@omnicross/ui 0.1.2 → 0.1.4

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,357 +0,0 @@
1
- var Yh=Object.defineProperty;var Xh=(e,t,a)=>t in e?Yh(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a;var Xd=(e,t,a)=>Xh(e,typeof t!="symbol"?t+"":t,a);function Jh(e,t){for(var a=0;a<t.length;a++){const n=t[a];if(typeof n!="string"&&!Array.isArray(n)){for(const o in n)if(o!=="default"&&!(o in e)){const i=Object.getOwnPropertyDescriptor(n,o);i&&Object.defineProperty(e,o,i.get?i:{enumerable:!0,get:()=>n[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const s of i.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&n(s)}).observe(document,{childList:!0,subtree:!0});function a(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(o){if(o.ep)return;o.ep=!0;const i=a(o);fetch(o.href,i)}})();function El(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var sp={exports:{}},vr={},lp={exports:{}},X={};/**
2
- * @license React
3
- * react.production.min.js
4
- *
5
- * Copyright (c) Facebook, Inc. and its affiliates.
6
- *
7
- * This source code is licensed under the MIT license found in the
8
- * LICENSE file in the root directory of this source tree.
9
- */var Ro=Symbol.for("react.element"),ef=Symbol.for("react.portal"),tf=Symbol.for("react.fragment"),af=Symbol.for("react.strict_mode"),nf=Symbol.for("react.profiler"),of=Symbol.for("react.provider"),rf=Symbol.for("react.context"),sf=Symbol.for("react.forward_ref"),lf=Symbol.for("react.suspense"),df=Symbol.for("react.memo"),cf=Symbol.for("react.lazy"),Jd=Symbol.iterator;function uf(e){return e===null||typeof e!="object"?null:(e=Jd&&e[Jd]||e["@@iterator"],typeof e=="function"?e:null)}var dp={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},cp=Object.assign,up={};function jn(e,t,a){this.props=e,this.context=t,this.refs=up,this.updater=a||dp}jn.prototype.isReactComponent={};jn.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};jn.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function pp(){}pp.prototype=jn.prototype;function Ol(e,t,a){this.props=e,this.context=t,this.refs=up,this.updater=a||dp}var Kl=Ol.prototype=new pp;Kl.constructor=Ol;cp(Kl,jn.prototype);Kl.isPureReactComponent=!0;var ec=Array.isArray,mp=Object.prototype.hasOwnProperty,Ul={current:null},gp={key:!0,ref:!0,__self:!0,__source:!0};function hp(e,t,a){var n,o={},i=null,s=null;if(t!=null)for(n in t.ref!==void 0&&(s=t.ref),t.key!==void 0&&(i=""+t.key),t)mp.call(t,n)&&!gp.hasOwnProperty(n)&&(o[n]=t[n]);var l=arguments.length-2;if(l===1)o.children=a;else if(1<l){for(var d=Array(l),c=0;c<l;c++)d[c]=arguments[c+2];o.children=d}if(e&&e.defaultProps)for(n in l=e.defaultProps,l)o[n]===void 0&&(o[n]=l[n]);return{$$typeof:Ro,type:e,key:i,ref:s,props:o,_owner:Ul.current}}function pf(e,t){return{$$typeof:Ro,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}function Hl(e){return typeof e=="object"&&e!==null&&e.$$typeof===Ro}function mf(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,function(a){return t[a]})}var tc=/\/+/g;function Br(e,t){return typeof e=="object"&&e!==null&&e.key!=null?mf(""+e.key):t.toString(36)}function Ii(e,t,a,n,o){var i=typeof e;(i==="undefined"||i==="boolean")&&(e=null);var s=!1;if(e===null)s=!0;else switch(i){case"string":case"number":s=!0;break;case"object":switch(e.$$typeof){case Ro:case ef:s=!0}}if(s)return s=e,o=o(s),e=n===""?"."+Br(s,0):n,ec(o)?(a="",e!=null&&(a=e.replace(tc,"$&/")+"/"),Ii(o,t,a,"",function(c){return c})):o!=null&&(Hl(o)&&(o=pf(o,a+(!o.key||s&&s.key===o.key?"":(""+o.key).replace(tc,"$&/")+"/")+e)),t.push(o)),1;if(s=0,n=n===""?".":n+":",ec(e))for(var l=0;l<e.length;l++){i=e[l];var d=n+Br(i,l);s+=Ii(i,t,a,d,o)}else if(d=uf(e),typeof d=="function")for(e=d.call(e),l=0;!(i=e.next()).done;)i=i.value,d=n+Br(i,l++),s+=Ii(i,t,a,d,o);else if(i==="object")throw t=String(e),Error("Objects are not valid as a React child (found: "+(t==="[object Object]"?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.");return s}function qo(e,t,a){if(e==null)return e;var n=[],o=0;return Ii(e,n,"","",function(i){return t.call(a,i,o++)}),n}function gf(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(a){(e._status===0||e._status===-1)&&(e._status=1,e._result=a)},function(a){(e._status===0||e._status===-1)&&(e._status=2,e._result=a)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var Oe={current:null},Si={transition:null},hf={ReactCurrentDispatcher:Oe,ReactCurrentBatchConfig:Si,ReactCurrentOwner:Ul};function fp(){throw Error("act(...) is not supported in production builds of React.")}X.Children={map:qo,forEach:function(e,t,a){qo(e,function(){t.apply(this,arguments)},a)},count:function(e){var t=0;return qo(e,function(){t++}),t},toArray:function(e){return qo(e,function(t){return t})||[]},only:function(e){if(!Hl(e))throw Error("React.Children.only expected to receive a single React element child.");return e}};X.Component=jn;X.Fragment=tf;X.Profiler=nf;X.PureComponent=Ol;X.StrictMode=af;X.Suspense=lf;X.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=hf;X.act=fp;X.cloneElement=function(e,t,a){if(e==null)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var n=cp({},e.props),o=e.key,i=e.ref,s=e._owner;if(t!=null){if(t.ref!==void 0&&(i=t.ref,s=Ul.current),t.key!==void 0&&(o=""+t.key),e.type&&e.type.defaultProps)var l=e.type.defaultProps;for(d in t)mp.call(t,d)&&!gp.hasOwnProperty(d)&&(n[d]=t[d]===void 0&&l!==void 0?l[d]:t[d])}var d=arguments.length-2;if(d===1)n.children=a;else if(1<d){l=Array(d);for(var c=0;c<d;c++)l[c]=arguments[c+2];n.children=l}return{$$typeof:Ro,type:e.type,key:o,ref:i,props:n,_owner:s}};X.createContext=function(e){return e={$$typeof:rf,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null},e.Provider={$$typeof:of,_context:e},e.Consumer=e};X.createElement=hp;X.createFactory=function(e){var t=hp.bind(null,e);return t.type=e,t};X.createRef=function(){return{current:null}};X.forwardRef=function(e){return{$$typeof:sf,render:e}};X.isValidElement=Hl;X.lazy=function(e){return{$$typeof:cf,_payload:{_status:-1,_result:e},_init:gf}};X.memo=function(e,t){return{$$typeof:df,type:e,compare:t===void 0?null:t}};X.startTransition=function(e){var t=Si.transition;Si.transition={};try{e()}finally{Si.transition=t}};X.unstable_act=fp;X.useCallback=function(e,t){return Oe.current.useCallback(e,t)};X.useContext=function(e){return Oe.current.useContext(e)};X.useDebugValue=function(){};X.useDeferredValue=function(e){return Oe.current.useDeferredValue(e)};X.useEffect=function(e,t){return Oe.current.useEffect(e,t)};X.useId=function(){return Oe.current.useId()};X.useImperativeHandle=function(e,t,a){return Oe.current.useImperativeHandle(e,t,a)};X.useInsertionEffect=function(e,t){return Oe.current.useInsertionEffect(e,t)};X.useLayoutEffect=function(e,t){return Oe.current.useLayoutEffect(e,t)};X.useMemo=function(e,t){return Oe.current.useMemo(e,t)};X.useReducer=function(e,t,a){return Oe.current.useReducer(e,t,a)};X.useRef=function(e){return Oe.current.useRef(e)};X.useState=function(e){return Oe.current.useState(e)};X.useSyncExternalStore=function(e,t,a){return Oe.current.useSyncExternalStore(e,t,a)};X.useTransition=function(){return Oe.current.useTransition()};X.version="18.3.1";lp.exports=X;var g=lp.exports;const Mt=El(g),Fl=Jh({__proto__:null,default:Mt},[g]);/**
10
- * @license React
11
- * react-jsx-runtime.production.min.js
12
- *
13
- * Copyright (c) Facebook, Inc. and its affiliates.
14
- *
15
- * This source code is licensed under the MIT license found in the
16
- * LICENSE file in the root directory of this source tree.
17
- */var ff=g,vf=Symbol.for("react.element"),kf=Symbol.for("react.fragment"),yf=Object.prototype.hasOwnProperty,bf=ff.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,Pf={key:!0,ref:!0,__self:!0,__source:!0};function vp(e,t,a){var n,o={},i=null,s=null;a!==void 0&&(i=""+a),t.key!==void 0&&(i=""+t.key),t.ref!==void 0&&(s=t.ref);for(n in t)yf.call(t,n)&&!Pf.hasOwnProperty(n)&&(o[n]=t[n]);if(e&&e.defaultProps)for(n in t=e.defaultProps,t)o[n]===void 0&&(o[n]=t[n]);return{$$typeof:vf,type:e,key:i,ref:s,props:o,_owner:bf.current}}vr.Fragment=kf;vr.jsx=vp;vr.jsxs=vp;sp.exports=vr;var r=sp.exports,Ms={},kp={exports:{}},Xe={},yp={exports:{}},bp={};/**
18
- * @license React
19
- * scheduler.production.min.js
20
- *
21
- * Copyright (c) Facebook, Inc. and its affiliates.
22
- *
23
- * This source code is licensed under the MIT license found in the
24
- * LICENSE file in the root directory of this source tree.
25
- */(function(e){function t(w,E){var U=w.length;w.push(E);e:for(;0<U;){var Z=U-1>>>1,ae=w[Z];if(0<o(ae,E))w[Z]=E,w[U]=ae,U=Z;else break e}}function a(w){return w.length===0?null:w[0]}function n(w){if(w.length===0)return null;var E=w[0],U=w.pop();if(U!==E){w[0]=U;e:for(var Z=0,ae=w.length,_e=ae>>>1;Z<_e;){var xe=2*(Z+1)-1,ne=w[xe],Pe=xe+1,Ge=w[Pe];if(0>o(ne,U))Pe<ae&&0>o(Ge,ne)?(w[Z]=Ge,w[Pe]=U,Z=Pe):(w[Z]=ne,w[xe]=U,Z=xe);else if(Pe<ae&&0>o(Ge,U))w[Z]=Ge,w[Pe]=U,Z=Pe;else break e}}return E}function o(w,E){var U=w.sortIndex-E.sortIndex;return U!==0?U:w.id-E.id}if(typeof performance=="object"&&typeof performance.now=="function"){var i=performance;e.unstable_now=function(){return i.now()}}else{var s=Date,l=s.now();e.unstable_now=function(){return s.now()-l}}var d=[],c=[],u=1,p=null,m=3,f=!1,P=!1,y=!1,A=typeof setTimeout=="function"?setTimeout:null,h=typeof clearTimeout=="function"?clearTimeout:null,k=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function v(w){for(var E=a(c);E!==null;){if(E.callback===null)n(c);else if(E.startTime<=w)n(c),E.sortIndex=E.expirationTime,t(d,E);else break;E=a(c)}}function b(w){if(y=!1,v(w),!P)if(a(d)!==null)P=!0,ye(z);else{var E=a(c);E!==null&&ve(b,E.startTime-w)}}function z(w,E){P=!1,y&&(y=!1,h(S),S=-1),f=!0;var U=m;try{for(v(E),p=a(d);p!==null&&(!(p.expirationTime>E)||w&&!M());){var Z=p.callback;if(typeof Z=="function"){p.callback=null,m=p.priorityLevel;var ae=Z(p.expirationTime<=E);E=e.unstable_now(),typeof ae=="function"?p.callback=ae:p===a(d)&&n(d),v(E)}else n(d);p=a(d)}if(p!==null)var _e=!0;else{var xe=a(c);xe!==null&&ve(b,xe.startTime-E),_e=!1}return _e}finally{p=null,m=U,f=!1}}var I=!1,C=null,S=-1,L=5,T=-1;function M(){return!(e.unstable_now()-T<L)}function D(){if(C!==null){var w=e.unstable_now();T=w;var E=!0;try{E=C(!0,w)}finally{E?Q():(I=!1,C=null)}}else I=!1}var Q;if(typeof k=="function")Q=function(){k(D)};else if(typeof MessageChannel<"u"){var W=new MessageChannel,J=W.port2;W.port1.onmessage=D,Q=function(){J.postMessage(null)}}else Q=function(){A(D,0)};function ye(w){C=w,I||(I=!0,Q())}function ve(w,E){S=A(function(){w(e.unstable_now())},E)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(w){w.callback=null},e.unstable_continueExecution=function(){P||f||(P=!0,ye(z))},e.unstable_forceFrameRate=function(w){0>w||125<w?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):L=0<w?Math.floor(1e3/w):5},e.unstable_getCurrentPriorityLevel=function(){return m},e.unstable_getFirstCallbackNode=function(){return a(d)},e.unstable_next=function(w){switch(m){case 1:case 2:case 3:var E=3;break;default:E=m}var U=m;m=E;try{return w()}finally{m=U}},e.unstable_pauseExecution=function(){},e.unstable_requestPaint=function(){},e.unstable_runWithPriority=function(w,E){switch(w){case 1:case 2:case 3:case 4:case 5:break;default:w=3}var U=m;m=w;try{return E()}finally{m=U}},e.unstable_scheduleCallback=function(w,E,U){var Z=e.unstable_now();switch(typeof U=="object"&&U!==null?(U=U.delay,U=typeof U=="number"&&0<U?Z+U:Z):U=Z,w){case 1:var ae=-1;break;case 2:ae=250;break;case 5:ae=1073741823;break;case 4:ae=1e4;break;default:ae=5e3}return ae=U+ae,w={id:u++,callback:E,priorityLevel:w,startTime:U,expirationTime:ae,sortIndex:-1},U>Z?(w.sortIndex=U,t(c,w),a(d)===null&&w===a(c)&&(y?(h(S),S=-1):y=!0,ve(b,U-Z))):(w.sortIndex=ae,t(d,w),P||f||(P=!0,ye(z))),w},e.unstable_shouldYield=M,e.unstable_wrapCallback=function(w){var E=m;return function(){var U=m;m=E;try{return w.apply(this,arguments)}finally{m=U}}}})(bp);yp.exports=bp;var Af=yp.exports;/**
26
- * @license React
27
- * react-dom.production.min.js
28
- *
29
- * Copyright (c) Facebook, Inc. and its affiliates.
30
- *
31
- * This source code is licensed under the MIT license found in the
32
- * LICENSE file in the root directory of this source tree.
33
- */var Cf=g,Ye=Af;function N(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,a=1;a<arguments.length;a++)t+="&args[]="+encodeURIComponent(arguments[a]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var Pp=new Set,uo={};function Oa(e,t){yn(e,t),yn(e+"Capture",t)}function yn(e,t){for(uo[e]=t,e=0;e<t.length;e++)Pp.add(t[e])}var Rt=!(typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Ns=Object.prototype.hasOwnProperty,xf=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,ac={},nc={};function zf(e){return Ns.call(nc,e)?!0:Ns.call(ac,e)?!1:xf.test(e)?nc[e]=!0:(ac[e]=!0,!1)}function If(e,t,a,n){if(a!==null&&a.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return n?!1:a!==null?!a.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Sf(e,t,a,n){if(t===null||typeof t>"u"||If(e,t,a,n))return!0;if(n)return!1;if(a!==null)switch(a.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function Ke(e,t,a,n,o,i,s){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=n,this.attributeNamespace=o,this.mustUseProperty=a,this.propertyName=e,this.type=t,this.sanitizeURL=i,this.removeEmptyString=s}var Te={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){Te[e]=new Ke(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];Te[t]=new Ke(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){Te[e]=new Ke(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){Te[e]=new Ke(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){Te[e]=new Ke(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){Te[e]=new Ke(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){Te[e]=new Ke(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){Te[e]=new Ke(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){Te[e]=new Ke(e,5,!1,e.toLowerCase(),null,!1,!1)});var Bl=/[\-:]([a-z])/g;function Vl(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Bl,Vl);Te[t]=new Ke(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Bl,Vl);Te[t]=new Ke(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Bl,Vl);Te[t]=new Ke(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){Te[e]=new Ke(e,1,!1,e.toLowerCase(),null,!1,!1)});Te.xlinkHref=new Ke("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){Te[e]=new Ke(e,1,!1,e.toLowerCase(),null,!0,!0)});function ql(e,t,a,n){var o=Te.hasOwnProperty(t)?Te[t]:null;(o!==null?o.type!==0:n||!(2<t.length)||t[0]!=="o"&&t[0]!=="O"||t[1]!=="n"&&t[1]!=="N")&&(Sf(t,a,o,n)&&(a=null),n||o===null?zf(t)&&(a===null?e.removeAttribute(t):e.setAttribute(t,""+a)):o.mustUseProperty?e[o.propertyName]=a===null?o.type===3?!1:"":a:(t=o.attributeName,n=o.attributeNamespace,a===null?e.removeAttribute(t):(o=o.type,a=o===3||o===4&&a===!0?"":""+a,n?e.setAttributeNS(n,t,a):e.setAttribute(t,a))))}var Ut=Cf.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,$o=Symbol.for("react.element"),Xa=Symbol.for("react.portal"),Ja=Symbol.for("react.fragment"),$l=Symbol.for("react.strict_mode"),Ls=Symbol.for("react.profiler"),Ap=Symbol.for("react.provider"),Cp=Symbol.for("react.context"),_l=Symbol.for("react.forward_ref"),Rs=Symbol.for("react.suspense"),Ds=Symbol.for("react.suspense_list"),Gl=Symbol.for("react.memo"),_t=Symbol.for("react.lazy"),xp=Symbol.for("react.offscreen"),oc=Symbol.iterator;function En(e){return e===null||typeof e!="object"?null:(e=oc&&e[oc]||e["@@iterator"],typeof e=="function"?e:null)}var ge=Object.assign,Vr;function Zn(e){if(Vr===void 0)try{throw Error()}catch(a){var t=a.stack.trim().match(/\n( *(at )?)/);Vr=t&&t[1]||""}return`
34
- `+Vr+e}var qr=!1;function $r(e,t){if(!e||qr)return"";qr=!0;var a=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(t,[])}catch(c){var n=c}Reflect.construct(e,[],t)}else{try{t.call()}catch(c){n=c}e.call(t.prototype)}else{try{throw Error()}catch(c){n=c}e()}}catch(c){if(c&&n&&typeof c.stack=="string"){for(var o=c.stack.split(`
35
- `),i=n.stack.split(`
36
- `),s=o.length-1,l=i.length-1;1<=s&&0<=l&&o[s]!==i[l];)l--;for(;1<=s&&0<=l;s--,l--)if(o[s]!==i[l]){if(s!==1||l!==1)do if(s--,l--,0>l||o[s]!==i[l]){var d=`
37
- `+o[s].replace(" at new "," at ");return e.displayName&&d.includes("<anonymous>")&&(d=d.replace("<anonymous>",e.displayName)),d}while(1<=s&&0<=l);break}}}finally{qr=!1,Error.prepareStackTrace=a}return(e=e?e.displayName||e.name:"")?Zn(e):""}function wf(e){switch(e.tag){case 5:return Zn(e.type);case 16:return Zn("Lazy");case 13:return Zn("Suspense");case 19:return Zn("SuspenseList");case 0:case 2:case 15:return e=$r(e.type,!1),e;case 11:return e=$r(e.type.render,!1),e;case 1:return e=$r(e.type,!0),e;default:return""}}function Es(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case Ja:return"Fragment";case Xa:return"Portal";case Ls:return"Profiler";case $l:return"StrictMode";case Rs:return"Suspense";case Ds:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Cp:return(e.displayName||"Context")+".Consumer";case Ap:return(e._context.displayName||"Context")+".Provider";case _l:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Gl:return t=e.displayName||null,t!==null?t:Es(e.type)||"Memo";case _t:t=e._payload,e=e._init;try{return Es(e(t))}catch{}}return null}function Tf(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Es(t);case 8:return t===$l?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function da(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function zp(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function jf(e){var t=zp(e)?"checked":"value",a=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),n=""+e[t];if(!e.hasOwnProperty(t)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var o=a.get,i=a.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(s){n=""+s,i.call(this,s)}}),Object.defineProperty(e,t,{enumerable:a.enumerable}),{getValue:function(){return n},setValue:function(s){n=""+s},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function _o(e){e._valueTracker||(e._valueTracker=jf(e))}function Ip(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var a=t.getValue(),n="";return e&&(n=zp(e)?e.checked?"true":"false":e.value),e=n,e!==a?(t.setValue(e),!0):!1}function Hi(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Os(e,t){var a=t.checked;return ge({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??e._wrapperState.initialChecked})}function ic(e,t){var a=t.defaultValue==null?"":t.defaultValue,n=t.checked!=null?t.checked:t.defaultChecked;a=da(t.value!=null?t.value:a),e._wrapperState={initialChecked:n,initialValue:a,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Sp(e,t){t=t.checked,t!=null&&ql(e,"checked",t,!1)}function Ks(e,t){Sp(e,t);var a=da(t.value),n=t.type;if(a!=null)n==="number"?(a===0&&e.value===""||e.value!=a)&&(e.value=""+a):e.value!==""+a&&(e.value=""+a);else if(n==="submit"||n==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Us(e,t.type,a):t.hasOwnProperty("defaultValue")&&Us(e,t.type,da(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function rc(e,t,a){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var n=t.type;if(!(n!=="submit"&&n!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,a||t===e.value||(e.value=t),e.defaultValue=t}a=e.name,a!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,a!==""&&(e.name=a)}function Us(e,t,a){(t!=="number"||Hi(e.ownerDocument)!==e)&&(a==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+a&&(e.defaultValue=""+a))}var Qn=Array.isArray;function un(e,t,a,n){if(e=e.options,t){t={};for(var o=0;o<a.length;o++)t["$"+a[o]]=!0;for(a=0;a<e.length;a++)o=t.hasOwnProperty("$"+e[a].value),e[a].selected!==o&&(e[a].selected=o),o&&n&&(e[a].defaultSelected=!0)}else{for(a=""+da(a),t=null,o=0;o<e.length;o++){if(e[o].value===a){e[o].selected=!0,n&&(e[o].defaultSelected=!0);return}t!==null||e[o].disabled||(t=e[o])}t!==null&&(t.selected=!0)}}function Hs(e,t){if(t.dangerouslySetInnerHTML!=null)throw Error(N(91));return ge({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function sc(e,t){var a=t.value;if(a==null){if(a=t.children,t=t.defaultValue,a!=null){if(t!=null)throw Error(N(92));if(Qn(a)){if(1<a.length)throw Error(N(93));a=a[0]}t=a}t==null&&(t=""),a=t}e._wrapperState={initialValue:da(a)}}function wp(e,t){var a=da(t.value),n=da(t.defaultValue);a!=null&&(a=""+a,a!==e.value&&(e.value=a),t.defaultValue==null&&e.defaultValue!==a&&(e.defaultValue=a)),n!=null&&(e.defaultValue=""+n)}function lc(e){var t=e.textContent;t===e._wrapperState.initialValue&&t!==""&&t!==null&&(e.value=t)}function Tp(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Fs(e,t){return e==null||e==="http://www.w3.org/1999/xhtml"?Tp(t):e==="http://www.w3.org/2000/svg"&&t==="foreignObject"?"http://www.w3.org/1999/xhtml":e}var Go,jp=function(e){return typeof MSApp<"u"&&MSApp.execUnsafeLocalFunction?function(t,a,n,o){MSApp.execUnsafeLocalFunction(function(){return e(t,a,n,o)})}:e}(function(e,t){if(e.namespaceURI!=="http://www.w3.org/2000/svg"||"innerHTML"in e)e.innerHTML=t;else{for(Go=Go||document.createElement("div"),Go.innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=Go.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function po(e,t){if(t){var a=e.firstChild;if(a&&a===e.lastChild&&a.nodeType===3){a.nodeValue=t;return}}e.textContent=t}var eo={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Mf=["Webkit","ms","Moz","O"];Object.keys(eo).forEach(function(e){Mf.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),eo[t]=eo[e]})});function Mp(e,t,a){return t==null||typeof t=="boolean"||t===""?"":a||typeof t!="number"||t===0||eo.hasOwnProperty(e)&&eo[e]?(""+t).trim():t+"px"}function Np(e,t){e=e.style;for(var a in t)if(t.hasOwnProperty(a)){var n=a.indexOf("--")===0,o=Mp(a,t[a],n);a==="float"&&(a="cssFloat"),n?e.setProperty(a,o):e[a]=o}}var Nf=ge({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Bs(e,t){if(t){if(Nf[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(N(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(N(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(N(61))}if(t.style!=null&&typeof t.style!="object")throw Error(N(62))}}function Vs(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var qs=null;function Wl(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var $s=null,pn=null,mn=null;function dc(e){if(e=Oo(e)){if(typeof $s!="function")throw Error(N(280));var t=e.stateNode;t&&(t=Ar(t),$s(e.stateNode,e.type,t))}}function Lp(e){pn?mn?mn.push(e):mn=[e]:pn=e}function Rp(){if(pn){var e=pn,t=mn;if(mn=pn=null,dc(e),t)for(e=0;e<t.length;e++)dc(t[e])}}function Dp(e,t){return e(t)}function Ep(){}var _r=!1;function Op(e,t,a){if(_r)return e(t,a);_r=!0;try{return Dp(e,t,a)}finally{_r=!1,(pn!==null||mn!==null)&&(Ep(),Rp())}}function mo(e,t){var a=e.stateNode;if(a===null)return null;var n=Ar(a);if(n===null)return null;a=n[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(n=!n.disabled)||(e=e.type,n=!(e==="button"||e==="input"||e==="select"||e==="textarea")),e=!n;break e;default:e=!1}if(e)return null;if(a&&typeof a!="function")throw Error(N(231,t,typeof a));return a}var _s=!1;if(Rt)try{var On={};Object.defineProperty(On,"passive",{get:function(){_s=!0}}),window.addEventListener("test",On,On),window.removeEventListener("test",On,On)}catch{_s=!1}function Lf(e,t,a,n,o,i,s,l,d){var c=Array.prototype.slice.call(arguments,3);try{t.apply(a,c)}catch(u){this.onError(u)}}var to=!1,Fi=null,Bi=!1,Gs=null,Rf={onError:function(e){to=!0,Fi=e}};function Df(e,t,a,n,o,i,s,l,d){to=!1,Fi=null,Lf.apply(Rf,arguments)}function Ef(e,t,a,n,o,i,s,l,d){if(Df.apply(this,arguments),to){if(to){var c=Fi;to=!1,Fi=null}else throw Error(N(198));Bi||(Bi=!0,Gs=c)}}function Ka(e){var t=e,a=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,t.flags&4098&&(a=t.return),e=t.return;while(e)}return t.tag===3?a:null}function Kp(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function cc(e){if(Ka(e)!==e)throw Error(N(188))}function Of(e){var t=e.alternate;if(!t){if(t=Ka(e),t===null)throw Error(N(188));return t!==e?null:e}for(var a=e,n=t;;){var o=a.return;if(o===null)break;var i=o.alternate;if(i===null){if(n=o.return,n!==null){a=n;continue}break}if(o.child===i.child){for(i=o.child;i;){if(i===a)return cc(o),e;if(i===n)return cc(o),t;i=i.sibling}throw Error(N(188))}if(a.return!==n.return)a=o,n=i;else{for(var s=!1,l=o.child;l;){if(l===a){s=!0,a=o,n=i;break}if(l===n){s=!0,n=o,a=i;break}l=l.sibling}if(!s){for(l=i.child;l;){if(l===a){s=!0,a=i,n=o;break}if(l===n){s=!0,n=i,a=o;break}l=l.sibling}if(!s)throw Error(N(189))}}if(a.alternate!==n)throw Error(N(190))}if(a.tag!==3)throw Error(N(188));return a.stateNode.current===a?e:t}function Up(e){return e=Of(e),e!==null?Hp(e):null}function Hp(e){if(e.tag===5||e.tag===6)return e;for(e=e.child;e!==null;){var t=Hp(e);if(t!==null)return t;e=e.sibling}return null}var Fp=Ye.unstable_scheduleCallback,uc=Ye.unstable_cancelCallback,Kf=Ye.unstable_shouldYield,Uf=Ye.unstable_requestPaint,ke=Ye.unstable_now,Hf=Ye.unstable_getCurrentPriorityLevel,Zl=Ye.unstable_ImmediatePriority,Bp=Ye.unstable_UserBlockingPriority,Vi=Ye.unstable_NormalPriority,Ff=Ye.unstable_LowPriority,Vp=Ye.unstable_IdlePriority,kr=null,At=null;function Bf(e){if(At&&typeof At.onCommitFiberRoot=="function")try{At.onCommitFiberRoot(kr,e,void 0,(e.current.flags&128)===128)}catch{}}var ut=Math.clz32?Math.clz32:$f,Vf=Math.log,qf=Math.LN2;function $f(e){return e>>>=0,e===0?32:31-(Vf(e)/qf|0)|0}var Wo=64,Zo=4194304;function Yn(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function qi(e,t){var a=e.pendingLanes;if(a===0)return 0;var n=0,o=e.suspendedLanes,i=e.pingedLanes,s=a&268435455;if(s!==0){var l=s&~o;l!==0?n=Yn(l):(i&=s,i!==0&&(n=Yn(i)))}else s=a&~o,s!==0?n=Yn(s):i!==0&&(n=Yn(i));if(n===0)return 0;if(t!==0&&t!==n&&!(t&o)&&(o=n&-n,i=t&-t,o>=i||o===16&&(i&4194240)!==0))return t;if(n&4&&(n|=a&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=n;0<t;)a=31-ut(t),o=1<<a,n|=e[a],t&=~o;return n}function _f(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return-1;case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Gf(e,t){for(var a=e.suspendedLanes,n=e.pingedLanes,o=e.expirationTimes,i=e.pendingLanes;0<i;){var s=31-ut(i),l=1<<s,d=o[s];d===-1?(!(l&a)||l&n)&&(o[s]=_f(l,t)):d<=t&&(e.expiredLanes|=l),i&=~l}}function Ws(e){return e=e.pendingLanes&-1073741825,e!==0?e:e&1073741824?1073741824:0}function qp(){var e=Wo;return Wo<<=1,!(Wo&4194240)&&(Wo=64),e}function Gr(e){for(var t=[],a=0;31>a;a++)t.push(e);return t}function Do(e,t,a){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-ut(t),e[t]=a}function Wf(e,t){var a=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var n=e.eventTimes;for(e=e.expirationTimes;0<a;){var o=31-ut(a),i=1<<o;t[o]=0,n[o]=-1,e[o]=-1,a&=~i}}function Ql(e,t){var a=e.entangledLanes|=t;for(e=e.entanglements;a;){var n=31-ut(a),o=1<<n;o&t|e[n]&t&&(e[n]|=t),a&=~o}}var oe=0;function $p(e){return e&=-e,1<e?4<e?e&268435455?16:536870912:4:1}var _p,Yl,Gp,Wp,Zp,Zs=!1,Qo=[],ea=null,ta=null,aa=null,go=new Map,ho=new Map,Wt=[],Zf="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function pc(e,t){switch(e){case"focusin":case"focusout":ea=null;break;case"dragenter":case"dragleave":ta=null;break;case"mouseover":case"mouseout":aa=null;break;case"pointerover":case"pointerout":go.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":ho.delete(t.pointerId)}}function Kn(e,t,a,n,o,i){return e===null||e.nativeEvent!==i?(e={blockedOn:t,domEventName:a,eventSystemFlags:n,nativeEvent:i,targetContainers:[o]},t!==null&&(t=Oo(t),t!==null&&Yl(t)),e):(e.eventSystemFlags|=n,t=e.targetContainers,o!==null&&t.indexOf(o)===-1&&t.push(o),e)}function Qf(e,t,a,n,o){switch(t){case"focusin":return ea=Kn(ea,e,t,a,n,o),!0;case"dragenter":return ta=Kn(ta,e,t,a,n,o),!0;case"mouseover":return aa=Kn(aa,e,t,a,n,o),!0;case"pointerover":var i=o.pointerId;return go.set(i,Kn(go.get(i)||null,e,t,a,n,o)),!0;case"gotpointercapture":return i=o.pointerId,ho.set(i,Kn(ho.get(i)||null,e,t,a,n,o)),!0}return!1}function Qp(e){var t=Pa(e.target);if(t!==null){var a=Ka(t);if(a!==null){if(t=a.tag,t===13){if(t=Kp(a),t!==null){e.blockedOn=t,Zp(e.priority,function(){Gp(a)});return}}else if(t===3&&a.stateNode.current.memoizedState.isDehydrated){e.blockedOn=a.tag===3?a.stateNode.containerInfo:null;return}}}e.blockedOn=null}function wi(e){if(e.blockedOn!==null)return!1;for(var t=e.targetContainers;0<t.length;){var a=Qs(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(a===null){a=e.nativeEvent;var n=new a.constructor(a.type,a);qs=n,a.target.dispatchEvent(n),qs=null}else return t=Oo(a),t!==null&&Yl(t),e.blockedOn=a,!1;t.shift()}return!0}function mc(e,t,a){wi(e)&&a.delete(t)}function Yf(){Zs=!1,ea!==null&&wi(ea)&&(ea=null),ta!==null&&wi(ta)&&(ta=null),aa!==null&&wi(aa)&&(aa=null),go.forEach(mc),ho.forEach(mc)}function Un(e,t){e.blockedOn===t&&(e.blockedOn=null,Zs||(Zs=!0,Ye.unstable_scheduleCallback(Ye.unstable_NormalPriority,Yf)))}function fo(e){function t(o){return Un(o,e)}if(0<Qo.length){Un(Qo[0],e);for(var a=1;a<Qo.length;a++){var n=Qo[a];n.blockedOn===e&&(n.blockedOn=null)}}for(ea!==null&&Un(ea,e),ta!==null&&Un(ta,e),aa!==null&&Un(aa,e),go.forEach(t),ho.forEach(t),a=0;a<Wt.length;a++)n=Wt[a],n.blockedOn===e&&(n.blockedOn=null);for(;0<Wt.length&&(a=Wt[0],a.blockedOn===null);)Qp(a),a.blockedOn===null&&Wt.shift()}var gn=Ut.ReactCurrentBatchConfig,$i=!0;function Xf(e,t,a,n){var o=oe,i=gn.transition;gn.transition=null;try{oe=1,Xl(e,t,a,n)}finally{oe=o,gn.transition=i}}function Jf(e,t,a,n){var o=oe,i=gn.transition;gn.transition=null;try{oe=4,Xl(e,t,a,n)}finally{oe=o,gn.transition=i}}function Xl(e,t,a,n){if($i){var o=Qs(e,t,a,n);if(o===null)ns(e,t,n,_i,a),pc(e,n);else if(Qf(o,e,t,a,n))n.stopPropagation();else if(pc(e,n),t&4&&-1<Zf.indexOf(e)){for(;o!==null;){var i=Oo(o);if(i!==null&&_p(i),i=Qs(e,t,a,n),i===null&&ns(e,t,n,_i,a),i===o)break;o=i}o!==null&&n.stopPropagation()}else ns(e,t,n,null,a)}}var _i=null;function Qs(e,t,a,n){if(_i=null,e=Wl(n),e=Pa(e),e!==null)if(t=Ka(e),t===null)e=null;else if(a=t.tag,a===13){if(e=Kp(t),e!==null)return e;e=null}else if(a===3){if(t.stateNode.current.memoizedState.isDehydrated)return t.tag===3?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null);return _i=e,null}function Yp(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(Hf()){case Zl:return 1;case Bp:return 4;case Vi:case Ff:return 16;case Vp:return 536870912;default:return 16}default:return 16}}var Yt=null,Jl=null,Ti=null;function Xp(){if(Ti)return Ti;var e,t=Jl,a=t.length,n,o="value"in Yt?Yt.value:Yt.textContent,i=o.length;for(e=0;e<a&&t[e]===o[e];e++);var s=a-e;for(n=1;n<=s&&t[a-n]===o[i-n];n++);return Ti=o.slice(e,1<n?1-n:void 0)}function ji(e){var t=e.keyCode;return"charCode"in e?(e=e.charCode,e===0&&t===13&&(e=13)):e=t,e===10&&(e=13),32<=e||e===13?e:0}function Yo(){return!0}function gc(){return!1}function Je(e){function t(a,n,o,i,s){this._reactName=a,this._targetInst=o,this.type=n,this.nativeEvent=i,this.target=s,this.currentTarget=null;for(var l in e)e.hasOwnProperty(l)&&(a=e[l],this[l]=a?a(i):i[l]);return this.isDefaultPrevented=(i.defaultPrevented!=null?i.defaultPrevented:i.returnValue===!1)?Yo:gc,this.isPropagationStopped=gc,this}return ge(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var a=this.nativeEvent;a&&(a.preventDefault?a.preventDefault():typeof a.returnValue!="unknown"&&(a.returnValue=!1),this.isDefaultPrevented=Yo)},stopPropagation:function(){var a=this.nativeEvent;a&&(a.stopPropagation?a.stopPropagation():typeof a.cancelBubble!="unknown"&&(a.cancelBubble=!0),this.isPropagationStopped=Yo)},persist:function(){},isPersistent:Yo}),t}var Mn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},ed=Je(Mn),Eo=ge({},Mn,{view:0,detail:0}),ev=Je(Eo),Wr,Zr,Hn,yr=ge({},Eo,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:td,button:0,buttons:0,relatedTarget:function(e){return e.relatedTarget===void 0?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==Hn&&(Hn&&e.type==="mousemove"?(Wr=e.screenX-Hn.screenX,Zr=e.screenY-Hn.screenY):Zr=Wr=0,Hn=e),Wr)},movementY:function(e){return"movementY"in e?e.movementY:Zr}}),hc=Je(yr),tv=ge({},yr,{dataTransfer:0}),av=Je(tv),nv=ge({},Eo,{relatedTarget:0}),Qr=Je(nv),ov=ge({},Mn,{animationName:0,elapsedTime:0,pseudoElement:0}),iv=Je(ov),rv=ge({},Mn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),sv=Je(rv),lv=ge({},Mn,{data:0}),fc=Je(lv),dv={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},cv={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},uv={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function pv(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):(e=uv[e])?!!t[e]:!1}function td(){return pv}var mv=ge({},Eo,{key:function(e){if(e.key){var t=dv[e.key]||e.key;if(t!=="Unidentified")return t}return e.type==="keypress"?(e=ji(e),e===13?"Enter":String.fromCharCode(e)):e.type==="keydown"||e.type==="keyup"?cv[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:td,charCode:function(e){return e.type==="keypress"?ji(e):0},keyCode:function(e){return e.type==="keydown"||e.type==="keyup"?e.keyCode:0},which:function(e){return e.type==="keypress"?ji(e):e.type==="keydown"||e.type==="keyup"?e.keyCode:0}}),gv=Je(mv),hv=ge({},yr,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0}),vc=Je(hv),fv=ge({},Eo,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:td}),vv=Je(fv),kv=ge({},Mn,{propertyName:0,elapsedTime:0,pseudoElement:0}),yv=Je(kv),bv=ge({},yr,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),Pv=Je(bv),Av=[9,13,27,32],ad=Rt&&"CompositionEvent"in window,ao=null;Rt&&"documentMode"in document&&(ao=document.documentMode);var Cv=Rt&&"TextEvent"in window&&!ao,Jp=Rt&&(!ad||ao&&8<ao&&11>=ao),kc=" ",yc=!1;function em(e,t){switch(e){case"keyup":return Av.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function tm(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var en=!1;function xv(e,t){switch(e){case"compositionend":return tm(t);case"keypress":return t.which!==32?null:(yc=!0,kc);case"textInput":return e=t.data,e===kc&&yc?null:e;default:return null}}function zv(e,t){if(en)return e==="compositionend"||!ad&&em(e,t)?(e=Xp(),Ti=Jl=Yt=null,en=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Jp&&t.locale!=="ko"?null:t.data;default:return null}}var Iv={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function bc(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t==="input"?!!Iv[e.type]:t==="textarea"}function am(e,t,a,n){Lp(n),t=Gi(t,"onChange"),0<t.length&&(a=new ed("onChange","change",null,a,n),e.push({event:a,listeners:t}))}var no=null,vo=null;function Sv(e){mm(e,0)}function br(e){var t=nn(e);if(Ip(t))return e}function wv(e,t){if(e==="change")return t}var nm=!1;if(Rt){var Yr;if(Rt){var Xr="oninput"in document;if(!Xr){var Pc=document.createElement("div");Pc.setAttribute("oninput","return;"),Xr=typeof Pc.oninput=="function"}Yr=Xr}else Yr=!1;nm=Yr&&(!document.documentMode||9<document.documentMode)}function Ac(){no&&(no.detachEvent("onpropertychange",om),vo=no=null)}function om(e){if(e.propertyName==="value"&&br(vo)){var t=[];am(t,vo,e,Wl(e)),Op(Sv,t)}}function Tv(e,t,a){e==="focusin"?(Ac(),no=t,vo=a,no.attachEvent("onpropertychange",om)):e==="focusout"&&Ac()}function jv(e){if(e==="selectionchange"||e==="keyup"||e==="keydown")return br(vo)}function Mv(e,t){if(e==="click")return br(t)}function Nv(e,t){if(e==="input"||e==="change")return br(t)}function Lv(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var mt=typeof Object.is=="function"?Object.is:Lv;function ko(e,t){if(mt(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;var a=Object.keys(e),n=Object.keys(t);if(a.length!==n.length)return!1;for(n=0;n<a.length;n++){var o=a[n];if(!Ns.call(t,o)||!mt(e[o],t[o]))return!1}return!0}function Cc(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function xc(e,t){var a=Cc(e);e=0;for(var n;a;){if(a.nodeType===3){if(n=e+a.textContent.length,e<=t&&n>=t)return{node:a,offset:t-e};e=n}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=Cc(a)}}function im(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?im(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function rm(){for(var e=window,t=Hi();t instanceof e.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)e=t.contentWindow;else break;t=Hi(e.document)}return t}function nd(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function Rv(e){var t=rm(),a=e.focusedElem,n=e.selectionRange;if(t!==a&&a&&a.ownerDocument&&im(a.ownerDocument.documentElement,a)){if(n!==null&&nd(a)){if(t=n.start,e=n.end,e===void 0&&(e=t),"selectionStart"in a)a.selectionStart=t,a.selectionEnd=Math.min(e,a.value.length);else if(e=(t=a.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var o=a.textContent.length,i=Math.min(n.start,o);n=n.end===void 0?i:Math.min(n.end,o),!e.extend&&i>n&&(o=n,n=i,i=o),o=xc(a,i);var s=xc(a,n);o&&s&&(e.rangeCount!==1||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==s.node||e.focusOffset!==s.offset)&&(t=t.createRange(),t.setStart(o.node,o.offset),e.removeAllRanges(),i>n?(e.addRange(t),e.extend(s.node,s.offset)):(t.setEnd(s.node,s.offset),e.addRange(t)))}}for(t=[],e=a;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof a.focus=="function"&&a.focus(),a=0;a<t.length;a++)e=t[a],e.element.scrollLeft=e.left,e.element.scrollTop=e.top}}var Dv=Rt&&"documentMode"in document&&11>=document.documentMode,tn=null,Ys=null,oo=null,Xs=!1;function zc(e,t,a){var n=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;Xs||tn==null||tn!==Hi(n)||(n=tn,"selectionStart"in n&&nd(n)?n={start:n.selectionStart,end:n.selectionEnd}:(n=(n.ownerDocument&&n.ownerDocument.defaultView||window).getSelection(),n={anchorNode:n.anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset}),oo&&ko(oo,n)||(oo=n,n=Gi(Ys,"onSelect"),0<n.length&&(t=new ed("onSelect","select",null,t,a),e.push({event:t,listeners:n}),t.target=tn)))}function Xo(e,t){var a={};return a[e.toLowerCase()]=t.toLowerCase(),a["Webkit"+e]="webkit"+t,a["Moz"+e]="moz"+t,a}var an={animationend:Xo("Animation","AnimationEnd"),animationiteration:Xo("Animation","AnimationIteration"),animationstart:Xo("Animation","AnimationStart"),transitionend:Xo("Transition","TransitionEnd")},Jr={},sm={};Rt&&(sm=document.createElement("div").style,"AnimationEvent"in window||(delete an.animationend.animation,delete an.animationiteration.animation,delete an.animationstart.animation),"TransitionEvent"in window||delete an.transitionend.transition);function Pr(e){if(Jr[e])return Jr[e];if(!an[e])return e;var t=an[e],a;for(a in t)if(t.hasOwnProperty(a)&&a in sm)return Jr[e]=t[a];return e}var lm=Pr("animationend"),dm=Pr("animationiteration"),cm=Pr("animationstart"),um=Pr("transitionend"),pm=new Map,Ic="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function ua(e,t){pm.set(e,t),Oa(t,[e])}for(var es=0;es<Ic.length;es++){var ts=Ic[es],Ev=ts.toLowerCase(),Ov=ts[0].toUpperCase()+ts.slice(1);ua(Ev,"on"+Ov)}ua(lm,"onAnimationEnd");ua(dm,"onAnimationIteration");ua(cm,"onAnimationStart");ua("dblclick","onDoubleClick");ua("focusin","onFocus");ua("focusout","onBlur");ua(um,"onTransitionEnd");yn("onMouseEnter",["mouseout","mouseover"]);yn("onMouseLeave",["mouseout","mouseover"]);yn("onPointerEnter",["pointerout","pointerover"]);yn("onPointerLeave",["pointerout","pointerover"]);Oa("onChange","change click focusin focusout input keydown keyup selectionchange".split(" "));Oa("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" "));Oa("onBeforeInput",["compositionend","keypress","textInput","paste"]);Oa("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" "));Oa("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" "));Oa("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Xn="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Kv=new Set("cancel close invalid load scroll toggle".split(" ").concat(Xn));function Sc(e,t,a){var n=e.type||"unknown-event";e.currentTarget=a,Ef(n,t,void 0,e),e.currentTarget=null}function mm(e,t){t=(t&4)!==0;for(var a=0;a<e.length;a++){var n=e[a],o=n.event;n=n.listeners;e:{var i=void 0;if(t)for(var s=n.length-1;0<=s;s--){var l=n[s],d=l.instance,c=l.currentTarget;if(l=l.listener,d!==i&&o.isPropagationStopped())break e;Sc(o,l,c),i=d}else for(s=0;s<n.length;s++){if(l=n[s],d=l.instance,c=l.currentTarget,l=l.listener,d!==i&&o.isPropagationStopped())break e;Sc(o,l,c),i=d}}}if(Bi)throw e=Gs,Bi=!1,Gs=null,e}function se(e,t){var a=t[nl];a===void 0&&(a=t[nl]=new Set);var n=e+"__bubble";a.has(n)||(gm(t,e,2,!1),a.add(n))}function as(e,t,a){var n=0;t&&(n|=4),gm(a,e,n,t)}var Jo="_reactListening"+Math.random().toString(36).slice(2);function yo(e){if(!e[Jo]){e[Jo]=!0,Pp.forEach(function(a){a!=="selectionchange"&&(Kv.has(a)||as(a,!1,e),as(a,!0,e))});var t=e.nodeType===9?e:e.ownerDocument;t===null||t[Jo]||(t[Jo]=!0,as("selectionchange",!1,t))}}function gm(e,t,a,n){switch(Yp(t)){case 1:var o=Xf;break;case 4:o=Jf;break;default:o=Xl}a=o.bind(null,t,a,e),o=void 0,!_s||t!=="touchstart"&&t!=="touchmove"&&t!=="wheel"||(o=!0),n?o!==void 0?e.addEventListener(t,a,{capture:!0,passive:o}):e.addEventListener(t,a,!0):o!==void 0?e.addEventListener(t,a,{passive:o}):e.addEventListener(t,a,!1)}function ns(e,t,a,n,o){var i=n;if(!(t&1)&&!(t&2)&&n!==null)e:for(;;){if(n===null)return;var s=n.tag;if(s===3||s===4){var l=n.stateNode.containerInfo;if(l===o||l.nodeType===8&&l.parentNode===o)break;if(s===4)for(s=n.return;s!==null;){var d=s.tag;if((d===3||d===4)&&(d=s.stateNode.containerInfo,d===o||d.nodeType===8&&d.parentNode===o))return;s=s.return}for(;l!==null;){if(s=Pa(l),s===null)return;if(d=s.tag,d===5||d===6){n=i=s;continue e}l=l.parentNode}}n=n.return}Op(function(){var c=i,u=Wl(a),p=[];e:{var m=pm.get(e);if(m!==void 0){var f=ed,P=e;switch(e){case"keypress":if(ji(a)===0)break e;case"keydown":case"keyup":f=gv;break;case"focusin":P="focus",f=Qr;break;case"focusout":P="blur",f=Qr;break;case"beforeblur":case"afterblur":f=Qr;break;case"click":if(a.button===2)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":f=hc;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":f=av;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":f=vv;break;case lm:case dm:case cm:f=iv;break;case um:f=yv;break;case"scroll":f=ev;break;case"wheel":f=Pv;break;case"copy":case"cut":case"paste":f=sv;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":f=vc}var y=(t&4)!==0,A=!y&&e==="scroll",h=y?m!==null?m+"Capture":null:m;y=[];for(var k=c,v;k!==null;){v=k;var b=v.stateNode;if(v.tag===5&&b!==null&&(v=b,h!==null&&(b=mo(k,h),b!=null&&y.push(bo(k,b,v)))),A)break;k=k.return}0<y.length&&(m=new f(m,P,null,a,u),p.push({event:m,listeners:y}))}}if(!(t&7)){e:{if(m=e==="mouseover"||e==="pointerover",f=e==="mouseout"||e==="pointerout",m&&a!==qs&&(P=a.relatedTarget||a.fromElement)&&(Pa(P)||P[Dt]))break e;if((f||m)&&(m=u.window===u?u:(m=u.ownerDocument)?m.defaultView||m.parentWindow:window,f?(P=a.relatedTarget||a.toElement,f=c,P=P?Pa(P):null,P!==null&&(A=Ka(P),P!==A||P.tag!==5&&P.tag!==6)&&(P=null)):(f=null,P=c),f!==P)){if(y=hc,b="onMouseLeave",h="onMouseEnter",k="mouse",(e==="pointerout"||e==="pointerover")&&(y=vc,b="onPointerLeave",h="onPointerEnter",k="pointer"),A=f==null?m:nn(f),v=P==null?m:nn(P),m=new y(b,k+"leave",f,a,u),m.target=A,m.relatedTarget=v,b=null,Pa(u)===c&&(y=new y(h,k+"enter",P,a,u),y.target=v,y.relatedTarget=A,b=y),A=b,f&&P)t:{for(y=f,h=P,k=0,v=y;v;v=Ba(v))k++;for(v=0,b=h;b;b=Ba(b))v++;for(;0<k-v;)y=Ba(y),k--;for(;0<v-k;)h=Ba(h),v--;for(;k--;){if(y===h||h!==null&&y===h.alternate)break t;y=Ba(y),h=Ba(h)}y=null}else y=null;f!==null&&wc(p,m,f,y,!1),P!==null&&A!==null&&wc(p,A,P,y,!0)}}e:{if(m=c?nn(c):window,f=m.nodeName&&m.nodeName.toLowerCase(),f==="select"||f==="input"&&m.type==="file")var z=wv;else if(bc(m))if(nm)z=Nv;else{z=jv;var I=Tv}else(f=m.nodeName)&&f.toLowerCase()==="input"&&(m.type==="checkbox"||m.type==="radio")&&(z=Mv);if(z&&(z=z(e,c))){am(p,z,a,u);break e}I&&I(e,m,c),e==="focusout"&&(I=m._wrapperState)&&I.controlled&&m.type==="number"&&Us(m,"number",m.value)}switch(I=c?nn(c):window,e){case"focusin":(bc(I)||I.contentEditable==="true")&&(tn=I,Ys=c,oo=null);break;case"focusout":oo=Ys=tn=null;break;case"mousedown":Xs=!0;break;case"contextmenu":case"mouseup":case"dragend":Xs=!1,zc(p,a,u);break;case"selectionchange":if(Dv)break;case"keydown":case"keyup":zc(p,a,u)}var C;if(ad)e:{switch(e){case"compositionstart":var S="onCompositionStart";break e;case"compositionend":S="onCompositionEnd";break e;case"compositionupdate":S="onCompositionUpdate";break e}S=void 0}else en?em(e,a)&&(S="onCompositionEnd"):e==="keydown"&&a.keyCode===229&&(S="onCompositionStart");S&&(Jp&&a.locale!=="ko"&&(en||S!=="onCompositionStart"?S==="onCompositionEnd"&&en&&(C=Xp()):(Yt=u,Jl="value"in Yt?Yt.value:Yt.textContent,en=!0)),I=Gi(c,S),0<I.length&&(S=new fc(S,e,null,a,u),p.push({event:S,listeners:I}),C?S.data=C:(C=tm(a),C!==null&&(S.data=C)))),(C=Cv?xv(e,a):zv(e,a))&&(c=Gi(c,"onBeforeInput"),0<c.length&&(u=new fc("onBeforeInput","beforeinput",null,a,u),p.push({event:u,listeners:c}),u.data=C))}mm(p,t)})}function bo(e,t,a){return{instance:e,listener:t,currentTarget:a}}function Gi(e,t){for(var a=t+"Capture",n=[];e!==null;){var o=e,i=o.stateNode;o.tag===5&&i!==null&&(o=i,i=mo(e,a),i!=null&&n.unshift(bo(e,i,o)),i=mo(e,t),i!=null&&n.push(bo(e,i,o))),e=e.return}return n}function Ba(e){if(e===null)return null;do e=e.return;while(e&&e.tag!==5);return e||null}function wc(e,t,a,n,o){for(var i=t._reactName,s=[];a!==null&&a!==n;){var l=a,d=l.alternate,c=l.stateNode;if(d!==null&&d===n)break;l.tag===5&&c!==null&&(l=c,o?(d=mo(a,i),d!=null&&s.unshift(bo(a,d,l))):o||(d=mo(a,i),d!=null&&s.push(bo(a,d,l)))),a=a.return}s.length!==0&&e.push({event:t,listeners:s})}var Uv=/\r\n?/g,Hv=/\u0000|\uFFFD/g;function Tc(e){return(typeof e=="string"?e:""+e).replace(Uv,`
38
- `).replace(Hv,"")}function ei(e,t,a){if(t=Tc(t),Tc(e)!==t&&a)throw Error(N(425))}function Wi(){}var Js=null,el=null;function tl(e,t){return e==="textarea"||e==="noscript"||typeof t.children=="string"||typeof t.children=="number"||typeof t.dangerouslySetInnerHTML=="object"&&t.dangerouslySetInnerHTML!==null&&t.dangerouslySetInnerHTML.__html!=null}var al=typeof setTimeout=="function"?setTimeout:void 0,Fv=typeof clearTimeout=="function"?clearTimeout:void 0,jc=typeof Promise=="function"?Promise:void 0,Bv=typeof queueMicrotask=="function"?queueMicrotask:typeof jc<"u"?function(e){return jc.resolve(null).then(e).catch(Vv)}:al;function Vv(e){setTimeout(function(){throw e})}function os(e,t){var a=t,n=0;do{var o=a.nextSibling;if(e.removeChild(a),o&&o.nodeType===8)if(a=o.data,a==="/$"){if(n===0){e.removeChild(o),fo(t);return}n--}else a!=="$"&&a!=="$?"&&a!=="$!"||n++;a=o}while(a);fo(t)}function na(e){for(;e!=null;e=e.nextSibling){var t=e.nodeType;if(t===1||t===3)break;if(t===8){if(t=e.data,t==="$"||t==="$!"||t==="$?")break;if(t==="/$")return null}}return e}function Mc(e){e=e.previousSibling;for(var t=0;e;){if(e.nodeType===8){var a=e.data;if(a==="$"||a==="$!"||a==="$?"){if(t===0)return e;t--}else a==="/$"&&t++}e=e.previousSibling}return null}var Nn=Math.random().toString(36).slice(2),yt="__reactFiber$"+Nn,Po="__reactProps$"+Nn,Dt="__reactContainer$"+Nn,nl="__reactEvents$"+Nn,qv="__reactListeners$"+Nn,$v="__reactHandles$"+Nn;function Pa(e){var t=e[yt];if(t)return t;for(var a=e.parentNode;a;){if(t=a[Dt]||a[yt]){if(a=t.alternate,t.child!==null||a!==null&&a.child!==null)for(e=Mc(e);e!==null;){if(a=e[yt])return a;e=Mc(e)}return t}e=a,a=e.parentNode}return null}function Oo(e){return e=e[yt]||e[Dt],!e||e.tag!==5&&e.tag!==6&&e.tag!==13&&e.tag!==3?null:e}function nn(e){if(e.tag===5||e.tag===6)return e.stateNode;throw Error(N(33))}function Ar(e){return e[Po]||null}var ol=[],on=-1;function pa(e){return{current:e}}function de(e){0>on||(e.current=ol[on],ol[on]=null,on--)}function re(e,t){on++,ol[on]=e.current,e.current=t}var ca={},Re=pa(ca),Ve=pa(!1),wa=ca;function bn(e,t){var a=e.type.contextTypes;if(!a)return ca;var n=e.stateNode;if(n&&n.__reactInternalMemoizedUnmaskedChildContext===t)return n.__reactInternalMemoizedMaskedChildContext;var o={},i;for(i in a)o[i]=t[i];return n&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function qe(e){return e=e.childContextTypes,e!=null}function Zi(){de(Ve),de(Re)}function Nc(e,t,a){if(Re.current!==ca)throw Error(N(168));re(Re,t),re(Ve,a)}function hm(e,t,a){var n=e.stateNode;if(t=t.childContextTypes,typeof n.getChildContext!="function")return a;n=n.getChildContext();for(var o in n)if(!(o in t))throw Error(N(108,Tf(e)||"Unknown",o));return ge({},a,n)}function Qi(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||ca,wa=Re.current,re(Re,e),re(Ve,Ve.current),!0}function Lc(e,t,a){var n=e.stateNode;if(!n)throw Error(N(169));a?(e=hm(e,t,wa),n.__reactInternalMemoizedMergedChildContext=e,de(Ve),de(Re),re(Re,e)):de(Ve),re(Ve,a)}var wt=null,Cr=!1,is=!1;function fm(e){wt===null?wt=[e]:wt.push(e)}function _v(e){Cr=!0,fm(e)}function ma(){if(!is&&wt!==null){is=!0;var e=0,t=oe;try{var a=wt;for(oe=1;e<a.length;e++){var n=a[e];do n=n(!0);while(n!==null)}wt=null,Cr=!1}catch(o){throw wt!==null&&(wt=wt.slice(e+1)),Fp(Zl,ma),o}finally{oe=t,is=!1}}return null}var rn=[],sn=0,Yi=null,Xi=0,tt=[],at=0,Ta=null,Tt=1,jt="";function ya(e,t){rn[sn++]=Xi,rn[sn++]=Yi,Yi=e,Xi=t}function vm(e,t,a){tt[at++]=Tt,tt[at++]=jt,tt[at++]=Ta,Ta=e;var n=Tt;e=jt;var o=32-ut(n)-1;n&=~(1<<o),a+=1;var i=32-ut(t)+o;if(30<i){var s=o-o%5;i=(n&(1<<s)-1).toString(32),n>>=s,o-=s,Tt=1<<32-ut(t)+o|a<<o|n,jt=i+e}else Tt=1<<i|a<<o|n,jt=e}function od(e){e.return!==null&&(ya(e,1),vm(e,1,0))}function id(e){for(;e===Yi;)Yi=rn[--sn],rn[sn]=null,Xi=rn[--sn],rn[sn]=null;for(;e===Ta;)Ta=tt[--at],tt[at]=null,jt=tt[--at],tt[at]=null,Tt=tt[--at],tt[at]=null}var Qe=null,Ze=null,ce=!1,ct=null;function km(e,t){var a=nt(5,null,null,0);a.elementType="DELETED",a.stateNode=t,a.return=e,t=e.deletions,t===null?(e.deletions=[a],e.flags|=16):t.push(a)}function Rc(e,t){switch(e.tag){case 5:var a=e.type;return t=t.nodeType!==1||a.toLowerCase()!==t.nodeName.toLowerCase()?null:t,t!==null?(e.stateNode=t,Qe=e,Ze=na(t.firstChild),!0):!1;case 6:return t=e.pendingProps===""||t.nodeType!==3?null:t,t!==null?(e.stateNode=t,Qe=e,Ze=null,!0):!1;case 13:return t=t.nodeType!==8?null:t,t!==null?(a=Ta!==null?{id:Tt,overflow:jt}:null,e.memoizedState={dehydrated:t,treeContext:a,retryLane:1073741824},a=nt(18,null,null,0),a.stateNode=t,a.return=e,e.child=a,Qe=e,Ze=null,!0):!1;default:return!1}}function il(e){return(e.mode&1)!==0&&(e.flags&128)===0}function rl(e){if(ce){var t=Ze;if(t){var a=t;if(!Rc(e,t)){if(il(e))throw Error(N(418));t=na(a.nextSibling);var n=Qe;t&&Rc(e,t)?km(n,a):(e.flags=e.flags&-4097|2,ce=!1,Qe=e)}}else{if(il(e))throw Error(N(418));e.flags=e.flags&-4097|2,ce=!1,Qe=e}}}function Dc(e){for(e=e.return;e!==null&&e.tag!==5&&e.tag!==3&&e.tag!==13;)e=e.return;Qe=e}function ti(e){if(e!==Qe)return!1;if(!ce)return Dc(e),ce=!0,!1;var t;if((t=e.tag!==3)&&!(t=e.tag!==5)&&(t=e.type,t=t!=="head"&&t!=="body"&&!tl(e.type,e.memoizedProps)),t&&(t=Ze)){if(il(e))throw ym(),Error(N(418));for(;t;)km(e,t),t=na(t.nextSibling)}if(Dc(e),e.tag===13){if(e=e.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(N(317));e:{for(e=e.nextSibling,t=0;e;){if(e.nodeType===8){var a=e.data;if(a==="/$"){if(t===0){Ze=na(e.nextSibling);break e}t--}else a!=="$"&&a!=="$!"&&a!=="$?"||t++}e=e.nextSibling}Ze=null}}else Ze=Qe?na(e.stateNode.nextSibling):null;return!0}function ym(){for(var e=Ze;e;)e=na(e.nextSibling)}function Pn(){Ze=Qe=null,ce=!1}function rd(e){ct===null?ct=[e]:ct.push(e)}var Gv=Ut.ReactCurrentBatchConfig;function Fn(e,t,a){if(e=a.ref,e!==null&&typeof e!="function"&&typeof e!="object"){if(a._owner){if(a=a._owner,a){if(a.tag!==1)throw Error(N(309));var n=a.stateNode}if(!n)throw Error(N(147,e));var o=n,i=""+e;return t!==null&&t.ref!==null&&typeof t.ref=="function"&&t.ref._stringRef===i?t.ref:(t=function(s){var l=o.refs;s===null?delete l[i]:l[i]=s},t._stringRef=i,t)}if(typeof e!="string")throw Error(N(284));if(!a._owner)throw Error(N(290,e))}return e}function ai(e,t){throw e=Object.prototype.toString.call(t),Error(N(31,e==="[object Object]"?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function Ec(e){var t=e._init;return t(e._payload)}function bm(e){function t(h,k){if(e){var v=h.deletions;v===null?(h.deletions=[k],h.flags|=16):v.push(k)}}function a(h,k){if(!e)return null;for(;k!==null;)t(h,k),k=k.sibling;return null}function n(h,k){for(h=new Map;k!==null;)k.key!==null?h.set(k.key,k):h.set(k.index,k),k=k.sibling;return h}function o(h,k){return h=sa(h,k),h.index=0,h.sibling=null,h}function i(h,k,v){return h.index=v,e?(v=h.alternate,v!==null?(v=v.index,v<k?(h.flags|=2,k):v):(h.flags|=2,k)):(h.flags|=1048576,k)}function s(h){return e&&h.alternate===null&&(h.flags|=2),h}function l(h,k,v,b){return k===null||k.tag!==6?(k=ps(v,h.mode,b),k.return=h,k):(k=o(k,v),k.return=h,k)}function d(h,k,v,b){var z=v.type;return z===Ja?u(h,k,v.props.children,b,v.key):k!==null&&(k.elementType===z||typeof z=="object"&&z!==null&&z.$$typeof===_t&&Ec(z)===k.type)?(b=o(k,v.props),b.ref=Fn(h,k,v),b.return=h,b):(b=Oi(v.type,v.key,v.props,null,h.mode,b),b.ref=Fn(h,k,v),b.return=h,b)}function c(h,k,v,b){return k===null||k.tag!==4||k.stateNode.containerInfo!==v.containerInfo||k.stateNode.implementation!==v.implementation?(k=ms(v,h.mode,b),k.return=h,k):(k=o(k,v.children||[]),k.return=h,k)}function u(h,k,v,b,z){return k===null||k.tag!==7?(k=za(v,h.mode,b,z),k.return=h,k):(k=o(k,v),k.return=h,k)}function p(h,k,v){if(typeof k=="string"&&k!==""||typeof k=="number")return k=ps(""+k,h.mode,v),k.return=h,k;if(typeof k=="object"&&k!==null){switch(k.$$typeof){case $o:return v=Oi(k.type,k.key,k.props,null,h.mode,v),v.ref=Fn(h,null,k),v.return=h,v;case Xa:return k=ms(k,h.mode,v),k.return=h,k;case _t:var b=k._init;return p(h,b(k._payload),v)}if(Qn(k)||En(k))return k=za(k,h.mode,v,null),k.return=h,k;ai(h,k)}return null}function m(h,k,v,b){var z=k!==null?k.key:null;if(typeof v=="string"&&v!==""||typeof v=="number")return z!==null?null:l(h,k,""+v,b);if(typeof v=="object"&&v!==null){switch(v.$$typeof){case $o:return v.key===z?d(h,k,v,b):null;case Xa:return v.key===z?c(h,k,v,b):null;case _t:return z=v._init,m(h,k,z(v._payload),b)}if(Qn(v)||En(v))return z!==null?null:u(h,k,v,b,null);ai(h,v)}return null}function f(h,k,v,b,z){if(typeof b=="string"&&b!==""||typeof b=="number")return h=h.get(v)||null,l(k,h,""+b,z);if(typeof b=="object"&&b!==null){switch(b.$$typeof){case $o:return h=h.get(b.key===null?v:b.key)||null,d(k,h,b,z);case Xa:return h=h.get(b.key===null?v:b.key)||null,c(k,h,b,z);case _t:var I=b._init;return f(h,k,v,I(b._payload),z)}if(Qn(b)||En(b))return h=h.get(v)||null,u(k,h,b,z,null);ai(k,b)}return null}function P(h,k,v,b){for(var z=null,I=null,C=k,S=k=0,L=null;C!==null&&S<v.length;S++){C.index>S?(L=C,C=null):L=C.sibling;var T=m(h,C,v[S],b);if(T===null){C===null&&(C=L);break}e&&C&&T.alternate===null&&t(h,C),k=i(T,k,S),I===null?z=T:I.sibling=T,I=T,C=L}if(S===v.length)return a(h,C),ce&&ya(h,S),z;if(C===null){for(;S<v.length;S++)C=p(h,v[S],b),C!==null&&(k=i(C,k,S),I===null?z=C:I.sibling=C,I=C);return ce&&ya(h,S),z}for(C=n(h,C);S<v.length;S++)L=f(C,h,S,v[S],b),L!==null&&(e&&L.alternate!==null&&C.delete(L.key===null?S:L.key),k=i(L,k,S),I===null?z=L:I.sibling=L,I=L);return e&&C.forEach(function(M){return t(h,M)}),ce&&ya(h,S),z}function y(h,k,v,b){var z=En(v);if(typeof z!="function")throw Error(N(150));if(v=z.call(v),v==null)throw Error(N(151));for(var I=z=null,C=k,S=k=0,L=null,T=v.next();C!==null&&!T.done;S++,T=v.next()){C.index>S?(L=C,C=null):L=C.sibling;var M=m(h,C,T.value,b);if(M===null){C===null&&(C=L);break}e&&C&&M.alternate===null&&t(h,C),k=i(M,k,S),I===null?z=M:I.sibling=M,I=M,C=L}if(T.done)return a(h,C),ce&&ya(h,S),z;if(C===null){for(;!T.done;S++,T=v.next())T=p(h,T.value,b),T!==null&&(k=i(T,k,S),I===null?z=T:I.sibling=T,I=T);return ce&&ya(h,S),z}for(C=n(h,C);!T.done;S++,T=v.next())T=f(C,h,S,T.value,b),T!==null&&(e&&T.alternate!==null&&C.delete(T.key===null?S:T.key),k=i(T,k,S),I===null?z=T:I.sibling=T,I=T);return e&&C.forEach(function(D){return t(h,D)}),ce&&ya(h,S),z}function A(h,k,v,b){if(typeof v=="object"&&v!==null&&v.type===Ja&&v.key===null&&(v=v.props.children),typeof v=="object"&&v!==null){switch(v.$$typeof){case $o:e:{for(var z=v.key,I=k;I!==null;){if(I.key===z){if(z=v.type,z===Ja){if(I.tag===7){a(h,I.sibling),k=o(I,v.props.children),k.return=h,h=k;break e}}else if(I.elementType===z||typeof z=="object"&&z!==null&&z.$$typeof===_t&&Ec(z)===I.type){a(h,I.sibling),k=o(I,v.props),k.ref=Fn(h,I,v),k.return=h,h=k;break e}a(h,I);break}else t(h,I);I=I.sibling}v.type===Ja?(k=za(v.props.children,h.mode,b,v.key),k.return=h,h=k):(b=Oi(v.type,v.key,v.props,null,h.mode,b),b.ref=Fn(h,k,v),b.return=h,h=b)}return s(h);case Xa:e:{for(I=v.key;k!==null;){if(k.key===I)if(k.tag===4&&k.stateNode.containerInfo===v.containerInfo&&k.stateNode.implementation===v.implementation){a(h,k.sibling),k=o(k,v.children||[]),k.return=h,h=k;break e}else{a(h,k);break}else t(h,k);k=k.sibling}k=ms(v,h.mode,b),k.return=h,h=k}return s(h);case _t:return I=v._init,A(h,k,I(v._payload),b)}if(Qn(v))return P(h,k,v,b);if(En(v))return y(h,k,v,b);ai(h,v)}return typeof v=="string"&&v!==""||typeof v=="number"?(v=""+v,k!==null&&k.tag===6?(a(h,k.sibling),k=o(k,v),k.return=h,h=k):(a(h,k),k=ps(v,h.mode,b),k.return=h,h=k),s(h)):a(h,k)}return A}var An=bm(!0),Pm=bm(!1),Ji=pa(null),er=null,ln=null,sd=null;function ld(){sd=ln=er=null}function dd(e){var t=Ji.current;de(Ji),e._currentValue=t}function sl(e,t,a){for(;e!==null;){var n=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,n!==null&&(n.childLanes|=t)):n!==null&&(n.childLanes&t)!==t&&(n.childLanes|=t),e===a)break;e=e.return}}function hn(e,t){er=e,sd=ln=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Fe=!0),e.firstContext=null)}function it(e){var t=e._currentValue;if(sd!==e)if(e={context:e,memoizedValue:t,next:null},ln===null){if(er===null)throw Error(N(308));ln=e,er.dependencies={lanes:0,firstContext:e}}else ln=ln.next=e;return t}var Aa=null;function cd(e){Aa===null?Aa=[e]:Aa.push(e)}function Am(e,t,a,n){var o=t.interleaved;return o===null?(a.next=a,cd(t)):(a.next=o.next,o.next=a),t.interleaved=a,Et(e,n)}function Et(e,t){e.lanes|=t;var a=e.alternate;for(a!==null&&(a.lanes|=t),a=e,e=e.return;e!==null;)e.childLanes|=t,a=e.alternate,a!==null&&(a.childLanes|=t),a=e,e=e.return;return a.tag===3?a.stateNode:null}var Gt=!1;function ud(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Cm(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Nt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function oa(e,t,a){var n=e.updateQueue;if(n===null)return null;if(n=n.shared,te&2){var o=n.pending;return o===null?t.next=t:(t.next=o.next,o.next=t),n.pending=t,Et(e,a)}return o=n.interleaved,o===null?(t.next=t,cd(n)):(t.next=o.next,o.next=t),n.interleaved=t,Et(e,a)}function Mi(e,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194240)!==0)){var n=t.lanes;n&=e.pendingLanes,a|=n,t.lanes=a,Ql(e,a)}}function Oc(e,t){var a=e.updateQueue,n=e.alternate;if(n!==null&&(n=n.updateQueue,a===n)){var o=null,i=null;if(a=a.firstBaseUpdate,a!==null){do{var s={eventTime:a.eventTime,lane:a.lane,tag:a.tag,payload:a.payload,callback:a.callback,next:null};i===null?o=i=s:i=i.next=s,a=a.next}while(a!==null);i===null?o=i=t:i=i.next=t}else o=i=t;a={baseState:n.baseState,firstBaseUpdate:o,lastBaseUpdate:i,shared:n.shared,effects:n.effects},e.updateQueue=a;return}e=a.lastBaseUpdate,e===null?a.firstBaseUpdate=t:e.next=t,a.lastBaseUpdate=t}function tr(e,t,a,n){var o=e.updateQueue;Gt=!1;var i=o.firstBaseUpdate,s=o.lastBaseUpdate,l=o.shared.pending;if(l!==null){o.shared.pending=null;var d=l,c=d.next;d.next=null,s===null?i=c:s.next=c,s=d;var u=e.alternate;u!==null&&(u=u.updateQueue,l=u.lastBaseUpdate,l!==s&&(l===null?u.firstBaseUpdate=c:l.next=c,u.lastBaseUpdate=d))}if(i!==null){var p=o.baseState;s=0,u=c=d=null,l=i;do{var m=l.lane,f=l.eventTime;if((n&m)===m){u!==null&&(u=u.next={eventTime:f,lane:0,tag:l.tag,payload:l.payload,callback:l.callback,next:null});e:{var P=e,y=l;switch(m=t,f=a,y.tag){case 1:if(P=y.payload,typeof P=="function"){p=P.call(f,p,m);break e}p=P;break e;case 3:P.flags=P.flags&-65537|128;case 0:if(P=y.payload,m=typeof P=="function"?P.call(f,p,m):P,m==null)break e;p=ge({},p,m);break e;case 2:Gt=!0}}l.callback!==null&&l.lane!==0&&(e.flags|=64,m=o.effects,m===null?o.effects=[l]:m.push(l))}else f={eventTime:f,lane:m,tag:l.tag,payload:l.payload,callback:l.callback,next:null},u===null?(c=u=f,d=p):u=u.next=f,s|=m;if(l=l.next,l===null){if(l=o.shared.pending,l===null)break;m=l,l=m.next,m.next=null,o.lastBaseUpdate=m,o.shared.pending=null}}while(!0);if(u===null&&(d=p),o.baseState=d,o.firstBaseUpdate=c,o.lastBaseUpdate=u,t=o.shared.interleaved,t!==null){o=t;do s|=o.lane,o=o.next;while(o!==t)}else i===null&&(o.shared.lanes=0);Ma|=s,e.lanes=s,e.memoizedState=p}}function Kc(e,t,a){if(e=t.effects,t.effects=null,e!==null)for(t=0;t<e.length;t++){var n=e[t],o=n.callback;if(o!==null){if(n.callback=null,n=a,typeof o!="function")throw Error(N(191,o));o.call(n)}}}var Ko={},Ct=pa(Ko),Ao=pa(Ko),Co=pa(Ko);function Ca(e){if(e===Ko)throw Error(N(174));return e}function pd(e,t){switch(re(Co,t),re(Ao,e),re(Ct,Ko),e=t.nodeType,e){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:Fs(null,"");break;default:e=e===8?t.parentNode:t,t=e.namespaceURI||null,e=e.tagName,t=Fs(t,e)}de(Ct),re(Ct,t)}function Cn(){de(Ct),de(Ao),de(Co)}function xm(e){Ca(Co.current);var t=Ca(Ct.current),a=Fs(t,e.type);t!==a&&(re(Ao,e),re(Ct,a))}function md(e){Ao.current===e&&(de(Ct),de(Ao))}var ue=pa(0);function ar(e){for(var t=e;t!==null;){if(t.tag===13){var a=t.memoizedState;if(a!==null&&(a=a.dehydrated,a===null||a.data==="$?"||a.data==="$!"))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if(t.flags&128)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var rs=[];function gd(){for(var e=0;e<rs.length;e++)rs[e]._workInProgressVersionPrimary=null;rs.length=0}var Ni=Ut.ReactCurrentDispatcher,ss=Ut.ReactCurrentBatchConfig,ja=0,pe=null,Ae=null,ze=null,nr=!1,io=!1,xo=0,Wv=0;function je(){throw Error(N(321))}function hd(e,t){if(t===null)return!1;for(var a=0;a<t.length&&a<e.length;a++)if(!mt(e[a],t[a]))return!1;return!0}function fd(e,t,a,n,o,i){if(ja=i,pe=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Ni.current=e===null||e.memoizedState===null?Xv:Jv,e=a(n,o),io){i=0;do{if(io=!1,xo=0,25<=i)throw Error(N(301));i+=1,ze=Ae=null,t.updateQueue=null,Ni.current=ek,e=a(n,o)}while(io)}if(Ni.current=or,t=Ae!==null&&Ae.next!==null,ja=0,ze=Ae=pe=null,nr=!1,t)throw Error(N(300));return e}function vd(){var e=xo!==0;return xo=0,e}function kt(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return ze===null?pe.memoizedState=ze=e:ze=ze.next=e,ze}function rt(){if(Ae===null){var e=pe.alternate;e=e!==null?e.memoizedState:null}else e=Ae.next;var t=ze===null?pe.memoizedState:ze.next;if(t!==null)ze=t,Ae=e;else{if(e===null)throw Error(N(310));Ae=e,e={memoizedState:Ae.memoizedState,baseState:Ae.baseState,baseQueue:Ae.baseQueue,queue:Ae.queue,next:null},ze===null?pe.memoizedState=ze=e:ze=ze.next=e}return ze}function zo(e,t){return typeof t=="function"?t(e):t}function ls(e){var t=rt(),a=t.queue;if(a===null)throw Error(N(311));a.lastRenderedReducer=e;var n=Ae,o=n.baseQueue,i=a.pending;if(i!==null){if(o!==null){var s=o.next;o.next=i.next,i.next=s}n.baseQueue=o=i,a.pending=null}if(o!==null){i=o.next,n=n.baseState;var l=s=null,d=null,c=i;do{var u=c.lane;if((ja&u)===u)d!==null&&(d=d.next={lane:0,action:c.action,hasEagerState:c.hasEagerState,eagerState:c.eagerState,next:null}),n=c.hasEagerState?c.eagerState:e(n,c.action);else{var p={lane:u,action:c.action,hasEagerState:c.hasEagerState,eagerState:c.eagerState,next:null};d===null?(l=d=p,s=n):d=d.next=p,pe.lanes|=u,Ma|=u}c=c.next}while(c!==null&&c!==i);d===null?s=n:d.next=l,mt(n,t.memoizedState)||(Fe=!0),t.memoizedState=n,t.baseState=s,t.baseQueue=d,a.lastRenderedState=n}if(e=a.interleaved,e!==null){o=e;do i=o.lane,pe.lanes|=i,Ma|=i,o=o.next;while(o!==e)}else o===null&&(a.lanes=0);return[t.memoizedState,a.dispatch]}function ds(e){var t=rt(),a=t.queue;if(a===null)throw Error(N(311));a.lastRenderedReducer=e;var n=a.dispatch,o=a.pending,i=t.memoizedState;if(o!==null){a.pending=null;var s=o=o.next;do i=e(i,s.action),s=s.next;while(s!==o);mt(i,t.memoizedState)||(Fe=!0),t.memoizedState=i,t.baseQueue===null&&(t.baseState=i),a.lastRenderedState=i}return[i,n]}function zm(){}function Im(e,t){var a=pe,n=rt(),o=t(),i=!mt(n.memoizedState,o);if(i&&(n.memoizedState=o,Fe=!0),n=n.queue,kd(Tm.bind(null,a,n,e),[e]),n.getSnapshot!==t||i||ze!==null&&ze.memoizedState.tag&1){if(a.flags|=2048,Io(9,wm.bind(null,a,n,o,t),void 0,null),Ie===null)throw Error(N(349));ja&30||Sm(a,t,o)}return o}function Sm(e,t,a){e.flags|=16384,e={getSnapshot:t,value:a},t=pe.updateQueue,t===null?(t={lastEffect:null,stores:null},pe.updateQueue=t,t.stores=[e]):(a=t.stores,a===null?t.stores=[e]:a.push(e))}function wm(e,t,a,n){t.value=a,t.getSnapshot=n,jm(t)&&Mm(e)}function Tm(e,t,a){return a(function(){jm(t)&&Mm(e)})}function jm(e){var t=e.getSnapshot;e=e.value;try{var a=t();return!mt(e,a)}catch{return!0}}function Mm(e){var t=Et(e,1);t!==null&&pt(t,e,1,-1)}function Uc(e){var t=kt();return typeof e=="function"&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:zo,lastRenderedState:e},t.queue=e,e=e.dispatch=Yv.bind(null,pe,e),[t.memoizedState,e]}function Io(e,t,a,n){return e={tag:e,create:t,destroy:a,deps:n,next:null},t=pe.updateQueue,t===null?(t={lastEffect:null,stores:null},pe.updateQueue=t,t.lastEffect=e.next=e):(a=t.lastEffect,a===null?t.lastEffect=e.next=e:(n=a.next,a.next=e,e.next=n,t.lastEffect=e)),e}function Nm(){return rt().memoizedState}function Li(e,t,a,n){var o=kt();pe.flags|=e,o.memoizedState=Io(1|t,a,void 0,n===void 0?null:n)}function xr(e,t,a,n){var o=rt();n=n===void 0?null:n;var i=void 0;if(Ae!==null){var s=Ae.memoizedState;if(i=s.destroy,n!==null&&hd(n,s.deps)){o.memoizedState=Io(t,a,i,n);return}}pe.flags|=e,o.memoizedState=Io(1|t,a,i,n)}function Hc(e,t){return Li(8390656,8,e,t)}function kd(e,t){return xr(2048,8,e,t)}function Lm(e,t){return xr(4,2,e,t)}function Rm(e,t){return xr(4,4,e,t)}function Dm(e,t){if(typeof t=="function")return e=e(),t(e),function(){t(null)};if(t!=null)return e=e(),t.current=e,function(){t.current=null}}function Em(e,t,a){return a=a!=null?a.concat([e]):null,xr(4,4,Dm.bind(null,t,e),a)}function yd(){}function Om(e,t){var a=rt();t=t===void 0?null:t;var n=a.memoizedState;return n!==null&&t!==null&&hd(t,n[1])?n[0]:(a.memoizedState=[e,t],e)}function Km(e,t){var a=rt();t=t===void 0?null:t;var n=a.memoizedState;return n!==null&&t!==null&&hd(t,n[1])?n[0]:(e=e(),a.memoizedState=[e,t],e)}function Um(e,t,a){return ja&21?(mt(a,t)||(a=qp(),pe.lanes|=a,Ma|=a,e.baseState=!0),t):(e.baseState&&(e.baseState=!1,Fe=!0),e.memoizedState=a)}function Zv(e,t){var a=oe;oe=a!==0&&4>a?a:4,e(!0);var n=ss.transition;ss.transition={};try{e(!1),t()}finally{oe=a,ss.transition=n}}function Hm(){return rt().memoizedState}function Qv(e,t,a){var n=ra(e);if(a={lane:n,action:a,hasEagerState:!1,eagerState:null,next:null},Fm(e))Bm(t,a);else if(a=Am(e,t,a,n),a!==null){var o=Ee();pt(a,e,n,o),Vm(a,t,n)}}function Yv(e,t,a){var n=ra(e),o={lane:n,action:a,hasEagerState:!1,eagerState:null,next:null};if(Fm(e))Bm(t,o);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var s=t.lastRenderedState,l=i(s,a);if(o.hasEagerState=!0,o.eagerState=l,mt(l,s)){var d=t.interleaved;d===null?(o.next=o,cd(t)):(o.next=d.next,d.next=o),t.interleaved=o;return}}catch{}finally{}a=Am(e,t,o,n),a!==null&&(o=Ee(),pt(a,e,n,o),Vm(a,t,n))}}function Fm(e){var t=e.alternate;return e===pe||t!==null&&t===pe}function Bm(e,t){io=nr=!0;var a=e.pending;a===null?t.next=t:(t.next=a.next,a.next=t),e.pending=t}function Vm(e,t,a){if(a&4194240){var n=t.lanes;n&=e.pendingLanes,a|=n,t.lanes=a,Ql(e,a)}}var or={readContext:it,useCallback:je,useContext:je,useEffect:je,useImperativeHandle:je,useInsertionEffect:je,useLayoutEffect:je,useMemo:je,useReducer:je,useRef:je,useState:je,useDebugValue:je,useDeferredValue:je,useTransition:je,useMutableSource:je,useSyncExternalStore:je,useId:je,unstable_isNewReconciler:!1},Xv={readContext:it,useCallback:function(e,t){return kt().memoizedState=[e,t===void 0?null:t],e},useContext:it,useEffect:Hc,useImperativeHandle:function(e,t,a){return a=a!=null?a.concat([e]):null,Li(4194308,4,Dm.bind(null,t,e),a)},useLayoutEffect:function(e,t){return Li(4194308,4,e,t)},useInsertionEffect:function(e,t){return Li(4,2,e,t)},useMemo:function(e,t){var a=kt();return t=t===void 0?null:t,e=e(),a.memoizedState=[e,t],e},useReducer:function(e,t,a){var n=kt();return t=a!==void 0?a(t):t,n.memoizedState=n.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},n.queue=e,e=e.dispatch=Qv.bind(null,pe,e),[n.memoizedState,e]},useRef:function(e){var t=kt();return e={current:e},t.memoizedState=e},useState:Uc,useDebugValue:yd,useDeferredValue:function(e){return kt().memoizedState=e},useTransition:function(){var e=Uc(!1),t=e[0];return e=Zv.bind(null,e[1]),kt().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,a){var n=pe,o=kt();if(ce){if(a===void 0)throw Error(N(407));a=a()}else{if(a=t(),Ie===null)throw Error(N(349));ja&30||Sm(n,t,a)}o.memoizedState=a;var i={value:a,getSnapshot:t};return o.queue=i,Hc(Tm.bind(null,n,i,e),[e]),n.flags|=2048,Io(9,wm.bind(null,n,i,a,t),void 0,null),a},useId:function(){var e=kt(),t=Ie.identifierPrefix;if(ce){var a=jt,n=Tt;a=(n&~(1<<32-ut(n)-1)).toString(32)+a,t=":"+t+"R"+a,a=xo++,0<a&&(t+="H"+a.toString(32)),t+=":"}else a=Wv++,t=":"+t+"r"+a.toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},Jv={readContext:it,useCallback:Om,useContext:it,useEffect:kd,useImperativeHandle:Em,useInsertionEffect:Lm,useLayoutEffect:Rm,useMemo:Km,useReducer:ls,useRef:Nm,useState:function(){return ls(zo)},useDebugValue:yd,useDeferredValue:function(e){var t=rt();return Um(t,Ae.memoizedState,e)},useTransition:function(){var e=ls(zo)[0],t=rt().memoizedState;return[e,t]},useMutableSource:zm,useSyncExternalStore:Im,useId:Hm,unstable_isNewReconciler:!1},ek={readContext:it,useCallback:Om,useContext:it,useEffect:kd,useImperativeHandle:Em,useInsertionEffect:Lm,useLayoutEffect:Rm,useMemo:Km,useReducer:ds,useRef:Nm,useState:function(){return ds(zo)},useDebugValue:yd,useDeferredValue:function(e){var t=rt();return Ae===null?t.memoizedState=e:Um(t,Ae.memoizedState,e)},useTransition:function(){var e=ds(zo)[0],t=rt().memoizedState;return[e,t]},useMutableSource:zm,useSyncExternalStore:Im,useId:Hm,unstable_isNewReconciler:!1};function lt(e,t){if(e&&e.defaultProps){t=ge({},t),e=e.defaultProps;for(var a in e)t[a]===void 0&&(t[a]=e[a]);return t}return t}function ll(e,t,a,n){t=e.memoizedState,a=a(n,t),a=a==null?t:ge({},t,a),e.memoizedState=a,e.lanes===0&&(e.updateQueue.baseState=a)}var zr={isMounted:function(e){return(e=e._reactInternals)?Ka(e)===e:!1},enqueueSetState:function(e,t,a){e=e._reactInternals;var n=Ee(),o=ra(e),i=Nt(n,o);i.payload=t,a!=null&&(i.callback=a),t=oa(e,i,o),t!==null&&(pt(t,e,o,n),Mi(t,e,o))},enqueueReplaceState:function(e,t,a){e=e._reactInternals;var n=Ee(),o=ra(e),i=Nt(n,o);i.tag=1,i.payload=t,a!=null&&(i.callback=a),t=oa(e,i,o),t!==null&&(pt(t,e,o,n),Mi(t,e,o))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var a=Ee(),n=ra(e),o=Nt(a,n);o.tag=2,t!=null&&(o.callback=t),t=oa(e,o,n),t!==null&&(pt(t,e,n,a),Mi(t,e,n))}};function Fc(e,t,a,n,o,i,s){return e=e.stateNode,typeof e.shouldComponentUpdate=="function"?e.shouldComponentUpdate(n,i,s):t.prototype&&t.prototype.isPureReactComponent?!ko(a,n)||!ko(o,i):!0}function qm(e,t,a){var n=!1,o=ca,i=t.contextType;return typeof i=="object"&&i!==null?i=it(i):(o=qe(t)?wa:Re.current,n=t.contextTypes,i=(n=n!=null)?bn(e,o):ca),t=new t(a,i),e.memoizedState=t.state!==null&&t.state!==void 0?t.state:null,t.updater=zr,e.stateNode=t,t._reactInternals=e,n&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=o,e.__reactInternalMemoizedMaskedChildContext=i),t}function Bc(e,t,a,n){e=t.state,typeof t.componentWillReceiveProps=="function"&&t.componentWillReceiveProps(a,n),typeof t.UNSAFE_componentWillReceiveProps=="function"&&t.UNSAFE_componentWillReceiveProps(a,n),t.state!==e&&zr.enqueueReplaceState(t,t.state,null)}function dl(e,t,a,n){var o=e.stateNode;o.props=a,o.state=e.memoizedState,o.refs={},ud(e);var i=t.contextType;typeof i=="object"&&i!==null?o.context=it(i):(i=qe(t)?wa:Re.current,o.context=bn(e,i)),o.state=e.memoizedState,i=t.getDerivedStateFromProps,typeof i=="function"&&(ll(e,t,i,a),o.state=e.memoizedState),typeof t.getDerivedStateFromProps=="function"||typeof o.getSnapshotBeforeUpdate=="function"||typeof o.UNSAFE_componentWillMount!="function"&&typeof o.componentWillMount!="function"||(t=o.state,typeof o.componentWillMount=="function"&&o.componentWillMount(),typeof o.UNSAFE_componentWillMount=="function"&&o.UNSAFE_componentWillMount(),t!==o.state&&zr.enqueueReplaceState(o,o.state,null),tr(e,a,o,n),o.state=e.memoizedState),typeof o.componentDidMount=="function"&&(e.flags|=4194308)}function xn(e,t){try{var a="",n=t;do a+=wf(n),n=n.return;while(n);var o=a}catch(i){o=`
39
- Error generating stack: `+i.message+`
40
- `+i.stack}return{value:e,source:t,stack:o,digest:null}}function cs(e,t,a){return{value:e,source:null,stack:a??null,digest:t??null}}function cl(e,t){try{console.error(t.value)}catch(a){setTimeout(function(){throw a})}}var tk=typeof WeakMap=="function"?WeakMap:Map;function $m(e,t,a){a=Nt(-1,a),a.tag=3,a.payload={element:null};var n=t.value;return a.callback=function(){rr||(rr=!0,bl=n),cl(e,t)},a}function _m(e,t,a){a=Nt(-1,a),a.tag=3;var n=e.type.getDerivedStateFromError;if(typeof n=="function"){var o=t.value;a.payload=function(){return n(o)},a.callback=function(){cl(e,t)}}var i=e.stateNode;return i!==null&&typeof i.componentDidCatch=="function"&&(a.callback=function(){cl(e,t),typeof n!="function"&&(ia===null?ia=new Set([this]):ia.add(this));var s=t.stack;this.componentDidCatch(t.value,{componentStack:s!==null?s:""})}),a}function Vc(e,t,a){var n=e.pingCache;if(n===null){n=e.pingCache=new tk;var o=new Set;n.set(t,o)}else o=n.get(t),o===void 0&&(o=new Set,n.set(t,o));o.has(a)||(o.add(a),e=hk.bind(null,e,t,a),t.then(e,e))}function qc(e){do{var t;if((t=e.tag===13)&&(t=e.memoizedState,t=t!==null?t.dehydrated!==null:!0),t)return e;e=e.return}while(e!==null);return null}function $c(e,t,a,n,o){return e.mode&1?(e.flags|=65536,e.lanes=o,e):(e===t?e.flags|=65536:(e.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(t=Nt(-1,1),t.tag=2,oa(a,t,1))),a.lanes|=1),e)}var ak=Ut.ReactCurrentOwner,Fe=!1;function De(e,t,a,n){t.child=e===null?Pm(t,null,a,n):An(t,e.child,a,n)}function _c(e,t,a,n,o){a=a.render;var i=t.ref;return hn(t,o),n=fd(e,t,a,n,i,o),a=vd(),e!==null&&!Fe?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,Ot(e,t,o)):(ce&&a&&od(t),t.flags|=1,De(e,t,n,o),t.child)}function Gc(e,t,a,n,o){if(e===null){var i=a.type;return typeof i=="function"&&!Sd(i)&&i.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(t.tag=15,t.type=i,Gm(e,t,i,n,o)):(e=Oi(a.type,null,n,t,t.mode,o),e.ref=t.ref,e.return=t,t.child=e)}if(i=e.child,!(e.lanes&o)){var s=i.memoizedProps;if(a=a.compare,a=a!==null?a:ko,a(s,n)&&e.ref===t.ref)return Ot(e,t,o)}return t.flags|=1,e=sa(i,n),e.ref=t.ref,e.return=t,t.child=e}function Gm(e,t,a,n,o){if(e!==null){var i=e.memoizedProps;if(ko(i,n)&&e.ref===t.ref)if(Fe=!1,t.pendingProps=n=i,(e.lanes&o)!==0)e.flags&131072&&(Fe=!0);else return t.lanes=e.lanes,Ot(e,t,o)}return ul(e,t,a,n,o)}function Wm(e,t,a){var n=t.pendingProps,o=n.children,i=e!==null?e.memoizedState:null;if(n.mode==="hidden")if(!(t.mode&1))t.memoizedState={baseLanes:0,cachePool:null,transitions:null},re(cn,We),We|=a;else{if(!(a&1073741824))return e=i!==null?i.baseLanes|a:a,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,re(cn,We),We|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},n=i!==null?i.baseLanes:a,re(cn,We),We|=n}else i!==null?(n=i.baseLanes|a,t.memoizedState=null):n=a,re(cn,We),We|=n;return De(e,t,o,a),t.child}function Zm(e,t){var a=t.ref;(e===null&&a!==null||e!==null&&e.ref!==a)&&(t.flags|=512,t.flags|=2097152)}function ul(e,t,a,n,o){var i=qe(a)?wa:Re.current;return i=bn(t,i),hn(t,o),a=fd(e,t,a,n,i,o),n=vd(),e!==null&&!Fe?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,Ot(e,t,o)):(ce&&n&&od(t),t.flags|=1,De(e,t,a,o),t.child)}function Wc(e,t,a,n,o){if(qe(a)){var i=!0;Qi(t)}else i=!1;if(hn(t,o),t.stateNode===null)Ri(e,t),qm(t,a,n),dl(t,a,n,o),n=!0;else if(e===null){var s=t.stateNode,l=t.memoizedProps;s.props=l;var d=s.context,c=a.contextType;typeof c=="object"&&c!==null?c=it(c):(c=qe(a)?wa:Re.current,c=bn(t,c));var u=a.getDerivedStateFromProps,p=typeof u=="function"||typeof s.getSnapshotBeforeUpdate=="function";p||typeof s.UNSAFE_componentWillReceiveProps!="function"&&typeof s.componentWillReceiveProps!="function"||(l!==n||d!==c)&&Bc(t,s,n,c),Gt=!1;var m=t.memoizedState;s.state=m,tr(t,n,s,o),d=t.memoizedState,l!==n||m!==d||Ve.current||Gt?(typeof u=="function"&&(ll(t,a,u,n),d=t.memoizedState),(l=Gt||Fc(t,a,l,n,m,d,c))?(p||typeof s.UNSAFE_componentWillMount!="function"&&typeof s.componentWillMount!="function"||(typeof s.componentWillMount=="function"&&s.componentWillMount(),typeof s.UNSAFE_componentWillMount=="function"&&s.UNSAFE_componentWillMount()),typeof s.componentDidMount=="function"&&(t.flags|=4194308)):(typeof s.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=n,t.memoizedState=d),s.props=n,s.state=d,s.context=c,n=l):(typeof s.componentDidMount=="function"&&(t.flags|=4194308),n=!1)}else{s=t.stateNode,Cm(e,t),l=t.memoizedProps,c=t.type===t.elementType?l:lt(t.type,l),s.props=c,p=t.pendingProps,m=s.context,d=a.contextType,typeof d=="object"&&d!==null?d=it(d):(d=qe(a)?wa:Re.current,d=bn(t,d));var f=a.getDerivedStateFromProps;(u=typeof f=="function"||typeof s.getSnapshotBeforeUpdate=="function")||typeof s.UNSAFE_componentWillReceiveProps!="function"&&typeof s.componentWillReceiveProps!="function"||(l!==p||m!==d)&&Bc(t,s,n,d),Gt=!1,m=t.memoizedState,s.state=m,tr(t,n,s,o);var P=t.memoizedState;l!==p||m!==P||Ve.current||Gt?(typeof f=="function"&&(ll(t,a,f,n),P=t.memoizedState),(c=Gt||Fc(t,a,c,n,m,P,d)||!1)?(u||typeof s.UNSAFE_componentWillUpdate!="function"&&typeof s.componentWillUpdate!="function"||(typeof s.componentWillUpdate=="function"&&s.componentWillUpdate(n,P,d),typeof s.UNSAFE_componentWillUpdate=="function"&&s.UNSAFE_componentWillUpdate(n,P,d)),typeof s.componentDidUpdate=="function"&&(t.flags|=4),typeof s.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof s.componentDidUpdate!="function"||l===e.memoizedProps&&m===e.memoizedState||(t.flags|=4),typeof s.getSnapshotBeforeUpdate!="function"||l===e.memoizedProps&&m===e.memoizedState||(t.flags|=1024),t.memoizedProps=n,t.memoizedState=P),s.props=n,s.state=P,s.context=d,n=c):(typeof s.componentDidUpdate!="function"||l===e.memoizedProps&&m===e.memoizedState||(t.flags|=4),typeof s.getSnapshotBeforeUpdate!="function"||l===e.memoizedProps&&m===e.memoizedState||(t.flags|=1024),n=!1)}return pl(e,t,a,n,i,o)}function pl(e,t,a,n,o,i){Zm(e,t);var s=(t.flags&128)!==0;if(!n&&!s)return o&&Lc(t,a,!1),Ot(e,t,i);n=t.stateNode,ak.current=t;var l=s&&typeof a.getDerivedStateFromError!="function"?null:n.render();return t.flags|=1,e!==null&&s?(t.child=An(t,e.child,null,i),t.child=An(t,null,l,i)):De(e,t,l,i),t.memoizedState=n.state,o&&Lc(t,a,!0),t.child}function Qm(e){var t=e.stateNode;t.pendingContext?Nc(e,t.pendingContext,t.pendingContext!==t.context):t.context&&Nc(e,t.context,!1),pd(e,t.containerInfo)}function Zc(e,t,a,n,o){return Pn(),rd(o),t.flags|=256,De(e,t,a,n),t.child}var ml={dehydrated:null,treeContext:null,retryLane:0};function gl(e){return{baseLanes:e,cachePool:null,transitions:null}}function Ym(e,t,a){var n=t.pendingProps,o=ue.current,i=!1,s=(t.flags&128)!==0,l;if((l=s)||(l=e!==null&&e.memoizedState===null?!1:(o&2)!==0),l?(i=!0,t.flags&=-129):(e===null||e.memoizedState!==null)&&(o|=1),re(ue,o&1),e===null)return rl(t),e=t.memoizedState,e!==null&&(e=e.dehydrated,e!==null)?(t.mode&1?e.data==="$!"?t.lanes=8:t.lanes=1073741824:t.lanes=1,null):(s=n.children,e=n.fallback,i?(n=t.mode,i=t.child,s={mode:"hidden",children:s},!(n&1)&&i!==null?(i.childLanes=0,i.pendingProps=s):i=wr(s,n,0,null),e=za(e,n,a,null),i.return=t,e.return=t,i.sibling=e,t.child=i,t.child.memoizedState=gl(a),t.memoizedState=ml,e):bd(t,s));if(o=e.memoizedState,o!==null&&(l=o.dehydrated,l!==null))return nk(e,t,s,n,l,o,a);if(i){i=n.fallback,s=t.mode,o=e.child,l=o.sibling;var d={mode:"hidden",children:n.children};return!(s&1)&&t.child!==o?(n=t.child,n.childLanes=0,n.pendingProps=d,t.deletions=null):(n=sa(o,d),n.subtreeFlags=o.subtreeFlags&14680064),l!==null?i=sa(l,i):(i=za(i,s,a,null),i.flags|=2),i.return=t,n.return=t,n.sibling=i,t.child=n,n=i,i=t.child,s=e.child.memoizedState,s=s===null?gl(a):{baseLanes:s.baseLanes|a,cachePool:null,transitions:s.transitions},i.memoizedState=s,i.childLanes=e.childLanes&~a,t.memoizedState=ml,n}return i=e.child,e=i.sibling,n=sa(i,{mode:"visible",children:n.children}),!(t.mode&1)&&(n.lanes=a),n.return=t,n.sibling=null,e!==null&&(a=t.deletions,a===null?(t.deletions=[e],t.flags|=16):a.push(e)),t.child=n,t.memoizedState=null,n}function bd(e,t){return t=wr({mode:"visible",children:t},e.mode,0,null),t.return=e,e.child=t}function ni(e,t,a,n){return n!==null&&rd(n),An(t,e.child,null,a),e=bd(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function nk(e,t,a,n,o,i,s){if(a)return t.flags&256?(t.flags&=-257,n=cs(Error(N(422))),ni(e,t,s,n)):t.memoizedState!==null?(t.child=e.child,t.flags|=128,null):(i=n.fallback,o=t.mode,n=wr({mode:"visible",children:n.children},o,0,null),i=za(i,o,s,null),i.flags|=2,n.return=t,i.return=t,n.sibling=i,t.child=n,t.mode&1&&An(t,e.child,null,s),t.child.memoizedState=gl(s),t.memoizedState=ml,i);if(!(t.mode&1))return ni(e,t,s,null);if(o.data==="$!"){if(n=o.nextSibling&&o.nextSibling.dataset,n)var l=n.dgst;return n=l,i=Error(N(419)),n=cs(i,n,void 0),ni(e,t,s,n)}if(l=(s&e.childLanes)!==0,Fe||l){if(n=Ie,n!==null){switch(s&-s){case 4:o=2;break;case 16:o=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:o=32;break;case 536870912:o=268435456;break;default:o=0}o=o&(n.suspendedLanes|s)?0:o,o!==0&&o!==i.retryLane&&(i.retryLane=o,Et(e,o),pt(n,e,o,-1))}return Id(),n=cs(Error(N(421))),ni(e,t,s,n)}return o.data==="$?"?(t.flags|=128,t.child=e.child,t=fk.bind(null,e),o._reactRetry=t,null):(e=i.treeContext,Ze=na(o.nextSibling),Qe=t,ce=!0,ct=null,e!==null&&(tt[at++]=Tt,tt[at++]=jt,tt[at++]=Ta,Tt=e.id,jt=e.overflow,Ta=t),t=bd(t,n.children),t.flags|=4096,t)}function Qc(e,t,a){e.lanes|=t;var n=e.alternate;n!==null&&(n.lanes|=t),sl(e.return,t,a)}function us(e,t,a,n,o){var i=e.memoizedState;i===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:n,tail:a,tailMode:o}:(i.isBackwards=t,i.rendering=null,i.renderingStartTime=0,i.last=n,i.tail=a,i.tailMode=o)}function Xm(e,t,a){var n=t.pendingProps,o=n.revealOrder,i=n.tail;if(De(e,t,n.children,a),n=ue.current,n&2)n=n&1|2,t.flags|=128;else{if(e!==null&&e.flags&128)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&Qc(e,a,t);else if(e.tag===19)Qc(e,a,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}n&=1}if(re(ue,n),!(t.mode&1))t.memoizedState=null;else switch(o){case"forwards":for(a=t.child,o=null;a!==null;)e=a.alternate,e!==null&&ar(e)===null&&(o=a),a=a.sibling;a=o,a===null?(o=t.child,t.child=null):(o=a.sibling,a.sibling=null),us(t,!1,o,a,i);break;case"backwards":for(a=null,o=t.child,t.child=null;o!==null;){if(e=o.alternate,e!==null&&ar(e)===null){t.child=o;break}e=o.sibling,o.sibling=a,a=o,o=e}us(t,!0,a,null,i);break;case"together":us(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Ri(e,t){!(t.mode&1)&&e!==null&&(e.alternate=null,t.alternate=null,t.flags|=2)}function Ot(e,t,a){if(e!==null&&(t.dependencies=e.dependencies),Ma|=t.lanes,!(a&t.childLanes))return null;if(e!==null&&t.child!==e.child)throw Error(N(153));if(t.child!==null){for(e=t.child,a=sa(e,e.pendingProps),t.child=a,a.return=t;e.sibling!==null;)e=e.sibling,a=a.sibling=sa(e,e.pendingProps),a.return=t;a.sibling=null}return t.child}function ok(e,t,a){switch(t.tag){case 3:Qm(t),Pn();break;case 5:xm(t);break;case 1:qe(t.type)&&Qi(t);break;case 4:pd(t,t.stateNode.containerInfo);break;case 10:var n=t.type._context,o=t.memoizedProps.value;re(Ji,n._currentValue),n._currentValue=o;break;case 13:if(n=t.memoizedState,n!==null)return n.dehydrated!==null?(re(ue,ue.current&1),t.flags|=128,null):a&t.child.childLanes?Ym(e,t,a):(re(ue,ue.current&1),e=Ot(e,t,a),e!==null?e.sibling:null);re(ue,ue.current&1);break;case 19:if(n=(a&t.childLanes)!==0,e.flags&128){if(n)return Xm(e,t,a);t.flags|=128}if(o=t.memoizedState,o!==null&&(o.rendering=null,o.tail=null,o.lastEffect=null),re(ue,ue.current),n)break;return null;case 22:case 23:return t.lanes=0,Wm(e,t,a)}return Ot(e,t,a)}var Jm,hl,eg,tg;Jm=function(e,t){for(var a=t.child;a!==null;){if(a.tag===5||a.tag===6)e.appendChild(a.stateNode);else if(a.tag!==4&&a.child!==null){a.child.return=a,a=a.child;continue}if(a===t)break;for(;a.sibling===null;){if(a.return===null||a.return===t)return;a=a.return}a.sibling.return=a.return,a=a.sibling}};hl=function(){};eg=function(e,t,a,n){var o=e.memoizedProps;if(o!==n){e=t.stateNode,Ca(Ct.current);var i=null;switch(a){case"input":o=Os(e,o),n=Os(e,n),i=[];break;case"select":o=ge({},o,{value:void 0}),n=ge({},n,{value:void 0}),i=[];break;case"textarea":o=Hs(e,o),n=Hs(e,n),i=[];break;default:typeof o.onClick!="function"&&typeof n.onClick=="function"&&(e.onclick=Wi)}Bs(a,n);var s;a=null;for(c in o)if(!n.hasOwnProperty(c)&&o.hasOwnProperty(c)&&o[c]!=null)if(c==="style"){var l=o[c];for(s in l)l.hasOwnProperty(s)&&(a||(a={}),a[s]="")}else c!=="dangerouslySetInnerHTML"&&c!=="children"&&c!=="suppressContentEditableWarning"&&c!=="suppressHydrationWarning"&&c!=="autoFocus"&&(uo.hasOwnProperty(c)?i||(i=[]):(i=i||[]).push(c,null));for(c in n){var d=n[c];if(l=o?.[c],n.hasOwnProperty(c)&&d!==l&&(d!=null||l!=null))if(c==="style")if(l){for(s in l)!l.hasOwnProperty(s)||d&&d.hasOwnProperty(s)||(a||(a={}),a[s]="");for(s in d)d.hasOwnProperty(s)&&l[s]!==d[s]&&(a||(a={}),a[s]=d[s])}else a||(i||(i=[]),i.push(c,a)),a=d;else c==="dangerouslySetInnerHTML"?(d=d?d.__html:void 0,l=l?l.__html:void 0,d!=null&&l!==d&&(i=i||[]).push(c,d)):c==="children"?typeof d!="string"&&typeof d!="number"||(i=i||[]).push(c,""+d):c!=="suppressContentEditableWarning"&&c!=="suppressHydrationWarning"&&(uo.hasOwnProperty(c)?(d!=null&&c==="onScroll"&&se("scroll",e),i||l===d||(i=[])):(i=i||[]).push(c,d))}a&&(i=i||[]).push("style",a);var c=i;(t.updateQueue=c)&&(t.flags|=4)}};tg=function(e,t,a,n){a!==n&&(t.flags|=4)};function Bn(e,t){if(!ce)switch(e.tailMode){case"hidden":t=e.tail;for(var a=null;t!==null;)t.alternate!==null&&(a=t),t=t.sibling;a===null?e.tail=null:a.sibling=null;break;case"collapsed":a=e.tail;for(var n=null;a!==null;)a.alternate!==null&&(n=a),a=a.sibling;n===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:n.sibling=null}}function Me(e){var t=e.alternate!==null&&e.alternate.child===e.child,a=0,n=0;if(t)for(var o=e.child;o!==null;)a|=o.lanes|o.childLanes,n|=o.subtreeFlags&14680064,n|=o.flags&14680064,o.return=e,o=o.sibling;else for(o=e.child;o!==null;)a|=o.lanes|o.childLanes,n|=o.subtreeFlags,n|=o.flags,o.return=e,o=o.sibling;return e.subtreeFlags|=n,e.childLanes=a,t}function ik(e,t,a){var n=t.pendingProps;switch(id(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Me(t),null;case 1:return qe(t.type)&&Zi(),Me(t),null;case 3:return n=t.stateNode,Cn(),de(Ve),de(Re),gd(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),(e===null||e.child===null)&&(ti(t)?t.flags|=4:e===null||e.memoizedState.isDehydrated&&!(t.flags&256)||(t.flags|=1024,ct!==null&&(Cl(ct),ct=null))),hl(e,t),Me(t),null;case 5:md(t);var o=Ca(Co.current);if(a=t.type,e!==null&&t.stateNode!=null)eg(e,t,a,n,o),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!n){if(t.stateNode===null)throw Error(N(166));return Me(t),null}if(e=Ca(Ct.current),ti(t)){n=t.stateNode,a=t.type;var i=t.memoizedProps;switch(n[yt]=t,n[Po]=i,e=(t.mode&1)!==0,a){case"dialog":se("cancel",n),se("close",n);break;case"iframe":case"object":case"embed":se("load",n);break;case"video":case"audio":for(o=0;o<Xn.length;o++)se(Xn[o],n);break;case"source":se("error",n);break;case"img":case"image":case"link":se("error",n),se("load",n);break;case"details":se("toggle",n);break;case"input":ic(n,i),se("invalid",n);break;case"select":n._wrapperState={wasMultiple:!!i.multiple},se("invalid",n);break;case"textarea":sc(n,i),se("invalid",n)}Bs(a,i),o=null;for(var s in i)if(i.hasOwnProperty(s)){var l=i[s];s==="children"?typeof l=="string"?n.textContent!==l&&(i.suppressHydrationWarning!==!0&&ei(n.textContent,l,e),o=["children",l]):typeof l=="number"&&n.textContent!==""+l&&(i.suppressHydrationWarning!==!0&&ei(n.textContent,l,e),o=["children",""+l]):uo.hasOwnProperty(s)&&l!=null&&s==="onScroll"&&se("scroll",n)}switch(a){case"input":_o(n),rc(n,i,!0);break;case"textarea":_o(n),lc(n);break;case"select":case"option":break;default:typeof i.onClick=="function"&&(n.onclick=Wi)}n=o,t.updateQueue=n,n!==null&&(t.flags|=4)}else{s=o.nodeType===9?o:o.ownerDocument,e==="http://www.w3.org/1999/xhtml"&&(e=Tp(a)),e==="http://www.w3.org/1999/xhtml"?a==="script"?(e=s.createElement("div"),e.innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):typeof n.is=="string"?e=s.createElement(a,{is:n.is}):(e=s.createElement(a),a==="select"&&(s=e,n.multiple?s.multiple=!0:n.size&&(s.size=n.size))):e=s.createElementNS(e,a),e[yt]=t,e[Po]=n,Jm(e,t,!1,!1),t.stateNode=e;e:{switch(s=Vs(a,n),a){case"dialog":se("cancel",e),se("close",e),o=n;break;case"iframe":case"object":case"embed":se("load",e),o=n;break;case"video":case"audio":for(o=0;o<Xn.length;o++)se(Xn[o],e);o=n;break;case"source":se("error",e),o=n;break;case"img":case"image":case"link":se("error",e),se("load",e),o=n;break;case"details":se("toggle",e),o=n;break;case"input":ic(e,n),o=Os(e,n),se("invalid",e);break;case"option":o=n;break;case"select":e._wrapperState={wasMultiple:!!n.multiple},o=ge({},n,{value:void 0}),se("invalid",e);break;case"textarea":sc(e,n),o=Hs(e,n),se("invalid",e);break;default:o=n}Bs(a,o),l=o;for(i in l)if(l.hasOwnProperty(i)){var d=l[i];i==="style"?Np(e,d):i==="dangerouslySetInnerHTML"?(d=d?d.__html:void 0,d!=null&&jp(e,d)):i==="children"?typeof d=="string"?(a!=="textarea"||d!=="")&&po(e,d):typeof d=="number"&&po(e,""+d):i!=="suppressContentEditableWarning"&&i!=="suppressHydrationWarning"&&i!=="autoFocus"&&(uo.hasOwnProperty(i)?d!=null&&i==="onScroll"&&se("scroll",e):d!=null&&ql(e,i,d,s))}switch(a){case"input":_o(e),rc(e,n,!1);break;case"textarea":_o(e),lc(e);break;case"option":n.value!=null&&e.setAttribute("value",""+da(n.value));break;case"select":e.multiple=!!n.multiple,i=n.value,i!=null?un(e,!!n.multiple,i,!1):n.defaultValue!=null&&un(e,!!n.multiple,n.defaultValue,!0);break;default:typeof o.onClick=="function"&&(e.onclick=Wi)}switch(a){case"button":case"input":case"select":case"textarea":n=!!n.autoFocus;break e;case"img":n=!0;break e;default:n=!1}}n&&(t.flags|=4)}t.ref!==null&&(t.flags|=512,t.flags|=2097152)}return Me(t),null;case 6:if(e&&t.stateNode!=null)tg(e,t,e.memoizedProps,n);else{if(typeof n!="string"&&t.stateNode===null)throw Error(N(166));if(a=Ca(Co.current),Ca(Ct.current),ti(t)){if(n=t.stateNode,a=t.memoizedProps,n[yt]=t,(i=n.nodeValue!==a)&&(e=Qe,e!==null))switch(e.tag){case 3:ei(n.nodeValue,a,(e.mode&1)!==0);break;case 5:e.memoizedProps.suppressHydrationWarning!==!0&&ei(n.nodeValue,a,(e.mode&1)!==0)}i&&(t.flags|=4)}else n=(a.nodeType===9?a:a.ownerDocument).createTextNode(n),n[yt]=t,t.stateNode=n}return Me(t),null;case 13:if(de(ue),n=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(ce&&Ze!==null&&t.mode&1&&!(t.flags&128))ym(),Pn(),t.flags|=98560,i=!1;else if(i=ti(t),n!==null&&n.dehydrated!==null){if(e===null){if(!i)throw Error(N(318));if(i=t.memoizedState,i=i!==null?i.dehydrated:null,!i)throw Error(N(317));i[yt]=t}else Pn(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Me(t),i=!1}else ct!==null&&(Cl(ct),ct=null),i=!0;if(!i)return t.flags&65536?t:null}return t.flags&128?(t.lanes=a,t):(n=n!==null,n!==(e!==null&&e.memoizedState!==null)&&n&&(t.child.flags|=8192,t.mode&1&&(e===null||ue.current&1?Ce===0&&(Ce=3):Id())),t.updateQueue!==null&&(t.flags|=4),Me(t),null);case 4:return Cn(),hl(e,t),e===null&&yo(t.stateNode.containerInfo),Me(t),null;case 10:return dd(t.type._context),Me(t),null;case 17:return qe(t.type)&&Zi(),Me(t),null;case 19:if(de(ue),i=t.memoizedState,i===null)return Me(t),null;if(n=(t.flags&128)!==0,s=i.rendering,s===null)if(n)Bn(i,!1);else{if(Ce!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(s=ar(e),s!==null){for(t.flags|=128,Bn(i,!1),n=s.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),t.subtreeFlags=0,n=a,a=t.child;a!==null;)i=a,e=n,i.flags&=14680066,s=i.alternate,s===null?(i.childLanes=0,i.lanes=e,i.child=null,i.subtreeFlags=0,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=s.childLanes,i.lanes=s.lanes,i.child=s.child,i.subtreeFlags=0,i.deletions=null,i.memoizedProps=s.memoizedProps,i.memoizedState=s.memoizedState,i.updateQueue=s.updateQueue,i.type=s.type,e=s.dependencies,i.dependencies=e===null?null:{lanes:e.lanes,firstContext:e.firstContext}),a=a.sibling;return re(ue,ue.current&1|2),t.child}e=e.sibling}i.tail!==null&&ke()>zn&&(t.flags|=128,n=!0,Bn(i,!1),t.lanes=4194304)}else{if(!n)if(e=ar(s),e!==null){if(t.flags|=128,n=!0,a=e.updateQueue,a!==null&&(t.updateQueue=a,t.flags|=4),Bn(i,!0),i.tail===null&&i.tailMode==="hidden"&&!s.alternate&&!ce)return Me(t),null}else 2*ke()-i.renderingStartTime>zn&&a!==1073741824&&(t.flags|=128,n=!0,Bn(i,!1),t.lanes=4194304);i.isBackwards?(s.sibling=t.child,t.child=s):(a=i.last,a!==null?a.sibling=s:t.child=s,i.last=s)}return i.tail!==null?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=ke(),t.sibling=null,a=ue.current,re(ue,n?a&1|2:a&1),t):(Me(t),null);case 22:case 23:return zd(),n=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==n&&(t.flags|=8192),n&&t.mode&1?We&1073741824&&(Me(t),t.subtreeFlags&6&&(t.flags|=8192)):Me(t),null;case 24:return null;case 25:return null}throw Error(N(156,t.tag))}function rk(e,t){switch(id(t),t.tag){case 1:return qe(t.type)&&Zi(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Cn(),de(Ve),de(Re),gd(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return md(t),null;case 13:if(de(ue),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(N(340));Pn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return de(ue),null;case 4:return Cn(),null;case 10:return dd(t.type._context),null;case 22:case 23:return zd(),null;case 24:return null;default:return null}}var oi=!1,Ne=!1,sk=typeof WeakSet=="function"?WeakSet:Set,O=null;function dn(e,t){var a=e.ref;if(a!==null)if(typeof a=="function")try{a(null)}catch(n){fe(e,t,n)}else a.current=null}function fl(e,t,a){try{a()}catch(n){fe(e,t,n)}}var Yc=!1;function lk(e,t){if(Js=$i,e=rm(),nd(e)){if("selectionStart"in e)var a={start:e.selectionStart,end:e.selectionEnd};else e:{a=(a=e.ownerDocument)&&a.defaultView||window;var n=a.getSelection&&a.getSelection();if(n&&n.rangeCount!==0){a=n.anchorNode;var o=n.anchorOffset,i=n.focusNode;n=n.focusOffset;try{a.nodeType,i.nodeType}catch{a=null;break e}var s=0,l=-1,d=-1,c=0,u=0,p=e,m=null;t:for(;;){for(var f;p!==a||o!==0&&p.nodeType!==3||(l=s+o),p!==i||n!==0&&p.nodeType!==3||(d=s+n),p.nodeType===3&&(s+=p.nodeValue.length),(f=p.firstChild)!==null;)m=p,p=f;for(;;){if(p===e)break t;if(m===a&&++c===o&&(l=s),m===i&&++u===n&&(d=s),(f=p.nextSibling)!==null)break;p=m,m=p.parentNode}p=f}a=l===-1||d===-1?null:{start:l,end:d}}else a=null}a=a||{start:0,end:0}}else a=null;for(el={focusedElem:e,selectionRange:a},$i=!1,O=t;O!==null;)if(t=O,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,O=e;else for(;O!==null;){t=O;try{var P=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(P!==null){var y=P.memoizedProps,A=P.memoizedState,h=t.stateNode,k=h.getSnapshotBeforeUpdate(t.elementType===t.type?y:lt(t.type,y),A);h.__reactInternalSnapshotBeforeUpdate=k}break;case 3:var v=t.stateNode.containerInfo;v.nodeType===1?v.textContent="":v.nodeType===9&&v.documentElement&&v.removeChild(v.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(N(163))}}catch(b){fe(t,t.return,b)}if(e=t.sibling,e!==null){e.return=t.return,O=e;break}O=t.return}return P=Yc,Yc=!1,P}function ro(e,t,a){var n=t.updateQueue;if(n=n!==null?n.lastEffect:null,n!==null){var o=n=n.next;do{if((o.tag&e)===e){var i=o.destroy;o.destroy=void 0,i!==void 0&&fl(t,a,i)}o=o.next}while(o!==n)}}function Ir(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var a=t=t.next;do{if((a.tag&e)===e){var n=a.create;a.destroy=n()}a=a.next}while(a!==t)}}function vl(e){var t=e.ref;if(t!==null){var a=e.stateNode;switch(e.tag){case 5:e=a;break;default:e=a}typeof t=="function"?t(e):t.current=e}}function ag(e){var t=e.alternate;t!==null&&(e.alternate=null,ag(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[yt],delete t[Po],delete t[nl],delete t[qv],delete t[$v])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function ng(e){return e.tag===5||e.tag===3||e.tag===4}function Xc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||ng(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function kl(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.nodeType===8?a.parentNode.insertBefore(e,t):a.insertBefore(e,t):(a.nodeType===8?(t=a.parentNode,t.insertBefore(e,a)):(t=a,t.appendChild(e)),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=Wi));else if(n!==4&&(e=e.child,e!==null))for(kl(e,t,a),e=e.sibling;e!==null;)kl(e,t,a),e=e.sibling}function yl(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.insertBefore(e,t):a.appendChild(e);else if(n!==4&&(e=e.child,e!==null))for(yl(e,t,a),e=e.sibling;e!==null;)yl(e,t,a),e=e.sibling}var Se=null,dt=!1;function qt(e,t,a){for(a=a.child;a!==null;)og(e,t,a),a=a.sibling}function og(e,t,a){if(At&&typeof At.onCommitFiberUnmount=="function")try{At.onCommitFiberUnmount(kr,a)}catch{}switch(a.tag){case 5:Ne||dn(a,t);case 6:var n=Se,o=dt;Se=null,qt(e,t,a),Se=n,dt=o,Se!==null&&(dt?(e=Se,a=a.stateNode,e.nodeType===8?e.parentNode.removeChild(a):e.removeChild(a)):Se.removeChild(a.stateNode));break;case 18:Se!==null&&(dt?(e=Se,a=a.stateNode,e.nodeType===8?os(e.parentNode,a):e.nodeType===1&&os(e,a),fo(e)):os(Se,a.stateNode));break;case 4:n=Se,o=dt,Se=a.stateNode.containerInfo,dt=!0,qt(e,t,a),Se=n,dt=o;break;case 0:case 11:case 14:case 15:if(!Ne&&(n=a.updateQueue,n!==null&&(n=n.lastEffect,n!==null))){o=n=n.next;do{var i=o,s=i.destroy;i=i.tag,s!==void 0&&(i&2||i&4)&&fl(a,t,s),o=o.next}while(o!==n)}qt(e,t,a);break;case 1:if(!Ne&&(dn(a,t),n=a.stateNode,typeof n.componentWillUnmount=="function"))try{n.props=a.memoizedProps,n.state=a.memoizedState,n.componentWillUnmount()}catch(l){fe(a,t,l)}qt(e,t,a);break;case 21:qt(e,t,a);break;case 22:a.mode&1?(Ne=(n=Ne)||a.memoizedState!==null,qt(e,t,a),Ne=n):qt(e,t,a);break;default:qt(e,t,a)}}function Jc(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var a=e.stateNode;a===null&&(a=e.stateNode=new sk),t.forEach(function(n){var o=vk.bind(null,e,n);a.has(n)||(a.add(n),n.then(o,o))})}}function st(e,t){var a=t.deletions;if(a!==null)for(var n=0;n<a.length;n++){var o=a[n];try{var i=e,s=t,l=s;e:for(;l!==null;){switch(l.tag){case 5:Se=l.stateNode,dt=!1;break e;case 3:Se=l.stateNode.containerInfo,dt=!0;break e;case 4:Se=l.stateNode.containerInfo,dt=!0;break e}l=l.return}if(Se===null)throw Error(N(160));og(i,s,o),Se=null,dt=!1;var d=o.alternate;d!==null&&(d.return=null),o.return=null}catch(c){fe(o,t,c)}}if(t.subtreeFlags&12854)for(t=t.child;t!==null;)ig(t,e),t=t.sibling}function ig(e,t){var a=e.alternate,n=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(st(t,e),ft(e),n&4){try{ro(3,e,e.return),Ir(3,e)}catch(y){fe(e,e.return,y)}try{ro(5,e,e.return)}catch(y){fe(e,e.return,y)}}break;case 1:st(t,e),ft(e),n&512&&a!==null&&dn(a,a.return);break;case 5:if(st(t,e),ft(e),n&512&&a!==null&&dn(a,a.return),e.flags&32){var o=e.stateNode;try{po(o,"")}catch(y){fe(e,e.return,y)}}if(n&4&&(o=e.stateNode,o!=null)){var i=e.memoizedProps,s=a!==null?a.memoizedProps:i,l=e.type,d=e.updateQueue;if(e.updateQueue=null,d!==null)try{l==="input"&&i.type==="radio"&&i.name!=null&&Sp(o,i),Vs(l,s);var c=Vs(l,i);for(s=0;s<d.length;s+=2){var u=d[s],p=d[s+1];u==="style"?Np(o,p):u==="dangerouslySetInnerHTML"?jp(o,p):u==="children"?po(o,p):ql(o,u,p,c)}switch(l){case"input":Ks(o,i);break;case"textarea":wp(o,i);break;case"select":var m=o._wrapperState.wasMultiple;o._wrapperState.wasMultiple=!!i.multiple;var f=i.value;f!=null?un(o,!!i.multiple,f,!1):m!==!!i.multiple&&(i.defaultValue!=null?un(o,!!i.multiple,i.defaultValue,!0):un(o,!!i.multiple,i.multiple?[]:"",!1))}o[Po]=i}catch(y){fe(e,e.return,y)}}break;case 6:if(st(t,e),ft(e),n&4){if(e.stateNode===null)throw Error(N(162));o=e.stateNode,i=e.memoizedProps;try{o.nodeValue=i}catch(y){fe(e,e.return,y)}}break;case 3:if(st(t,e),ft(e),n&4&&a!==null&&a.memoizedState.isDehydrated)try{fo(t.containerInfo)}catch(y){fe(e,e.return,y)}break;case 4:st(t,e),ft(e);break;case 13:st(t,e),ft(e),o=e.child,o.flags&8192&&(i=o.memoizedState!==null,o.stateNode.isHidden=i,!i||o.alternate!==null&&o.alternate.memoizedState!==null||(Cd=ke())),n&4&&Jc(e);break;case 22:if(u=a!==null&&a.memoizedState!==null,e.mode&1?(Ne=(c=Ne)||u,st(t,e),Ne=c):st(t,e),ft(e),n&8192){if(c=e.memoizedState!==null,(e.stateNode.isHidden=c)&&!u&&e.mode&1)for(O=e,u=e.child;u!==null;){for(p=O=u;O!==null;){switch(m=O,f=m.child,m.tag){case 0:case 11:case 14:case 15:ro(4,m,m.return);break;case 1:dn(m,m.return);var P=m.stateNode;if(typeof P.componentWillUnmount=="function"){n=m,a=m.return;try{t=n,P.props=t.memoizedProps,P.state=t.memoizedState,P.componentWillUnmount()}catch(y){fe(n,a,y)}}break;case 5:dn(m,m.return);break;case 22:if(m.memoizedState!==null){tu(p);continue}}f!==null?(f.return=m,O=f):tu(p)}u=u.sibling}e:for(u=null,p=e;;){if(p.tag===5){if(u===null){u=p;try{o=p.stateNode,c?(i=o.style,typeof i.setProperty=="function"?i.setProperty("display","none","important"):i.display="none"):(l=p.stateNode,d=p.memoizedProps.style,s=d!=null&&d.hasOwnProperty("display")?d.display:null,l.style.display=Mp("display",s))}catch(y){fe(e,e.return,y)}}}else if(p.tag===6){if(u===null)try{p.stateNode.nodeValue=c?"":p.memoizedProps}catch(y){fe(e,e.return,y)}}else if((p.tag!==22&&p.tag!==23||p.memoizedState===null||p===e)&&p.child!==null){p.child.return=p,p=p.child;continue}if(p===e)break e;for(;p.sibling===null;){if(p.return===null||p.return===e)break e;u===p&&(u=null),p=p.return}u===p&&(u=null),p.sibling.return=p.return,p=p.sibling}}break;case 19:st(t,e),ft(e),n&4&&Jc(e);break;case 21:break;default:st(t,e),ft(e)}}function ft(e){var t=e.flags;if(t&2){try{e:{for(var a=e.return;a!==null;){if(ng(a)){var n=a;break e}a=a.return}throw Error(N(160))}switch(n.tag){case 5:var o=n.stateNode;n.flags&32&&(po(o,""),n.flags&=-33);var i=Xc(e);yl(e,i,o);break;case 3:case 4:var s=n.stateNode.containerInfo,l=Xc(e);kl(e,l,s);break;default:throw Error(N(161))}}catch(d){fe(e,e.return,d)}e.flags&=-3}t&4096&&(e.flags&=-4097)}function dk(e,t,a){O=e,rg(e)}function rg(e,t,a){for(var n=(e.mode&1)!==0;O!==null;){var o=O,i=o.child;if(o.tag===22&&n){var s=o.memoizedState!==null||oi;if(!s){var l=o.alternate,d=l!==null&&l.memoizedState!==null||Ne;l=oi;var c=Ne;if(oi=s,(Ne=d)&&!c)for(O=o;O!==null;)s=O,d=s.child,s.tag===22&&s.memoizedState!==null?au(o):d!==null?(d.return=s,O=d):au(o);for(;i!==null;)O=i,rg(i),i=i.sibling;O=o,oi=l,Ne=c}eu(e)}else o.subtreeFlags&8772&&i!==null?(i.return=o,O=i):eu(e)}}function eu(e){for(;O!==null;){var t=O;if(t.flags&8772){var a=t.alternate;try{if(t.flags&8772)switch(t.tag){case 0:case 11:case 15:Ne||Ir(5,t);break;case 1:var n=t.stateNode;if(t.flags&4&&!Ne)if(a===null)n.componentDidMount();else{var o=t.elementType===t.type?a.memoizedProps:lt(t.type,a.memoizedProps);n.componentDidUpdate(o,a.memoizedState,n.__reactInternalSnapshotBeforeUpdate)}var i=t.updateQueue;i!==null&&Kc(t,i,n);break;case 3:var s=t.updateQueue;if(s!==null){if(a=null,t.child!==null)switch(t.child.tag){case 5:a=t.child.stateNode;break;case 1:a=t.child.stateNode}Kc(t,s,a)}break;case 5:var l=t.stateNode;if(a===null&&t.flags&4){a=l;var d=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":d.autoFocus&&a.focus();break;case"img":d.src&&(a.src=d.src)}}break;case 6:break;case 4:break;case 12:break;case 13:if(t.memoizedState===null){var c=t.alternate;if(c!==null){var u=c.memoizedState;if(u!==null){var p=u.dehydrated;p!==null&&fo(p)}}}break;case 19:case 17:case 21:case 22:case 23:case 25:break;default:throw Error(N(163))}Ne||t.flags&512&&vl(t)}catch(m){fe(t,t.return,m)}}if(t===e){O=null;break}if(a=t.sibling,a!==null){a.return=t.return,O=a;break}O=t.return}}function tu(e){for(;O!==null;){var t=O;if(t===e){O=null;break}var a=t.sibling;if(a!==null){a.return=t.return,O=a;break}O=t.return}}function au(e){for(;O!==null;){var t=O;try{switch(t.tag){case 0:case 11:case 15:var a=t.return;try{Ir(4,t)}catch(d){fe(t,a,d)}break;case 1:var n=t.stateNode;if(typeof n.componentDidMount=="function"){var o=t.return;try{n.componentDidMount()}catch(d){fe(t,o,d)}}var i=t.return;try{vl(t)}catch(d){fe(t,i,d)}break;case 5:var s=t.return;try{vl(t)}catch(d){fe(t,s,d)}}}catch(d){fe(t,t.return,d)}if(t===e){O=null;break}var l=t.sibling;if(l!==null){l.return=t.return,O=l;break}O=t.return}}var ck=Math.ceil,ir=Ut.ReactCurrentDispatcher,Pd=Ut.ReactCurrentOwner,ot=Ut.ReactCurrentBatchConfig,te=0,Ie=null,be=null,we=0,We=0,cn=pa(0),Ce=0,So=null,Ma=0,Sr=0,Ad=0,so=null,Ue=null,Cd=0,zn=1/0,St=null,rr=!1,bl=null,ia=null,ii=!1,Xt=null,sr=0,lo=0,Pl=null,Di=-1,Ei=0;function Ee(){return te&6?ke():Di!==-1?Di:Di=ke()}function ra(e){return e.mode&1?te&2&&we!==0?we&-we:Gv.transition!==null?(Ei===0&&(Ei=qp()),Ei):(e=oe,e!==0||(e=window.event,e=e===void 0?16:Yp(e.type)),e):1}function pt(e,t,a,n){if(50<lo)throw lo=0,Pl=null,Error(N(185));Do(e,a,n),(!(te&2)||e!==Ie)&&(e===Ie&&(!(te&2)&&(Sr|=a),Ce===4&&Zt(e,we)),$e(e,n),a===1&&te===0&&!(t.mode&1)&&(zn=ke()+500,Cr&&ma()))}function $e(e,t){var a=e.callbackNode;Gf(e,t);var n=qi(e,e===Ie?we:0);if(n===0)a!==null&&uc(a),e.callbackNode=null,e.callbackPriority=0;else if(t=n&-n,e.callbackPriority!==t){if(a!=null&&uc(a),t===1)e.tag===0?_v(nu.bind(null,e)):fm(nu.bind(null,e)),Bv(function(){!(te&6)&&ma()}),a=null;else{switch($p(n)){case 1:a=Zl;break;case 4:a=Bp;break;case 16:a=Vi;break;case 536870912:a=Vp;break;default:a=Vi}a=gg(a,sg.bind(null,e))}e.callbackPriority=t,e.callbackNode=a}}function sg(e,t){if(Di=-1,Ei=0,te&6)throw Error(N(327));var a=e.callbackNode;if(fn()&&e.callbackNode!==a)return null;var n=qi(e,e===Ie?we:0);if(n===0)return null;if(n&30||n&e.expiredLanes||t)t=lr(e,n);else{t=n;var o=te;te|=2;var i=dg();(Ie!==e||we!==t)&&(St=null,zn=ke()+500,xa(e,t));do try{mk();break}catch(l){lg(e,l)}while(!0);ld(),ir.current=i,te=o,be!==null?t=0:(Ie=null,we=0,t=Ce)}if(t!==0){if(t===2&&(o=Ws(e),o!==0&&(n=o,t=Al(e,o))),t===1)throw a=So,xa(e,0),Zt(e,n),$e(e,ke()),a;if(t===6)Zt(e,n);else{if(o=e.current.alternate,!(n&30)&&!uk(o)&&(t=lr(e,n),t===2&&(i=Ws(e),i!==0&&(n=i,t=Al(e,i))),t===1))throw a=So,xa(e,0),Zt(e,n),$e(e,ke()),a;switch(e.finishedWork=o,e.finishedLanes=n,t){case 0:case 1:throw Error(N(345));case 2:ba(e,Ue,St);break;case 3:if(Zt(e,n),(n&130023424)===n&&(t=Cd+500-ke(),10<t)){if(qi(e,0)!==0)break;if(o=e.suspendedLanes,(o&n)!==n){Ee(),e.pingedLanes|=e.suspendedLanes&o;break}e.timeoutHandle=al(ba.bind(null,e,Ue,St),t);break}ba(e,Ue,St);break;case 4:if(Zt(e,n),(n&4194240)===n)break;for(t=e.eventTimes,o=-1;0<n;){var s=31-ut(n);i=1<<s,s=t[s],s>o&&(o=s),n&=~i}if(n=o,n=ke()-n,n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*ck(n/1960))-n,10<n){e.timeoutHandle=al(ba.bind(null,e,Ue,St),n);break}ba(e,Ue,St);break;case 5:ba(e,Ue,St);break;default:throw Error(N(329))}}}return $e(e,ke()),e.callbackNode===a?sg.bind(null,e):null}function Al(e,t){var a=so;return e.current.memoizedState.isDehydrated&&(xa(e,t).flags|=256),e=lr(e,t),e!==2&&(t=Ue,Ue=a,t!==null&&Cl(t)),e}function Cl(e){Ue===null?Ue=e:Ue.push.apply(Ue,e)}function uk(e){for(var t=e;;){if(t.flags&16384){var a=t.updateQueue;if(a!==null&&(a=a.stores,a!==null))for(var n=0;n<a.length;n++){var o=a[n],i=o.getSnapshot;o=o.value;try{if(!mt(i(),o))return!1}catch{return!1}}}if(a=t.child,t.subtreeFlags&16384&&a!==null)a.return=t,t=a;else{if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}function Zt(e,t){for(t&=~Ad,t&=~Sr,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var a=31-ut(t),n=1<<a;e[a]=-1,t&=~n}}function nu(e){if(te&6)throw Error(N(327));fn();var t=qi(e,0);if(!(t&1))return $e(e,ke()),null;var a=lr(e,t);if(e.tag!==0&&a===2){var n=Ws(e);n!==0&&(t=n,a=Al(e,n))}if(a===1)throw a=So,xa(e,0),Zt(e,t),$e(e,ke()),a;if(a===6)throw Error(N(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,ba(e,Ue,St),$e(e,ke()),null}function xd(e,t){var a=te;te|=1;try{return e(t)}finally{te=a,te===0&&(zn=ke()+500,Cr&&ma())}}function Na(e){Xt!==null&&Xt.tag===0&&!(te&6)&&fn();var t=te;te|=1;var a=ot.transition,n=oe;try{if(ot.transition=null,oe=1,e)return e()}finally{oe=n,ot.transition=a,te=t,!(te&6)&&ma()}}function zd(){We=cn.current,de(cn)}function xa(e,t){e.finishedWork=null,e.finishedLanes=0;var a=e.timeoutHandle;if(a!==-1&&(e.timeoutHandle=-1,Fv(a)),be!==null)for(a=be.return;a!==null;){var n=a;switch(id(n),n.tag){case 1:n=n.type.childContextTypes,n!=null&&Zi();break;case 3:Cn(),de(Ve),de(Re),gd();break;case 5:md(n);break;case 4:Cn();break;case 13:de(ue);break;case 19:de(ue);break;case 10:dd(n.type._context);break;case 22:case 23:zd()}a=a.return}if(Ie=e,be=e=sa(e.current,null),we=We=t,Ce=0,So=null,Ad=Sr=Ma=0,Ue=so=null,Aa!==null){for(t=0;t<Aa.length;t++)if(a=Aa[t],n=a.interleaved,n!==null){a.interleaved=null;var o=n.next,i=a.pending;if(i!==null){var s=i.next;i.next=o,n.next=s}a.pending=n}Aa=null}return e}function lg(e,t){do{var a=be;try{if(ld(),Ni.current=or,nr){for(var n=pe.memoizedState;n!==null;){var o=n.queue;o!==null&&(o.pending=null),n=n.next}nr=!1}if(ja=0,ze=Ae=pe=null,io=!1,xo=0,Pd.current=null,a===null||a.return===null){Ce=1,So=t,be=null;break}e:{var i=e,s=a.return,l=a,d=t;if(t=we,l.flags|=32768,d!==null&&typeof d=="object"&&typeof d.then=="function"){var c=d,u=l,p=u.tag;if(!(u.mode&1)&&(p===0||p===11||p===15)){var m=u.alternate;m?(u.updateQueue=m.updateQueue,u.memoizedState=m.memoizedState,u.lanes=m.lanes):(u.updateQueue=null,u.memoizedState=null)}var f=qc(s);if(f!==null){f.flags&=-257,$c(f,s,l,i,t),f.mode&1&&Vc(i,c,t),t=f,d=c;var P=t.updateQueue;if(P===null){var y=new Set;y.add(d),t.updateQueue=y}else P.add(d);break e}else{if(!(t&1)){Vc(i,c,t),Id();break e}d=Error(N(426))}}else if(ce&&l.mode&1){var A=qc(s);if(A!==null){!(A.flags&65536)&&(A.flags|=256),$c(A,s,l,i,t),rd(xn(d,l));break e}}i=d=xn(d,l),Ce!==4&&(Ce=2),so===null?so=[i]:so.push(i),i=s;do{switch(i.tag){case 3:i.flags|=65536,t&=-t,i.lanes|=t;var h=$m(i,d,t);Oc(i,h);break e;case 1:l=d;var k=i.type,v=i.stateNode;if(!(i.flags&128)&&(typeof k.getDerivedStateFromError=="function"||v!==null&&typeof v.componentDidCatch=="function"&&(ia===null||!ia.has(v)))){i.flags|=65536,t&=-t,i.lanes|=t;var b=_m(i,l,t);Oc(i,b);break e}}i=i.return}while(i!==null)}ug(a)}catch(z){t=z,be===a&&a!==null&&(be=a=a.return);continue}break}while(!0)}function dg(){var e=ir.current;return ir.current=or,e===null?or:e}function Id(){(Ce===0||Ce===3||Ce===2)&&(Ce=4),Ie===null||!(Ma&268435455)&&!(Sr&268435455)||Zt(Ie,we)}function lr(e,t){var a=te;te|=2;var n=dg();(Ie!==e||we!==t)&&(St=null,xa(e,t));do try{pk();break}catch(o){lg(e,o)}while(!0);if(ld(),te=a,ir.current=n,be!==null)throw Error(N(261));return Ie=null,we=0,Ce}function pk(){for(;be!==null;)cg(be)}function mk(){for(;be!==null&&!Kf();)cg(be)}function cg(e){var t=mg(e.alternate,e,We);e.memoizedProps=e.pendingProps,t===null?ug(e):be=t,Pd.current=null}function ug(e){var t=e;do{var a=t.alternate;if(e=t.return,t.flags&32768){if(a=rk(a,t),a!==null){a.flags&=32767,be=a;return}if(e!==null)e.flags|=32768,e.subtreeFlags=0,e.deletions=null;else{Ce=6,be=null;return}}else if(a=ik(a,t,We),a!==null){be=a;return}if(t=t.sibling,t!==null){be=t;return}be=t=e}while(t!==null);Ce===0&&(Ce=5)}function ba(e,t,a){var n=oe,o=ot.transition;try{ot.transition=null,oe=1,gk(e,t,a,n)}finally{ot.transition=o,oe=n}return null}function gk(e,t,a,n){do fn();while(Xt!==null);if(te&6)throw Error(N(327));a=e.finishedWork;var o=e.finishedLanes;if(a===null)return null;if(e.finishedWork=null,e.finishedLanes=0,a===e.current)throw Error(N(177));e.callbackNode=null,e.callbackPriority=0;var i=a.lanes|a.childLanes;if(Wf(e,i),e===Ie&&(be=Ie=null,we=0),!(a.subtreeFlags&2064)&&!(a.flags&2064)||ii||(ii=!0,gg(Vi,function(){return fn(),null})),i=(a.flags&15990)!==0,a.subtreeFlags&15990||i){i=ot.transition,ot.transition=null;var s=oe;oe=1;var l=te;te|=4,Pd.current=null,lk(e,a),ig(a,e),Rv(el),$i=!!Js,el=Js=null,e.current=a,dk(a),Uf(),te=l,oe=s,ot.transition=i}else e.current=a;if(ii&&(ii=!1,Xt=e,sr=o),i=e.pendingLanes,i===0&&(ia=null),Bf(a.stateNode),$e(e,ke()),t!==null)for(n=e.onRecoverableError,a=0;a<t.length;a++)o=t[a],n(o.value,{componentStack:o.stack,digest:o.digest});if(rr)throw rr=!1,e=bl,bl=null,e;return sr&1&&e.tag!==0&&fn(),i=e.pendingLanes,i&1?e===Pl?lo++:(lo=0,Pl=e):lo=0,ma(),null}function fn(){if(Xt!==null){var e=$p(sr),t=ot.transition,a=oe;try{if(ot.transition=null,oe=16>e?16:e,Xt===null)var n=!1;else{if(e=Xt,Xt=null,sr=0,te&6)throw Error(N(331));var o=te;for(te|=4,O=e.current;O!==null;){var i=O,s=i.child;if(O.flags&16){var l=i.deletions;if(l!==null){for(var d=0;d<l.length;d++){var c=l[d];for(O=c;O!==null;){var u=O;switch(u.tag){case 0:case 11:case 15:ro(8,u,i)}var p=u.child;if(p!==null)p.return=u,O=p;else for(;O!==null;){u=O;var m=u.sibling,f=u.return;if(ag(u),u===c){O=null;break}if(m!==null){m.return=f,O=m;break}O=f}}}var P=i.alternate;if(P!==null){var y=P.child;if(y!==null){P.child=null;do{var A=y.sibling;y.sibling=null,y=A}while(y!==null)}}O=i}}if(i.subtreeFlags&2064&&s!==null)s.return=i,O=s;else e:for(;O!==null;){if(i=O,i.flags&2048)switch(i.tag){case 0:case 11:case 15:ro(9,i,i.return)}var h=i.sibling;if(h!==null){h.return=i.return,O=h;break e}O=i.return}}var k=e.current;for(O=k;O!==null;){s=O;var v=s.child;if(s.subtreeFlags&2064&&v!==null)v.return=s,O=v;else e:for(s=k;O!==null;){if(l=O,l.flags&2048)try{switch(l.tag){case 0:case 11:case 15:Ir(9,l)}}catch(z){fe(l,l.return,z)}if(l===s){O=null;break e}var b=l.sibling;if(b!==null){b.return=l.return,O=b;break e}O=l.return}}if(te=o,ma(),At&&typeof At.onPostCommitFiberRoot=="function")try{At.onPostCommitFiberRoot(kr,e)}catch{}n=!0}return n}finally{oe=a,ot.transition=t}}return!1}function ou(e,t,a){t=xn(a,t),t=$m(e,t,1),e=oa(e,t,1),t=Ee(),e!==null&&(Do(e,1,t),$e(e,t))}function fe(e,t,a){if(e.tag===3)ou(e,e,a);else for(;t!==null;){if(t.tag===3){ou(t,e,a);break}else if(t.tag===1){var n=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof n.componentDidCatch=="function"&&(ia===null||!ia.has(n))){e=xn(a,e),e=_m(t,e,1),t=oa(t,e,1),e=Ee(),t!==null&&(Do(t,1,e),$e(t,e));break}}t=t.return}}function hk(e,t,a){var n=e.pingCache;n!==null&&n.delete(t),t=Ee(),e.pingedLanes|=e.suspendedLanes&a,Ie===e&&(we&a)===a&&(Ce===4||Ce===3&&(we&130023424)===we&&500>ke()-Cd?xa(e,0):Ad|=a),$e(e,t)}function pg(e,t){t===0&&(e.mode&1?(t=Zo,Zo<<=1,!(Zo&130023424)&&(Zo=4194304)):t=1);var a=Ee();e=Et(e,t),e!==null&&(Do(e,t,a),$e(e,a))}function fk(e){var t=e.memoizedState,a=0;t!==null&&(a=t.retryLane),pg(e,a)}function vk(e,t){var a=0;switch(e.tag){case 13:var n=e.stateNode,o=e.memoizedState;o!==null&&(a=o.retryLane);break;case 19:n=e.stateNode;break;default:throw Error(N(314))}n!==null&&n.delete(t),pg(e,a)}var mg;mg=function(e,t,a){if(e!==null)if(e.memoizedProps!==t.pendingProps||Ve.current)Fe=!0;else{if(!(e.lanes&a)&&!(t.flags&128))return Fe=!1,ok(e,t,a);Fe=!!(e.flags&131072)}else Fe=!1,ce&&t.flags&1048576&&vm(t,Xi,t.index);switch(t.lanes=0,t.tag){case 2:var n=t.type;Ri(e,t),e=t.pendingProps;var o=bn(t,Re.current);hn(t,a),o=fd(null,t,n,e,o,a);var i=vd();return t.flags|=1,typeof o=="object"&&o!==null&&typeof o.render=="function"&&o.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,qe(n)?(i=!0,Qi(t)):i=!1,t.memoizedState=o.state!==null&&o.state!==void 0?o.state:null,ud(t),o.updater=zr,t.stateNode=o,o._reactInternals=t,dl(t,n,e,a),t=pl(null,t,n,!0,i,a)):(t.tag=0,ce&&i&&od(t),De(null,t,o,a),t=t.child),t;case 16:n=t.elementType;e:{switch(Ri(e,t),e=t.pendingProps,o=n._init,n=o(n._payload),t.type=n,o=t.tag=yk(n),e=lt(n,e),o){case 0:t=ul(null,t,n,e,a);break e;case 1:t=Wc(null,t,n,e,a);break e;case 11:t=_c(null,t,n,e,a);break e;case 14:t=Gc(null,t,n,lt(n.type,e),a);break e}throw Error(N(306,n,""))}return t;case 0:return n=t.type,o=t.pendingProps,o=t.elementType===n?o:lt(n,o),ul(e,t,n,o,a);case 1:return n=t.type,o=t.pendingProps,o=t.elementType===n?o:lt(n,o),Wc(e,t,n,o,a);case 3:e:{if(Qm(t),e===null)throw Error(N(387));n=t.pendingProps,i=t.memoizedState,o=i.element,Cm(e,t),tr(t,n,null,a);var s=t.memoizedState;if(n=s.element,i.isDehydrated)if(i={element:n,isDehydrated:!1,cache:s.cache,pendingSuspenseBoundaries:s.pendingSuspenseBoundaries,transitions:s.transitions},t.updateQueue.baseState=i,t.memoizedState=i,t.flags&256){o=xn(Error(N(423)),t),t=Zc(e,t,n,a,o);break e}else if(n!==o){o=xn(Error(N(424)),t),t=Zc(e,t,n,a,o);break e}else for(Ze=na(t.stateNode.containerInfo.firstChild),Qe=t,ce=!0,ct=null,a=Pm(t,null,n,a),t.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling;else{if(Pn(),n===o){t=Ot(e,t,a);break e}De(e,t,n,a)}t=t.child}return t;case 5:return xm(t),e===null&&rl(t),n=t.type,o=t.pendingProps,i=e!==null?e.memoizedProps:null,s=o.children,tl(n,o)?s=null:i!==null&&tl(n,i)&&(t.flags|=32),Zm(e,t),De(e,t,s,a),t.child;case 6:return e===null&&rl(t),null;case 13:return Ym(e,t,a);case 4:return pd(t,t.stateNode.containerInfo),n=t.pendingProps,e===null?t.child=An(t,null,n,a):De(e,t,n,a),t.child;case 11:return n=t.type,o=t.pendingProps,o=t.elementType===n?o:lt(n,o),_c(e,t,n,o,a);case 7:return De(e,t,t.pendingProps,a),t.child;case 8:return De(e,t,t.pendingProps.children,a),t.child;case 12:return De(e,t,t.pendingProps.children,a),t.child;case 10:e:{if(n=t.type._context,o=t.pendingProps,i=t.memoizedProps,s=o.value,re(Ji,n._currentValue),n._currentValue=s,i!==null)if(mt(i.value,s)){if(i.children===o.children&&!Ve.current){t=Ot(e,t,a);break e}}else for(i=t.child,i!==null&&(i.return=t);i!==null;){var l=i.dependencies;if(l!==null){s=i.child;for(var d=l.firstContext;d!==null;){if(d.context===n){if(i.tag===1){d=Nt(-1,a&-a),d.tag=2;var c=i.updateQueue;if(c!==null){c=c.shared;var u=c.pending;u===null?d.next=d:(d.next=u.next,u.next=d),c.pending=d}}i.lanes|=a,d=i.alternate,d!==null&&(d.lanes|=a),sl(i.return,a,t),l.lanes|=a;break}d=d.next}}else if(i.tag===10)s=i.type===t.type?null:i.child;else if(i.tag===18){if(s=i.return,s===null)throw Error(N(341));s.lanes|=a,l=s.alternate,l!==null&&(l.lanes|=a),sl(s,a,t),s=i.sibling}else s=i.child;if(s!==null)s.return=i;else for(s=i;s!==null;){if(s===t){s=null;break}if(i=s.sibling,i!==null){i.return=s.return,s=i;break}s=s.return}i=s}De(e,t,o.children,a),t=t.child}return t;case 9:return o=t.type,n=t.pendingProps.children,hn(t,a),o=it(o),n=n(o),t.flags|=1,De(e,t,n,a),t.child;case 14:return n=t.type,o=lt(n,t.pendingProps),o=lt(n.type,o),Gc(e,t,n,o,a);case 15:return Gm(e,t,t.type,t.pendingProps,a);case 17:return n=t.type,o=t.pendingProps,o=t.elementType===n?o:lt(n,o),Ri(e,t),t.tag=1,qe(n)?(e=!0,Qi(t)):e=!1,hn(t,a),qm(t,n,o),dl(t,n,o,a),pl(null,t,n,!0,e,a);case 19:return Xm(e,t,a);case 22:return Wm(e,t,a)}throw Error(N(156,t.tag))};function gg(e,t){return Fp(e,t)}function kk(e,t,a,n){this.tag=e,this.key=a,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=n,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function nt(e,t,a,n){return new kk(e,t,a,n)}function Sd(e){return e=e.prototype,!(!e||!e.isReactComponent)}function yk(e){if(typeof e=="function")return Sd(e)?1:0;if(e!=null){if(e=e.$$typeof,e===_l)return 11;if(e===Gl)return 14}return 2}function sa(e,t){var a=e.alternate;return a===null?(a=nt(e.tag,t,e.key,e.mode),a.elementType=e.elementType,a.type=e.type,a.stateNode=e.stateNode,a.alternate=e,e.alternate=a):(a.pendingProps=t,a.type=e.type,a.flags=0,a.subtreeFlags=0,a.deletions=null),a.flags=e.flags&14680064,a.childLanes=e.childLanes,a.lanes=e.lanes,a.child=e.child,a.memoizedProps=e.memoizedProps,a.memoizedState=e.memoizedState,a.updateQueue=e.updateQueue,t=e.dependencies,a.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},a.sibling=e.sibling,a.index=e.index,a.ref=e.ref,a}function Oi(e,t,a,n,o,i){var s=2;if(n=e,typeof e=="function")Sd(e)&&(s=1);else if(typeof e=="string")s=5;else e:switch(e){case Ja:return za(a.children,o,i,t);case $l:s=8,o|=8;break;case Ls:return e=nt(12,a,t,o|2),e.elementType=Ls,e.lanes=i,e;case Rs:return e=nt(13,a,t,o),e.elementType=Rs,e.lanes=i,e;case Ds:return e=nt(19,a,t,o),e.elementType=Ds,e.lanes=i,e;case xp:return wr(a,o,i,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Ap:s=10;break e;case Cp:s=9;break e;case _l:s=11;break e;case Gl:s=14;break e;case _t:s=16,n=null;break e}throw Error(N(130,e==null?e:typeof e,""))}return t=nt(s,a,t,o),t.elementType=e,t.type=n,t.lanes=i,t}function za(e,t,a,n){return e=nt(7,e,n,t),e.lanes=a,e}function wr(e,t,a,n){return e=nt(22,e,n,t),e.elementType=xp,e.lanes=a,e.stateNode={isHidden:!1},e}function ps(e,t,a){return e=nt(6,e,null,t),e.lanes=a,e}function ms(e,t,a){return t=nt(4,e.children!==null?e.children:[],e.key,t),t.lanes=a,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function bk(e,t,a,n,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Gr(0),this.expirationTimes=Gr(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Gr(0),this.identifierPrefix=n,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function wd(e,t,a,n,o,i,s,l,d){return e=new bk(e,t,a,l,d),t===1?(t=1,i===!0&&(t|=8)):t=0,i=nt(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:n,isDehydrated:a,cache:null,transitions:null,pendingSuspenseBoundaries:null},ud(i),e}function Pk(e,t,a){var n=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:Xa,key:n==null?null:""+n,children:e,containerInfo:t,implementation:a}}function hg(e){if(!e)return ca;e=e._reactInternals;e:{if(Ka(e)!==e||e.tag!==1)throw Error(N(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(qe(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(t!==null);throw Error(N(171))}if(e.tag===1){var a=e.type;if(qe(a))return hm(e,a,t)}return t}function fg(e,t,a,n,o,i,s,l,d){return e=wd(a,n,!0,e,o,i,s,l,d),e.context=hg(null),a=e.current,n=Ee(),o=ra(a),i=Nt(n,o),i.callback=t??null,oa(a,i,o),e.current.lanes=o,Do(e,o,n),$e(e,n),e}function Tr(e,t,a,n){var o=t.current,i=Ee(),s=ra(o);return a=hg(a),t.context===null?t.context=a:t.pendingContext=a,t=Nt(i,s),t.payload={element:e},n=n===void 0?null:n,n!==null&&(t.callback=n),e=oa(o,t,s),e!==null&&(pt(e,o,s,i),Mi(e,o,s)),s}function dr(e){if(e=e.current,!e.child)return null;switch(e.child.tag){case 5:return e.child.stateNode;default:return e.child.stateNode}}function iu(e,t){if(e=e.memoizedState,e!==null&&e.dehydrated!==null){var a=e.retryLane;e.retryLane=a!==0&&a<t?a:t}}function Td(e,t){iu(e,t),(e=e.alternate)&&iu(e,t)}function Ak(){return null}var vg=typeof reportError=="function"?reportError:function(e){console.error(e)};function jd(e){this._internalRoot=e}jr.prototype.render=jd.prototype.render=function(e){var t=this._internalRoot;if(t===null)throw Error(N(409));Tr(e,t,null,null)};jr.prototype.unmount=jd.prototype.unmount=function(){var e=this._internalRoot;if(e!==null){this._internalRoot=null;var t=e.containerInfo;Na(function(){Tr(null,e,null,null)}),t[Dt]=null}};function jr(e){this._internalRoot=e}jr.prototype.unstable_scheduleHydration=function(e){if(e){var t=Wp();e={blockedOn:null,target:e,priority:t};for(var a=0;a<Wt.length&&t!==0&&t<Wt[a].priority;a++);Wt.splice(a,0,e),a===0&&Qp(e)}};function Md(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function Mr(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11&&(e.nodeType!==8||e.nodeValue!==" react-mount-point-unstable "))}function ru(){}function Ck(e,t,a,n,o){if(o){if(typeof n=="function"){var i=n;n=function(){var c=dr(s);i.call(c)}}var s=fg(t,n,e,0,null,!1,!1,"",ru);return e._reactRootContainer=s,e[Dt]=s.current,yo(e.nodeType===8?e.parentNode:e),Na(),s}for(;o=e.lastChild;)e.removeChild(o);if(typeof n=="function"){var l=n;n=function(){var c=dr(d);l.call(c)}}var d=wd(e,0,!1,null,null,!1,!1,"",ru);return e._reactRootContainer=d,e[Dt]=d.current,yo(e.nodeType===8?e.parentNode:e),Na(function(){Tr(t,d,a,n)}),d}function Nr(e,t,a,n,o){var i=a._reactRootContainer;if(i){var s=i;if(typeof o=="function"){var l=o;o=function(){var d=dr(s);l.call(d)}}Tr(t,s,e,o)}else s=Ck(a,t,e,o,n);return dr(s)}_p=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var a=Yn(t.pendingLanes);a!==0&&(Ql(t,a|1),$e(t,ke()),!(te&6)&&(zn=ke()+500,ma()))}break;case 13:Na(function(){var n=Et(e,1);if(n!==null){var o=Ee();pt(n,e,1,o)}}),Td(e,1)}};Yl=function(e){if(e.tag===13){var t=Et(e,134217728);if(t!==null){var a=Ee();pt(t,e,134217728,a)}Td(e,134217728)}};Gp=function(e){if(e.tag===13){var t=ra(e),a=Et(e,t);if(a!==null){var n=Ee();pt(a,e,t,n)}Td(e,t)}};Wp=function(){return oe};Zp=function(e,t){var a=oe;try{return oe=e,t()}finally{oe=a}};$s=function(e,t,a){switch(t){case"input":if(Ks(e,a),t=a.name,a.type==="radio"&&t!=null){for(a=e;a.parentNode;)a=a.parentNode;for(a=a.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<a.length;t++){var n=a[t];if(n!==e&&n.form===e.form){var o=Ar(n);if(!o)throw Error(N(90));Ip(n),Ks(n,o)}}}break;case"textarea":wp(e,a);break;case"select":t=a.value,t!=null&&un(e,!!a.multiple,t,!1)}};Dp=xd;Ep=Na;var xk={usingClientEntryPoint:!1,Events:[Oo,nn,Ar,Lp,Rp,xd]},Vn={findFiberByHostInstance:Pa,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},zk={bundleType:Vn.bundleType,version:Vn.version,rendererPackageName:Vn.rendererPackageName,rendererConfig:Vn.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:Ut.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return e=Up(e),e===null?null:e.stateNode},findFiberByHostInstance:Vn.findFiberByHostInstance||Ak,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"){var ri=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!ri.isDisabled&&ri.supportsFiber)try{kr=ri.inject(zk),At=ri}catch{}}Xe.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=xk;Xe.createPortal=function(e,t){var a=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!Md(t))throw Error(N(200));return Pk(e,t,null,a)};Xe.createRoot=function(e,t){if(!Md(e))throw Error(N(299));var a=!1,n="",o=vg;return t!=null&&(t.unstable_strictMode===!0&&(a=!0),t.identifierPrefix!==void 0&&(n=t.identifierPrefix),t.onRecoverableError!==void 0&&(o=t.onRecoverableError)),t=wd(e,1,!1,null,null,a,!1,n,o),e[Dt]=t.current,yo(e.nodeType===8?e.parentNode:e),new jd(t)};Xe.findDOMNode=function(e){if(e==null)return null;if(e.nodeType===1)return e;var t=e._reactInternals;if(t===void 0)throw typeof e.render=="function"?Error(N(188)):(e=Object.keys(e).join(","),Error(N(268,e)));return e=Up(t),e=e===null?null:e.stateNode,e};Xe.flushSync=function(e){return Na(e)};Xe.hydrate=function(e,t,a){if(!Mr(t))throw Error(N(200));return Nr(null,e,t,!0,a)};Xe.hydrateRoot=function(e,t,a){if(!Md(e))throw Error(N(405));var n=a!=null&&a.hydratedSources||null,o=!1,i="",s=vg;if(a!=null&&(a.unstable_strictMode===!0&&(o=!0),a.identifierPrefix!==void 0&&(i=a.identifierPrefix),a.onRecoverableError!==void 0&&(s=a.onRecoverableError)),t=fg(t,null,e,1,a??null,o,!1,i,s),e[Dt]=t.current,yo(e),n)for(e=0;e<n.length;e++)a=n[e],o=a._getVersion,o=o(a._source),t.mutableSourceEagerHydrationData==null?t.mutableSourceEagerHydrationData=[a,o]:t.mutableSourceEagerHydrationData.push(a,o);return new jr(t)};Xe.render=function(e,t,a){if(!Mr(t))throw Error(N(200));return Nr(null,e,t,!1,a)};Xe.unmountComponentAtNode=function(e){if(!Mr(e))throw Error(N(40));return e._reactRootContainer?(Na(function(){Nr(null,null,e,!1,function(){e._reactRootContainer=null,e[Dt]=null})}),!0):!1};Xe.unstable_batchedUpdates=xd;Xe.unstable_renderSubtreeIntoContainer=function(e,t,a,n){if(!Mr(a))throw Error(N(200));if(e==null||e._reactInternals===void 0)throw Error(N(38));return Nr(e,t,a,!1,n)};Xe.version="18.3.1-next-f1338f8080-20240426";function kg(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(kg)}catch(e){console.error(e)}}kg(),kp.exports=Xe;var Uo=kp.exports;const Ik=El(Uo);var su=Uo;Ms.createRoot=su.createRoot,Ms.hydrateRoot=su.hydrateRoot;/**
41
- * @license lucide-react v0.451.0 - ISC
42
- *
43
- * This source code is licensed under the ISC license.
44
- * See the LICENSE file in the root directory of this source tree.
45
- */const Sk=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),yg=(...e)=>e.filter((t,a,n)=>!!t&&n.indexOf(t)===a).join(" ");/**
46
- * @license lucide-react v0.451.0 - ISC
47
- *
48
- * This source code is licensed under the ISC license.
49
- * See the LICENSE file in the root directory of this source tree.
50
- */var wk={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
51
- * @license lucide-react v0.451.0 - ISC
52
- *
53
- * This source code is licensed under the ISC license.
54
- * See the LICENSE file in the root directory of this source tree.
55
- */const Tk=g.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:a=2,absoluteStrokeWidth:n,className:o="",children:i,iconNode:s,...l},d)=>g.createElement("svg",{ref:d,...wk,width:t,height:t,stroke:e,strokeWidth:n?Number(a)*24/Number(t):a,className:yg("lucide",o),...l},[...s.map(([c,u])=>g.createElement(c,u)),...Array.isArray(i)?i:[i]]));/**
56
- * @license lucide-react v0.451.0 - ISC
57
- *
58
- * This source code is licensed under the ISC license.
59
- * See the LICENSE file in the root directory of this source tree.
60
- */const q=(e,t)=>{const a=g.forwardRef(({className:n,...o},i)=>g.createElement(Tk,{ref:i,iconNode:t,className:yg(`lucide-${Sk(e)}`,n),...o}));return a.displayName=`${e}`,a};/**
61
- * @license lucide-react v0.451.0 - ISC
62
- *
63
- * This source code is licensed under the ISC license.
64
- * See the LICENSE file in the root directory of this source tree.
65
- */const bg=q("ChartColumn",[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]);/**
66
- * @license lucide-react v0.451.0 - ISC
67
- *
68
- * This source code is licensed under the ISC license.
69
- * See the LICENSE file in the root directory of this source tree.
70
- */const Ln=q("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);/**
71
- * @license lucide-react v0.451.0 - ISC
72
- *
73
- * This source code is licensed under the ISC license.
74
- * See the LICENSE file in the root directory of this source tree.
75
- */const ga=q("ChevronDown",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);/**
76
- * @license lucide-react v0.451.0 - ISC
77
- *
78
- * This source code is licensed under the ISC license.
79
- * See the LICENSE file in the root directory of this source tree.
80
- */const Nd=q("ChevronRight",[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]);/**
81
- * @license lucide-react v0.451.0 - ISC
82
- *
83
- * This source code is licensed under the ISC license.
84
- * See the LICENSE file in the root directory of this source tree.
85
- */const Ld=q("ChevronUp",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]);/**
86
- * @license lucide-react v0.451.0 - ISC
87
- *
88
- * This source code is licensed under the ISC license.
89
- * See the LICENSE file in the root directory of this source tree.
90
- */const Pg=q("CircleAlert",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]);/**
91
- * @license lucide-react v0.451.0 - ISC
92
- *
93
- * This source code is licensed under the ISC license.
94
- * See the LICENSE file in the root directory of this source tree.
95
- */const wo=q("CircleCheckBig",[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]]);/**
96
- * @license lucide-react v0.451.0 - ISC
97
- *
98
- * This source code is licensed under the ISC license.
99
- * See the LICENSE file in the root directory of this source tree.
100
- */const Ag=q("CircleDollarSign",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8",key:"1h4pet"}],["path",{d:"M12 18V6",key:"zqpxq5"}]]);/**
101
- * @license lucide-react v0.451.0 - ISC
102
- *
103
- * This source code is licensed under the ISC license.
104
- * See the LICENSE file in the root directory of this source tree.
105
- */const Cg=q("CircleDot",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}]]);/**
106
- * @license lucide-react v0.451.0 - ISC
107
- *
108
- * This source code is licensed under the ISC license.
109
- * See the LICENSE file in the root directory of this source tree.
110
- */const jk=q("CircleHelp",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]]);/**
111
- * @license lucide-react v0.451.0 - ISC
112
- *
113
- * This source code is licensed under the ISC license.
114
- * See the LICENSE file in the root directory of this source tree.
115
- */const Mk=q("CircleUser",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"10",r:"3",key:"ilqhr7"}],["path",{d:"M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662",key:"154egf"}]]);/**
116
- * @license lucide-react v0.451.0 - ISC
117
- *
118
- * This source code is licensed under the ISC license.
119
- * See the LICENSE file in the root directory of this source tree.
120
- */const xl=q("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]);/**
121
- * @license lucide-react v0.451.0 - ISC
122
- *
123
- * This source code is licensed under the ISC license.
124
- * See the LICENSE file in the root directory of this source tree.
125
- */const Nk=q("Clock",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16 14",key:"68esgv"}]]);/**
126
- * @license lucide-react v0.451.0 - ISC
127
- *
128
- * This source code is licensed under the ISC license.
129
- * See the LICENSE file in the root directory of this source tree.
130
- */const Lr=q("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/**
131
- * @license lucide-react v0.451.0 - ISC
132
- *
133
- * This source code is licensed under the ISC license.
134
- * See the LICENSE file in the root directory of this source tree.
135
- */const Rd=q("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/**
136
- * @license lucide-react v0.451.0 - ISC
137
- *
138
- * This source code is licensed under the ISC license.
139
- * See the LICENSE file in the root directory of this source tree.
140
- */const Ho=q("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/**
141
- * @license lucide-react v0.451.0 - ISC
142
- *
143
- * This source code is licensed under the ISC license.
144
- * See the LICENSE file in the root directory of this source tree.
145
- */const xg=q("EyeOff",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);/**
146
- * @license lucide-react v0.451.0 - ISC
147
- *
148
- * This source code is licensed under the ISC license.
149
- * See the LICENSE file in the root directory of this source tree.
150
- */const zg=q("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/**
151
- * @license lucide-react v0.451.0 - ISC
152
- *
153
- * This source code is licensed under the ISC license.
154
- * See the LICENSE file in the root directory of this source tree.
155
- */const Ig=q("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);/**
156
- * @license lucide-react v0.451.0 - ISC
157
- *
158
- * This source code is licensed under the ISC license.
159
- * See the LICENSE file in the root directory of this source tree.
160
- */const Lk=q("GripVertical",[["circle",{cx:"9",cy:"12",r:"1",key:"1vctgf"}],["circle",{cx:"9",cy:"5",r:"1",key:"hp0tcf"}],["circle",{cx:"9",cy:"19",r:"1",key:"fkjjf6"}],["circle",{cx:"15",cy:"12",r:"1",key:"1tmaij"}],["circle",{cx:"15",cy:"5",r:"1",key:"19l28e"}],["circle",{cx:"15",cy:"19",r:"1",key:"f4zoj3"}]]);/**
161
- * @license lucide-react v0.451.0 - ISC
162
- *
163
- * This source code is licensed under the ISC license.
164
- * See the LICENSE file in the root directory of this source tree.
165
- */const Rk=q("HardDriveDownload",[["path",{d:"M12 2v8",key:"1q4o3n"}],["path",{d:"m16 6-4 4-4-4",key:"6wukr"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",key:"w68u3i"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"M10 18h.01",key:"h775k"}]]);/**
166
- * @license lucide-react v0.451.0 - ISC
167
- *
168
- * This source code is licensed under the ISC license.
169
- * See the LICENSE file in the root directory of this source tree.
170
- */const Dk=q("Info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/**
171
- * @license lucide-react v0.451.0 - ISC
172
- *
173
- * This source code is licensed under the ISC license.
174
- * See the LICENSE file in the root directory of this source tree.
175
- */const Dd=q("KeyRound",[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]);/**
176
- * @license lucide-react v0.451.0 - ISC
177
- *
178
- * This source code is licensed under the ISC license.
179
- * See the LICENSE file in the root directory of this source tree.
180
- */const Sg=q("Key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]]);/**
181
- * @license lucide-react v0.451.0 - ISC
182
- *
183
- * This source code is licensed under the ISC license.
184
- * See the LICENSE file in the root directory of this source tree.
185
- */const La=q("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);/**
186
- * @license lucide-react v0.451.0 - ISC
187
- *
188
- * This source code is licensed under the ISC license.
189
- * See the LICENSE file in the root directory of this source tree.
190
- */const Ek=q("Pen",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}]]);/**
191
- * @license lucide-react v0.451.0 - ISC
192
- *
193
- * This source code is licensed under the ISC license.
194
- * See the LICENSE file in the root directory of this source tree.
195
- */const Ok=q("Pencil",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]);/**
196
- * @license lucide-react v0.451.0 - ISC
197
- *
198
- * This source code is licensed under the ISC license.
199
- * See the LICENSE file in the root directory of this source tree.
200
- */const zl=q("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);/**
201
- * @license lucide-react v0.451.0 - ISC
202
- *
203
- * This source code is licensed under the ISC license.
204
- * See the LICENSE file in the root directory of this source tree.
205
- */const Ra=q("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/**
206
- * @license lucide-react v0.451.0 - ISC
207
- *
208
- * This source code is licensed under the ISC license.
209
- * See the LICENSE file in the root directory of this source tree.
210
- */const wg=q("Power",[["path",{d:"M12 2v10",key:"mnfbl"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04",key:"obofu9"}]]);/**
211
- * @license lucide-react v0.451.0 - ISC
212
- *
213
- * This source code is licensed under the ISC license.
214
- * See the LICENSE file in the root directory of this source tree.
215
- */const Fo=q("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/**
216
- * @license lucide-react v0.451.0 - ISC
217
- *
218
- * This source code is licensed under the ISC license.
219
- * See the LICENSE file in the root directory of this source tree.
220
- */const Kk=q("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/**
221
- * @license lucide-react v0.451.0 - ISC
222
- *
223
- * This source code is licensed under the ISC license.
224
- * See the LICENSE file in the root directory of this source tree.
225
- */const Uk=q("Save",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);/**
226
- * @license lucide-react v0.451.0 - ISC
227
- *
228
- * This source code is licensed under the ISC license.
229
- * See the LICENSE file in the root directory of this source tree.
230
- */const Tg=q("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);/**
231
- * @license lucide-react v0.451.0 - ISC
232
- *
233
- * This source code is licensed under the ISC license.
234
- * See the LICENSE file in the root directory of this source tree.
235
- */const Ed=q("ServerCog",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5",key:"tn8das"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5",key:"1g2pve"}],["path",{d:"M6 6h.01",key:"1utrut"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"m15.7 13.4-.9-.3",key:"1jwmzr"}],["path",{d:"m9.2 10.9-.9-.3",key:"qapnim"}],["path",{d:"m10.6 15.7.3-.9",key:"quwk0k"}],["path",{d:"m13.6 15.7-.4-1",key:"cb9xp7"}],["path",{d:"m10.8 9.3-.4-1",key:"1uaiz5"}],["path",{d:"m8.3 13.6 1-.4",key:"s6srou"}],["path",{d:"m14.7 10.8 1-.4",key:"4d31cq"}],["path",{d:"m13.4 8.3-.3.9",key:"1bm987"}]]);/**
236
- * @license lucide-react v0.451.0 - ISC
237
- *
238
- * This source code is licensed under the ISC license.
239
- * See the LICENSE file in the root directory of this source tree.
240
- */const Il=q("Settings2",[["path",{d:"M20 7h-9",key:"3s1dr2"}],["path",{d:"M14 17H5",key:"gfn3mx"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]]);/**
241
- * @license lucide-react v0.451.0 - ISC
242
- *
243
- * This source code is licensed under the ISC license.
244
- * See the LICENSE file in the root directory of this source tree.
245
- */const jg=q("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/**
246
- * @license lucide-react v0.451.0 - ISC
247
- *
248
- * This source code is licensed under the ISC license.
249
- * See the LICENSE file in the root directory of this source tree.
250
- */const Hk=q("SlidersVertical",[["line",{x1:"4",x2:"4",y1:"21",y2:"14",key:"1p332r"}],["line",{x1:"4",x2:"4",y1:"10",y2:"3",key:"gb41h5"}],["line",{x1:"12",x2:"12",y1:"21",y2:"12",key:"hf2csr"}],["line",{x1:"12",x2:"12",y1:"8",y2:"3",key:"1kfi7u"}],["line",{x1:"20",x2:"20",y1:"21",y2:"16",key:"1lhrwl"}],["line",{x1:"20",x2:"20",y1:"12",y2:"3",key:"16vvfq"}],["line",{x1:"2",x2:"6",y1:"14",y2:"14",key:"1uebub"}],["line",{x1:"10",x2:"14",y1:"8",y2:"8",key:"1yglbp"}],["line",{x1:"18",x2:"22",y1:"16",y2:"16",key:"1jxqpz"}]]);/**
251
- * @license lucide-react v0.451.0 - ISC
252
- *
253
- * This source code is licensed under the ISC license.
254
- * See the LICENSE file in the root directory of this source tree.
255
- */const Fk=q("SquareMinus",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M8 12h8",key:"1wcyev"}]]);/**
256
- * @license lucide-react v0.451.0 - ISC
257
- *
258
- * This source code is licensed under the ISC license.
259
- * See the LICENSE file in the root directory of this source tree.
260
- */const Bk=q("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);/**
261
- * @license lucide-react v0.451.0 - ISC
262
- *
263
- * This source code is licensed under the ISC license.
264
- * See the LICENSE file in the root directory of this source tree.
265
- */const Od=q("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]);/**
266
- * @license lucide-react v0.451.0 - ISC
267
- *
268
- * This source code is licensed under the ISC license.
269
- * See the LICENSE file in the root directory of this source tree.
270
- */const Vk=q("TestTube",[["path",{d:"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2",key:"125lnx"}],["path",{d:"M8.5 2h7",key:"csnxdl"}],["path",{d:"M14.5 16h-5",key:"1ox875"}]]);/**
271
- * @license lucide-react v0.451.0 - ISC
272
- *
273
- * This source code is licensed under the ISC license.
274
- * See the LICENSE file in the root directory of this source tree.
275
- */const qk=q("Timer",[["line",{x1:"10",x2:"14",y1:"2",y2:"2",key:"14vaq8"}],["line",{x1:"12",x2:"15",y1:"14",y2:"11",key:"17fdiu"}],["circle",{cx:"12",cy:"14",r:"8",key:"1e1u0o"}]]);/**
276
- * @license lucide-react v0.451.0 - ISC
277
- *
278
- * This source code is licensed under the ISC license.
279
- * See the LICENSE file in the root directory of this source tree.
280
- */const In=q("Trash2",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]);/**
281
- * @license lucide-react v0.451.0 - ISC
282
- *
283
- * This source code is licensed under the ISC license.
284
- * See the LICENSE file in the root directory of this source tree.
285
- */const Kd=q("TriangleAlert",[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]]);/**
286
- * @license lucide-react v0.451.0 - ISC
287
- *
288
- * This source code is licensed under the ISC license.
289
- * See the LICENSE file in the root directory of this source tree.
290
- */const $k=q("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]);/**
291
- * @license lucide-react v0.451.0 - ISC
292
- *
293
- * This source code is licensed under the ISC license.
294
- * See the LICENSE file in the root directory of this source tree.
295
- */const Da=q("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),_k=(e,t,a,n)=>{const o=[a,{code:t,...n||{}}];if(e?.services?.logger?.forward)return e.services.logger.forward(o,"warn","react-i18next::",!0);Ia(o[0])&&(o[0]=`react-i18next:: ${o[0]}`),e?.services?.logger?.warn?e.services.logger.warn(...o):console?.warn&&console.warn(...o)},lu={},Sl=(e,t,a,n)=>{Ia(a)&&lu[a]||(Ia(a)&&(lu[a]=new Date),_k(e,t,a,n))},Mg=(e,t)=>()=>{if(e.isInitialized)t();else{const a=()=>{setTimeout(()=>{e.off("initialized",a)},0),t()};e.on("initialized",a)}},wl=(e,t,a)=>{e.loadNamespaces(t,Mg(e,a))},du=(e,t,a,n)=>{if(Ia(a)&&(a=[a]),e.options.preload&&e.options.preload.indexOf(t)>-1)return wl(e,a,n);a.forEach(o=>{e.options.ns.indexOf(o)<0&&e.options.ns.push(o)}),e.loadLanguages(t,Mg(e,n))},Gk=(e,t,a={})=>!t.languages||!t.languages.length?(Sl(t,"NO_LANGUAGES","i18n.languages were undefined or empty",{languages:t.languages}),!0):t.hasLoadedNamespace(e,{lng:a.lng,precheck:(n,o)=>{if(a.bindI18n&&a.bindI18n.indexOf("languageChanging")>-1&&n.services.backendConnector.backend&&n.isLanguageChangingTo&&!o(n.isLanguageChangingTo,e))return!1}}),Ia=e=>typeof e=="string",Wk=e=>typeof e=="object"&&e!==null,Zk=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,Qk={"&amp;":"&","&#38;":"&","&lt;":"<","&#60;":"<","&gt;":">","&#62;":">","&apos;":"'","&#39;":"'","&quot;":'"',"&#34;":'"',"&nbsp;":" ","&#160;":" ","&copy;":"©","&#169;":"©","&reg;":"®","&#174;":"®","&hellip;":"…","&#8230;":"…","&#x2F;":"/","&#47;":"/"},Yk=e=>Qk[e],Xk=e=>e.replace(Zk,Yk);let Tl={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:Xk};const Jk=(e={})=>{Tl={...Tl,...e}},ey=()=>Tl;let Ng;const ty=e=>{Ng=e},ay=()=>Ng,ny={type:"3rdParty",init(e){Jk(e.options.react),ty(e)}},oy=g.createContext();class iy{constructor(){this.usedNamespaces={}}addUsedNamespaces(t){t.forEach(a=>{this.usedNamespaces[a]||(this.usedNamespaces[a]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}}const ry=(e,t)=>{const a=g.useRef();return g.useEffect(()=>{a.current=e},[e,t]),a.current},Lg=(e,t,a,n)=>e.getFixedT(t,a,n),sy=(e,t,a,n)=>g.useCallback(Lg(e,t,a,n),[e,t,a,n]),ly=(e,t={})=>{const{i18n:a}=t,{i18n:n,defaultNS:o}=g.useContext(oy)||{},i=a||n||ay();if(i&&!i.reportNamespaces&&(i.reportNamespaces=new iy),!i){Sl(i,"NO_I18NEXT_INSTANCE","useTranslation: You will need to pass in an i18next instance by using initReactI18next");const b=(I,C)=>Ia(C)?C:Wk(C)&&Ia(C.defaultValue)?C.defaultValue:Array.isArray(I)?I[I.length-1]:I,z=[b,{},!1];return z.t=b,z.i18n={},z.ready=!1,z}i.options.react?.wait&&Sl(i,"DEPRECATED_OPTION","useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.");const s={...ey(),...i.options.react,...t},{useSuspense:l,keyPrefix:d}=s;let c=o||i.options?.defaultNS;c=Ia(c)?[c]:c||["translation"],i.reportNamespaces.addUsedNamespaces?.(c);const u=(i.isInitialized||i.initializedStoreOnce)&&c.every(b=>Gk(b,i,s)),p=sy(i,t.lng||null,s.nsMode==="fallback"?c:c[0],d),m=()=>p,f=()=>Lg(i,t.lng||null,s.nsMode==="fallback"?c:c[0],d),[P,y]=g.useState(m);let A=c.join();t.lng&&(A=`${t.lng}${A}`);const h=ry(A),k=g.useRef(!0);g.useEffect(()=>{const{bindI18n:b,bindI18nStore:z}=s;k.current=!0,!u&&!l&&(t.lng?du(i,t.lng,c,()=>{k.current&&y(f)}):wl(i,c,()=>{k.current&&y(f)})),u&&h&&h!==A&&k.current&&y(f);const I=()=>{k.current&&y(f)};return b&&i?.on(b,I),z&&i?.store.on(z,I),()=>{k.current=!1,i&&b&&b?.split(" ").forEach(C=>i.off(C,I)),z&&i&&z.split(" ").forEach(C=>i.store.off(C,I))}},[i,A]),g.useEffect(()=>{k.current&&u&&y(m)},[i,d,u]);const v=[P,i,u];if(v.t=P,v.i18n=i,v.ready=u,u||!u&&!l)return v;throw new Promise(b=>{t.lng?du(i,t.lng,c,()=>b()):wl(i,c,()=>b())})};function $(){const{t:e}=ly();return(t,a)=>{const o=e(t,typeof a=="string"?{defaultValue:a}:a);return typeof o=="string"?o:t}}async function Qt(e,t={},a){return window.__TAURI_INTERNALS__.invoke(e,t,a)}function Rr(){return!!(globalThis||window).isTauri}const si="Request cancelled";async function dy(e,t){const a=t?.signal;if(a?.aborted)throw new Error(si);const n=t?.maxRedirections,o=t?.connectTimeout,i=t?.proxy,s=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const l=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,d=new Request(e,t),c=await d.arrayBuffer(),u=c.byteLength!==0?Array.from(new Uint8Array(c)):null;for(const[L,T]of d.headers)l.get(L)||l.set(L,T);const m=(l instanceof Headers?Array.from(l.entries()):Array.isArray(l)?l:Object.entries(l)).map(([L,T])=>[L,typeof T=="string"?T:T.toString()]);if(a?.aborted)throw new Error(si);const f=await Qt("plugin:http|fetch",{clientConfig:{method:d.method,url:d.url,headers:m,data:u,maxRedirections:n,connectTimeout:o,proxy:i,danger:s}}),P=()=>Qt("plugin:http|fetch_cancel",{rid:f});if(a?.aborted)throw P(),new Error(si);a?.addEventListener("abort",()=>void P());const{status:y,statusText:A,url:h,headers:k,rid:v}=await Qt("plugin:http|fetch_send",{rid:f}),b=()=>Qt("plugin:http|fetch_cancel_body",{rid:v}),z=async L=>{let T;try{T=await Qt("plugin:http|fetch_read_body",{rid:v})}catch(W){L.error(W),b();return}const M=new Uint8Array(T),D=M[M.byteLength-1],Q=M.slice(0,M.byteLength-1);if(D===1){L.close();return}L.enqueue(Q)},I=[101,103,204,205,304].includes(y)?null:new ReadableStream({start:L=>{a?.addEventListener("abort",()=>{L.error(si),b()})},pull:L=>z(L),cancel:()=>{b()}}),C=new Response(I,{status:y,statusText:A});Object.defineProperty(C,"url",{value:h,writable:!1}),Object.defineProperty(C,"headers",{value:new Headers(k),writable:!1});const S=C.clone.bind(C);return Object.defineProperty(C,"clone",{value:()=>{const L=S();return Object.defineProperty(L,"url",{value:h,writable:!1}),Object.defineProperty(L,"headers",{value:new Headers(k),writable:!1}),L}}),C}const cy=Rr(),Rg=cy?(e,t)=>dy(e,t):(e,t)=>fetch(e,t),uy={BASE_URL:"./",DEV:!1,MODE:"production",PROD:!0,SSR:!1},py="http://127.0.0.1:8766";function Dg(e){return uy?.[e]}function my(){return Rr()?py:""}const Sa=(Dg("VITE_DAEMON_BASE_URL")||my()).replace(/\/+$/,""),cu=Dg("VITE_DAEMON_ADMIN_TOKEN")||"";class cr extends Error{constructor(a,n){super(n);Xd(this,"status");this.name="AdminApiError",this.status=a}}async function li(e,t,a){const n={};a!==void 0&&(n["Content-Type"]="application/json"),cu&&(n.Authorization=`Bearer ${cu}`);let o;try{o=await Rg(`${Sa}/admin/api${t}`,{method:e,headers:n,body:a===void 0?void 0:JSON.stringify(a)})}catch(l){throw new cr(0,l instanceof Error?l.message:"network error")}const i=await o.text();let s=null;try{s=i?JSON.parse(i):null}catch{s=null}if(!o.ok){const l=s?.error?.message||`request failed (${o.status})`;throw new cr(o.status,l)}return s}const H={get:e=>li("GET",e),post:(e,t)=>li("POST",e,t),put:(e,t)=>li("PUT",e,t),delete:e=>li("DELETE",e)},gy=750;function hy(e){return e==="running"||e==="failed"}async function uu(){try{return await Rg(`${Sa}/admin/api/status`,{method:"GET"}),{state:"running",port:8766,adopted:!0}}catch{return{state:"failed",reason:"daemon not reachable on 127.0.0.1:8766"}}}function fy(){const[e,t]=g.useState({state:"probing"}),a=g.useRef(!0);return g.useEffect(()=>{a.current=!0;let n;async function o(){let i;if(Rr())try{i=await Qt("daemon_status")}catch{i=await uu()}else i=await uu();a.current&&(t(i),hy(i.state)||(n=setTimeout(()=>void o(),gy)))}return o(),()=>{a.current=!1,n&&clearTimeout(n)}},[]),e}function vy(){const e=$(),t=fy();if(t.state==="running"||t.state==="adopted")return null;if(t.state==="failed")return r.jsxs("div",{role:"alert",className:"flex items-start gap-2 border-b border-destructive/40 bg-destructive/10 px-4 py-2 text-xs text-foreground",children:[r.jsx(Kd,{className:"mt-0.5 h-4 w-4 shrink-0 text-destructive","aria-hidden":"true"}),r.jsxs("div",{className:"min-w-0 flex-1 space-y-0.5",children:[r.jsx("p",{className:"font-medium text-destructive",children:e("daemonStatus.failed")}),t.reason?r.jsx("p",{className:"break-words text-muted-foreground",children:t.reason}):null,r.jsx("p",{className:"text-muted-foreground",children:e("daemonStatus.failedHint")})]})]});const a=t.state==="spawning"?e("daemonStatus.spawning"):e("daemonStatus.probing");return r.jsxs("div",{className:"flex items-center gap-2 border-b border-border/50 bg-surface-1/60 px-4 py-1.5 text-xs text-muted-foreground",children:[r.jsx(La,{className:"h-3.5 w-3.5 shrink-0 animate-spin","aria-hidden":"true"}),r.jsx("span",{children:a})]})}function G(...e){const t=[],a=n=>{!n&&n!==0||(Array.isArray(n)?n.forEach(a):(typeof n=="string"||typeof n=="number")&&t.push(String(n)))};return e.forEach(a),t.join(" ")}const ky=[{id:"providers",icon:Hk,labelKey:"nav.providers"},{id:"api-service",icon:Ed,labelKey:"nav.apiService"},{id:"accounts",icon:$k,labelKey:"nav.accounts"},{id:"code-cli",icon:Od,labelKey:"nav.codeCli"},{id:"usage-stats",icon:bg,labelKey:"nav.usageStats"},{id:"pricing",icon:Ag,labelKey:"nav.pricing"},{id:"settings",icon:jg,labelKey:"nav.settings"}];function yy({activePage:e,onNavigate:t}){const a=$();return r.jsxs("aside",{className:"flex w-56 shrink-0 flex-col border-r border-border bg-surface-1",children:[r.jsxs("div",{className:"border-b border-border/60 px-4 py-4",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(Ed,{className:"h-5 w-5 text-primary","aria-hidden":"true"}),r.jsx("span",{className:"font-display text-base font-semibold",children:"Omnicross"})]}),r.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a("nav.subtitle")})]}),r.jsx("nav",{className:"flex-1 space-y-1 p-2",children:ky.map(n=>{const o=n.icon,i=n.id===e;return r.jsxs("button",{type:"button",onClick:()=>t(n.id),"aria-current":i?"page":void 0,className:G("flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors",i?"bg-surface-2/60 text-foreground":"text-muted-foreground hover:bg-surface-2/40 hover:text-foreground"),children:[r.jsx(o,{className:"h-4 w-4 shrink-0",strokeWidth:1.5}),r.jsx("span",{className:"truncate",children:a(n.labelKey)})]},n.id)})}),r.jsx("div",{className:"border-t border-border/60 p-3",children:r.jsx("p",{className:"truncate text-[10px] text-muted-foreground/70",title:Sa,children:Sa})})]})}const ha=g.forwardRef(({className:e,children:t,shadow:a=!0,...n},o)=>r.jsxs("div",{ref:o,className:G("relative h-full min-h-0",e),style:{overflow:"clip"},...n,children:[r.jsx("div",{"data-scroll-container":!0,className:"h-full scroll-smooth overflow-auto rounded-[inherit] pr-2",style:{WebkitOverflowScrolling:"touch",touchAction:"pan-y",maxHeight:"inherit"},children:t}),a?r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"scroll-shadow pointer-events-none absolute inset-x-0 top-0 h-2 bg-gradient-to-b from-surface-0 via-surface-0/80 to-transparent"}),r.jsx("div",{className:"scroll-shadow pointer-events-none absolute inset-x-0 bottom-0 h-2 bg-gradient-to-t from-surface-0 via-surface-0/80 to-transparent"})]}):null]}));ha.displayName="ScrollArea";function Eg(e){var t,a,n="";if(typeof e=="string"||typeof e=="number")n+=e;else if(typeof e=="object")if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(a=Eg(e[t]))&&(n&&(n+=" "),n+=a)}else for(a in e)e[a]&&(n&&(n+=" "),n+=a);return n}function by(){for(var e,t,a=0,n="",o=arguments.length;a<o;a++)(e=arguments[a])&&(t=Eg(e))&&(n&&(n+=" "),n+=t);return n}const pu=e=>typeof e=="boolean"?`${e}`:e===0?"0":e,mu=by,Og=(e,t)=>a=>{var n;if(t?.variants==null)return mu(e,a?.class,a?.className);const{variants:o,defaultVariants:i}=t,s=Object.keys(o).map(c=>{const u=a?.[c],p=i?.[c];if(u===null)return null;const m=pu(u)||pu(p);return o[c][m]}),l=a&&Object.entries(a).reduce((c,u)=>{let[p,m]=u;return m===void 0||(c[p]=m),c},{}),d=t==null||(n=t.compoundVariants)===null||n===void 0?void 0:n.reduce((c,u)=>{let{class:p,className:m,...f}=u;return Object.entries(f).every(P=>{let[y,A]=P;return Array.isArray(A)?A.includes({...i,...l}[y]):{...i,...l}[y]===A})?[...c,p,m]:c},[]);return mu(e,s,d,a?.class,a?.className)},Py=Og("inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-[3px] border text-sm font-medium tracking-[0.01em] transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-40 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground border-transparent hover:bg-primary/90 active:bg-primary/80",destructive:"bg-destructive text-destructive-foreground border-transparent hover:bg-destructive/90",outline:"border-border bg-surface-1 text-foreground hover:border-primary hover:text-foreground",secondary:"bg-transparent text-foreground border-border hover:bg-surface-2/80 hover:border-text-subtle/40",ghost:"border-transparent bg-transparent text-text-muted hover:text-foreground hover:bg-primary-soft/30",subtle:"border-transparent bg-primary-soft/20 text-foreground hover:bg-primary-soft/30",link:"border-transparent bg-transparent text-primary underline-offset-4 hover:underline"},size:{default:"h-8 px-3.5",xs:"h-6 px-2 text-xs",sm:"h-7 px-3 text-xs",lg:"h-9 px-4",icon:"h-8 w-8"}},defaultVariants:{variant:"default",size:"default"}}),R=g.forwardRef(({className:e,variant:t,size:a,...n},o)=>r.jsx("button",{className:G(Py({variant:t,size:a,className:e})),ref:o,...n}));R.displayName="Button";function Ay(e,t){const a=e.getBoundingClientRect(),n=window.innerHeight-a.bottom,o=n<t&&a.top>n;return{left:a.left,width:a.width,flipUp:o,...o?{bottom:window.innerHeight-a.top+4}:{top:a.bottom+4}}}function Lt(e){if("children"in e&&e.children){const a=e;return r.jsx(xy,{...a})}return r.jsx(Cy,{...e})}function Cy({value:e,onChange:t,options:a,placeholder:n="Select...",disabled:o=!1,className:i,id:s,size:l="default"}){const[d,c]=g.useState(!1),u=g.useRef(null),p=g.useRef(null),[m,f]=g.useState({});g.useEffect(()=>{if(d&&u.current){const A=Math.min(a.length*36+16,272),{flipUp:h,...k}=Ay(u.current,A);f(k)}},[d,a.length]),g.useEffect(()=>{if(!d)return;const A=h=>{const k=h.target;(!u.current||!u.current.contains(k))&&(!p.current||!p.current.contains(k))&&c(!1)};return document.addEventListener("mousedown",A),()=>document.removeEventListener("mousedown",A)},[d]),g.useEffect(()=>{if(!d)return;const A=h=>{h.key==="Escape"&&c(!1)};return document.addEventListener("keydown",A),()=>document.removeEventListener("keydown",A)},[d]);const P=a.find(A=>A.value===e),y=A=>{t(A),c(!1)};return r.jsxs("div",{className:"relative",children:[r.jsxs("button",{ref:u,type:"button",id:s,onClick:()=>!o&&c(!d),disabled:o,className:G("flex items-center justify-between gap-2 rounded-lg border border-border bg-surface-1 text-sm text-foreground transition-colors","hover:bg-surface-2 focus:outline-none focus:ring-2 focus:ring-primary/50",o&&"opacity-50 cursor-not-allowed",l==="sm"?"h-8 px-2 py-1":"h-9 px-3 py-2",i),children:[r.jsx("span",{className:G("truncate",!P&&"text-muted-foreground"),children:P?.label||n}),r.jsx(ga,{className:G("h-4 w-4 shrink-0 text-muted-foreground transition-transform",d&&"rotate-180")})]}),d?Uo.createPortal(r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"fixed inset-0 z-[60] pointer-events-auto",onClick:()=>c(!1)}),r.jsx("div",{ref:p,className:"fixed z-[70] pointer-events-auto bg-popover wallpaper-panel border border-border rounded-lg shadow-lg overflow-hidden",style:m,children:r.jsx("div",{className:"max-h-64 overflow-y-auto py-1",children:a.length===0?r.jsx("div",{className:"px-3 py-2 text-sm text-muted-foreground text-center",children:"No options"}):a.map(A=>{const h=A.value===e;return r.jsxs("button",{type:"button",onClick:()=>!A.disabled&&y(A.value),disabled:A.disabled,className:G("w-full flex items-center justify-between gap-2 px-3 py-2 text-sm text-left transition-colors",h?"bg-primary/10 text-foreground":"text-foreground hover:bg-surface-2",A.disabled&&"opacity-50 cursor-not-allowed"),children:[r.jsx("span",{className:"truncate",children:A.label}),h?r.jsx(Ln,{className:"h-4 w-4 shrink-0 text-primary"}):null]},A.value)})})})]}),document.body):null]})}const Kg=g.createContext(null);function xy({value:e,defaultValue:t,onValueChange:a,disabled:n=!1,children:o}){const[i,s]=g.useState(t||""),[l,d]=g.useState(!1),[c,u]=g.useState(null),p=e!==void 0?e:i,m=g.useCallback(P=>{n||(e===void 0&&s(P),a?.(P))},[n,e,a]),f=g.useCallback(P=>{n||d(P)},[n]);return r.jsx(Kg.Provider,{value:{value:p,onValueChange:m,open:n?!1:l,setOpen:f,disabled:n,triggerEl:c,setTriggerEl:u},children:r.jsx("div",{className:G("relative",n&&"opacity-50 cursor-not-allowed"),children:o})})}const zy=g.forwardRef(({className:e,children:t,disabled:a,...n},o)=>{const i=g.useContext(Kg);if(!i)throw new Error("SelectTrigger must be used within Select");const s=a||i.disabled,{setTriggerEl:l}=i,d=g.useCallback(c=>{typeof o=="function"?o(c):o&&(o.current=c),l(c)},[o,l]);return r.jsxs("button",{ref:d,type:"button",disabled:s,className:G("flex h-9 w-full items-center justify-between gap-2 rounded-lg border border-border bg-surface-1 px-3 py-2 text-sm text-foreground transition-colors","hover:bg-surface-2 focus:outline-none focus:ring-2 focus:ring-primary/50","disabled:cursor-not-allowed disabled:opacity-50",e),onClick:()=>!s&&i.setOpen(!i.open),...n,children:[t,r.jsx(ga,{className:G("h-4 w-4 shrink-0 text-muted-foreground transition-transform",i.open&&"rotate-180")})]})});zy.displayName="SelectTrigger";function la(e,t,{checkForDefaultPrevented:a=!0}={}){return function(o){if(e?.(o),a===!1||!o.defaultPrevented)return t?.(o)}}function gu(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function Iy(...e){return t=>{let a=!1;const n=e.map(o=>{const i=gu(o,t);return!a&&typeof i=="function"&&(a=!0),i});if(a)return()=>{for(let o=0;o<n.length;o++){const i=n[o];typeof i=="function"?i():gu(e[o],null)}}}}function Ua(...e){return g.useCallback(Iy(...e),e)}function Sy(e,t){const a=g.createContext(t);a.displayName=e+"Context";const n=i=>{const{children:s,...l}=i,d=g.useMemo(()=>l,Object.values(l));return r.jsx(a.Provider,{value:d,children:s})};n.displayName=e+"Provider";function o(i){const s=g.useContext(a);if(s)return s;if(t!==void 0)return t;throw new Error(`\`${i}\` must be used within \`${e}\``)}return[n,o]}function wy(e,t=[]){let a=[];function n(i,s){const l=g.createContext(s);l.displayName=i+"Context";const d=a.length;a=[...a,s];const c=p=>{const{scope:m,children:f,...P}=p,y=m?.[e]?.[d]||l,A=g.useMemo(()=>P,Object.values(P));return r.jsx(y.Provider,{value:A,children:f})};c.displayName=i+"Provider";function u(p,m){const f=m?.[e]?.[d]||l,P=g.useContext(f);if(P)return P;if(s!==void 0)return s;throw new Error(`\`${p}\` must be used within \`${i}\``)}return[c,u]}const o=()=>{const i=a.map(s=>g.createContext(s));return function(l){const d=l?.[e]||i;return g.useMemo(()=>({[`__scope${e}`]:{...l,[e]:d}}),[l,d])}};return o.scopeName=e,[n,Ty(o,...t)]}function Ty(...e){const t=e[0];if(e.length===1)return t;const a=()=>{const n=e.map(o=>({useScope:o(),scopeName:o.scopeName}));return function(i){const s=n.reduce((l,{useScope:d,scopeName:c})=>{const p=d(i)[`__scope${c}`];return{...l,...p}},{});return g.useMemo(()=>({[`__scope${t.scopeName}`]:s}),[s])}};return a.scopeName=t.scopeName,a}var To=globalThis?.document?g.useLayoutEffect:()=>{},jy=Fl[" useId ".trim().toString()]||(()=>{}),My=0;function gs(e){const[t,a]=g.useState(jy());return To(()=>{a(n=>n??String(My++))},[e]),e||(t?`radix-${t}`:"")}var Ny=Fl[" useInsertionEffect ".trim().toString()]||To;function Ly({prop:e,defaultProp:t,onChange:a=()=>{},caller:n}){const[o,i,s]=Ry({defaultProp:t,onChange:a}),l=e!==void 0,d=l?e:o;{const u=g.useRef(e!==void 0);g.useEffect(()=>{const p=u.current;p!==l&&console.warn(`${n} is changing from ${p?"controlled":"uncontrolled"} to ${l?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),u.current=l},[l,n])}const c=g.useCallback(u=>{if(l){const p=Dy(u)?u(e):u;p!==e&&s.current?.(p)}else i(u)},[l,e,i,s]);return[d,c]}function Ry({defaultProp:e,onChange:t}){const[a,n]=g.useState(e),o=g.useRef(a),i=g.useRef(t);return Ny(()=>{i.current=t},[t]),g.useEffect(()=>{o.current!==a&&(i.current?.(a),o.current=a)},[a,o]),[a,n,i]}function Dy(e){return typeof e=="function"}function Ug(e){const t=g.forwardRef((a,n)=>{let{children:o,...i}=a,s=null,l=!1;const d=[];hu(o)&&typeof di=="function"&&(o=di(o._payload)),g.Children.forEach(o,m=>{if(Hy(m)){l=!0;const f=m;let P="child"in f.props?f.props.child:f.props.children;hu(P)&&typeof di=="function"&&(P=di(P._payload)),s=Oy(f,P),d.push(s?.props?.children)}else d.push(m)}),s?s=g.cloneElement(s,void 0,d):!l&&g.Children.count(o)===1&&g.isValidElement(o)&&(s=o);const c=s?Uy(s):void 0,u=Ua(n,c);if(!s){if(o||o===0)throw new Error(l?qy(e):Vy(e));return o}const p=Ky(i,s.props??{});return s.type!==g.Fragment&&(p.ref=n?u:c),g.cloneElement(s,p)});return t.displayName=`${e}.Slot`,t}var Ey=Symbol.for("radix.slottable"),Oy=(e,t)=>{if("child"in e.props){const a=e.props.child;return g.isValidElement(a)?g.cloneElement(a,void 0,e.props.children(a.props.children)):null}return g.isValidElement(t)?t:null};function Ky(e,t){const a={...t};for(const n in t){const o=e[n],i=t[n];/^on[A-Z]/.test(n)?o&&i?a[n]=(...l)=>{const d=i(...l);return o(...l),d}:o&&(a[n]=o):n==="style"?a[n]={...o,...i}:n==="className"&&(a[n]=[o,i].filter(Boolean).join(" "))}return{...e,...a}}function Uy(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get,a=t&&"isReactWarning"in t&&t.isReactWarning;return a?e.ref:(t=Object.getOwnPropertyDescriptor(e,"ref")?.get,a=t&&"isReactWarning"in t&&t.isReactWarning,a?e.props.ref:e.props.ref||e.ref)}function Hy(e){return g.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===Ey}var Fy=Symbol.for("react.lazy");function hu(e){return e!=null&&typeof e=="object"&&"$$typeof"in e&&e.$$typeof===Fy&&"_payload"in e&&By(e._payload)}function By(e){return typeof e=="object"&&e!==null&&"then"in e}var Vy=e=>`${e} failed to slot onto its children. Expected a single React element child or \`Slottable\`.`,qy=e=>`${e} failed to slot onto its \`Slottable\`. Expected \`Slottable\` to receive a single React element child.`,di=Fl[" use ".trim().toString()],$y=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],Ht=$y.reduce((e,t)=>{const a=Ug(`Primitive.${t}`),n=g.forwardRef((o,i)=>{const{asChild:s,...l}=o,d=s?a:t;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),r.jsx(d,{...l,ref:i})});return n.displayName=`Primitive.${t}`,{...e,[t]:n}},{});function _y(e,t){e&&Uo.flushSync(()=>e.dispatchEvent(t))}function jo(e){const t=g.useRef(e);return g.useEffect(()=>{t.current=e}),g.useMemo(()=>(...a)=>t.current?.(...a),[])}function Gy(e,t=globalThis?.document){const a=jo(e);g.useEffect(()=>{const n=o=>{o.key==="Escape"&&a(o)};return t.addEventListener("keydown",n,{capture:!0}),()=>t.removeEventListener("keydown",n,{capture:!0})},[a,t])}var Wy="DismissableLayer",jl="dismissableLayer.update",Zy="dismissableLayer.pointerDownOutside",Qy="dismissableLayer.focusOutside",fu,Hg=g.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Fg=g.forwardRef((e,t)=>{const{disableOutsidePointerEvents:a=!1,onEscapeKeyDown:n,onPointerDownOutside:o,onFocusOutside:i,onInteractOutside:s,onDismiss:l,...d}=e,c=g.useContext(Hg),[u,p]=g.useState(null),m=u?.ownerDocument??globalThis?.document,[,f]=g.useState({}),P=Ua(t,C=>p(C)),y=Array.from(c.layers),[A]=[...c.layersWithOutsidePointerEventsDisabled].slice(-1),h=y.indexOf(A),k=u?y.indexOf(u):-1,v=c.layersWithOutsidePointerEventsDisabled.size>0,b=k>=h,z=Jy(C=>{const S=C.target,L=[...c.branches].some(T=>T.contains(S));!b||L||(o?.(C),s?.(C),C.defaultPrevented||l?.())},m),I=eb(C=>{const S=C.target;[...c.branches].some(T=>T.contains(S))||(i?.(C),s?.(C),C.defaultPrevented||l?.())},m);return Gy(C=>{k===c.layers.size-1&&(n?.(C),!C.defaultPrevented&&l&&(C.preventDefault(),l()))},m),g.useEffect(()=>{if(u)return a&&(c.layersWithOutsidePointerEventsDisabled.size===0&&(fu=m.body.style.pointerEvents,m.body.style.pointerEvents="none"),c.layersWithOutsidePointerEventsDisabled.add(u)),c.layers.add(u),vu(),()=>{a&&(c.layersWithOutsidePointerEventsDisabled.delete(u),c.layersWithOutsidePointerEventsDisabled.size===0&&(m.body.style.pointerEvents=fu))}},[u,m,a,c]),g.useEffect(()=>()=>{u&&(c.layers.delete(u),c.layersWithOutsidePointerEventsDisabled.delete(u),vu())},[u,c]),g.useEffect(()=>{const C=()=>f({});return document.addEventListener(jl,C),()=>document.removeEventListener(jl,C)},[]),r.jsx(Ht.div,{...d,ref:P,style:{pointerEvents:v?b?"auto":"none":void 0,...e.style},onFocusCapture:la(e.onFocusCapture,I.onFocusCapture),onBlurCapture:la(e.onBlurCapture,I.onBlurCapture),onPointerDownCapture:la(e.onPointerDownCapture,z.onPointerDownCapture)})});Fg.displayName=Wy;var Yy="DismissableLayerBranch",Xy=g.forwardRef((e,t)=>{const a=g.useContext(Hg),n=g.useRef(null),o=Ua(t,n);return g.useEffect(()=>{const i=n.current;if(i)return a.branches.add(i),()=>{a.branches.delete(i)}},[a.branches]),r.jsx(Ht.div,{...e,ref:o})});Xy.displayName=Yy;function Jy(e,t=globalThis?.document){const a=jo(e),n=g.useRef(!1),o=g.useRef(()=>{});return g.useEffect(()=>{const i=l=>{if(l.target&&!n.current){let d=function(){Bg(Zy,a,c,{discrete:!0})};const c={originalEvent:l};l.pointerType==="touch"?(t.removeEventListener("click",o.current),o.current=d,t.addEventListener("click",o.current,{once:!0})):d()}else t.removeEventListener("click",o.current);n.current=!1},s=window.setTimeout(()=>{t.addEventListener("pointerdown",i)},0);return()=>{window.clearTimeout(s),t.removeEventListener("pointerdown",i),t.removeEventListener("click",o.current)}},[t,a]),{onPointerDownCapture:()=>n.current=!0}}function eb(e,t=globalThis?.document){const a=jo(e),n=g.useRef(!1);return g.useEffect(()=>{const o=i=>{i.target&&!n.current&&Bg(Qy,a,{originalEvent:i},{discrete:!1})};return t.addEventListener("focusin",o),()=>t.removeEventListener("focusin",o)},[t,a]),{onFocusCapture:()=>n.current=!0,onBlurCapture:()=>n.current=!1}}function vu(){const e=new CustomEvent(jl);document.dispatchEvent(e)}function Bg(e,t,a,{discrete:n}){const o=a.originalEvent.target,i=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:a});t&&o.addEventListener(e,t,{once:!0}),n?_y(o,i):o.dispatchEvent(i)}var hs="focusScope.autoFocusOnMount",fs="focusScope.autoFocusOnUnmount",ku={bubbles:!1,cancelable:!0},tb="FocusScope",Vg=g.forwardRef((e,t)=>{const{loop:a=!1,trapped:n=!1,onMountAutoFocus:o,onUnmountAutoFocus:i,...s}=e,[l,d]=g.useState(null),c=jo(o),u=jo(i),p=g.useRef(null),m=Ua(t,y=>d(y)),f=g.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;g.useEffect(()=>{if(n){let y=function(v){if(f.paused||!l)return;const b=v.target;l.contains(b)?p.current=b:$t(p.current,{select:!0})},A=function(v){if(f.paused||!l)return;const b=v.relatedTarget;b!==null&&(l.contains(b)||$t(p.current,{select:!0}))},h=function(v){if(document.activeElement===document.body)for(const z of v)z.removedNodes.length>0&&$t(l)};document.addEventListener("focusin",y),document.addEventListener("focusout",A);const k=new MutationObserver(h);return l&&k.observe(l,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",y),document.removeEventListener("focusout",A),k.disconnect()}}},[n,l,f.paused]),g.useEffect(()=>{if(l){bu.add(f);const y=document.activeElement;if(!l.contains(y)){const h=new CustomEvent(hs,ku);l.addEventListener(hs,c),l.dispatchEvent(h),h.defaultPrevented||(ab(sb(qg(l)),{select:!0}),document.activeElement===y&&$t(l))}return()=>{l.removeEventListener(hs,c),setTimeout(()=>{const h=new CustomEvent(fs,ku);l.addEventListener(fs,u),l.dispatchEvent(h),h.defaultPrevented||$t(y??document.body,{select:!0}),l.removeEventListener(fs,u),bu.remove(f)},0)}}},[l,c,u,f]);const P=g.useCallback(y=>{if(!a&&!n||f.paused)return;const A=y.key==="Tab"&&!y.altKey&&!y.ctrlKey&&!y.metaKey,h=document.activeElement;if(A&&h){const k=y.currentTarget,[v,b]=nb(k);v&&b?!y.shiftKey&&h===b?(y.preventDefault(),a&&$t(v,{select:!0})):y.shiftKey&&h===v&&(y.preventDefault(),a&&$t(b,{select:!0})):h===k&&y.preventDefault()}},[a,n,f.paused]);return r.jsx(Ht.div,{tabIndex:-1,...s,ref:m,onKeyDown:P})});Vg.displayName=tb;function ab(e,{select:t=!1}={}){const a=document.activeElement;for(const n of e)if($t(n,{select:t}),document.activeElement!==a)return}function nb(e){const t=qg(e),a=yu(t,e),n=yu(t.reverse(),e);return[a,n]}function qg(e){const t=[],a=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:n=>{const o=n.tagName==="INPUT"&&n.type==="hidden";return n.disabled||n.hidden||o?NodeFilter.FILTER_SKIP:n.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;a.nextNode();)t.push(a.currentNode);return t}function yu(e,t){for(const a of e)if(!ob(a,{upTo:t}))return a}function ob(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t!==void 0&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1}function ib(e){return e instanceof HTMLInputElement&&"select"in e}function $t(e,{select:t=!1}={}){if(e&&e.focus){const a=document.activeElement;e.focus({preventScroll:!0}),e!==a&&ib(e)&&t&&e.select()}}var bu=rb();function rb(){let e=[];return{add(t){const a=e[0];t!==a&&a?.pause(),e=Pu(e,t),e.unshift(t)},remove(t){e=Pu(e,t),e[0]?.resume()}}}function Pu(e,t){const a=[...e],n=a.indexOf(t);return n!==-1&&a.splice(n,1),a}function sb(e){return e.filter(t=>t.tagName!=="A")}var lb="Portal",$g=g.forwardRef((e,t)=>{const{container:a,...n}=e,[o,i]=g.useState(!1);To(()=>i(!0),[]);const s=a||o&&globalThis?.document?.body;return s?Uo.createPortal(r.jsx(Ht.div,{...n,ref:t}),s):null});$g.displayName=lb;function db(e,t){return g.useReducer((a,n)=>t[a][n]??a,e)}var Dr=e=>{const{present:t,children:a}=e,n=cb(t),o=typeof a=="function"?a({present:n.isPresent}):g.Children.only(a),i=ub(n.ref,pb(o));return typeof a=="function"||n.isPresent?g.cloneElement(o,{ref:i}):null};Dr.displayName="Presence";function cb(e){const[t,a]=g.useState(),n=g.useRef(null),o=g.useRef(e),i=g.useRef("none"),s=e?"mounted":"unmounted",[l,d]=db(s,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return g.useEffect(()=>{const c=ci(n.current);i.current=l==="mounted"?c:"none"},[l]),To(()=>{const c=n.current,u=o.current;if(u!==e){const m=i.current,f=ci(c);e?d("MOUNT"):f==="none"||c?.display==="none"?d("UNMOUNT"):d(u&&m!==f?"ANIMATION_OUT":"UNMOUNT"),o.current=e}},[e,d]),To(()=>{if(t){let c;const u=t.ownerDocument.defaultView??window,p=f=>{const y=ci(n.current).includes(CSS.escape(f.animationName));if(f.target===t&&y&&(d("ANIMATION_END"),!o.current)){const A=t.style.animationFillMode;t.style.animationFillMode="forwards",c=u.setTimeout(()=>{t.style.animationFillMode==="forwards"&&(t.style.animationFillMode=A)})}},m=f=>{f.target===t&&(i.current=ci(n.current))};return t.addEventListener("animationstart",m),t.addEventListener("animationcancel",p),t.addEventListener("animationend",p),()=>{u.clearTimeout(c),t.removeEventListener("animationstart",m),t.removeEventListener("animationcancel",p),t.removeEventListener("animationend",p)}}else d("ANIMATION_END")},[t,d]),{isPresent:["mounted","unmountSuspended"].includes(l),ref:g.useCallback(c=>{n.current=c?getComputedStyle(c):null,a(c)},[])}}function Au(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function ub(...e){const t=g.useRef(e);return t.current=e,g.useCallback(a=>{const n=t.current;let o=!1;const i=n.map(s=>{const l=Au(s,a);return!o&&typeof l=="function"&&(o=!0),l});if(o)return()=>{for(let s=0;s<i.length;s++){const l=i[s];typeof l=="function"?l():Au(n[s],null)}}},[])}function ci(e){return e?.animationName||"none"}function pb(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get,a=t&&"isReactWarning"in t&&t.isReactWarning;return a?e.ref:(t=Object.getOwnPropertyDescriptor(e,"ref")?.get,a=t&&"isReactWarning"in t&&t.isReactWarning,a?e.props.ref:e.props.ref||e.ref)}var ui=0,Va=null;function mb(){g.useEffect(()=>{Va||(Va={start:Cu(),end:Cu()});const{start:e,end:t}=Va;return document.body.firstElementChild!==e&&document.body.insertAdjacentElement("afterbegin",e),document.body.lastElementChild!==t&&document.body.insertAdjacentElement("beforeend",t),ui++,()=>{ui===1&&(Va?.start.remove(),Va?.end.remove(),Va=null),ui=Math.max(0,ui-1)}},[])}function Cu(){const e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var bt=function(){return bt=Object.assign||function(t){for(var a,n=1,o=arguments.length;n<o;n++){a=arguments[n];for(var i in a)Object.prototype.hasOwnProperty.call(a,i)&&(t[i]=a[i])}return t},bt.apply(this,arguments)};function _g(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(a[n]=e[n]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(a[n[o]]=e[n[o]]);return a}function gb(e,t,a){if(a||arguments.length===2)for(var n=0,o=t.length,i;n<o;n++)(i||!(n in t))&&(i||(i=Array.prototype.slice.call(t,0,n)),i[n]=t[n]);return e.concat(i||Array.prototype.slice.call(t))}var Ki="right-scroll-bar-position",Ui="width-before-scroll-bar",hb="with-scroll-bars-hidden",fb="--removed-body-scroll-bar-size";function vs(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}function vb(e,t){var a=g.useState(function(){return{value:e,callback:t,facade:{get current(){return a.value},set current(n){var o=a.value;o!==n&&(a.value=n,a.callback(n,o))}}}})[0];return a.callback=t,a.facade}var kb=typeof window<"u"?g.useLayoutEffect:g.useEffect,xu=new WeakMap;function yb(e,t){var a=vb(null,function(n){return e.forEach(function(o){return vs(o,n)})});return kb(function(){var n=xu.get(a);if(n){var o=new Set(n),i=new Set(e),s=a.current;o.forEach(function(l){i.has(l)||vs(l,null)}),i.forEach(function(l){o.has(l)||vs(l,s)})}xu.set(a,e)},[e]),a}function bb(e){return e}function Pb(e,t){t===void 0&&(t=bb);var a=[],n=!1,o={read:function(){if(n)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return a.length?a[a.length-1]:e},useMedium:function(i){var s=t(i,n);return a.push(s),function(){a=a.filter(function(l){return l!==s})}},assignSyncMedium:function(i){for(n=!0;a.length;){var s=a;a=[],s.forEach(i)}a={push:function(l){return i(l)},filter:function(){return a}}},assignMedium:function(i){n=!0;var s=[];if(a.length){var l=a;a=[],l.forEach(i),s=a}var d=function(){var u=s;s=[],u.forEach(i)},c=function(){return Promise.resolve().then(d)};c(),a={push:function(u){s.push(u),c()},filter:function(u){return s=s.filter(u),a}}}};return o}function Ab(e){e===void 0&&(e={});var t=Pb(null);return t.options=bt({async:!0,ssr:!1},e),t}var Gg=function(e){var t=e.sideCar,a=_g(e,["sideCar"]);if(!t)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var n=t.read();if(!n)throw new Error("Sidecar medium not found");return g.createElement(n,bt({},a))};Gg.isSideCarExport=!0;function Cb(e,t){return e.useMedium(t),Gg}var Wg=Ab(),ks=function(){},Er=g.forwardRef(function(e,t){var a=g.useRef(null),n=g.useState({onScrollCapture:ks,onWheelCapture:ks,onTouchMoveCapture:ks}),o=n[0],i=n[1],s=e.forwardProps,l=e.children,d=e.className,c=e.removeScrollBar,u=e.enabled,p=e.shards,m=e.sideCar,f=e.noRelative,P=e.noIsolation,y=e.inert,A=e.allowPinchZoom,h=e.as,k=h===void 0?"div":h,v=e.gapMode,b=_g(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),z=m,I=yb([a,t]),C=bt(bt({},b),o);return g.createElement(g.Fragment,null,u&&g.createElement(z,{sideCar:Wg,removeScrollBar:c,shards:p,noRelative:f,noIsolation:P,inert:y,setCallbacks:i,allowPinchZoom:!!A,lockRef:a,gapMode:v}),s?g.cloneElement(g.Children.only(l),bt(bt({},C),{ref:I})):g.createElement(k,bt({},C,{className:d,ref:I}),l))});Er.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Er.classNames={fullWidth:Ui,zeroRight:Ki};var xb=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function zb(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=xb();return t&&e.setAttribute("nonce",t),e}function Ib(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function Sb(e){var t=document.head||document.getElementsByTagName("head")[0];t.appendChild(e)}var wb=function(){var e=0,t=null;return{add:function(a){e==0&&(t=zb())&&(Ib(t,a),Sb(t)),e++},remove:function(){e--,!e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}},Tb=function(){var e=wb();return function(t,a){g.useEffect(function(){return e.add(t),function(){e.remove()}},[t&&a])}},Zg=function(){var e=Tb(),t=function(a){var n=a.styles,o=a.dynamic;return e(n,o),null};return t},jb={left:0,top:0,right:0,gap:0},ys=function(e){return parseInt(e||"",10)||0},Mb=function(e){var t=window.getComputedStyle(document.body),a=t[e==="padding"?"paddingLeft":"marginLeft"],n=t[e==="padding"?"paddingTop":"marginTop"],o=t[e==="padding"?"paddingRight":"marginRight"];return[ys(a),ys(n),ys(o)]},Nb=function(e){if(e===void 0&&(e="margin"),typeof window>"u")return jb;var t=Mb(e),a=document.documentElement.clientWidth,n=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,n-a+t[2]-t[0])}},Lb=Zg(),vn="data-scroll-locked",Rb=function(e,t,a,n){var o=e.left,i=e.top,s=e.right,l=e.gap;return a===void 0&&(a="margin"),`
296
- .`.concat(hb,` {
297
- overflow: hidden `).concat(n,`;
298
- padding-right: `).concat(l,"px ").concat(n,`;
299
- }
300
- body[`).concat(vn,`] {
301
- overflow: hidden `).concat(n,`;
302
- overscroll-behavior: contain;
303
- `).concat([t&&"position: relative ".concat(n,";"),a==="margin"&&`
304
- padding-left: `.concat(o,`px;
305
- padding-top: `).concat(i,`px;
306
- padding-right: `).concat(s,`px;
307
- margin-left:0;
308
- margin-top:0;
309
- margin-right: `).concat(l,"px ").concat(n,`;
310
- `),a==="padding"&&"padding-right: ".concat(l,"px ").concat(n,";")].filter(Boolean).join(""),`
311
- }
312
-
313
- .`).concat(Ki,` {
314
- right: `).concat(l,"px ").concat(n,`;
315
- }
316
-
317
- .`).concat(Ui,` {
318
- margin-right: `).concat(l,"px ").concat(n,`;
319
- }
320
-
321
- .`).concat(Ki," .").concat(Ki,` {
322
- right: 0 `).concat(n,`;
323
- }
324
-
325
- .`).concat(Ui," .").concat(Ui,` {
326
- margin-right: 0 `).concat(n,`;
327
- }
328
-
329
- body[`).concat(vn,`] {
330
- `).concat(fb,": ").concat(l,`px;
331
- }
332
- `)},zu=function(){var e=parseInt(document.body.getAttribute(vn)||"0",10);return isFinite(e)?e:0},Db=function(){g.useEffect(function(){return document.body.setAttribute(vn,(zu()+1).toString()),function(){var e=zu()-1;e<=0?document.body.removeAttribute(vn):document.body.setAttribute(vn,e.toString())}},[])},Eb=function(e){var t=e.noRelative,a=e.noImportant,n=e.gapMode,o=n===void 0?"margin":n;Db();var i=g.useMemo(function(){return Nb(o)},[o]);return g.createElement(Lb,{styles:Rb(i,!t,o,a?"":"!important")})},Ml=!1;if(typeof window<"u")try{var pi=Object.defineProperty({},"passive",{get:function(){return Ml=!0,!0}});window.addEventListener("test",pi,pi),window.removeEventListener("test",pi,pi)}catch{Ml=!1}var qa=Ml?{passive:!1}:!1,Ob=function(e){return e.tagName==="TEXTAREA"},Qg=function(e,t){if(!(e instanceof Element))return!1;var a=window.getComputedStyle(e);return a[t]!=="hidden"&&!(a.overflowY===a.overflowX&&!Ob(e)&&a[t]==="visible")},Kb=function(e){return Qg(e,"overflowY")},Ub=function(e){return Qg(e,"overflowX")},Iu=function(e,t){var a=t.ownerDocument,n=t;do{typeof ShadowRoot<"u"&&n instanceof ShadowRoot&&(n=n.host);var o=Yg(e,n);if(o){var i=Xg(e,n),s=i[1],l=i[2];if(s>l)return!0}n=n.parentNode}while(n&&n!==a.body);return!1},Hb=function(e){var t=e.scrollTop,a=e.scrollHeight,n=e.clientHeight;return[t,a,n]},Fb=function(e){var t=e.scrollLeft,a=e.scrollWidth,n=e.clientWidth;return[t,a,n]},Yg=function(e,t){return e==="v"?Kb(t):Ub(t)},Xg=function(e,t){return e==="v"?Hb(t):Fb(t)},Bb=function(e,t){return e==="h"&&t==="rtl"?-1:1},Vb=function(e,t,a,n,o){var i=Bb(e,window.getComputedStyle(t).direction),s=i*n,l=a.target,d=t.contains(l),c=!1,u=s>0,p=0,m=0;do{if(!l)break;var f=Xg(e,l),P=f[0],y=f[1],A=f[2],h=y-A-i*P;(P||h)&&Yg(e,l)&&(p+=h,m+=P);var k=l.parentNode;l=k&&k.nodeType===Node.DOCUMENT_FRAGMENT_NODE?k.host:k}while(!d&&l!==document.body||d&&(t.contains(l)||t===l));return(u&&Math.abs(p)<1||!u&&Math.abs(m)<1)&&(c=!0),c},mi=function(e){return"changedTouches"in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},Su=function(e){return[e.deltaX,e.deltaY]},wu=function(e){return e&&"current"in e?e.current:e},qb=function(e,t){return e[0]===t[0]&&e[1]===t[1]},$b=function(e){return`
333
- .block-interactivity-`.concat(e,` {pointer-events: none;}
334
- .allow-interactivity-`).concat(e,` {pointer-events: all;}
335
- `)},_b=0,$a=[];function Gb(e){var t=g.useRef([]),a=g.useRef([0,0]),n=g.useRef(),o=g.useState(_b++)[0],i=g.useState(Zg)[0],s=g.useRef(e);g.useEffect(function(){s.current=e},[e]),g.useEffect(function(){if(e.inert){document.body.classList.add("block-interactivity-".concat(o));var y=gb([e.lockRef.current],(e.shards||[]).map(wu),!0).filter(Boolean);return y.forEach(function(A){return A.classList.add("allow-interactivity-".concat(o))}),function(){document.body.classList.remove("block-interactivity-".concat(o)),y.forEach(function(A){return A.classList.remove("allow-interactivity-".concat(o))})}}},[e.inert,e.lockRef.current,e.shards]);var l=g.useCallback(function(y,A){if("touches"in y&&y.touches.length===2||y.type==="wheel"&&y.ctrlKey)return!s.current.allowPinchZoom;var h=mi(y),k=a.current,v="deltaX"in y?y.deltaX:k[0]-h[0],b="deltaY"in y?y.deltaY:k[1]-h[1],z,I=y.target,C=Math.abs(v)>Math.abs(b)?"h":"v";if("touches"in y&&C==="h"&&I.type==="range")return!1;var S=window.getSelection(),L=S&&S.anchorNode,T=L?L===I||L.contains(I):!1;if(T)return!1;var M=Iu(C,I);if(!M)return!0;if(M?z=C:(z=C==="v"?"h":"v",M=Iu(C,I)),!M)return!1;if(!n.current&&"changedTouches"in y&&(v||b)&&(n.current=z),!z)return!0;var D=n.current||z;return Vb(D,A,y,D==="h"?v:b)},[]),d=g.useCallback(function(y){var A=y;if(!(!$a.length||$a[$a.length-1]!==i)){var h="deltaY"in A?Su(A):mi(A),k=t.current.filter(function(z){return z.name===A.type&&(z.target===A.target||A.target===z.shadowParent)&&qb(z.delta,h)})[0];if(k&&k.should){A.cancelable&&A.preventDefault();return}if(!k){var v=(s.current.shards||[]).map(wu).filter(Boolean).filter(function(z){return z.contains(A.target)}),b=v.length>0?l(A,v[0]):!s.current.noIsolation;b&&A.cancelable&&A.preventDefault()}}},[]),c=g.useCallback(function(y,A,h,k){var v={name:y,delta:A,target:h,should:k,shadowParent:Wb(h)};t.current.push(v),setTimeout(function(){t.current=t.current.filter(function(b){return b!==v})},1)},[]),u=g.useCallback(function(y){a.current=mi(y),n.current=void 0},[]),p=g.useCallback(function(y){c(y.type,Su(y),y.target,l(y,e.lockRef.current))},[]),m=g.useCallback(function(y){c(y.type,mi(y),y.target,l(y,e.lockRef.current))},[]);g.useEffect(function(){return $a.push(i),e.setCallbacks({onScrollCapture:p,onWheelCapture:p,onTouchMoveCapture:m}),document.addEventListener("wheel",d,qa),document.addEventListener("touchmove",d,qa),document.addEventListener("touchstart",u,qa),function(){$a=$a.filter(function(y){return y!==i}),document.removeEventListener("wheel",d,qa),document.removeEventListener("touchmove",d,qa),document.removeEventListener("touchstart",u,qa)}},[]);var f=e.removeScrollBar,P=e.inert;return g.createElement(g.Fragment,null,P?g.createElement(i,{styles:$b(o)}):null,f?g.createElement(Eb,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function Wb(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}const Zb=Cb(Wg,Gb);var Jg=g.forwardRef(function(e,t){return g.createElement(Er,bt({},e,{ref:t,sideCar:Zb}))});Jg.classNames=Er.classNames;var Qb=function(e){if(typeof document>"u")return null;var t=Array.isArray(e)?e[0]:e;return t.ownerDocument.body},_a=new WeakMap,gi=new WeakMap,hi={},bs=0,eh=function(e){return e&&(e.host||eh(e.parentNode))},Yb=function(e,t){return t.map(function(a){if(e.contains(a))return a;var n=eh(a);return n&&e.contains(n)?n:(console.error("aria-hidden",a,"in not contained inside",e,". Doing nothing"),null)}).filter(function(a){return!!a})},Xb=function(e,t,a,n){var o=Yb(t,Array.isArray(e)?e:[e]);hi[a]||(hi[a]=new WeakMap);var i=hi[a],s=[],l=new Set,d=new Set(o),c=function(p){!p||l.has(p)||(l.add(p),c(p.parentNode))};o.forEach(c);var u=function(p){!p||d.has(p)||Array.prototype.forEach.call(p.children,function(m){if(l.has(m))u(m);else try{var f=m.getAttribute(n),P=f!==null&&f!=="false",y=(_a.get(m)||0)+1,A=(i.get(m)||0)+1;_a.set(m,y),i.set(m,A),s.push(m),y===1&&P&&gi.set(m,!0),A===1&&m.setAttribute(a,"true"),P||m.setAttribute(n,"true")}catch(h){console.error("aria-hidden: cannot operate on ",m,h)}})};return u(t),l.clear(),bs++,function(){s.forEach(function(p){var m=_a.get(p)-1,f=i.get(p)-1;_a.set(p,m),i.set(p,f),m||(gi.has(p)||p.removeAttribute(n),gi.delete(p)),f||p.removeAttribute(a)}),bs--,bs||(_a=new WeakMap,_a=new WeakMap,gi=new WeakMap,hi={})}},Jb=function(e,t,a){a===void 0&&(a="data-aria-hidden");var n=Array.from(Array.isArray(e)?e:[e]),o=Qb(e);return o?(n.push.apply(n,Array.from(o.querySelectorAll("[aria-live], script"))),Xb(n,o,a,"aria-hidden")):function(){return null}},Or="Dialog",[th]=wy(Or),[eP,gt]=th(Or),ah=e=>{const{__scopeDialog:t,children:a,open:n,defaultOpen:o,onOpenChange:i,modal:s=!0}=e,l=g.useRef(null),d=g.useRef(null),[c,u]=Ly({prop:n,defaultProp:o??!1,onChange:i,caller:Or});return r.jsx(eP,{scope:t,triggerRef:l,contentRef:d,contentId:gs(),titleId:gs(),descriptionId:gs(),open:c,onOpenChange:u,onOpenToggle:g.useCallback(()=>u(p=>!p),[u]),modal:s,children:a})};ah.displayName=Or;var nh="DialogTrigger",tP=g.forwardRef((e,t)=>{const{__scopeDialog:a,...n}=e,o=gt(nh,a),i=Ua(t,o.triggerRef);return r.jsx(Ht.button,{type:"button","aria-haspopup":"dialog","aria-expanded":o.open,"aria-controls":o.open?o.contentId:void 0,"data-state":Fd(o.open),...n,ref:i,onClick:la(e.onClick,o.onOpenToggle)})});tP.displayName=nh;var Ud="DialogPortal",[aP,oh]=th(Ud,{forceMount:void 0}),ih=e=>{const{__scopeDialog:t,forceMount:a,children:n,container:o}=e,i=gt(Ud,t);return r.jsx(aP,{scope:t,forceMount:a,children:g.Children.map(n,s=>r.jsx(Dr,{present:a||i.open,children:r.jsx($g,{asChild:!0,container:o,children:s})}))})};ih.displayName=Ud;var ur="DialogOverlay",rh=g.forwardRef((e,t)=>{const a=oh(ur,e.__scopeDialog),{forceMount:n=a.forceMount,...o}=e,i=gt(ur,e.__scopeDialog);return i.modal?r.jsx(Dr,{present:n||i.open,children:r.jsx(oP,{...o,ref:t})}):null});rh.displayName=ur;var nP=Ug("DialogOverlay.RemoveScroll"),oP=g.forwardRef((e,t)=>{const{__scopeDialog:a,...n}=e,o=gt(ur,a);return r.jsx(Jg,{as:nP,allowPinchZoom:!0,shards:[o.contentRef],children:r.jsx(Ht.div,{"data-state":Fd(o.open),...n,ref:t,style:{pointerEvents:"auto",...n.style}})})}),Ea="DialogContent",sh=g.forwardRef((e,t)=>{const a=oh(Ea,e.__scopeDialog),{forceMount:n=a.forceMount,...o}=e,i=gt(Ea,e.__scopeDialog);return r.jsx(Dr,{present:n||i.open,children:i.modal?r.jsx(iP,{...o,ref:t}):r.jsx(rP,{...o,ref:t})})});sh.displayName=Ea;var iP=g.forwardRef((e,t)=>{const a=gt(Ea,e.__scopeDialog),n=g.useRef(null),o=Ua(t,a.contentRef,n);return g.useEffect(()=>{const i=n.current;if(i)return Jb(i)},[]),r.jsx(lh,{...e,ref:o,trapFocus:a.open,disableOutsidePointerEvents:a.open,onCloseAutoFocus:la(e.onCloseAutoFocus,i=>{i.preventDefault(),a.triggerRef.current?.focus()}),onPointerDownOutside:la(e.onPointerDownOutside,i=>{const s=i.detail.originalEvent,l=s.button===0&&s.ctrlKey===!0;(s.button===2||l)&&i.preventDefault()}),onFocusOutside:la(e.onFocusOutside,i=>i.preventDefault())})}),rP=g.forwardRef((e,t)=>{const a=gt(Ea,e.__scopeDialog),n=g.useRef(!1),o=g.useRef(!1);return r.jsx(lh,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:i=>{e.onCloseAutoFocus?.(i),i.defaultPrevented||(n.current||a.triggerRef.current?.focus(),i.preventDefault()),n.current=!1,o.current=!1},onInteractOutside:i=>{e.onInteractOutside?.(i),i.defaultPrevented||(n.current=!0,i.detail.originalEvent.type==="pointerdown"&&(o.current=!0));const s=i.target;a.triggerRef.current?.contains(s)&&i.preventDefault(),i.detail.originalEvent.type==="focusin"&&o.current&&i.preventDefault()}})}),lh=g.forwardRef((e,t)=>{const{__scopeDialog:a,trapFocus:n,onOpenAutoFocus:o,onCloseAutoFocus:i,...s}=e,l=gt(Ea,a),d=g.useRef(null),c=Ua(t,d);return mb(),r.jsxs(r.Fragment,{children:[r.jsx(Vg,{asChild:!0,loop:!0,trapped:n,onMountAutoFocus:o,onUnmountAutoFocus:i,children:r.jsx(Fg,{role:"dialog",id:l.contentId,"aria-describedby":l.descriptionId,"aria-labelledby":l.titleId,"data-state":Fd(l.open),...s,ref:c,onDismiss:()=>l.onOpenChange(!1)})}),r.jsxs(r.Fragment,{children:[r.jsx(sP,{titleId:l.titleId}),r.jsx(dP,{contentRef:d,descriptionId:l.descriptionId})]})]})}),Hd="DialogTitle",dh=g.forwardRef((e,t)=>{const{__scopeDialog:a,...n}=e,o=gt(Hd,a);return r.jsx(Ht.h2,{id:o.titleId,...n,ref:t})});dh.displayName=Hd;var ch="DialogDescription",uh=g.forwardRef((e,t)=>{const{__scopeDialog:a,...n}=e,o=gt(ch,a);return r.jsx(Ht.p,{id:o.descriptionId,...n,ref:t})});uh.displayName=ch;var ph="DialogClose",mh=g.forwardRef((e,t)=>{const{__scopeDialog:a,...n}=e,o=gt(ph,a);return r.jsx(Ht.button,{type:"button",...n,ref:t,onClick:la(e.onClick,()=>o.onOpenChange(!1))})});mh.displayName=ph;function Fd(e){return e?"open":"closed"}var gh="DialogTitleWarning",[mL,hh]=Sy(gh,{contentName:Ea,titleName:Hd,docsSlug:"dialog"}),sP=({titleId:e})=>{const t=hh(gh),a=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
336
-
337
- If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
338
-
339
- For more information, see https://radix-ui.com/primitives/docs/components/${t.docsSlug}`;return g.useEffect(()=>{e&&(document.getElementById(e)||console.error(a))},[a,e]),null},lP="DialogDescriptionWarning",dP=({contentRef:e,descriptionId:t})=>{const n=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${hh(lP).contentName}}.`;return g.useEffect(()=>{const o=e.current?.getAttribute("aria-describedby");t&&o&&(document.getElementById(t)||console.warn(n))},[n,e,t]),null},cP=ah,uP=ih,fh=rh,vh=sh,kh=dh,yh=uh,pP=mh;const Ft=cP,mP=uP,bh=g.forwardRef(({className:e,...t},a)=>r.jsx(fh,{ref:a,className:G("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",e),...t}));bh.displayName=fh.displayName;const xt=g.forwardRef(({className:e,children:t,hideCloseButton:a,...n},o)=>r.jsxs(mP,{children:[r.jsx(bh,{}),r.jsxs(vh,{ref:o,className:G("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-surface-0 wallpaper-solid p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",e),...n,children:[t,!a&&r.jsxs(pP,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-surface-1 data-[state=open]:text-muted-foreground",children:[r.jsx(Da,{className:"h-4 w-4"}),r.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));xt.displayName=vh.displayName;const zt=({className:e,...t})=>r.jsx("div",{className:G("flex flex-col space-y-1.5 text-center sm:text-left",e),...t});zt.displayName="DialogHeader";const Bt=({className:e,...t})=>r.jsx("div",{className:G("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",e),...t});Bt.displayName="DialogFooter";const It=g.forwardRef(({className:e,...t},a)=>r.jsx(kh,{ref:a,className:G("text-lg font-semibold leading-none tracking-tight text-foreground",e),...t}));It.displayName=kh.displayName;const Vt=g.forwardRef(({className:e,...t},a)=>r.jsx(yh,{ref:a,className:G("text-sm text-muted-foreground",e),...t}));Vt.displayName=yh.displayName;function Kr({open:e,onOpenChange:t,title:a,description:n,confirmLabel:o="确认",cancelLabel:i="取消",variant:s="destructive",onConfirm:l}){const d=()=>{t(!1),l()};return r.jsx(Ft,{open:e,onOpenChange:t,children:r.jsxs(xt,{className:"max-w-sm",hideCloseButton:!0,"data-testid":"dialog-confirm",children:[r.jsxs(zt,{children:[r.jsx(It,{children:a}),n?r.jsx(Vt,{children:n}):null]}),r.jsxs(Bt,{className:"gap-2 sm:gap-0",children:[r.jsx("button",{onClick:()=>t(!1),"data-testid":"dialog-confirm-cancel-btn",className:"px-4 py-2 text-sm rounded-lg border border-border text-foreground hover:bg-surface-1 transition-colors",children:i}),r.jsx("button",{onClick:d,"data-testid":"dialog-confirm-ok-btn","data-variant":s,className:G("px-4 py-2 text-sm rounded-lg transition-colors",s==="destructive"?"bg-destructive text-destructive-foreground hover:bg-destructive/90":"bg-primary text-primary-foreground hover:bg-primary/90"),children:o})]})]})})}const gP={default:"h-8 py-1.5",compact:"h-7 py-1"},V=g.forwardRef(({className:e,type:t="text",density:a="default",...n},o)=>r.jsx("input",{type:t,"data-density":a,className:G("flex w-full rounded-md border border-input bg-surface-1 px-3 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",gP[a],e),ref:o,...n}));V.displayName="Input";const hP={unconfigured:{icon:xl,className:"text-muted-foreground",labelKey:"accounts.status.unconfigured"},authorized:{icon:wo,className:"text-success",labelKey:"accounts.status.authorized"},configured:{icon:wo,className:"text-primary",labelKey:"accounts.status.configured"},expired:{icon:Nk,className:"text-warning",labelKey:"accounts.status.expired"},error:{icon:Pg,className:"text-destructive",labelKey:"accounts.status.error"}};function Bd({status:e}){const t=$(),{icon:a,className:n,labelKey:o}=hP[e??"unconfigured"];return r.jsxs("div",{className:G("flex shrink-0 items-center gap-1.5 text-sm",n),children:[r.jsx(a,{className:"h-4 w-4","aria-hidden":"true"}),r.jsx("span",{children:t(o)})]})}function fi({label:e,value:t}){return r.jsxs("div",{className:"flex justify-between gap-3",children:[r.jsx("span",{className:"text-muted-foreground",children:e}),r.jsx("span",{className:"truncate text-foreground",children:t})]})}function fP(e){return e.status==="expired"?!0:e.expiresAt?new Date(e.expiresAt).getTime()<Date.now():!1}function Ph({accounts:e,busy:t,onSetActive:a,onRemove:n,onRename:o,onRefreshActive:i}){const s=$(),[l,d]=g.useState(null),[c,u]=g.useState(null),[p,m]=g.useState({}),[f,P]=g.useState(null),[y,A]=g.useState(null);if(e.length===0)return null;const h=async v=>{if(!o)return;const b=(p[v.id]??v.label??"").trim();if(b!==(v.label??"").trim()){P(v.id),A(null);try{const z=await o(v.id,b);z.success||A({kind:"error",text:z.message??s("accounts.rename.failed")})}finally{P(null)}}},k=async v=>{if(i){P(v.id),A(null);try{const b=await i();b.ok||A({kind:"error",text:b.message??s("accounts.refresh.failed")})}finally{P(null)}}};return r.jsxs("div",{className:"space-y-2",children:[r.jsx("div",{className:"text-sm font-medium text-foreground",children:s("accounts.list.title")}),r.jsx("ul",{className:"space-y-2",children:e.map(v=>{const b=l===v.id,z=(v.label??"").trim()||v.id,I=p[v.id]??v.label??"",C=v.expiresAt?new Date(v.expiresAt):null,S=v.lastRefreshedAt?new Date(v.lastRefreshedAt):null,L=f===v.id,T=!!(i&&v.isActive&&fP(v));return r.jsxs("li",{className:G("rounded-md border px-3 py-2",v.isActive?"border-primary/40 bg-surface-2/60":"border-border/50 bg-surface-1/50"),children:[r.jsxs("div",{className:"flex items-center justify-between gap-3",children:[r.jsxs("button",{type:"button",className:"flex min-w-0 flex-1 items-center gap-2 text-left",onClick:()=>d(b?null:v.id),"aria-expanded":b,children:[b?r.jsx(ga,{className:"h-4 w-4 shrink-0 text-muted-foreground"}):r.jsx(Nd,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),r.jsx("span",{className:"min-w-0 flex-1 truncate text-sm text-foreground",children:z}),r.jsx(Bd,{status:v.status}),v.isActive?r.jsx("span",{className:"shrink-0 rounded bg-primary/15 px-1.5 py-0.5 text-xs text-primary",children:s("accounts.list.active")}):null]}),r.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[T?r.jsxs(R,{size:"sm",variant:"outline",disabled:t||L,onClick:()=>void k(v),title:s("accounts.actions.refresh"),children:[r.jsx(Fo,{className:G("mr-1 h-3.5 w-3.5",L&&"animate-spin")}),s("accounts.actions.refresh")]}):null,v.isActive?null:r.jsxs(R,{size:"sm",variant:"outline",disabled:t||L,onClick:()=>a(v.id),children:[r.jsx(Ln,{className:"mr-1 h-3.5 w-3.5"}),s("accounts.list.setActive")]}),r.jsx(R,{size:"icon",variant:"outline",className:"h-7 w-7 text-destructive hover:text-destructive",disabled:t||L,onClick:()=>u(v),"aria-label":s("accounts.list.remove"),children:r.jsx(In,{className:"h-3.5 w-3.5"})})]})]}),v.syncWarning?r.jsxs("p",{className:"mt-1.5 flex items-start gap-1.5 text-xs text-amber-600 dark:text-amber-500",children:[r.jsx(Kd,{className:"mt-0.5 h-3.5 w-3.5 shrink-0"}),r.jsx("span",{children:s(`accounts.syncWarning.${v.syncWarning}`)})]}):null,b?r.jsxs("div",{className:"mt-2 space-y-2 border-t border-border/40 pt-2",children:[o?r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:s("accounts.detail.label")}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(V,{density:"compact",value:I,placeholder:s("accounts.detail.labelPlaceholder"),onChange:M=>m(D=>({...D,[v.id]:M.target.value})),onKeyDown:M=>{M.key==="Enter"&&(M.preventDefault(),h(v))},disabled:L}),r.jsx(R,{size:"sm",variant:"outline",disabled:L||I.trim()===(v.label??"").trim(),onClick:()=>void h(v),"aria-label":s("accounts.detail.saveLabel"),children:r.jsx(Uk,{className:"h-3.5 w-3.5"})})]})]}):null,r.jsxs("div",{className:"grid gap-1 text-xs sm:grid-cols-2",children:[v.authMethod?r.jsx(fi,{label:s("accounts.detail.authMethod"),value:s(`accounts.authMethod.${v.authMethod}`)}):null,v.subscriptionLevel?r.jsx(fi,{label:s("accounts.detail.subscriptionLevel"),value:v.subscriptionLevel}):null,C?r.jsx(fi,{label:s("accounts.detail.expiresAt"),value:C.toLocaleString()}):null,S?r.jsx(fi,{label:s("accounts.detail.lastRefreshed"),value:S.toLocaleString()}):null]})]}):null]},v.id)})}),y?r.jsx("p",{className:G("text-xs",y.kind==="error"?"text-destructive":"text-muted-foreground"),children:y.text}):null,r.jsx(Kr,{open:c!==null,onOpenChange:v=>{v||u(null)},title:s("accounts.list.removeConfirmTitle"),description:c?s("accounts.list.removeConfirmDesc",{name:c.label||c.id}):void 0,confirmLabel:s("accounts.list.remove"),cancelLabel:s("common.cancel"),variant:"destructive",onConfirm:()=>{c&&n(c.id),u(null)}})]})}const Tu=2e3;function vP({authUrl:e,sessionId:t,onPoll:a,onDone:n,onCancel:o}){const i=$(),[s,l]=g.useState("pending"),[d,c]=g.useState(null);return g.useEffect(()=>{if(!t)return;let u=!1,p;l("pending"),c(null);const m=async()=>{if(u)return;let f;try{f=await a(t)}catch{f={state:"error",message:i("accounts.codexOauth.failed")}}if(!u){if(f.state==="done"){n();return}if(f.state==="error"){l("error"),c(f.message??i("accounts.codexOauth.failed"));return}p=setTimeout(()=>void m(),Tu)}};return p=setTimeout(()=>void m(),Tu),()=>{u=!0,clearTimeout(p)}},[t,a,n,i]),r.jsxs("div",{className:"space-y-3 rounded-md bg-surface-2 p-4",children:[r.jsx("p",{className:"text-sm text-muted-foreground",children:i("accounts.codexOauth.description")}),r.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[r.jsxs("a",{href:e,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-2 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",children:[r.jsx(Ho,{className:"h-4 w-4"}),i("accounts.oauth.openPage")]}),r.jsx(R,{variant:"outline",size:"sm",onClick:o,children:i("common.cancel")})]}),s==="pending"?r.jsxs("p",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[r.jsx(La,{className:"h-3.5 w-3.5 animate-spin"}),i("accounts.codexOauth.waiting")]}):null,s==="error"&&d?r.jsx("p",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:d}):null]})}const Sn=g.forwardRef(({revealed:e,onRevealedChange:t,className:a,...n},o)=>{const[i,s]=g.useState(!1),l=e!==void 0,d=l?e:i,c=()=>{const u=!d;l||s(u),t?.(u)};return r.jsxs("div",{className:"relative",children:[r.jsx(V,{ref:o,type:d?"text":"password",className:G("pr-10",a),...n}),r.jsx("button",{type:"button",className:"absolute inset-y-0 right-0 flex items-center pr-3 text-muted-foreground hover:text-foreground transition-colors",onClick:c,tabIndex:-1,"aria-label":d?"Hide":"Show",children:d?r.jsx(xg,{className:"h-4 w-4"}):r.jsx(zg,{className:"h-4 w-4"})})]})});Sn.displayName="RevealableInput";const kP=["Free","Pro","Max"];function yP({open:e,onOpenChange:t,provider:a,busy:n,error:o,onSubmit:i}){const s=$(),[l,d]=g.useState(""),[c,u]=g.useState(""),[p,m]=g.useState(""),[f,P]=g.useState("Free");g.useEffect(()=>{e&&(d(""),u(""),m(""),P("Free"))},[e]);const y=async()=>{if(l.trim().length===0)return;const h={};a==="claude"&&(h.subscriptionLevel=f),a==="gemini"&&c.trim()&&(h.refreshToken=c.trim()),(await i(l.trim(),p.trim()||void 0,h)).success&&t(!1)},A=kP.map(h=>({value:h,label:h}));return r.jsx(Ft,{open:e,onOpenChange:t,children:r.jsxs(xt,{className:"max-w-md",children:[r.jsxs(zt,{children:[r.jsx(It,{children:s("accounts.manual.title")}),r.jsx(Vt,{children:s("accounts.manual.description")})]}),r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-xs font-medium text-muted-foreground",children:[s("accounts.detail.label")," ",r.jsxs("span",{className:"font-normal text-muted-foreground/80",children:["(",s("common.optional"),")"]})]}),r.jsx(V,{density:"compact",value:p,placeholder:s("accounts.detail.labelPlaceholder"),onChange:h=>m(h.target.value),autoComplete:"off"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:s("accounts.field.accessToken")}),r.jsx(Sn,{value:l,placeholder:s("accounts.manual.accessTokenPlaceholder"),onChange:h=>d(h.target.value),autoComplete:"off",autoFocus:!0})]}),a==="claude"?r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:s("accounts.write.subscriptionLevel")}),r.jsx(Lt,{value:f,options:A,onChange:h=>P(h),size:"sm"})]}):null,a==="gemini"?r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-xs font-medium text-muted-foreground",children:[s("accounts.field.refreshToken")," ",r.jsxs("span",{className:"font-normal text-muted-foreground/80",children:["(",s("common.optional"),")"]})]}),r.jsx(Sn,{value:c,placeholder:s("accounts.manual.refreshTokenPlaceholder"),onChange:h=>u(h.target.value),autoComplete:"off"})]}):null,r.jsx("p",{className:"rounded-md bg-surface-2 px-3 py-2 text-xs text-muted-foreground",children:s("accounts.manual.hint")}),o?r.jsx("p",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:o}):null]}),r.jsxs(Bt,{className:"gap-2 sm:gap-0",children:[r.jsx(R,{variant:"secondary",onClick:()=>t(!1),disabled:n,children:s("common.cancel")}),r.jsx(R,{variant:"default",onClick:()=>void y(),disabled:n||l.trim().length===0,children:s("common.save")})]})]})})}const ju=["step1","step2","step3","step4"];function bP({authUrl:e,authCode:t,accountLabel:a,isExchanging:n,error:o,onAccountLabelChange:i,onAuthCodeChange:s,onExchange:l,onCancel:d}){const c=$(),[u,p]=g.useState(!1),m=g.useCallback(()=>{navigator.clipboard?.writeText(e).then(()=>{p(!0),window.setTimeout(()=>p(!1),2e3)})},[e]);return r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"space-y-1.5 rounded-md bg-surface-2 p-4",children:[r.jsxs("label",{className:"text-sm font-medium text-foreground",children:[c("accounts.detail.label")," ",r.jsxs("span",{className:"font-normal text-muted-foreground/80",children:["(",c("common.optional"),")"]})]}),r.jsx(V,{value:a,placeholder:c("accounts.detail.labelPlaceholder"),onChange:f=>i(f.target.value),autoComplete:"off"})]}),ju.map((f,P)=>r.jsxs("div",{className:"space-y-2 rounded-md bg-surface-2 p-4",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground",children:P+1}),r.jsx("span",{className:"font-medium text-foreground",children:c(`accounts.oauthFlow.${f}.title`)})]}),r.jsx("p",{className:"pl-8 text-sm text-muted-foreground",children:c(`accounts.oauthFlow.${f}.desc`)}),P===0?r.jsx("div",{className:"pl-8",children:r.jsxs("a",{href:e,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-2 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",children:[r.jsx(Ho,{className:"h-4 w-4"}),c("accounts.oauth.openPage")]})}):null,P===ju.length-1?r.jsx("div",{className:"pl-8",children:r.jsx("input",{type:"text",value:t,onChange:y=>s(y.target.value),placeholder:c("accounts.oauth.codePlaceholder"),autoComplete:"off",className:"w-full rounded-md border border-border bg-surface-1 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50"})}):null]},f)),o?r.jsx("p",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:o}):null,r.jsxs("details",{className:"rounded-md bg-surface-1/50 p-3",children:[r.jsx("summary",{className:"cursor-pointer text-sm text-muted-foreground",children:c("accounts.oauthFlow.showUrl")}),r.jsxs("div",{className:"mt-2 flex items-center gap-2",children:[r.jsx("code",{className:"flex-1 truncate rounded bg-surface-1 px-2 py-1 text-xs",children:e}),r.jsx(R,{variant:"ghost",size:"sm",className:"shrink-0",onClick:m,children:u?r.jsx(Ln,{className:"h-4 w-4"}):r.jsx(Lr,{className:"h-4 w-4"})})]})]}),r.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[r.jsxs(R,{className:"flex-1",onClick:l,disabled:t.trim().length===0||n,children:[n?r.jsx(Fo,{className:"mr-2 h-4 w-4 animate-spin"}):r.jsx(wo,{className:"mr-2 h-4 w-4"}),c("accounts.oauthFlow.authorize")]}),r.jsx(R,{variant:"outline",onClick:d,disabled:n,children:c("common.cancel")})]})]})}function PP(e,t){const a=t.find(n=>n.isActive)??t[0];return a?a.status:e.credentialStatus.ok?"configured":"unconfigured"}function AP(e,t,a){switch(e){case"claude":return{providerId:"claude",input:{authMethod:"manual",status:"configured",accessToken:t,subscriptionLevel:a?.subscriptionLevel}};case"gemini":return{providerId:"gemini",input:{authMethod:"manual",status:"configured",accessToken:t,refreshToken:a?.refreshToken}};case"codex":return{providerId:"codex",input:{authMethod:"manual",status:"configured",accessToken:t}}}}function CP({entry:e,accounts:t,accountsApi:a}){const n=$(),o=e.providerId,i=o==="codex",{busy:s,data:l,appendTokens:d,setActive:c,removeAccount:u,renameAccount:p,refreshProvider:m,startOAuth:f,completeOAuth:P,pollCodexOAuth:y,importExternalCli:A,refresh:h}=a,[k,v]=g.useState("oauth"),[b,z]=g.useState(null),[I,C]=g.useState(""),[S,L]=g.useState(""),[T,M]=g.useState(!1),[D,Q]=g.useState(!1),[W,J]=g.useState(null),ye=PP(e,t),ve=t.length===0&&(o==="claude"||o==="codex")&&!!l.externalCli?.[o],w=async()=>{if(o==="gemini")return;J(null);const ne=await A(o);ne.success||J(ne.message??n("accounts.errors.requestFailed"))},E=async()=>{J(null);const ne=await f(o);ne?(z(ne),C(""),L("")):J(n("accounts.errors.requestFailed"))},U=async()=>{if(!(!b||I.trim().length===0)){M(!0);try{const ne=await P(o,{sessionId:b.sessionId,code:I.trim(),label:S.trim()||void 0});ne.success?(z(null),C(""),L(""),J(null)):J(ne.message??n("accounts.errors.requestFailed"))}finally{M(!1)}}},Z=()=>{z(null),C(""),L(""),J(null)},ae=async(ne,Pe,Ge)=>{const ht=await d(AP(o,ne,Ge),Pe);return ht.success||J(ht.message??n("accounts.errors.requestFailed")),ht},_e=[{value:"oauth",label:n("accounts.authMethod.oauth")},{value:"manual",label:n("accounts.authMethod.manual")}],xe=t.length>0?n("accounts.accounts.addAccount"):n(k==="manual"?"accounts.actions.enterToken":"accounts.actions.authorize");return r.jsxs("div",{className:"space-y-4 rounded-lg border border-border bg-surface-1/50 p-4",children:[r.jsxs("div",{className:"flex items-start justify-between gap-3",children:[r.jsxs("div",{className:"flex items-center gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Sg,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{className:"min-w-0",children:[r.jsx("h3",{className:"font-medium text-foreground",children:n(`accounts.provider.${o}.title`)}),r.jsx("p",{className:"text-sm text-muted-foreground",children:n(`accounts.provider.${o}.description`)})]})]}),r.jsx(Bd,{status:ye})]}),W&&!b?r.jsx("div",{className:"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive",children:W}):null,r.jsx(Ph,{accounts:t,busy:s,onSetActive:ne=>void c(o,ne),onRemove:ne=>void u(o,ne),onRename:(ne,Pe)=>p(o,ne,Pe),onRefreshActive:()=>m(o)}),b&&i?r.jsx(vP,{authUrl:b.authUrl,sessionId:b.sessionId,onPoll:y,onDone:()=>{z(null),h()},onCancel:Z}):b?r.jsx(bP,{authUrl:b.authUrl,authCode:I,accountLabel:S,isExchanging:T,error:W,onAccountLabelChange:L,onAuthCodeChange:C,onExchange:()=>void U(),onCancel:Z}):r.jsxs(r.Fragment,{children:[ve?r.jsxs("div",{className:"space-y-2 rounded-md border border-border/60 bg-surface-2/40 p-3",children:[r.jsx("p",{className:"text-sm text-foreground",children:n("accounts.importExternal.detected",{name:n(`accounts.provider.${o}.title`)})}),r.jsx("p",{className:"text-xs text-muted-foreground",children:n("accounts.importExternal.hint")}),r.jsxs(R,{className:"w-full",variant:"outline",disabled:s,onClick:()=>void w(),children:[r.jsx(Rk,{className:"mr-2 h-4 w-4"}),n("accounts.importExternal.button")]})]}):null,r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium text-foreground",children:n("accounts.authMethodLabel")}),r.jsx(Lt,{value:k,options:_e,onChange:ne=>v(ne)}),r.jsx("p",{className:"text-xs text-muted-foreground",children:n(`accounts.authMethodDesc.${k}`)})]}),r.jsxs(R,{className:"w-full",disabled:s,onClick:()=>{J(null),k==="manual"?Q(!0):E()},children:[k==="manual"?r.jsx(Ek,{className:"mr-2 h-4 w-4"}):r.jsx(Ho,{className:"mr-2 h-4 w-4"}),xe]})]}),r.jsx(yP,{open:D,onOpenChange:Q,provider:o,busy:s,error:W,onSubmit:ae})]})}function xP(e,t){const a=t.find(n=>n.isActive)??t[0];return a?a.status:e.credentialStatus.ok?"configured":"unconfigured"}function zP({entry:e,accounts:t,accountsApi:a}){const n=$(),{busy:o,appendTokens:i,setActive:s,removeAccount:l,renameAccount:d}=a,[c,u]=g.useState(!1),[p,m]=g.useState(""),[f,P]=g.useState(""),[y,A]=g.useState(""),[h,k]=g.useState(""),[v,b]=g.useState(null),z=xP(e,t),I=()=>{m(""),P(""),A(""),k(""),b(null)},C=async()=>{if(p.trim().length===0){b(n("accounts.openCodeGo.apiKeyRequired"));return}b(null);const S=await i({providerId:"opencodego",input:{authMethod:"manual",status:"configured",apiKey:p.trim(),baseUrl:y.trim()||void 0,zenBaseUrl:h.trim()||void 0}},f.trim()||void 0);S.success?(I(),u(!1)):b(S.message??n("accounts.errors.requestFailed"))};return r.jsxs("div",{className:"space-y-4 rounded-lg border border-border bg-surface-1/50 p-4",children:[r.jsxs("div",{className:"flex items-start justify-between gap-3",children:[r.jsxs("div",{className:"flex items-center gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Dd,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{className:"min-w-0",children:[r.jsx("h3",{className:"font-medium text-foreground",children:n("accounts.provider.opencodego.title")}),r.jsx("p",{className:"text-sm text-muted-foreground",children:n("accounts.provider.opencodego.description")})]})]}),r.jsx(Bd,{status:z})]}),r.jsx(Ph,{accounts:t,busy:o,onSetActive:S=>void s("opencodego",S),onRemove:S=>void l("opencodego",S),onRename:(S,L)=>d("opencodego",S,L)}),c?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:n("accounts.field.apiKey")}),r.jsx(Sn,{value:p,placeholder:n("accounts.openCodeGo.apiKeyPlaceholder"),onChange:S=>m(S.target.value),autoComplete:"off"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-xs font-medium text-muted-foreground",children:[n("accounts.detail.label")," ",r.jsxs("span",{className:"font-normal text-muted-foreground/80",children:["(",n("common.optional"),")"]})]}),r.jsx(V,{density:"compact",value:f,placeholder:n("accounts.detail.labelPlaceholder"),onChange:S=>P(S.target.value),autoComplete:"off"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:n("accounts.field.baseUrl")}),r.jsx(V,{density:"compact",value:y,placeholder:n("accounts.openCodeGo.baseUrlPlaceholder"),onChange:S=>A(S.target.value),autoComplete:"off"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:n("accounts.field.zenBaseUrl")}),r.jsx(V,{density:"compact",value:h,placeholder:n("accounts.openCodeGo.zenBaseUrlPlaceholder"),onChange:S=>k(S.target.value),autoComplete:"off"})]}),v?r.jsx("p",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:v}):null,r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsxs(R,{className:"flex-1",disabled:o||p.trim().length===0,onClick:()=>void C(),children:[r.jsx(Ra,{className:"mr-2 h-4 w-4"}),n("accounts.accounts.addAccount")]}),r.jsx(R,{variant:"outline",disabled:o,onClick:()=>{I(),u(!1)},children:n("common.cancel")})]})]}):r.jsxs(R,{className:"w-full",disabled:o,onClick:()=>{b(null),u(!0)},children:[r.jsx(Ra,{className:"mr-2 h-4 w-4"}),n("accounts.accounts.addAccount")]})]})}const _=e=>typeof e=="string",qn=()=>{let e,t;const a=new Promise((n,o)=>{e=n,t=o});return a.resolve=e,a.reject=t,a},Mu=e=>e==null?"":""+e,IP=(e,t,a)=>{e.forEach(n=>{t[n]&&(a[n]=t[n])})},SP=/###/g,Nu=e=>e&&e.indexOf("###")>-1?e.replace(SP,"."):e,Lu=e=>!e||_(e),co=(e,t,a)=>{const n=_(t)?t.split("."):t;let o=0;for(;o<n.length-1;){if(Lu(e))return{};const i=Nu(n[o]);!e[i]&&a&&(e[i]=new a),Object.prototype.hasOwnProperty.call(e,i)?e=e[i]:e={},++o}return Lu(e)?{}:{obj:e,k:Nu(n[o])}},Ru=(e,t,a)=>{const{obj:n,k:o}=co(e,t,Object);if(n!==void 0||t.length===1){n[o]=a;return}let i=t[t.length-1],s=t.slice(0,t.length-1),l=co(e,s,Object);for(;l.obj===void 0&&s.length;)i=`${s[s.length-1]}.${i}`,s=s.slice(0,s.length-1),l=co(e,s,Object),l&&l.obj&&typeof l.obj[`${l.k}.${i}`]<"u"&&(l.obj=void 0);l.obj[`${l.k}.${i}`]=a},wP=(e,t,a,n)=>{const{obj:o,k:i}=co(e,t,Object);o[i]=o[i]||[],o[i].push(a)},pr=(e,t)=>{const{obj:a,k:n}=co(e,t);if(a)return a[n]},TP=(e,t,a)=>{const n=pr(e,a);return n!==void 0?n:pr(t,a)},Ah=(e,t,a)=>{for(const n in t)n!=="__proto__"&&n!=="constructor"&&(n in e?_(e[n])||e[n]instanceof String||_(t[n])||t[n]instanceof String?a&&(e[n]=t[n]):Ah(e[n],t[n],a):e[n]=t[n]);return e},Ga=e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");var jP={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"};const MP=e=>_(e)?e.replace(/[&<>"'\/]/g,t=>jP[t]):e;class NP{constructor(t){this.capacity=t,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(t){const a=this.regExpMap.get(t);if(a!==void 0)return a;const n=new RegExp(t);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(t,n),this.regExpQueue.push(t),n}}const LP=[" ",",","?","!",";"],RP=new NP(20),DP=(e,t,a)=>{t=t||"",a=a||"";const n=LP.filter(s=>t.indexOf(s)<0&&a.indexOf(s)<0);if(n.length===0)return!0;const o=RP.getRegExp(`(${n.map(s=>s==="?"?"\\?":s).join("|")})`);let i=!o.test(e);if(!i){const s=e.indexOf(a);s>0&&!o.test(e.substring(0,s))&&(i=!0)}return i},Nl=function(e,t){let a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:".";if(!e)return;if(e[t])return e[t];const n=t.split(a);let o=e;for(let i=0;i<n.length;){if(!o||typeof o!="object")return;let s,l="";for(let d=i;d<n.length;++d)if(d!==i&&(l+=a),l+=n[d],s=o[l],s!==void 0){if(["string","number","boolean"].indexOf(typeof s)>-1&&d<n.length-1)continue;i+=d-i+1;break}o=s}return o},mr=e=>e&&e.replace("_","-"),EP={type:"logger",log(e){this.output("log",e)},warn(e){this.output("warn",e)},error(e){this.output("error",e)},output(e,t){console&&console[e]&&console[e].apply(console,t)}};class gr{constructor(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.init(t,a)}init(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.prefix=a.prefix||"i18next:",this.logger=t||EP,this.options=a,this.debug=a.debug}log(){for(var t=arguments.length,a=new Array(t),n=0;n<t;n++)a[n]=arguments[n];return this.forward(a,"log","",!0)}warn(){for(var t=arguments.length,a=new Array(t),n=0;n<t;n++)a[n]=arguments[n];return this.forward(a,"warn","",!0)}error(){for(var t=arguments.length,a=new Array(t),n=0;n<t;n++)a[n]=arguments[n];return this.forward(a,"error","")}deprecate(){for(var t=arguments.length,a=new Array(t),n=0;n<t;n++)a[n]=arguments[n];return this.forward(a,"warn","WARNING DEPRECATED: ",!0)}forward(t,a,n,o){return o&&!this.debug?null:(_(t[0])&&(t[0]=`${n}${this.prefix} ${t[0]}`),this.logger[a](t))}create(t){return new gr(this.logger,{prefix:`${this.prefix}:${t}:`,...this.options})}clone(t){return t=t||this.options,t.prefix=t.prefix||this.prefix,new gr(this.logger,t)}}var Pt=new gr;class Ur{constructor(){this.observers={}}on(t,a){return t.split(" ").forEach(n=>{this.observers[n]||(this.observers[n]=new Map);const o=this.observers[n].get(a)||0;this.observers[n].set(a,o+1)}),this}off(t,a){if(this.observers[t]){if(!a){delete this.observers[t];return}this.observers[t].delete(a)}}emit(t){for(var a=arguments.length,n=new Array(a>1?a-1:0),o=1;o<a;o++)n[o-1]=arguments[o];this.observers[t]&&Array.from(this.observers[t].entries()).forEach(s=>{let[l,d]=s;for(let c=0;c<d;c++)l(...n)}),this.observers["*"]&&Array.from(this.observers["*"].entries()).forEach(s=>{let[l,d]=s;for(let c=0;c<d;c++)l.apply(l,[t,...n])})}}class Du extends Ur{constructor(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{ns:["translation"],defaultNS:"translation"};super(),this.data=t||{},this.options=a,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.options.ignoreJSONStructure===void 0&&(this.options.ignoreJSONStructure=!0)}addNamespaces(t){this.options.ns.indexOf(t)<0&&this.options.ns.push(t)}removeNamespaces(t){const a=this.options.ns.indexOf(t);a>-1&&this.options.ns.splice(a,1)}getResource(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=o.keySeparator!==void 0?o.keySeparator:this.options.keySeparator,s=o.ignoreJSONStructure!==void 0?o.ignoreJSONStructure:this.options.ignoreJSONStructure;let l;t.indexOf(".")>-1?l=t.split("."):(l=[t,a],n&&(Array.isArray(n)?l.push(...n):_(n)&&i?l.push(...n.split(i)):l.push(n)));const d=pr(this.data,l);return!d&&!a&&!n&&t.indexOf(".")>-1&&(t=l[0],a=l[1],n=l.slice(2).join(".")),d||!s||!_(n)?d:Nl(this.data&&this.data[t]&&this.data[t][a],n,i)}addResource(t,a,n,o){let i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:{silent:!1};const s=i.keySeparator!==void 0?i.keySeparator:this.options.keySeparator;let l=[t,a];n&&(l=l.concat(s?n.split(s):n)),t.indexOf(".")>-1&&(l=t.split("."),o=a,a=l[1]),this.addNamespaces(a),Ru(this.data,l,o),i.silent||this.emit("added",t,a,n,o)}addResources(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{silent:!1};for(const i in n)(_(n[i])||Array.isArray(n[i]))&&this.addResource(t,a,i,n[i],{silent:!0});o.silent||this.emit("added",t,a,n)}addResourceBundle(t,a,n,o,i){let s=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{silent:!1,skipCopy:!1},l=[t,a];t.indexOf(".")>-1&&(l=t.split("."),o=n,n=a,a=l[1]),this.addNamespaces(a);let d=pr(this.data,l)||{};s.skipCopy||(n=JSON.parse(JSON.stringify(n))),o?Ah(d,n,i):d={...d,...n},Ru(this.data,l,d),s.silent||this.emit("added",t,a,n)}removeResourceBundle(t,a){this.hasResourceBundle(t,a)&&delete this.data[t][a],this.removeNamespaces(a),this.emit("removed",t,a)}hasResourceBundle(t,a){return this.getResource(t,a)!==void 0}getResourceBundle(t,a){return a||(a=this.options.defaultNS),this.options.compatibilityAPI==="v1"?{...this.getResource(t,a)}:this.getResource(t,a)}getDataByLanguage(t){return this.data[t]}hasLanguageSomeTranslations(t){const a=this.getDataByLanguage(t);return!!(a&&Object.keys(a)||[]).find(o=>a[o]&&Object.keys(a[o]).length>0)}toJSON(){return this.data}}var Ch={processors:{},addPostProcessor(e){this.processors[e.name]=e},handle(e,t,a,n,o){return e.forEach(i=>{this.processors[i]&&(t=this.processors[i].process(t,a,n,o))}),t}};const Eu={};class hr extends Ur{constructor(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};super(),IP(["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],t,this),this.options=a,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.logger=Pt.create("translator")}changeLanguage(t){t&&(this.language=t)}exists(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};if(t==null)return!1;const n=this.resolve(t,a);return n&&n.res!==void 0}extractFromKey(t,a){let n=a.nsSeparator!==void 0?a.nsSeparator:this.options.nsSeparator;n===void 0&&(n=":");const o=a.keySeparator!==void 0?a.keySeparator:this.options.keySeparator;let i=a.ns||this.options.defaultNS||[];const s=n&&t.indexOf(n)>-1,l=!this.options.userDefinedKeySeparator&&!a.keySeparator&&!this.options.userDefinedNsSeparator&&!a.nsSeparator&&!DP(t,n,o);if(s&&!l){const d=t.match(this.interpolator.nestingRegexp);if(d&&d.length>0)return{key:t,namespaces:_(i)?[i]:i};const c=t.split(n);(n!==o||n===o&&this.options.ns.indexOf(c[0])>-1)&&(i=c.shift()),t=c.join(o)}return{key:t,namespaces:_(i)?[i]:i}}translate(t,a,n){if(typeof a!="object"&&this.options.overloadTranslationOptionHandler&&(a=this.options.overloadTranslationOptionHandler(arguments)),typeof a=="object"&&(a={...a}),a||(a={}),t==null)return"";Array.isArray(t)||(t=[String(t)]);const o=a.returnDetails!==void 0?a.returnDetails:this.options.returnDetails,i=a.keySeparator!==void 0?a.keySeparator:this.options.keySeparator,{key:s,namespaces:l}=this.extractFromKey(t[t.length-1],a),d=l[l.length-1],c=a.lng||this.language,u=a.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(c&&c.toLowerCase()==="cimode"){if(u){const b=a.nsSeparator||this.options.nsSeparator;return o?{res:`${d}${b}${s}`,usedKey:s,exactUsedKey:s,usedLng:c,usedNS:d,usedParams:this.getUsedParamsDetails(a)}:`${d}${b}${s}`}return o?{res:s,usedKey:s,exactUsedKey:s,usedLng:c,usedNS:d,usedParams:this.getUsedParamsDetails(a)}:s}const p=this.resolve(t,a);let m=p&&p.res;const f=p&&p.usedKey||s,P=p&&p.exactUsedKey||s,y=Object.prototype.toString.apply(m),A=["[object Number]","[object Function]","[object RegExp]"],h=a.joinArrays!==void 0?a.joinArrays:this.options.joinArrays,k=!this.i18nFormat||this.i18nFormat.handleAsObject,v=!_(m)&&typeof m!="boolean"&&typeof m!="number";if(k&&m&&v&&A.indexOf(y)<0&&!(_(h)&&Array.isArray(m))){if(!a.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn("accessing an object - but returnObjects options is not enabled!");const b=this.options.returnedObjectHandler?this.options.returnedObjectHandler(f,m,{...a,ns:l}):`key '${s} (${this.language})' returned an object instead of string.`;return o?(p.res=b,p.usedParams=this.getUsedParamsDetails(a),p):b}if(i){const b=Array.isArray(m),z=b?[]:{},I=b?P:f;for(const C in m)if(Object.prototype.hasOwnProperty.call(m,C)){const S=`${I}${i}${C}`;z[C]=this.translate(S,{...a,joinArrays:!1,ns:l}),z[C]===S&&(z[C]=m[C])}m=z}}else if(k&&_(h)&&Array.isArray(m))m=m.join(h),m&&(m=this.extendTranslation(m,t,a,n));else{let b=!1,z=!1;const I=a.count!==void 0&&!_(a.count),C=hr.hasDefaultValue(a),S=I?this.pluralResolver.getSuffix(c,a.count,a):"",L=a.ordinal&&I?this.pluralResolver.getSuffix(c,a.count,{ordinal:!1}):"",T=I&&!a.ordinal&&a.count===0&&this.pluralResolver.shouldUseIntlApi(),M=T&&a[`defaultValue${this.options.pluralSeparator}zero`]||a[`defaultValue${S}`]||a[`defaultValue${L}`]||a.defaultValue;!this.isValidLookup(m)&&C&&(b=!0,m=M),this.isValidLookup(m)||(z=!0,m=s);const Q=(a.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&z?void 0:m,W=C&&M!==m&&this.options.updateMissing;if(z||b||W){if(this.logger.log(W?"updateKey":"missingKey",c,d,s,W?M:m),i){const w=this.resolve(s,{...a,keySeparator:!1});w&&w.res&&this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.")}let J=[];const ye=this.languageUtils.getFallbackCodes(this.options.fallbackLng,a.lng||this.language);if(this.options.saveMissingTo==="fallback"&&ye&&ye[0])for(let w=0;w<ye.length;w++)J.push(ye[w]);else this.options.saveMissingTo==="all"?J=this.languageUtils.toResolveHierarchy(a.lng||this.language):J.push(a.lng||this.language);const ve=(w,E,U)=>{const Z=C&&U!==m?U:Q;this.options.missingKeyHandler?this.options.missingKeyHandler(w,d,E,Z,W,a):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(w,d,E,Z,W,a),this.emit("missingKey",w,d,E,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&I?J.forEach(w=>{const E=this.pluralResolver.getSuffixes(w,a);T&&a[`defaultValue${this.options.pluralSeparator}zero`]&&E.indexOf(`${this.options.pluralSeparator}zero`)<0&&E.push(`${this.options.pluralSeparator}zero`),E.forEach(U=>{ve([w],s+U,a[`defaultValue${U}`]||M)})}):ve(J,s,M))}m=this.extendTranslation(m,t,a,p,n),z&&m===s&&this.options.appendNamespaceToMissingKey&&(m=`${d}:${s}`),(z||b)&&this.options.parseMissingKeyHandler&&(this.options.compatibilityAPI!=="v1"?m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${d}:${s}`:s,b?m:void 0):m=this.options.parseMissingKeyHandler(m))}return o?(p.res=m,p.usedParams=this.getUsedParamsDetails(a),p):m}extendTranslation(t,a,n,o,i){var s=this;if(this.i18nFormat&&this.i18nFormat.parse)t=this.i18nFormat.parse(t,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});const c=_(t)&&(n&&n.interpolation&&n.interpolation.skipOnVariables!==void 0?n.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables);let u;if(c){const m=t.match(this.interpolator.nestingRegexp);u=m&&m.length}let p=n.replace&&!_(n.replace)?n.replace:n;if(this.options.interpolation.defaultVariables&&(p={...this.options.interpolation.defaultVariables,...p}),t=this.interpolator.interpolate(t,p,n.lng||this.language||o.usedLng,n),c){const m=t.match(this.interpolator.nestingRegexp),f=m&&m.length;u<f&&(n.nest=!1)}!n.lng&&this.options.compatibilityAPI!=="v1"&&o&&o.res&&(n.lng=this.language||o.usedLng),n.nest!==!1&&(t=this.interpolator.nest(t,function(){for(var m=arguments.length,f=new Array(m),P=0;P<m;P++)f[P]=arguments[P];return i&&i[0]===f[0]&&!n.context?(s.logger.warn(`It seems you are nesting recursively key: ${f[0]} in key: ${a[0]}`),null):s.translate(...f,a)},n)),n.interpolation&&this.interpolator.reset()}const l=n.postProcess||this.options.postProcess,d=_(l)?[l]:l;return t!=null&&d&&d.length&&n.applyPostProcessor!==!1&&(t=Ch.handle(d,t,a,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...o,usedParams:this.getUsedParamsDetails(n)},...n}:n,this)),t}resolve(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n,o,i,s,l;return _(t)&&(t=[t]),t.forEach(d=>{if(this.isValidLookup(n))return;const c=this.extractFromKey(d,a),u=c.key;o=u;let p=c.namespaces;this.options.fallbackNS&&(p=p.concat(this.options.fallbackNS));const m=a.count!==void 0&&!_(a.count),f=m&&!a.ordinal&&a.count===0&&this.pluralResolver.shouldUseIntlApi(),P=a.context!==void 0&&(_(a.context)||typeof a.context=="number")&&a.context!=="",y=a.lngs?a.lngs:this.languageUtils.toResolveHierarchy(a.lng||this.language,a.fallbackLng);p.forEach(A=>{this.isValidLookup(n)||(l=A,!Eu[`${y[0]}-${A}`]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(l)&&(Eu[`${y[0]}-${A}`]=!0,this.logger.warn(`key "${o}" for languages "${y.join(", ")}" won't get resolved as namespace "${l}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),y.forEach(h=>{if(this.isValidLookup(n))return;s=h;const k=[u];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(k,u,h,A,a);else{let b;m&&(b=this.pluralResolver.getSuffix(h,a.count,a));const z=`${this.options.pluralSeparator}zero`,I=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(m&&(k.push(u+b),a.ordinal&&b.indexOf(I)===0&&k.push(u+b.replace(I,this.options.pluralSeparator)),f&&k.push(u+z)),P){const C=`${u}${this.options.contextSeparator}${a.context}`;k.push(C),m&&(k.push(C+b),a.ordinal&&b.indexOf(I)===0&&k.push(C+b.replace(I,this.options.pluralSeparator)),f&&k.push(C+z))}}let v;for(;v=k.pop();)this.isValidLookup(n)||(i=v,n=this.getResource(h,A,v,a))}))})}),{res:n,usedKey:o,exactUsedKey:i,usedLng:s,usedNS:l}}isValidLookup(t){return t!==void 0&&!(!this.options.returnNull&&t===null)&&!(!this.options.returnEmptyString&&t==="")}getResource(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};return this.i18nFormat&&this.i18nFormat.getResource?this.i18nFormat.getResource(t,a,n,o):this.resourceStore.getResource(t,a,n,o)}getUsedParamsDetails(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};const a=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],n=t.replace&&!_(t.replace);let o=n?t.replace:t;if(n&&typeof t.count<"u"&&(o.count=t.count),this.options.interpolation.defaultVariables&&(o={...this.options.interpolation.defaultVariables,...o}),!n){o={...o};for(const i of a)delete o[i]}return o}static hasDefaultValue(t){const a="defaultValue";for(const n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&a===n.substring(0,a.length)&&t[n]!==void 0)return!0;return!1}}const Ps=e=>e.charAt(0).toUpperCase()+e.slice(1);class Ou{constructor(t){this.options=t,this.supportedLngs=this.options.supportedLngs||!1,this.logger=Pt.create("languageUtils")}getScriptPartFromCode(t){if(t=mr(t),!t||t.indexOf("-")<0)return null;const a=t.split("-");return a.length===2||(a.pop(),a[a.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(a.join("-"))}getLanguagePartFromCode(t){if(t=mr(t),!t||t.indexOf("-")<0)return t;const a=t.split("-");return this.formatLanguageCode(a[0])}formatLanguageCode(t){if(_(t)&&t.indexOf("-")>-1){if(typeof Intl<"u"&&typeof Intl.getCanonicalLocales<"u")try{let o=Intl.getCanonicalLocales(t)[0];if(o&&this.options.lowerCaseLng&&(o=o.toLowerCase()),o)return o}catch{}const a=["hans","hant","latn","cyrl","cans","mong","arab"];let n=t.split("-");return this.options.lowerCaseLng?n=n.map(o=>o.toLowerCase()):n.length===2?(n[0]=n[0].toLowerCase(),n[1]=n[1].toUpperCase(),a.indexOf(n[1].toLowerCase())>-1&&(n[1]=Ps(n[1].toLowerCase()))):n.length===3&&(n[0]=n[0].toLowerCase(),n[1].length===2&&(n[1]=n[1].toUpperCase()),n[0]!=="sgn"&&n[2].length===2&&(n[2]=n[2].toUpperCase()),a.indexOf(n[1].toLowerCase())>-1&&(n[1]=Ps(n[1].toLowerCase())),a.indexOf(n[2].toLowerCase())>-1&&(n[2]=Ps(n[2].toLowerCase()))),n.join("-")}return this.options.cleanCode||this.options.lowerCaseLng?t.toLowerCase():t}isSupportedCode(t){return(this.options.load==="languageOnly"||this.options.nonExplicitSupportedLngs)&&(t=this.getLanguagePartFromCode(t)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(t)>-1}getBestMatchFromCodes(t){if(!t)return null;let a;return t.forEach(n=>{if(a)return;const o=this.formatLanguageCode(n);(!this.options.supportedLngs||this.isSupportedCode(o))&&(a=o)}),!a&&this.options.supportedLngs&&t.forEach(n=>{if(a)return;const o=this.getLanguagePartFromCode(n);if(this.isSupportedCode(o))return a=o;a=this.options.supportedLngs.find(i=>{if(i===o)return i;if(!(i.indexOf("-")<0&&o.indexOf("-")<0)&&(i.indexOf("-")>0&&o.indexOf("-")<0&&i.substring(0,i.indexOf("-"))===o||i.indexOf(o)===0&&o.length>1))return i})}),a||(a=this.getFallbackCodes(this.options.fallbackLng)[0]),a}getFallbackCodes(t,a){if(!t)return[];if(typeof t=="function"&&(t=t(a)),_(t)&&(t=[t]),Array.isArray(t))return t;if(!a)return t.default||[];let n=t[a];return n||(n=t[this.getScriptPartFromCode(a)]),n||(n=t[this.formatLanguageCode(a)]),n||(n=t[this.getLanguagePartFromCode(a)]),n||(n=t.default),n||[]}toResolveHierarchy(t,a){const n=this.getFallbackCodes(a||this.options.fallbackLng||[],t),o=[],i=s=>{s&&(this.isSupportedCode(s)?o.push(s):this.logger.warn(`rejecting language code not found in supportedLngs: ${s}`))};return _(t)&&(t.indexOf("-")>-1||t.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&i(this.formatLanguageCode(t)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&i(this.getScriptPartFromCode(t)),this.options.load!=="currentOnly"&&i(this.getLanguagePartFromCode(t))):_(t)&&i(this.formatLanguageCode(t)),n.forEach(s=>{o.indexOf(s)<0&&i(this.formatLanguageCode(s))}),o}}let OP=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],KP={1:e=>+(e>1),2:e=>+(e!=1),3:e=>0,4:e=>e%10==1&&e%100!=11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2,5:e=>e==0?0:e==1?1:e==2?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5,6:e=>e==1?0:e>=2&&e<=4?1:2,7:e=>e==1?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2,8:e=>e==1?0:e==2?1:e!=8&&e!=11?2:3,9:e=>+(e>=2),10:e=>e==1?0:e==2?1:e<7?2:e<11?3:4,11:e=>e==1||e==11?0:e==2||e==12?1:e>2&&e<20?2:3,12:e=>+(e%10!=1||e%100==11),13:e=>+(e!==0),14:e=>e==1?0:e==2?1:e==3?2:3,15:e=>e%10==1&&e%100!=11?0:e%10>=2&&(e%100<10||e%100>=20)?1:2,16:e=>e%10==1&&e%100!=11?0:e!==0?1:2,17:e=>e==1||e%10==1&&e%100!=11?0:1,18:e=>e==0?0:e==1?1:2,19:e=>e==1?0:e==0||e%100>1&&e%100<11?1:e%100>10&&e%100<20?2:3,20:e=>e==1?0:e==0||e%100>0&&e%100<20?1:2,21:e=>e%100==1?1:e%100==2?2:e%100==3||e%100==4?3:0,22:e=>e==1?0:e==2?1:(e<0||e>10)&&e%10==0?2:3};const UP=["v1","v2","v3"],HP=["v4"],Ku={zero:0,one:1,two:2,few:3,many:4,other:5},FP=()=>{const e={};return OP.forEach(t=>{t.lngs.forEach(a=>{e[a]={numbers:t.nr,plurals:KP[t.fc]}})}),e};class BP{constructor(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.languageUtils=t,this.options=a,this.logger=Pt.create("pluralResolver"),(!this.options.compatibilityJSON||HP.includes(this.options.compatibilityJSON))&&(typeof Intl>"u"||!Intl.PluralRules)&&(this.options.compatibilityJSON="v3",this.logger.error("Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.")),this.rules=FP(),this.pluralRulesCache={}}addRule(t,a){this.rules[t]=a}clearCache(){this.pluralRulesCache={}}getRule(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(this.shouldUseIntlApi()){const n=mr(t==="dev"?"en":t),o=a.ordinal?"ordinal":"cardinal",i=JSON.stringify({cleanedCode:n,type:o});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let s;try{s=new Intl.PluralRules(n,{type:o})}catch{if(!t.match(/-|_/))return;const d=this.languageUtils.getLanguagePartFromCode(t);s=this.getRule(d,a)}return this.pluralRulesCache[i]=s,s}return this.rules[t]||this.rules[this.languageUtils.getLanguagePartFromCode(t)]}needsPlural(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const n=this.getRule(t,a);return this.shouldUseIntlApi()?n&&n.resolvedOptions().pluralCategories.length>1:n&&n.numbers.length>1}getPluralFormsOfKey(t,a){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return this.getSuffixes(t,n).map(o=>`${a}${o}`)}getSuffixes(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const n=this.getRule(t,a);return n?this.shouldUseIntlApi()?n.resolvedOptions().pluralCategories.sort((o,i)=>Ku[o]-Ku[i]).map(o=>`${this.options.prepend}${a.ordinal?`ordinal${this.options.prepend}`:""}${o}`):n.numbers.map(o=>this.getSuffix(t,o,a)):[]}getSuffix(t,a){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};const o=this.getRule(t,n);return o?this.shouldUseIntlApi()?`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${o.select(a)}`:this.getSuffixRetroCompatible(o,a):(this.logger.warn(`no plural rule found for: ${t}`),"")}getSuffixRetroCompatible(t,a){const n=t.noAbs?t.plurals(a):t.plurals(Math.abs(a));let o=t.numbers[n];this.options.simplifyPluralSuffix&&t.numbers.length===2&&t.numbers[0]===1&&(o===2?o="plural":o===1&&(o=""));const i=()=>this.options.prepend&&o.toString()?this.options.prepend+o.toString():o.toString();return this.options.compatibilityJSON==="v1"?o===1?"":typeof o=="number"?`_plural_${o.toString()}`:i():this.options.compatibilityJSON==="v2"||this.options.simplifyPluralSuffix&&t.numbers.length===2&&t.numbers[0]===1?i():this.options.prepend&&n.toString()?this.options.prepend+n.toString():n.toString()}shouldUseIntlApi(){return!UP.includes(this.options.compatibilityJSON)}}const Uu=function(e,t,a){let n=arguments.length>3&&arguments[3]!==void 0?arguments[3]:".",o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,i=TP(e,t,a);return!i&&o&&_(a)&&(i=Nl(e,a,n),i===void 0&&(i=Nl(t,a,n))),i},As=e=>e.replace(/\$/g,"$$$$");class VP{constructor(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Pt.create("interpolator"),this.options=t,this.format=t.interpolation&&t.interpolation.format||(a=>a),this.init(t)}init(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};t.interpolation||(t.interpolation={escapeValue:!0});const{escape:a,escapeValue:n,useRawValueToEscape:o,prefix:i,prefixEscaped:s,suffix:l,suffixEscaped:d,formatSeparator:c,unescapeSuffix:u,unescapePrefix:p,nestingPrefix:m,nestingPrefixEscaped:f,nestingSuffix:P,nestingSuffixEscaped:y,nestingOptionsSeparator:A,maxReplaces:h,alwaysFormat:k}=t.interpolation;this.escape=a!==void 0?a:MP,this.escapeValue=n!==void 0?n:!0,this.useRawValueToEscape=o!==void 0?o:!1,this.prefix=i?Ga(i):s||"{{",this.suffix=l?Ga(l):d||"}}",this.formatSeparator=c||",",this.unescapePrefix=u?"":p||"-",this.unescapeSuffix=this.unescapePrefix?"":u||"",this.nestingPrefix=m?Ga(m):f||Ga("$t("),this.nestingSuffix=P?Ga(P):y||Ga(")"),this.nestingOptionsSeparator=A||",",this.maxReplaces=h||1e3,this.alwaysFormat=k!==void 0?k:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){const t=(a,n)=>a&&a.source===n?(a.lastIndex=0,a):new RegExp(n,"g");this.regexp=t(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=t(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=t(this.nestingRegexp,`${this.nestingPrefix}(.+?)${this.nestingSuffix}`)}interpolate(t,a,n,o){let i,s,l;const d=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=f=>{if(f.indexOf(this.formatSeparator)<0){const h=Uu(a,d,f,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(h,void 0,n,{...o,...a,interpolationkey:f}):h}const P=f.split(this.formatSeparator),y=P.shift().trim(),A=P.join(this.formatSeparator).trim();return this.format(Uu(a,d,y,this.options.keySeparator,this.options.ignoreJSONStructure),A,n,{...o,...a,interpolationkey:y})};this.resetRegExp();const u=o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler,p=o&&o.interpolation&&o.interpolation.skipOnVariables!==void 0?o.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:f=>As(f)},{regex:this.regexp,safeValue:f=>this.escapeValue?As(this.escape(f)):As(f)}].forEach(f=>{for(l=0;i=f.regex.exec(t);){const P=i[1].trim();if(s=c(P),s===void 0)if(typeof u=="function"){const A=u(t,i,o);s=_(A)?A:""}else if(o&&Object.prototype.hasOwnProperty.call(o,P))s="";else if(p){s=i[0];continue}else this.logger.warn(`missed to pass in variable ${P} for interpolating ${t}`),s="";else!_(s)&&!this.useRawValueToEscape&&(s=Mu(s));const y=f.safeValue(s);if(t=t.replace(i[0],y),p?(f.regex.lastIndex+=s.length,f.regex.lastIndex-=i[0].length):f.regex.lastIndex=0,l++,l>=this.maxReplaces)break}}),t}nest(t,a){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},o,i,s;const l=(d,c)=>{const u=this.nestingOptionsSeparator;if(d.indexOf(u)<0)return d;const p=d.split(new RegExp(`${u}[ ]*{`));let m=`{${p[1]}`;d=p[0],m=this.interpolate(m,s);const f=m.match(/'/g),P=m.match(/"/g);(f&&f.length%2===0&&!P||P.length%2!==0)&&(m=m.replace(/'/g,'"'));try{s=JSON.parse(m),c&&(s={...c,...s})}catch(y){return this.logger.warn(`failed parsing options string in nesting for key ${d}`,y),`${d}${u}${m}`}return s.defaultValue&&s.defaultValue.indexOf(this.prefix)>-1&&delete s.defaultValue,d};for(;o=this.nestingRegexp.exec(t);){let d=[];s={...n},s=s.replace&&!_(s.replace)?s.replace:s,s.applyPostProcessor=!1,delete s.defaultValue;let c=!1;if(o[0].indexOf(this.formatSeparator)!==-1&&!/{.*}/.test(o[1])){const u=o[1].split(this.formatSeparator).map(p=>p.trim());o[1]=u.shift(),d=u,c=!0}if(i=a(l.call(this,o[1].trim(),s),s),i&&o[0]===t&&!_(i))return i;_(i)||(i=Mu(i)),i||(this.logger.warn(`missed to resolve ${o[1]} for nesting ${t}`),i=""),c&&(i=d.reduce((u,p)=>this.format(u,p,n.lng,{...n,interpolationkey:o[1].trim()}),i.trim())),t=t.replace(o[0],i),this.regexp.lastIndex=0}return t}}const qP=e=>{let t=e.toLowerCase().trim();const a={};if(e.indexOf("(")>-1){const n=e.split("(");t=n[0].toLowerCase().trim();const o=n[1].substring(0,n[1].length-1);t==="currency"&&o.indexOf(":")<0?a.currency||(a.currency=o.trim()):t==="relativetime"&&o.indexOf(":")<0?a.range||(a.range=o.trim()):o.split(";").forEach(s=>{if(s){const[l,...d]=s.split(":"),c=d.join(":").trim().replace(/^'+|'+$/g,""),u=l.trim();a[u]||(a[u]=c),c==="false"&&(a[u]=!1),c==="true"&&(a[u]=!0),isNaN(c)||(a[u]=parseInt(c,10))}})}return{formatName:t,formatOptions:a}},Wa=e=>{const t={};return(a,n,o)=>{let i=o;o&&o.interpolationkey&&o.formatParams&&o.formatParams[o.interpolationkey]&&o[o.interpolationkey]&&(i={...i,[o.interpolationkey]:void 0});const s=n+JSON.stringify(i);let l=t[s];return l||(l=e(mr(n),o),t[s]=l),l(a)}};class $P{constructor(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Pt.create("formatter"),this.options=t,this.formats={number:Wa((a,n)=>{const o=new Intl.NumberFormat(a,{...n});return i=>o.format(i)}),currency:Wa((a,n)=>{const o=new Intl.NumberFormat(a,{...n,style:"currency"});return i=>o.format(i)}),datetime:Wa((a,n)=>{const o=new Intl.DateTimeFormat(a,{...n});return i=>o.format(i)}),relativetime:Wa((a,n)=>{const o=new Intl.RelativeTimeFormat(a,{...n});return i=>o.format(i,n.range||"day")}),list:Wa((a,n)=>{const o=new Intl.ListFormat(a,{...n});return i=>o.format(i)})},this.init(t)}init(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};this.formatSeparator=a.interpolation.formatSeparator||","}add(t,a){this.formats[t.toLowerCase().trim()]=a}addCached(t,a){this.formats[t.toLowerCase().trim()]=Wa(a)}format(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=a.split(this.formatSeparator);if(i.length>1&&i[0].indexOf("(")>1&&i[0].indexOf(")")<0&&i.find(l=>l.indexOf(")")>-1)){const l=i.findIndex(d=>d.indexOf(")")>-1);i[0]=[i[0],...i.splice(1,l)].join(this.formatSeparator)}return i.reduce((l,d)=>{const{formatName:c,formatOptions:u}=qP(d);if(this.formats[c]){let p=l;try{const m=o&&o.formatParams&&o.formatParams[o.interpolationkey]||{},f=m.locale||m.lng||o.locale||o.lng||n;p=this.formats[c](l,f,{...u,...o,...m})}catch(m){this.logger.warn(m)}return p}else this.logger.warn(`there was no format function for ${c}`);return l},t)}}const _P=(e,t)=>{e.pending[t]!==void 0&&(delete e.pending[t],e.pendingCount--)};class GP extends Ur{constructor(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};super(),this.backend=t,this.store=a,this.services=n,this.languageUtils=n.languageUtils,this.options=o,this.logger=Pt.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=o.maxParallelReads||10,this.readingCalls=0,this.maxRetries=o.maxRetries>=0?o.maxRetries:5,this.retryTimeout=o.retryTimeout>=1?o.retryTimeout:350,this.state={},this.queue=[],this.backend&&this.backend.init&&this.backend.init(n,o.backend,o)}queueLoad(t,a,n,o){const i={},s={},l={},d={};return t.forEach(c=>{let u=!0;a.forEach(p=>{const m=`${c}|${p}`;!n.reload&&this.store.hasResourceBundle(c,p)?this.state[m]=2:this.state[m]<0||(this.state[m]===1?s[m]===void 0&&(s[m]=!0):(this.state[m]=1,u=!1,s[m]===void 0&&(s[m]=!0),i[m]===void 0&&(i[m]=!0),d[p]===void 0&&(d[p]=!0)))}),u||(l[c]=!0)}),(Object.keys(i).length||Object.keys(s).length)&&this.queue.push({pending:s,pendingCount:Object.keys(s).length,loaded:{},errors:[],callback:o}),{toLoad:Object.keys(i),pending:Object.keys(s),toLoadLanguages:Object.keys(l),toLoadNamespaces:Object.keys(d)}}loaded(t,a,n){const o=t.split("|"),i=o[0],s=o[1];a&&this.emit("failedLoading",i,s,a),!a&&n&&this.store.addResourceBundle(i,s,n,void 0,void 0,{skipCopy:!0}),this.state[t]=a?-1:2,a&&n&&(this.state[t]=0);const l={};this.queue.forEach(d=>{wP(d.loaded,[i],s),_P(d,t),a&&d.errors.push(a),d.pendingCount===0&&!d.done&&(Object.keys(d.loaded).forEach(c=>{l[c]||(l[c]={});const u=d.loaded[c];u.length&&u.forEach(p=>{l[c][p]===void 0&&(l[c][p]=!0)})}),d.done=!0,d.errors.length?d.callback(d.errors):d.callback())}),this.emit("loaded",l),this.queue=this.queue.filter(d=>!d.done)}read(t,a,n){let o=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:this.retryTimeout,s=arguments.length>5?arguments[5]:void 0;if(!t.length)return s(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:t,ns:a,fcName:n,tried:o,wait:i,callback:s});return}this.readingCalls++;const l=(c,u)=>{if(this.readingCalls--,this.waitingReads.length>0){const p=this.waitingReads.shift();this.read(p.lng,p.ns,p.fcName,p.tried,p.wait,p.callback)}if(c&&u&&o<this.maxRetries){setTimeout(()=>{this.read.call(this,t,a,n,o+1,i*2,s)},i);return}s(c,u)},d=this.backend[n].bind(this.backend);if(d.length===2){try{const c=d(t,a);c&&typeof c.then=="function"?c.then(u=>l(null,u)).catch(l):l(null,c)}catch(c){l(c)}return}return d(t,a,l)}prepareLoading(t,a){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},o=arguments.length>3?arguments[3]:void 0;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),o&&o();_(t)&&(t=this.languageUtils.toResolveHierarchy(t)),_(a)&&(a=[a]);const i=this.queueLoad(t,a,n,o);if(!i.toLoad.length)return i.pending.length||o(),null;i.toLoad.forEach(s=>{this.loadOne(s)})}load(t,a,n){this.prepareLoading(t,a,{},n)}reload(t,a,n){this.prepareLoading(t,a,{reload:!0},n)}loadOne(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"";const n=t.split("|"),o=n[0],i=n[1];this.read(o,i,"read",void 0,void 0,(s,l)=>{s&&this.logger.warn(`${a}loading namespace ${i} for language ${o} failed`,s),!s&&l&&this.logger.log(`${a}loaded namespace ${i} for language ${o}`,l),this.loaded(t,s,l)})}saveMissing(t,a,n,o,i){let s=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{},l=arguments.length>6&&arguments[6]!==void 0?arguments[6]:()=>{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(a)){this.logger.warn(`did not save key "${n}" as the namespace "${a}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");return}if(!(n==null||n==="")){if(this.backend&&this.backend.create){const d={...s,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let u;c.length===5?u=c(t,a,n,o,d):u=c(t,a,n,o),u&&typeof u.then=="function"?u.then(p=>l(null,p)).catch(l):l(null,u)}catch(u){l(u)}else c(t,a,n,o,l,d)}!t||!t[0]||this.store.addResource(t[0],a,n,o)}}}const Hu=()=>({debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:e=>{let t={};if(typeof e[1]=="object"&&(t=e[1]),_(e[1])&&(t.defaultValue=e[1]),_(e[2])&&(t.tDescription=e[2]),typeof e[2]=="object"||typeof e[3]=="object"){const a=e[3]||e[2];Object.keys(a).forEach(n=>{t[n]=a[n]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}),Fu=e=>(_(e.ns)&&(e.ns=[e.ns]),_(e.fallbackLng)&&(e.fallbackLng=[e.fallbackLng]),_(e.fallbackNS)&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&e.supportedLngs.indexOf("cimode")<0&&(e.supportedLngs=e.supportedLngs.concat(["cimode"])),e),vi=()=>{},WP=e=>{Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach(a=>{typeof e[a]=="function"&&(e[a]=e[a].bind(e))})};class Mo extends Ur{constructor(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},a=arguments.length>1?arguments[1]:void 0;if(super(),this.options=Fu(t),this.services={},this.logger=Pt,this.modules={external:[]},WP(this),a&&!this.isInitialized&&!t.isClone){if(!this.options.initImmediate)return this.init(t,a),this;setTimeout(()=>{this.init(t,a)},0)}}init(){var t=this;let a=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;this.isInitializing=!0,typeof a=="function"&&(n=a,a={}),!a.defaultNS&&a.defaultNS!==!1&&a.ns&&(_(a.ns)?a.defaultNS=a.ns:a.ns.indexOf("translation")<0&&(a.defaultNS=a.ns[0]));const o=Hu();this.options={...o,...this.options,...Fu(a)},this.options.compatibilityAPI!=="v1"&&(this.options.interpolation={...o.interpolation,...this.options.interpolation}),a.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=a.keySeparator),a.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=a.nsSeparator);const i=u=>u?typeof u=="function"?new u:u:null;if(!this.options.isClone){this.modules.logger?Pt.init(i(this.modules.logger),this.options):Pt.init(null,this.options);let u;this.modules.formatter?u=this.modules.formatter:typeof Intl<"u"&&(u=$P);const p=new Ou(this.options);this.store=new Du(this.options.resources,this.options);const m=this.services;m.logger=Pt,m.resourceStore=this.store,m.languageUtils=p,m.pluralResolver=new BP(p,{prepend:this.options.pluralSeparator,compatibilityJSON:this.options.compatibilityJSON,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),u&&(!this.options.interpolation.format||this.options.interpolation.format===o.interpolation.format)&&(m.formatter=i(u),m.formatter.init(m,this.options),this.options.interpolation.format=m.formatter.format.bind(m.formatter)),m.interpolator=new VP(this.options),m.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},m.backendConnector=new GP(i(this.modules.backend),m.resourceStore,m,this.options),m.backendConnector.on("*",function(f){for(var P=arguments.length,y=new Array(P>1?P-1:0),A=1;A<P;A++)y[A-1]=arguments[A];t.emit(f,...y)}),this.modules.languageDetector&&(m.languageDetector=i(this.modules.languageDetector),m.languageDetector.init&&m.languageDetector.init(m,this.options.detection,this.options)),this.modules.i18nFormat&&(m.i18nFormat=i(this.modules.i18nFormat),m.i18nFormat.init&&m.i18nFormat.init(this)),this.translator=new hr(this.services,this.options),this.translator.on("*",function(f){for(var P=arguments.length,y=new Array(P>1?P-1:0),A=1;A<P;A++)y[A-1]=arguments[A];t.emit(f,...y)}),this.modules.external.forEach(f=>{f.init&&f.init(this)})}if(this.format=this.options.interpolation.format,n||(n=vi),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){const u=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);u.length>0&&u[0]!=="dev"&&(this.options.lng=u[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn("init: no languageDetector is used and no lng is defined"),["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(u=>{this[u]=function(){return t.store[u](...arguments)}}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(u=>{this[u]=function(){return t.store[u](...arguments),t}});const d=qn(),c=()=>{const u=(p,m)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),d.resolve(m),n(p,m)};if(this.languages&&this.options.compatibilityAPI!=="v1"&&!this.isInitialized)return u(null,this.t.bind(this));this.changeLanguage(this.options.lng,u)};return this.options.resources||!this.options.initImmediate?c():setTimeout(c,0),d}loadResources(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:vi;const o=_(t)?t:this.language;if(typeof t=="function"&&(n=t),!this.options.resources||this.options.partialBundledLanguages){if(o&&o.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return n();const i=[],s=l=>{if(!l||l==="cimode")return;this.services.languageUtils.toResolveHierarchy(l).forEach(c=>{c!=="cimode"&&i.indexOf(c)<0&&i.push(c)})};o?s(o):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(d=>s(d)),this.options.preload&&this.options.preload.forEach(l=>s(l)),this.services.backendConnector.load(i,this.options.ns,l=>{!l&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),n(l)})}else n(null)}reloadResources(t,a,n){const o=qn();return typeof t=="function"&&(n=t,t=void 0),typeof a=="function"&&(n=a,a=void 0),t||(t=this.languages),a||(a=this.options.ns),n||(n=vi),this.services.backendConnector.reload(t,a,i=>{o.resolve(),n(i)}),o}use(t){if(!t)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!t.type)throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");return t.type==="backend"&&(this.modules.backend=t),(t.type==="logger"||t.log&&t.warn&&t.error)&&(this.modules.logger=t),t.type==="languageDetector"&&(this.modules.languageDetector=t),t.type==="i18nFormat"&&(this.modules.i18nFormat=t),t.type==="postProcessor"&&Ch.addPostProcessor(t),t.type==="formatter"&&(this.modules.formatter=t),t.type==="3rdParty"&&this.modules.external.push(t),this}setResolvedLanguage(t){if(!(!t||!this.languages)&&!(["cimode","dev"].indexOf(t)>-1))for(let a=0;a<this.languages.length;a++){const n=this.languages[a];if(!(["cimode","dev"].indexOf(n)>-1)&&this.store.hasLanguageSomeTranslations(n)){this.resolvedLanguage=n;break}}}changeLanguage(t,a){var n=this;this.isLanguageChangingTo=t;const o=qn();this.emit("languageChanging",t);const i=d=>{this.language=d,this.languages=this.services.languageUtils.toResolveHierarchy(d),this.resolvedLanguage=void 0,this.setResolvedLanguage(d)},s=(d,c)=>{c?(i(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,o.resolve(function(){return n.t(...arguments)}),a&&a(d,function(){return n.t(...arguments)})},l=d=>{!t&&!d&&this.services.languageDetector&&(d=[]);const c=_(d)?d:this.services.languageUtils.getBestMatchFromCodes(d);c&&(this.language||i(c),this.translator.language||this.translator.changeLanguage(c),this.services.languageDetector&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(c)),this.loadResources(c,u=>{s(u,c)})};return!t&&this.services.languageDetector&&!this.services.languageDetector.async?l(this.services.languageDetector.detect()):!t&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(l):this.services.languageDetector.detect(l):l(t),o}getFixedT(t,a,n){var o=this;const i=function(s,l){let d;if(typeof l!="object"){for(var c=arguments.length,u=new Array(c>2?c-2:0),p=2;p<c;p++)u[p-2]=arguments[p];d=o.options.overloadTranslationOptionHandler([s,l].concat(u))}else d={...l};d.lng=d.lng||i.lng,d.lngs=d.lngs||i.lngs,d.ns=d.ns||i.ns,d.keyPrefix!==""&&(d.keyPrefix=d.keyPrefix||n||i.keyPrefix);const m=o.options.keySeparator||".";let f;return d.keyPrefix&&Array.isArray(s)?f=s.map(P=>`${d.keyPrefix}${m}${P}`):f=d.keyPrefix?`${d.keyPrefix}${m}${s}`:s,o.t(f,d)};return _(t)?i.lng=t:i.lngs=t,i.ns=a,i.keyPrefix=n,i}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(t){this.options.defaultNS=t}hasLoadedNamespace(t){let a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!this.isInitialized)return this.logger.warn("hasLoadedNamespace: i18next was not initialized",this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty",this.languages),!1;const n=a.lng||this.resolvedLanguage||this.languages[0],o=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(n.toLowerCase()==="cimode")return!0;const s=(l,d)=>{const c=this.services.backendConnector.state[`${l}|${d}`];return c===-1||c===0||c===2};if(a.precheck){const l=a.precheck(this,s);if(l!==void 0)return l}return!!(this.hasResourceBundle(n,t)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||s(n,t)&&(!o||s(i,t)))}loadNamespaces(t,a){const n=qn();return this.options.ns?(_(t)&&(t=[t]),t.forEach(o=>{this.options.ns.indexOf(o)<0&&this.options.ns.push(o)}),this.loadResources(o=>{n.resolve(),a&&a(o)}),n):(a&&a(),Promise.resolve())}loadLanguages(t,a){const n=qn();_(t)&&(t=[t]);const o=this.options.preload||[],i=t.filter(s=>o.indexOf(s)<0&&this.services.languageUtils.isSupportedCode(s));return i.length?(this.options.preload=o.concat(i),this.loadResources(s=>{n.resolve(),a&&a(s)}),n):(a&&a(),Promise.resolve())}dir(t){if(t||(t=this.resolvedLanguage||(this.languages&&this.languages.length>0?this.languages[0]:this.language)),!t)return"rtl";const a=["ar","shu","sqr","ssh","xaa","yhd","yud","aao","abh","abv","acm","acq","acw","acx","acy","adf","ads","aeb","aec","afb","ajp","apc","apd","arb","arq","ars","ary","arz","auz","avl","ayh","ayl","ayn","ayp","bbz","pga","he","iw","ps","pbt","pbu","pst","prp","prd","ug","ur","ydd","yds","yih","ji","yi","hbo","men","xmn","fa","jpr","peo","pes","prs","dv","sam","ckb"],n=this.services&&this.services.languageUtils||new Ou(Hu());return a.indexOf(n.getLanguagePartFromCode(t))>-1||t.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},a=arguments.length>1?arguments[1]:void 0;return new Mo(t,a)}cloneInstance(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:vi;const n=t.forkResourceStore;n&&delete t.forkResourceStore;const o={...this.options,...t,isClone:!0},i=new Mo(o);return(t.debug!==void 0||t.prefix!==void 0)&&(i.logger=i.logger.clone(t)),["store","services","language"].forEach(l=>{i[l]=this[l]}),i.services={...this.services},i.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},n&&(i.store=new Du(this.store.data,o),i.services.resourceStore=i.store),i.translator=new hr(i.services,o),i.translator.on("*",function(l){for(var d=arguments.length,c=new Array(d>1?d-1:0),u=1;u<d;u++)c[u-1]=arguments[u];i.emit(l,...c)}),i.init(o,a),i.translator.options=o,i.translator.backendConnector.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},i}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}const ie=Mo.createInstance();ie.createInstance=Mo.createInstance;ie.createInstance;ie.dir;ie.init;ie.loadResources;ie.reloadResources;ie.use;ie.changeLanguage;ie.getFixedT;ie.t;ie.exists;ie.setDefaultNamespace;ie.hasLoadedNamespace;ie.loadNamespaces;ie.loadLanguages;const ZP={loading:"جارٍ تحميل إعدادات نموذج اللغة...",reset:{button:"استعادة الافتراضيات",confirmTitle:"استعادة الإعدادات الافتراضية؟",confirmBody:"سيؤدي هذا إلى مسح تخصيصاتك لهذا الموفر وإعادته إلى الإعدادات الافتراضية المضمّنة. سيتم الاحتفاظ بمفتاح API والجلسات المحفوظة.",confirmButton:"استعادة الافتراضيات"},reentryBanner:{message:"{{count}} موفر (موفرات) مُفعَّل يحتاج إلى إعادة إدخال مفتاح API. افتح كلًا منها وأضف مفتاحه مجددًا."},migrationPack:{barHint:"انقل مفاتيح الموفر ورموز الاشتراك إلى جهاز آخر باستخدام حزمة مشفرة.",passphrase:"عبارة المرور",passphrasePlaceholder:"أدخل عبارة المرور",passphraseHint:"استخدم 8 أحرف على الأقل؛ يُنصح بـ 12 حرفًا أو أكثر.",confirm:"تأكيد عبارة المرور",confirmPlaceholder:"أعد إدخال عبارة المرور",mismatch:"عبارتا المرور غير متطابقتين.",strength:{weak:"قصيرة جدًا — استخدم 8 أحرف على الأقل.",fair:"مقبولة — 12 حرفًا أو أكثر أكثر أمانًا.",strong:"عبارة مرور قوية."},export:{button:"تصدير الحزمة",title:"تصدير حزمة مشفرة",subtitle:"تشفير مفاتيح الموفر ورموز الاشتراك في ملف قابل للنقل.",warning:"يحتوي هذا الملف على أسرار قابلة للفك. احتفظ به في مكان آمن — يمكن لأي شخص لديه الملف وعبارة المرور قراءة مفاتيحك. لا يمكن استرداد عبارة المرور في حال فقدانها.",submit:"تصدير",success:"تم تصدير الحزمة بنجاح.",error:"فشل التصدير. يرجى المحاولة مجددًا."},import:{button:"استيراد الحزمة",title:"استيراد حزمة مشفرة",subtitle:"استعادة مفاتيح الموفر ورموز الاشتراك من حزمة مصدَّرة.",hint:"أدخل عبارة المرور المستخدمة عند تصدير الحزمة، ثم اختر الملف.",submit:"استيراد",successTitle:"اكتمل الاستيراد",summary:"تم استيراد {{providerKeys}} مفتاح (مفاتيح) موفر، و{{poolKeys}} مفتاح (مفاتيح) مجموعة، و{{tokenSets}} مجموعة (مجموعات) رموز.",duplicates:"تم تخطي {{count}} مفتاح (مفاتيح) مجموعة موجود بالفعل.",skipped:"تم التخطي (لا يوجد موفر مطابق): {{names}}",error:"عبارة مرور خاطئة أو حزمة تالفة. لم يتم تغيير أي شيء."}},searchPlaceholder:"البحث عن الموفرين...",emptySearch:"لا يوجد موفرون يطابقون بحثك.",emptyList:"لا يوجد موفرون مُهيَّأون.",selectPrompt:"اختر موفرًا لعرض التفاصيل",listStatus:"{{count}} نموذج (نماذج)",noModels:"لا توجد نماذج مُهيَّأة",enabled:"مُفعَّل",disabled:"مُعطَّل",showEnabledOnly:"إظهار المُفعَّلة فقط",showAll:"إظهار جميع الموفرين",dragHandle:"اسحب لإعادة الترتيب",reorderFailed:"فشل حفظ ترتيب الموفرين",credentials:{apiKey:"مفتاح API",apiBaseUrl:"عنوان URL الأساسي لـ API"},filter:{all:"الكل",chat:"محادثة",code:"برمجة"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"اختر قالبًا",skipTemplates:"تخطي، تهيئة يدوية",name:"الاسم *",providerType:"النوع",apiType:"نوع API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"تنسيق API القياسي للمحادثة/الإكمال من OpenAI",claudecode:"تنسيق Anthropic Messages API (Claude Code)"},chatApiFormat:"تنسيق API",chatApiFormatDescription:"اختر تنسيق API الذي يتوافق مع نقطة نهاية موفرك",apiKey:"مفتاح API",apiKeyPlaceholder:"sk-... أو $ENV_VAR",apiKeyHelper:"استخدم $VAR_NAME للإشارة إلى متغيرات البيئة",apiKeySetPlaceholder:"تم تعيين المفتاح — اتركه فارغًا للاحتفاظ به",apiKeyReplaceHelper:"يوجد مفتاح محفوظ بشكل آمن. اكتب قيمة جديدة لاستبداله، أو اتركه فارغًا للاحتفاظ به.",testApiKey:"اختبار مفتاح API",apiUrl:"عنوان URL لـ API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"معاينة:",models:"النماذج",modelPlaceholder:"اسم النموذج (مثال: gpt-4، claude-3-opus)",transformers:"المحوِّلات",transformerConfig:"محوِّلات API",transformerConfigDescription:"تهيئة المحوِّلات لتكييف تنسيقات طلب/استجابة API لهذا الموفر",transformerConfigNote:"يطبّق Daemon هذه المحوِّلات في سلسلة الطلب، بعد محوِّل تنسيق الموفر (الذي يتولى تحويل التنسيق السلكي). يتم تخطي أسماء المحوِّلات غير المعروفة.",enabled:"مُفعَّل",apiVersion:"إصدار API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"إصدار Azure OpenAI API (مثال: 2024-08-01-preview)",official:"Anthropic API الرسمي",officialHelper:"فعّل إذا كان هذا الموفر يتصل مباشرةً بـ Anthropic API الرسمي. عطّل للوكلاء العكسيين أو الخدمات التابعة لجهات خارجية.",maxConcurrency:"الحد الأقصى للطلبات المتزامنة",maxConcurrencyHelper:"الحد الأقصى لعدد طلبات API المتزامنة المرسلة إلى هذا الموفر. القيم المنخفضة تساعد على تجنب تحديد المعدل (أخطاء 429). اضبط `-1` لإزالة الحد.",codingPlan:{label:"خطة البرمجة",description:"استخدام نقطة نهاية API منفصلة لخطط البرمجة المبنية على الاشتراك",baseUrl:"عنوان URL الأساسي لخطة البرمجة",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"مفتاح API لخطة البرمجة (اختياري)",apiKeyPlaceholder:"اتركه فارغًا لاستخدام مفتاح API الخاص بالموفر",apiKeyHelper:"مطلوب فقط إذا كانت خطة البرمجة تستخدم مفتاح API مختلفًا",tokenPlanHint:"بعض الموفرين (مثل Xiaomi MiMo) يُصدرون مفاتيح Token Plan بادئتها `tp-` — للمعلومات فقط، غير مُطبَّق."},selectTypeFirst:"اختر نوع الموفر",selectTypeFirstDesc:"اختر نوع الموفر الذي تريد إضافته",codeProviderNote:"موفرو البرمجة يحتاجون فقط إلى مفتاح API وعنوان URL. تتم إدارة النماذج بواسطة موجِّه الوكيل.",buttons:{cancel:"إلغاء",submitAdd:"إضافة موفر",submitUpdate:"تحديث الموفر",continue:"متابعة",back:"رجوع"}},details:{noSelection:"اختر موفرًا لعرض التفاصيل",apiKey:"مفتاح API",apiUrl:"عنوان URL لـ API",nameLabel:"اسم الموفر",modelsEndpoint:"نقطة نهاية النماذج",modelsEndpointHelper:"تجاوز نقطة نهاية الاكتشاف إذا كان الموفر يعرض مسار /models مخصصًا.",models:"النماذج",transformers:"المحوِّلات",codeProviderNote:"موفرو البرمجة (مثل Claude Code) لا يحتاجون إلى تهيئة النماذج. يتم إدارة النماذج تلقائيًا بواسطة موجِّه الوكيل.",buttons:{more:"إعدادات إضافية",delete:"حذف"}},providerModelSelector:{placeholder:"اختر الموفر والنموذج",noProviders:"لا يوجد موفرون متاحون",noModels:"لا توجد نماذج مُهيَّأة"},apiKeyPool:{title:"مجموعة مفاتيح API",description:"تهيئة مفاتيح API متعددة لموازنة التحميل. تلتزم كل جلسة بمفتاح واحد للحفاظ على ذاكرة التخزين المؤقت للمطالبات.",defaultLabel:"افتراضي",weight:"الوزن",noKey:"لا يوجد مفتاح",labelPlaceholder:"التسمية (مثال: المفتاح #1، الإنتاج)",addKey:"إضافة مفتاح API",add:"إضافة",empty:"لا توجد مفاتيح إضافية مُهيَّأة.",statusCoolingDown:"في فترة التهدئة {{time}}",statusAuthFailed:"فشل المصادقة · مُعطَّل",statusDisabled:"مُعطَّل",statusHealthy:"سليم",agoSeconds:"منذ {{count}} ثانية",agoMinutes:"منذ {{count}} دقيقة",agoHours:"منذ {{count}} ساعة",agoDays:"منذ {{count}} يوم"},modelsManager:{searchPlaceholder:"البحث عن النماذج...",defaultGroup:"جميع النماذج",add:"إضافة نموذج",manage:"إدارة",empty:"لا توجد نماذج في هذه المجموعة",enabled:"مُفعَّل",disabled:"مُعطَّل",filters:{all:"الكل",vision:"رؤية",reasoning:"استدلال",free:"مجاني",tools:"أدوات"},manualDialog:{title:"إضافة نموذج",subtitle:"إضافة نموذج مخصص لهذا الموفر",modelId:"معرّف النموذج",modelIdPlaceholder:"gpt-4o، claude-3.5، gemini-2.0-flash، إلخ.",modelIdHelper:"معرّف النموذج الدقيق المستخدم عند استدعاء API",modelName:"الاسم المعروض",modelNamePlaceholder:"اسم عرض ودّي (اختياري)",modelNameHelper:"اسم اختياري يظهر في واجهة المستخدم. إذا تُرك فارغًا، سيُستخدم معرّف النموذج",group:"المجموعة",groupPlaceholder:"اختر أو أدخل اسم مجموعة",submit:"إضافة",cancel:"إلغاء",helper:"أدخل معرّف النموذج الدقيق الذي يعرضه API الخاص بالموفر."},editDialog:{title:"تعديل النموذج",subtitle:"تعديل إعدادات النموذج",modelId:"معرّف النموذج",modelIdPlaceholder:"معرّف النموذج",modelIdHelper:"معرّف النموذج المستخدم عند استدعاء API",modelName:"الاسم المعروض",modelNamePlaceholder:"اسم عرض ودّي",modelNameHelper:"الاسم المعروض في واجهة المستخدم",group:"المجموعة",groupPlaceholder:"اختر أو أدخل اسم مجموعة",submit:"حفظ",cancel:"إلغاء",vision:"قدرة الرؤية",visionHint:"ما إذا كان النموذج يدعم إدخال الصور/الرؤية",reasoning:"نموذج التفكير",reasoningHint:"ما إذا كان النموذج يدعم وضع التفكير/الاستدلال"},manageDialog:{title:"إدارة النماذج",cachedAt:"مخزّن مؤقتًا في {{date}} ({{source}})",refresh:"تحديث",close:"إغلاق",raw:"JSON خام",empty:"لا توجد نماذج بعيدة متاحة.",error:"فشل تحميل النماذج: {{message}}",addFromCatalog:"إضافة",sourceCache:"ذاكرة التخزين المؤقت",sourceNetwork:"مباشر",contextLength:"سياق {{value}} رمز",maxTokens:"الحد الأقصى {{value}} رمز"},messages:{added:"تمت إضافة النموذج.",updated:"تم تحديث النموذج.",removed:"تمت إزالة النموذج.",duplicate:"النموذج موجود بالفعل.",refreshed:"تم تحديث النماذج",refreshFailed:"فشل تحديث النماذج"},testDialog:{title:"اختبار اتصال النموذج",provider:"الموفر",model:"النموذج",testing:"جارٍ الاختبار...",success:"نجح الاختبار",successMessage:"يمكن الوصول إلى النموذج بشكل طبيعي",failure:"فشل الاختبار",aiResponse:"استجابة الذكاء الاصطناعي",charCount:"{{count}} حرف",duration:"المدة {{time}} ثانية",close:"إغلاق",retest:"إعادة الاختبار",testButton:"اختبار النموذج",unsupportedFormat:"الاختبار غير مدعوم لتنسيق هذا الموفر بعد."}},router:{title:"إعداد الموجِّه",description:"تهيئة الموفر/النموذج المستخدم لسيناريوهات مختلفة.",labels:{default:"افتراضي",background:"خلفية",think:"تفكير",longContext:"سياق طويل",webSearch:"بحث ويب",image:"صورة",longContextThreshold:"حد السياق الطويل"},helper:{longContextThreshold:"عدد الرموز قبل التبديل إلى نموذج السياق الطويل."},placeholder:{required:"مطلوب",optional:"اختياري"}},agentRouter:{title:"موجِّه الوكيل",description:"تهيئة التوجيه ثنائي الاتجاه بين وضعي المحادثة والبرمجة.",searchPlaceholder:"البحث عن الموجِّهات...",noSearchResults:"لا توجد موجِّهات تطابق بحثك.",tabs:{chatToCode:"محادثة ← برمجة",codeToChatPlaceholder:"برمجة ← محادثة"},chatToCode:{title:"موجِّه المحادثة إلى البرمجة",description:"استخدام موفري المحادثة في وضع الوكيل/البرمجة",addRouter:"إضافة موجِّه",emptyState:"لا توجد موجِّهات من محادثة إلى برمجة. أضف واحدًا لاستخدام موفري المحادثة في وضع البرمجة.",form:{name:"اسم الموجِّه",namePlaceholder:"موجِّهي من محادثة إلى برمجة",chatProvider:"موفر المحادثة",chatProviderPlaceholder:"اختر موفر محادثة",mode:"الوضع",modeSimple:"بسيط",modeAdvanced:"متقدم",modeSimpleDesc:"تمرير مباشر إلى موفر المحادثة",modeAdvancedDesc:"تهيئة تعيين النماذج ومعالجة السياق",enabled:"مُفعَّل",save:"حفظ الموجِّه",cancel:"إلغاء"},list:{provider:"الموفر",mode:"الوضع",status:"الحالة"},mappings:{title:"تعيينات النماذج",description:"تعيين نماذج موفر المحادثة إلى نماذج موفر البرمجة",count:"تعيين (تعيينات)",empty:"لا توجد تعيينات نماذج. أضف تعيينات لتوجيه نماذج المحادثة إلى موفري البرمجة.",addNew:"إضافة تعيين جديد",selectSource:"اختر النموذج المصدر (محادثة)",selectTarget:"اختر النموذج الهدف (برمجة)",targetPlaceholder:"أدخل اسم نموذج Claude Code",notSet:"(غير مضبوط - انقر للاختيار)",add:"إضافة",edit:"تعديل",done:"تم"},advanced:{title:"الإعداد المتقدم",description:"تهيئة النماذج لأنواع مختلفة من المهام",helpText:"النموذج الافتراضي مطلوب. النماذج الأخرى اختيارية وستعود إلى الافتراضي إذا لم تُهيَّأ.",default:{label:"افتراضي",placeholder:"اختر النموذج الافتراضي",description:"النموذج الأساسي للمهام العامة (مشابه لـ Claude Sonnet)"},background:{label:"خلفية",placeholder:"اختر نموذج الخلفية",description:"نموذج خفيف للمهام الخلفية (مشابه لـ Claude Haiku)"},think:{label:"تفكير",placeholder:"اختر نموذج التفكير",description:"نموذج متقدم للاستدلال المعقد (مشابه لـ Claude Opus)"},image:{label:"صورة",placeholder:"اختر نموذج الصور",description:"نموذج للمهام المتعلقة بالصور بقدرة الرؤية"}}},codeToChat:{title:"موجِّه البرمجة إلى المحادثة",description:"عرض نماذج خطة البرمجة في وضع المحادثة",addRouter:"إضافة موجِّه",emptyState:"لا توجد موجِّهات من برمجة إلى محادثة. أضف واحدًا لعرض نماذج خطة البرمجة في وضع المحادثة.",form:{name:"اسم الموجِّه",namePlaceholder:"موجِّهي من برمجة إلى محادثة",codeProvider:"موفر البرمجة",codeProviderPlaceholder:"اختر موفر برمجة",codeProviderHelper:"اختر موفر البرمجة المستخدم للتحويل",models:"نماذج خطة البرمجة",modelsHelper:"اختر نماذج خطة البرمجة التي تريد عرضها",enabled:"مُفعَّل",save:"حفظ الموجِّه",cancel:"إلغاء"},mappings:{title:"تعيينات النماذج",description:"تعيين نماذج موفر البرمجة إلى نماذج موفر المحادثة للعرض",count:"تعيين (تعيينات)",empty:"لا توجد تعيينات نماذج. أضف تعيينات لعرض نماذج البرمجة في وضع المحادثة.",addNew:"إضافة تعيين جديد",selectSource:"اختر النموذج المصدر (برمجة)",selectTarget:"اختر النموذج الهدف (محادثة)",sourcePlaceholder:"أدخل اسم النموذج المصدر",targetPlaceholder:"أدخل اسم النموذج الهدف",add:"إضافة",edit:"تعديل",done:"تم"}},transformers:{title:"المحوِّلات",description:"تهيئة المحوِّلات لتحويل الطلبات والاستجابات",noProvider:"اختر موفرًا لتهيئة المحوِّلات",empty:"لا توجد محوِّلات",count:"{{count}} محوِّل (محوِّلات)"},status:{enabled:"مُفعَّل",disabled:"مُعطَّل"},messages:{routerAdded:"تمت إضافة الموجِّه بنجاح",routerUpdated:"تم تحديث الموجِّه بنجاح",routerDeleted:"تم حذف الموجِّه بنجاح",saveFailed:"فشل حفظ الموجِّه"}},presets:{title:"إضافة موفر سريعة",added:"تمت الإضافة",add:"إضافة",features:{search:"بحث",vision:"رؤية",mcp:"MCP",codingPlan:"خطة البرمجة"}},alerts:{deleteConfirm:"هل أنت متأكد من حذف هذا الموفر؟"},errors:{nameRequired:"اسم الموفر مطلوب",urlRequired:"عنوان URL الأساسي لـ API مطلوب",urlInvalid:"يرجى إدخال عنوان URL صحيح (مثال: https://api.example.com)",saveFailed:"فشل حفظ الموفر",deleteFailed:"خطأ في حذف الموفر. يرجى المحاولة مجددًا.",toggleFailed:"خطأ في تبديل حالة الموفر. يرجى المحاولة مجددًا."},openRouter:{title:"توجيه موفر OpenRouter",description:"تهيئة كيفية توجيه الطلبات إلى موفرين مختلفين على OpenRouter.",sort:"استراتيجية التوجيه",sortTooltip:"اختر كيفية تحديد أولوية الموفرين. يستخدم الوضع التلقائي موازنة تحميل ذكية.",order:"ترتيب أولوية الموفر",orderTooltip:"حدد الموفرين المراد تجربتهم بالترتيب (مثال: anthropic، openai، together). اضغط Enter للإضافة.",orderPlaceholder:"اكتب معرّف الموفر واضغط Enter...",allowFallbacks:"السماح بالاحتياط",allowFallbacksTooltip:"عند التفعيل، سيجرب OpenRouter موفرين احتياطيين إذا كان الأساسي غير متاح.",requireParameters:"طلب جميع المعاملات",requireParametersTooltip:"التوجيه فقط إلى الموفرين الذين يدعمون جميع المعاملات في طلبك.",dataCollection:"سياسة جمع البيانات",dataCollectionTooltip:"تحكم في ما إذا كنت تستخدم موفرين قد يخزنون بياناتك أو يتدربون عليها.",zdr:"صفر احتفاظ بالبيانات",zdrTooltip:"التوجيه فقط إلى نقاط نهاية ذات سياسة صفر احتفاظ بالبيانات.",only:"السماح بموفرين محددين فقط",onlyTooltip:"استخدام هؤلاء الموفرين المحددين فقط. اتركه فارغًا للسماح بجميع الموفرين.",onlyPlaceholder:"اكتب معرّف الموفر واضغط Enter...",ignore:"تجاهل الموفرين",ignoreTooltip:"تخطي هؤلاء الموفرين عند توجيه الطلبات.",ignorePlaceholder:"اكتب معرّف الموفر واضغط Enter...",quantizations:"فلتر الضغط الكمي",quantizationsTooltip:"استخدام موفرين بمستويات ضغط كمي محددة فقط. الدقة المنخفضة قد تقلل الجودة لكن تحسّن السرعة.",maxPrice:"السعر الأقصى",maxPriceTooltip:"تعيين حدود سعر أقصى لكل مليون رمز. اتركه فارغًا لعدم تحديد سقف.",configured:"مُهيَّأ"}},QP={label:"وضع API",standard:"قياسي",codingPlan:"خطة البرمجة",tokenPlan:"خطة الرموز",apiKeyPrefixHint:"تبدأ مفاتيح هذه الخطة عادةً بـ `{{prefix}}`. تلميح فقط — غير مُطبَّق.",dashscopeCodingPlanSeparateKey:"تستخدم خطة برمجة DashScope مفتاح API منفصلًا عن نقطة النهاية القياسية.",baiduCodingPlanSeparateKey:"تستخدم خطة برمجة Qianfan مفتاح API منفصلًا عن نقطة النهاية القياسية.",tencentTokenPlanAnthropicOnly:"خطة رموز Tencent تعمل ببروتوكول Anthropic فقط.",xiaomiTokenPlanRegions:"عنوان URL الأساسي الافتراضي هو `token-plan-cn.*`. يمكنك تعديله يدويًا إلى `token-plan-sgp.*` أو `token-plan-ams.*`.",confirmOverwriteTitle:"تبديل وضع API؟",confirmOverwriteBody:"لقد خصصت عنوان URL لـ API أو مفتاح API. سيؤدي تبديل الأوضاع إلى الكتابة فوقهما بالإعدادات الافتراضية للوضع الجديد — أو يمكنك الاحتفاظ بتخصيصاتك وتحديث تسمية الوضع فقط.",overwriteAndSwitch:"الكتابة فوق والتبديل",keepCustomizations:"الاحتفاظ بالتخصيصات"},YP={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (خطة الرموز)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},XP={cancel:"إلغاء",close:"إغلاق",copy:"نسخ",delete:"حذف",dismiss:"رفض",save:"حفظ",optional:"اختياري",retry:"إعادة المحاولة",loading:"جارٍ التحميل…"},JP={common:{learnMore:"الوثائق"}},eA={notSupportedByDaemon:"غير مدعوم بعد من قِبَل Daemon",discoveryUnsupportedFormat:"اكتشاف النماذج غير مدعوم لتنسيق هذا الموفر بعد. أضف النماذج يدويًا."},tA={subtitle:"لوحة التحكم",providers:"الموفرون",apiService:"خدمة API",accounts:"الحسابات",codeCli:"واجهة سطر أوامر البرمجة",settings:"الإعدادات",usageStats:"الاستخدام",pricing:"الأسعار"},aA={title:"خدمة API",description:"تهيئة خادم API الصادر، وتوجيه النماذج لكل نقطة نهاية، ومفاتيح الوصول المسماة.",loading:"جارٍ تحميل إعداد الخادم…",loadError:"تعذّر تحميل إعداد الخادم. تحقق من إمكانية الوصول إلى Daemon.",enable:{label:"تفعيل الخادم الصادر",description:"تشغيل خادم API المحلي الذي يوجّه المتصلين الخارجيين عبر موفريك."},networkBinding:{label:"السماح بوصول الشبكة المحلية",description:"ربط الخادم بواجهة الشبكة بدلًا من الاسترجاع المحلي فقط.",warning:"يُعرّض وصول الشبكة المحلية خادم API لأجهزة أخرى على شبكتك. مقترنًا بتوجيه الاشتراك، يمكن للطلبات استهلاك حصة اشتراكك — أبقِه معطّلًا ما لم تثق بالشبكة."},status:{running:"الخادم يعمل",stopped:"الخادم متوقف",runningHint:"خادم API الصادر يقبل الطلبات.",stoppedHint:"فعّل الخادم لبدء قبول الطلبات.",port:"المنفذ {{port}}",loopback:"عناوين URL الاسترجاع المحلي",lan:"عناوين URL الشبكة المحلية"},endpoints:{title:"توجيه نقاط النهاية",description:"اختر النموذج الذي يوجّه إليه كل تنسيق سلكي. النموذج الافتراضي يندمج هنا — الخادم موجِّه وليس تطبيق محادثة."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"النموذج الافتراضي",backgroundModel:"نموذج الخلفية",visionModel:"نموذج الرؤية",noVisionModel:"لا يوجد",backgroundModelIds:"معرّفات نموذج الخلفية",backgroundModelIdsPlaceholder:"معرّفات نماذج مفصولة بفواصل",modelPlaceholder:"اختر نموذجًا…",useSubscription:"استخدام الاشتراك",subscriptionUnsupported:"توجيه الاشتراك غير متاح لهذه النقطة."},keys:{title:"مفاتيح الوصول",description:"مفاتيح مسماة يرسلها المتصلون الخارجيون كرمز Bearer. يظهر المفتاح الكامل مرة واحدة فقط عند الإنشاء.",namePlaceholder:"اسم المفتاح (مثال: واجهتي-سطر-أوامر)",create:"إنشاء مفتاح",empty:"لا توجد مفاتيح وصول بعد.",enabled:"مُفعَّل",disabled:"مُعطَّل",revoked:"مُلغى",toggle:"تبديل المفتاح",revoke:"إلغاء",revokeConfirmTitle:"إلغاء هذا المفتاح؟",revokeConfirmDesc:'إلغاء "{{name}}" يوقف مصادقته فورًا. لا يمكن التراجع عن هذا.',created:{title:"تم إنشاء المفتاح",warning:"انسخ هذا المفتاح الآن — لن يُعرض مجددًا. احفظه في مكان آمن.",copy:"نسخ",copied:"تم النسخ",dismiss:"تم"}}},nA={title:"الحسابات والاشتراكات",description:"إدارة بيانات اعتماد الاشتراك التي يوجِّه من خلالها الخادم. تُكتب الرموز هنا ولا تُعرض مجددًا.",loading:"جارٍ تحميل الحسابات…",empty:"لا يوجد موفرو اشتراك متاحون.",signIn:"تسجيل الدخول",oauth:{title:"تسجيل الدخول إلى {{name}}",description:"افتح صفحة تسجيل الدخول في متصفحك، وامنح الإذن، ثم الصق رمز التفويض أدناه. يُرسل الرمز إلى Daemon فقط — الرمز المُنشأ لا يُعرض أبدًا.",openPage:"فتح صفحة تسجيل الدخول",codeLabel:"رمز التفويض",codePlaceholder:"الصق الرمز هنا",submit:"إتمام تسجيل الدخول"},codexOauth:{title:"تسجيل الدخول إلى {{name}}",description:"افتح صفحة تسجيل الدخول في متصفحك وامنح الإذن. يلتقط Daemon النتيجة تلقائيًا — أبقِ هذه النافذة مفتوحة حتى الاكتمال. لا يُعرض الرمز أبدًا.",waiting:"في انتظار إتمام تسجيل الدخول في متصفحك…",failed:"فشل تسجيل الدخول. يرجى المحاولة مجددًا."},clearProvider:"مسح الكل",clearConfirmTitle:"مسح حسابات {{name}}؟",clearConfirmDesc:"سيؤدي هذا إلى إزالة جميع بيانات الاعتماد المخزنة لهذا الموفر. لا يمكن التراجع عن هذا.",credential:{ok:"مُهيَّأ",notConfigured:"غير مُهيَّأ"},kind:{"pass-through":"بيانات اعتماد مرور مباشر","oauth-bearer":"Bearer من OAuth","static-bearer":"مفتاح Bearer ثابت"},reason:{"missing-credential":"لا توجد بيانات اعتماد مخزنة.",expired:"انتهت صلاحية بيانات الاعتماد.","reauth-required":"إعادة المصادقة مطلوبة.","refresh-failed":"فشل تحديث الرمز.","not-refreshable":"بيانات الاعتماد غير قابلة للتحديث.",unknown:"الحالة غير معروفة."},status:{unconfigured:"غير مُهيَّأ",authorized:"مُصرَّح به",configured:"مُهيَّأ",expired:"منتهي الصلاحية",error:"خطأ"},authMethod:{oauth:"OAuth",setup_token:"رمز الإعداد",manual:"يدوي"},list:{empty:"لا توجد حسابات مخزنة لهذا الموفر.",active:"نشط",expiresAt:"ينتهي {{value}}",setActive:"تعيين كنشط",remove:"إزالة",removeConfirmTitle:"إزالة هذا الحساب؟",removeConfirmDesc:'إزالة "{{name}}" يحذف بيانات اعتماده المخزنة. لا يمكن التراجع عن هذا.',title:"الحسابات"},write:{trigger:"إضافة بيانات اعتماد",title:"كتابة بيانات اعتماد {{name}}",description:"الصق مواد الرمز التي تم الحصول عليها مسبقًا. الحقول محدودة بما يقبله هذا الموفر؛ يُخزَّن الرمز ولا يُعرض مجددًا.",authMethod:"طريقة المصادقة",status:"الحالة",subscriptionLevel:"مستوى الاشتراك",subscriptionLevelNone:"غير مضبوط",submit:"حفظ بيانات الاعتماد"},field:{accessToken:"رمز الوصول",refreshToken:"رمز التحديث",idToken:"رمز الهوية",apiKey:"مفتاح API",expiresAt:"ينتهي في (ISO)",setupTokenExpiresAt:"رمز الإعداد ينتهي في (ISO)",accountId:"معرّف الحساب",email:"البريد الإلكتروني",organizationId:"معرّف المؤسسة",baseUrl:"عنوان URL الأساسي",zenBaseUrl:"عنوان URL الأساسي لـ Zen"},provider:{claude:{title:"Claude",description:"بيانات اعتماد اشتراك Anthropic التي يوجّهها Daemon."},codex:{title:"Codex",description:"بيانات اعتماد اشتراك OpenAI Codex التي يوجّهها Daemon."},gemini:{title:"Gemini",description:"بيانات اعتماد اشتراك Google Gemini التي يوجّهها Daemon."},opencodego:{title:"OpenCodeGo",description:"بيانات اعتماد مفتاح API ثابتة يوجّهها Daemon."}},authMethodLabel:"طريقة التفويض",authMethodDesc:{oauth:"تسجيل الدخول عبر متصفحك؛ يلتقط Daemon الرمز ويخزّنه.",manual:"الصق رمزًا تم الحصول عليه مسبقًا. يُخزَّن ولا يُعرض مجددًا."},actions:{authorize:"تفويض",enterToken:"إدخال الرمز",refresh:"تحديث"},accounts:{addAccount:"إضافة حساب"},detail:{authMethod:"طريقة التفويض",subscriptionLevel:"مستوى الاشتراك",expiresAt:"ينتهي",lastRefreshed:"آخر تحديث",label:"تسمية الحساب",labelPlaceholder:"أعطِ هذا الحساب اسمًا",saveLabel:"حفظ التسمية"},oauthFlow:{step1:{title:"فتح صفحة التفويض",desc:"افتح صفحة تسجيل الدخول في متصفحك."},step2:{title:"منح الوصول",desc:"سجّل الدخول وامنح الوصول للموفر."},step3:{title:"نسخ رمز التفويض",desc:"تعرض الصفحة رمز تفويض بعد الموافقة."},step4:{title:"لصق الرمز",desc:"الصق رمز التفويض أدناه للإتمام. يُرسل الرمز إلى Daemon فقط — الرمز المُنشأ لا يُعرض أبدًا."},authorize:"إتمام تسجيل الدخول",showUrl:"إظهار عنوان URL للتفويض"},manual:{title:"لصق بيانات الاعتماد",description:"الصق رمزًا تم الحصول عليه مسبقًا. الحقول محدودة بما يقبله هذا الموفر؛ يُخزَّن الرمز ولا يُعرض مجددًا.",accessTokenPlaceholder:"الصق رمز الوصول",refreshTokenPlaceholder:"الصق رمز التحديث (اختياري)",hint:"يُرسَل الرمز إلى Daemon ويُخزَّن مشفرًا. لا يُعرض مجددًا."},openCodeGo:{apiKeyRequired:"مفتاح API مطلوب.",apiKeyPlaceholder:"الصق مفتاح API",baseUrlPlaceholder:"https://… (اختياري)",zenBaseUrlPlaceholder:"https://… (اختياري)"},info:{title:"حول حسابات الاشتراك",description:"تُكتب الرموز إلى Daemon وتُستخدم لمصادقة الطلبات المتجهة للخارج. تُخزَّن مشفرة ولا تُعرض مجددًا. إزالة الحساب تحذف بيانات اعتماده المخزنة."},rename:{failed:"تعذّر إعادة تسمية الحساب."},refresh:{failed:"تعذّر تحديث الرمز."},errors:{requestFailed:"فشل الطلب. يرجى المحاولة مجددًا."},syncWarning:{"external-divergent":"يحتوي ملف تسجيل الدخول الخاص بـ CLI الخارجي على بيانات اعتماد أحدث من هذا الحساب. قد يتوقف الرمز المخزَّن عن التحديث — حدِّث الآن أو سجِّل الدخول مجددًا.","external-not-rotated":"فشل التحديث، ويحتوي CLI الخارجي على بيانات الاعتماد المنتهية الصلاحية نفسها. يُرجى تسجيل الدخول مجددًا.","duplicate-token":"حساب آخر يشارك بيانات الاعتماد هذه. تحديث أي منهما سيؤدي إلى تسجيل خروج الآخر."},importExternal:{detected:"تم العثور على تسجيل دخول CLI لـ {{name}} موجود على هذا الجهاز.",hint:"بعد الاستيراد، يحافظ هذا التطبيق على تحديثه: عند كل تحديث للرمز يتم أيضًا تحديث ملف تسجيل دخول CLI، فيبقى CLI في الطرفية مسجلاً للدخول.",button:"استيراد تسجيل دخول CLI الحالي"}},oA={title:"واجهة سطر أوامر البرمجة",description:"توجيه واجهة سطر أوامر البرمجة إلى الوكيل الوسيط لـ Daemon. هذه الصفحة للقراءة فقط — لا يوجد شيء للتهيئة هنا.",copy:"نسخ",copied:"تم النسخ",baseUrl:{title:"عنوان URL الأساسي لـ Daemon",description:"عنوان الوكيل الوسيط الذي تتصل به واجهة سطر الأوامر.",label:"عنوان URL الأساسي"},token:{title:"المصادقة",hint:"أرسل 'Authorization: Bearer <رمز-الإدارة>' للمسارات الإدارية. يُهيَّأ رمز الإدارة في Daemon (ملف الإعداد أو بيئة التشغيل) — لا يُعرض هنا."},examples:{title:"مثال على بيئة التشغيل",keyNote:"استخدم مفتاح وصول صادر تم إنشاؤه في صفحة خدمة API — وليس رمز الإدارة.",anthropic:"واجهة سطر أوامر بتنسيق Anthropic",openai:"واجهة سطر أوامر بتنسيق OpenAI"},launchDescription:"تشغيل واجهة سطر أوامر البرمجة في طرفية، موجَّهة إلى هذا Daemon. يُدخل Daemon بيئة إعادة التوجيه ويشغّل واجهة سطر الأوامر نيابةً عنك.",refresh:"تحديث",loading:"جارٍ الكشف عن واجهات سطر الأوامر…",cli:{installed:"مُثبَّت",notFound:"غير موجود",notFoundHint:"واجهة سطر الأوامر هذه ليست في PATH الخاص بمضيف Daemon. ثبّتها ثم حدّث.",install:"تثبيت",installing:"جارٍ التثبيت…",installingHint:"جارٍ التثبيت على مضيف Daemon — قد يستغرق ذلك دقيقة.",launch:"تشغيل",launchTitle:"تشغيل {{name}}",launchDescription:"يفتح طرفية جديدة على مضيف Daemon تشغّل واجهة سطر الأوامر هذه، موجَّهة عبر وكيل Daemon الوسيط. اختر دليل عمل اختياري.",cwdLabel:"دليل العمل",cwdPlaceholder:"/مسار/مشروعك",runningVia:"يعمل · {{provider}} / {{model}}",stop:"إيقاف"},manual:{title:"الإعداد اليدوي",description:"تفضّل تشغيل واجهة سطر الأوامر بنفسك؟ وجّهها إلى Daemon باستخدام متغيرات البيئة هذه.",show:"إظهار",hide:"إخفاء"}},iA={probing:"جارٍ التحقق من Daemon…",spawning:"جارٍ تشغيل Daemon…",failed:"تعذّر تشغيل Daemon",failedHint:"تأكد من تثبيت Node.js وبناء Daemon (وجود dist)، أو اضبط OMNICROSS_DAEMON_ENTRY على مسار cli.js الخاص بـ Daemon."},rA={title:"الإعدادات",description:"تفضيلات تطبيق سطح المكتب.",desktopOnly:"خيارات بدء التشغيل وشريط المهام تنطبق فقط على تطبيق سطح المكتب.",startup:{title:"بدء التشغيل",autoLaunch:"التشغيل عند تسجيل الدخول",autoLaunchHint:"تشغيل Omnicross تلقائيًا عند تسجيل دخولك.",startMinimized:"البدء مصغّرًا إلى شريط المهام",startMinimizedHint:"التشغيل في الخلفية دون فتح النافذة."},tray:{title:"شريط المهام",minimizeOnClose:"التصغير إلى شريط المهام عند الإغلاق",minimizeOnCloseHint:"إغلاق النافذة يخفيها إلى شريط المهام بدلًا من الإنهاء."},language:{title:"اللغة",label:"لغة الواجهة"}},sA={title:"إحصاءات الاستخدام",description:"إحصاءات الرموز والتكاليف للطلبات التي خدمها البرنامج الخفي.",rangeToday:"اليوم",range7d:"آخر 7 أيام",range30d:"آخر 30 يومًا",rangeCustom:"مخصص",from:"من",to:"إلى",totalCost:"التكلفة الإجمالية",cacheSavings:"توفير الذاكرة المؤقتة",events:"الطلبات",inputTokens:"رموز الإدخال",outputTokens:"رموز الإخراج",cacheReadTokens:"قراءة الذاكرة المؤقتة",cacheWriteTokens:"كتابة الذاكرة المؤقتة",reasoningTokens:"رموز الاستدلال",byModel:"حسب النموذج",byApiKey:"حسب مفتاح API",provider:"المزوّد",model:"النموذج",cost:"التكلفة",apiKey:"مفتاح API",unpriced:"بدون سعر",unpricedHint:"لا يوجد إدخال سعر لهذا النموذج — أضِفه في صفحة الأسعار.",unattributed:"غير منسوب",unattributedHint:"طلبات غير مرتبطة بمفتاح API محدد. هذا متوقع حتى يبدأ تسجيل النسبة لكل مفتاح.",empty:"لا توجد طلبات في هذا النطاق.",invalidRange:"اختر نطاق تواريخ صالحًا."},lA={title:"أسعار النماذج",description:"أسعار الرموز لكل نموذج المستخدمة لحساب تكاليف الطلبات، بالدولار الأمريكي لكل مليون رمز.",search:"ابحث عن مزوّد أو نموذج…",fetchLatest:"جلب الأحدث",fetching:"جارٍ الجلب…",addEntry:"إضافة إدخال",provider:"المزوّد",model:"النموذج",inputPrice:"الإدخال",outputPrice:"الإخراج",cacheReadPrice:"قراءة الذاكرة المؤقتة",cacheWritePrice:"كتابة الذاكرة المؤقتة",source:"المصدر",updated:"آخر تحديث",userEdited:"معدّل",edit:"تعديل",deleteTitle:"حذف إدخال السعر؟",empty:"جدول الأسعار فارغ.",emptyHint:"اجلب أحدث الأسعار لملئه.",noMatches:"لا توجد إدخالات مطابقة لبحثك.",saved:"تم حفظ إدخال السعر.",saveFailed:"فشل الحفظ: {{message}}",deleteFailed:"فشل الحذف: {{message}}",alreadyDeleted:"الإدخال لم يعد موجودًا.",fetchApplied:"تم تحديث {{count}} إدخالًا من المصدر.",fetchFailed:"فشل الجلب: {{message}}",requiredId:"مطلوب",invalidPrice:"أدخل رقمًا غير سالب",conflictTitle:"حل تعارضات الأسعار",conflictHint:"هذه الإدخالات عدّلتها أنت وتغيّرت أيضًا في المصدر. اختر لكل صف الاحتفاظ بقيمتك (تخطّي) أو اعتماد القيمة الواردة (استبدال).",current:"الحالي",incoming:"الوارد",overwrite:"استبدال",skip:"تخطّي",overwriteAll:"استبدال الكل",skipAll:"تخطّي الكل",applyResolutions:"تطبيق",resolved:"تم استبدال {{overwritten}} وتخطّي {{skipped}}.",resolvedWithStale:"تم استبدال {{overwritten}} وتخطّي {{skipped}}. تغيّر {{stale}} في هذه الأثناء وتُرك دون تغيير.",refreshFailed:"تم تطبيق التغيير، لكن فشلت إعادة تحميل القائمة: {{message}}",sourceBuiltin:"مدمج",sourceLitellm:"LiteLLM",sourceUser:"المستخدم"},dA={providerSettings:ZP,apiMode:QP,presetName:YP,common:XP,mediaSettings:JP,appLocal:eA,nav:tA,apiService:aA,accounts:nA,codeCli:oA,daemonStatus:iA,settings:rA,usageStats:sA,pricing:lA},cA={loading:"Зареждане на LLM конфигурацията...",reset:{button:"Възстанови настройките по подразбиране",confirmTitle:"Да се възстановят ли настройките по подразбиране?",confirmBody:"Това ще изчисти вашите персонализации за този доставчик и той отново ще следва вградените настройки по подразбиране. Вашият API ключ и запазените сесии се запазват.",confirmButton:"Възстанови настройките по подразбиране"},reentryBanner:{message:"{{count}} активиран(-и) доставчик(-ци) изискват повторно въвеждане на API ключ. Отворете всеки от тях и добавете ключа отново."},migrationPack:{barHint:"Прехвърлете ключовете на доставчиците и токените на абонаментите на друга машина с криптиран пакет.",passphrase:"Парола-фраза",passphrasePlaceholder:"Въведете парола-фраза",passphraseHint:"Използвайте поне 8 символа; препоръчват се 12 или повече.",confirm:"Потвърди парола-фраза",confirmPlaceholder:"Въведете паролата-фраза отново",mismatch:"Паролите-фрази не съвпадат.",strength:{weak:"Твърде кратка — използвайте поне 8 символа.",fair:"Приемливо — 12 или повече символа е по-надеждно.",strong:"Надеждна парола-фраза."},export:{button:"Експортирай пакет",title:"Експортиране на криптиран пакет",subtitle:"Криптирайте ключовете на доставчиците и токените на абонаментите в преносим файл.",warning:"Този файл съдържа разшифровуеми тайни. Пазете го на сигурно място — всеки, който има файла и паролата-фраза, може да прочете вашите ключове. Изгубена парола-фраза не може да бъде възстановена.",submit:"Експортирай",success:"Пакетът е успешно експортиран.",error:"Експортирането не успя. Моля, опитайте отново."},import:{button:"Импортирай пакет",title:"Импортиране на криптиран пакет",subtitle:"Възстановете ключовете на доставчиците и токените на абонаментите от експортиран пакет.",hint:"Въведете паролата-фраза, използвана при експортирането на пакета, след което изберете файла.",submit:"Импортирай",successTitle:"Импортирането е завършено",summary:"Импортирани {{providerKeys}} ключ(-а) на доставчик, {{poolKeys}} ключ(-а) на пул и {{tokenSets}} набор(-и) от токени.",duplicates:"Пропуснати {{count}} ключ(-а) на пул, вече присъстващи.",skipped:"Пропуснато (няма съответстващ доставчик): {{names}}",error:"Грешна парола-фраза или повреден пакет. Нищо не е променено."}},searchPlaceholder:"Търсене на доставчици...",emptySearch:"Няма доставчици, съответстващи на търсенето.",emptyList:"Няма конфигурирани доставчици.",selectPrompt:"Изберете доставчик за преглед на подробности",listStatus:"{{count}} модел(-и)",noModels:"Няма конфигурирани модели",enabled:"Активиран",disabled:"Деактивиран",showEnabledOnly:"Показвай само активираните",showAll:"Показвай всички доставчици",dragHandle:"Плъзнете за пренареждане",reorderFailed:"Неуспешно запазване на реда на доставчиците",credentials:{apiKey:"API ключ",apiBaseUrl:"Основен URL на API"},filter:{all:"Всички",chat:"Чат",code:"Код"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Изберете шаблон",skipTemplates:"Пропусни, конфигурирай ръчно",name:"Име *",providerType:"Тип",apiType:"Тип API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Стандартен формат на API OpenAI chat/completions",claudecode:"Формат на API Anthropic Messages (Claude Code)"},chatApiFormat:"Формат на API",chatApiFormatDescription:"Изберете формата на API, съответстващ на крайната точка на вашия доставчик",apiKey:"API ключ",apiKeyPlaceholder:"sk-... или $ENV_VAR",apiKeyHelper:"Използвайте $VAR_NAME за препратка към променливи на средата",apiKeySetPlaceholder:"Ключът е зададен — оставете празно за запазване на текущия",apiKeyReplaceHelper:"Ключът е съхранен сигурно. Въведете ново стойност за замяна или оставете полето празно.",testApiKey:"Тествай API ключ",apiUrl:"URL на API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Преглед:",models:"Модели",modelPlaceholder:"Име на модела (напр. gpt-4, claude-3-opus)",transformers:"Трансформатори",transformerConfig:"Трансформатори на API",transformerConfigDescription:"Конфигурирайте трансформатори за адаптиране на форматите на заявки/отговори на API за този доставчик",transformerConfigNote:"Демонът прилага тези трансформатори в веригата на заявките, след трансформатора на формата на доставчика (който обработва конвертирането на формата). Непознатите имена на трансформатори се пропускат.",enabled:"Активиран",apiVersion:"Версия на API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Версия на API Azure OpenAI (напр. 2024-08-01-preview)",official:"Официален Anthropic API",officialHelper:"Активирайте, ако този доставчик се свързва директно с официалния Anthropic API. Деактивирайте за обратни прокси или услуги на трети страни.",maxConcurrency:"Макс. едновременни заявки",maxConcurrencyHelper:"Максимален брой едновременни API заявки към този доставчик. По-ниски стойности помагат да се избегне ограничаване на честотата (грешки 429). Задайте `-1` за без ограничение.",codingPlan:{label:"Абонаментен план за кодиране",description:"Използвайте отделна крайна точка на API за абонаментни планове за кодиране",baseUrl:"Основен URL на плана за кодиране",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"API ключ на плана за кодиране (по желание)",apiKeyPlaceholder:"Оставете празно за използване на API ключа на доставчика",apiKeyHelper:"Необходим само ако планът за кодиране използва различен API ключ",tokenPlanHint:"Някои доставчици (напр. Xiaomi MiMo) издават ключове Token Plan с префикс `tp-` — само информационно, не се прилага."},selectTypeFirst:"Изберете тип доставчик",selectTypeFirstDesc:"Изберете какъв тип доставчик искате да добавите",codeProviderNote:"Доставчиците на код се нуждаят само от API ключ и URL. Моделите се управляват от маршрутизатора на агентите.",buttons:{cancel:"Отказ",submitAdd:"Добави доставчик",submitUpdate:"Актуализирай доставчик",continue:"Продължи",back:"Назад"}},details:{noSelection:"Изберете доставчик за преглед на подробности",apiKey:"API ключ",apiUrl:"URL на API",nameLabel:"Име на доставчика",modelsEndpoint:"Крайна точка на моделите",modelsEndpointHelper:"Заменете крайната точка за откриване, ако доставчикът предоставя персонализиран път /models.",models:"Модели",transformers:"Трансформатори",codeProviderNote:"Доставчиците на код (като Claude Code) не изискват конфигурация на модели. Моделите се управляват автоматично от маршрутизатора на агентите.",buttons:{more:"Още настройки",delete:"Изтрий"}},providerModelSelector:{placeholder:"Изберете доставчик и модел",noProviders:"Няма налични доставчици",noModels:"Няма конфигурирани модели"},apiKeyPool:{title:"Пул от API ключове",description:"Конфигурирайте множество API ключове за балансиране на натоварването. Всяка сесия се придържа към един ключ за запазване на кеша на подканите.",defaultLabel:"По подразбиране",weight:"Тегло",noKey:"Без ключ",labelPlaceholder:"Етикет (напр. Ключ №1, Производствен)",addKey:"Добави API ключ",add:"Добави",empty:"Няма конфигурирани допълнителни ключове.",statusCoolingDown:"Охлаждане {{time}}",statusAuthFailed:"Неуспешна автентикация · деактивиран",statusDisabled:"Деактивиран",statusHealthy:"Активен",agoSeconds:"преди {{count}} с",agoMinutes:"преди {{count}} мин",agoHours:"преди {{count}} ч",agoDays:"преди {{count}} д"},modelsManager:{searchPlaceholder:"Търсене на модели...",defaultGroup:"Всички модели",add:"Добави модел",manage:"Управление",empty:"Няма модели в тази група",enabled:"Активиран",disabled:"Деактивиран",filters:{all:"Всички",vision:"Визия",reasoning:"Разсъждение",free:"Безплатни",tools:"Инструменти"},manualDialog:{title:"Добави модел",subtitle:"Добавете персонализиран модел към този доставчик",modelId:"Идентификатор на модела",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash и др.",modelIdHelper:"Точният идентификатор на модела, използван при извикване на API",modelName:"Показвано име",modelNamePlaceholder:"Удобно показвано име (по желание)",modelNameHelper:"Незадължително име, показвано в интерфейса. Ако е празно, ще се използва идентификаторът на модела",group:"Група",groupPlaceholder:"Изберете или въведете име на група",submit:"Добави",cancel:"Отказ",helper:"Посочете точния идентификатор на модела, предоставен от API на доставчика."},editDialog:{title:"Редактирай модел",subtitle:"Промяна на настройките на модела",modelId:"Идентификатор на модела",modelIdPlaceholder:"Идентификатор на модела",modelIdHelper:"Идентификаторът на модела, използван при извикване на API",modelName:"Показвано име",modelNamePlaceholder:"Удобно показвано име",modelNameHelper:"Името, показвано в интерфейса",group:"Група",groupPlaceholder:"Изберете или въведете име на група",submit:"Запази",cancel:"Отказ",vision:"Визуална способност",visionHint:"Дали моделът поддържа въвеждане на изображения/визия",reasoning:"Модел с мислене",reasoningHint:"Дали моделът поддържа режим на мислене/разсъждение"},manageDialog:{title:"Управление на модели",cachedAt:"Кеширан на {{date}} ({{source}})",refresh:"Обнови",close:"Затвори",raw:"Необработен JSON",empty:"Няма налични отдалечени модели.",error:"Неуспешно зареждане на модели: {{message}}",addFromCatalog:"Добави",sourceCache:"кеш",sourceNetwork:"мрежа",contextLength:"Контекст {{value}} токена",maxTokens:"Макс. {{value}} токена"},messages:{added:"Моделът е добавен.",updated:"Моделът е актуализиран.",removed:"Моделът е премахнат.",duplicate:"Моделът вече съществува.",refreshed:"Моделите са обновени",refreshFailed:"Неуспешно обновяване на моделите"},testDialog:{title:"Тест за свързаност на модела",provider:"Доставчик",model:"Модел",testing:"Тестване...",success:"Тестът е успешен",successMessage:"Моделът е достъпен и работи нормално",failure:"Тестът неуспешен",aiResponse:"Отговор на ИИ",charCount:"{{count}} символа",duration:"Продължителност {{time}} с",close:"Затвори",retest:"Повторен тест",testButton:"Тествай модел",unsupportedFormat:"Тестването все още не се поддържа за този формат на доставчика."}},router:{title:"Конфигурация на маршрутизатор",description:"Конфигурирайте кой доставчик/модел да се използва за различни сценарии.",labels:{default:"По подразбиране",background:"фонов",think:"мислене",longContext:"Дълъг контекст",webSearch:"Уеб търсене",image:"Изображение",longContextThreshold:"Праг за дълъг контекст"},helper:{longContextThreshold:"Брой токени преди превключване към модела с дълъг контекст."},placeholder:{required:"Задължително",optional:"По желание"}},agentRouter:{title:"Маршрутизатор на агенти",description:"Конфигурирайте двупосочна маршрутизация между режимите на чат и код.",searchPlaceholder:"Търсене на маршрутизатори...",noSearchResults:"Няма маршрутизатори, съответстващи на търсенето.",tabs:{chatToCode:"Чат → Код",codeToChatPlaceholder:"Код → Чат"},chatToCode:{title:"Маршрутизатор Чат → Код",description:"Използвайте доставчици на чат в режим агент/кодиране",addRouter:"Добави маршрутизатор",emptyState:"Няма конфигурирани маршрутизатори Чат→Код. Добавете един, за да използвате доставчици на чат в режим на кодиране.",form:{name:"Име на маршрутизатора",namePlaceholder:"Моят маршрутизатор Чат→Код",chatProvider:"Доставчик на чат",chatProviderPlaceholder:"Изберете доставчик на чат",mode:"Режим",modeSimple:"Прост",modeAdvanced:"Разширен",modeSimpleDesc:"Директно предаване към доставчика на чат",modeAdvancedDesc:"Конфигурирайте съпоставяне на модели и обработка на контекст",enabled:"Активиран",save:"Запази маршрутизатор",cancel:"Отказ"},list:{provider:"Доставчик",mode:"Режим",status:"Статус"},mappings:{title:"Съпоставяния на модели",description:"Съпоставете моделите на доставчика на чат с моделите на доставчика на код",count:"съпоставяния(-е)",empty:"Няма конфигурирани съпоставяния на модели. Добавете съпоставяния за маршрутизиране на модели за чат към доставчици на код.",addNew:"Добави ново съпоставяне",selectSource:"Изберете изходен модел (Чат)",selectTarget:"Изберете целеви модел (Код)",targetPlaceholder:"Въведете име на модела Claude Code",notSet:"(Не е зададено — щракнете за избор)",add:"Добави",edit:"Редактирай",done:"Готово"},advanced:{title:"Разширена конфигурация",description:"Конфигурирайте модели за различни типове задачи",helpText:"Моделът по подразбиране е задължителен. Другите модели са незадължителни и ще използват модела по подразбиране, ако не са конфигурирани.",default:{label:"По подразбиране",placeholder:"Изберете модел по подразбиране",description:"Основен модел за общи задачи (подобен на Claude Sonnet)"},background:{label:"Фонов",placeholder:"Изберете фонов модел",description:"Лек модел за фонови задачи (подобен на Claude Haiku)"},think:{label:"Мислене",placeholder:"Изберете модел за мислене",description:"Усъвършенстван модел за сложни разсъждения (подобен на Claude Opus)"},image:{label:"Изображение",placeholder:"Изберете модел за изображения",description:"Модел за задачи, свързани с изображения, с визуална способност"}}},codeToChat:{title:"Маршрутизатор Код → Чат",description:"Излагане на модели от абонаментния план за кодиране в режим на чат",addRouter:"Добави маршрутизатор",emptyState:"Няма конфигурирани маршрутизатори Код→Чат. Добавете един, за да изложите модели от абонаментния план за кодиране в режим на чат.",form:{name:"Име на маршрутизатора",namePlaceholder:"Моят маршрутизатор Код→Чат",codeProvider:"Доставчик на код",codeProviderPlaceholder:"Изберете доставчик на код",codeProviderHelper:"Изберете доставчика на код за трансформация",models:"Модели от абонаментния план за кодиране",modelsHelper:"Изберете кои модели от абонаментния план за кодиране да се изложат",enabled:"Активиран",save:"Запази маршрутизатор",cancel:"Отказ"},mappings:{title:"Съпоставяния на модели",description:"Съпоставете моделите на доставчика на код с моделите на доставчика на чат за излагане",count:"съпоставяния(-е)",empty:"Няма конфигурирани съпоставяния на модели. Добавете съпоставяния за излагане на модели за код в режим на чат.",addNew:"Добави ново съпоставяне",selectSource:"Изберете изходен модел (Код)",selectTarget:"Изберете целеви модел (Чат)",sourcePlaceholder:"Въведете името на изходния модел",targetPlaceholder:"Въведете името на целевия модел",add:"Добави",edit:"Редактирай",done:"Готово"}},transformers:{title:"Трансформатори",description:"Конфигурирайте трансформатори за конвертиране на заявки/отговори",noProvider:"Изберете доставчик за конфигуриране на трансформатори",empty:"Няма трансформатори",count:"{{count}} трансформатор(-а)"},status:{enabled:"Активиран",disabled:"Деактивиран"},messages:{routerAdded:"Маршрутизаторът е добавен успешно",routerUpdated:"Маршрутизаторът е актуализиран успешно",routerDeleted:"Маршрутизаторът е изтрит успешно",saveFailed:"Неуспешно запазване на маршрутизатора"}},presets:{title:"Бързо добавяне на доставчик",added:"Добавен",add:"Добави",features:{search:"Търсене",vision:"Визия",mcp:"MCP",codingPlan:"План за кодиране"}},alerts:{deleteConfirm:"Сигурни ли сте, че искате да изтриете този доставчик?"},errors:{nameRequired:"Името на доставчика е задължително",urlRequired:"Основният URL на API е задължителен",urlInvalid:"Моля, въведете валиден URL (напр. https://api.example.com)",saveFailed:"Неуспешно запазване на доставчика",deleteFailed:"Грешка при изтриването на доставчика. Моля, опитайте отново.",toggleFailed:"Грешка при смяна на състоянието на доставчика. Моля, опитайте отново."},openRouter:{title:"Маршрутизация на доставчици OpenRouter",description:"Конфигурирайте как заявките се маршрутизират към различни доставчици в OpenRouter.",sort:"Стратегия за маршрутизиране",sortTooltip:"Изберете как да се приоритизират доставчиците. Авто използва интелигентно балансиране на натоварването.",order:"Ред на приоритет на доставчиците",orderTooltip:"Посочете доставчиците за последователно изпробване (напр. anthropic, openai, together). Натиснете Enter за добавяне.",orderPlaceholder:"Въведете идентификатор на доставчик и натиснете Enter...",allowFallbacks:"Разреши резервни варианти",allowFallbacksTooltip:"При активиране OpenRouter ще опита резервни доставчици, ако основният е недостъпен.",requireParameters:"Изисквай всички параметри",requireParametersTooltip:"Маршрутизирай само към доставчици, поддържащи всички параметри в заявката.",dataCollection:"Политика за събиране на данни",dataCollectionTooltip:"Контролирайте дали да се използват доставчици, които могат да съхраняват или обучават върху вашите данни.",zdr:"Нулево задържане на данни",zdrTooltip:"Маршрутизирай само към крайни точки с политика за нулево задържане на данни.",only:"Само разрешени доставчици",onlyTooltip:"Използвай само тези конкретни доставчици. Оставете празно за разрешаване на всички доставчици.",onlyPlaceholder:"Въведете идентификатор на доставчик и натиснете Enter...",ignore:"Игнорирай доставчици",ignoreTooltip:"Пропускай тези доставчици при маршрутизиране на заявките.",ignorePlaceholder:"Въведете идентификатор на доставчик и натиснете Enter...",quantizations:"Филтър за квантизация",quantizationsTooltip:"Използвай само доставчици с конкретни нива на квантизация. По-ниската точност може да намали качеството, но да подобри скоростта.",maxPrice:"Максимална цена",maxPriceTooltip:"Задайте максимални ценови ограничения на милион токени. Оставете празно за без ограничение.",configured:"Конфигурирано"}},uA={label:"Режим на API",standard:"Стандартен",codingPlan:"План за кодиране",tokenPlan:"Токен план",apiKeyPrefixHint:"Ключовете за този план обикновено започват с `{{prefix}}`. Само подсказка — не се прилага.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan използва отделен API ключ от стандартната крайна точка.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan използва отделен API ключ от стандартната крайна точка.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan е само за протокол Anthropic.",xiaomiTokenPlanRegions:"Основният baseUrl по подразбиране е `token-plan-cn.*`. Може да го промените ръчно на `token-plan-sgp.*` или `token-plan-ams.*`.",confirmOverwriteTitle:"Смяна на режима на API?",confirmOverwriteBody:"Персонализирали сте URL на API или API ключ. Смяната на режима ще ги презапише с настройките по подразбиране на новия режим — или запазете персонализациите и актуализирайте само етикета на режима.",overwriteAndSwitch:"Презапиши и смени",keepCustomizations:"Запази персонализациите"},pA={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},mA={cancel:"Отказ",close:"Затвори",copy:"Копирай",delete:"Изтрий",dismiss:"Затвори",save:"Запази",optional:"по желание",retry:"Опитай отново",loading:"Зареждане…"},gA={common:{learnMore:"Документация"}},hA={notSupportedByDaemon:"Все още не се поддържа от демона",discoveryUnsupportedFormat:"Откриването на модели не се поддържа за този формат на доставчика. Добавете модели ръчно."},fA={subtitle:"Контролен панел",providers:"Доставчици",apiService:"API услуга",accounts:"Акаунти",codeCli:"Code CLI",settings:"Настройки",usageStats:"Използване",pricing:"Цени"},vA={title:"API услуга",description:"Конфигурирайте изходящия API сървър, маршрутизацията на модели по крайни точки и именуваните ключове за достъп.",loading:"Зареждане на конфигурацията на сървъра…",loadError:"Конфигурацията на сървъра не може да се зареди. Проверете дали демонът е достъпен.",enable:{label:"Активирай изходящ сървър",description:"Стартирайте локалния API сървър, който маршрутизира външни извиквания чрез вашите доставчици."},networkBinding:{label:"Разреши достъп от локална мрежа",description:"Свържете сървъра с мрежовия интерфейс вместо само с loopback.",warning:"Достъпът от локална мрежа излага API сървъра на други устройства в мрежата ви. В комбинация с маршрутизация на абонамент заявките могат да изразходват вашата абонаментна квота — оставете изключено, освен ако не доверявате на мрежата."},status:{running:"Сървърът работи",stopped:"Сървърът е спрян",runningHint:"Изходящият API сървър приема заявки.",stoppedHint:"Активирайте сървъра, за да започнете приемане на заявки.",port:"порт {{port}}",loopback:"Loopback URL адреси",lan:"URL адреси на локалната мрежа"},endpoints:{title:"Маршрутизация на крайни точки",description:"Изберете модела за всеки формат на протокол. Моделът по подразбиране е включен тук — сървърът е маршрутизатор, а не чат приложение."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Модел по подразбиране",backgroundModel:"Фонов модел",visionModel:"Визуален модел",noVisionModel:"Няма",backgroundModelIds:"Идентификатори на фонови модели",backgroundModelIdsPlaceholder:"идентификатори на модели, разделени със запетая",modelPlaceholder:"Изберете модел…",useSubscription:"Използвай абонамент",subscriptionUnsupported:"Маршрутизацията на абонамент не е налична за тази крайна точка."},keys:{title:"Ключове за достъп",description:"Именувани ключове, които外ните извикващи изпращат като Bearer токен. Пълният ключ се показва само веднъж при създаване.",namePlaceholder:"Название на ключа (напр. my-cli)",create:"Създай ключ",empty:"Все още няма ключове за достъп.",enabled:"Активен",disabled:"Деактивиран",revoked:"Отменен",toggle:"Превключи ключ",revoke:"Отмени",revokeConfirmTitle:"Да се отмени ли този ключ?",revokeConfirmDesc:"Отмяната на „{{name}}“ незабавно ще спре използването му за автентикация. Това не може да бъде отменено.",created:{title:"Ключът е създаден",warning:"Копирайте ключа сега — той няма да бъде показан отново. Съхранявайте го на сигурно място.",copy:"Копирай",copied:"Копирано",dismiss:"Готово"}}},kA={title:"Акаунти и абонаменти",description:"Управлявайте абонаментните идентификационни данни, чрез които маршрутизира сървърът. Токените се записват тук, но никога не се показват обратно.",loading:"Зареждане на акаунти…",empty:"Няма налични доставчици на абонаменти.",signIn:"Влезте",oauth:{title:"Влезте в {{name}}",description:"Отворете страницата за влизане в браузъра, оторизирайте, след което поставете кода за оторизация по-долу. Кодът преминава само към демона — създаденият токен никога не се показва.",openPage:"Отвори страницата за влизане",codeLabel:"Код за оторизация",codePlaceholder:"Поставете кода тук",submit:"Завърши влизането"},codexOauth:{title:"Влезте в {{name}}",description:"Отворете страницата за влизане в браузъра и оторизирайте. Демонът автоматично ще улови резултата — оставете тази страница отворена, докато завърши. Токенът никога не се показва.",waiting:"Изчакване на завършване на влизането в браузъра…",failed:"Влизането неуспешно. Моля, опитайте отново."},clearProvider:"Изчисти всичко",clearConfirmTitle:"Да се изчистят ли акаунтите {{name}}?",clearConfirmDesc:"Това ще премахне всички съхранени идентификационни данни за този доставчик. Това не може да бъде отменено.",credential:{ok:"Конфигурирано",notConfigured:"Не е конфигурирано"},kind:{"pass-through":"Прозрачни идентификационни данни","oauth-bearer":"OAuth bearer","static-bearer":"Статичен bearer ключ"},reason:{"missing-credential":"Няма съхранени идентификационни данни.",expired:"Идентификационните данни са изтекли.","reauth-required":"Необходима е повторна автентикация.","refresh-failed":"Обновяването на токена не успя.","not-refreshable":"Идентификационните данни не могат да бъдат обновени.",unknown:"Статусът е неизвестен."},status:{unconfigured:"Не е конфигурирано",authorized:"Оторизирано",configured:"Конфигурирано",expired:"Изтекъл",error:"Грешка"},authMethod:{oauth:"OAuth",setup_token:"Токен за настройка",manual:"Ръчно"},list:{empty:"Няма съхранени акаунти за този доставчик.",active:"Активен",expiresAt:"Изтича {{value}}",setActive:"Задай като активен",remove:"Премахни",removeConfirmTitle:"Да се премахне ли този акаунт?",removeConfirmDesc:"Премахването на „{{name}}“ ще изтрие съхранените идентификационни данни. Това не може да бъде отменено.",title:"Акаунти"},write:{trigger:"Добави идентификационни данни",title:"Запиши идентификационни данни {{name}}",description:"Поставете вече получените данни на токена. Полетата са ограничени до това, което приема доставчикът; токенът се съхранява, никога не се показва обратно.",authMethod:"Метод на автентикация",status:"Статус",subscriptionLevel:"Ниво на абонамент",subscriptionLevelNone:"Не е зададено",submit:"Запази идентификационни данни"},field:{accessToken:"Токен за достъп",refreshToken:"Токен за обновяване",idToken:"ID токен",apiKey:"API ключ",expiresAt:"Изтича на (ISO)",setupTokenExpiresAt:"Токенът за настройка изтича на (ISO)",accountId:"Идентификатор на акаунта",email:"Имейл",organizationId:"Идентификатор на организацията",baseUrl:"Основен URL",zenBaseUrl:"Zen основен URL"},provider:{claude:{title:"Claude",description:"Абонаментни идентификационни данни на Anthropic, маршрутизирани от демона."},codex:{title:"Codex",description:"Абонаментни идентификационни данни на OpenAI Codex, маршрутизирани от демона."},gemini:{title:"Gemini",description:"Абонаментни идентификационни данни на Google Gemini, маршрутизирани от демона."},opencodego:{title:"OpenCodeGo",description:"Статични идентификационни данни с API ключ, маршрутизирани от демона."}},authMethodLabel:"Метод на оторизация",authMethodDesc:{oauth:"Влезте чрез браузъра; демонът ще улови и съхрани токена.",manual:"Поставете вече получен токен. Той се съхранява, никога не се показва обратно."},actions:{authorize:"Оторизирай",enterToken:"Въведи токен",refresh:"Обнови"},accounts:{addAccount:"Добави акаунт"},detail:{authMethod:"Метод на оторизация",subscriptionLevel:"Ниво на абонамент",expiresAt:"Изтича",lastRefreshed:"Последно обновен",label:"Етикет на акаунта",labelPlaceholder:"Именувайте този акаунт",saveLabel:"Запази етикета"},oauthFlow:{step1:{title:"Отворете страницата за оторизация",desc:"Отворете страницата за влизане в браузъра."},step2:{title:"Оторизирайте достъпа",desc:"Влезте и одобрете достъпа за доставчика."},step3:{title:"Копирайте кода за оторизация",desc:"Страницата показва код за оторизация след одобрение."},step4:{title:"Поставете кода",desc:"Поставете кода за оторизация по-долу за завършване. Кодът преминава само към демона — създаденият токен никога не се показва."},authorize:"Завърши влизането",showUrl:"Покажи URL за оторизация"},manual:{title:"Поставяне на идентификационни данни",description:"Поставете вече получен токен. Полетата са ограничени до това, което приема доставчикът; токенът се съхранява, никога не се показва обратно.",accessTokenPlaceholder:"Поставете токена за достъп",refreshTokenPlaceholder:"Поставете токена за обновяване (по желание)",hint:"Токенът се изпраща на демона и се съхранява криптиран. Никога не се показва обратно."},openCodeGo:{apiKeyRequired:"Необходим е API ключ.",apiKeyPlaceholder:"Поставете API ключа",baseUrlPlaceholder:"https://… (по желание)",zenBaseUrlPlaceholder:"https://… (по желание)"},info:{title:"Относно абонаментните акаунти",description:"Токените се записват в демона и се използват за автентикация на заявките нагоре по веригата. Те се съхраняват криптирани и никога не се показват обратно. Премахването на акаунт изтрива съхранените идентификационни данни."},rename:{failed:"Неуспешно преименуване на акаунта."},refresh:{failed:"Неуспешно обновяване на токена."},errors:{requestFailed:"Заявката неуспешна. Моля, опитайте отново."},syncWarning:{"external-divergent":"Файлът за вход на външния CLI съдържа по-нови идентификационни данни от този акаунт. Записаният токен може да спре да се обновява — обновете сега или влезте отново.","external-not-rotated":"Обновяването е неуспешно и външният CLI съдържа същите изтекли идентификационни данни. Влезте отново.","duplicate-token":"Друг акаунт споделя тези идентификационни данни. Обновяването на единия ще отпише другия."},importExternal:{detected:"На тази машина беше открит съществуващ вход в CLI на {{name}}.",hint:"След импортирането това приложение го поддържа актуален: при всяко обновяване на токена се обновява и файлът за вход на CLI, така че CLI в терминала остава вписан.",button:"Импортиране на съществуващ CLI вход"}},yA={title:"Code CLI",description:"Насочете CLI за кодиране към изходящия прокси на демона. Тази страница е само за четене — тук няма какво да се конфигурира.",copy:"Копирай",copied:"Копирано",baseUrl:{title:"Основен URL на демона",description:"Адресът на проксито, към което се свързва вашият CLI.",label:"Основен URL"},token:{title:"Автентикация",hint:"Изпращайте 'Authorization: Bearer <вашия-admin-токен>' за администраторски маршрути. Администраторският токен се конфигурира в демона (конфигурационен файл или среда) — никога не се показва тук."},examples:{title:"Примерна среда за стартиране",keyNote:"Използвайте изходящ ключ за достъп, създаден на страницата API услуга — не администраторския токен.",anthropic:"CLI в Anthropic формат",openai:"CLI в OpenAI формат"},launchDescription:"Стартирайте CLI за кодиране в терминал, насочен към този демон. Демонът инжектира средата за пренасочване и стартира CLI вместо вас.",refresh:"Обнови",loading:"Откриване на CLI…",cli:{installed:"Инсталиран",notFound:"Не е намерен",notFoundHint:"Този CLI не е в PATH на хоста на демона. Инсталирайте го, след което обновете.",install:"Инсталирай",installing:"Инсталиране…",installingHint:"Инсталиране на хоста на демона — това може да отнеме минута.",launch:"Стартирай",launchTitle:"Стартирай {{name}}",launchDescription:"Отваря нов терминал на хоста на демона с ттози CLI, маршрутизиран чрез прокси на демона. Изберете незадължителна работна директория.",cwdLabel:"Работна директория",cwdPlaceholder:"/path/to/your/project",runningVia:"Работи · {{provider}} / {{model}}",stop:"Спри"},manual:{title:"Ръчна настройка",description:"Предпочитате да стартирате CLI сами? Насочете го към демона с тези променливи на средата.",show:"Покажи",hide:"Скрий"}},bA={probing:"Проверка за демон…",spawning:"Стартиране на демона…",failed:"Демонът не може да стартира",failedHint:"Уверете се, че Node.js е инсталиран и демонът е компилиран (наличен dist), или задайте OMNICROSS_DAEMON_ENTRY към cli.js на демона."},PA={title:"Настройки",description:"Предпочитания за десктоп приложението.",desktopOnly:"Опциите за стартиране и системната лента се прилагат само в десктоп приложението.",startup:{title:"Автоматично стартиране",autoLaunch:"Стартирай при влизане",autoLaunchHint:"Стартирайте Omnicross автоматично при влизане в системата.",startMinimized:"Стартирай минимизирано в системната лента",startMinimizedHint:"Стартирайте на заден план без отваряне на прозореца."},tray:{title:"Системна лента",minimizeOnClose:"Минимизирай в системната лента при затваряне",minimizeOnCloseHint:"Затварянето на прозореца го скрива в системната лента вместо да излезе."},language:{title:"Език",label:"Език на интерфейса"}},AA={title:"Статистика на използването",description:"Статистика за токени и разходи на заявките, обслужени от демона.",rangeToday:"Днес",range7d:"Последните 7 дни",range30d:"Последните 30 дни",rangeCustom:"Персонализиран",from:"От",to:"До",totalCost:"Обща цена",cacheSavings:"Спестявания от кеш",events:"Заявки",inputTokens:"Входни токени",outputTokens:"Изходни токени",cacheReadTokens:"Четене от кеш",cacheWriteTokens:"Запис в кеш",reasoningTokens:"Токени за разсъждение",byModel:"По модел",byApiKey:"По API ключ",provider:"Доставчик",model:"Модел",cost:"Цена",apiKey:"API ключ",unpriced:"Без цена",unpricedHint:"Няма ценови запис за този модел — добавете го на страницата „Цени“.",unattributed:"Неприписани",unattributedHint:"Заявки, несвързани с конкретен API ключ. Това е нормално, докато приписването по ключ не се записва.",empty:"Няма заявки в този период.",invalidRange:"Изберете валиден период от дати."},CA={title:"Цени на моделите",description:"Цени на токени по модел за изчисляване на разходите на заявките, в USD за 1 млн. токена.",search:"Търсене на доставчик или модел…",fetchLatest:"Изтегли най-новите",fetching:"Изтегляне…",addEntry:"Добави запис",provider:"Доставчик",model:"Модел",inputPrice:"Вход",outputPrice:"Изход",cacheReadPrice:"Четене от кеш",cacheWritePrice:"Запис в кеш",source:"Източник",updated:"Обновено",userEdited:"редактирано",edit:"Редактирай",deleteTitle:"Изтриване на ценовия запис?",empty:"Ценовата таблица е празна.",emptyHint:"Изтеглете най-новите цени, за да я попълните.",noMatches:"Няма записи, отговарящи на търсенето.",saved:"Ценовият запис е запазен.",saveFailed:"Запазването е неуспешно: {{message}}",deleteFailed:"Изтриването е неуспешно: {{message}}",alreadyDeleted:"Записът вече не съществуваше.",fetchApplied:"Обновени са {{count}} записа от източника.",fetchFailed:"Изтеглянето е неуспешно: {{message}}",requiredId:"Задължително",invalidPrice:"Въведете неотрицателно число",conflictTitle:"Разрешаване на ценови конфликти",conflictHint:"Тези записи са редактирани от вас и едновременно са се променили в източника. Изберете за всеки ред дали да запазите вашата стойност (Пропусни) или да приемете новата (Презапиши).",current:"Текуща",incoming:"Входяща",overwrite:"Презапиши",skip:"Пропусни",overwriteAll:"Презапиши всички",skipAll:"Пропусни всички",applyResolutions:"Приложи",resolved:"Презаписани: {{overwritten}}, пропуснати: {{skipped}}.",resolvedWithStale:"Презаписани: {{overwritten}}, пропуснати: {{skipped}}. {{stale}} се промениха междувременно и останаха непокътнати.",refreshFailed:"Промяната беше приложена, но презареждането на списъка не успя: {{message}}",sourceBuiltin:"Вграден",sourceLitellm:"LiteLLM",sourceUser:"Потребител"},xA={providerSettings:cA,apiMode:uA,presetName:pA,common:mA,mediaSettings:gA,appLocal:hA,nav:fA,apiService:vA,accounts:kA,codeCli:yA,daemonStatus:bA,settings:PA,usageStats:AA,pricing:CA},zA={loading:"Načítání konfigurace LLM...",reset:{button:"Obnovit výchozí nastavení",confirmTitle:"Obnovit výchozí nastavení?",confirmBody:"Tímto vymažete svá přizpůsobení pro tohoto poskytovatele a vrátíte se na vestavěné výchozí hodnoty. Váš klíč API a uložené relace zůstanou zachovány.",confirmButton:"Obnovit výchozí nastavení"},reentryBanner:{message:"{{count}} povolený(-ch) poskytovatel(é) vyžaduje opětovné zadání klíče API. Otevřete každého z nich a znovu zadejte klíč."},migrationPack:{barHint:"Přesuňte klíče poskytovatele a tokeny předplatného na jiný počítač pomocí šifrovaného balíčku.",passphrase:"Přístupová fráze",passphrasePlaceholder:"Zadejte přístupovou frázi",passphraseHint:"Použijte alespoň 8 znaků; doporučujeme 12 nebo více.",confirm:"Potvrdit přístupovou frázi",confirmPlaceholder:"Zadejte přístupovou frázi znovu",mismatch:"Přístupové fráze se neshodují.",strength:{weak:"Příliš krátká — použijte alespoň 8 znaků.",fair:"Dobrá — 12 nebo více znaků je silnější.",strong:"Silná přístupová fráze."},export:{button:"Exportovat balíček",title:"Exportovat šifrovaný balíček",subtitle:"Zašifrujte klíče poskytovatele a tokeny předplatného do přenosného souboru.",warning:"Tento soubor obsahuje dešifrovatelná tajemství. Uchovávejte ho bezpečně — kdokoli s tímto souborem a přístupovou frází může přečíst vaše klíče. Ztracenou přístupovou frázi nelze obnovit.",submit:"Exportovat",success:"Balíček byl úspěšně exportován.",error:"Export se nezdařil. Zkuste to prosím znovu."},import:{button:"Importovat balíček",title:"Importovat šifrovaný balíček",subtitle:"Obnovte klíče poskytovatele a tokeny předplatného z exportovaného balíčku.",hint:"Zadejte přístupovou frázi použitou při exportu balíčku a poté vyberte soubor.",submit:"Importovat",successTitle:"Import dokončen",summary:"Importováno {{providerKeys}} klíč(ů) poskytovatele, {{poolKeys}} klíč(ů) fondu a {{tokenSets}} sada(-y) tokenů.",duplicates:"Přeskočeno {{count}} klíč(ů) fondu, které již existují.",skipped:"Přeskočeno (žádný odpovídající poskytovatel): {{names}}",error:"Nesprávná přístupová fráze nebo poškozený balíček. Nic nebylo změněno."}},searchPlaceholder:"Hledat poskytovatele...",emptySearch:"Žádní poskytovatelé neodpovídají vašemu hledání.",emptyList:"Žádní poskytovatelé nejsou nakonfigurováni.",selectPrompt:"Vyberte poskytovatele pro zobrazení podrobností",listStatus:"{{count}} model(ů)",noModels:"Žádné modely nejsou nakonfigurovány",enabled:"Povoleno",disabled:"Zakázáno",showEnabledOnly:"Zobrazit pouze povolené",showAll:"Zobrazit všechny poskytovatele",dragHandle:"Přetáhnout pro změnu pořadí",reorderFailed:"Nepodařilo se uložit pořadí poskytovatelů",credentials:{apiKey:"Klíč API",apiBaseUrl:"Základní URL API"},filter:{all:"Vše",chat:"Chat",code:"Kód"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Vyberte šablonu",skipTemplates:"Přeskočit, konfigurovat ručně",name:"Název *",providerType:"Typ",apiType:"Typ API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standardní formát API chat/completions OpenAI",claudecode:"Formát Anthropic Messages API (Claude Code)"},chatApiFormat:"Formát API",chatApiFormatDescription:"Vyberte formát API odpovídající koncovému bodu vašeho poskytovatele",apiKey:"Klíč API",apiKeyPlaceholder:"sk-... nebo $PROMĚNNÁ_PROSTŘEDÍ",apiKeyHelper:"Použijte $NÁZEV_PROMĚNNÉ pro odkaz na proměnné prostředí",apiKeySetPlaceholder:"Klíč je nastaven — ponechte prázdné pro zachování",apiKeyReplaceHelper:"Klíč je bezpečně uložen. Zadejte novou hodnotu pro jeho nahrazení, nebo ponechte prázdné pro zachování.",testApiKey:"Testovat klíč API",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Náhled:",models:"Modely",modelPlaceholder:"Název modelu (např. gpt-4, claude-3-opus)",transformers:"Transforméry",transformerConfig:"Transforméry API",transformerConfigDescription:"Nakonfigurujte transforméry pro přizpůsobení formátů požadavků/odpovědí API pro tohoto poskytovatele",transformerConfigNote:"Daemon aplikuje tyto transforméry v řetězci požadavků, po transforméru formátu poskytovatele (který zpracovává konverzi drátového formátu). Neznámé názvy transformérů jsou přeskočeny.",enabled:"Povoleno",apiVersion:"Verze API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Verze Azure OpenAI API (např. 2024-08-01-preview)",official:"Oficiální Anthropic API",officialHelper:"Povolte, pokud se tento poskytovatel připojuje přímo k oficiálnímu Anthropic API. Zakažte pro reverzní proxy nebo služby třetích stran.",maxConcurrency:"Max. souběžných požadavků",maxConcurrencyHelper:"Maximální počet souběžných požadavků API odesílaných tomuto poskytovateli. Nižší hodnoty pomáhají předejít omezení rychlosti (chyby 429). Nastavte `-1` pro neomezený počet.",codingPlan:{label:"Plán kódování",description:"Použijte samostatný koncový bod API pro plány kódování na základě předplatného",baseUrl:"Základní URL plánu kódování",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Klíč API plánu kódování (volitelný)",apiKeyPlaceholder:"Ponechte prázdné pro použití klíče API poskytovatele",apiKeyHelper:"Vyžadováno pouze pokud plán kódování používá jiný klíč API",tokenPlanHint:"Někteří poskytovatelé (např. Xiaomi MiMo) vydávají klíče Token Plan s předponou `tp-` — pouze informativní, není vynucováno."},selectTypeFirst:"Vyberte typ poskytovatele",selectTypeFirstDesc:"Zvolte, jaký typ poskytovatele chcete přidat",codeProviderNote:"Poskytovatelé kódu potřebují pouze klíč API a URL. Modely jsou spravovány směrovačem agentů.",buttons:{cancel:"Zrušit",submitAdd:"Přidat poskytovatele",submitUpdate:"Aktualizovat poskytovatele",continue:"Pokračovat",back:"Zpět"}},details:{noSelection:"Vyberte poskytovatele pro zobrazení podrobností",apiKey:"Klíč API",apiUrl:"URL API",nameLabel:"Název poskytovatele",modelsEndpoint:"Koncový bod modelů",modelsEndpointHelper:"Přepište koncový bod zjišťování, pokud poskytovatel zpřístupňuje vlastní cestu /models.",models:"Modely",transformers:"Transforméry",codeProviderNote:"Poskytovatelé kódu (jako Claude Code) nevyžadují konfiguraci modelů. Modely jsou automaticky spravovány směrovačem agentů.",buttons:{more:"Další nastavení",delete:"Smazat"}},providerModelSelector:{placeholder:"Vyberte poskytovatele a model",noProviders:"Žádní poskytovatelé nejsou k dispozici",noModels:"Žádné modely nejsou nakonfigurovány"},apiKeyPool:{title:"Fond klíčů API",description:"Nakonfigurujte více klíčů API pro vyvažování zátěže. Každá relace lpí na jednom klíči pro zachování mezipaměti promptů.",defaultLabel:"Výchozí",weight:"Váha",noKey:"Žádný klíč",labelPlaceholder:"Popisek (např. Klíč č. 1, Produkce)",addKey:"Přidat klíč API",add:"Přidat",empty:"Žádné další klíče nejsou nakonfigurovány.",statusCoolingDown:"Ochlazování {{time}}",statusAuthFailed:"Ověřování se nezdařilo · zakázáno",statusDisabled:"Zakázáno",statusHealthy:"V pořádku",agoSeconds:"před {{count}}s",agoMinutes:"před {{count}}m",agoHours:"před {{count}}h",agoDays:"před {{count}}d"},modelsManager:{searchPlaceholder:"Hledat modely...",defaultGroup:"Všechny modely",add:"Přidat model",manage:"Spravovat",empty:"V této skupině nejsou žádné modely",enabled:"Povoleno",disabled:"Zakázáno",filters:{all:"Vše",vision:"Vidění",reasoning:"Uvažování",free:"Zdarma",tools:"Nástroje"},manualDialog:{title:"Přidat model",subtitle:"Přidat vlastní model k tomuto poskytovateli",modelId:"ID modelu",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash atd.",modelIdHelper:"Přesný identifikátor modelu používaný při volání API",modelName:"Zobrazovaný název",modelNamePlaceholder:"Přátelský zobrazovaný název (volitelný)",modelNameHelper:"Volitelný název zobrazený v rozhraní. Pokud je prázdný, použije se ID modelu",group:"Skupina",groupPlaceholder:"Vyberte nebo zadejte název skupiny",submit:"Přidat",cancel:"Zrušit",helper:"Zadejte přesný identifikátor modelu zpřístupněný API poskytovatele."},editDialog:{title:"Upravit model",subtitle:"Změnit nastavení modelu",modelId:"ID modelu",modelIdPlaceholder:"Identifikátor modelu",modelIdHelper:"Identifikátor modelu používaný při volání API",modelName:"Zobrazovaný název",modelNamePlaceholder:"Přátelský zobrazovaný název",modelNameHelper:"Název zobrazený v rozhraní",group:"Skupina",groupPlaceholder:"Vyberte nebo zadejte název skupiny",submit:"Uložit",cancel:"Zrušit",vision:"Schopnost vidění",visionHint:"Zda tento model podporuje vstup obrázků/vidění",reasoning:"Model uvažování",reasoningHint:"Zda tento model podporuje režim uvažování/myšlení"},manageDialog:{title:"Spravovat modely",cachedAt:"Uloženo v mezipaměti {{date}} ({{source}})",refresh:"Obnovit",close:"Zavřít",raw:"Surový JSON",empty:"Žádné vzdálené modely nejsou k dispozici.",error:"Nepodařilo se načíst modely: {{message}}",addFromCatalog:"Přidat",sourceCache:"mezipaměť",sourceNetwork:"živě",contextLength:"Kontext {{value}} tokenů",maxTokens:"Max. {{value}} tokenů"},messages:{added:"Model přidán.",updated:"Model aktualizován.",removed:"Model odebrán.",duplicate:"Model již existuje.",refreshed:"Modely obnoveny",refreshFailed:"Nepodařilo se obnovit modely"},testDialog:{title:"Test připojení modelu",provider:"Poskytovatel",model:"Model",testing:"Testování...",success:"Test úspěšný",successMessage:"Model je dostupný a funkční",failure:"Test se nezdařil",aiResponse:"Odpověď AI",charCount:"{{count}} znaků",duration:"Doba trvání {{time}}s",close:"Zavřít",retest:"Otestovat znovu",testButton:"Testovat model",unsupportedFormat:"Testování pro tento formát poskytovatele zatím není podporováno."}},router:{title:"Konfigurace směrovače",description:"Nakonfigurujte, který poskytovatel/model použít pro různé scénáře.",labels:{default:"Výchozí",background:"na pozadí",think:"uvažování",longContext:"Dlouhý kontext",webSearch:"Webové vyhledávání",image:"Obrázek",longContextThreshold:"Práh dlouhého kontextu"},helper:{longContextThreshold:"Počet tokenů, po kterém se přepne na model s dlouhým kontextem."},placeholder:{required:"Povinné",optional:"Volitelné"}},agentRouter:{title:"Směrovač agentů",description:"Nakonfigurujte obousměrné směrování mezi režimy Chat a Kód.",searchPlaceholder:"Hledat směrovače...",noSearchResults:"Žádné směrovače neodpovídají vašemu hledání.",tabs:{chatToCode:"Chat → Kód",codeToChatPlaceholder:"Kód → Chat"},chatToCode:{title:"Směrovač Chat na Kód",description:"Používejte poskytovatele chatu v režimu agenta/kódování",addRouter:"Přidat směrovač",emptyState:"Žádné směrovače Chat→Kód nejsou nakonfigurovány. Přidejte jeden pro použití poskytovatelů chatu v režimu kódování.",form:{name:"Název směrovače",namePlaceholder:"Můj směrovač Chat→Kód",chatProvider:"Poskytovatel chatu",chatProviderPlaceholder:"Vyberte poskytovatele chatu",mode:"Režim",modeSimple:"Jednoduchý",modeAdvanced:"Pokročilý",modeSimpleDesc:"Přímý průchod k poskytovateli chatu",modeAdvancedDesc:"Konfigurace mapování modelů a zpracování kontextu",enabled:"Povoleno",save:"Uložit směrovač",cancel:"Zrušit"},list:{provider:"Poskytovatel",mode:"Režim",status:"Stav"},mappings:{title:"Mapování modelů",description:"Mapujte modely poskytovatele chatu na modely poskytovatele kódu",count:"mapování",empty:"Žádná mapování modelů nejsou nakonfigurována. Přidejte mapování pro směrování chat modelů k poskytovatelům kódu.",addNew:"Přidat nové mapování",selectSource:"Vyberte zdrojový model (Chat)",selectTarget:"Vyberte cílový model (Kód)",targetPlaceholder:"Zadejte název modelu Claude Code",notSet:"(Nenastaveno — klikněte pro výběr)",add:"Přidat",edit:"Upravit",done:"Hotovo"},advanced:{title:"Pokročilá konfigurace",description:"Nakonfigurujte modely pro různé typy úloh",helpText:"Výchozí model je povinný. Ostatní modely jsou volitelné a v případě nekonfigurace se vrátí k výchozímu.",default:{label:"Výchozí",placeholder:"Vyberte výchozí model",description:"Primární model pro obecné úlohy (podobný Claude Sonnet)"},background:{label:"Pozadí",placeholder:"Vyberte model na pozadí",description:"Odlehčený model pro úlohy na pozadí (podobný Claude Haiku)"},think:{label:"Uvažování",placeholder:"Vyberte model uvažování",description:"Pokročilý model pro komplexní uvažování (podobný Claude Opus)"},image:{label:"Obrázek",placeholder:"Vyberte model obrázků",description:"Model pro úlohy související s obrázky se schopností vidění"}}},codeToChat:{title:"Směrovač Kód na Chat",description:"Zpřístupněte modely plánu kódování v režimu chatu",addRouter:"Přidat směrovač",emptyState:"Žádné směrovače Kód→Chat nejsou nakonfigurovány. Přidejte jeden pro zpřístupnění modelů plánu kódování v režimu chatu.",form:{name:"Název směrovače",namePlaceholder:"Můj směrovač Kód→Chat",codeProvider:"Poskytovatel kódu",codeProviderPlaceholder:"Vyberte poskytovatele kódu",codeProviderHelper:"Vyberte poskytovatele kódu pro použití při transformaci",models:"Modely plánu kódování",modelsHelper:"Vyberte, které modely plánu kódování zpřístupnit",enabled:"Povoleno",save:"Uložit směrovač",cancel:"Zrušit"},mappings:{title:"Mapování modelů",description:"Mapujte modely poskytovatele kódu na modely poskytovatele chatu pro zpřístupnění",count:"mapování",empty:"Žádná mapování modelů nejsou nakonfigurována. Přidejte mapování pro zpřístupnění modelů kódu v režimu chatu.",addNew:"Přidat nové mapování",selectSource:"Vyberte zdrojový model (Kód)",selectTarget:"Vyberte cílový model (Chat)",sourcePlaceholder:"Zadejte název zdrojového modelu",targetPlaceholder:"Zadejte název cílového modelu",add:"Přidat",edit:"Upravit",done:"Hotovo"}},transformers:{title:"Transforméry",description:"Nakonfigurujte transforméry pro konverzi požadavků/odpovědí",noProvider:"Vyberte poskytovatele pro konfiguraci transformérů",empty:"Žádné transforméry",count:"{{count}} transformér(ů)"},status:{enabled:"Povoleno",disabled:"Zakázáno"},messages:{routerAdded:"Směrovač byl úspěšně přidán",routerUpdated:"Směrovač byl úspěšně aktualizován",routerDeleted:"Směrovač byl úspěšně odstraněn",saveFailed:"Nepodařilo se uložit směrovač"}},presets:{title:"Rychlé přidání poskytovatele",added:"Přidáno",add:"Přidat",features:{search:"Vyhledávání",vision:"Vidění",mcp:"MCP",codingPlan:"Plán kódování"}},alerts:{deleteConfirm:"Opravdu chcete smazat tohoto poskytovatele?"},errors:{nameRequired:"Název poskytovatele je povinný",urlRequired:"Základní URL API je povinná",urlInvalid:"Zadejte platnou URL (např. https://api.example.com)",saveFailed:"Nepodařilo se uložit poskytovatele",deleteFailed:"Chyba při mazání poskytovatele. Zkuste to prosím znovu.",toggleFailed:"Chyba při přepínání poskytovatele. Zkuste to prosím znovu."},openRouter:{title:"Směrování poskytovatelů OpenRouter",description:"Nakonfigurujte, jak jsou požadavky směrovány k různým poskytovatelům v OpenRouter.",sort:"Strategie směrování",sortTooltip:"Zvolte způsob prioritizace poskytovatelů. Auto používá inteligentní vyvažování zátěže.",order:"Pořadí priorit poskytovatelů",orderTooltip:"Určete poskytovatele, kteří mají být vyzkoušeni v pořadí (např. anthropic, openai, together). Stiskněte Enter pro přidání.",orderPlaceholder:"Zadejte identifikátor poskytovatele a stiskněte Enter...",allowFallbacks:"Povolit záložní možnosti",allowFallbacksTooltip:"Pokud je povoleno, OpenRouter vyzkouší záložní poskytovatele, pokud je primární nedostupný.",requireParameters:"Vyžadovat všechny parametry",requireParametersTooltip:"Směrovat pouze k poskytovatelům, kteří podporují všechny parametry v požadavku.",dataCollection:"Zásady sběru dat",dataCollectionTooltip:"Kontrolujte, zda používat poskytovatele, kteří mohou ukládat nebo trénovat na vašich datech.",zdr:"Nulové uchovávání dat",zdrTooltip:"Směrovat pouze ke koncovým bodům s politikou nulového uchovávání dat.",only:"Povolení poskytovatelé",onlyTooltip:"Používejte pouze tyto konkrétní poskytovatele. Ponechte prázdné pro povolení všech.",onlyPlaceholder:"Zadejte identifikátor poskytovatele a stiskněte Enter...",ignore:"Ignorovaní poskytovatelé",ignoreTooltip:"Přeskočte tyto poskytovatele při směrování požadavků.",ignorePlaceholder:"Zadejte identifikátor poskytovatele a stiskněte Enter...",quantizations:"Filtr kvantizace",quantizationsTooltip:"Používejte pouze poskytovatele s konkrétními úrovněmi kvantizace. Nižší přesnost může snížit kvalitu, ale zvýšit rychlost.",maxPrice:"Maximální cena",maxPriceTooltip:"Nastavte maximální cenové limity za milion tokenů. Ponechte prázdné pro neomezené.",configured:"Nakonfigurováno"}},IA={label:"Režim API",standard:"Standardní",codingPlan:"Plán kódování",tokenPlan:"Plán tokenů",apiKeyPrefixHint:"Klíče pro tento plán obvykle začínají na `{{prefix}}`. Pouze informativní — není vynucováno.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan používá samostatný klíč API od standardního koncového bodu.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan používá samostatný klíč API od standardního koncového bodu.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan podporuje pouze protokol Anthropic.",xiaomiTokenPlanRegions:"Výchozí baseUrl je `token-plan-cn.*`. Můžete ho ručně upravit na `token-plan-sgp.*` nebo `token-plan-ams.*`.",confirmOverwriteTitle:"Přepnout režim API?",confirmOverwriteBody:"Přizpůsobili jste URL API nebo klíč API. Přepnutím režimů je přepíšete výchozími hodnotami nového režimu — nebo zachovejte svá přizpůsobení a aktualizujte pouze popisek režimu.",overwriteAndSwitch:"Přepsat a přepnout",keepCustomizations:"Zachovat přizpůsobení"},SA={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},wA={cancel:"Zrušit",close:"Zavřít",copy:"Kopírovat",delete:"Smazat",dismiss:"Zavřít",save:"Uložit",optional:"volitelné",retry:"Zkusit znovu",loading:"Načítání…"},TA={common:{learnMore:"Dokumentace"}},jA={notSupportedByDaemon:"Daemon to zatím nepodporuje",discoveryUnsupportedFormat:"Zjišťování modelů pro tento formát poskytovatele zatím není podporováno. Přidejte modely ručně."},MA={subtitle:"Ovládací panel",providers:"Poskytovatelé",apiService:"Služba API",accounts:"Účty",codeCli:"Code CLI",settings:"Nastavení",usageStats:"Využití",pricing:"Ceník"},NA={title:"Služba API",description:"Nakonfigurujte odchozí API server, směrování modelů pro každý koncový bod a pojmenované přístupové klíče.",loading:"Načítání konfigurace serveru…",loadError:"Nepodařilo se načíst konfiguraci serveru. Zkontrolujte, zda je daemon dostupný.",enable:{label:"Povolit odchozí server",description:"Spusťte lokální API server, který směruje externí klienty přes vaše poskytovatele."},networkBinding:{label:"Povolit přístup z LAN",description:"Svažte server se síťovým rozhraním místo pouze se smyčkovým rozhraním.",warning:"Přístup z LAN vystavuje API server ostatním zařízením v síti. V kombinaci se směrováním předplatného mohou požadavky spotřebovávat váš limit předplatného — tuto možnost vypněte, pokud síti nedůvěřujete."},status:{running:"Server běží",stopped:"Server zastaven",runningHint:"Odchozí API server přijímá požadavky.",stoppedHint:"Povolte server pro začátek přijímání požadavků.",port:"port {{port}}",loopback:"URL smyčkového rozhraní",lan:"URL LAN"},endpoints:{title:"Směrování koncových bodů",description:"Vyberte model, na který každý drátový formát směruje. Výchozí model je zde zahrnut — server je směrovač, nikoli chatovací aplikace."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Výchozí model",backgroundModel:"Model na pozadí",visionModel:"Model vidění",noVisionModel:"Žádný",backgroundModelIds:"ID modelů na pozadí",backgroundModelIdsPlaceholder:"ID modelů oddělená čárkou",modelPlaceholder:"Vyberte model…",useSubscription:"Použít předplatné",subscriptionUnsupported:"Směrování předplatného není pro tento koncový bod dostupné."},keys:{title:"Přístupové klíče",description:"Pojmenované klíče, které externí klienti odesílají jako Bearer token. Celý klíč je zobrazen pouze jednou při vytvoření.",namePlaceholder:"Název klíče (např. moje-cli)",create:"Vytvořit klíč",empty:"Zatím žádné přístupové klíče.",enabled:"Povoleno",disabled:"Zakázáno",revoked:"Odvoláno",toggle:"Přepnout klíč",revoke:"Odvolat",revokeConfirmTitle:"Odvolat tento klíč?",revokeConfirmDesc:"Odvoláním „{{name}}“ okamžitě zastavíte jeho ověřování. Tuto akci nelze vrátit zpět.",created:{title:"Klíč vytvořen",warning:"Zkopírujte tento klíč nyní — nebude znovu zobrazen. Uchovávejte ho bezpečně.",copy:"Kopírovat",copied:"Zkopírováno",dismiss:"Hotovo"}}},LA={title:"Účty a předplatná",description:"Spravujte přihlašovací údaje předplatného, přes které server směruje provoz. Tokeny jsou zde zapsány, ale nikdy znovu zobrazeny.",loading:"Načítání účtů…",empty:"Žádní poskytovatelé předplatného nejsou k dispozici.",signIn:"Přihlásit se",oauth:{title:"Přihlásit se do {{name}}",description:"Otevřete přihlašovací stránku v prohlížeči, autorizujte a poté vložte autorizační kód níže. Kód přechází pouze k daemonu — vydaný token není nikdy zobrazen.",openPage:"Otevřít přihlašovací stránku",codeLabel:"Autorizační kód",codePlaceholder:"Vložte kód sem",submit:"Dokončit přihlášení"},codexOauth:{title:"Přihlásit se do {{name}}",description:"Otevřete přihlašovací stránku v prohlížeči a autorizujte. Daemon výsledek automaticky zachytí — ponechte tuto stránku otevřenou, dokud se proces nedokončí. Token není nikdy zobrazen.",waiting:"Čekání na dokončení přihlášení v prohlížeči…",failed:"Přihlášení se nezdařilo. Zkuste to prosím znovu."},clearProvider:"Vymazat vše",clearConfirmTitle:"Vymazat účty {{name}}?",clearConfirmDesc:"Tímto odstraníte všechny uložené přihlašovací údaje pro tohoto poskytovatele. Tuto akci nelze vrátit zpět.",credential:{ok:"Nakonfigurováno",notConfigured:"Nenakonfigurováno"},kind:{"pass-through":"Průchozí přihlašovací údaje","oauth-bearer":"OAuth bearer","static-bearer":"Statický bearer klíč"},reason:{"missing-credential":"Žádné uložené přihlašovací údaje.",expired:"Přihlašovací údaje vypršely.","reauth-required":"Vyžadováno opětovné ověření.","refresh-failed":"Obnovení tokenu se nezdařilo.","not-refreshable":"Přihlašovací údaje nelze obnovit.",unknown:"Stav neznámý."},status:{unconfigured:"Nenakonfigurováno",authorized:"Autorizováno",configured:"Nakonfigurováno",expired:"Vypršelo",error:"Chyba"},authMethod:{oauth:"OAuth",setup_token:"Nastavovací token",manual:"Ručně"},list:{empty:"Pro tohoto poskytovatele nejsou uloženy žádné účty.",active:"Aktivní",expiresAt:"Vyprší {{value}}",setActive:"Nastavit jako aktivní",remove:"Odebrat",removeConfirmTitle:"Odebrat tento účet?",removeConfirmDesc:"Odebrání „{{name}}“ odstraní uložené přihlašovací údaje. Tuto akci nelze vrátit zpět.",title:"Účty"},write:{trigger:"Přidat přihlašovací údaje",title:"Zapsat přihlašovací údaje {{name}}",description:"Vložte již získaný token. Pole jsou omezena na to, co tento poskytovatel přijímá; token je uložen a nikdy znovu zobrazen.",authMethod:"Metoda ověřování",status:"Stav",subscriptionLevel:"Úroveň předplatného",subscriptionLevelNone:"Nenastaveno",submit:"Uložit přihlašovací údaje"},field:{accessToken:"Přístupový token",refreshToken:"Obnovovací token",idToken:"ID token",apiKey:"Klíč API",expiresAt:"Vyprší (ISO)",setupTokenExpiresAt:"Nastavovací token vyprší (ISO)",accountId:"ID účtu",email:"E-mail",organizationId:"ID organizace",baseUrl:"Základní URL",zenBaseUrl:"Zen základní URL"},provider:{claude:{title:"Claude",description:"Přihlašovací údaje předplatného Anthropic směrované daemonem."},codex:{title:"Codex",description:"Přihlašovací údaje předplatného OpenAI Codex směrované daemonem."},gemini:{title:"Gemini",description:"Přihlašovací údaje předplatného Google Gemini směrované daemonem."},opencodego:{title:"OpenCodeGo",description:"Statické přihlašovací údaje klíče API směrované daemonem."}},authMethodLabel:"Metoda autorizace",authMethodDesc:{oauth:"Přihlaste se přes prohlížeč; daemon token zachytí a uloží.",manual:"Vložte již získaný token. Je uložen a nikdy znovu nezobrazován."},actions:{authorize:"Autorizovat",enterToken:"Zadat token",refresh:"Obnovit"},accounts:{addAccount:"Přidat účet"},detail:{authMethod:"Metoda autorizace",subscriptionLevel:"Úroveň předplatného",expiresAt:"Vyprší",lastRefreshed:"Naposledy obnoveno",label:"Popisek účtu",labelPlaceholder:"Pojmenujte tento účet",saveLabel:"Uložit popisek"},oauthFlow:{step1:{title:"Otevřete stránku autorizace",desc:"Otevřete přihlašovací stránku v prohlížeči."},step2:{title:"Autorizujte přístup",desc:"Přihlaste se a schvalte přístup pro poskytovatele."},step3:{title:"Zkopírujte autorizační kód",desc:"Stránka zobrazí autorizační kód po schválení."},step4:{title:"Vložte kód",desc:"Vložte autorizační kód níže pro dokončení. Kód přechází pouze k daemonu — vydaný token není nikdy zobrazen."},authorize:"Dokončit přihlášení",showUrl:"Zobrazit URL autorizace"},manual:{title:"Vložit přihlašovací údaje",description:"Vložte již získaný token. Pole jsou omezena na to, co tento poskytovatel přijímá; token je uložen a nikdy znovu zobrazen.",accessTokenPlaceholder:"Vložte přístupový token",refreshTokenPlaceholder:"Vložte obnovovací token (volitelný)",hint:"Token je odeslán daemonu a uložen v zašifrované podobě. Nikdy není znovu zobrazen."},openCodeGo:{apiKeyRequired:"Klíč API je povinný.",apiKeyPlaceholder:"Vložte klíč API",baseUrlPlaceholder:"https://… (volitelné)",zenBaseUrlPlaceholder:"https://… (volitelné)"},info:{title:"O účtech předplatného",description:"Tokeny jsou zapsány do daemona a používány k ověřování upstream požadavků. Jsou uloženy v zašifrované podobě a nikdy znovu nezobrazovány. Odebrání účtu odstraní jeho uložené přihlašovací údaje."},rename:{failed:"Přejmenování účtu se nezdařilo."},refresh:{failed:"Obnovení tokenu se nezdařilo."},errors:{requestFailed:"Požadavek se nezdařil. Zkuste to prosím znovu."},syncWarning:{"external-divergent":"Přihlašovací soubor externího CLI obsahuje novější přihlašovací údaje než tento účet. Uložený token se možná přestane obnovovat — obnovte jej nyní nebo se znovu přihlaste.","external-not-rotated":"Obnovení selhalo a externí CLI obsahuje stejné prošlé přihlašovací údaje. Přihlaste se znovu.","duplicate-token":"Jiný účet sdílí tyto přihlašovací údaje. Obnovení jednoho z nich odhlásí druhý."},importExternal:{detected:"Na tomto počítači bylo nalezeno existující přihlášení CLI {{name}}.",hint:"Po importu jej tato aplikace udržuje aktuální: při každém obnovení tokenu se aktualizuje i přihlašovací soubor CLI, takže CLI v terminálu zůstává přihlášené.",button:"Importovat existující přihlášení CLI"}},RA={title:"Code CLI",description:"Nasměrujte kódovací CLI na odchozí proxy daemona. Tato stránka je pouze ke čtení — není zde co konfigurovat.",copy:"Kopírovat",copied:"Zkopírováno",baseUrl:{title:"Základní URL daemona",description:"Adresa proxy, ke které se vaše CLI připojuje.",label:"Základní URL"},token:{title:"Ověřování",hint:"Pro administrátorské trasy odešlete 'Authorization: Bearer <váš-admin-token>'. Administrátorský token je konfigurován v daemonu (jeho konfigurační soubor nebo prostředí) — zde není nikdy zobrazen."},examples:{title:"Příklad spouštěcího prostředí",keyNote:"Použijte odchozí přístupový klíč vytvořený na stránce Služba API — nikoli administrátorský token.",anthropic:"CLI ve formátu Anthropic",openai:"CLI ve formátu OpenAI"},launchDescription:"Spusťte kódovací CLI v terminálu nasměrované na tohoto daemona. Daemon vloží přesměrování prostředí a spustí CLI za vás.",refresh:"Obnovit",loading:"Zjišťování CLI…",cli:{installed:"Nainstalováno",notFound:"Nenalezeno",notFoundHint:"Toto CLI není v PATH hostitele daemona. Nainstalujte ho a poté obnovte.",install:"Nainstalovat",installing:"Instalování…",installingHint:"Instalování na hostiteli daemona — může to chvíli trvat.",launch:"Spustit",launchTitle:"Spustit {{name}}",launchDescription:"Otevře nový terminál na hostiteli daemona se spuštěným tímto CLI, směrovaným přes proxy daemona. Vyberte volitelný pracovní adresář.",cwdLabel:"Pracovní adresář",cwdPlaceholder:"/cesta/k/vašemu/projektu",runningVia:"Běží · {{provider}} / {{model}}",stop:"Zastavit"},manual:{title:"Ruční nastavení",description:"Preferujete spuštění CLI sami? Nasměrujte ho na daemon pomocí těchto proměnných prostředí.",show:"Zobrazit",hide:"Skrýt"}},DA={probing:"Kontrola daemona…",spawning:"Spouštění daemona…",failed:"Daemon se nepodařilo spustit",failedHint:"Ujistěte se, že je nainstalován Node.js a daemon je sestaven (přítomný adresář dist), nebo nastavte OMNICROSS_DAEMON_ENTRY na cli.js daemona."},EA={title:"Nastavení",description:"Předvolby desktopové aplikace.",desktopOnly:"Možnosti spouštění a systémové lišty platí pouze v desktopové aplikaci.",startup:{title:"Spouštění",autoLaunch:"Spustit při přihlášení",autoLaunchHint:"Spouštět Omnicross automaticky při přihlášení.",startMinimized:"Spustit minimalizováno do systémové lišty",startMinimizedHint:"Spustit na pozadí bez otevření okna."},tray:{title:"Systémová lišta",minimizeOnClose:"Minimalizovat do systémové lišty při zavření",minimizeOnCloseHint:"Zavřením okna ho skryjete do systémové lišty místo ukončení."},language:{title:"Jazyk",label:"Jazyk rozhraní"}},OA={title:"Statistiky využití",description:"Statistiky tokenů a nákladů požadavků obsloužených démonem.",rangeToday:"Dnes",range7d:"Posledních 7 dní",range30d:"Posledních 30 dní",rangeCustom:"Vlastní",from:"Od",to:"Do",totalCost:"Celkové náklady",cacheSavings:"Úspora cache",events:"Požadavky",inputTokens:"Vstupní tokeny",outputTokens:"Výstupní tokeny",cacheReadTokens:"Čtení cache",cacheWriteTokens:"Zápis cache",reasoningTokens:"Tokeny uvažování",byModel:"Podle modelu",byApiKey:"Podle API klíče",provider:"Poskytovatel",model:"Model",cost:"Náklady",apiKey:"API klíč",unpriced:"Bez ceny",unpricedHint:"Pro tento model neexistuje cenový záznam — přidejte ho na stránce Ceník.",unattributed:"Nepřiřazeno",unattributedHint:"Požadavky nespojené s konkrétním API klíčem. To je normální, dokud se přiřazení podle klíčů nezaznamenává.",empty:"V tomto rozsahu nejsou žádné požadavky.",invalidRange:"Vyberte platný rozsah dat."},KA={title:"Ceník modelů",description:"Ceny tokenů podle modelu pro výpočet nákladů požadavků, v USD za 1 mil. tokenů.",search:"Hledat poskytovatele nebo model…",fetchLatest:"Načíst nejnovější",fetching:"Načítání…",addEntry:"Přidat záznam",provider:"Poskytovatel",model:"Model",inputPrice:"Vstup",outputPrice:"Výstup",cacheReadPrice:"Čtení cache",cacheWritePrice:"Zápis cache",source:"Zdroj",updated:"Aktualizováno",userEdited:"upraveno",edit:"Upravit",deleteTitle:"Smazat cenový záznam?",empty:"Ceník je prázdný.",emptyHint:"Načtěte nejnovější ceny pro jeho naplnění.",noMatches:"Hledání neodpovídají žádné záznamy.",saved:"Cenový záznam uložen.",saveFailed:"Uložení selhalo: {{message}}",deleteFailed:"Smazání selhalo: {{message}}",alreadyDeleted:"Záznam už neexistoval.",fetchApplied:"Aktualizováno {{count}} záznamů ze zdroje.",fetchFailed:"Načtení selhalo: {{message}}",requiredId:"Povinné",invalidPrice:"Zadejte nezáporné číslo",conflictTitle:"Vyřešit cenové konflikty",conflictHint:"Tyto záznamy jste upravili a zároveň se změnily ve zdroji. U každého řádku zvolte, zda ponechat svou hodnotu (Přeskočit), nebo převzít novou (Přepsat).",current:"Aktuální",incoming:"Příchozí",overwrite:"Přepsat",skip:"Přeskočit",overwriteAll:"Přepsat vše",skipAll:"Přeskočit vše",applyResolutions:"Použít",resolved:"Přepsáno: {{overwritten}}, přeskočeno: {{skipped}}.",resolvedWithStale:"Přepsáno: {{overwritten}}, přeskočeno: {{skipped}}. {{stale}} se mezitím změnily a zůstaly nedotčené.",refreshFailed:"Změna byla použita, ale opětovné načtení seznamu se nezdařilo: {{message}}",sourceBuiltin:"Vestavěné",sourceLitellm:"LiteLLM",sourceUser:"Uživatel"},UA={providerSettings:zA,apiMode:IA,presetName:SA,common:wA,mediaSettings:TA,appLocal:jA,nav:MA,apiService:NA,accounts:LA,codeCli:RA,daemonStatus:DA,settings:EA,usageStats:OA,pricing:KA},HA={loading:"Indlæser LLM-konfiguration...",reset:{button:"Gendan standardindstillinger",confirmTitle:"Gendan standardindstillinger?",confirmBody:"Dette rydder dine tilpasninger for denne udbyder, så den igen følger de indbyggede standarder. Din API-nøgle og gemte sessioner bevares.",confirmButton:"Gendan standardindstillinger"},reentryBanner:{message:"{{count}} aktiv(e) udbyder(e) skal have deres API-nøgle genindtastet. Åbn hver enkelt og tilføj nøglen igen."},migrationPack:{barHint:"Flyt dine udbydernøgler og abonnementstokens til en anden maskine med en krypteret pakke.",passphrase:"Adgangssætning",passphrasePlaceholder:"Indtast en adgangssætning",passphraseHint:"Brug mindst 8 tegn; 12 eller flere anbefales.",confirm:"Bekræft adgangssætning",confirmPlaceholder:"Gentag adgangssætningen",mismatch:"Adgangssætningerne stemmer ikke overens.",strength:{weak:"For kort — brug mindst 8 tegn.",fair:"OK — 12 eller flere tegn er stærkere.",strong:"Stærk adgangssætning."},export:{button:"Eksportér pakke",title:"Eksportér krypteret pakke",subtitle:"Kryptér dine udbydernøgler og abonnementstokens til en bærbar fil.",warning:"Denne fil indeholder dekrypterbare hemmeligheder. Hold den sikker — enhver med filen og adgangssætningen kan læse dine nøgler. En tabt adgangssætning kan ikke gendannes.",submit:"Eksportér",success:"Pakke eksporteret.",error:"Eksporten mislykkedes. Prøv venligst igen."},import:{button:"Importér pakke",title:"Importér krypteret pakke",subtitle:"Gendan udbydernøgler og abonnementstokens fra en eksporteret pakke.",hint:"Indtast adgangssætningen, der blev brugt ved eksport, og vælg derefter filen.",submit:"Importér",successTitle:"Import fuldført",summary:"Importerede {{providerKeys}} udbydernøgle(r), {{poolKeys}} puljenøgle(r) og {{tokenSets}} tokensæt.",duplicates:"Sprang {{count}} puljenøgle(r) over, da de allerede fandtes.",skipped:"Sprunget over (ingen matchende udbyder): {{names}}",error:"Forkert adgangssætning eller beskadiget pakke. Intet blev ændret."}},searchPlaceholder:"Søg efter udbydere...",emptySearch:"Ingen udbydere matcher din søgning.",emptyList:"Ingen udbydere konfigureret.",selectPrompt:"Vælg en udbyder for at se detaljer",listStatus:"{{count}} model(ler)",noModels:"Ingen modeller konfigureret",enabled:"Aktiveret",disabled:"Deaktiveret",showEnabledOnly:"Vis kun aktiverede",showAll:"Vis alle udbydere",dragHandle:"Træk for at omsortere",reorderFailed:"Kunne ikke gemme udbydernes rækkefølge",credentials:{apiKey:"API-nøgle",apiBaseUrl:"API-basis-URL"},filter:{all:"Alle",chat:"Chat",code:"Kode"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Vælg en skabelon",skipTemplates:"Spring over, konfigurér manuelt",name:"Navn *",providerType:"Type",apiType:"API-type",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standard OpenAI chat/completions API-format",claudecode:"Anthropic Messages API-format (Claude Code)"},chatApiFormat:"API-format",chatApiFormatDescription:"Vælg det API-format, der svarer til din udbyders endpoint",apiKey:"API-nøgle",apiKeyPlaceholder:"sk-... eller $ENV_VAR",apiKeyHelper:"Brug $VAR_NAVN til at referere til miljøvariabler",apiKeySetPlaceholder:"Nøgle er indstillet — lad stå tomt for at beholde den",apiKeyReplaceHelper:"En nøgle er gemt sikkert. Skriv en ny værdi for at erstatte den, eller lad stå tomt for at beholde den.",testApiKey:"Test API-nøgle",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Forhåndsvisning:",models:"Modeller",modelPlaceholder:"Modelnavn (f.eks. gpt-4, claude-3-opus)",transformers:"Transformere",transformerConfig:"API-transformere",transformerConfigDescription:"Konfigurér transformere til at tilpasse API-anmodnings-/svarformater for denne udbyder",transformerConfigNote:"Dæmonen anvender disse transformere i anmodningskæden, efter udbyderens formattransformer (som håndterer wire-formatkonverteringen). Ukendte transformernavne springes over.",enabled:"Aktiveret",apiVersion:"API-version",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API-version (f.eks. 2024-08-01-preview)",official:"Officiel Anthropic API",officialHelper:"Aktivér, hvis denne udbyder opretter direkte forbindelse til den officielle Anthropic API. Deaktivér for reverse proxies eller tredjepartstjenester.",maxConcurrency:"Maks. samtidige anmodninger",maxConcurrencyHelper:"Maksimalt antal samtidige API-anmodninger sendt til denne udbyder. Lavere værdier hjælper med at undgå hastighedsbegrænsning (429-fejl). Sæt `-1` for ingen grænse.",codingPlan:{label:"Kodningsplan",description:"Brug et separat API-endpoint til abonnementsbaserede kodningsplaner",baseUrl:"Kodningsplan basis-URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kodningsplan API-nøgle (valgfri)",apiKeyPlaceholder:"Lad stå tomt for at bruge udbyderens API-nøgle",apiKeyHelper:"Kun nødvendigt, hvis kodningsplanen bruger en anden API-nøgle",tokenPlanHint:"Nogle udbydere (f.eks. Xiaomi MiMo) udsteder Token Plan-nøgler med præfikset `tp-` — kun vejledende, ikke håndhævet."},selectTypeFirst:"Vælg udbydervtype",selectTypeFirstDesc:"Vælg hvilken type udbyder du vil tilføje",codeProviderNote:"Kodeudbydere kræver kun API-nøgle og URL. Modeller administreres af Agent Router.",buttons:{cancel:"Annullér",submitAdd:"Tilføj udbyder",submitUpdate:"Opdatér udbyder",continue:"Fortsæt",back:"Tilbage"}},details:{noSelection:"Vælg en udbyder for at se detaljer",apiKey:"API-nøgle",apiUrl:"API-URL",nameLabel:"Udbydernavn",modelsEndpoint:"Modeller-endpoint",modelsEndpointHelper:"Tilsidesæt opdagelsesendpointet, hvis udbyderen eksponerer en brugerdefineret /models-sti.",models:"Modeller",transformers:"Transformere",codeProviderNote:"Kodeudbydere (som Claude Code) kræver ikke modelkonfiguration. Modeller administreres automatisk af Agent Router.",buttons:{more:"Flere indstillinger",delete:"Slet"}},providerModelSelector:{placeholder:"Vælg udbyder og model",noProviders:"Ingen udbydere tilgængelige",noModels:"Ingen modeller konfigureret"},apiKeyPool:{title:"API-nøglepulje",description:"Konfigurér flere API-nøgler til belastningsfordeling. Hver session holder sig til én nøgle for at bevare prompt-cachen.",defaultLabel:"Standard",weight:"Vægt",noKey:"Ingen nøgle",labelPlaceholder:"Etiket (f.eks. Nøgle #1, Produktion)",addKey:"Tilføj API-nøgle",add:"Tilføj",empty:"Ingen ekstra nøgler konfigureret.",statusCoolingDown:"Nedkøling {{time}}",statusAuthFailed:"Godkendelse mislykkedes · deaktiveret",statusDisabled:"Deaktiveret",statusHealthy:"Fungerer",agoSeconds:"{{count}}s siden",agoMinutes:"{{count}}m siden",agoHours:"{{count}}t siden",agoDays:"{{count}}d siden"},modelsManager:{searchPlaceholder:"Søg efter modeller...",defaultGroup:"Alle modeller",add:"Tilføj model",manage:"Administrér",empty:"Ingen modeller i denne gruppe",enabled:"Aktiveret",disabled:"Deaktiveret",filters:{all:"Alle",vision:"Vision",reasoning:"Ræsonnering",free:"Gratis",tools:"Værktøjer"},manualDialog:{title:"Tilføj model",subtitle:"Tilføj en brugerdefineret model til denne udbyder",modelId:"Model-ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, osv.",modelIdHelper:"Den præcise modelidentifikator, der bruges ved kald til API'en",modelName:"Visningsnavn",modelNamePlaceholder:"Brugervenligt visningsnavn (valgfrit)",modelNameHelper:"Valgfrit navn vist i grænsefladen. Hvis tomt bruges Model-ID",group:"Gruppe",groupPlaceholder:"Vælg eller indtast et gruppenavn",submit:"Tilføj",cancel:"Annullér",helper:"Angiv den præcise modelidentifikator, der eksponeres af udbyderens API."},editDialog:{title:"Redigér model",subtitle:"Ændr modelindstillinger",modelId:"Model-ID",modelIdPlaceholder:"Modelidentifikator",modelIdHelper:"Den modelidentifikator, der bruges ved kald til API'en",modelName:"Visningsnavn",modelNamePlaceholder:"Brugervenligt visningsnavn",modelNameHelper:"Navn vist i grænsefladen",group:"Gruppe",groupPlaceholder:"Vælg eller indtast et gruppenavn",submit:"Gem",cancel:"Annullér",vision:"Visionkapacitet",visionHint:"Om denne model understøtter billede-/visioninput",reasoning:"Ræsonneringsmodel",reasoningHint:"Om denne model understøtter tænke-/ræsonneringstilstand"},manageDialog:{title:"Administrér modeller",cachedAt:"Cachet den {{date}} ({{source}})",refresh:"Opdatér",close:"Luk",raw:"Rå JSON",empty:"Ingen eksterne modeller tilgængelige.",error:"Kunne ikke indlæse modeller: {{message}}",addFromCatalog:"Tilføj",sourceCache:"cache",sourceNetwork:"live",contextLength:"Kontekst {{value}} tokens",maxTokens:"Maks. {{value}} tokens"},messages:{added:"Model tilføjet.",updated:"Model opdateret.",removed:"Model fjernet.",duplicate:"Model findes allerede.",refreshed:"Modeller opdateret",refreshFailed:"Opdatering af modeller mislykkedes"},testDialog:{title:"Forbindelsestest for model",provider:"Udbyder",model:"Model",testing:"Tester...",success:"Test lykkedes",successMessage:"Modellen er tilgængelig og fungerer normalt",failure:"Test mislykkedes",aiResponse:"AI-svar",charCount:"{{count}} tegn",duration:"Varighed {{time}}s",close:"Luk",retest:"Test igen",testButton:"Test model",unsupportedFormat:"Test understøttes endnu ikke for dette udbydervformat."}},router:{title:"Router-konfiguration",description:"Konfigurér hvilken udbyder/model der bruges til forskellige scenarier.",labels:{default:"Standard",background:"baggrund",think:"tænkning",longContext:"Lang kontekst",webSearch:"Websøgning",image:"Billede",longContextThreshold:"Grænse for lang kontekst"},helper:{longContextThreshold:"Antal tokens, inden der skiftes til lang-kontekst-modellen."},placeholder:{required:"Påkrævet",optional:"Valgfrit"}},agentRouter:{title:"Agent Router",description:"Konfigurér tovejsrouting mellem Chat- og Kodetilstand.",searchPlaceholder:"Søg efter routere...",noSearchResults:"Ingen routere matcher din søgning.",tabs:{chatToCode:"Chat → Kode",codeToChatPlaceholder:"Kode → Chat"},chatToCode:{title:"Chat-til-Kode-router",description:"Brug chatudbydere i agent-/kodetilstand",addRouter:"Tilføj router",emptyState:"Ingen Chat→Kode-routere konfigureret. Tilføj én for at bruge chatudbydere i kodetilstand.",form:{name:"Routernavn",namePlaceholder:"Min Chat→Kode-router",chatProvider:"Chatudbyder",chatProviderPlaceholder:"Vælg en chatudbyder",mode:"Tilstand",modeSimple:"Simpel",modeAdvanced:"Avanceret",modeSimpleDesc:"Direkte videregivelse til chatudbyder",modeAdvancedDesc:"Konfigurér modeltilknytning og konteksthåndtering",enabled:"Aktiveret",save:"Gem router",cancel:"Annullér"},list:{provider:"Udbyder",mode:"Tilstand",status:"Status"},mappings:{title:"Modeltilknytninger",description:"Tilknyt chatudbyderes modeller til kodeudbyderes modeller",count:"tilknytning(er)",empty:"Ingen modeltilknytninger konfigureret. Tilføj tilknytninger for at route chatmodeller til kodeudbydere.",addNew:"Tilføj ny tilknytning",selectSource:"Vælg kildemodel (Chat)",selectTarget:"Vælg målmodel (Kode)",targetPlaceholder:"Indtast Claude Code-modelnavn",notSet:"(Ikke indstillet — klik for at vælge)",add:"Tilføj",edit:"Redigér",done:"Færdig"},advanced:{title:"Avanceret konfiguration",description:"Konfigurér modeller til forskellige opgavetyper",helpText:"Standardmodel er påkrævet. Andre modeller er valgfrie og falder tilbage til standard, hvis de ikke er konfigureret.",default:{label:"Standard",placeholder:"Vælg standardmodel",description:"Primær model til generelle opgaver (svarende til Claude Sonnet)"},background:{label:"Baggrund",placeholder:"Vælg baggrundsmodel",description:"Letvægtsmodel til baggrundsopgaver (svarende til Claude Haiku)"},think:{label:"Tænkning",placeholder:"Vælg tænkningsmodel",description:"Avanceret model til kompleks ræsonnering (svarende til Claude Opus)"},image:{label:"Billede",placeholder:"Vælg billedmodel",description:"Model til billedrelaterede opgaver med visionkapacitet"}}},codeToChat:{title:"Kode-til-Chat-router",description:"Eksponér kodningsplanmodeller i chattilstand",addRouter:"Tilføj router",emptyState:"Ingen Kode→Chat-routere konfigureret. Tilføj én for at eksponere kodningsplanmodeller i chattilstand.",form:{name:"Routernavn",namePlaceholder:"Min Kode→Chat-router",codeProvider:"Kodeudbyder",codeProviderPlaceholder:"Vælg en kodeudbyder",codeProviderHelper:"Vælg den kodeudbyder, der skal bruges til transformation",models:"Kodningsplanmodeller",modelsHelper:"Vælg hvilke kodningsplanmodeller der skal eksponeres",enabled:"Aktiveret",save:"Gem router",cancel:"Annullér"},mappings:{title:"Modeltilknytninger",description:"Tilknyt kodeudbyderes modeller til chatudbyderes modeller til eksponering",count:"tilknytning(er)",empty:"Ingen modeltilknytninger konfigureret. Tilføj tilknytninger for at eksponere kodemodeller i chattilstand.",addNew:"Tilføj ny tilknytning",selectSource:"Vælg kildemodel (Kode)",selectTarget:"Vælg målmodel (Chat)",sourcePlaceholder:"Indtast kildemodelnavn",targetPlaceholder:"Indtast målmodelnavn",add:"Tilføj",edit:"Redigér",done:"Færdig"}},transformers:{title:"Transformere",description:"Konfigurér transformere til anmodnings-/svarkonvertering",noProvider:"Vælg en udbyder for at konfigurere transformere",empty:"Ingen transformere",count:"{{count}} transformer(e)"},status:{enabled:"Aktiveret",disabled:"Deaktiveret"},messages:{routerAdded:"Router tilføjet",routerUpdated:"Router opdateret",routerDeleted:"Router slettet",saveFailed:"Kunne ikke gemme router"}},presets:{title:"Tilføj udbyder hurtigt",added:"Tilføjet",add:"Tilføj",features:{search:"Søgning",vision:"Vision",mcp:"MCP",codingPlan:"Kodningsplan"}},alerts:{deleteConfirm:"Er du sikker på, at du vil slette denne udbyder?"},errors:{nameRequired:"Udbydernavn er påkrævet",urlRequired:"API-basis-URL er påkrævet",urlInvalid:"Indtast en gyldig URL (f.eks. https://api.example.com)",saveFailed:"Kunne ikke gemme udbyder",deleteFailed:"Fejl ved sletning af udbyder. Prøv venligst igen.",toggleFailed:"Fejl ved aktivering/deaktivering af udbyder. Prøv venligst igen."},openRouter:{title:"OpenRouter-udbyder-routing",description:"Konfigurér, hvordan anmodninger routes til forskellige udbydere på OpenRouter.",sort:"Routingstrategi",sortTooltip:"Vælg, hvordan udbydere prioriteres. Auto bruger intelligent belastningsfordeling.",order:"Prioritetsrækkefølge for udbydere",orderTooltip:"Angiv udbydere, der skal forsøges i rækkefølge (f.eks. anthropic, openai, together). Tryk Enter for at tilføje.",orderPlaceholder:"Skriv udbyder-slug og tryk Enter...",allowFallbacks:"Tillad fallbacks",allowFallbacksTooltip:"Når aktiveret, vil OpenRouter forsøge reserveudbydere, hvis den primære ikke er tilgængelig.",requireParameters:"Kræv alle parametre",requireParametersTooltip:"Route kun til udbydere, der understøtter alle parametre i din anmodning.",dataCollection:"Politik for dataindsamling",dataCollectionTooltip:"Kontrollér, om udbydere, der muligvis gemmer eller træner på dine data, bruges.",zdr:"Nul dataopbevaring",zdrTooltip:"Route kun til endpoints med politik for nul dataopbevaring.",only:"Tillad kun udbydere",onlyTooltip:"Brug kun disse specifikke udbydere. Lad stå tomt for at tillade alle udbydere.",onlyPlaceholder:"Skriv udbyder-slug og tryk Enter...",ignore:"Ignorér udbydere",ignoreTooltip:"Spring disse udbydere over ved routing af anmodninger.",ignorePlaceholder:"Skriv udbyder-slug og tryk Enter...",quantizations:"Kvantiseringsfilter",quantizationsTooltip:"Brug kun udbydere med specifikke kvantiseringsniveauer. Lavere præcision kan reducere kvalitet men forbedre hastighed.",maxPrice:"Maksimumspris",maxPriceTooltip:"Indstil maksimale prisgrænser per million tokens. Lad stå tomt for ingen grænse.",configured:"Konfigureret"}},FA={label:"API-tilstand",standard:"Standard",codingPlan:"Kodningsplan",tokenPlan:"Tokenplan",apiKeyPrefixHint:"Nøgler til denne plan begynder typisk med `{{prefix}}`. Kun vejledende — ikke håndhævet.",dashscopeCodingPlanSeparateKey:"DashScope Kodningsplan bruger en separat API-nøgle fra standard-endpointet.",baiduCodingPlanSeparateKey:"Qianfan Kodningsplan bruger en separat API-nøgle fra standard-endpointet.",tencentTokenPlanAnthropicOnly:"Tencent Tokenplan er kun Anthropic-protokol.",xiaomiTokenPlanRegions:"Standard baseUrl er `token-plan-cn.*`. Du kan redigere den manuelt til `token-plan-sgp.*` eller `token-plan-ams.*`.",confirmOverwriteTitle:"Skift API-tilstand?",confirmOverwriteBody:"Du har tilpasset API-URL'en eller API-nøglen. Skift af tilstand overskriver dem med den nye tilstands standarder — eller behold dine tilpasninger og opdatér kun tilstandsetiketten.",overwriteAndSwitch:"Overskriv og skift",keepCustomizations:"Behold tilpasninger"},BA={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Tokenplan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},VA={cancel:"Annullér",close:"Luk",copy:"Kopiér",delete:"Slet",dismiss:"Afvis",save:"Gem",optional:"valgfrit",retry:"Prøv igen",loading:"Indlæser…"},qA={common:{learnMore:"Dokumentation"}},$A={notSupportedByDaemon:"Ikke understøttet af dæmonen endnu",discoveryUnsupportedFormat:"Modelregistrering understøttes endnu ikke for dette udbydervformat. Tilføj modeller manuelt."},_A={subtitle:"Kontrolpanel",providers:"Udbydere",apiService:"API-tjeneste",accounts:"Konti",codeCli:"Code CLI",settings:"Indstillinger",usageStats:"Forbrug",pricing:"Priser"},GA={title:"API-tjeneste",description:"Konfigurér den udgående API-server, modelrouting per endpoint og navngivne adgangsnøgler.",loading:"Indlæser serverkonfiguration…",loadError:"Serverkonfigurationen kunne ikke indlæses. Kontrollér at dæmonen er tilgængelig.",enable:{label:"Aktivér udgående server",description:"Start den lokale API-server, der router eksterne kald gennem dine udbydere."},networkBinding:{label:"Tillad LAN-adgang",description:"Bind serveren til din netværksgrænseflade i stedet for kun loopback.",warning:"LAN-adgang eksponerer API-serveren for andre enheder på dit netværk. Kombineret med abonnementsrouting kan anmodninger forbruge din abonnementskvote — hold dette deaktiveret, medmindre du stoler på netværket."},status:{running:"Server kører",stopped:"Server stoppet",runningHint:"Den udgående API-server accepterer anmodninger.",stoppedHint:"Aktivér serveren for at begynde at acceptere anmodninger.",port:"port {{port}}",loopback:"Loopback-URL'er",lan:"LAN-URL'er"},endpoints:{title:"Endpoint-routing",description:"Vælg den model, som hvert wire-format router til. Standardmodellen indstilles her — serveren er en router, ikke en chatapplikation."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Standardmodel",backgroundModel:"Baggrundsmodel",visionModel:"Visionmodel",noVisionModel:"Ingen",backgroundModelIds:"Baggrundsmodel-ID'er",backgroundModelIdsPlaceholder:"kommaseparerede model-ID'er",modelPlaceholder:"Vælg en model…",useSubscription:"Brug abonnement",subscriptionUnsupported:"Abonnementsrouting er ikke tilgængeligt for dette endpoint."},keys:{title:"Adgangsnøgler",description:"Navngivne nøgler, som eksterne kaldere sender som Bearer-token. Den fulde nøgle vises kun én gang ved oprettelse.",namePlaceholder:"Nøglenavn (f.eks. min-cli)",create:"Opret nøgle",empty:"Ingen adgangsnøgler endnu.",enabled:"Aktiveret",disabled:"Deaktiveret",revoked:"Tilbagekaldt",toggle:"Slå nøgle til/fra",revoke:"Tilbagekald",revokeConfirmTitle:"Tilbagekald denne nøgle?",revokeConfirmDesc:'Tilbagekaldelse af "{{name}}" stopper straks dens godkendelse. Dette kan ikke fortrydes.',created:{title:"Nøgle oprettet",warning:"Kopiér denne nøgle nu — den vises ikke igen. Opbevar den sikkert.",copy:"Kopiér",copied:"Kopieret",dismiss:"Færdig"}}},WA={title:"Konti og abonnementer",description:"Administrér de abonnementskredentialer, som serveren router igennem. Tokens skrives her, men vises aldrig igen.",loading:"Indlæser konti…",empty:"Ingen abonnementsudbydere er tilgængelige.",signIn:"Log ind",oauth:{title:"Log ind på {{name}}",description:"Åbn login-siden i din browser, autorisér, og indsæt derefter autorisationskoden nedenfor. Koden sendes kun til dæmonen — det oprettede token vises aldrig.",openPage:"Åbn login-side",codeLabel:"Autorisationskode",codePlaceholder:"Indsæt koden her",submit:"Fuldfør login"},codexOauth:{title:"Log ind på {{name}}",description:"Åbn login-siden i din browser og autorisér. Dæmonen registrerer resultatet automatisk — hold dette åbent, indtil det er fuldført. Tokenet vises aldrig.",waiting:"Venter på, at du fuldfører login i din browser…",failed:"Login mislykkedes. Prøv venligst igen."},clearProvider:"Ryd alle",clearConfirmTitle:"Ryd {{name}}-konti?",clearConfirmDesc:"Dette fjerner alle gemte kredentialer for denne udbyder. Dette kan ikke fortrydes.",credential:{ok:"Konfigureret",notConfigured:"Ikke konfigureret"},kind:{"pass-through":"Videregivne kredentialer","oauth-bearer":"OAuth-bearer","static-bearer":"Statisk bearer-nøgle"},reason:{"missing-credential":"Ingen credential gemt.",expired:"Credential udløbet.","reauth-required":"Gengodkendelse påkrævet.","refresh-failed":"Tokenfornyet mislykkedes.","not-refreshable":"Credential kan ikke fornyes.",unknown:"Status ukendt."},status:{unconfigured:"Ikke konfigureret",authorized:"Autoriseret",configured:"Konfigureret",expired:"Udløbet",error:"Fejl"},authMethod:{oauth:"OAuth",setup_token:"Opsætningstoken",manual:"Manuel"},list:{empty:"Ingen konti gemt for denne udbyder.",active:"Aktiv",expiresAt:"Udløber {{value}}",setActive:"Sæt som aktiv",remove:"Fjern",removeConfirmTitle:"Fjern denne konto?",removeConfirmDesc:'Fjernelse af "{{name}}" sletter den gemte credential. Dette kan ikke fortrydes.',title:"Konti"},write:{trigger:"Tilføj credential",title:"Skriv {{name}}-credential",description:"Indsæt allerede indhentet tokenmateriale. Felter er begrænset til hvad denne udbyder accepterer; tokenet gemmes og vises aldrig igen.",authMethod:"Godkendelsesmetode",status:"Status",subscriptionLevel:"Abonnementsniveau",subscriptionLevelNone:"Ikke indstillet",submit:"Gem credential"},field:{accessToken:"Adgangstoken",refreshToken:"Opdateringstoken",idToken:"ID-token",apiKey:"API-nøgle",expiresAt:"Udløber (ISO)",setupTokenExpiresAt:"Opsætningstoken udløber (ISO)",accountId:"Konto-ID",email:"E-mail",organizationId:"Organisations-ID",baseUrl:"Basis-URL",zenBaseUrl:"Zen basis-URL"},provider:{claude:{title:"Claude",description:"Anthropic-abonnementskredentialer routet af dæmonen."},codex:{title:"Codex",description:"OpenAI Codex-abonnementskredentialer routet af dæmonen."},gemini:{title:"Gemini",description:"Google Gemini-abonnementskredentialer routet af dæmonen."},opencodego:{title:"OpenCodeGo",description:"Statiske API-nøglekredentialer routet af dæmonen."}},authMethodLabel:"Autorisationsmetode",authMethodDesc:{oauth:"Log ind via din browser; dæmonen registrerer og gemmer tokenet.",manual:"Indsæt et allerede indhentet token. Det gemmes og vises aldrig igen."},actions:{authorize:"Autorisér",enterToken:"Indtast token",refresh:"Opdatér"},accounts:{addAccount:"Tilføj konto"},detail:{authMethod:"Autorisationsmetode",subscriptionLevel:"Abonnementsniveau",expiresAt:"Udløber",lastRefreshed:"Sidst opdateret",label:"Kontoetiket",labelPlaceholder:"Navngiv denne konto",saveLabel:"Gem etiket"},oauthFlow:{step1:{title:"Åbn autorisationssiden",desc:"Åbn login-siden i din browser."},step2:{title:"Autorisér adgang",desc:"Log ind og godkend adgang for udbyderen."},step3:{title:"Kopiér autorisationskoden",desc:"Siden viser en autorisationskode, når du godkender."},step4:{title:"Indsæt koden",desc:"Indsæt autorisationskoden nedenfor for at afslutte. Koden sendes kun til dæmonen — det oprettede token vises aldrig."},authorize:"Fuldfør login",showUrl:"Vis autorisations-URL"},manual:{title:"Indsæt credential",description:"Indsæt et allerede indhentet token. Felter er begrænset til hvad denne udbyder accepterer; tokenet gemmes og vises aldrig igen.",accessTokenPlaceholder:"Indsæt adgangstokenet",refreshTokenPlaceholder:"Indsæt opdateringstokenet (valgfrit)",hint:"Tokenet sendes til dæmonen og gemmes krypteret. Det vises aldrig igen."},openCodeGo:{apiKeyRequired:"En API-nøgle er påkrævet.",apiKeyPlaceholder:"Indsæt API-nøglen",baseUrlPlaceholder:"https://… (valgfrit)",zenBaseUrlPlaceholder:"https://… (valgfrit)"},info:{title:"Om abonnementskonti",description:"Tokens skrives til dæmonen og bruges til at godkende upstream-anmodninger. De gemmes krypteret og vises aldrig igen. Fjernelse af en konto sletter den gemte credential."},rename:{failed:"Kontoen kunne ikke omdøbes."},refresh:{failed:"Tokenet kunne ikke opdateres."},errors:{requestFailed:"Anmodningen mislykkedes. Prøv venligst igen."},syncWarning:{"external-divergent":"Den eksterne CLI-loginfil indeholder nyere legitimationsoplysninger end denne konto. Det gemte token kan muligvis ikke længere opdateres — opdater nu, eller log ind igen.","external-not-rotated":"Opdateringen mislykkedes, og den eksterne CLI indeholder de samme udløbne legitimationsoplysninger. Log ind igen.","duplicate-token":"En anden konto deler disse legitimationsoplysninger. Opdatering af den ene logger den anden ud."},importExternal:{detected:"Der blev fundet et eksisterende {{name}}-CLI-login på denne maskine.",hint:"Efter importen holder denne app det opdateret: ved hver tokenopdatering opdateres CLI-loginfilen også, så CLI’en i terminalen forbliver logget ind.",button:"Importér eksisterende CLI-login"}},ZA={title:"Code CLI",description:"Peg en kodnings-CLI mod dæmonens udgående proxy. Denne side er skrivebeskyttet — der er intet at konfigurere her.",copy:"Kopiér",copied:"Kopieret",baseUrl:{title:"Dæmon basis-URL",description:"Den proxyadresse, din CLI opretter forbindelse til.",label:"Basis-URL"},token:{title:"Godkendelse",hint:"Send 'Authorization: Bearer <dit-admintoken>' for administratorruter. Admintokenet konfigureres i dæmonen (dens konfigurationsfil eller miljø) — det vises aldrig her."},examples:{title:"Eksempel på startmiljø",keyNote:"Brug en udgående adgangsnøgle oprettet på API-tjenestesiden — ikke admintokenet.",anthropic:"Anthropic-format CLI",openai:"OpenAI-format CLI"},launchDescription:"Start en kodnings-CLI i en terminal, peget mod denne dæmon. Dæmonen injicerer omledirningsmiljøet og starter CLI'en for dig.",refresh:"Opdatér",loading:"Registrerer CLI'er…",cli:{installed:"Installeret",notFound:"Ikke fundet",notFoundHint:"Denne CLI er ikke på dæmonværtens PATH. Installér den og opdatér.",install:"Installér",installing:"Installerer…",installingHint:"Installerer på dæmonværten — dette kan tage et øjeblik.",launch:"Start",launchTitle:"Start {{name}}",launchDescription:"Åbner en ny terminal på dæmonværten, der kører denne CLI, routet gennem dæmonproxyen. Vælg en valgfri arbejdsmappe.",cwdLabel:"Arbejdsmappe",cwdPlaceholder:"/sti/til/dit/projekt",runningVia:"Kører · {{provider}} / {{model}}",stop:"Stop"},manual:{title:"Manuel opsætning",description:"Foretrækker du at køre CLI'en selv? Peg den mod dæmonen med disse miljøvariabler.",show:"Vis",hide:"Skjul"}},QA={probing:"Kontrollerer for dæmon…",spawning:"Starter dæmon…",failed:"Dæmonen kunne ikke starte",failedHint:"Sørg for at Node.js er installeret og dæmonen er bygget (dist til stede), eller sæt OMNICROSS_DAEMON_ENTRY til dæmonens cli.js."},YA={title:"Indstillinger",description:"Præferencer for desktopapplicationen.",desktopOnly:"Opstart- og systembakkemuligheder gælder kun i desktopapplicationen.",startup:{title:"Opstart",autoLaunch:"Start ved login",autoLaunchHint:"Start Omnicross automatisk, når du logger ind.",startMinimized:"Start minimeret til systembakke",startMinimizedHint:"Start i baggrunden uden at åbne vinduet."},tray:{title:"Systembakke",minimizeOnClose:"Minimér til systembakke ved lukning",minimizeOnCloseHint:"Lukning af vinduet skjuler det i systembakken i stedet for at afslutte."},language:{title:"Sprog",label:"Grænsefladesprog"}},XA={title:"Forbrugsstatistik",description:"Token- og omkostningsstatistik for forespørgsler håndteret af dæmonen.",rangeToday:"I dag",range7d:"Seneste 7 dage",range30d:"Seneste 30 dage",rangeCustom:"Tilpasset",from:"Fra",to:"Til",totalCost:"Samlet omkostning",cacheSavings:"Cache-besparelse",events:"Forespørgsler",inputTokens:"Input-tokens",outputTokens:"Output-tokens",cacheReadTokens:"Cache-læsning",cacheWriteTokens:"Cache-skrivning",reasoningTokens:"Ræsonnement-tokens",byModel:"Pr. model",byApiKey:"Pr. API-nøgle",provider:"Udbyder",model:"Model",cost:"Omkostning",apiKey:"API-nøgle",unpriced:"Uden pris",unpricedHint:"Der findes ingen prispost for denne model — tilføj en på siden Priser.",unattributed:"Ikke tildelt",unattributedHint:"Forespørgsler, der ikke er knyttet til en bestemt API-nøgle. Dette er forventet, indtil tildeling pr. nøgle registreres.",empty:"Ingen forespørgsler i dette interval.",invalidRange:"Vælg et gyldigt datointerval."},JA={title:"Modelpriser",description:"Tokenpriser pr. model til omkostningsberegning, i USD pr. million tokens.",search:"Søg efter udbyder eller model…",fetchLatest:"Hent seneste",fetching:"Henter…",addEntry:"Tilføj post",provider:"Udbyder",model:"Model",inputPrice:"Input",outputPrice:"Output",cacheReadPrice:"Cache-læsning",cacheWritePrice:"Cache-skrivning",source:"Kilde",updated:"Opdateret",userEdited:"redigeret",edit:"Rediger",deleteTitle:"Slet prisposten?",empty:"Pristabellen er tom.",emptyHint:"Hent de seneste priser for at udfylde den.",noMatches:"Ingen poster matcher din søgning.",saved:"Prispost gemt.",saveFailed:"Gem mislykkedes: {{message}}",deleteFailed:"Sletning mislykkedes: {{message}}",alreadyDeleted:"Posten fandtes ikke længere.",fetchApplied:"{{count}} poster opdateret fra kilden.",fetchFailed:"Hentning mislykkedes: {{message}}",requiredId:"Påkrævet",invalidPrice:"Indtast et ikke-negativt tal",conflictTitle:"Løs priskonflikter",conflictHint:"Disse poster er redigeret af dig og har også ændret sig i kilden. Vælg pr. række, om du vil beholde din værdi (Spring over) eller tage den indkommende (Overskriv).",current:"Aktuel",incoming:"Indkommende",overwrite:"Overskriv",skip:"Spring over",overwriteAll:"Overskriv alle",skipAll:"Spring alle over",applyResolutions:"Anvend",resolved:"{{overwritten}} overskrevet, {{skipped}} sprunget over.",resolvedWithStale:"{{overwritten}} overskrevet, {{skipped}} sprunget over. {{stale}} blev ændret i mellemtiden og forblev urørte.",refreshFailed:"Ændringen blev anvendt, men genindlæsning af listen mislykkedes: {{message}}",sourceBuiltin:"Indbygget",sourceLitellm:"LiteLLM",sourceUser:"Bruger"},eC={providerSettings:HA,apiMode:FA,presetName:BA,common:VA,mediaSettings:qA,appLocal:$A,nav:_A,apiService:GA,accounts:WA,codeCli:ZA,daemonStatus:QA,settings:YA,usageStats:XA,pricing:JA},tC={loading:"LLM-Konfiguration wird geladen...",reset:{button:"Standardwerte wiederherstellen",confirmTitle:"Standardeinstellungen wiederherstellen?",confirmBody:"Dies löscht Ihre Anpassungen für diesen Anbieter, sodass wieder die integrierten Standardwerte gelten. Ihr API-Key und gespeicherte Sitzungen bleiben erhalten.",confirmButton:"Standardwerte wiederherstellen"},reentryBanner:{message:"{{count}} aktivierter/aktivierte Anbieter benötigt/benötigen eine erneute Eingabe des API-Keys. Öffnen Sie jeden Anbieter und geben Sie den Key erneut ein."},migrationPack:{barHint:"Übertragen Sie Ihre Anbieter-Keys und Abonnement-Tokens mit einem verschlüsselten Paket auf einen anderen Computer.",passphrase:"Passphrase",passphrasePlaceholder:"Passphrase eingeben",passphraseHint:"Verwenden Sie mindestens 8 Zeichen; 12 oder mehr werden empfohlen.",confirm:"Passphrase bestätigen",confirmPlaceholder:"Passphrase erneut eingeben",mismatch:"Die Passphrases stimmen nicht überein.",strength:{weak:"Zu kurz — verwenden Sie mindestens 8 Zeichen.",fair:"Akzeptabel — 12 oder mehr Zeichen sind sicherer.",strong:"Starke Passphrase."},export:{button:"Paket exportieren",title:"Verschlüsseltes Paket exportieren",subtitle:"Verschlüsseln Sie Ihre Anbieter-Keys und Abonnement-Tokens in einer portablen Datei.",warning:"Diese Datei enthält entschlüsselbare Geheimnisse. Bewahren Sie sie sicher auf — jeder mit der Datei und der Passphrase kann Ihre Keys lesen. Eine verlorene Passphrase kann nicht wiederhergestellt werden.",submit:"Exportieren",success:"Paket erfolgreich exportiert.",error:"Export fehlgeschlagen. Bitte versuchen Sie es erneut."},import:{button:"Paket importieren",title:"Verschlüsseltes Paket importieren",subtitle:"Stellen Sie Anbieter-Keys und Abonnement-Tokens aus einem exportierten Paket wieder her.",hint:"Geben Sie die beim Export verwendete Passphrase ein und wählen Sie dann die Datei.",submit:"Importieren",successTitle:"Import abgeschlossen",summary:"{{providerKeys}} Anbieter-Key(s), {{poolKeys}} Pool-Key(s) und {{tokenSets}} Token-Set(s) importiert.",duplicates:"{{count}} bereits vorhandene(r) Pool-Key(s) übersprungen.",skipped:"Übersprungen (kein passender Anbieter): {{names}}",error:"Falsche Passphrase oder beschädigtes Paket. Es wurden keine Änderungen vorgenommen."}},searchPlaceholder:"Anbieter suchen...",emptySearch:"Keine Anbieter entsprechen Ihrer Suche.",emptyList:"Keine Anbieter konfiguriert.",selectPrompt:"Wählen Sie einen Anbieter aus, um Details anzuzeigen",listStatus:"{{count}} Modell(e)",noModels:"Keine Modelle konfiguriert",enabled:"Aktiviert",disabled:"Deaktiviert",showEnabledOnly:"Nur aktivierte anzeigen",showAll:"Alle Anbieter anzeigen",dragHandle:"Ziehen zum Neuanordnen",reorderFailed:"Anbieterreihenfolge konnte nicht gespeichert werden",credentials:{apiKey:"API-Key",apiBaseUrl:"API-Basis-URL"},filter:{all:"Alle",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Vorlage auswählen",skipTemplates:"Überspringen, manuell konfigurieren",name:"Name *",providerType:"Typ",apiType:"API-Typ",apiTypeOptions:{openai:"OpenAI-Vervollständigung",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standard-OpenAI-Chat/Completions-API-Format",claudecode:"Anthropic Messages API-Format (Claude Code)"},chatApiFormat:"API-Format",chatApiFormatDescription:"Wählen Sie das API-Format, das zum Endpunkt Ihres Anbieters passt",apiKey:"API-Key",apiKeyPlaceholder:"sk-... oder $ENV_VAR",apiKeyHelper:"Verwenden Sie $VAR_NAME, um auf Umgebungsvariablen zu verweisen",apiKeySetPlaceholder:"Key ist gesetzt — leer lassen, um ihn beizubehalten",apiKeyReplaceHelper:"Ein Key ist sicher gespeichert. Geben Sie einen neuen Wert ein, um ihn zu ersetzen, oder lassen Sie das Feld leer, um ihn zu behalten.",testApiKey:"API-Key testen",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Vorschau:",models:"Modelle",modelPlaceholder:"Modellname (z. B. gpt-4, claude-3-opus)",transformers:"Transformer",transformerConfig:"API-Transformer",transformerConfigDescription:"Konfigurieren Sie Transformer, um API-Anfrage-/Antwortformate für diesen Anbieter anzupassen",transformerConfigNote:"Der Daemon wendet diese Transformer in der Anfragekette an, nach dem Format-Transformer des Anbieters (der die Wire-Format-Konvertierung übernimmt). Unbekannte Transformer-Namen werden übersprungen.",enabled:"Aktiviert",apiVersion:"API-Version",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API-Version (z. B. 2024-08-01-preview)",official:"Offizielle Anthropic API",officialHelper:"Aktivieren, wenn dieser Anbieter direkt mit der offiziellen Anthropic API verbunden ist. Deaktivieren für Reverse Proxys oder Drittanbieterdienste.",maxConcurrency:"Max. gleichzeitige Anfragen",maxConcurrencyHelper:"Maximale Anzahl gleichzeitiger API-Anfragen an diesen Anbieter. Niedrigere Werte helfen, Rate-Limiting zu vermeiden (429-Fehler). Setzen Sie `-1` für kein Limit.",codingPlan:{label:"Coding Plan",description:"Separaten API-Endpunkt für abonnementbasierte Coding Plans verwenden",baseUrl:"Coding Plan Basis-URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API-Key (optional)",apiKeyPlaceholder:"Leer lassen, um den API-Key des Anbieters zu verwenden",apiKeyHelper:"Nur erforderlich, wenn der Coding Plan einen anderen API-Key verwendet",tokenPlanHint:"Einige Anbieter (z. B. Xiaomi MiMo) stellen Token Plan Keys mit dem Präfix `tp-` aus — nur informativ, wird nicht erzwungen."},selectTypeFirst:"Anbietertyp auswählen",selectTypeFirstDesc:"Wählen Sie, welchen Anbietertyp Sie hinzufügen möchten",codeProviderNote:"Code-Anbieter benötigen nur API-Key und URL. Modelle werden vom Agent Router verwaltet.",buttons:{cancel:"Abbrechen",submitAdd:"Anbieter hinzufügen",submitUpdate:"Anbieter aktualisieren",continue:"Weiter",back:"Zurück"}},details:{noSelection:"Wählen Sie einen Anbieter aus, um Details anzuzeigen",apiKey:"API-Key",apiUrl:"API-URL",nameLabel:"Anbietername",modelsEndpoint:"Modell-Endpunkt",modelsEndpointHelper:"Überschreiben Sie den Discovery-Endpunkt, wenn der Anbieter einen benutzerdefinierten /models-Pfad bereitstellt.",models:"Modelle",transformers:"Transformer",codeProviderNote:"Code-Anbieter (wie Claude Code) erfordern keine Modellkonfiguration. Modelle werden automatisch vom Agent Router verwaltet.",buttons:{more:"Weitere Einstellungen",delete:"Löschen"}},providerModelSelector:{placeholder:"Anbieter und Modell auswählen",noProviders:"Keine Anbieter verfügbar",noModels:"Keine Modelle konfiguriert"},apiKeyPool:{title:"API-Key-Pool",description:"Konfigurieren Sie mehrere API-Keys für den Lastausgleich. Jede Sitzung bleibt einem Key zugeordnet, um den Prompt-Cache zu erhalten.",defaultLabel:"Standard",weight:"Gewichtung",noKey:"Kein Key",labelPlaceholder:"Bezeichnung (z. B. Key #1, Produktion)",addKey:"API-Key hinzufügen",add:"Hinzufügen",empty:"Keine zusätzlichen Keys konfiguriert.",statusCoolingDown:"Abkühlphase {{time}}",statusAuthFailed:"Authentifizierung fehlgeschlagen · deaktiviert",statusDisabled:"Deaktiviert",statusHealthy:"Betriebsbereit",agoSeconds:"vor {{count}}s",agoMinutes:"vor {{count}}min",agoHours:"vor {{count}}h",agoDays:"vor {{count}}T"},modelsManager:{searchPlaceholder:"Modelle suchen...",defaultGroup:"Alle Modelle",add:"Modell hinzufügen",manage:"Verwalten",empty:"Keine Modelle in dieser Gruppe",enabled:"Aktiviert",disabled:"Deaktiviert",filters:{all:"Alle",vision:"Vision",reasoning:"Reasoning",free:"Kostenlos",tools:"Tools"},manualDialog:{title:"Modell hinzufügen",subtitle:"Benutzerdefiniertes Modell zu diesem Anbieter hinzufügen",modelId:"Modell-ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash usw.",modelIdHelper:"Der genaue Modellbezeichner, der beim API-Aufruf verwendet wird",modelName:"Anzeigename",modelNamePlaceholder:"Benutzerfreundlicher Anzeigename (optional)",modelNameHelper:"Optionaler Name, der in der Oberfläche angezeigt wird. Wenn leer, wird die Modell-ID verwendet",group:"Gruppe",groupPlaceholder:"Gruppenname auswählen oder eingeben",submit:"Hinzufügen",cancel:"Abbrechen",helper:"Geben Sie den genauen Modellbezeichner an, der von der Anbieter-API bereitgestellt wird."},editDialog:{title:"Modell bearbeiten",subtitle:"Modelleinstellungen ändern",modelId:"Modell-ID",modelIdPlaceholder:"Modellbezeichner",modelIdHelper:"Der Modellbezeichner, der beim API-Aufruf verwendet wird",modelName:"Anzeigename",modelNamePlaceholder:"Benutzerfreundlicher Anzeigename",modelNameHelper:"In der Oberfläche angezeigter Name",group:"Gruppe",groupPlaceholder:"Gruppenname auswählen oder eingeben",submit:"Speichern",cancel:"Abbrechen",vision:"Vision-Fähigkeit",visionHint:"Gibt an, ob dieses Modell Bild-/Vision-Eingaben unterstützt",reasoning:"Reasoning-Modell",reasoningHint:"Gibt an, ob dieses Modell den Denk-/Reasoning-Modus unterstützt"},manageDialog:{title:"Modelle verwalten",cachedAt:"Gecacht am {{date}} ({{source}})",refresh:"Aktualisieren",close:"Schließen",raw:"Raw JSON",empty:"Keine Remote-Modelle verfügbar.",error:"Modelle konnten nicht geladen werden: {{message}}",addFromCatalog:"Hinzufügen",sourceCache:"Cache",sourceNetwork:"Live",contextLength:"Kontext {{value}} Token",maxTokens:"Max. {{value}} Token"},messages:{added:"Modell hinzugefügt.",updated:"Modell aktualisiert.",removed:"Modell entfernt.",duplicate:"Modell existiert bereits.",refreshed:"Modelle aktualisiert",refreshFailed:"Modelle konnten nicht aktualisiert werden"},testDialog:{title:"Modell-Konnektivitätstest",provider:"Anbieter",model:"Modell",testing:"Test läuft...",success:"Test erfolgreich",successMessage:"Modell ist normal erreichbar",failure:"Test fehlgeschlagen",aiResponse:"KI-Antwort",charCount:"{{count}} Zeichen",duration:"Dauer {{time}}s",close:"Schließen",retest:"Erneut testen",testButton:"Modell testen",unsupportedFormat:"Tests werden für dieses Anbieterformat noch nicht unterstützt."}},router:{title:"Router-Konfiguration",description:"Konfigurieren Sie, welcher Anbieter/welches Modell für verschiedene Szenarien verwendet wird.",labels:{default:"Standard",background:"Hintergrund",think:"Denken",longContext:"Langer Kontext",webSearch:"Websuche",image:"Bild",longContextThreshold:"Schwellenwert für langen Kontext"},helper:{longContextThreshold:"Token-Anzahl, bevor zum Langkontext-Modell gewechselt wird."},placeholder:{required:"Erforderlich",optional:"Optional"}},agentRouter:{title:"Agent Router",description:"Konfigurieren Sie das bidirektionale Routing zwischen Chat- und Code-Modus.",searchPlaceholder:"Router suchen...",noSearchResults:"Keine Router entsprechen Ihrer Suche.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Chat-zu-Code-Router",description:"Chat-Anbieter im Agenten-/Codiermodus verwenden",addRouter:"Router hinzufügen",emptyState:"Keine Chat→Code-Router konfiguriert. Fügen Sie einen hinzu, um Chat-Anbieter im Codiermodus zu verwenden.",form:{name:"Router-Name",namePlaceholder:"Mein Chat→Code-Router",chatProvider:"Chat-Anbieter",chatProviderPlaceholder:"Chat-Anbieter auswählen",mode:"Modus",modeSimple:"Einfach",modeAdvanced:"Erweitert",modeSimpleDesc:"Direkter Durchlauf zum Chat-Anbieter",modeAdvancedDesc:"Modell-Mapping und Kontextbehandlung konfigurieren",enabled:"Aktiviert",save:"Router speichern",cancel:"Abbrechen"},list:{provider:"Anbieter",mode:"Modus",status:"Status"},mappings:{title:"Modell-Mappings",description:"Chat-Anbietermodelle auf Code-Anbietermodelle abbilden",count:"Mapping(s)",empty:"Keine Modell-Mappings konfiguriert. Fügen Sie Mappings hinzu, um Chat-Modelle zu Code-Anbietern zu routen.",addNew:"Neues Mapping hinzufügen",selectSource:"Quellmodell auswählen (Chat)",selectTarget:"Zielmodell auswählen (Code)",targetPlaceholder:"Claude Code Modellnamen eingeben",notSet:"(Nicht gesetzt – zum Auswählen klicken)",add:"Hinzufügen",edit:"Bearbeiten",done:"Fertig"},advanced:{title:"Erweiterte Konfiguration",description:"Modelle für verschiedene Aufgabentypen konfigurieren",helpText:"Das Standardmodell ist erforderlich. Andere Modelle sind optional und fallen auf das Standardmodell zurück, wenn sie nicht konfiguriert sind.",default:{label:"Standard",placeholder:"Standardmodell auswählen",description:"Hauptmodell für allgemeine Aufgaben (ähnlich wie Claude Sonnet)"},background:{label:"Hintergrund",placeholder:"Hintergrundmodell auswählen",description:"Leichtes Modell für Hintergrundaufgaben (ähnlich wie Claude Haiku)"},think:{label:"Denken",placeholder:"Denkmodell auswählen",description:"Erweitertes Modell für komplexes Reasoning (ähnlich wie Claude Opus)"},image:{label:"Bild",placeholder:"Bildmodell auswählen",description:"Modell für bildbasierte Aufgaben mit Vision-Fähigkeit"}}},codeToChat:{title:"Code-zu-Chat-Router",description:"Coding Plan Modelle im Chat-Modus bereitstellen",addRouter:"Router hinzufügen",emptyState:"Keine Code→Chat-Router konfiguriert. Fügen Sie einen hinzu, um Coding Plan Modelle im Chat-Modus bereitzustellen.",form:{name:"Router-Name",namePlaceholder:"Mein Code→Chat-Router",codeProvider:"Code-Anbieter",codeProviderPlaceholder:"Code-Anbieter auswählen",codeProviderHelper:"Wählen Sie den Code-Anbieter für die Transformation",models:"Coding Plan Modelle",modelsHelper:"Wählen Sie, welche Coding Plan Modelle bereitgestellt werden sollen",enabled:"Aktiviert",save:"Router speichern",cancel:"Abbrechen"},mappings:{title:"Modell-Mappings",description:"Code-Anbietermodelle auf Chat-Anbietermodelle abbilden, um sie bereitzustellen",count:"Mapping(s)",empty:"Keine Modell-Mappings konfiguriert. Fügen Sie Mappings hinzu, um Code-Modelle im Chat-Modus bereitzustellen.",addNew:"Neues Mapping hinzufügen",selectSource:"Quellmodell auswählen (Code)",selectTarget:"Zielmodell auswählen (Chat)",sourcePlaceholder:"Quellmodellnamen eingeben",targetPlaceholder:"Zielmodellnamen eingeben",add:"Hinzufügen",edit:"Bearbeiten",done:"Fertig"}},transformers:{title:"Transformer",description:"Transformer für die Anfrage-/Antwortkonvertierung konfigurieren",noProvider:"Wählen Sie einen Anbieter, um Transformer zu konfigurieren",empty:"Keine Transformer",count:"{{count}} Transformer"},status:{enabled:"Aktiviert",disabled:"Deaktiviert"},messages:{routerAdded:"Router erfolgreich hinzugefügt",routerUpdated:"Router erfolgreich aktualisiert",routerDeleted:"Router erfolgreich gelöscht",saveFailed:"Router konnte nicht gespeichert werden"}},presets:{title:"Anbieter schnell hinzufügen",added:"Hinzugefügt",add:"Hinzufügen",features:{search:"Suche",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"Möchten Sie diesen Anbieter wirklich löschen?"},errors:{nameRequired:"Anbietername ist erforderlich",urlRequired:"API-Basis-URL ist erforderlich",urlInvalid:"Bitte geben Sie eine gültige URL ein (z. B. https://api.example.com)",saveFailed:"Anbieter konnte nicht gespeichert werden",deleteFailed:"Fehler beim Löschen des Anbieters. Bitte versuchen Sie es erneut.",toggleFailed:"Fehler beim Aktivieren/Deaktivieren des Anbieters. Bitte versuchen Sie es erneut."},openRouter:{title:"OpenRouter-Anbieter-Routing",description:"Konfigurieren Sie, wie Anfragen zu verschiedenen Anbietern auf OpenRouter geleitet werden.",sort:"Routing-Strategie",sortTooltip:"Wählen Sie, wie Anbieter priorisiert werden. Automatisch verwendet intelligenten Lastausgleich.",order:"Anbieter-Prioritätsreihenfolge",orderTooltip:"Geben Sie Anbieter in der Reihenfolge an, in der sie versucht werden sollen (z. B. anthropic, openai, together). Drücken Sie Enter zum Hinzufügen.",orderPlaceholder:"Anbieter-Slug eingeben und Enter drücken...",allowFallbacks:"Fallbacks erlauben",allowFallbacksTooltip:"Wenn aktiviert, versucht OpenRouter Backup-Anbieter, wenn der primäre nicht verfügbar ist.",requireParameters:"Alle Parameter erfordern",requireParametersTooltip:"Nur zu Anbietern routen, die alle Parameter in Ihrer Anfrage unterstützen.",dataCollection:"Datenerfassungsrichtlinie",dataCollectionTooltip:"Steuern Sie, ob Anbieter verwendet werden, die Ihre Daten möglicherweise speichern oder für Training verwenden.",zdr:"Zero Data Retention",zdrTooltip:"Nur zu Endpunkten mit Zero Data Retention Richtlinie routen.",only:"Nur diese Anbieter erlauben",onlyTooltip:"Nur diese spezifischen Anbieter verwenden. Leer lassen, um alle Anbieter zu erlauben.",onlyPlaceholder:"Anbieter-Slug eingeben und Enter drücken...",ignore:"Anbieter ignorieren",ignoreTooltip:"Diese Anbieter beim Routing von Anfragen überspringen.",ignorePlaceholder:"Anbieter-Slug eingeben und Enter drücken...",quantizations:"Quantisierungsfilter",quantizationsTooltip:"Nur Anbieter mit bestimmten Quantisierungsstufen verwenden. Geringere Präzision kann die Qualität verringern, aber die Geschwindigkeit verbessern.",maxPrice:"Höchstpreis",maxPriceTooltip:"Maximale Preisgrenzen pro Million Token festlegen. Leer lassen für kein Limit.",configured:"Konfiguriert"}},aC={label:"API-Modus",standard:"Standard",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Keys für diesen Plan beginnen typischerweise mit `{{prefix}}`. Nur ein Hinweis — wird nicht erzwungen.",dashscopeCodingPlanSeparateKey:"Der DashScope Coding Plan verwendet einen separaten API-Key vom Standard-Endpunkt.",baiduCodingPlanSeparateKey:"Der Qianfan Coding Plan verwendet einen separaten API-Key vom Standard-Endpunkt.",tencentTokenPlanAnthropicOnly:"Der Tencent Token Plan ist ausschließlich mit dem Anthropic-Protokoll kompatibel.",xiaomiTokenPlanRegions:"Die Standard-Basis-URL ist `token-plan-cn.*`. Sie können sie manuell auf `token-plan-sgp.*` oder `token-plan-ams.*` ändern.",confirmOverwriteTitle:"API-Modus wechseln?",confirmOverwriteBody:"Sie haben die API-URL oder den API-Key angepasst. Das Wechseln des Modus überschreibt diese mit den Standardwerten des neuen Modus — oder behalten Sie Ihre Anpassungen bei und aktualisieren Sie nur die Modusbezeichnung.",overwriteAndSwitch:"Überschreiben und wechseln",keepCustomizations:"Anpassungen beibehalten"},nC={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},oC={cancel:"Abbrechen",close:"Schließen",copy:"Kopieren",delete:"Löschen",dismiss:"Schließen",save:"Speichern",optional:"optional",retry:"Erneut versuchen",loading:"Wird geladen…"},iC={common:{learnMore:"Dokumentation"}},rC={notSupportedByDaemon:"Vom Daemon noch nicht unterstützt",discoveryUnsupportedFormat:"Die Modellerkennung wird für dieses Anbieterformat noch nicht unterstützt. Fügen Sie Modelle manuell hinzu."},sC={subtitle:"Systemsteuerung",providers:"Anbieter",apiService:"API-Dienst",accounts:"Konten",codeCli:"Code CLI",settings:"Einstellungen",usageStats:"Nutzung",pricing:"Preise"},lC={title:"API-Dienst",description:"Konfigurieren Sie den ausgehenden API-Server, das endpunktbasierte Modell-Routing und benannte Zugriffsschlüssel.",loading:"Serverkonfiguration wird geladen…",loadError:"Die Serverkonfiguration konnte nicht geladen werden. Stellen Sie sicher, dass der Daemon erreichbar ist.",enable:{label:"Ausgehenden Server aktivieren",description:"Starten Sie den lokalen API-Server, der externe Aufrufer durch Ihre Anbieter leitet."},networkBinding:{label:"LAN-Zugriff erlauben",description:"Server an die Netzwerkschnittstelle binden statt nur an Loopback.",warning:"LAN-Zugriff macht den API-Server für andere Geräte in Ihrem Netzwerk zugänglich. In Kombination mit Abonnement-Routing können Anfragen Ihr Abonnementkontingent verbrauchen — lassen Sie dies deaktiviert, es sei denn, Sie vertrauen dem Netzwerk."},status:{running:"Server läuft",stopped:"Server gestoppt",runningHint:"Der ausgehende API-Server nimmt Anfragen entgegen.",stoppedHint:"Aktivieren Sie den Server, um Anfragen entgegennehmen zu können.",port:"Port {{port}}",loopback:"Loopback-URLs",lan:"LAN-URLs"},endpoints:{title:"Endpunkt-Routing",description:"Wählen Sie das Modell, zu dem jedes Wire-Format geroutet wird. Das Standardmodell wird hier festgelegt — der Server ist ein Router, keine Chat-App."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Standardmodell",backgroundModel:"Hintergrundmodell",visionModel:"Vision-Modell",noVisionModel:"Keines",backgroundModelIds:"Hintergrundmodell-IDs",backgroundModelIdsPlaceholder:"Kommagetrennte Modell-IDs",modelPlaceholder:"Modell auswählen…",useSubscription:"Abonnement verwenden",subscriptionUnsupported:"Abonnement-Routing ist für diesen Endpunkt nicht verfügbar."},keys:{title:"Zugriffsschlüssel",description:"Benannte Schlüssel, die externe Aufrufer als Bearer-Token senden. Der vollständige Schlüssel wird nur einmal bei der Erstellung angezeigt.",namePlaceholder:"Schlüsselname (z. B. mein-cli)",create:"Schlüssel erstellen",empty:"Noch keine Zugriffsschlüssel vorhanden.",enabled:"Aktiviert",disabled:"Deaktiviert",revoked:"Widerrufen",toggle:"Schlüssel umschalten",revoke:"Widerrufen",revokeConfirmTitle:"Diesen Schlüssel widerrufen?",revokeConfirmDesc:'Das Widerrufen von "{{name}}" verhindert sofort die Authentifizierung damit. Dies kann nicht rückgängig gemacht werden.',created:{title:"Schlüssel erstellt",warning:"Kopieren Sie diesen Schlüssel jetzt — er wird nicht erneut angezeigt. Bewahren Sie ihn sicher auf.",copy:"Kopieren",copied:"Kopiert",dismiss:"Fertig"}}},dC={title:"Konten & Abonnements",description:"Verwalten Sie die Abonnement-Anmeldeinformationen, durch die der Server leitet. Tokens werden hier geschrieben, aber nie angezeigt.",loading:"Konten werden geladen…",empty:"Keine Abonnement-Anbieter verfügbar.",signIn:"Anmelden",oauth:{title:"Bei {{name}} anmelden",description:"Öffnen Sie die Anmeldeseite in Ihrem Browser, autorisieren Sie, und fügen Sie dann den Autorisierungscode unten ein. Der Code wird nur an den Daemon übermittelt — das erstellte Token wird nie angezeigt.",openPage:"Anmeldeseite öffnen",codeLabel:"Autorisierungscode",codePlaceholder:"Code hier einfügen",submit:"Anmeldung abschließen"},codexOauth:{title:"Bei {{name}} anmelden",description:"Öffnen Sie die Anmeldeseite in Ihrem Browser und autorisieren Sie. Der Daemon erfasst das Ergebnis automatisch — lassen Sie dieses Fenster geöffnet, bis der Vorgang abgeschlossen ist. Das Token wird nie angezeigt.",waiting:"Warten auf den Abschluss der Anmeldung im Browser…",failed:"Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut."},clearProvider:"Alle löschen",clearConfirmTitle:"{{name}}-Konten löschen?",clearConfirmDesc:"Dadurch werden alle gespeicherten Anmeldeinformationen für diesen Anbieter entfernt. Dies kann nicht rückgängig gemacht werden.",credential:{ok:"Konfiguriert",notConfigured:"Nicht konfiguriert"},kind:{"pass-through":"Pass-through-Anmeldeinformationen","oauth-bearer":"OAuth Bearer","static-bearer":"Statischer Bearer-Schlüssel"},reason:{"missing-credential":"Keine Anmeldeinformationen gespeichert.",expired:"Anmeldeinformationen abgelaufen.","reauth-required":"Erneute Authentifizierung erforderlich.","refresh-failed":"Token-Aktualisierung fehlgeschlagen.","not-refreshable":"Anmeldeinformationen können nicht aktualisiert werden.",unknown:"Status unbekannt."},status:{unconfigured:"Nicht konfiguriert",authorized:"Autorisiert",configured:"Konfiguriert",expired:"Abgelaufen",error:"Fehler"},authMethod:{oauth:"OAuth",setup_token:"Setup-Token",manual:"Manuell"},list:{empty:"Keine Konten für diesen Anbieter gespeichert.",active:"Aktiv",expiresAt:"Läuft ab am {{value}}",setActive:"Als aktiv festlegen",remove:"Entfernen",removeConfirmTitle:"Dieses Konto entfernen?",removeConfirmDesc:'Das Entfernen von "{{name}}" löscht die gespeicherten Anmeldeinformationen. Dies kann nicht rückgängig gemacht werden.',title:"Konten"},write:{trigger:"Anmeldeinformation hinzufügen",title:"{{name}}-Anmeldeinformation schreiben",description:"Fügen Sie ein bereits erhaltenes Token ein. Die Felder sind auf das beschränkt, was dieser Anbieter akzeptiert; das Token wird gespeichert, nie zurück angezeigt.",authMethod:"Authentifizierungsmethode",status:"Status",subscriptionLevel:"Abonnementstufe",subscriptionLevelNone:"Nicht festgelegt",submit:"Anmeldeinformation speichern"},field:{accessToken:"Zugriffstoken",refreshToken:"Aktualisierungstoken",idToken:"ID-Token",apiKey:"API-Key",expiresAt:"Läuft ab am (ISO)",setupTokenExpiresAt:"Setup-Token läuft ab am (ISO)",accountId:"Konto-ID",email:"E-Mail",organizationId:"Organisations-ID",baseUrl:"Basis-URL",zenBaseUrl:"Zen-Basis-URL"},provider:{claude:{title:"Claude",description:"Anthropic-Abonnement-Anmeldeinformationen, die vom Daemon geleitet werden."},codex:{title:"Codex",description:"OpenAI Codex Abonnement-Anmeldeinformationen, die vom Daemon geleitet werden."},gemini:{title:"Gemini",description:"Google Gemini Abonnement-Anmeldeinformationen, die vom Daemon geleitet werden."},opencodego:{title:"OpenCodeGo",description:"Statische API-Key-Anmeldeinformationen, die vom Daemon geleitet werden."}},authMethodLabel:"Autorisierungsmethode",authMethodDesc:{oauth:"Melden Sie sich über Ihren Browser an; der Daemon erfasst und speichert das Token.",manual:"Fügen Sie ein bereits erhaltenes Token ein. Es wird gespeichert, nie zurück angezeigt."},actions:{authorize:"Autorisieren",enterToken:"Token eingeben",refresh:"Aktualisieren"},accounts:{addAccount:"Konto hinzufügen"},detail:{authMethod:"Autorisierungsmethode",subscriptionLevel:"Abonnementstufe",expiresAt:"Läuft ab",lastRefreshed:"Zuletzt aktualisiert",label:"Kontobezeichnung",labelPlaceholder:"Diesem Konto einen Namen geben",saveLabel:"Bezeichnung speichern"},oauthFlow:{step1:{title:"Autorisierungsseite öffnen",desc:"Öffnen Sie die Anmeldeseite in Ihrem Browser."},step2:{title:"Zugriff autorisieren",desc:"Melden Sie sich an und genehmigen Sie den Zugriff für den Anbieter."},step3:{title:"Autorisierungscode kopieren",desc:"Die Seite zeigt nach der Genehmigung einen Autorisierungscode an."},step4:{title:"Code einfügen",desc:"Fügen Sie den Autorisierungscode unten ein, um den Vorgang abzuschließen. Der Code wird nur an den Daemon übermittelt — das erstellte Token wird nie angezeigt."},authorize:"Anmeldung abschließen",showUrl:"Autorisierungs-URL anzeigen"},manual:{title:"Anmeldeinformation einfügen",description:"Fügen Sie ein bereits erhaltenes Token ein. Die Felder sind auf das beschränkt, was dieser Anbieter akzeptiert; das Token wird gespeichert, nie zurück angezeigt.",accessTokenPlaceholder:"Zugriffstoken einfügen",refreshTokenPlaceholder:"Aktualisierungstoken einfügen (optional)",hint:"Das Token wird an den Daemon gesendet und verschlüsselt gespeichert. Es wird nie zurück angezeigt."},openCodeGo:{apiKeyRequired:"Ein API-Key ist erforderlich.",apiKeyPlaceholder:"API-Key einfügen",baseUrlPlaceholder:"https://… (optional)",zenBaseUrlPlaceholder:"https://… (optional)"},info:{title:"Über Abonnementkonten",description:"Tokens werden in den Daemon geschrieben und zur Authentifizierung von Upstream-Anfragen verwendet. Sie werden verschlüsselt gespeichert und nie zurück angezeigt. Das Entfernen eines Kontos löscht die gespeicherten Anmeldeinformationen."},rename:{failed:"Konto konnte nicht umbenannt werden."},refresh:{failed:"Token konnte nicht aktualisiert werden."},errors:{requestFailed:"Anfrage fehlgeschlagen. Bitte versuchen Sie es erneut."},syncWarning:{"external-divergent":"Die externe CLI-Anmeldedatei enthält neuere Zugangsdaten als dieses Konto. Das gespeicherte Token kann sich möglicherweise nicht mehr aktualisieren — jetzt aktualisieren oder neu anmelden.","external-not-rotated":"Aktualisierung fehlgeschlagen, und die externe CLI enthält dieselben abgelaufenen Zugangsdaten. Bitte erneut anmelden.","duplicate-token":"Ein anderes Konto verwendet dieselben Zugangsdaten. Das Aktualisieren eines Kontos meldet das andere ab."},importExternal:{detected:"Auf diesem Rechner wurde eine vorhandene {{name}}-CLI-Anmeldung gefunden.",hint:"Nach dem Import hält diese App sie aktuell: Bei jeder Token-Aktualisierung wird auch die CLI-Anmeldedatei aktualisiert, sodass die CLI im Terminal angemeldet bleibt.",button:"Vorhandene CLI-Anmeldung importieren"}},cC={title:"Code CLI",description:"Richten Sie eine Coding-CLI auf den ausgehenden Proxy des Daemons. Diese Seite ist schreibgeschützt — hier ist nichts zu konfigurieren.",copy:"Kopieren",copied:"Kopiert",baseUrl:{title:"Daemon-Basis-URL",description:"Die Proxy-Adresse, mit der sich Ihr CLI verbindet.",label:"Basis-URL"},token:{title:"Authentifizierung",hint:"Senden Sie 'Authorization: Bearer <Ihr-Admin-Token>' für Admin-Routen. Das Admin-Token wird im Daemon konfiguriert (in der Konfigurationsdatei oder Umgebung) — es wird hier nie angezeigt."},examples:{title:"Beispiel-Startumgebung",keyNote:"Verwenden Sie einen ausgehenden Zugriffsschlüssel, der auf der Seite API-Dienst erstellt wurde — nicht das Admin-Token.",anthropic:"CLI im Anthropic-Format",openai:"CLI im OpenAI-Format"},launchDescription:"Starten Sie eine Coding-CLI in einem Terminal, das auf diesen Daemon zeigt. Der Daemon injiziert die Umleitungsumgebung und startet die CLI für Sie.",refresh:"Aktualisieren",loading:"CLIs werden erkannt…",cli:{installed:"Installiert",notFound:"Nicht gefunden",notFoundHint:"Diese CLI ist nicht im PATH des Daemon-Hosts. Installieren Sie sie und aktualisieren Sie dann.",install:"Installieren",installing:"Wird installiert…",installingHint:"Installation auf dem Daemon-Host — das kann eine Minute dauern.",launch:"Starten",launchTitle:"{{name}} starten",launchDescription:"Öffnet ein neues Terminal auf dem Daemon-Host, das diese CLI ausführt und über den Daemon-Proxy geleitet wird. Wählen Sie ein optionales Arbeitsverzeichnis.",cwdLabel:"Arbeitsverzeichnis",cwdPlaceholder:"/Pfad/zu/Ihrem/Projekt",runningVia:"Läuft · {{provider}} / {{model}}",stop:"Beenden"},manual:{title:"Manuelle Einrichtung",description:"Bevorzugen Sie es, die CLI selbst auszuführen? Richten Sie sie mit diesen Umgebungsvariablen auf den Daemon.",show:"Anzeigen",hide:"Ausblenden"}},uC={probing:"Daemon wird gesucht…",spawning:"Daemon wird gestartet…",failed:"Der Daemon konnte nicht gestartet werden",failedHint:"Stellen Sie sicher, dass Node.js installiert ist und der Daemon erstellt wurde (dist vorhanden), oder setzen Sie OMNICROSS_DAEMON_ENTRY auf die cli.js des Daemons."},pC={title:"Einstellungen",description:"Desktop-App-Einstellungen.",desktopOnly:"Start- und Infobereichsoptionen gelten nur in der Desktop-App.",startup:{title:"Autostart",autoLaunch:"Bei Anmeldung starten",autoLaunchHint:"Omnicross automatisch starten, wenn Sie sich anmelden.",startMinimized:"Minimiert im Infobereich starten",startMinimizedHint:"Im Hintergrund starten, ohne das Fenster zu öffnen."},tray:{title:"Infobereich",minimizeOnClose:"Beim Schließen in den Infobereich minimieren",minimizeOnCloseHint:"Das Schließen des Fensters blendet es in den Infobereich ein, anstatt die App zu beenden."},language:{title:"Sprache",label:"Oberflächensprache"}},mC={title:"Nutzungsstatistik",description:"Token- und Kostenstatistik der vom Daemon bedienten Anfragen.",rangeToday:"Heute",range7d:"Letzte 7 Tage",range30d:"Letzte 30 Tage",rangeCustom:"Benutzerdefiniert",from:"Von",to:"Bis",totalCost:"Gesamtkosten",cacheSavings:"Cache-Ersparnis",events:"Anfragen",inputTokens:"Eingabe-Token",outputTokens:"Ausgabe-Token",cacheReadTokens:"Cache-Lesen",cacheWriteTokens:"Cache-Schreiben",reasoningTokens:"Reasoning-Token",byModel:"Nach Modell",byApiKey:"Nach API-Schlüssel",provider:"Anbieter",model:"Modell",cost:"Kosten",apiKey:"API-Schlüssel",unpriced:"Ohne Preis",unpricedHint:"Für dieses Modell existiert kein Preiseintrag — auf der Preise-Seite hinzufügen.",unattributed:"Nicht zugeordnet",unattributedHint:"Anfragen ohne Zuordnung zu einem bestimmten API-Schlüssel. Bis die Zuordnung pro Schlüssel erfasst wird, ist das normal.",empty:"Keine Anfragen in diesem Zeitraum.",invalidRange:"Bitte einen gültigen Datumsbereich wählen."},gC={title:"Modellpreise",description:"Token-Preise pro Modell zur Kostenberechnung, in USD pro 1 Mio. Token.",search:"Anbieter oder Modell suchen…",fetchLatest:"Neueste abrufen",fetching:"Wird abgerufen…",addEntry:"Eintrag hinzufügen",provider:"Anbieter",model:"Modell",inputPrice:"Eingabe",outputPrice:"Ausgabe",cacheReadPrice:"Cache-Lesen",cacheWritePrice:"Cache-Schreiben",source:"Quelle",updated:"Aktualisiert",userEdited:"bearbeitet",edit:"Bearbeiten",deleteTitle:"Preiseintrag löschen?",empty:"Die Preistabelle ist leer.",emptyHint:"Neueste Preise abrufen, um sie zu füllen.",noMatches:"Keine Einträge entsprechen der Suche.",saved:"Preiseintrag gespeichert.",saveFailed:"Speichern fehlgeschlagen: {{message}}",deleteFailed:"Löschen fehlgeschlagen: {{message}}",alreadyDeleted:"Der Eintrag war bereits entfernt.",fetchApplied:"{{count}} Einträge aus der Quelle aktualisiert.",fetchFailed:"Abruf fehlgeschlagen: {{message}}",requiredId:"Erforderlich",invalidPrice:"Bitte eine nicht negative Zahl eingeben",conflictTitle:"Preiskonflikte lösen",conflictHint:"Diese Einträge wurden von Ihnen bearbeitet und haben sich zugleich in der Quelle geändert. Wählen Sie pro Zeile, ob Ihr Wert erhalten bleibt (Überspringen) oder der neue übernommen wird (Überschreiben).",current:"Aktuell",incoming:"Eingehend",overwrite:"Überschreiben",skip:"Überspringen",overwriteAll:"Alle überschreiben",skipAll:"Alle überspringen",applyResolutions:"Anwenden",resolved:"{{overwritten}} überschrieben, {{skipped}} übersprungen.",resolvedWithStale:"{{overwritten}} überschrieben, {{skipped}} übersprungen. {{stale}} wurden zwischenzeitlich geändert und blieben unberührt.",refreshFailed:"Die Änderung wurde übernommen, aber das Neuladen der Liste ist fehlgeschlagen: {{message}}",sourceBuiltin:"Integriert",sourceLitellm:"LiteLLM",sourceUser:"Benutzer"},hC={providerSettings:tC,apiMode:aC,presetName:nC,common:oC,mediaSettings:iC,appLocal:rC,nav:sC,apiService:lC,accounts:dC,codeCli:cC,daemonStatus:uC,settings:pC,usageStats:mC,pricing:gC},fC={loading:"Φόρτωση ρυθμίσεων LLM...",reset:{button:"Επαναφορά προεπιλογών",confirmTitle:"Επαναφορά προεπιλεγμένων ρυθμίσεων;",confirmBody:"Αυτό διαγράφει τις προσαρμογές σας για αυτόν τον provider και επαναφέρει τις ενσωματωμένες προεπιλογές. Το API key και οι αποθηκευμένες συνεδρίες διατηρούνται.",confirmButton:"Επαναφορά προεπιλογών"},reentryBanner:{message:"{{count}} ενεργός/ενεργοί provider(s) χρειάζονται εκ νέου εισαγωγή του API key τους. Ανοίξτε καθέναν και προσθέστε ξανά το key."},migrationPack:{barHint:"Μεταφέρετε τα keys provider και τα subscription tokens σε άλλο υπολογιστή με ένα κρυπτογραφημένο πακέτο.",passphrase:"Φράση πρόσβασης",passphrasePlaceholder:"Εισάγετε φράση πρόσβασης",passphraseHint:"Χρησιμοποιήστε τουλάχιστον 8 χαρακτήρες· συνιστώνται 12 ή περισσότεροι.",confirm:"Επιβεβαίωση φράσης πρόσβασης",confirmPlaceholder:"Εισάγετε ξανά τη φράση πρόσβασης",mismatch:"Οι φράσεις πρόσβασης δεν ταιριάζουν.",strength:{weak:"Πολύ σύντομη — χρησιμοποιήστε τουλάχιστον 8 χαρακτήρες.",fair:"Εντάξει — 12 ή περισσότεροι χαρακτήρες είναι πιο ασφαλείς.",strong:"Ισχυρή φράση πρόσβασης."},export:{button:"Εξαγωγή πακέτου",title:"Εξαγωγή κρυπτογραφημένου πακέτου",subtitle:"Κρυπτογραφήστε τα keys provider και τα subscription tokens σε φορητό αρχείο.",warning:"Αυτό το αρχείο περιέχει αποκρυπτογραφήσιμα μυστικά. Φυλάξτε το με ασφάλεια — όποιος έχει το αρχείο και τη φράση πρόσβασης μπορεί να διαβάσει τα keys σας. Η απώλεια της φράσης πρόσβασης δεν μπορεί να ανακτηθεί.",submit:"Εξαγωγή",success:"Το πακέτο εξήχθη επιτυχώς.",error:"Η εξαγωγή απέτυχε. Δοκιμάστε ξανά."},import:{button:"Εισαγωγή πακέτου",title:"Εισαγωγή κρυπτογραφημένου πακέτου",subtitle:"Επαναφέρετε keys provider και subscription tokens από εξαγόμενο πακέτο.",hint:"Εισάγετε τη φράση πρόσβασης που χρησιμοποιήθηκε κατά την εξαγωγή και επιλέξτε το αρχείο.",submit:"Εισαγωγή",successTitle:"Η εισαγωγή ολοκληρώθηκε",summary:"Εισήχθησαν {{providerKeys}} provider key(s), {{poolKeys}} pool key(s) και {{tokenSets}} token set(s).",duplicates:"Παραλείφθηκαν {{count}} pool key(s) που υπήρχαν ήδη.",skipped:"Παραλείφθηκαν (δεν βρέθηκε αντίστοιχος provider): {{names}}",error:"Λανθασμένη φράση πρόσβασης ή κατεστραμμένο πακέτο. Δεν έγινε καμία αλλαγή."}},searchPlaceholder:"Αναζήτηση providers...",emptySearch:"Κανένας provider δεν ταιριάζει με την αναζήτησή σας.",emptyList:"Δεν έχουν ρυθμιστεί providers.",selectPrompt:"Επιλέξτε έναν provider για προβολή λεπτομερειών",listStatus:"{{count}} μοντέλο/α",noModels:"Δεν έχουν ρυθμιστεί μοντέλα",enabled:"Ενεργός",disabled:"Ανενεργός",showEnabledOnly:"Εμφάνιση μόνο ενεργών",showAll:"Εμφάνιση όλων των providers",dragHandle:"Σύρετε για αναδιάταξη",reorderFailed:"Αποτυχία αποθήκευσης σειράς providers",credentials:{apiKey:"API Key",apiBaseUrl:"Βασικό API URL"},filter:{all:"Όλα",chat:"Chat",code:"Κώδικας"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Επιλέξτε πρότυπο",skipTemplates:"Παράλειψη, χειροκίνητη ρύθμιση",name:"Όνομα *",providerType:"Τύπος",apiType:"Τύπος API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Τυπική μορφή API chat/completions OpenAI",claudecode:"Μορφή Anthropic Messages API (Claude Code)"},chatApiFormat:"Μορφή API",chatApiFormatDescription:"Επιλέξτε τη μορφή API που αντιστοιχεί στο endpoint του provider σας",apiKey:"API Key",apiKeyPlaceholder:"sk-... ή $ENV_VAR",apiKeyHelper:"Χρησιμοποιήστε $VAR_NAME για αναφορά σε μεταβλητές περιβάλλοντος",apiKeySetPlaceholder:"Το key έχει οριστεί — αφήστε κενό για να το διατηρήσετε",apiKeyReplaceHelper:"Ένα key είναι αποθηκευμένο με ασφάλεια. Πληκτρολογήστε νέα τιμή για αντικατάσταση, ή αφήστε κενό για να το διατηρήσετε.",testApiKey:"Δοκιμή API Key",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Προεπισκόπηση:",models:"Μοντέλα",modelPlaceholder:"Όνομα μοντέλου (π.χ. gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API Transformers",transformerConfigDescription:"Ρυθμίστε transformers για προσαρμογή μορφών αίτησης/απόκρισης API για αυτόν τον provider",transformerConfigNote:"Το daemon εφαρμόζει αυτούς τους transformers στην αλυσίδα αίτησης, μετά τον transformer μορφής του provider (που χειρίζεται τη μετατροπή wire-format). Άγνωστα ονόματα transformer παραλείπονται.",enabled:"Ενεργός",apiVersion:"Έκδοση API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Έκδοση Azure OpenAI API (π.χ. 2024-08-01-preview)",official:"Επίσημο Anthropic API",officialHelper:"Ενεργοποιήστε αν αυτός ο provider συνδέεται απευθείας στο επίσημο Anthropic API. Απενεργοποιήστε για reverse proxies ή υπηρεσίες τρίτων.",maxConcurrency:"Μέγιστες Ταυτόχρονες Αιτήσεις",maxConcurrencyHelper:"Μέγιστος αριθμός ταυτόχρονων αιτήσεων API προς αυτόν τον provider. Χαμηλότερες τιμές βοηθούν στην αποφυγή rate limiting (σφάλματα 429). Ορίστε `-1` για χωρίς όριο.",codingPlan:{label:"Coding Plan",description:"Χρήση ξεχωριστού API endpoint για subscription-based coding plans",baseUrl:"Βασικό URL Coding Plan",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"API Key Coding Plan (προαιρετικό)",apiKeyPlaceholder:"Αφήστε κενό για χρήση του API key του provider",apiKeyHelper:"Απαιτείται μόνο αν το coding plan χρησιμοποιεί διαφορετικό API key",tokenPlanHint:"Ορισμένοι providers (π.χ. Xiaomi MiMo) εκδίδουν Token Plan keys με πρόθεμα `tp-` — μόνο για πληροφόρηση, δεν επιβάλλεται."},selectTypeFirst:"Επιλογή τύπου provider",selectTypeFirstDesc:"Επιλέξτε τον τύπο provider που θέλετε να προσθέσετε",codeProviderNote:"Οι code providers χρειάζονται μόνο API Key και URL. Τα μοντέλα διαχειρίζονται από τον Agent Router.",buttons:{cancel:"Ακύρωση",submitAdd:"Προσθήκη Provider",submitUpdate:"Ενημέρωση Provider",continue:"Συνέχεια",back:"Πίσω"}},details:{noSelection:"Επιλέξτε έναν provider για προβολή λεπτομερειών",apiKey:"API Key",apiUrl:"API URL",nameLabel:"Όνομα Provider",modelsEndpoint:"Endpoint Μοντέλων",modelsEndpointHelper:"Αντικαταστήστε το endpoint ανακάλυψης αν ο provider εκθέτει προσαρμοσμένο μονοπάτι /models.",models:"Μοντέλα",transformers:"Transformers",codeProviderNote:"Οι code providers (όπως το Claude Code) δεν απαιτούν ρύθμιση μοντέλων. Τα μοντέλα διαχειρίζονται αυτόματα από τον Agent Router.",buttons:{more:"Περισσότερες Ρυθμίσεις",delete:"Διαγραφή"}},providerModelSelector:{placeholder:"Επιλέξτε provider και μοντέλο",noProviders:"Δεν υπάρχουν διαθέσιμοι providers",noModels:"Δεν έχουν ρυθμιστεί μοντέλα"},apiKeyPool:{title:"Δεξαμενή API Key",description:"Ρυθμίστε πολλαπλά API keys για εξισορρόπηση φορτίου. Κάθε συνεδρία χρησιμοποιεί ένα key για διατήρηση της prompt cache.",defaultLabel:"Προεπιλογή",weight:"Βάρος",noKey:"Χωρίς key",labelPlaceholder:"Ετικέτα (π.χ. Key #1, Παραγωγή)",addKey:"Προσθήκη API Key",add:"Προσθήκη",empty:"Δεν έχουν ρυθμιστεί πρόσθετα keys.",statusCoolingDown:"Ανάκαμψη {{time}}",statusAuthFailed:"Αποτυχία ελέγχου ταυτότητας · ανενεργό",statusDisabled:"Ανενεργό",statusHealthy:"Λειτουργικό",agoSeconds:"πριν {{count}}δ",agoMinutes:"πριν {{count}}λ",agoHours:"πριν {{count}}ω",agoDays:"πριν {{count}}η"},modelsManager:{searchPlaceholder:"Αναζήτηση μοντέλων...",defaultGroup:"Όλα τα Μοντέλα",add:"Προσθήκη Μοντέλου",manage:"Διαχείριση",empty:"Δεν υπάρχουν μοντέλα σε αυτή την ομάδα",enabled:"Ενεργό",disabled:"Ανενεργό",filters:{all:"Όλα",vision:"Vision",reasoning:"Reasoning",free:"Δωρεάν",tools:"Εργαλεία"},manualDialog:{title:"Προσθήκη Μοντέλου",subtitle:"Προσθέστε προσαρμοσμένο μοντέλο σε αυτόν τον provider",modelId:"ID Μοντέλου",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash κ.λπ.",modelIdHelper:"Το ακριβές αναγνωριστικό μοντέλου που χρησιμοποιείται κατά την κλήση του API",modelName:"Εμφανιζόμενο Όνομα",modelNamePlaceholder:"Φιλικό εμφανιζόμενο όνομα (προαιρετικό)",modelNameHelper:"Προαιρετικό όνομα που εμφανίζεται στο UI. Αν είναι κενό, θα χρησιμοποιηθεί το ID Μοντέλου",group:"Ομάδα",groupPlaceholder:"Επιλέξτε ή εισάγετε όνομα ομάδας",submit:"Προσθήκη",cancel:"Ακύρωση",helper:"Δώστε το ακριβές αναγνωριστικό μοντέλου που εκθέτει το API του provider."},editDialog:{title:"Επεξεργασία Μοντέλου",subtitle:"Τροποποίηση ρυθμίσεων μοντέλου",modelId:"ID Μοντέλου",modelIdPlaceholder:"Αναγνωριστικό μοντέλου",modelIdHelper:"Το αναγνωριστικό μοντέλου που χρησιμοποιείται κατά την κλήση του API",modelName:"Εμφανιζόμενο Όνομα",modelNamePlaceholder:"Φιλικό εμφανιζόμενο όνομα",modelNameHelper:"Όνομα που εμφανίζεται στο UI",group:"Ομάδα",groupPlaceholder:"Επιλέξτε ή εισάγετε όνομα ομάδας",submit:"Αποθήκευση",cancel:"Ακύρωση",vision:"Δυνατότητα Vision",visionHint:"Αν αυτό το μοντέλο υποστηρίζει εισαγωγή εικόνας/vision",reasoning:"Μοντέλο Σκέψης",reasoningHint:"Αν αυτό το μοντέλο υποστηρίζει λειτουργία thinking/reasoning"},manageDialog:{title:"Διαχείριση Μοντέλων",cachedAt:"Αποθηκεύτηκε στην κρυφή μνήμη στις {{date}} ({{source}})",refresh:"Ανανέωση",close:"Κλείσιμο",raw:"Raw JSON",empty:"Δεν υπάρχουν διαθέσιμα απομακρυσμένα μοντέλα.",error:"Αποτυχία φόρτωσης μοντέλων: {{message}}",addFromCatalog:"Προσθήκη",sourceCache:"κρυφή μνήμη",sourceNetwork:"ζωντανό",contextLength:"Πλαίσιο {{value}} tokens",maxTokens:"Μέγιστο {{value}} tokens"},messages:{added:"Το μοντέλο προστέθηκε.",updated:"Το μοντέλο ενημερώθηκε.",removed:"Το μοντέλο αφαιρέθηκε.",duplicate:"Το μοντέλο υπάρχει ήδη.",refreshed:"Τα μοντέλα ανανεώθηκαν",refreshFailed:"Αποτυχία ανανέωσης μοντέλων"},testDialog:{title:"Δοκιμή Συνδεσιμότητας Μοντέλου",provider:"Provider",model:"Μοντέλο",testing:"Δοκιμή...",success:"Η Δοκιμή Πέτυχε",successMessage:"Το μοντέλο είναι προσβάσιμο κανονικά",failure:"Η Δοκιμή Απέτυχε",aiResponse:"Απόκριση AI",charCount:"{{count}} χαρακτήρες",duration:"Διάρκεια {{time}}δλ",close:"Κλείσιμο",retest:"Επανάληψη δοκιμής",testButton:"Δοκιμή μοντέλου",unsupportedFormat:"Η δοκιμή δεν υποστηρίζεται ακόμα για αυτή τη μορφή provider."}},router:{title:"Ρύθμιση Router",description:"Ρυθμίστε ποιον provider/μοντέλο να χρησιμοποιείτε για διαφορετικά σενάρια.",labels:{default:"Προεπιλογή",background:"παρασκήνιο",think:"σκέψη",longContext:"Μεγάλο Πλαίσιο",webSearch:"Αναζήτηση Ιστού",image:"Εικόνα",longContextThreshold:"Όριο Μεγάλου Πλαισίου"},helper:{longContextThreshold:"Αριθμός tokens πριν την εναλλαγή στο μοντέλο μεγάλου πλαισίου."},placeholder:{required:"Απαιτείται",optional:"Προαιρετικό"}},agentRouter:{title:"Agent Router",description:"Ρυθμίστε αμφίδρομη δρομολόγηση μεταξύ λειτουργιών Chat και Κώδικα.",searchPlaceholder:"Αναζήτηση routers...",noSearchResults:"Κανένας router δεν ταιριάζει με την αναζήτησή σας.",tabs:{chatToCode:"Chat → Κώδικας",codeToChatPlaceholder:"Κώδικας → Chat"},chatToCode:{title:"Router Chat προς Κώδικα",description:"Χρήση chat providers σε λειτουργία agent/κωδικοποίησης",addRouter:"Προσθήκη Router",emptyState:"Δεν έχουν ρυθμιστεί routers Chat→Κώδικα. Προσθέστε έναν για χρήση chat providers σε λειτουργία κωδικοποίησης.",form:{name:"Όνομα Router",namePlaceholder:"Ο Router Chat→Κώδικα μου",chatProvider:"Chat Provider",chatProviderPlaceholder:"Επιλέξτε chat provider",mode:"Λειτουργία",modeSimple:"Απλή",modeAdvanced:"Προχωρημένη",modeSimpleDesc:"Άμεση διαβίβαση στον chat provider",modeAdvancedDesc:"Ρύθμιση αντιστοίχισης μοντέλων και διαχείρισης πλαισίου",enabled:"Ενεργός",save:"Αποθήκευση Router",cancel:"Ακύρωση"},list:{provider:"Provider",mode:"Λειτουργία",status:"Κατάσταση"},mappings:{title:"Αντιστοιχίσεις Μοντέλων",description:"Αντιστοιχίστε μοντέλα chat provider σε μοντέλα code provider",count:"αντιστοίχιση/εις",empty:"Δεν έχουν ρυθμιστεί αντιστοιχίσεις μοντέλων. Προσθέστε αντιστοιχίσεις για δρομολόγηση chat μοντέλων σε code providers.",addNew:"Προσθήκη Νέας Αντιστοίχισης",selectSource:"Επιλογή μοντέλου πηγής (Chat)",selectTarget:"Επιλογή μοντέλου προορισμού (Κώδικας)",targetPlaceholder:"Εισάγετε όνομα μοντέλου Claude Code",notSet:"(Δεν έχει οριστεί - κάντε κλικ για επιλογή)",add:"Προσθήκη",edit:"Επεξεργασία",done:"Τέλος"},advanced:{title:"Προχωρημένη Ρύθμιση",description:"Ρυθμίστε μοντέλα για διαφορετικούς τύπους εργασιών",helpText:"Το προεπιλεγμένο μοντέλο είναι απαραίτητο. Τα υπόλοιπα μοντέλα είναι προαιρετικά και θα χρησιμοποιούν την προεπιλογή αν δεν οριστούν.",default:{label:"Προεπιλογή",placeholder:"Επιλέξτε προεπιλεγμένο μοντέλο",description:"Κύριο μοντέλο για γενικές εργασίες (παρόμοιο με Claude Sonnet)"},background:{label:"Παρασκήνιο",placeholder:"Επιλέξτε μοντέλο παρασκηνίου",description:"Ελαφρύ μοντέλο για εργασίες παρασκηνίου (παρόμοιο με Claude Haiku)"},think:{label:"Σκέψη",placeholder:"Επιλέξτε μοντέλο σκέψης",description:"Προχωρημένο μοντέλο για σύνθετη συλλογιστική (παρόμοιο με Claude Opus)"},image:{label:"Εικόνα",placeholder:"Επιλέξτε μοντέλο εικόνας",description:"Μοντέλο για εργασίες με εικόνες με δυνατότητα vision"}}},codeToChat:{title:"Router Κώδικα προς Chat",description:"Εκθέτει μοντέλα Coding Plan σε λειτουργία chat",addRouter:"Προσθήκη Router",emptyState:"Δεν έχουν ρυθμιστεί routers Κώδικας→Chat. Προσθέστε έναν για έκθεση μοντέλων Coding Plan σε λειτουργία chat.",form:{name:"Όνομα Router",namePlaceholder:"Ο Router Κώδικας→Chat μου",codeProvider:"Code Provider",codeProviderPlaceholder:"Επιλέξτε code provider",codeProviderHelper:"Επιλέξτε τον Code provider για χρήση στη μετατροπή",models:"Μοντέλα Coding Plan",modelsHelper:"Επιλέξτε ποια μοντέλα Coding Plan θα εκτεθούν",enabled:"Ενεργός",save:"Αποθήκευση Router",cancel:"Ακύρωση"},mappings:{title:"Αντιστοιχίσεις Μοντέλων",description:"Αντιστοιχίστε μοντέλα code provider σε μοντέλα chat provider για έκθεση",count:"αντιστοίχιση/εις",empty:"Δεν έχουν ρυθμιστεί αντιστοιχίσεις μοντέλων. Προσθέστε αντιστοιχίσεις για έκθεση μοντέλων Code σε λειτουργία chat.",addNew:"Προσθήκη Νέας Αντιστοίχισης",selectSource:"Επιλογή μοντέλου πηγής (Κώδικας)",selectTarget:"Επιλογή μοντέλου προορισμού (Chat)",sourcePlaceholder:"Εισάγετε όνομα μοντέλου πηγής",targetPlaceholder:"Εισάγετε όνομα μοντέλου προορισμού",add:"Προσθήκη",edit:"Επεξεργασία",done:"Τέλος"}},transformers:{title:"Transformers",description:"Ρυθμίστε transformers για μετατροπή αίτησης/απόκρισης",noProvider:"Επιλέξτε provider για ρύθμιση transformers",empty:"Δεν υπάρχουν transformers",count:"{{count}} transformer(s)"},status:{enabled:"Ενεργός",disabled:"Ανενεργός"},messages:{routerAdded:"Ο router προστέθηκε επιτυχώς",routerUpdated:"Ο router ενημερώθηκε επιτυχώς",routerDeleted:"Ο router διαγράφηκε επιτυχώς",saveFailed:"Αποτυχία αποθήκευσης router"}},presets:{title:"Γρήγορη Προσθήκη Provider",added:"Προστέθηκε",add:"Προσθήκη",features:{search:"Αναζήτηση",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"Είστε σίγουροι ότι θέλετε να διαγράψετε αυτόν τον provider;"},errors:{nameRequired:"Απαιτείται όνομα provider",urlRequired:"Απαιτείται βασικό API URL",urlInvalid:"Εισάγετε έγκυρο URL (π.χ. https://api.example.com)",saveFailed:"Αποτυχία αποθήκευσης provider",deleteFailed:"Σφάλμα κατά τη διαγραφή provider. Δοκιμάστε ξανά.",toggleFailed:"Σφάλμα κατά την εναλλαγή provider. Δοκιμάστε ξανά."},openRouter:{title:"Δρομολόγηση Provider OpenRouter",description:"Ρυθμίστε τον τρόπο δρομολόγησης αιτήσεων σε διαφορετικούς providers στο OpenRouter.",sort:"Στρατηγική Δρομολόγησης",sortTooltip:"Επιλέξτε τον τρόπο ιεράρχησης providers. Το Auto χρησιμοποιεί ευφυή εξισορρόπηση φορτίου.",order:"Σειρά Προτεραιότητας Provider",orderTooltip:"Καθορίστε providers για δοκιμή με σειρά (π.χ. anthropic, openai, together). Πατήστε Enter για προσθήκη.",orderPlaceholder:"Πληκτρολογήστε slug provider και πατήστε Enter...",allowFallbacks:"Να επιτρέπονται τα Fallbacks",allowFallbacksTooltip:"Όταν είναι ενεργό, το OpenRouter θα δοκιμάζει εφεδρικούς providers αν ο κύριος δεν είναι διαθέσιμος.",requireParameters:"Να απαιτούνται Όλες οι Παράμετροι",requireParametersTooltip:"Δρομολόγηση μόνο σε providers που υποστηρίζουν όλες τις παραμέτρους της αίτησης.",dataCollection:"Πολιτική Συλλογής Δεδομένων",dataCollectionTooltip:"Ελέγξτε αν θα χρησιμοποιούνται providers που ενδέχεται να αποθηκεύουν ή να εκπαιδεύουν βάσει των δεδομένων σας.",zdr:"Μηδενική Διατήρηση Δεδομένων",zdrTooltip:"Δρομολόγηση μόνο σε endpoints με πολιτική Zero Data Retention.",only:"Να επιτρέπονται Μόνο οι Providers",onlyTooltip:"Χρήση μόνο αυτών των συγκεκριμένων providers. Αφήστε κενό για να επιτρέπονται όλοι.",onlyPlaceholder:"Πληκτρολογήστε slug provider και πατήστε Enter...",ignore:"Αγνόηση Providers",ignoreTooltip:"Παράλειψη αυτών των providers κατά τη δρομολόγηση αιτήσεων.",ignorePlaceholder:"Πληκτρολογήστε slug provider και πατήστε Enter...",quantizations:"Φίλτρο Quantization",quantizationsTooltip:"Χρήση μόνο providers με συγκεκριμένα επίπεδα quantization. Χαμηλότερη ακρίβεια μπορεί να μειώσει την ποιότητα αλλά να βελτιώσει την ταχύτητα.",maxPrice:"Μέγιστη Τιμή",maxPriceTooltip:"Ορίστε ανώτατα όρια τιμής ανά εκατομμύριο tokens. Αφήστε κενό για χωρίς όριο.",configured:"Ρυθμισμένο"}},vC={label:"Λειτουργία API",standard:"Τυπική",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Τα keys για αυτό το πλάνο συνήθως ξεκινούν με `{{prefix}}`. Μόνο για πληροφόρηση — δεν επιβάλλεται.",dashscopeCodingPlanSeparateKey:"Το DashScope Coding Plan χρησιμοποιεί ξεχωριστό API key από το τυπικό endpoint.",baiduCodingPlanSeparateKey:"Το Qianfan Coding Plan χρησιμοποιεί ξεχωριστό API key από το τυπικό endpoint.",tencentTokenPlanAnthropicOnly:"Το Tencent Token Plan είναι μόνο για πρωτόκολλο Anthropic.",xiaomiTokenPlanRegions:"Το προεπιλεγμένο baseUrl είναι `token-plan-cn.*`. Μπορείτε να το επεξεργαστείτε χειροκίνητα σε `token-plan-sgp.*` ή `token-plan-ams.*`.",confirmOverwriteTitle:"Εναλλαγή λειτουργίας API;",confirmOverwriteBody:"Έχετε προσαρμόσει το API URL ή το API Key. Η εναλλαγή λειτουργίας θα τα αντικαταστήσει με τις προεπιλογές της νέας λειτουργίας — ή μπορείτε να διατηρήσετε τις προσαρμογές σας και να ενημερωθεί μόνο η ετικέτα λειτουργίας.",overwriteAndSwitch:"Αντικατάσταση και εναλλαγή",keepCustomizations:"Διατήρηση προσαρμογών"},kC={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},yC={cancel:"Ακύρωση",close:"Κλείσιμο",copy:"Αντιγραφή",delete:"Διαγραφή",dismiss:"Απόρριψη",save:"Αποθήκευση",optional:"προαιρετικό",retry:"Επανάληψη",loading:"Φόρτωση…"},bC={common:{learnMore:"Τεκμηρίωση"}},PC={notSupportedByDaemon:"Δεν υποστηρίζεται ακόμα από το daemon",discoveryUnsupportedFormat:"Η ανακάλυψη μοντέλων δεν υποστηρίζεται ακόμα για αυτή τη μορφή provider. Προσθέστε μοντέλα χειροκίνητα."},AC={subtitle:"Πίνακας Ελέγχου",providers:"Providers",apiService:"Υπηρεσία API",accounts:"Λογαριασμοί",codeCli:"Code CLI",settings:"Ρυθμίσεις",usageStats:"Χρήση",pricing:"Τιμές"},CC={title:"Υπηρεσία API",description:"Ρυθμίστε τον εξερχόμενο διακομιστή API, τη δρομολόγηση μοντέλων ανά endpoint και τα ονομαστικά access keys.",loading:"Φόρτωση ρύθμισης διακομιστή…",loadError:"Αδυναμία φόρτωσης ρύθμισης διακομιστή. Βεβαιωθείτε ότι το daemon είναι προσβάσιμο.",enable:{label:"Ενεργοποίηση εξερχόμενου διακομιστή",description:"Εκκινήστε τον τοπικό διακομιστή API που δρομολογεί εξωτερικές κλήσεις μέσω των providers σας."},networkBinding:{label:"Να επιτρέπεται πρόσβαση LAN",description:"Συνδέστε τον διακομιστή στη διεπαφή δικτύου σας αντί μόνο στο loopback.",warning:"Η πρόσβαση LAN εκθέτει τον διακομιστή API σε άλλες συσκευές του δικτύου σας. Σε συνδυασμό με δρομολόγηση subscription, τα αιτήματα μπορούν να καταναλώσουν την ποσόστωσή σας — κρατήστε το απενεργοποιημένο αν δεν εμπιστεύεστε το δίκτυο."},status:{running:"Ο διακομιστής εκτελείται",stopped:"Ο διακομιστής έχει σταματήσει",runningHint:"Ο εξερχόμενος διακομιστής API δέχεται αιτήματα.",stoppedHint:"Ενεργοποιήστε τον διακομιστή για να αρχίσει να δέχεται αιτήματα.",port:"θύρα {{port}}",loopback:"URLs Loopback",lan:"URLs LAN"},endpoints:{title:"Δρομολόγηση endpoint",description:"Επιλέξτε το μοντέλο στο οποίο δρομολογεί κάθε μορφή wire. Το προεπιλεγμένο μοντέλο ενσωματώνεται εδώ — ο διακομιστής είναι router, όχι εφαρμογή chat."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Προεπιλεγμένο μοντέλο",backgroundModel:"Μοντέλο παρασκηνίου",visionModel:"Μοντέλο vision",noVisionModel:"Κανένα",backgroundModelIds:"IDs μοντέλων παρασκηνίου",backgroundModelIdsPlaceholder:"IDs μοντέλων διαχωρισμένα με κόμμα",modelPlaceholder:"Επιλέξτε μοντέλο…",useSubscription:"Χρήση subscription",subscriptionUnsupported:"Η δρομολόγηση subscription δεν είναι διαθέσιμη για αυτό το endpoint."},keys:{title:"Access keys",description:"Ονομαστικά keys που οι εξωτερικοί καλούντες στέλνουν ως Bearer token. Το πλήρες key εμφανίζεται μόνο μία φορά κατά τη δημιουργία.",namePlaceholder:"Όνομα key (π.χ. my-cli)",create:"Δημιουργία key",empty:"Δεν υπάρχουν access keys ακόμα.",enabled:"Ενεργό",disabled:"Ανενεργό",revoked:"Ανακλήθηκε",toggle:"Εναλλαγή key",revoke:"Ανάκληση",revokeConfirmTitle:"Ανάκληση αυτού του key;",revokeConfirmDesc:"Η ανάκληση του «{{name}}» σταματά αμέσως τον έλεγχο ταυτότητάς του. Δεν μπορεί να αναιρεθεί.",created:{title:"Το key δημιουργήθηκε",warning:"Αντιγράψτε αυτό το key τώρα — δεν θα εμφανιστεί ξανά. Φυλάξτε το με ασφάλεια.",copy:"Αντιγραφή",copied:"Αντιγράφηκε",dismiss:"Τέλος"}}},xC={title:"Λογαριασμοί & Subscriptions",description:"Διαχειριστείτε τα διαπιστευτήρια subscription μέσω των οποίων δρομολογεί ο διακομιστής. Τα tokens καταχωρίζονται εδώ αλλά δεν εμφανίζονται ποτέ ξανά.",loading:"Φόρτωση λογαριασμών…",empty:"Δεν υπάρχουν διαθέσιμοι providers subscription.",signIn:"Σύνδεση",oauth:{title:"Σύνδεση στο {{name}}",description:"Ανοίξτε τη σελίδα σύνδεσης στο πρόγραμμα περιήγησής σας, εξουσιοδοτήστε και επικολλήστε τον κωδικό εξουσιοδότησης παρακάτω. Ο κωδικός μεταδίδεται μόνο στο daemon — το παραγόμενο token δεν εμφανίζεται ποτέ.",openPage:"Άνοιγμα σελίδας σύνδεσης",codeLabel:"Κωδικός εξουσιοδότησης",codePlaceholder:"Επικολλήστε τον κωδικό εδώ",submit:"Ολοκλήρωση σύνδεσης"},codexOauth:{title:"Σύνδεση στο {{name}}",description:"Ανοίξτε τη σελίδα σύνδεσης στο πρόγραμμα περιήγησής σας και εξουσιοδοτήστε. Το daemon καταγράφει αυτόματα το αποτέλεσμα — κρατήστε αυτό ανοιχτό μέχρι να ολοκληρωθεί. Το token δεν εμφανίζεται ποτέ.",waiting:"Αναμονή ολοκλήρωσης σύνδεσης στο πρόγραμμα περιήγησής σας…",failed:"Η σύνδεση απέτυχε. Δοκιμάστε ξανά."},clearProvider:"Εκκαθάριση όλων",clearConfirmTitle:"Εκκαθάριση λογαριασμών {{name}};",clearConfirmDesc:"Αυτό αφαιρεί κάθε αποθηκευμένο διαπιστευτήριο για αυτόν τον provider. Δεν μπορεί να αναιρεθεί.",credential:{ok:"Ρυθμισμένο",notConfigured:"Δεν έχει ρυθμιστεί"},kind:{"pass-through":"Διαπιστευτήρια pass-through","oauth-bearer":"OAuth bearer","static-bearer":"Στατικό bearer key"},reason:{"missing-credential":"Δεν υπάρχει αποθηκευμένο διαπιστευτήριο.",expired:"Το διαπιστευτήριο έχει λήξει.","reauth-required":"Απαιτείται επανέλεγχος ταυτότητας.","refresh-failed":"Αποτυχία ανανέωσης token.","not-refreshable":"Το διαπιστευτήριο δεν μπορεί να ανανεωθεί.",unknown:"Άγνωστη κατάσταση."},status:{unconfigured:"Μη ρυθμισμένο",authorized:"Εξουσιοδοτημένο",configured:"Ρυθμισμένο",expired:"Έχει λήξει",error:"Σφάλμα"},authMethod:{oauth:"OAuth",setup_token:"Token ρύθμισης",manual:"Χειροκίνητα"},list:{empty:"Δεν υπάρχουν αποθηκευμένοι λογαριασμοί για αυτόν τον provider.",active:"Ενεργός",expiresAt:"Λήγει {{value}}",setActive:"Ορισμός ως ενεργός",remove:"Αφαίρεση",removeConfirmTitle:"Αφαίρεση αυτού του λογαριασμού;",removeConfirmDesc:"Η αφαίρεση του «{{name}}» διαγράφει το αποθηκευμένο διαπιστευτήριό του. Δεν μπορεί να αναιρεθεί.",title:"Λογαριασμοί"},write:{trigger:"Προσθήκη διαπιστευτηρίου",title:"Καταχώριση διαπιστευτηρίου {{name}}",description:"Επικολλήστε ήδη αποκτηθέν υλικό token. Τα πεδία περιορίζονται σε αυτά που αποδέχεται αυτός ο provider· το token αποθηκεύεται, δεν εμφανίζεται ποτέ ξανά.",authMethod:"Μέθοδος ελέγχου ταυτότητας",status:"Κατάσταση",subscriptionLevel:"Επίπεδο subscription",subscriptionLevelNone:"Δεν έχει οριστεί",submit:"Αποθήκευση διαπιστευτηρίου"},field:{accessToken:"Access token",refreshToken:"Refresh token",idToken:"ID token",apiKey:"API key",expiresAt:"Λήγει στις (ISO)",setupTokenExpiresAt:"Το setup token λήγει στις (ISO)",accountId:"ID Λογαριασμού",email:"Email",organizationId:"ID Οργανισμού",baseUrl:"Βασικό URL",zenBaseUrl:"Βασικό URL Zen"},provider:{claude:{title:"Claude",description:"Διαπιστευτήρια subscription Anthropic που δρομολογούνται από το daemon."},codex:{title:"Codex",description:"Διαπιστευτήρια subscription OpenAI Codex που δρομολογούνται από το daemon."},gemini:{title:"Gemini",description:"Διαπιστευτήρια subscription Google Gemini που δρομολογούνται από το daemon."},opencodego:{title:"OpenCodeGo",description:"Στατικά διαπιστευτήρια API-key που δρομολογούνται από το daemon."}},authMethodLabel:"Μέθοδος εξουσιοδότησης",authMethodDesc:{oauth:"Σύνδεση μέσω προγράμματος περιήγησης· το daemon καταγράφει και αποθηκεύει το token.",manual:"Επικολλήστε ήδη αποκτηθέν token. Αποθηκεύεται, δεν εμφανίζεται ποτέ ξανά."},actions:{authorize:"Εξουσιοδότηση",enterToken:"Εισαγωγή token",refresh:"Ανανέωση"},accounts:{addAccount:"Προσθήκη λογαριασμού"},detail:{authMethod:"Μέθοδος εξουσιοδότησης",subscriptionLevel:"Επίπεδο subscription",expiresAt:"Λήγει",lastRefreshed:"Τελευταία ανανέωση",label:"Ετικέτα λογαριασμού",labelPlaceholder:"Δώστε όνομα στον λογαριασμό",saveLabel:"Αποθήκευση ετικέτας"},oauthFlow:{step1:{title:"Άνοιγμα σελίδας εξουσιοδότησης",desc:"Ανοίξτε τη σελίδα σύνδεσης στο πρόγραμμα περιήγησής σας."},step2:{title:"Εξουσιοδότηση πρόσβασης",desc:"Συνδεθείτε και εγκρίνετε την πρόσβαση για τον provider."},step3:{title:"Αντιγραφή κωδικού εξουσιοδότησης",desc:"Η σελίδα εμφανίζει κωδικό εξουσιοδότησης αφού εγκρίνετε."},step4:{title:"Επικόλληση κωδικού",desc:"Επικολλήστε τον κωδικό εξουσιοδότησης παρακάτω για να ολοκληρώσετε. Ο κωδικός μεταδίδεται μόνο στο daemon — το παραγόμενο token δεν εμφανίζεται ποτέ."},authorize:"Ολοκλήρωση σύνδεσης",showUrl:"Εμφάνιση URL εξουσιοδότησης"},manual:{title:"Επικόλληση διαπιστευτηρίου",description:"Επικολλήστε ήδη αποκτηθέν token. Τα πεδία περιορίζονται σε αυτά που αποδέχεται αυτός ο provider· το token αποθηκεύεται, δεν εμφανίζεται ποτέ ξανά.",accessTokenPlaceholder:"Επικολλήστε το access token",refreshTokenPlaceholder:"Επικολλήστε το refresh token (προαιρετικό)",hint:"Το token αποστέλλεται στο daemon και αποθηκεύεται κρυπτογραφημένο. Δεν εμφανίζεται ποτέ ξανά."},openCodeGo:{apiKeyRequired:"Απαιτείται API key.",apiKeyPlaceholder:"Επικολλήστε το API key",baseUrlPlaceholder:"https://… (προαιρετικό)",zenBaseUrlPlaceholder:"https://… (προαιρετικό)"},info:{title:"Σχετικά με τους λογαριασμούς subscription",description:"Τα tokens καταχωρίζονται στο daemon και χρησιμοποιούνται για έλεγχο ταυτότητας σε upstream αιτήματα. Αποθηκεύονται κρυπτογραφημένα και δεν εμφανίζονται ποτέ ξανά. Η αφαίρεση λογαριασμού διαγράφει το αποθηκευμένο διαπιστευτήριό του."},rename:{failed:"Αδυναμία μετονομασίας του λογαριασμού."},refresh:{failed:"Αδυναμία ανανέωσης του token."},errors:{requestFailed:"Το αίτημα απέτυχε. Δοκιμάστε ξανά."},syncWarning:{"external-divergent":"Το αρχείο σύνδεσης του εξωτερικού CLI περιέχει νεότερα διαπιστευτήρια από αυτόν τον λογαριασμό. Το αποθηκευμένο token ίσως σταματήσει να ανανεώνεται — ανανεώστε τώρα ή συνδεθείτε ξανά.","external-not-rotated":"Η ανανέωση απέτυχε και το εξωτερικό CLI περιέχει τα ίδια ληγμένα διαπιστευτήρια. Συνδεθείτε ξανά.","duplicate-token":"Ένας άλλος λογαριασμός μοιράζεται αυτά τα διαπιστευτήρια. Η ανανέωση του ενός θα αποσυνδέσει τον άλλον."},importExternal:{detected:"Βρέθηκε υπάρχουσα σύνδεση CLI {{name}} σε αυτό το μηχάνημα.",hint:"Μετά την εισαγωγή, αυτή η εφαρμογή τη διατηρεί ενημερωμένη: σε κάθε ανανέωση του token ενημερώνεται και το αρχείο σύνδεσης του CLI, ώστε το CLI στο τερματικό να παραμένει συνδεδεμένο.",button:"Εισαγωγή υπάρχουσας σύνδεσης CLI"}},zC={title:"Code CLI",description:"Ρυθμίστε ένα coding CLI να χρησιμοποιεί τον εξερχόμενο proxy του daemon. Αυτή η σελίδα είναι μόνο ανάγνωσης — δεν υπάρχει τίποτα να ρυθμίσετε εδώ.",copy:"Αντιγραφή",copied:"Αντιγράφηκε",baseUrl:{title:"Βασικό URL Daemon",description:"Η διεύθυνση proxy στην οποία συνδέεται το CLI σας.",label:"Βασικό URL"},token:{title:"Έλεγχος ταυτότητας",hint:"Στείλτε 'Authorization: Bearer <your-admin-token>' για διαδρομές διαχειριστή. Το admin token ρυθμίζεται στο daemon (αρχείο ρυθμίσεων ή περιβάλλον) — δεν εμφανίζεται εδώ."},examples:{title:"Παράδειγμα περιβάλλοντος εκκίνησης",keyNote:"Χρησιμοποιήστε outbound access key δημιουργημένο στη σελίδα Υπηρεσία API — όχι το admin token.",anthropic:"CLI μορφής Anthropic",openai:"CLI μορφής OpenAI"},launchDescription:"Εκκινήστε ένα coding CLI σε τερματικό, ρυθμισμένο σε αυτό το daemon. Το daemon εισάγει το env ανακατεύθυνσης και εκκινεί το CLI για εσάς.",refresh:"Ανανέωση",loading:"Ανίχνευση CLIs…",cli:{installed:"Εγκατεστημένο",notFound:"Δεν βρέθηκε",notFoundHint:"Αυτό το CLI δεν βρίσκεται στο PATH του κεντρικού υπολογιστή daemon. Εγκαταστήστε το και ανανεώστε.",install:"Εγκατάσταση",installing:"Εγκατάσταση…",installingHint:"Εγκατάσταση στον κεντρικό υπολογιστή daemon — μπορεί να χρειαστεί λίγο.",launch:"Εκκίνηση",launchTitle:"Εκκίνηση {{name}}",launchDescription:"Ανοίγει νέο τερματικό στον κεντρικό υπολογιστή daemon εκτελώντας αυτό το CLI, δρομολογημένο μέσω του proxy daemon. Επιλέξτε προαιρετικό κατάλογο εργασίας.",cwdLabel:"Κατάλογος εργασίας",cwdPlaceholder:"/διαδρομή/προς/το/έργο/σας",runningVia:"Εκτελείται · {{provider}} / {{model}}",stop:"Διακοπή"},manual:{title:"Χειροκίνητη ρύθμιση",description:"Προτιμάτε να εκτελείτε το CLI μόνοι σας; Ρυθμίστε το να χρησιμοποιεί το daemon με αυτές τις μεταβλητές περιβάλλοντος.",show:"Εμφάνιση",hide:"Απόκρυψη"}},IC={probing:"Έλεγχος για το daemon…",spawning:"Εκκίνηση daemon…",failed:"Το daemon δεν μπόρεσε να εκκινήσει",failedHint:"Βεβαιωθείτε ότι το Node.js είναι εγκατεστημένο και το daemon έχει γίνει build (dist παρόν), ή ορίστε OMNICROSS_DAEMON_ENTRY στο cli.js του daemon."},SC={title:"Ρυθμίσεις",description:"Προτιμήσεις εφαρμογής επιφάνειας εργασίας.",desktopOnly:"Οι επιλογές εκκίνησης και δίσκου συστήματος ισχύουν μόνο στην εφαρμογή επιφάνειας εργασίας.",startup:{title:"Εκκίνηση",autoLaunch:"Εκκίνηση κατά τη σύνδεση",autoLaunchHint:"Εκκίνηση του Omnicross αυτόματα όταν συνδέεστε.",startMinimized:"Εκκίνηση ελαχιστοποιημένο στο δίσκο συστήματος",startMinimizedHint:"Εκκίνηση στο παρασκήνιο χωρίς άνοιγμα παραθύρου."},tray:{title:"Δίσκος συστήματος",minimizeOnClose:"Ελαχιστοποίηση στο δίσκο κατά το κλείσιμο",minimizeOnCloseHint:"Το κλείσιμο του παραθύρου το αποκρύπτει στο δίσκο αντί να τερματίζει."},language:{title:"Γλώσσα",label:"Γλώσσα διεπαφής"}},wC={title:"Στατιστικά χρήσης",description:"Στατιστικά token και κόστους για τα αιτήματα που εξυπηρετεί ο δαίμονας.",rangeToday:"Σήμερα",range7d:"Τελευταίες 7 ημέρες",range30d:"Τελευταίες 30 ημέρες",rangeCustom:"Προσαρμοσμένο",from:"Από",to:"Έως",totalCost:"Συνολικό κόστος",cacheSavings:"Εξοικονόμηση cache",events:"Αιτήματα",inputTokens:"Token εισόδου",outputTokens:"Token εξόδου",cacheReadTokens:"Ανάγνωση cache",cacheWriteTokens:"Εγγραφή cache",reasoningTokens:"Token συλλογισμού",byModel:"Ανά μοντέλο",byApiKey:"Ανά κλειδί API",provider:"Πάροχος",model:"Μοντέλο",cost:"Κόστος",apiKey:"Κλειδί API",unpriced:"Χωρίς τιμή",unpricedHint:"Δεν υπάρχει καταχώρηση τιμής για αυτό το μοντέλο — προσθέστε μία στη σελίδα Τιμές.",unattributed:"Μη αποδιδόμενα",unattributedHint:"Αιτήματα που δεν συνδέονται με συγκεκριμένο κλειδί API. Αυτό είναι αναμενόμενο μέχρι να καταγράφεται η απόδοση ανά κλειδί.",empty:"Κανένα αίτημα σε αυτό το διάστημα.",invalidRange:"Επιλέξτε έγκυρο εύρος ημερομηνιών."},TC={title:"Τιμές μοντέλων",description:"Τιμές token ανά μοντέλο για τον υπολογισμό του κόστους αιτημάτων, σε USD ανά 1 εκατ. token.",search:"Αναζήτηση παρόχου ή μοντέλου…",fetchLatest:"Λήψη πιο πρόσφατων",fetching:"Λήψη…",addEntry:"Προσθήκη καταχώρησης",provider:"Πάροχος",model:"Μοντέλο",inputPrice:"Είσοδος",outputPrice:"Έξοδος",cacheReadPrice:"Ανάγνωση cache",cacheWritePrice:"Εγγραφή cache",source:"Πηγή",updated:"Ενημερώθηκε",userEdited:"επεξεργασμένο",edit:"Επεξεργασία",deleteTitle:"Διαγραφή της καταχώρησης τιμής;",empty:"Ο πίνακας τιμών είναι κενός.",emptyHint:"Λάβετε τις πιο πρόσφατες τιμές για να τον γεμίσετε.",noMatches:"Καμία καταχώρηση δεν ταιριάζει με την αναζήτηση.",saved:"Η καταχώρηση τιμής αποθηκεύτηκε.",saveFailed:"Η αποθήκευση απέτυχε: {{message}}",deleteFailed:"Η διαγραφή απέτυχε: {{message}}",alreadyDeleted:"Η καταχώρηση δεν υπήρχε πια.",fetchApplied:"Ενημερώθηκαν {{count}} καταχωρήσεις από την πηγή.",fetchFailed:"Η λήψη απέτυχε: {{message}}",requiredId:"Απαιτείται",invalidPrice:"Εισαγάγετε μη αρνητικό αριθμό",conflictTitle:"Επίλυση συγκρούσεων τιμών",conflictHint:"Αυτές οι καταχωρήσεις επεξεργάστηκαν από εσάς και άλλαξαν επίσης στην πηγή. Επιλέξτε ανά γραμμή αν θα κρατήσετε την τιμή σας (Παράλειψη) ή θα πάρετε τη νέα (Αντικατάσταση).",current:"Τρέχουσα",incoming:"Εισερχόμενη",overwrite:"Αντικατάσταση",skip:"Παράλειψη",overwriteAll:"Αντικατάσταση όλων",skipAll:"Παράλειψη όλων",applyResolutions:"Εφαρμογή",resolved:"{{overwritten}} αντικαταστάθηκαν, {{skipped}} παραλείφθηκαν.",resolvedWithStale:"{{overwritten}} αντικαταστάθηκαν, {{skipped}} παραλείφθηκαν. {{stale}} άλλαξαν στο μεταξύ και έμειναν ανέγγιχτες.",refreshFailed:"Η αλλαγή εφαρμόστηκε, αλλά η επαναφόρτωση της λίστας απέτυχε: {{message}}",sourceBuiltin:"Ενσωματωμένο",sourceLitellm:"LiteLLM",sourceUser:"Χρήστης"},jC={providerSettings:fC,apiMode:vC,presetName:kC,common:yC,mediaSettings:bC,appLocal:PC,nav:AC,apiService:CC,accounts:xC,codeCli:zC,daemonStatus:IC,settings:SC,usageStats:wC,pricing:TC},MC={loading:"Loading LLM configuration...",reset:{button:"Restore defaults",confirmTitle:"Restore default settings?",confirmBody:"This clears your customizations for this provider so it follows the built-in defaults again. Your API key and saved sessions are kept.",confirmButton:"Restore defaults"},reentryBanner:{message:"{{count}} enabled provider(s) need their API key re-entered. Open each one and add its key again."},migrationPack:{barHint:"Move your provider keys and subscription tokens to another machine with an encrypted pack.",passphrase:"Passphrase",passphrasePlaceholder:"Enter a passphrase",passphraseHint:"Use at least 8 characters; 12 or more is recommended.",confirm:"Confirm passphrase",confirmPlaceholder:"Re-enter the passphrase",mismatch:"Passphrases do not match.",strength:{weak:"Too short — use at least 8 characters.",fair:"OK — 12 or more characters is stronger.",strong:"Strong passphrase."},export:{button:"Export pack",title:"Export encrypted pack",subtitle:"Encrypt your provider keys and subscription tokens into a portable file.",warning:"This file contains decryptable secrets. Keep it safe — anyone with the file and the passphrase can read your keys. A lost passphrase cannot be recovered.",submit:"Export",success:"Pack exported successfully.",error:"Export failed. Please try again."},import:{button:"Import pack",title:"Import encrypted pack",subtitle:"Restore provider keys and subscription tokens from an exported pack.",hint:"Enter the passphrase used when the pack was exported, then choose the file.",submit:"Import",successTitle:"Import complete",summary:"Imported {{providerKeys}} provider key(s), {{poolKeys}} pool key(s), and {{tokenSets}} token set(s).",duplicates:"Skipped {{count}} pool key(s) already present.",skipped:"Skipped (no matching provider): {{names}}",error:"Wrong passphrase or corrupted pack. Nothing was changed."}},searchPlaceholder:"Search providers...",emptySearch:"No providers match your search.",emptyList:"No providers configured.",selectPrompt:"Select a provider to view details",listStatus:"{{count}} model(s)",noModels:"No models configured",enabled:"Enabled",disabled:"Disabled",showEnabledOnly:"Show enabled only",showAll:"Show all providers",dragHandle:"Drag to reorder",reorderFailed:"Failed to save provider order",credentials:{apiKey:"API Key",apiBaseUrl:"API Base URL"},filter:{all:"All",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Select a Template",skipTemplates:"Skip, configure manually",name:"Name *",providerType:"Type",apiType:"API Type",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standard OpenAI chat/completions API format",claudecode:"Anthropic Messages API format (Claude Code)"},chatApiFormat:"API Format",chatApiFormatDescription:"Select the API format that matches your provider's endpoint",apiKey:"API Key",apiKeyPlaceholder:"sk-... or $ENV_VAR",apiKeyHelper:"Use $VAR_NAME to reference environment variables",apiKeySetPlaceholder:"Key is set — leave blank to keep it",apiKeyReplaceHelper:"A key is stored securely. Type a new value to replace it, or leave blank to keep it.",testApiKey:"Test API Key",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Preview:",models:"Models",modelPlaceholder:"Model name (e.g., gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API Transformers",transformerConfigDescription:"Configure transformers to adapt API request/response formats for this provider",transformerConfigNote:"The daemon applies these transformers in the request chain, after the provider's format transformer (which handles the wire-format conversion). Unknown transformer names are skipped.",enabled:"Enabled",apiVersion:"API Version",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API version (e.g., 2024-08-01-preview)",official:"Official Anthropic API",officialHelper:"Enable if this provider connects directly to the official Anthropic API. Disable for reverse proxies or third-party services.",maxConcurrency:"Max Concurrent Requests",maxConcurrencyHelper:"Maximum number of concurrent API requests sent to this provider. Lower values help avoid rate limiting (429 errors). Set `-1` for no limit.",codingPlan:{label:"Coding Plan",description:"Use a separate API endpoint for subscription-based coding plans",baseUrl:"Coding Plan Base URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API Key (optional)",apiKeyPlaceholder:"Leave empty to use provider's API key",apiKeyHelper:"Only required if the coding plan uses a different API key",tokenPlanHint:"Some providers (e.g. Xiaomi MiMo) issue Token Plan keys with a `tp-` prefix — informational only, not enforced."},selectTypeFirst:"Select Provider Type",selectTypeFirstDesc:"Choose what type of provider you want to add",codeProviderNote:"Code providers only need API Key and URL. Models are managed by the Agent Router.",buttons:{cancel:"Cancel",submitAdd:"Add Provider",submitUpdate:"Update Provider",continue:"Continue",back:"Back"}},details:{noSelection:"Select a provider to view details",apiKey:"API Key",apiUrl:"API URL",nameLabel:"Provider Name",modelsEndpoint:"Models Endpoint",modelsEndpointHelper:"Override the discovery endpoint if the provider exposes a custom /models path.",models:"Models",transformers:"Transformers",codeProviderNote:"Code providers (like Claude Code) do not require model configuration. Models are automatically managed by the Agent Router.",buttons:{more:"More Settings",delete:"Delete"}},providerModelSelector:{placeholder:"Select provider and model",noProviders:"No providers available",noModels:"No models configured"},apiKeyPool:{title:"API Key Pool",description:"Configure multiple API keys for load balancing. Each session sticks to one key to preserve prompt cache.",defaultLabel:"Default",weight:"Weight",noKey:"No key",labelPlaceholder:"Label (e.g., Key #1, Production)",addKey:"Add API Key",add:"Add",empty:"No additional keys configured.",statusCoolingDown:"Cooling down {{time}}",statusAuthFailed:"Auth failed · disabled",statusDisabled:"Disabled",statusHealthy:"Healthy",agoSeconds:"{{count}}s ago",agoMinutes:"{{count}}m ago",agoHours:"{{count}}h ago",agoDays:"{{count}}d ago"},modelsManager:{searchPlaceholder:"Search models...",defaultGroup:"All Models",add:"Add Model",manage:"Manage",empty:"No models in this group",enabled:"Enabled",disabled:"Disabled",filters:{all:"All",vision:"Vision",reasoning:"Reasoning",free:"Free",tools:"Tools"},manualDialog:{title:"Add Model",subtitle:"Add a custom model to this provider",modelId:"Model ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"The exact model identifier used when calling the API",modelName:"Display Name",modelNamePlaceholder:"Friendly display name (optional)",modelNameHelper:"Optional name shown in the UI. If empty, Model ID will be used",group:"Group",groupPlaceholder:"Select or enter a group name",submit:"Add",cancel:"Cancel",helper:"Provide the exact model identifier exposed by the provider API."},editDialog:{title:"Edit Model",subtitle:"Modify model settings",modelId:"Model ID",modelIdPlaceholder:"Model identifier",modelIdHelper:"The model identifier used when calling the API",modelName:"Display Name",modelNamePlaceholder:"Friendly display name",modelNameHelper:"Name shown in the UI",group:"Group",groupPlaceholder:"Select or enter a group name",submit:"Save",cancel:"Cancel",vision:"Vision Capability",visionHint:"Whether this model supports image/vision input",reasoning:"Thinking Model",reasoningHint:"Whether this model supports thinking/reasoning mode"},manageDialog:{title:"Manage Models",cachedAt:"Cached at {{date}} ({{source}})",refresh:"Refresh",close:"Close",raw:"Raw JSON",empty:"No remote models available.",error:"Failed to load models: {{message}}",addFromCatalog:"Add",sourceCache:"cache",sourceNetwork:"live",contextLength:"Context {{value}} tokens",maxTokens:"Max {{value}} tokens"},messages:{added:"Model added.",updated:"Model updated.",removed:"Model removed.",duplicate:"Model already exists.",refreshed:"Models refreshed",refreshFailed:"Failed to refresh models"},testDialog:{title:"Model Connectivity Test",provider:"Provider",model:"Model",testing:"Testing...",success:"Test Successful",successMessage:"Model can be accessed normally",failure:"Test Failed",aiResponse:"AI Response",charCount:"{{count}} chars",duration:"Duration {{time}}s",close:"Close",retest:"Re-test",testButton:"Test model",unsupportedFormat:"Testing isn't supported for this provider format yet."}},router:{title:"Router Configuration",description:"Configure which provider/model to use for different scenarios.",labels:{default:"Default",background:"background",think:"think",longContext:"Long Context",webSearch:"Web Search",image:"Image",longContextThreshold:"Long Context Threshold"},helper:{longContextThreshold:"Token count before switching to the long-context model."},placeholder:{required:"Required",optional:"Optional"}},agentRouter:{title:"Agent Router",description:"Configure bidirectional routing between Chat and Code modes.",searchPlaceholder:"Search routers...",noSearchResults:"No routers match your search.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Chat to Code Router",description:"Use chat providers in agent/coding mode",addRouter:"Add Router",emptyState:"No Chat→Code routers configured. Add one to use chat providers in coding mode.",form:{name:"Router Name",namePlaceholder:"My Chat→Code Router",chatProvider:"Chat Provider",chatProviderPlaceholder:"Select a chat provider",mode:"Mode",modeSimple:"Simple",modeAdvanced:"Advanced",modeSimpleDesc:"Direct pass-through to chat provider",modeAdvancedDesc:"Configure model mapping and context handling",enabled:"Enabled",save:"Save Router",cancel:"Cancel"},list:{provider:"Provider",mode:"Mode",status:"Status"},mappings:{title:"Model Mappings",description:"Map Chat provider models to Code provider models",count:"mapping(s)",empty:"No model mappings configured. Add mappings to route chat models to code providers.",addNew:"Add New Mapping",selectSource:"Select source model (Chat)",selectTarget:"Select target model (Code)",targetPlaceholder:"Enter Claude Code model name",notSet:"(Not set - click to select)",add:"Add",edit:"Edit",done:"Done"},advanced:{title:"Advanced Configuration",description:"Configure models for different task types",helpText:"Default model is required. Other models are optional and will fall back to default if not configured.",default:{label:"Default",placeholder:"Select default model",description:"Primary model for general tasks (similar to Claude Sonnet)"},background:{label:"Background",placeholder:"Select background model",description:"Lightweight model for background tasks (similar to Claude Haiku)"},think:{label:"Think",placeholder:"Select think model",description:"Advanced model for complex reasoning (similar to Claude Opus)"},image:{label:"Image",placeholder:"Select image model",description:"Model for image-related tasks with vision capability"}}},codeToChat:{title:"Code to Chat Router",description:"Expose Coding Plan models in chat mode",addRouter:"Add Router",emptyState:"No Code→Chat routers configured. Add one to expose Coding Plan models in chat mode.",form:{name:"Router Name",namePlaceholder:"My Code→Chat Router",codeProvider:"Code Provider",codeProviderPlaceholder:"Select a code provider",codeProviderHelper:"Select the Code provider to use for transformation",models:"Coding Plan Models",modelsHelper:"Select which Coding Plan models to expose",enabled:"Enabled",save:"Save Router",cancel:"Cancel"},mappings:{title:"Model Mappings",description:"Map Code provider models to Chat provider models for exposure",count:"mapping(s)",empty:"No model mappings configured. Add mappings to expose Code models in chat mode.",addNew:"Add New Mapping",selectSource:"Select source model (Code)",selectTarget:"Select target model (Chat)",sourcePlaceholder:"Enter source model name",targetPlaceholder:"Enter target model name",add:"Add",edit:"Edit",done:"Done"}},transformers:{title:"Transformers",description:"Configure transformers for request/response conversion",noProvider:"Select a provider to configure transformers",empty:"No transformers",count:"{{count}} transformer(s)"},status:{enabled:"Enabled",disabled:"Disabled"},messages:{routerAdded:"Router added successfully",routerUpdated:"Router updated successfully",routerDeleted:"Router deleted successfully",saveFailed:"Failed to save router"}},presets:{title:"Quick Add Provider",added:"Added",add:"Add",features:{search:"Search",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"Are you sure you want to delete this provider?"},errors:{nameRequired:"Provider name is required",urlRequired:"API Base URL is required",urlInvalid:"Please enter a valid URL (e.g., https://api.example.com)",saveFailed:"Failed to save provider",deleteFailed:"Error deleting provider. Please try again.",toggleFailed:"Error toggling provider. Please try again."},openRouter:{title:"OpenRouter Provider Routing",description:"Configure how requests are routed to different providers on OpenRouter.",sort:"Routing Strategy",sortTooltip:"Choose how to prioritize providers. Auto uses intelligent load balancing.",order:"Provider Priority Order",orderTooltip:"Specify providers to try in order (e.g., anthropic, openai, together). Press Enter to add.",orderPlaceholder:"Type provider slug and press Enter...",allowFallbacks:"Allow Fallbacks",allowFallbacksTooltip:"When enabled, OpenRouter will try backup providers if the primary is unavailable.",requireParameters:"Require All Parameters",requireParametersTooltip:"Only route to providers that support all parameters in your request.",dataCollection:"Data Collection Policy",dataCollectionTooltip:"Control whether to use providers that may store or train on your data.",zdr:"Zero Data Retention",zdrTooltip:"Only route to endpoints with Zero Data Retention policy.",only:"Only Allow Providers",onlyTooltip:"Only use these specific providers. Leave empty to allow all providers.",onlyPlaceholder:"Type provider slug and press Enter...",ignore:"Ignore Providers",ignoreTooltip:"Skip these providers when routing requests.",ignorePlaceholder:"Type provider slug and press Enter...",quantizations:"Quantization Filter",quantizationsTooltip:"Only use providers with specific quantization levels. Lower precision may reduce quality but improve speed.",maxPrice:"Maximum Price",maxPriceTooltip:"Set maximum price limits per million tokens. Leave empty for no limit.",configured:"Configured"}},NC={label:"API Mode",standard:"Standard",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Keys for this plan typically begin with `{{prefix}}`. Hint only — not enforced.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan uses a separate API key from the standard endpoint.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan uses a separate API key from the standard endpoint.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan is Anthropic-protocol only.",xiaomiTokenPlanRegions:"Default baseUrl is `token-plan-cn.*`. You can manually edit it to `token-plan-sgp.*` or `token-plan-ams.*`.",confirmOverwriteTitle:"Switch API mode?",confirmOverwriteBody:"You have customized the API URL or API Key. Switching modes will overwrite them with the new mode's defaults — or keep your customizations and only update the mode label.",overwriteAndSwitch:"Overwrite and switch",keepCustomizations:"Keep customizations"},LC={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},RC={cancel:"Cancel",close:"Close",copy:"Copy",delete:"Delete",dismiss:"Dismiss",save:"Save",optional:"optional",retry:"Retry",loading:"Loading…"},DC={common:{learnMore:"Docs"}},EC={notSupportedByDaemon:"Not yet supported by the daemon",discoveryUnsupportedFormat:"Model discovery is not supported for this provider format yet. Add models manually."},OC={subtitle:"Control Panel",providers:"Providers",apiService:"API Service",accounts:"Accounts",codeCli:"Code CLI",settings:"Settings",usageStats:"Usage",pricing:"Pricing"},KC={title:"API Service",description:"Configure the outbound API server, per-endpoint model routing, and named access keys.",loading:"Loading server configuration…",loadError:"Could not load the server configuration. Check that the daemon is reachable.",enable:{label:"Enable outbound server",description:"Start the local API server that routes external callers through your providers."},networkBinding:{label:"Allow LAN access",description:"Bind the server to your network interface instead of loopback only.",warning:"LAN access exposes the API server to other devices on your network. Combined with subscription routing, requests can consume your subscription quota — keep this off unless you trust the network."},status:{running:"Server running",stopped:"Server stopped",runningHint:"The outbound API server is accepting requests.",stoppedHint:"Enable the server to start accepting requests.",port:"port {{port}}",loopback:"Loopback URLs",lan:"LAN URLs"},endpoints:{title:"Endpoint routing",description:"Pick the model each wire format routes to. The default model folds in here — the server is a router, not a chat app."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Default model",backgroundModel:"Background model",visionModel:"Vision model",noVisionModel:"None",backgroundModelIds:"Background model IDs",backgroundModelIdsPlaceholder:"comma-separated model ids",modelPlaceholder:"Select a model…",useSubscription:"Use subscription",subscriptionUnsupported:"Subscription routing is not available for this endpoint."},keys:{title:"Access keys",description:"Named keys external callers send as a Bearer token. The full key is shown only once at creation.",namePlaceholder:"Key name (e.g. my-cli)",create:"Create key",empty:"No access keys yet.",enabled:"Enabled",disabled:"Disabled",revoked:"Revoked",toggle:"Toggle key",revoke:"Revoke",revokeConfirmTitle:"Revoke this key?",revokeConfirmDesc:'Revoking "{{name}}" immediately stops it from authenticating. This cannot be undone.',created:{title:"Key created",warning:"Copy this key now — it will not be shown again. Store it securely.",copy:"Copy",copied:"Copied",dismiss:"Done"}}},UC={title:"Accounts & Subscriptions",description:"Manage the subscription credentials the server routes through. Tokens are written here but never displayed back.",loading:"Loading accounts…",empty:"No subscription providers are available.",signIn:"Sign in",oauth:{title:"Sign in to {{name}}",description:"Open the sign-in page in your browser, authorize, then paste the authorization code below. The code crosses to the daemon only — the minted token is never shown.",openPage:"Open sign-in page",codeLabel:"Authorization code",codePlaceholder:"Paste the code here",submit:"Complete sign-in"},codexOauth:{title:"Sign in to {{name}}",description:"Open the sign-in page in your browser and authorize. The daemon captures the result automatically — keep this open until it completes. The token is never shown.",waiting:"Waiting for you to complete sign-in in your browser…",failed:"Sign-in failed. Please try again."},clearProvider:"Clear all",clearConfirmTitle:"Clear {{name}} accounts?",clearConfirmDesc:"This removes every stored credential for this provider. This cannot be undone.",credential:{ok:"Configured",notConfigured:"Not configured"},kind:{"pass-through":"Pass-through credentials","oauth-bearer":"OAuth bearer","static-bearer":"Static bearer key"},reason:{"missing-credential":"No credential stored.",expired:"Credential expired.","reauth-required":"Re-authentication required.","refresh-failed":"Token refresh failed.","not-refreshable":"Credential is not refreshable.",unknown:"Status unknown."},status:{unconfigured:"Unconfigured",authorized:"Authorized",configured:"Configured",expired:"Expired",error:"Error"},authMethod:{oauth:"OAuth",setup_token:"Setup token",manual:"Manual"},list:{empty:"No accounts stored for this provider.",active:"Active",expiresAt:"Expires {{value}}",setActive:"Set active",remove:"Remove",removeConfirmTitle:"Remove this account?",removeConfirmDesc:'Removing "{{name}}" deletes its stored credential. This cannot be undone.',title:"Accounts"},write:{trigger:"Add credential",title:"Write {{name}} credential",description:"Paste already-obtained token material. Fields are limited to what this provider accepts; the token is stored, never shown back.",authMethod:"Auth method",status:"Status",subscriptionLevel:"Subscription level",subscriptionLevelNone:"Not set",submit:"Save credential"},field:{accessToken:"Access token",refreshToken:"Refresh token",idToken:"ID token",apiKey:"API key",expiresAt:"Expires at (ISO)",setupTokenExpiresAt:"Setup token expires at (ISO)",accountId:"Account ID",email:"Email",organizationId:"Organization ID",baseUrl:"Base URL",zenBaseUrl:"Zen base URL"},provider:{claude:{title:"Claude",description:"Anthropic subscription credentials routed by the daemon."},codex:{title:"Codex",description:"OpenAI Codex subscription credentials routed by the daemon."},gemini:{title:"Gemini",description:"Google Gemini subscription credentials routed by the daemon."},opencodego:{title:"OpenCodeGo",description:"Static API-key credentials routed by the daemon."}},authMethodLabel:"Authorization method",authMethodDesc:{oauth:"Sign in through your browser; the daemon captures and stores the token.",manual:"Paste an already-obtained token. It is stored, never displayed back."},actions:{authorize:"Authorize",enterToken:"Enter token",refresh:"Refresh"},accounts:{addAccount:"Add account"},detail:{authMethod:"Authorization method",subscriptionLevel:"Subscription level",expiresAt:"Expires",lastRefreshed:"Last refreshed",label:"Account label",labelPlaceholder:"Name this account",saveLabel:"Save label"},oauthFlow:{step1:{title:"Open the authorization page",desc:"Open the sign-in page in your browser."},step2:{title:"Authorize access",desc:"Sign in and approve access for the provider."},step3:{title:"Copy the authorization code",desc:"The page shows an authorization code after you approve."},step4:{title:"Paste the code",desc:"Paste the authorization code below to finish. The code crosses to the daemon only — the minted token is never shown."},authorize:"Complete sign-in",showUrl:"Show authorization URL"},manual:{title:"Paste credential",description:"Paste an already-obtained token. Fields are limited to what this provider accepts; the token is stored, never shown back.",accessTokenPlaceholder:"Paste the access token",refreshTokenPlaceholder:"Paste the refresh token (optional)",hint:"The token is sent to the daemon and stored encrypted. It is never displayed back."},openCodeGo:{apiKeyRequired:"An API key is required.",apiKeyPlaceholder:"Paste the API key",baseUrlPlaceholder:"https://… (optional)",zenBaseUrlPlaceholder:"https://… (optional)"},info:{title:"About subscription accounts",description:"Tokens are written to the daemon and used to authenticate upstream requests. They are stored encrypted and never displayed back. Removing an account deletes its stored credential."},rename:{failed:"Couldn't rename the account."},refresh:{failed:"Couldn't refresh the token."},errors:{requestFailed:"Request failed. Please try again."},syncWarning:{"external-divergent":"The external CLI login file holds a newer credential than this account. The stored token may stop refreshing — refresh now or sign in again.","external-not-rotated":"Refresh failed, and the external CLI holds the same expired credential. Please sign in again.","duplicate-token":"Another account shares this credential. Refreshing either account will sign the other out."},importExternal:{detected:"An existing {{name}} CLI login was found on this machine.",hint:"Importing takes over keeping it fresh: after each token refresh the CLI login file is updated too, so the terminal CLI stays signed in.",button:"Import existing CLI login"}},HC={title:"Code CLI",description:"Point a coding CLI at the daemon's outbound proxy. This page is read-only — there is nothing to configure here.",copy:"Copy",copied:"Copied",baseUrl:{title:"Daemon base URL",description:"The proxy address your CLI connects to.",label:"Base URL"},token:{title:"Authentication",hint:"Send 'Authorization: Bearer <your-admin-token>' for admin routes. The admin token is configured in the daemon (its config file or environment) — it is never shown here."},examples:{title:"Example launch environment",keyNote:"Use an outbound access key created on the API Service page — not the admin token.",anthropic:"Anthropic-format CLI",openai:"OpenAI-format CLI"},launchDescription:"Launch a coding CLI in a terminal, pointed at this daemon. The daemon injects the redirect env and starts the CLI for you.",refresh:"Refresh",loading:"Detecting CLIs…",cli:{installed:"Installed",notFound:"Not found",notFoundHint:"This CLI isn't on the daemon host's PATH. Install it, then refresh.",install:"Install",installing:"Installing…",installingHint:"Installing on the daemon host — this can take a minute.",launch:"Launch",launchTitle:"Launch {{name}}",launchDescription:"Opens a new terminal on the daemon host running this CLI, routed through the daemon proxy. Pick an optional working directory.",cwdLabel:"Working directory",cwdPlaceholder:"/path/to/your/project",runningVia:"Running · {{provider}} / {{model}}",stop:"Stop"},manual:{title:"Manual setup",description:"Prefer to run the CLI yourself? Point it at the daemon with these env vars.",show:"Show",hide:"Hide"}},FC={probing:"Checking for the daemon…",spawning:"Starting the daemon…",failed:"The daemon could not start",failedHint:"Ensure Node.js is installed and the daemon is built (dist present), or set OMNICROSS_DAEMON_ENTRY to the daemon's cli.js."},BC={title:"Settings",description:"Desktop app preferences.",desktopOnly:"Startup and tray options apply only in the desktop app.",startup:{title:"Startup",autoLaunch:"Launch at login",autoLaunchHint:"Start Omnicross automatically when you sign in.",startMinimized:"Start minimized to tray",startMinimizedHint:"Launch in the background without opening the window."},tray:{title:"Tray",minimizeOnClose:"Minimize to tray on close",minimizeOnCloseHint:"Closing the window hides it to the tray instead of quitting."},language:{title:"Language",label:"Interface language"}},VC={title:"Usage Statistics",description:"Token and cost statistics for requests served by the daemon.",rangeToday:"Today",range7d:"Last 7 days",range30d:"Last 30 days",rangeCustom:"Custom",from:"From",to:"To",totalCost:"Total cost",cacheSavings:"Cache savings",events:"Requests",inputTokens:"Input tokens",outputTokens:"Output tokens",cacheReadTokens:"Cache read",cacheWriteTokens:"Cache write",reasoningTokens:"Reasoning tokens",byModel:"By model",byApiKey:"By API key",provider:"Provider",model:"Model",cost:"Cost",apiKey:"API key",unpriced:"Unpriced",unpricedHint:"No pricing entry exists for this model — add one on the Pricing page.",unattributed:"Unattributed",unattributedHint:"Requests not linked to a specific API key. This is expected until per-key attribution is recorded.",empty:"No requests in this range.",invalidRange:"Select a valid date range."},qC={title:"Model Pricing",description:"Per-model token prices used to compute request costs, in USD per 1M tokens.",search:"Search provider or model…",fetchLatest:"Fetch latest",fetching:"Fetching…",addEntry:"Add entry",provider:"Provider",model:"Model",inputPrice:"Input",outputPrice:"Output",cacheReadPrice:"Cache read",cacheWritePrice:"Cache write",source:"Source",updated:"Updated",userEdited:"edited",edit:"Edit",deleteTitle:"Delete pricing entry?",empty:"The pricing table is empty.",emptyHint:"Fetch the latest prices to populate it.",noMatches:"No entries match your search.",saved:"Pricing entry saved.",saveFailed:"Save failed: {{message}}",deleteFailed:"Delete failed: {{message}}",alreadyDeleted:"The entry was already gone.",fetchApplied:"Updated {{count}} entries from the source.",fetchFailed:"Fetch failed: {{message}}",requiredId:"Required",invalidPrice:"Enter a non-negative number",conflictTitle:"Resolve pricing conflicts",conflictHint:"These entries were edited by you and also changed at the source. Choose per row whether to keep your value (Skip) or take the incoming one (Overwrite).",current:"Current",incoming:"Incoming",overwrite:"Overwrite",skip:"Skip",overwriteAll:"Overwrite all",skipAll:"Skip all",applyResolutions:"Apply",resolved:"{{overwritten}} overwritten, {{skipped}} skipped.",resolvedWithStale:"{{overwritten}} overwritten, {{skipped}} skipped. {{stale}} changed meanwhile and were left untouched.",refreshFailed:"The change was applied, but reloading the list failed: {{message}}",sourceBuiltin:"Built-in",sourceLitellm:"LiteLLM",sourceUser:"User"},$C={providerSettings:MC,apiMode:NC,presetName:LC,common:RC,mediaSettings:DC,appLocal:EC,nav:OC,apiService:KC,accounts:UC,codeCli:HC,daemonStatus:FC,settings:BC,usageStats:VC,pricing:qC},_C={loading:"Cargando configuración de LLM...",reset:{button:"Restaurar valores predeterminados",confirmTitle:"¿Restaurar la configuración predeterminada?",confirmBody:"Esto borra tus personalizaciones para este proveedor y vuelve a los valores predeterminados integrados. Tu clave de API y las sesiones guardadas se conservan.",confirmButton:"Restaurar valores predeterminados"},reentryBanner:{message:"{{count}} proveedor(es) habilitado(s) necesita(n) que se vuelva a ingresar su clave de API. Abre cada uno y agrega su clave nuevamente."},migrationPack:{barHint:"Mueve tus claves de proveedor y tokens de suscripción a otra computadora con un paquete cifrado.",passphrase:"Contraseña",passphrasePlaceholder:"Ingresa una contraseña",passphraseHint:"Usa al menos 8 caracteres; se recomiendan 12 o más.",confirm:"Confirmar contraseña",confirmPlaceholder:"Vuelve a ingresar la contraseña",mismatch:"Las contraseñas no coinciden.",strength:{weak:"Demasiado corta — usa al menos 8 caracteres.",fair:"Aceptable — 12 o más caracteres es más seguro.",strong:"Contraseña segura."},export:{button:"Exportar paquete",title:"Exportar paquete cifrado",subtitle:"Cifra tus claves de proveedor y tokens de suscripción en un archivo portátil.",warning:"Este archivo contiene secretos descifrables. Guárdalo de forma segura — cualquiera que tenga el archivo y la contraseña puede leer tus claves. Una contraseña perdida no se puede recuperar.",submit:"Exportar",success:"Paquete exportado exitosamente.",error:"Error al exportar. Por favor, intenta de nuevo."},import:{button:"Importar paquete",title:"Importar paquete cifrado",subtitle:"Restaura las claves de proveedor y los tokens de suscripción desde un paquete exportado.",hint:"Ingresa la contraseña utilizada al exportar el paquete y luego elige el archivo.",submit:"Importar",successTitle:"Importación completada",summary:"Se importaron {{providerKeys}} clave(s) de proveedor, {{poolKeys}} clave(s) de grupo y {{tokenSets}} conjunto(s) de tokens.",duplicates:"Se omitieron {{count}} clave(s) de grupo ya presentes.",skipped:"Omitido (sin proveedor coincidente): {{names}}",error:"Contraseña incorrecta o paquete dañado. No se realizaron cambios."}},searchPlaceholder:"Buscar proveedores...",emptySearch:"Ningún proveedor coincide con tu búsqueda.",emptyList:"No hay proveedores configurados.",selectPrompt:"Selecciona un proveedor para ver los detalles",listStatus:"{{count}} modelo(s)",noModels:"No hay modelos configurados",enabled:"Habilitado",disabled:"Deshabilitado",showEnabledOnly:"Mostrar solo habilitados",showAll:"Mostrar todos los proveedores",dragHandle:"Arrastra para reordenar",reorderFailed:"Error al guardar el orden de los proveedores",credentials:{apiKey:"Clave de API",apiBaseUrl:"URL base de la API"},filter:{all:"Todos",chat:"Chat",code:"Código"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Selecciona una plantilla",skipTemplates:"Omitir, configurar manualmente",name:"Nombre *",providerType:"Tipo",apiType:"Tipo de API",apiTypeOptions:{openai:"Completado OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Formato estándar de API chat/completions de OpenAI",claudecode:"Formato de API de mensajes de Anthropic (Claude Code)"},chatApiFormat:"Formato de API",chatApiFormatDescription:"Selecciona el formato de API que corresponde al endpoint de tu proveedor",apiKey:"Clave de API",apiKeyPlaceholder:"sk-... o $ENV_VAR",apiKeyHelper:"Usa $VAR_NAME para referenciar variables de entorno",apiKeySetPlaceholder:"La clave está configurada — déjalo en blanco para conservarla",apiKeyReplaceHelper:"Hay una clave almacenada de forma segura. Escribe un nuevo valor para reemplazarla o déjalo en blanco para conservarla.",testApiKey:"Probar clave de API",apiUrl:"URL de la API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Vista previa:",models:"Modelos",modelPlaceholder:"Nombre del modelo (p. ej., gpt-4, claude-3-opus)",transformers:"Transformadores",transformerConfig:"Transformadores de API",transformerConfigDescription:"Configura transformadores para adaptar los formatos de solicitud/respuesta de la API de este proveedor",transformerConfigNote:"El daemon aplica estos transformadores en la cadena de solicitudes, después del transformador de formato del proveedor (que maneja la conversión del formato de red). Los nombres de transformadores desconocidos se omiten.",enabled:"Habilitado",apiVersion:"Versión de la API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versión de la API de Azure OpenAI (p. ej., 2024-08-01-preview)",official:"API oficial de Anthropic",officialHelper:"Habilita esta opción si el proveedor se conecta directamente a la API oficial de Anthropic. Desactívala para proxies inversos o servicios de terceros.",maxConcurrency:"Máximo de solicitudes simultáneas",maxConcurrencyHelper:"Número máximo de solicitudes de API simultáneas enviadas a este proveedor. Valores más bajos ayudan a evitar la limitación de velocidad (errores 429). Establece `-1` para sin límite.",codingPlan:{label:"Plan de codificación",description:"Usar un endpoint de API independiente para planes de codificación basados en suscripción",baseUrl:"URL base del plan de codificación",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Clave de API del plan de codificación (opcional)",apiKeyPlaceholder:"Déjalo vacío para usar la clave de API del proveedor",apiKeyHelper:"Solo se requiere si el plan de codificación utiliza una clave de API diferente",tokenPlanHint:"Algunos proveedores (p. ej., Xiaomi MiMo) emiten claves de Plan de tokens con el prefijo `tp-` — solo informativo, no se aplica."},selectTypeFirst:"Selecciona el tipo de proveedor",selectTypeFirstDesc:"Elige qué tipo de proveedor deseas agregar",codeProviderNote:"Los proveedores de código solo necesitan clave de API y URL. Los modelos son administrados por el router de agentes.",buttons:{cancel:"Cancelar",submitAdd:"Agregar proveedor",submitUpdate:"Actualizar proveedor",continue:"Continuar",back:"Atrás"}},details:{noSelection:"Selecciona un proveedor para ver los detalles",apiKey:"Clave de API",apiUrl:"URL de la API",nameLabel:"Nombre del proveedor",modelsEndpoint:"Endpoint de modelos",modelsEndpointHelper:"Anula el endpoint de descubrimiento si el proveedor expone una ruta /models personalizada.",models:"Modelos",transformers:"Transformadores",codeProviderNote:"Los proveedores de código (como Claude Code) no requieren configuración de modelos. Los modelos son administrados automáticamente por el router de agentes.",buttons:{more:"Más configuraciones",delete:"Eliminar"}},providerModelSelector:{placeholder:"Selecciona proveedor y modelo",noProviders:"No hay proveedores disponibles",noModels:"No hay modelos configurados"},apiKeyPool:{title:"Grupo de claves de API",description:"Configura varias claves de API para el balanceo de carga. Cada sesión se mantiene en una clave para conservar el caché de prompts.",defaultLabel:"Predeterminada",weight:"Peso",noKey:"Sin clave",labelPlaceholder:"Etiqueta (p. ej., Clave n.° 1, Producción)",addKey:"Agregar clave de API",add:"Agregar",empty:"No hay claves adicionales configuradas.",statusCoolingDown:"En enfriamiento {{time}}",statusAuthFailed:"Autenticación fallida · deshabilitada",statusDisabled:"Deshabilitada",statusHealthy:"En buen estado",agoSeconds:"hace {{count}}s",agoMinutes:"hace {{count}}m",agoHours:"hace {{count}}h",agoDays:"hace {{count}}d"},modelsManager:{searchPlaceholder:"Buscar modelos...",defaultGroup:"Todos los modelos",add:"Agregar modelo",manage:"Administrar",empty:"No hay modelos en este grupo",enabled:"Habilitado",disabled:"Deshabilitado",filters:{all:"Todos",vision:"Visión",reasoning:"Razonamiento",free:"Gratuito",tools:"Herramientas"},manualDialog:{title:"Agregar modelo",subtitle:"Agrega un modelo personalizado a este proveedor",modelId:"ID del modelo",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"El identificador exacto del modelo utilizado al llamar a la API",modelName:"Nombre para mostrar",modelNamePlaceholder:"Nombre descriptivo (opcional)",modelNameHelper:"Nombre opcional que se muestra en la interfaz. Si está vacío, se usará el ID del modelo",group:"Grupo",groupPlaceholder:"Selecciona o ingresa un nombre de grupo",submit:"Agregar",cancel:"Cancelar",helper:"Proporciona el identificador exacto del modelo expuesto por la API del proveedor."},editDialog:{title:"Editar modelo",subtitle:"Modificar la configuración del modelo",modelId:"ID del modelo",modelIdPlaceholder:"Identificador del modelo",modelIdHelper:"El identificador del modelo utilizado al llamar a la API",modelName:"Nombre para mostrar",modelNamePlaceholder:"Nombre descriptivo",modelNameHelper:"Nombre que se muestra en la interfaz",group:"Grupo",groupPlaceholder:"Selecciona o ingresa un nombre de grupo",submit:"Guardar",cancel:"Cancelar",vision:"Capacidad de visión",visionHint:"Si este modelo admite entrada de imágenes/visión",reasoning:"Modelo de razonamiento",reasoningHint:"Si este modelo admite el modo de razonamiento/pensamiento"},manageDialog:{title:"Administrar modelos",cachedAt:"En caché el {{date}} ({{source}})",refresh:"Actualizar",close:"Cerrar",raw:"JSON sin procesar",empty:"No hay modelos remotos disponibles.",error:"Error al cargar los modelos: {{message}}",addFromCatalog:"Agregar",sourceCache:"caché",sourceNetwork:"en vivo",contextLength:"Contexto de {{value}} tokens",maxTokens:"Máx. {{value}} tokens"},messages:{added:"Modelo agregado.",updated:"Modelo actualizado.",removed:"Modelo eliminado.",duplicate:"El modelo ya existe.",refreshed:"Modelos actualizados",refreshFailed:"Error al actualizar los modelos"},testDialog:{title:"Prueba de conectividad del modelo",provider:"Proveedor",model:"Modelo",testing:"Probando...",success:"Prueba exitosa",successMessage:"Se puede acceder al modelo con normalidad",failure:"Prueba fallida",aiResponse:"Respuesta de la IA",charCount:"{{count}} caracteres",duration:"Duración {{time}}s",close:"Cerrar",retest:"Volver a probar",testButton:"Probar modelo",unsupportedFormat:"Las pruebas aún no están disponibles para este formato de proveedor."}},router:{title:"Configuración del router",description:"Configura qué proveedor/modelo usar para cada escenario.",labels:{default:"Predeterminado",background:"fondo",think:"razonamiento",longContext:"Contexto largo",webSearch:"Búsqueda web",image:"Imagen",longContextThreshold:"Umbral de contexto largo"},helper:{longContextThreshold:"Cantidad de tokens a partir de la cual se cambia al modelo de contexto largo."},placeholder:{required:"Requerido",optional:"Opcional"}},agentRouter:{title:"Router de agentes",description:"Configura el enrutamiento bidireccional entre los modos Chat y Código.",searchPlaceholder:"Buscar routers...",noSearchResults:"Ningún router coincide con tu búsqueda.",tabs:{chatToCode:"Chat → Código",codeToChatPlaceholder:"Código → Chat"},chatToCode:{title:"Router de Chat a Código",description:"Usar proveedores de chat en modo agente/codificación",addRouter:"Agregar router",emptyState:"No hay routers Chat→Código configurados. Agrega uno para usar proveedores de chat en modo de codificación.",form:{name:"Nombre del router",namePlaceholder:"Mi router Chat→Código",chatProvider:"Proveedor de chat",chatProviderPlaceholder:"Selecciona un proveedor de chat",mode:"Modo",modeSimple:"Simple",modeAdvanced:"Avanzado",modeSimpleDesc:"Paso directo al proveedor de chat",modeAdvancedDesc:"Configurar la asignación de modelos y el manejo del contexto",enabled:"Habilitado",save:"Guardar router",cancel:"Cancelar"},list:{provider:"Proveedor",mode:"Modo",status:"Estado"},mappings:{title:"Asignaciones de modelos",description:"Asigna modelos del proveedor de Chat a modelos del proveedor de Código",count:"asignación(es)",empty:"No hay asignaciones de modelos configuradas. Agrega asignaciones para enrutar modelos de chat a proveedores de código.",addNew:"Agregar nueva asignación",selectSource:"Selecciona el modelo de origen (Chat)",selectTarget:"Selecciona el modelo de destino (Código)",targetPlaceholder:"Ingresa el nombre del modelo de Claude Code",notSet:"(No configurado — haz clic para seleccionar)",add:"Agregar",edit:"Editar",done:"Listo"},advanced:{title:"Configuración avanzada",description:"Configurar modelos para diferentes tipos de tareas",helpText:"El modelo predeterminado es requerido. Los demás modelos son opcionales y usarán el predeterminado si no están configurados.",default:{label:"Predeterminado",placeholder:"Selecciona el modelo predeterminado",description:"Modelo principal para tareas generales (similar a Claude Sonnet)"},background:{label:"Fondo",placeholder:"Selecciona el modelo de fondo",description:"Modelo liviano para tareas en segundo plano (similar a Claude Haiku)"},think:{label:"Razonamiento",placeholder:"Selecciona el modelo de razonamiento",description:"Modelo avanzado para razonamiento complejo (similar a Claude Opus)"},image:{label:"Imagen",placeholder:"Selecciona el modelo de imagen",description:"Modelo para tareas relacionadas con imágenes con capacidad de visión"}}},codeToChat:{title:"Router de Código a Chat",description:"Exponer modelos del Plan de codificación en modo chat",addRouter:"Agregar router",emptyState:"No hay routers Código→Chat configurados. Agrega uno para exponer modelos del Plan de codificación en modo chat.",form:{name:"Nombre del router",namePlaceholder:"Mi router Código→Chat",codeProvider:"Proveedor de código",codeProviderPlaceholder:"Selecciona un proveedor de código",codeProviderHelper:"Selecciona el proveedor de código a usar para la transformación",models:"Modelos del plan de codificación",modelsHelper:"Selecciona los modelos del Plan de codificación que quieres exponer",enabled:"Habilitado",save:"Guardar router",cancel:"Cancelar"},mappings:{title:"Asignaciones de modelos",description:"Asigna modelos del proveedor de Código a modelos del proveedor de Chat para su exposición",count:"asignación(es)",empty:"No hay asignaciones de modelos configuradas. Agrega asignaciones para exponer modelos de código en modo chat.",addNew:"Agregar nueva asignación",selectSource:"Selecciona el modelo de origen (Código)",selectTarget:"Selecciona el modelo de destino (Chat)",sourcePlaceholder:"Ingresa el nombre del modelo de origen",targetPlaceholder:"Ingresa el nombre del modelo de destino",add:"Agregar",edit:"Editar",done:"Listo"}},transformers:{title:"Transformadores",description:"Configura transformadores para la conversión de solicitudes/respuestas",noProvider:"Selecciona un proveedor para configurar los transformadores",empty:"Sin transformadores",count:"{{count}} transformador(es)"},status:{enabled:"Habilitado",disabled:"Deshabilitado"},messages:{routerAdded:"Router agregado exitosamente",routerUpdated:"Router actualizado exitosamente",routerDeleted:"Router eliminado exitosamente",saveFailed:"Error al guardar el router"}},presets:{title:"Agregar proveedor rápidamente",added:"Agregado",add:"Agregar",features:{search:"Búsqueda",vision:"Visión",mcp:"MCP",codingPlan:"Plan de codificación"}},alerts:{deleteConfirm:"¿Estás seguro de que quieres eliminar este proveedor?"},errors:{nameRequired:"El nombre del proveedor es requerido",urlRequired:"La URL base de la API es requerida",urlInvalid:"Ingresa una URL válida (p. ej., https://api.example.com)",saveFailed:"Error al guardar el proveedor",deleteFailed:"Error al eliminar el proveedor. Por favor, intenta de nuevo.",toggleFailed:"Error al activar/desactivar el proveedor. Por favor, intenta de nuevo."},openRouter:{title:"Enrutamiento de proveedores de OpenRouter",description:"Configura cómo se enrutan las solicitudes a los distintos proveedores en OpenRouter.",sort:"Estrategia de enrutamiento",sortTooltip:"Elige cómo priorizar los proveedores. Auto utiliza balanceo de carga inteligente.",order:"Orden de prioridad de proveedores",orderTooltip:"Especifica los proveedores que se intentarán en orden (p. ej., anthropic, openai, together). Presiona Enter para agregar.",orderPlaceholder:"Escribe el slug del proveedor y presiona Enter...",allowFallbacks:"Permitir alternativas",allowFallbacksTooltip:"Cuando está habilitado, OpenRouter intentará proveedores de respaldo si el principal no está disponible.",requireParameters:"Requerir todos los parámetros",requireParametersTooltip:"Solo enrutar a proveedores que admitan todos los parámetros de tu solicitud.",dataCollection:"Política de recopilación de datos",dataCollectionTooltip:"Controla si se usan proveedores que pueden almacenar o entrenar con tus datos.",zdr:"Retención cero de datos",zdrTooltip:"Solo enrutar a endpoints con política de retención cero de datos.",only:"Usar solo estos proveedores",onlyTooltip:"Usar únicamente estos proveedores específicos. Déjalo vacío para permitir todos los proveedores.",onlyPlaceholder:"Escribe el slug del proveedor y presiona Enter...",ignore:"Ignorar proveedores",ignoreTooltip:"Omitir estos proveedores al enrutar las solicitudes.",ignorePlaceholder:"Escribe el slug del proveedor y presiona Enter...",quantizations:"Filtro de cuantización",quantizationsTooltip:"Usar solo proveedores con niveles de cuantización específicos. Una precisión menor puede reducir la calidad pero mejorar la velocidad.",maxPrice:"Precio máximo",maxPriceTooltip:"Establece límites de precio máximo por millón de tokens. Déjalo vacío para sin límite.",configured:"Configurado"}},GC={label:"Modo de API",standard:"Estándar",codingPlan:"Plan de codificación",tokenPlan:"Plan de tokens",apiKeyPrefixHint:"Las claves de este plan suelen comenzar con `{{prefix}}`. Solo orientativo — no se aplica.",dashscopeCodingPlanSeparateKey:"El Plan de codificación de DashScope utiliza una clave de API independiente del endpoint estándar.",baiduCodingPlanSeparateKey:"El Plan de codificación de Qianfan utiliza una clave de API independiente del endpoint estándar.",tencentTokenPlanAnthropicOnly:"El Plan de tokens de Tencent solo es compatible con el protocolo Anthropic.",xiaomiTokenPlanRegions:"La baseUrl predeterminada es `token-plan-cn.*`. Puedes editarla manualmente a `token-plan-sgp.*` o `token-plan-ams.*`.",confirmOverwriteTitle:"¿Cambiar el modo de API?",confirmOverwriteBody:"Personalizaste la URL de la API o la clave de API. Cambiar de modo las sobreescribirá con los valores predeterminados del nuevo modo — o conserva tus personalizaciones y solo actualiza la etiqueta del modo.",overwriteAndSwitch:"Sobreescribir y cambiar",keepCustomizations:"Conservar personalizaciones"},WC={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Plan de tokens)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},ZC={cancel:"Cancelar",close:"Cerrar",copy:"Copiar",delete:"Eliminar",dismiss:"Descartar",save:"Guardar",optional:"opcional",retry:"Reintentar",loading:"Cargando…"},QC={common:{learnMore:"Documentación"}},YC={notSupportedByDaemon:"Aún no compatible con el daemon",discoveryUnsupportedFormat:"El descubrimiento de modelos aún no está disponible para este formato de proveedor. Agrega los modelos manualmente."},XC={subtitle:"Panel de control",providers:"Proveedores",apiService:"Servicio de API",accounts:"Cuentas",codeCli:"CLI de código",settings:"Configuración",usageStats:"Uso",pricing:"Precios"},JC={title:"Servicio de API",description:"Configura el servidor de API saliente, el enrutamiento de modelos por endpoint y las claves de acceso nombradas.",loading:"Cargando configuración del servidor…",loadError:"No se pudo cargar la configuración del servidor. Verifica que el daemon sea accesible.",enable:{label:"Habilitar servidor saliente",description:"Inicia el servidor de API local que enruta las llamadas externas a través de tus proveedores."},networkBinding:{label:"Permitir acceso por red local",description:"Vincula el servidor a tu interfaz de red en lugar de solo a la interfaz de bucle local.",warning:"El acceso por red local expone el servidor de API a otros dispositivos de tu red. Combinado con el enrutamiento de suscripciones, las solicitudes pueden consumir tu cuota de suscripción — mantén esto desactivado a menos que confíes en la red."},status:{running:"Servidor en ejecución",stopped:"Servidor detenido",runningHint:"El servidor de API saliente está aceptando solicitudes.",stoppedHint:"Habilita el servidor para comenzar a aceptar solicitudes.",port:"puerto {{port}}",loopback:"URLs de bucle local",lan:"URLs de red local"},endpoints:{title:"Enrutamiento de endpoints",description:"Elige el modelo al que enruta cada formato de red. El modelo predeterminado se incluye aquí — el servidor es un router, no una app de chat."},endpoint:{name:{chat:"Chat de OpenAI",responses:"Respuestas de OpenAI",messages:"Mensajes de Anthropic",gemini:"Gemini"},defaultModel:"Modelo predeterminado",backgroundModel:"Modelo de fondo",visionModel:"Modelo de visión",noVisionModel:"Ninguno",backgroundModelIds:"IDs de modelos de fondo",backgroundModelIdsPlaceholder:"IDs de modelos separados por comas",modelPlaceholder:"Selecciona un modelo…",useSubscription:"Usar suscripción",subscriptionUnsupported:"El enrutamiento por suscripción no está disponible para este endpoint."},keys:{title:"Claves de acceso",description:"Claves nombradas que los clientes externos envían como token Bearer. La clave completa solo se muestra una vez al crearla.",namePlaceholder:"Nombre de la clave (p. ej., mi-cli)",create:"Crear clave",empty:"Aún no hay claves de acceso.",enabled:"Habilitada",disabled:"Deshabilitada",revoked:"Revocada",toggle:"Activar/desactivar clave",revoke:"Revocar",revokeConfirmTitle:"¿Revocar esta clave?",revokeConfirmDesc:'Revocar "{{name}}" detiene inmediatamente su capacidad de autenticación. Esta acción no se puede deshacer.',created:{title:"Clave creada",warning:"Copia esta clave ahora — no se volverá a mostrar. Guárdala de forma segura.",copy:"Copiar",copied:"Copiada",dismiss:"Listo"}}},ex={title:"Cuentas y suscripciones",description:"Administra las credenciales de suscripción a través de las cuales enruta el servidor. Los tokens se escriben aquí pero nunca se vuelven a mostrar.",loading:"Cargando cuentas…",empty:"No hay proveedores de suscripción disponibles.",signIn:"Iniciar sesión",oauth:{title:"Iniciar sesión en {{name}}",description:"Abre la página de inicio de sesión en tu navegador, autoriza y pega el código de autorización a continuación. El código solo se envía al daemon — el token generado nunca se muestra.",openPage:"Abrir página de inicio de sesión",codeLabel:"Código de autorización",codePlaceholder:"Pega el código aquí",submit:"Completar inicio de sesión"},codexOauth:{title:"Iniciar sesión en {{name}}",description:"Abre la página de inicio de sesión en tu navegador y autoriza. El daemon captura el resultado automáticamente — mantén esta ventana abierta hasta que se complete. El token nunca se muestra.",waiting:"Esperando a que completes el inicio de sesión en tu navegador…",failed:"Error al iniciar sesión. Por favor, intenta de nuevo."},clearProvider:"Borrar todo",clearConfirmTitle:"¿Borrar las cuentas de {{name}}?",clearConfirmDesc:"Esto elimina todas las credenciales almacenadas para este proveedor. Esta acción no se puede deshacer.",credential:{ok:"Configurada",notConfigured:"No configurada"},kind:{"pass-through":"Credenciales de paso directo","oauth-bearer":"Bearer OAuth","static-bearer":"Clave bearer estática"},reason:{"missing-credential":"No hay credenciales almacenadas.",expired:"La credencial expiró.","reauth-required":"Se requiere reautenticación.","refresh-failed":"Error al renovar el token.","not-refreshable":"La credencial no se puede renovar.",unknown:"Estado desconocido."},status:{unconfigured:"Sin configurar",authorized:"Autorizada",configured:"Configurada",expired:"Expirada",error:"Error"},authMethod:{oauth:"OAuth",setup_token:"Token de configuración",manual:"Manual"},list:{empty:"No hay cuentas almacenadas para este proveedor.",active:"Activa",expiresAt:"Expira {{value}}",setActive:"Establecer como activa",remove:"Eliminar",removeConfirmTitle:"¿Eliminar esta cuenta?",removeConfirmDesc:'Eliminar "{{name}}" borra su credencial almacenada. Esta acción no se puede deshacer.',title:"Cuentas"},write:{trigger:"Agregar credencial",title:"Escribir credencial de {{name}}",description:"Pega el material del token ya obtenido. Los campos están limitados a lo que acepta este proveedor; el token se almacena y nunca se vuelve a mostrar.",authMethod:"Método de autenticación",status:"Estado",subscriptionLevel:"Nivel de suscripción",subscriptionLevelNone:"Sin definir",submit:"Guardar credencial"},field:{accessToken:"Token de acceso",refreshToken:"Token de actualización",idToken:"Token de ID",apiKey:"Clave de API",expiresAt:"Expira en (ISO)",setupTokenExpiresAt:"El token de configuración expira en (ISO)",accountId:"ID de cuenta",email:"Correo electrónico",organizationId:"ID de organización",baseUrl:"URL base",zenBaseUrl:"URL base de Zen"},provider:{claude:{title:"Claude",description:"Credenciales de suscripción de Anthropic enrutadas por el daemon."},codex:{title:"Codex",description:"Credenciales de suscripción de OpenAI Codex enrutadas por el daemon."},gemini:{title:"Gemini",description:"Credenciales de suscripción de Google Gemini enrutadas por el daemon."},opencodego:{title:"OpenCodeGo",description:"Credenciales de clave de API estática enrutadas por el daemon."}},authMethodLabel:"Método de autorización",authMethodDesc:{oauth:"Inicia sesión a través de tu navegador; el daemon captura y almacena el token.",manual:"Pega un token ya obtenido. Se almacena y nunca se vuelve a mostrar."},actions:{authorize:"Autorizar",enterToken:"Ingresar token",refresh:"Actualizar"},accounts:{addAccount:"Agregar cuenta"},detail:{authMethod:"Método de autorización",subscriptionLevel:"Nivel de suscripción",expiresAt:"Expira",lastRefreshed:"Última actualización",label:"Etiqueta de cuenta",labelPlaceholder:"Nombra esta cuenta",saveLabel:"Guardar etiqueta"},oauthFlow:{step1:{title:"Abre la página de autorización",desc:"Abre la página de inicio de sesión en tu navegador."},step2:{title:"Autoriza el acceso",desc:"Inicia sesión y aprueba el acceso para el proveedor."},step3:{title:"Copia el código de autorización",desc:"La página muestra un código de autorización tras tu aprobación."},step4:{title:"Pega el código",desc:"Pega el código de autorización a continuación para finalizar. El código solo se envía al daemon — el token generado nunca se muestra."},authorize:"Completar inicio de sesión",showUrl:"Mostrar URL de autorización"},manual:{title:"Pegar credencial",description:"Pega un token ya obtenido. Los campos están limitados a lo que acepta este proveedor; el token se almacena y nunca se vuelve a mostrar.",accessTokenPlaceholder:"Pega el token de acceso",refreshTokenPlaceholder:"Pega el token de actualización (opcional)",hint:"El token se envía al daemon y se almacena cifrado. Nunca se vuelve a mostrar."},openCodeGo:{apiKeyRequired:"Se requiere una clave de API.",apiKeyPlaceholder:"Pega la clave de API",baseUrlPlaceholder:"https://… (opcional)",zenBaseUrlPlaceholder:"https://… (opcional)"},info:{title:"Acerca de las cuentas de suscripción",description:"Los tokens se escriben en el daemon y se usan para autenticar las solicitudes de destino. Se almacenan cifrados y nunca se vuelven a mostrar. Eliminar una cuenta borra su credencial almacenada."},rename:{failed:"No se pudo cambiar el nombre de la cuenta."},refresh:{failed:"No se pudo actualizar el token."},errors:{requestFailed:"La solicitud falló. Por favor, intenta de nuevo."},syncWarning:{"external-divergent":"El archivo de inicio de sesión de la CLI externa contiene credenciales más recientes que esta cuenta. El token guardado podría dejar de renovarse: renueva ahora o vuelve a iniciar sesión.","external-not-rotated":"La renovación falló y la CLI externa contiene las mismas credenciales vencidas. Vuelve a iniciar sesión.","duplicate-token":"Otra cuenta comparte estas credenciales. Renovar cualquiera de las dos invalidará la otra."},importExternal:{detected:"Se encontró una sesión de CLI de {{name}} existente en esta máquina.",hint:"Tras la importación, esta aplicación la mantiene actualizada: en cada renovación del token también se actualiza el archivo de sesión de la CLI, de modo que la CLI de la terminal sigue conectada.",button:"Importar sesión de CLI existente"}},tx={title:"CLI de código",description:"Apunta una CLI de codificación al proxy saliente del daemon. Esta página es de solo lectura — no hay nada que configurar aquí.",copy:"Copiar",copied:"Copiado",baseUrl:{title:"URL base del daemon",description:"La dirección del proxy a la que se conecta tu CLI.",label:"URL base"},token:{title:"Autenticación",hint:"Envía 'Authorization: Bearer <tu-token-de-administración>' para las rutas de administración. El token de administración se configura en el daemon (su archivo de configuración o entorno) — nunca se muestra aquí."},examples:{title:"Entorno de lanzamiento de ejemplo",keyNote:"Usa una clave de acceso saliente creada en la página del Servicio de API — no el token de administración.",anthropic:"CLI en formato Anthropic",openai:"CLI en formato OpenAI"},launchDescription:"Lanza una CLI de codificación en una terminal apuntada a este daemon. El daemon inyecta el entorno de redirección e inicia la CLI automáticamente.",refresh:"Actualizar",loading:"Detectando CLIs…",cli:{installed:"Instalada",notFound:"No encontrada",notFoundHint:"Esta CLI no está en el PATH del host del daemon. Instálala y luego actualiza.",install:"Instalar",installing:"Instalando…",installingHint:"Instalando en el host del daemon — esto puede tardar un momento.",launch:"Lanzar",launchTitle:"Lanzar {{name}}",launchDescription:"Abre una nueva terminal en el host del daemon ejecutando esta CLI, enrutada a través del proxy del daemon. Elige un directorio de trabajo opcional.",cwdLabel:"Directorio de trabajo",cwdPlaceholder:"/ruta/a/tu/proyecto",runningVia:"En ejecución · {{provider}} / {{model}}",stop:"Detener"},manual:{title:"Configuración manual",description:"¿Prefieres ejecutar la CLI tú mismo? Apúntala al daemon con estas variables de entorno.",show:"Mostrar",hide:"Ocultar"}},ax={probing:"Verificando si el daemon está disponible…",spawning:"Iniciando el daemon…",failed:"El daemon no pudo iniciarse",failedHint:"Asegúrate de que Node.js esté instalado y el daemon esté compilado (dist presente), o establece OMNICROSS_DAEMON_ENTRY en el cli.js del daemon."},nx={title:"Configuración",description:"Preferencias de la aplicación de escritorio.",desktopOnly:"Las opciones de inicio y bandeja solo se aplican en la aplicación de escritorio.",startup:{title:"Inicio",autoLaunch:"Iniciar al arrancar",autoLaunchHint:"Inicia Omnicross automáticamente cuando inicias sesión.",startMinimized:"Iniciar minimizado en la bandeja",startMinimizedHint:"Lanza en segundo plano sin abrir la ventana."},tray:{title:"Bandeja del sistema",minimizeOnClose:"Minimizar a la bandeja al cerrar",minimizeOnCloseHint:"Cerrar la ventana la oculta en la bandeja en lugar de salir."},language:{title:"Idioma",label:"Idioma de la interfaz"}},ox={title:"Estadísticas de uso",description:"Estadísticas de tokens y costos de las solicitudes atendidas por el daemon.",rangeToday:"Hoy",range7d:"Últimos 7 días",range30d:"Últimos 30 días",rangeCustom:"Personalizado",from:"Desde",to:"Hasta",totalCost:"Costo total",cacheSavings:"Ahorro por caché",events:"Solicitudes",inputTokens:"Tokens de entrada",outputTokens:"Tokens de salida",cacheReadTokens:"Lectura de caché",cacheWriteTokens:"Escritura de caché",reasoningTokens:"Tokens de razonamiento",byModel:"Por modelo",byApiKey:"Por clave API",provider:"Proveedor",model:"Modelo",cost:"Costo",apiKey:"Clave API",unpriced:"Sin precio",unpricedHint:"No existe una entrada de precio para este modelo — agrégala en la página de Precios.",unattributed:"Sin atribuir",unattributedHint:"Solicitudes no vinculadas a una clave API concreta. Es lo esperado hasta que se registre la atribución por clave.",empty:"No hay solicitudes en este rango.",invalidRange:"Selecciona un rango de fechas válido."},ix={title:"Precios de modelos",description:"Precios de tokens por modelo usados para calcular el costo de las solicitudes, en USD por millón de tokens.",search:"Buscar proveedor o modelo…",fetchLatest:"Obtener los últimos",fetching:"Obteniendo…",addEntry:"Agregar entrada",provider:"Proveedor",model:"Modelo",inputPrice:"Entrada",outputPrice:"Salida",cacheReadPrice:"Lectura de caché",cacheWritePrice:"Escritura de caché",source:"Fuente",updated:"Actualizado",userEdited:"editado",edit:"Editar",deleteTitle:"¿Eliminar esta entrada de precio?",empty:"La tabla de precios está vacía.",emptyHint:"Obtén los últimos precios para llenarla.",noMatches:"Ninguna entrada coincide con tu búsqueda.",saved:"Entrada de precio guardada.",saveFailed:"Error al guardar: {{message}}",deleteFailed:"Error al eliminar: {{message}}",alreadyDeleted:"La entrada ya no existía.",fetchApplied:"Se actualizaron {{count}} entradas desde la fuente.",fetchFailed:"Error al obtener: {{message}}",requiredId:"Obligatorio",invalidPrice:"Introduce un número no negativo",conflictTitle:"Resolver conflictos de precios",conflictHint:"Estas entradas fueron editadas por ti y también cambiaron en la fuente. Elige por fila si conservar tu valor (Omitir) o tomar el entrante (Sobrescribir).",current:"Actual",incoming:"Entrante",overwrite:"Sobrescribir",skip:"Omitir",overwriteAll:"Sobrescribir todo",skipAll:"Omitir todo",applyResolutions:"Aplicar",resolved:"{{overwritten}} sobrescritas, {{skipped}} omitidas.",resolvedWithStale:"{{overwritten}} sobrescritas, {{skipped}} omitidas. {{stale}} cambiaron mientras tanto y quedaron intactas.",refreshFailed:"El cambio se aplicó, pero no se pudo recargar la lista: {{message}}",sourceBuiltin:"Integrado",sourceLitellm:"LiteLLM",sourceUser:"Usuario"},rx={providerSettings:_C,apiMode:GC,presetName:WC,common:ZC,mediaSettings:QC,appLocal:YC,nav:XC,apiService:JC,accounts:ex,codeCli:tx,daemonStatus:ax,settings:nx,usageStats:ox,pricing:ix},sx={loading:"Cargando configuración de LLM...",reset:{button:"Restaurar valores predeterminados",confirmTitle:"¿Restaurar la configuración predeterminada?",confirmBody:"Esto borra tus personalizaciones para este proveedor y vuelve a los valores predeterminados integrados. Tu clave de API y las sesiones guardadas se conservan.",confirmButton:"Restaurar valores predeterminados"},reentryBanner:{message:"{{count}} proveedor(es) habilitado(s) necesita(n) que se vuelva a introducir su clave de API. Abre cada uno y añade su clave de nuevo."},migrationPack:{barHint:"Mueve tus claves de proveedor y tokens de suscripción a otro ordenador con un paquete cifrado.",passphrase:"Contraseña",passphrasePlaceholder:"Introduce una contraseña",passphraseHint:"Usa al menos 8 caracteres; se recomiendan 12 o más.",confirm:"Confirmar contraseña",confirmPlaceholder:"Vuelve a introducir la contraseña",mismatch:"Las contraseñas no coinciden.",strength:{weak:"Demasiado corta — usa al menos 8 caracteres.",fair:"Aceptable — 12 o más caracteres es más seguro.",strong:"Contraseña segura."},export:{button:"Exportar paquete",title:"Exportar paquete cifrado",subtitle:"Cifra tus claves de proveedor y tokens de suscripción en un archivo portátil.",warning:"Este archivo contiene secretos descifRables. Guárdalo de forma segura — cualquiera que tenga el archivo y la contraseña puede leer tus claves. Una contraseña perdida no se puede recuperar.",submit:"Exportar",success:"Paquete exportado correctamente.",error:"Error al exportar. Por favor, inténtalo de nuevo."},import:{button:"Importar paquete",title:"Importar paquete cifrado",subtitle:"Restaura las claves de proveedor y los tokens de suscripción desde un paquete exportado.",hint:"Introduce la contraseña utilizada al exportar el paquete y, a continuación, elige el archivo.",submit:"Importar",successTitle:"Importación completada",summary:"Se han importado {{providerKeys}} clave(s) de proveedor, {{poolKeys}} clave(s) de grupo y {{tokenSets}} conjunto(s) de tokens.",duplicates:"Se han omitido {{count}} clave(s) de grupo ya presentes.",skipped:"Omitido (sin proveedor coincidente): {{names}}",error:"Contraseña incorrecta o paquete dañado. No se realizaron cambios."}},searchPlaceholder:"Buscar proveedores...",emptySearch:"Ningún proveedor coincide con tu búsqueda.",emptyList:"No hay proveedores configurados.",selectPrompt:"Selecciona un proveedor para ver los detalles",listStatus:"{{count}} modelo(s)",noModels:"No hay modelos configurados",enabled:"Habilitado",disabled:"Deshabilitado",showEnabledOnly:"Mostrar solo habilitados",showAll:"Mostrar todos los proveedores",dragHandle:"Arrastra para reordenar",reorderFailed:"Error al guardar el orden de los proveedores",credentials:{apiKey:"Clave de API",apiBaseUrl:"URL base de la API"},filter:{all:"Todos",chat:"Chat",code:"Código"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Selecciona una plantilla",skipTemplates:"Omitir, configurar manualmente",name:"Nombre *",providerType:"Tipo",apiType:"Tipo de API",apiTypeOptions:{openai:"Completado OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Formato estándar de API chat/completions de OpenAI",claudecode:"Formato de API de mensajes de Anthropic (Claude Code)"},chatApiFormat:"Formato de API",chatApiFormatDescription:"Selecciona el formato de API que corresponde al endpoint de tu proveedor",apiKey:"Clave de API",apiKeyPlaceholder:"sk-... o $ENV_VAR",apiKeyHelper:"Usa $VAR_NAME para referenciar variables de entorno",apiKeySetPlaceholder:"La clave está configurada — déjalo en blanco para conservarla",apiKeyReplaceHelper:"Hay una clave almacenada de forma segura. Escribe un nuevo valor para reemplazarla o déjalo en blanco para conservarla.",testApiKey:"Probar clave de API",apiUrl:"URL de la API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Vista previa:",models:"Modelos",modelPlaceholder:"Nombre del modelo (p. ej., gpt-4, claude-3-opus)",transformers:"Transformadores",transformerConfig:"Transformadores de API",transformerConfigDescription:"Configura transformadores para adaptar los formatos de solicitud/respuesta de la API de este proveedor",transformerConfigNote:"El daemon aplica estos transformadores en la cadena de solicitudes, después del transformador de formato del proveedor (que gestiona la conversión del formato de red). Los nombres de transformadores desconocidos se omiten.",enabled:"Habilitado",apiVersion:"Versión de la API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versión de la API de Azure OpenAI (p. ej., 2024-08-01-preview)",official:"API oficial de Anthropic",officialHelper:"Habilita esta opción si el proveedor se conecta directamente a la API oficial de Anthropic. Desactívala para proxies inversos o servicios de terceros.",maxConcurrency:"Máximo de solicitudes simultáneas",maxConcurrencyHelper:"Número máximo de solicitudes de API simultáneas enviadas a este proveedor. Valores más bajos ayudan a evitar la limitación de velocidad (errores 429). Establece `-1` para sin límite.",codingPlan:{label:"Plan de codificación",description:"Usar un endpoint de API independiente para planes de codificación basados en suscripción",baseUrl:"URL base del plan de codificación",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Clave de API del plan de codificación (opcional)",apiKeyPlaceholder:"Déjalo vacío para usar la clave de API del proveedor",apiKeyHelper:"Solo es necesaria si el plan de codificación utiliza una clave de API diferente",tokenPlanHint:"Algunos proveedores (p. ej., Xiaomi MiMo) emiten claves de Plan de tokens con el prefijo `tp-` — solo informativo, no se aplica."},selectTypeFirst:"Selecciona el tipo de proveedor",selectTypeFirstDesc:"Elige qué tipo de proveedor deseas añadir",codeProviderNote:"Los proveedores de código solo necesitan clave de API y URL. Los modelos son gestionados por el router de agentes.",buttons:{cancel:"Cancelar",submitAdd:"Añadir proveedor",submitUpdate:"Actualizar proveedor",continue:"Continuar",back:"Atrás"}},details:{noSelection:"Selecciona un proveedor para ver los detalles",apiKey:"Clave de API",apiUrl:"URL de la API",nameLabel:"Nombre del proveedor",modelsEndpoint:"Endpoint de modelos",modelsEndpointHelper:"Anula el endpoint de descubrimiento si el proveedor expone una ruta /models personalizada.",models:"Modelos",transformers:"Transformadores",codeProviderNote:"Los proveedores de código (como Claude Code) no requieren configuración de modelos. Los modelos son gestionados automáticamente por el router de agentes.",buttons:{more:"Más ajustes",delete:"Eliminar"}},providerModelSelector:{placeholder:"Selecciona proveedor y modelo",noProviders:"No hay proveedores disponibles",noModels:"No hay modelos configurados"},apiKeyPool:{title:"Grupo de claves de API",description:"Configura varias claves de API para el equilibrio de carga. Cada sesión se mantiene en una clave para conservar la caché de prompts.",defaultLabel:"Predeterminada",weight:"Peso",noKey:"Sin clave",labelPlaceholder:"Etiqueta (p. ej., Clave n.º 1, Producción)",addKey:"Añadir clave de API",add:"Añadir",empty:"No hay claves adicionales configuradas.",statusCoolingDown:"En enfriamiento {{time}}",statusAuthFailed:"Autenticación fallida · deshabilitada",statusDisabled:"Deshabilitada",statusHealthy:"En buen estado",agoSeconds:"hace {{count}}s",agoMinutes:"hace {{count}}m",agoHours:"hace {{count}}h",agoDays:"hace {{count}}d"},modelsManager:{searchPlaceholder:"Buscar modelos...",defaultGroup:"Todos los modelos",add:"Añadir modelo",manage:"Gestionar",empty:"No hay modelos en este grupo",enabled:"Habilitado",disabled:"Deshabilitado",filters:{all:"Todos",vision:"Visión",reasoning:"Razonamiento",free:"Gratuito",tools:"Herramientas"},manualDialog:{title:"Añadir modelo",subtitle:"Añade un modelo personalizado a este proveedor",modelId:"ID del modelo",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"El identificador exacto del modelo utilizado al llamar a la API",modelName:"Nombre para mostrar",modelNamePlaceholder:"Nombre descriptivo (opcional)",modelNameHelper:"Nombre opcional que se muestra en la interfaz. Si está vacío, se usará el ID del modelo",group:"Grupo",groupPlaceholder:"Selecciona o introduce un nombre de grupo",submit:"Añadir",cancel:"Cancelar",helper:"Proporciona el identificador exacto del modelo expuesto por la API del proveedor."},editDialog:{title:"Editar modelo",subtitle:"Modificar la configuración del modelo",modelId:"ID del modelo",modelIdPlaceholder:"Identificador del modelo",modelIdHelper:"El identificador del modelo utilizado al llamar a la API",modelName:"Nombre para mostrar",modelNamePlaceholder:"Nombre descriptivo",modelNameHelper:"Nombre que se muestra en la interfaz",group:"Grupo",groupPlaceholder:"Selecciona o introduce un nombre de grupo",submit:"Guardar",cancel:"Cancelar",vision:"Capacidad de visión",visionHint:"Si este modelo admite entrada de imágenes/visión",reasoning:"Modelo de razonamiento",reasoningHint:"Si este modelo admite el modo de razonamiento/pensamiento"},manageDialog:{title:"Gestionar modelos",cachedAt:"En caché el {{date}} ({{source}})",refresh:"Actualizar",close:"Cerrar",raw:"JSON sin procesar",empty:"No hay modelos remotos disponibles.",error:"Error al cargar los modelos: {{message}}",addFromCatalog:"Añadir",sourceCache:"caché",sourceNetwork:"en vivo",contextLength:"Contexto de {{value}} tokens",maxTokens:"Máx. {{value}} tokens"},messages:{added:"Modelo añadido.",updated:"Modelo actualizado.",removed:"Modelo eliminado.",duplicate:"El modelo ya existe.",refreshed:"Modelos actualizados",refreshFailed:"Error al actualizar los modelos"},testDialog:{title:"Prueba de conectividad del modelo",provider:"Proveedor",model:"Modelo",testing:"Probando...",success:"Prueba superada",successMessage:"Se puede acceder al modelo con normalidad",failure:"Prueba fallida",aiResponse:"Respuesta de la IA",charCount:"{{count}} caracteres",duration:"Duración {{time}}s",close:"Cerrar",retest:"Volver a probar",testButton:"Probar modelo",unsupportedFormat:"Las pruebas aún no están disponibles para este formato de proveedor."}},router:{title:"Configuración del router",description:"Configura qué proveedor/modelo usar para cada escenario.",labels:{default:"Predeterminado",background:"fondo",think:"razonamiento",longContext:"Contexto largo",webSearch:"Búsqueda web",image:"Imagen",longContextThreshold:"Umbral de contexto largo"},helper:{longContextThreshold:"Número de tokens a partir del cual se cambia al modelo de contexto largo."},placeholder:{required:"Obligatorio",optional:"Opcional"}},agentRouter:{title:"Router de agentes",description:"Configura el enrutamiento bidireccional entre los modos Chat y Código.",searchPlaceholder:"Buscar routers...",noSearchResults:"Ningún router coincide con tu búsqueda.",tabs:{chatToCode:"Chat → Código",codeToChatPlaceholder:"Código → Chat"},chatToCode:{title:"Router de Chat a Código",description:"Usar proveedores de chat en modo agente/codificación",addRouter:"Añadir router",emptyState:"No hay routers Chat→Código configurados. Añade uno para usar proveedores de chat en modo de codificación.",form:{name:"Nombre del router",namePlaceholder:"Mi router Chat→Código",chatProvider:"Proveedor de chat",chatProviderPlaceholder:"Selecciona un proveedor de chat",mode:"Modo",modeSimple:"Simple",modeAdvanced:"Avanzado",modeSimpleDesc:"Paso directo al proveedor de chat",modeAdvancedDesc:"Configurar la asignación de modelos y el manejo del contexto",enabled:"Habilitado",save:"Guardar router",cancel:"Cancelar"},list:{provider:"Proveedor",mode:"Modo",status:"Estado"},mappings:{title:"Asignaciones de modelos",description:"Asigna modelos del proveedor de Chat a modelos del proveedor de Código",count:"asignación(es)",empty:"No hay asignaciones de modelos configuradas. Añade asignaciones para enrutar modelos de chat a proveedores de código.",addNew:"Añadir nueva asignación",selectSource:"Selecciona el modelo de origen (Chat)",selectTarget:"Selecciona el modelo de destino (Código)",targetPlaceholder:"Introduce el nombre del modelo de Claude Code",notSet:"(No configurado — haz clic para seleccionar)",add:"Añadir",edit:"Editar",done:"Hecho"},advanced:{title:"Configuración avanzada",description:"Configurar modelos para diferentes tipos de tareas",helpText:"El modelo predeterminado es obligatorio. Los demás modelos son opcionales y usarán el predeterminado si no están configurados.",default:{label:"Predeterminado",placeholder:"Selecciona el modelo predeterminado",description:"Modelo principal para tareas generales (similar a Claude Sonnet)"},background:{label:"Fondo",placeholder:"Selecciona el modelo de fondo",description:"Modelo ligero para tareas en segundo plano (similar a Claude Haiku)"},think:{label:"Razonamiento",placeholder:"Selecciona el modelo de razonamiento",description:"Modelo avanzado para razonamiento complejo (similar a Claude Opus)"},image:{label:"Imagen",placeholder:"Selecciona el modelo de imagen",description:"Modelo para tareas relacionadas con imágenes con capacidad de visión"}}},codeToChat:{title:"Router de Código a Chat",description:"Exponer modelos del Plan de codificación en modo chat",addRouter:"Añadir router",emptyState:"No hay routers Código→Chat configurados. Añade uno para exponer modelos del Plan de codificación en modo chat.",form:{name:"Nombre del router",namePlaceholder:"Mi router Código→Chat",codeProvider:"Proveedor de código",codeProviderPlaceholder:"Selecciona un proveedor de código",codeProviderHelper:"Selecciona el proveedor de código a usar para la transformación",models:"Modelos del plan de codificación",modelsHelper:"Selecciona los modelos del Plan de codificación que quieres exponer",enabled:"Habilitado",save:"Guardar router",cancel:"Cancelar"},mappings:{title:"Asignaciones de modelos",description:"Asigna modelos del proveedor de Código a modelos del proveedor de Chat para su exposición",count:"asignación(es)",empty:"No hay asignaciones de modelos configuradas. Añade asignaciones para exponer modelos de código en modo chat.",addNew:"Añadir nueva asignación",selectSource:"Selecciona el modelo de origen (Código)",selectTarget:"Selecciona el modelo de destino (Chat)",sourcePlaceholder:"Introduce el nombre del modelo de origen",targetPlaceholder:"Introduce el nombre del modelo de destino",add:"Añadir",edit:"Editar",done:"Hecho"}},transformers:{title:"Transformadores",description:"Configura transformadores para la conversión de solicitudes/respuestas",noProvider:"Selecciona un proveedor para configurar los transformadores",empty:"Sin transformadores",count:"{{count}} transformador(es)"},status:{enabled:"Habilitado",disabled:"Deshabilitado"},messages:{routerAdded:"Router añadido correctamente",routerUpdated:"Router actualizado correctamente",routerDeleted:"Router eliminado correctamente",saveFailed:"Error al guardar el router"}},presets:{title:"Añadir proveedor rápidamente",added:"Añadido",add:"Añadir",features:{search:"Búsqueda",vision:"Visión",mcp:"MCP",codingPlan:"Plan de codificación"}},alerts:{deleteConfirm:"¿Estás seguro de que quieres eliminar este proveedor?"},errors:{nameRequired:"El nombre del proveedor es obligatorio",urlRequired:"La URL base de la API es obligatoria",urlInvalid:"Introduce una URL válida (p. ej., https://api.example.com)",saveFailed:"Error al guardar el proveedor",deleteFailed:"Error al eliminar el proveedor. Por favor, inténtalo de nuevo.",toggleFailed:"Error al activar/desactivar el proveedor. Por favor, inténtalo de nuevo."},openRouter:{title:"Enrutamiento de proveedores de OpenRouter",description:"Configura cómo se enrutan las solicitudes a los distintos proveedores en OpenRouter.",sort:"Estrategia de enrutamiento",sortTooltip:"Elige cómo priorizar los proveedores. Auto utiliza equilibrio de carga inteligente.",order:"Orden de prioridad de proveedores",orderTooltip:"Especifica los proveedores que se intentarán en orden (p. ej., anthropic, openai, together). Pulsa Intro para añadir.",orderPlaceholder:"Escribe el slug del proveedor y pulsa Intro...",allowFallbacks:"Permitir alternativas",allowFallbacksTooltip:"Cuando está habilitado, OpenRouter intentará proveedores de respaldo si el principal no está disponible.",requireParameters:"Requerir todos los parámetros",requireParametersTooltip:"Solo enrutar a proveedores que admitan todos los parámetros de tu solicitud.",dataCollection:"Política de recopilación de datos",dataCollectionTooltip:"Controla si se usan proveedores que pueden almacenar o entrenar con tus datos.",zdr:"Retención cero de datos",zdrTooltip:"Solo enrutar a endpoints con política de retención cero de datos.",only:"Usar solo estos proveedores",onlyTooltip:"Usar únicamente estos proveedores específicos. Déjalo vacío para permitir todos los proveedores.",onlyPlaceholder:"Escribe el slug del proveedor y pulsa Intro...",ignore:"Ignorar proveedores",ignoreTooltip:"Omitir estos proveedores al enrutar las solicitudes.",ignorePlaceholder:"Escribe el slug del proveedor y pulsa Intro...",quantizations:"Filtro de cuantización",quantizationsTooltip:"Usar solo proveedores con niveles de cuantización específicos. Una precisión menor puede reducir la calidad pero mejorar la velocidad.",maxPrice:"Precio máximo",maxPriceTooltip:"Establece límites de precio máximo por millón de tokens. Déjalo vacío para sin límite.",configured:"Configurado"}},lx={label:"Modo de API",standard:"Estándar",codingPlan:"Plan de codificación",tokenPlan:"Plan de tokens",apiKeyPrefixHint:"Las claves de este plan suelen comenzar con `{{prefix}}`. Solo orientativo — no se aplica.",dashscopeCodingPlanSeparateKey:"El Plan de codificación de DashScope utiliza una clave de API independiente del endpoint estándar.",baiduCodingPlanSeparateKey:"El Plan de codificación de Qianfan utiliza una clave de API independiente del endpoint estándar.",tencentTokenPlanAnthropicOnly:"El Plan de tokens de Tencent solo es compatible con el protocolo Anthropic.",xiaomiTokenPlanRegions:"La baseUrl predeterminada es `token-plan-cn.*`. Puedes editarla manualmente a `token-plan-sgp.*` o `token-plan-ams.*`.",confirmOverwriteTitle:"¿Cambiar el modo de API?",confirmOverwriteBody:"Has personalizado la URL de la API o la clave de API. Cambiar de modo las sobreescribirá con los valores predeterminados del nuevo modo — o conserva tus personalizaciones y solo actualiza la etiqueta del modo.",overwriteAndSwitch:"Sobreescribir y cambiar",keepCustomizations:"Conservar personalizaciones"},dx={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Plan de tokens)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},cx={cancel:"Cancelar",close:"Cerrar",copy:"Copiar",delete:"Eliminar",dismiss:"Descartar",save:"Guardar",optional:"opcional",retry:"Reintentar",loading:"Cargando…"},ux={common:{learnMore:"Documentación"}},px={notSupportedByDaemon:"Aún no compatible con el daemon",discoveryUnsupportedFormat:"El descubrimiento de modelos aún no está disponible para este formato de proveedor. Añade los modelos manualmente."},mx={subtitle:"Panel de control",providers:"Proveedores",apiService:"Servicio de API",accounts:"Cuentas",codeCli:"CLI de código",settings:"Ajustes",usageStats:"Uso",pricing:"Precios"},gx={title:"Servicio de API",description:"Configura el servidor de API saliente, el enrutamiento de modelos por endpoint y las claves de acceso nombradas.",loading:"Cargando configuración del servidor…",loadError:"No se pudo cargar la configuración del servidor. Comprueba que el daemon sea accesible.",enable:{label:"Habilitar servidor saliente",description:"Inicia el servidor de API local que enruta las llamadas externas a través de tus proveedores."},networkBinding:{label:"Permitir acceso por red local",description:"Vincula el servidor a tu interfaz de red en lugar de solo a la interfaz de bucle local.",warning:"El acceso por red local expone el servidor de API a otros dispositivos de tu red. Combinado con el enrutamiento de suscripciones, las solicitudes pueden consumir tu cuota de suscripción — mantén esto desactivado a menos que confíes en la red."},status:{running:"Servidor en ejecución",stopped:"Servidor detenido",runningHint:"El servidor de API saliente está aceptando solicitudes.",stoppedHint:"Habilita el servidor para comenzar a aceptar solicitudes.",port:"puerto {{port}}",loopback:"URLs de bucle local",lan:"URLs de red local"},endpoints:{title:"Enrutamiento de endpoints",description:"Elige el modelo al que enruta cada formato de red. El modelo predeterminado se incluye aquí — el servidor es un router, no una aplicación de chat."},endpoint:{name:{chat:"Chat de OpenAI",responses:"Respuestas de OpenAI",messages:"Mensajes de Anthropic",gemini:"Gemini"},defaultModel:"Modelo predeterminado",backgroundModel:"Modelo de fondo",visionModel:"Modelo de visión",noVisionModel:"Ninguno",backgroundModelIds:"IDs de modelos de fondo",backgroundModelIdsPlaceholder:"IDs de modelos separados por comas",modelPlaceholder:"Selecciona un modelo…",useSubscription:"Usar suscripción",subscriptionUnsupported:"El enrutamiento por suscripción no está disponible para este endpoint."},keys:{title:"Claves de acceso",description:"Claves nombradas que los clientes externos envían como token Bearer. La clave completa solo se muestra una vez al crearla.",namePlaceholder:"Nombre de la clave (p. ej., mi-cli)",create:"Crear clave",empty:"Aún no hay claves de acceso.",enabled:"Habilitada",disabled:"Deshabilitada",revoked:"Revocada",toggle:"Activar/desactivar clave",revoke:"Revocar",revokeConfirmTitle:"¿Revocar esta clave?",revokeConfirmDesc:'Revocar "{{name}}" detiene inmediatamente su capacidad de autenticación. Esta acción no se puede deshacer.',created:{title:"Clave creada",warning:"Copia esta clave ahora — no se volverá a mostrar. Guárdala de forma segura.",copy:"Copiar",copied:"Copiada",dismiss:"Listo"}}},hx={title:"Cuentas y suscripciones",description:"Gestiona las credenciales de suscripción a través de las cuales enruta el servidor. Los tokens se escriben aquí pero nunca se vuelven a mostrar.",loading:"Cargando cuentas…",empty:"No hay proveedores de suscripción disponibles.",signIn:"Iniciar sesión",oauth:{title:"Iniciar sesión en {{name}}",description:"Abre la página de inicio de sesión en tu navegador, autoriza y pega el código de autorización a continuación. El código solo se envía al daemon — el token generado nunca se muestra.",openPage:"Abrir página de inicio de sesión",codeLabel:"Código de autorización",codePlaceholder:"Pega el código aquí",submit:"Completar inicio de sesión"},codexOauth:{title:"Iniciar sesión en {{name}}",description:"Abre la página de inicio de sesión en tu navegador y autoriza. El daemon captura el resultado automáticamente — mantén esta ventana abierta hasta que se complete. El token nunca se muestra.",waiting:"Esperando a que completes el inicio de sesión en tu navegador…",failed:"Error al iniciar sesión. Por favor, inténtalo de nuevo."},clearProvider:"Borrar todo",clearConfirmTitle:"¿Borrar las cuentas de {{name}}?",clearConfirmDesc:"Esto elimina todas las credenciales almacenadas para este proveedor. Esta acción no se puede deshacer.",credential:{ok:"Configurada",notConfigured:"No configurada"},kind:{"pass-through":"Credenciales de paso directo","oauth-bearer":"Bearer OAuth","static-bearer":"Clave bearer estática"},reason:{"missing-credential":"No hay credenciales almacenadas.",expired:"La credencial ha caducado.","reauth-required":"Se requiere reautenticación.","refresh-failed":"Error al renovar el token.","not-refreshable":"La credencial no se puede renovar.",unknown:"Estado desconocido."},status:{unconfigured:"Sin configurar",authorized:"Autorizada",configured:"Configurada",expired:"Caducada",error:"Error"},authMethod:{oauth:"OAuth",setup_token:"Token de configuración",manual:"Manual"},list:{empty:"No hay cuentas almacenadas para este proveedor.",active:"Activa",expiresAt:"Caduca {{value}}",setActive:"Establecer como activa",remove:"Eliminar",removeConfirmTitle:"¿Eliminar esta cuenta?",removeConfirmDesc:'Eliminar "{{name}}" borra su credencial almacenada. Esta acción no se puede deshacer.',title:"Cuentas"},write:{trigger:"Añadir credencial",title:"Escribir credencial de {{name}}",description:"Pega el material del token ya obtenido. Los campos están limitados a lo que acepta este proveedor; el token se almacena y nunca se vuelve a mostrar.",authMethod:"Método de autenticación",status:"Estado",subscriptionLevel:"Nivel de suscripción",subscriptionLevelNone:"Sin definir",submit:"Guardar credencial"},field:{accessToken:"Token de acceso",refreshToken:"Token de actualización",idToken:"Token de ID",apiKey:"Clave de API",expiresAt:"Caduca en (ISO)",setupTokenExpiresAt:"El token de configuración caduca en (ISO)",accountId:"ID de cuenta",email:"Correo electrónico",organizationId:"ID de organización",baseUrl:"URL base",zenBaseUrl:"URL base de Zen"},provider:{claude:{title:"Claude",description:"Credenciales de suscripción de Anthropic enrutadas por el daemon."},codex:{title:"Codex",description:"Credenciales de suscripción de OpenAI Codex enrutadas por el daemon."},gemini:{title:"Gemini",description:"Credenciales de suscripción de Google Gemini enrutadas por el daemon."},opencodego:{title:"OpenCodeGo",description:"Credenciales de clave de API estática enrutadas por el daemon."}},authMethodLabel:"Método de autorización",authMethodDesc:{oauth:"Inicia sesión a través de tu navegador; el daemon captura y almacena el token.",manual:"Pega un token ya obtenido. Se almacena y nunca se vuelve a mostrar."},actions:{authorize:"Autorizar",enterToken:"Introducir token",refresh:"Actualizar"},accounts:{addAccount:"Añadir cuenta"},detail:{authMethod:"Método de autorización",subscriptionLevel:"Nivel de suscripción",expiresAt:"Caduca",lastRefreshed:"Última actualización",label:"Etiqueta de cuenta",labelPlaceholder:"Nombra esta cuenta",saveLabel:"Guardar etiqueta"},oauthFlow:{step1:{title:"Abre la página de autorización",desc:"Abre la página de inicio de sesión en tu navegador."},step2:{title:"Autoriza el acceso",desc:"Inicia sesión y aprueba el acceso para el proveedor."},step3:{title:"Copia el código de autorización",desc:"La página muestra un código de autorización tras tu aprobación."},step4:{title:"Pega el código",desc:"Pega el código de autorización a continuación para finalizar. El código solo se envía al daemon — el token generado nunca se muestra."},authorize:"Completar inicio de sesión",showUrl:"Mostrar URL de autorización"},manual:{title:"Pegar credencial",description:"Pega un token ya obtenido. Los campos están limitados a lo que acepta este proveedor; el token se almacena y nunca se vuelve a mostrar.",accessTokenPlaceholder:"Pega el token de acceso",refreshTokenPlaceholder:"Pega el token de actualización (opcional)",hint:"El token se envía al daemon y se almacena cifrado. Nunca se vuelve a mostrar."},openCodeGo:{apiKeyRequired:"Se requiere una clave de API.",apiKeyPlaceholder:"Pega la clave de API",baseUrlPlaceholder:"https://… (opcional)",zenBaseUrlPlaceholder:"https://… (opcional)"},info:{title:"Acerca de las cuentas de suscripción",description:"Los tokens se escriben en el daemon y se usan para autenticar las solicitudes de destino. Se almacenan cifrados y nunca se vuelven a mostrar. Eliminar una cuenta borra su credencial almacenada."},rename:{failed:"No se pudo cambiar el nombre de la cuenta."},refresh:{failed:"No se pudo actualizar el token."},errors:{requestFailed:"La solicitud falló. Por favor, inténtalo de nuevo."},syncWarning:{"external-divergent":"El archivo de inicio de sesión de la CLI externa contiene credenciales más recientes que esta cuenta. El token guardado podría dejar de renovarse: renueva ahora o vuelve a iniciar sesión.","external-not-rotated":"La renovación falló y la CLI externa contiene las mismas credenciales caducadas. Vuelve a iniciar sesión.","duplicate-token":"Otra cuenta comparte estas credenciales. Renovar cualquiera de las dos invalidará la otra."},importExternal:{detected:"Se encontró una sesión de CLI de {{name}} existente en esta máquina.",hint:"Tras la importación, esta aplicación la mantiene actualizada: en cada renovación del token también se actualiza el archivo de sesión de la CLI, de modo que la CLI del terminal sigue conectada.",button:"Importar sesión de CLI existente"}},fx={title:"CLI de código",description:"Apunta una CLI de codificación al proxy saliente del daemon. Esta página es de solo lectura — no hay nada que configurar aquí.",copy:"Copiar",copied:"Copiado",baseUrl:{title:"URL base del daemon",description:"La dirección del proxy a la que se conecta tu CLI.",label:"URL base"},token:{title:"Autenticación",hint:"Envía 'Authorization: Bearer <tu-token-de-administración>' para las rutas de administración. El token de administración se configura en el daemon (su archivo de configuración o entorno) — nunca se muestra aquí."},examples:{title:"Entorno de lanzamiento de ejemplo",keyNote:"Usa una clave de acceso saliente creada en la página del Servicio de API — no el token de administración.",anthropic:"CLI en formato Anthropic",openai:"CLI en formato OpenAI"},launchDescription:"Lanza una CLI de codificación en un terminal apuntada a este daemon. El daemon inyecta el entorno de redirección e inicia la CLI automáticamente.",refresh:"Actualizar",loading:"Detectando CLIs…",cli:{installed:"Instalada",notFound:"No encontrada",notFoundHint:"Esta CLI no está en el PATH del host del daemon. Instálala y luego actualiza.",install:"Instalar",installing:"Instalando…",installingHint:"Instalando en el host del daemon — esto puede tardar un momento.",launch:"Lanzar",launchTitle:"Lanzar {{name}}",launchDescription:"Abre un nuevo terminal en el host del daemon ejecutando esta CLI, enrutada a través del proxy del daemon. Elige un directorio de trabajo opcional.",cwdLabel:"Directorio de trabajo",cwdPlaceholder:"/ruta/a/tu/proyecto",runningVia:"En ejecución · {{provider}} / {{model}}",stop:"Detener"},manual:{title:"Configuración manual",description:"¿Prefieres ejecutar la CLI tú mismo? Apúntala al daemon con estas variables de entorno.",show:"Mostrar",hide:"Ocultar"}},vx={probing:"Comprobando si el daemon está disponible…",spawning:"Iniciando el daemon…",failed:"El daemon no ha podido iniciarse",failedHint:"Asegúrate de que Node.js está instalado y el daemon está compilado (dist presente), o establece OMNICROSS_DAEMON_ENTRY en el cli.js del daemon."},kx={title:"Ajustes",description:"Preferencias de la aplicación de escritorio.",desktopOnly:"Las opciones de inicio y bandeja solo se aplican en la aplicación de escritorio.",startup:{title:"Inicio",autoLaunch:"Iniciar al arrancar",autoLaunchHint:"Inicia Omnicross automáticamente cuando inicias sesión.",startMinimized:"Iniciar minimizado en la bandeja",startMinimizedHint:"Lanza en segundo plano sin abrir la ventana."},tray:{title:"Bandeja del sistema",minimizeOnClose:"Minimizar a la bandeja al cerrar",minimizeOnCloseHint:"Cerrar la ventana la oculta en la bandeja en lugar de salir."},language:{title:"Idioma",label:"Idioma de la interfaz"}},yx={title:"Estadísticas de uso",description:"Estadísticas de tokens y costes de las solicitudes atendidas por el daemon.",rangeToday:"Hoy",range7d:"Últimos 7 días",range30d:"Últimos 30 días",rangeCustom:"Personalizado",from:"Desde",to:"Hasta",totalCost:"Coste total",cacheSavings:"Ahorro por caché",events:"Solicitudes",inputTokens:"Tokens de entrada",outputTokens:"Tokens de salida",cacheReadTokens:"Lectura de caché",cacheWriteTokens:"Escritura de caché",reasoningTokens:"Tokens de razonamiento",byModel:"Por modelo",byApiKey:"Por clave API",provider:"Proveedor",model:"Modelo",cost:"Coste",apiKey:"Clave API",unpriced:"Sin precio",unpricedHint:"No existe una entrada de precio para este modelo — agrégala en la página de Precios.",unattributed:"Sin atribuir",unattributedHint:"Solicitudes no vinculadas a una clave API concreta. Es lo esperado hasta que se registre la atribución por clave.",empty:"No hay solicitudes en este rango.",invalidRange:"Selecciona un rango de fechas válido."},bx={title:"Precios de modelos",description:"Precios de tokens por modelo usados para calcular el coste de las solicitudes, en USD por millón de tokens.",search:"Buscar proveedor o modelo…",fetchLatest:"Obtener los últimos",fetching:"Obteniendo…",addEntry:"Añadir entrada",provider:"Proveedor",model:"Modelo",inputPrice:"Entrada",outputPrice:"Salida",cacheReadPrice:"Lectura de caché",cacheWritePrice:"Escritura de caché",source:"Fuente",updated:"Actualizado",userEdited:"editado",edit:"Editar",deleteTitle:"¿Eliminar esta entrada de precio?",empty:"La tabla de precios está vacía.",emptyHint:"Obtén los últimos precios para llenarla.",noMatches:"Ninguna entrada coincide con tu búsqueda.",saved:"Entrada de precio guardada.",saveFailed:"Error al guardar: {{message}}",deleteFailed:"Error al eliminar: {{message}}",alreadyDeleted:"La entrada ya no existía.",fetchApplied:"Se actualizaron {{count}} entradas desde la fuente.",fetchFailed:"Error al obtener: {{message}}",requiredId:"Obligatorio",invalidPrice:"Introduce un número no negativo",conflictTitle:"Resolver conflictos de precios",conflictHint:"Estas entradas fueron editadas por ti y también cambiaron en la fuente. Elige por fila si conservar tu valor (Omitir) o tomar el entrante (Sobrescribir).",current:"Actual",incoming:"Entrante",overwrite:"Sobrescribir",skip:"Omitir",overwriteAll:"Sobrescribir todo",skipAll:"Omitir todo",applyResolutions:"Aplicar",resolved:"{{overwritten}} sobrescritas, {{skipped}} omitidas.",resolvedWithStale:"{{overwritten}} sobrescritas, {{skipped}} omitidas. {{stale}} cambiaron mientras tanto y quedaron intactas.",refreshFailed:"El cambio se aplicó, pero no se pudo recargar la lista: {{message}}",sourceBuiltin:"Integrado",sourceLitellm:"LiteLLM",sourceUser:"Usuario"},Px={providerSettings:sx,apiMode:lx,presetName:dx,common:cx,mediaSettings:ux,appLocal:px,nav:mx,apiService:gx,accounts:hx,codeCli:fx,daemonStatus:vx,settings:kx,usageStats:yx,pricing:bx},Ax={loading:"Ladataan LLM-asetuksia...",reset:{button:"Palauta oletusasetukset",confirmTitle:"Palautetaanko oletusasetukset?",confirmBody:"Tämä poistaa tämän palveluntarjoajan mukautuksesi, jotta se noudattaa sisäänrakennettuja oletusasetuksia jälleen. API-avaimesi ja tallennetut istuntosi säilytetään.",confirmButton:"Palauta oletusasetukset"},reentryBanner:{message:"{{count}} käytössä oleva palveluntarjoaja tarvitsee API-avaimen uudelleensyöttämistä. Avaa jokainen ja lisää avain uudelleen."},migrationPack:{barHint:"Siirrä palveluntarjoaja-avaimesi ja tilaustoken toiselle koneelle salatulla paketilla.",passphrase:"Salasana",passphrasePlaceholder:"Kirjoita salasana",passphraseHint:"Käytä vähintään 8 merkkiä; 12 tai enemmän on suositeltavaa.",confirm:"Vahvista salasana",confirmPlaceholder:"Kirjoita salasana uudelleen",mismatch:"Salasanat eivät täsmää.",strength:{weak:"Liian lyhyt — käytä vähintään 8 merkkiä.",fair:"OK — 12 tai enemmän merkkiä on vahvempi.",strong:"Vahva salasana."},export:{button:"Vie paketti",title:"Vie salattu paketti",subtitle:"Salaa palveluntarjoaja-avaimesi ja tilaustokenisi siirrettävään tiedostoon.",warning:"Tämä tiedosto sisältää purettavia salaisuuksia. Säilytä se turvallisesti — kuka tahansa tiedoston ja salasanan hallussapitäjä voi lukea avaimesi. Hukattua salasanaa ei voi palauttaa.",submit:"Vie",success:"Paketti viety onnistuneesti.",error:"Vienti epäonnistui. Yritä uudelleen."},import:{button:"Tuo paketti",title:"Tuo salattu paketti",subtitle:"Palauta palveluntarjoaja-avaimet ja tilaustokenit viedystä paketista.",hint:"Kirjoita paketin viennissä käytetty salasana ja valitse sitten tiedosto.",submit:"Tuo",successTitle:"Tuonti valmis",summary:"Tuotiin {{providerKeys}} palveluntarjoaja-avain(ta), {{poolKeys}} pool-avain(ta) ja {{tokenSets}} tokenikokoelma(a).",duplicates:"Ohitettiin {{count}} jo olemassa oleva pool-avain.",skipped:"Ohitettu (ei vastaavaa palveluntarjoajaa): {{names}}",error:"Väärä salasana tai vioittunut paketti. Mitään ei muutettu."}},searchPlaceholder:"Hae palveluntarjoajia...",emptySearch:"Mikään palveluntarjoaja ei vastaa hakuasi.",emptyList:"Ei palveluntarjoajia määritetty.",selectPrompt:"Valitse palveluntarjoaja nähdäksesi tiedot",listStatus:"{{count}} malli(a)",noModels:"Ei malleja määritetty",enabled:"Käytössä",disabled:"Pois käytöstä",showEnabledOnly:"Näytä vain käytössä olevat",showAll:"Näytä kaikki palveluntarjoajat",dragHandle:"Vedä järjestyksen muuttamiseksi",reorderFailed:"Palveluntarjoajajärjestyksen tallentaminen epäonnistui",credentials:{apiKey:"API-avain",apiBaseUrl:"API-perus-URL"},filter:{all:"Kaikki",chat:"Chat",code:"Koodi"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Valitse malli",skipTemplates:"Ohita, määritä manuaalisesti",name:"Nimi *",providerType:"Tyyppi",apiType:"API-tyyppi",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"OpenAI chat/completions API:n vakiomuoto",claudecode:"Anthropic Messages API -muoto (Claude Code)"},chatApiFormat:"API-muoto",chatApiFormatDescription:"Valitse palveluntarjoajan päätepistettä vastaava API-muoto",apiKey:"API-avain",apiKeyPlaceholder:"sk-... tai $ENV_VAR",apiKeyHelper:"Käytä $VAR_NAME viitaamaan ympäristömuuttujiin",apiKeySetPlaceholder:"Avain on asetettu — jätä tyhjäksi säilyttääksesi sen",apiKeyReplaceHelper:"Avain on tallennettu turvallisesti. Kirjoita uusi arvo korvataksesi sen tai jätä tyhjäksi säilyttääksesi sen.",testApiKey:"Testaa API-avain",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Esikatselu:",models:"Mallit",modelPlaceholder:"Mallin nimi (esim. gpt-4, claude-3-opus)",transformers:"Muuntimet",transformerConfig:"API-muuntimet",transformerConfigDescription:"Määritä muuntimet mukauttamaan API-pyyntö-/vastausmuotoja tälle palveluntarjoajalle",transformerConfigNote:"Demoni soveltaa näitä muuntimia pyyntöketjussa palveluntarjoajan formattimuuntimen jälkeen (joka käsittelee johtotasolla tapahtuvan muuntamisen). Tuntemattomat muunninnimet ohitetaan.",enabled:"Käytössä",apiVersion:"API-versio",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API -versio (esim. 2024-08-01-preview)",official:"Virallinen Anthropic API",officialHelper:"Ota käyttöön, jos tämä palveluntarjoaja yhdistää suoraan viralliseen Anthropic API:iin. Poista käytöstä käänteisiä välityspalvelimia tai kolmannen osapuolen palveluja varten.",maxConcurrency:"Maksimaalinen samanaikaisuus",maxConcurrencyHelper:"Tähän palveluntarjoajaan lähetettävien samanaikaisten API-pyyntöjen enimmäismäärä. Alhaisemmat arvot auttavat välttämään nopeusrajoitusta (429-virheitä). Aseta `-1` ei rajoitusta varten.",codingPlan:{label:"Koodaussuunnitelma",description:"Käytä erillistä API-päätepistettä tilauspohjaisille koodaussuunnitelmille",baseUrl:"Koodaussuunnitelman perus-URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Koodaussuunnitelman API-avain (valinnainen)",apiKeyPlaceholder:"Jätä tyhjäksi käyttääksesi palveluntarjoajan API-avainta",apiKeyHelper:"Vaaditaan vain, jos koodaussuunnitelma käyttää eri API-avainta",tokenPlanHint:"Jotkin palveluntarjoajat (esim. Xiaomi MiMo) myöntävät Token Plan -avaimia `tp-`-etuliitteellä — vain tiedoksi, ei pakollinen."},selectTypeFirst:"Valitse palveluntarjoajatyyppi",selectTypeFirstDesc:"Valitse minkä tyyppinen palveluntarjoaja haluat lisätä",codeProviderNote:"Koodipalveluntarjoajat tarvitsevat vain API-avaimen ja URL-osoitteen. Malleja hallinnoi agenttireititin.",buttons:{cancel:"Peruuta",submitAdd:"Lisää palveluntarjoaja",submitUpdate:"Päivitä palveluntarjoaja",continue:"Jatka",back:"Takaisin"}},details:{noSelection:"Valitse palveluntarjoaja nähdäksesi tiedot",apiKey:"API-avain",apiUrl:"API-URL",nameLabel:"Palveluntarjoajan nimi",modelsEndpoint:"Mallipäätepiste",modelsEndpointHelper:"Korvaa etsintäpäätepiste, jos palveluntarjoaja paljastaa mukautetun /models-polun.",models:"Mallit",transformers:"Muuntimet",codeProviderNote:"Koodipalveluntarjoajat (kuten Claude Code) eivät vaadi mallikonfiguraatiota. Malleja hallinnoi automaattisesti agenttireititin.",buttons:{more:"Lisää asetuksia",delete:"Poista"}},providerModelSelector:{placeholder:"Valitse palveluntarjoaja ja malli",noProviders:"Ei palveluntarjoajia saatavilla",noModels:"Ei malleja määritetty"},apiKeyPool:{title:"API-avainallas",description:"Määritä useita API-avaimia kuormantasausta varten. Jokainen istunto pysyy yhdessä avaimessa kehotusvälimuistin säilyttämiseksi.",defaultLabel:"Oletus",weight:"Paino",noKey:"Ei avainta",labelPlaceholder:"Tunniste (esim. Avain #1, Tuotanto)",addKey:"Lisää API-avain",add:"Lisää",empty:"Ei lisäavaimia määritetty.",statusCoolingDown:"Jäähtyminen {{time}}",statusAuthFailed:"Todennus epäonnistui · poistettu käytöstä",statusDisabled:"Pois käytöstä",statusHealthy:"Kunnossa",agoSeconds:"{{count}}s sitten",agoMinutes:"{{count}}min sitten",agoHours:"{{count}}t sitten",agoDays:"{{count}}pv sitten"},modelsManager:{searchPlaceholder:"Hae malleja...",defaultGroup:"Kaikki mallit",add:"Lisää malli",manage:"Hallinnoi",empty:"Ei malleja tässä ryhmässä",enabled:"Käytössä",disabled:"Pois käytöstä",filters:{all:"Kaikki",vision:"Visio",reasoning:"Päättely",free:"Ilmainen",tools:"Työkalut"},manualDialog:{title:"Lisää malli",subtitle:"Lisää mukautettu malli tähän palveluntarjoajaan",modelId:"Mallin tunnus",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, jne.",modelIdHelper:"Tarkka mallitunniste, jota käytetään API-kutsuja tehdessä",modelName:"Näyttönimi",modelNamePlaceholder:"Ystävällinen näyttönimi (valinnainen)",modelNameHelper:"Valinnainen käyttöliittymässä näkyvä nimi. Jos tyhjä, käytetään mallin tunnusta",group:"Ryhmä",groupPlaceholder:"Valitse tai kirjoita ryhmän nimi",submit:"Lisää",cancel:"Peruuta",helper:"Anna palveluntarjoajan API:n paljastama tarkka mallitunniste."},editDialog:{title:"Muokkaa mallia",subtitle:"Muuta mallin asetuksia",modelId:"Mallin tunnus",modelIdPlaceholder:"Mallitunniste",modelIdHelper:"Mallitunniste, jota käytetään API-kutsuja tehdessä",modelName:"Näyttönimi",modelNamePlaceholder:"Ystävällinen näyttönimi",modelNameHelper:"Käyttöliittymässä näkyvä nimi",group:"Ryhmä",groupPlaceholder:"Valitse tai kirjoita ryhmän nimi",submit:"Tallenna",cancel:"Peruuta",vision:"Visio-ominaisuus",visionHint:"Tukeeko tämä malli kuva-/visionsyötettä",reasoning:"Päättelymalli",reasoningHint:"Tukeeko tämä malli ajattelu-/päättelytilaa"},manageDialog:{title:"Hallinnoi malleja",cachedAt:"Välimuistissa {{date}} ({{source}})",refresh:"Päivitä",close:"Sulje",raw:"Raaaka JSON",empty:"Ei etämalleja saatavilla.",error:"Mallien lataaminen epäonnistui: {{message}}",addFromCatalog:"Lisää",sourceCache:"välimuisti",sourceNetwork:"live",contextLength:"Konteksti {{value}} tokenia",maxTokens:"Maks {{value}} tokenia"},messages:{added:"Malli lisätty.",updated:"Malli päivitetty.",removed:"Malli poistettu.",duplicate:"Malli on jo olemassa.",refreshed:"Mallit päivitetty",refreshFailed:"Mallien päivittäminen epäonnistui"},testDialog:{title:"Mallin yhteystesti",provider:"Palveluntarjoaja",model:"Malli",testing:"Testataan...",success:"Testi onnistui",successMessage:"Malliin pääsee normaalisti",failure:"Testi epäonnistui",aiResponse:"Tekoälyvastaus",charCount:"{{count}} merkkiä",duration:"Kesto {{time}}s",close:"Sulje",retest:"Testaa uudelleen",testButton:"Testaa malli",unsupportedFormat:"Testaus ei vielä tue tätä palveluntarjoajamuotoa."}},router:{title:"Reitittimen asetukset",description:"Määritä, mitä palveluntarjoajaa/mallia käytetään eri tilanteissa.",labels:{default:"Oletus",background:"tausta",think:"ajattelu",longContext:"Pitkä konteksti",webSearch:"Verkkohaku",image:"Kuva",longContextThreshold:"Pitkän kontekstin kynnysarvo"},helper:{longContextThreshold:"Tokenien määrä ennen vaihtamista pitkän kontekstin malliin."},placeholder:{required:"Pakollinen",optional:"Valinnainen"}},agentRouter:{title:"Agenttireititin",description:"Määritä kaksisuuntainen reititys chat- ja kooditilan välillä.",searchPlaceholder:"Hae reitittimia...",noSearchResults:"Mikään reititin ei vastaa hakuasi.",tabs:{chatToCode:"Chat → Koodi",codeToChatPlaceholder:"Koodi → Chat"},chatToCode:{title:"Chat koodiksi -reititin",description:"Käytä chat-palveluntarjoajia agentti-/koodaustilassa",addRouter:"Lisää reititin",emptyState:"Ei Chat→Koodi-reitittimia määritetty. Lisää yksi käyttääksesi chat-palveluntarjoajia koodaustilassa.",form:{name:"Reitittimen nimi",namePlaceholder:"Oma Chat→Koodi-reititin",chatProvider:"Chat-palveluntarjoaja",chatProviderPlaceholder:"Valitse chat-palveluntarjoaja",mode:"Tila",modeSimple:"Yksinkertainen",modeAdvanced:"Edistynyt",modeSimpleDesc:"Suora läpivienti chat-palveluntarjoajalle",modeAdvancedDesc:"Määritä mallimappaukset ja kontekstinkäsittely",enabled:"Käytössä",save:"Tallenna reititin",cancel:"Peruuta"},list:{provider:"Palveluntarjoaja",mode:"Tila",status:"Tila"},mappings:{title:"Mallimappaykset",description:"Kartoita chat-palveluntarjoajan mallit koodipalveluntarjoajan malleihin",count:"mappausta",empty:"Ei mallimappayksia määritetty. Lisää mappayksia reitittääksesi chat-malleja koodipalveluntarjoajille.",addNew:"Lisää uusi mappaus",selectSource:"Valitse lähdemalli (Chat)",selectTarget:"Valitse kohdemalli (Koodi)",targetPlaceholder:"Kirjoita Claude Code -mallin nimi",notSet:"(Ei asetettu — napsauta valitaksesi)",add:"Lisää",edit:"Muokkaa",done:"Valmis"},advanced:{title:"Edistynyt asetukset",description:"Määritä mallit eri tehtävätyypeille",helpText:"Oletusmallia vaaditaan. Muut mallit ovat valinnaisia ja palautuvat oletukseen, jos niitä ei ole määritetty.",default:{label:"Oletus",placeholder:"Valitse oletusmalli",description:"Ensisijainen malli yleisiin tehtäviin (vastaava kuin Claude Sonnet)"},background:{label:"Tausta",placeholder:"Valitse taustamallin",description:"Kevyt malli taustatöitä varten (vastaava kuin Claude Haiku)"},think:{label:"Ajattelu",placeholder:"Valitse ajattelumalli",description:"Edistynyt malli monimutkaiseen päättelyyn (vastaava kuin Claude Opus)"},image:{label:"Kuva",placeholder:"Valitse kuvamalli",description:"Malli kuvaan liittyville tehtäville visio-ominaisuudella"}}},codeToChat:{title:"Koodi chatiksi -reititin",description:"Paljasta koodaussuunnitelmamalleja chat-tilassa",addRouter:"Lisää reititin",emptyState:"Ei Koodi→Chat-reitittimia määritetty. Lisää yksi paljastaaksesi koodaussuunnitelmamalleja chat-tilassa.",form:{name:"Reitittimen nimi",namePlaceholder:"Oma Koodi→Chat-reititin",codeProvider:"Koodipalveluntarjoaja",codeProviderPlaceholder:"Valitse koodipalveluntarjoaja",codeProviderHelper:"Valitse muunnokseen käytettävä koodipalveluntarjoaja",models:"Koodaussuunnitelmamallit",modelsHelper:"Valitse paljastettavat koodaussuunnitelmamallit",enabled:"Käytössä",save:"Tallenna reititin",cancel:"Peruuta"},mappings:{title:"Mallimappaykset",description:"Kartoita koodipalveluntarjoajan mallit chat-palveluntarjoajan malleihin paljastamista varten",count:"mappausta",empty:"Ei mallimappayksia määritetty. Lisää mappayksia paljastaaksesi koodimalleja chat-tilassa.",addNew:"Lisää uusi mappaus",selectSource:"Valitse lähdemalli (Koodi)",selectTarget:"Valitse kohdemalli (Chat)",sourcePlaceholder:"Kirjoita lähdemallin nimi",targetPlaceholder:"Kirjoita kohdemallin nimi",add:"Lisää",edit:"Muokkaa",done:"Valmis"}},transformers:{title:"Muuntimet",description:"Määritä muuntimet pyyntö-/vastausmuunnosta varten",noProvider:"Valitse palveluntarjoaja muuntimien määrittämiseksi",empty:"Ei muuntimia",count:"{{count}} muunnin(ta)"},status:{enabled:"Käytössä",disabled:"Pois käytöstä"},messages:{routerAdded:"Reititin lisätty",routerUpdated:"Reititin päivitetty",routerDeleted:"Reititin poistettu",saveFailed:"Reitittimen tallentaminen epäonnistui"}},presets:{title:"Lisää palveluntarjoaja nopeasti",added:"Lisätty",add:"Lisää",features:{search:"Haku",vision:"Visio",mcp:"MCP",codingPlan:"Koodaussuunnitelma"}},alerts:{deleteConfirm:"Haluatko varmasti poistaa tämän palveluntarjoajan?"},errors:{nameRequired:"Palveluntarjoajan nimi on pakollinen",urlRequired:"API-perus-URL on pakollinen",urlInvalid:"Kirjoita kelvollinen URL-osoite (esim. https://api.example.com)",saveFailed:"Palveluntarjoajan tallentaminen epäonnistui",deleteFailed:"Virhe palveluntarjoajan poistamisessa. Yritä uudelleen.",toggleFailed:"Virhe palveluntarjoajan käyttöönottamisessa/poistamisessa käytöstä. Yritä uudelleen."},openRouter:{title:"OpenRouter-palveluntarjoajareititys",description:"Määritä, miten pyynnöt reititetään eri palveluntarjoajille OpenRouterissa.",sort:"Reititystrategia",sortTooltip:"Valitse, miten palveluntarjoajat priorisoidaan. Auto käyttää älykkäätä kuormantasausta.",order:"Palveluntarjoajan prioriteettijärjestys",orderTooltip:"Määritä kokeiltavat palveluntarjoajat järjestyksessä (esim. anthropic, openai, together). Paina Enter lisätäksesi.",orderPlaceholder:"Kirjoita palveluntarjoajan slug ja paina Enter...",allowFallbacks:"Salli varavaihtoehdot",allowFallbacksTooltip:"Kun käytössä, OpenRouter kokeilee varapalveluntarjoajia, jos ensisijainen ei ole käytettävissä.",requireParameters:"Vaadi kaikki parametrit",requireParametersTooltip:"Reititä vain palveluntarjoajille, jotka tukevat kaikkia pyyntösi parametreja.",dataCollection:"Tiedonkeruukäytäntö",dataCollectionTooltip:"Hallinnoi, käytetäänkö palveluntarjoajia, jotka voivat tallentaa tai kouluttaa tietojesi perusteella.",zdr:"Nollatietojen säilytys",zdrTooltip:"Reititä vain päätepisteisiin, joilla on nollatietojen säilytyskäytäntö.",only:"Salli vain palveluntarjoajat",onlyTooltip:"Käytä vain näitä tiettyjä palveluntarjoajia. Jätä tyhjäksi salliaksesi kaikki palveluntarjoajat.",onlyPlaceholder:"Kirjoita palveluntarjoajan slug ja paina Enter...",ignore:"Ohita palveluntarjoajat",ignoreTooltip:"Ohita nämä palveluntarjoajat pyyntöjä reitittäessä.",ignorePlaceholder:"Kirjoita palveluntarjoajan slug ja paina Enter...",quantizations:"Kvantisoinnin suodatin",quantizationsTooltip:"Käytä vain palveluntarjoajia, joilla on tietyt kvantisoinnin tasot. Alhaisempi tarkkuus voi heikentää laatua, mutta parantaa nopeutta.",maxPrice:"Enimmäishinta",maxPriceTooltip:"Aseta enimmäishintarajat miljoonaa tokenia kohden. Jätä tyhjäksi, jos ei rajoitusta.",configured:"Määritetty"}},Cx={label:"API-tila",standard:"Vakio",codingPlan:"Koodaussuunnitelma",tokenPlan:"Tokenisuunnitelma",apiKeyPrefixHint:"Tämän suunnitelman avaimet alkavat yleensä `{{prefix}}`-etuliitteellä. Vain tiedoksi — ei pakollinen.",dashscopeCodingPlanSeparateKey:"DashScope Koodaussuunnitelma käyttää erillistä API-avainta vakiopäätepistestä.",baiduCodingPlanSeparateKey:"Qianfan Koodaussuunnitelma käyttää erillistä API-avainta vakiopäätepistestä.",tencentTokenPlanAnthropicOnly:"Tencent Tokenisuunnitelma on vain Anthropic-protokollan mukainen.",xiaomiTokenPlanRegions:"Oletusarvoinen baseUrl on `token-plan-cn.*`. Voit muokata sen manuaalisesti muotoon `token-plan-sgp.*` tai `token-plan-ams.*`.",confirmOverwriteTitle:"Vaihdetaanko API-tilaa?",confirmOverwriteBody:"Olet mukauttanut API-URL-osoitteen tai API-avaimen. Tilan vaihtaminen korvaa ne uuden tilan oletusarvoilla — tai pidä mukautuksesi ja päivitä vain tilatunniste.",overwriteAndSwitch:"Korvaa ja vaihda",keepCustomizations:"Pidä mukautukset"},xx={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Tokenisuunnitelma)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},zx={cancel:"Peruuta",close:"Sulje",copy:"Kopioi",delete:"Poista",dismiss:"Hylkää",save:"Tallenna",optional:"valinnainen",retry:"Yritä uudelleen",loading:"Ladataan…"},Ix={common:{learnMore:"Dokumentaatio"}},Sx={notSupportedByDaemon:"Demoni ei vielä tue tätä",discoveryUnsupportedFormat:"Mallien etsintä ei vielä tue tätä palveluntarjoajamuotoa. Lisää mallit manuaalisesti."},wx={subtitle:"Ohjauspaneeli",providers:"Palveluntarjoajat",apiService:"API-palvelu",accounts:"Tilit",codeCli:"Koodi-CLI",settings:"Asetukset",usageStats:"Käyttö",pricing:"Hinnat"},Tx={title:"API-palvelu",description:"Määritä lähtevä API-palvelin, mallireititys päätepistettä kohden ja nimetyt käyttöavaimet.",loading:"Ladataan palvelinasetuksia…",loadError:"Palvelinasetuksia ei voitu ladata. Tarkista, että demoni on käytettävissä.",enable:{label:"Ota käyttöön lähtevä palvelin",description:"Käynnistä paikallinen API-palvelin, joka reitittää ulkoiset kutsut palveluntarjoajiesi kautta."},networkBinding:{label:"Salli LAN-käyttö",description:"Sido palvelin verkkokäyttöliittymääsi vain loopbackin sijaan.",warning:"LAN-käyttö paljastaa API-palvelimen muille laitteillesi verkossasi. Yhdistettynä tilausreititykseen pyynnöt voivat kuluttaa tilauskvoottiasi — pidä tämä pois käytöstä, ellei luota verkkoon."},status:{running:"Palvelin käynnissä",stopped:"Palvelin pysäytetty",runningHint:"Lähtevä API-palvelin vastaanottaa pyyntöjä.",stoppedHint:"Ota palvelin käyttöön aloittaaksesi pyyntöjen vastaanottamisen.",port:"portti {{port}}",loopback:"Loopback-URL-osoitteet",lan:"LAN-URL-osoitteet"},endpoints:{title:"Päätepistereititys",description:"Valitse malli, johon kukin johtotason muoto reititetään. Oletusmalli sisältyy tähän — palvelin on reititin, ei chat-sovellus."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Oletusmalli",backgroundModel:"Taustamallin",visionModel:"Visiomalli",noVisionModel:"Ei mitään",backgroundModelIds:"Taustamallin tunnukset",backgroundModelIdsPlaceholder:"pilkuilla erotetut mallitunnukset",modelPlaceholder:"Valitse malli…",useSubscription:"Käytä tilausta",subscriptionUnsupported:"Tilausreititys ei ole käytettävissä tässä päätepisteessä."},keys:{title:"Käyttöavaimet",description:"Nimetyt avaimet, jotka ulkoiset kutsujat lähettävät Bearer-tokenina. Koko avain näytetään vain kerran luomisen yhteydessä.",namePlaceholder:"Avaimen nimi (esim. oma-cli)",create:"Luo avain",empty:"Ei käyttöavaimia vielä.",enabled:"Käytössä",disabled:"Pois käytöstä",revoked:"Peruutettu",toggle:"Vaihda avaimen tila",revoke:"Peruuta",revokeConfirmTitle:"Peruutetaanko tämä avain?",revokeConfirmDesc:'"{{name}}"-avaimen peruuttaminen estää todentamisen välittömästi. Tätä ei voi kumota.',created:{title:"Avain luotu",warning:"Kopioi tämä avain nyt — sitä ei näytetä uudelleen. Säilytä se turvallisesti.",copy:"Kopioi",copied:"Kopioitu",dismiss:"Valmis"}}},jx={title:"Tilit ja tilaukset",description:"Hallinnoi tilausten tunnistietoja, joiden kautta palvelin reitittää. Tokenit kirjoitetaan tänne, mutta niitä ei koskaan näytetä takaisin.",loading:"Ladataan tilejä…",empty:"Tilauspalveluntarjoajia ei ole käytettävissä.",signIn:"Kirjaudu sisään",oauth:{title:"Kirjaudu sisään {{name}}",description:"Avaa kirjautumissivu selaimessasi, valtuuta ja liitä sitten valtuutuskoodi alle. Koodi siirretään vain demonille — luotua tokenia ei koskaan näytetä.",openPage:"Avaa kirjautumissivu",codeLabel:"Valtuutuskoodi",codePlaceholder:"Liitä koodi tähän",submit:"Viimeistele kirjautuminen"},codexOauth:{title:"Kirjaudu sisään {{name}}",description:"Avaa kirjautumissivu selaimessasi ja valtuuta. Demoni kaappaa tuloksen automaattisesti — pidä tämä auki, kunnes se on valmis. Tokenia ei koskaan näytetä.",waiting:"Odotetaan, että viimeistelet kirjautumisen selaimessasi…",failed:"Kirjautuminen epäonnistui. Yritä uudelleen."},clearProvider:"Tyhjennä kaikki",clearConfirmTitle:"Tyhjennetäänkö {{name}}-tilit?",clearConfirmDesc:"Tämä poistaa kaikki tallennetut tunnistiedot tältä palveluntarjoajalta. Tätä ei voi kumota.",credential:{ok:"Määritetty",notConfigured:"Ei määritetty"},kind:{"pass-through":"Läpivistitunnistiedot","oauth-bearer":"OAuth bearer","static-bearer":"Staattinen bearer-avain"},reason:{"missing-credential":"Tunnistietoja ei tallennettu.",expired:"Tunnistieto on vanhentunut.","reauth-required":"Uudelleentodentaminen vaaditaan.","refresh-failed":"Tokenin päivittäminen epäonnistui.","not-refreshable":"Tunnistietoa ei voi päivittää.",unknown:"Tila tuntematon."},status:{unconfigured:"Ei määritetty",authorized:"Valtuutettu",configured:"Määritetty",expired:"Vanhentunut",error:"Virhe"},authMethod:{oauth:"OAuth",setup_token:"Asennustoken",manual:"Manuaalinen"},list:{empty:"Ei tilejä tallennettu tälle palveluntarjoajalle.",active:"Aktiivinen",expiresAt:"Vanhenee {{value}}",setActive:"Aseta aktiiviseksi",remove:"Poista",removeConfirmTitle:"Poistetaanko tämä tili?",removeConfirmDesc:'"{{name}}"-tilin poistaminen poistaa sen tallennetut tunnistiedot. Tätä ei voi kumota.',title:"Tilit"},write:{trigger:"Lisää tunnistieto",title:"Kirjoita {{name}}-tunnistieto",description:"Liitä jo hankittu tokeniaines. Kentät on rajoitettu siihen, mitä tämä palveluntarjoaja hyväksyy; token tallennetaan, eikä sitä koskaan näytetä takaisin.",authMethod:"Todennusmenetelmä",status:"Tila",subscriptionLevel:"Tilaustaso",subscriptionLevelNone:"Ei asetettu",submit:"Tallenna tunnistieto"},field:{accessToken:"Käyttötoken",refreshToken:"Päivitystoken",idToken:"ID-token",apiKey:"API-avain",expiresAt:"Vanhenee (ISO)",setupTokenExpiresAt:"Asennustoken vanhenee (ISO)",accountId:"Tilin tunnus",email:"Sähköposti",organizationId:"Organisaation tunnus",baseUrl:"Perus-URL",zenBaseUrl:"Zen-perus-URL"},provider:{claude:{title:"Claude",description:"Anthropicin tilaustunnistiedot, joita demoni reitittää."},codex:{title:"Codex",description:"OpenAI Codexin tilaustunnistiedot, joita demoni reitittää."},gemini:{title:"Gemini",description:"Google Geminin tilaustunnistiedot, joita demoni reitittää."},opencodego:{title:"OpenCodeGo",description:"Staattiset API-avaintunnistiedot, joita demoni reitittää."}},authMethodLabel:"Valtuutusmenetelmä",authMethodDesc:{oauth:"Kirjaudu sisään selaimen kautta; demoni kaappaa ja tallentaa tokenin.",manual:"Liitä jo hankittu token. Se tallennetaan, eikä sitä koskaan näytetä takaisin."},actions:{authorize:"Valtuuta",enterToken:"Syötä token",refresh:"Päivitä"},accounts:{addAccount:"Lisää tili"},detail:{authMethod:"Valtuutusmenetelmä",subscriptionLevel:"Tilaustaso",expiresAt:"Vanhenee",lastRefreshed:"Viimeksi päivitetty",label:"Tilin tunniste",labelPlaceholder:"Anna tälle tilille nimi",saveLabel:"Tallenna tunniste"},oauthFlow:{step1:{title:"Avaa valtuutussivu",desc:"Avaa kirjautumissivu selaimessasi."},step2:{title:"Valtuuta käyttö",desc:"Kirjaudu sisään ja hyväksy käyttö palveluntarjoajalle."},step3:{title:"Kopioi valtuutuskoodi",desc:"Sivu näyttää valtuutuskoodin hyväksymisen jälkeen."},step4:{title:"Liitä koodi",desc:"Liitä valtuutuskoodi alle viimeistelläksesi. Koodi siirretään vain demonille — luotua tokenia ei koskaan näytetä."},authorize:"Viimeistele kirjautuminen",showUrl:"Näytä valtuutus-URL"},manual:{title:"Liitä tunnistieto",description:"Liitä jo hankittu token. Kentät on rajoitettu siihen, mitä tämä palveluntarjoaja hyväksyy; token tallennetaan, eikä sitä koskaan näytetä takaisin.",accessTokenPlaceholder:"Liitä käyttötoken",refreshTokenPlaceholder:"Liitä päivitystoken (valinnainen)",hint:"Token lähetetään demonille ja tallennetaan salattuna. Sitä ei koskaan näytetä takaisin."},openCodeGo:{apiKeyRequired:"API-avain on pakollinen.",apiKeyPlaceholder:"Liitä API-avain",baseUrlPlaceholder:"https://… (valinnainen)",zenBaseUrlPlaceholder:"https://… (valinnainen)"},info:{title:"Tietoa tilaustileistä",description:"Tokenit kirjoitetaan demonille ja niitä käytetään ylävirran pyyntöjen todentamiseen. Ne tallennetaan salattuna eikä niitä koskaan näytetä takaisin. Tilin poistaminen poistaa sen tallennetut tunnistiedot."},rename:{failed:"Tilin nimeä ei voitu muuttaa."},refresh:{failed:"Tokenia ei voitu päivittää."},errors:{requestFailed:"Pyyntö epäonnistui. Yritä uudelleen."},syncWarning:{"external-divergent":"Ulkoisen CLI:n kirjautumistiedosto sisältää uudemmat tunnistetiedot kuin tämä tili. Tallennettu token ei ehkä enää päivity — päivitä nyt tai kirjaudu uudelleen.","external-not-rotated":"Päivitys epäonnistui, ja ulkoinen CLI sisältää samat vanhentuneet tunnistetiedot. Kirjaudu uudelleen.","duplicate-token":"Toinen tili käyttää samoja tunnistetietoja. Jommankumman päivittäminen kirjaa toisen ulos."},importExternal:{detected:"Tältä koneelta löytyi olemassa oleva {{name}} CLI -kirjautuminen.",hint:"Tuonnin jälkeen tämä sovellus pitää sen ajan tasalla: jokaisen tokenin päivityksen yhteydessä myös CLI:n kirjautumistiedosto päivitetään, joten terminaalin CLI pysyy kirjautuneena.",button:"Tuo olemassa oleva CLI-kirjautuminen"}},Mx={title:"Koodi-CLI",description:"Osoita koodaus-CLI demonin lähtevään välityspalvelimeen. Tämä sivu on vain luku — tässä ei ole mitään määritettävää.",copy:"Kopioi",copied:"Kopioitu",baseUrl:{title:"Demonin perus-URL",description:"Välityspalvelimen osoite, johon CLI:si yhdistää.",label:"Perus-URL"},token:{title:"Todennus",hint:"Lähetä 'Authorization: Bearer <oma-admin-token>' admin-reitteille. Admin-token määritetään demonissa (sen asetustiedostossa tai ympäristössä) — sitä ei koskaan näytetä tässä."},examples:{title:"Esimerkki käynnistysympäristöstä",keyNote:"Käytä API-palvelusivulla luotua lähtevää käyttöavainta — ei admin-tokenia.",anthropic:"Anthropic-muotoinen CLI",openai:"OpenAI-muotoinen CLI"},launchDescription:"Käynnistä koodaus-CLI päätteessä, osoitettuna tähän demoniin. Demoni lisää ohjausympäristömuuttujat ja käynnistää CLI:n puolestasi.",refresh:"Päivitä",loading:"Havaitaan CLI:tä…",cli:{installed:"Asennettu",notFound:"Ei löydy",notFoundHint:"Tämä CLI ei ole demonin isäntäkoneen PATH:ssa. Asenna se ja päivitä sitten.",install:"Asenna",installing:"Asennetaan…",installingHint:"Asennetaan demonin isäntäkoneelle — tämä voi kestää hetken.",launch:"Käynnistä",launchTitle:"Käynnistä {{name}}",launchDescription:"Avaa uuden päätteen demonin isäntäkoneella, jossa tämä CLI on käynnissä demonivälityspalvelimen kautta. Valitse valinnainen työhakemisto.",cwdLabel:"Työhakemisto",cwdPlaceholder:"/polku/projektillesi",runningVia:"Käynnissä · {{provider}} / {{model}}",stop:"Pysäytä"},manual:{title:"Manuaalinen asetus",description:"Haluatko mieluummin ajaa CLI:n itse? Osoita se demoniin näillä ympäristömuuttujilla.",show:"Näytä",hide:"Piilota"}},Nx={probing:"Etsitään demonia…",spawning:"Käynnistetään demonia…",failed:"Demoni ei käynnistynyt",failedHint:"Varmista, että Node.js on asennettu ja demoni on rakennettu (dist-hakemisto on olemassa), tai aseta OMNICROSS_DAEMON_ENTRY demonin cli.js-tiedostoon."},Lx={title:"Asetukset",description:"Työpöytäsovelluksen asetukset.",desktopOnly:"Käynnistys- ja ilmoitusalueen asetukset koskevat vain työpöytäsovellusta.",startup:{title:"Käynnistys",autoLaunch:"Käynnistä kirjautuessa",autoLaunchHint:"Käynnistä Omnicross automaattisesti, kun kirjaudut sisään.",startMinimized:"Käynnistä minimoituna ilmoitusalueelle",startMinimizedHint:"Käynnistä taustalla avaamatta ikkunaa."},tray:{title:"Ilmoitusalue",minimizeOnClose:"Minimoi ilmoitusalueelle suljettaessa",minimizeOnCloseHint:"Ikkunan sulkeminen piilottaa sen ilmoitusalueelle ohjelman sulkemisen sijaan."},language:{title:"Kieli",label:"Käyttöliittymän kieli"}},Rx={title:"Käyttötilastot",description:"Daemonin palvelemien pyyntöjen token- ja kustannustilastot.",rangeToday:"Tänään",range7d:"Viimeiset 7 päivää",range30d:"Viimeiset 30 päivää",rangeCustom:"Mukautettu",from:"Alkaen",to:"Asti",totalCost:"Kokonaiskustannus",cacheSavings:"Välimuistisäästö",events:"Pyynnöt",inputTokens:"Syöte-tokenit",outputTokens:"Tulos-tokenit",cacheReadTokens:"Välimuistin luku",cacheWriteTokens:"Välimuistin kirjoitus",reasoningTokens:"Päättely-tokenit",byModel:"Malleittain",byApiKey:"API-avaimittain",provider:"Palveluntarjoaja",model:"Malli",cost:"Kustannus",apiKey:"API-avain",unpriced:"Hinnoittelematon",unpricedHint:"Tälle mallille ei ole hintamerkintää — lisää se Hinnat-sivulla.",unattributed:"Kohdistamaton",unattributedHint:"Pyynnöt, joita ei ole liitetty tiettyyn API-avaimeen. Tämä on odotettua, kunnes avainkohtainen kohdistus tallennetaan.",empty:"Ei pyyntöjä tällä aikavälillä.",invalidRange:"Valitse kelvollinen päivämääräväli."},Dx={title:"Mallien hinnat",description:"Mallikohtaiset token-hinnat pyyntökustannusten laskentaan, USD / miljoona tokenia.",search:"Hae palveluntarjoajaa tai mallia…",fetchLatest:"Hae uusimmat",fetching:"Haetaan…",addEntry:"Lisää merkintä",provider:"Palveluntarjoaja",model:"Malli",inputPrice:"Syöte",outputPrice:"Tulos",cacheReadPrice:"Välimuistin luku",cacheWritePrice:"Välimuistin kirjoitus",source:"Lähde",updated:"Päivitetty",userEdited:"muokattu",edit:"Muokkaa",deleteTitle:"Poistetaanko hintamerkintä?",empty:"Hintataulukko on tyhjä.",emptyHint:"Hae uusimmat hinnat täyttääksesi sen.",noMatches:"Mikään merkintä ei vastaa hakua.",saved:"Hintamerkintä tallennettu.",saveFailed:"Tallennus epäonnistui: {{message}}",deleteFailed:"Poisto epäonnistui: {{message}}",alreadyDeleted:"Merkintää ei enää ollut.",fetchApplied:"{{count}} merkintää päivitetty lähteestä.",fetchFailed:"Haku epäonnistui: {{message}}",requiredId:"Pakollinen",invalidPrice:"Anna ei-negatiivinen luku",conflictTitle:"Ratkaise hintaristiriidat",conflictHint:"Olet muokannut näitä merkintöjä, ja ne ovat muuttuneet myös lähteessä. Valitse riveittäin, säilytetäänkö oma arvosi (Ohita) vai otetaanko uusi (Korvaa).",current:"Nykyinen",incoming:"Saapuva",overwrite:"Korvaa",skip:"Ohita",overwriteAll:"Korvaa kaikki",skipAll:"Ohita kaikki",applyResolutions:"Käytä",resolved:"{{overwritten}} korvattu, {{skipped}} ohitettu.",resolvedWithStale:"{{overwritten}} korvattu, {{skipped}} ohitettu. {{stale}} muuttui sillä välin ja jäi koskemattomaksi.",refreshFailed:"Muutos otettiin käyttöön, mutta luettelon uudelleenlataus epäonnistui: {{message}}",sourceBuiltin:"Sisäänrakennettu",sourceLitellm:"LiteLLM",sourceUser:"Käyttäjä"},Ex={providerSettings:Ax,apiMode:Cx,presetName:xx,common:zx,mediaSettings:Ix,appLocal:Sx,nav:wx,apiService:Tx,accounts:jx,codeCli:Mx,daemonStatus:Nx,settings:Lx,usageStats:Rx,pricing:Dx},Ox={loading:"Chargement de la configuration LLM...",reset:{button:"Restaurer les valeurs par défaut",confirmTitle:"Restaurer les paramètres par défaut ?",confirmBody:"Cela efface vos personnalisations pour ce fournisseur et restaure les valeurs par défaut intégrées. Votre clé API et vos sessions sauvegardées sont conservées.",confirmButton:"Restaurer les valeurs par défaut"},reentryBanner:{message:"{{count}} fournisseur(s) activé(s) nécessite(nt) la re-saisie de leur clé API. Ouvrez chacun et ajoutez à nouveau sa clé."},migrationPack:{barHint:"Transférez vos clés de fournisseur et tokens d'abonnement vers une autre machine via un pack chiffré.",passphrase:"Phrase secrète",passphrasePlaceholder:"Entrez une phrase secrète",passphraseHint:"Utilisez au moins 8 caractères ; 12 ou plus est recommandé.",confirm:"Confirmer la phrase secrète",confirmPlaceholder:"Ressaisissez la phrase secrète",mismatch:"Les phrases secrètes ne correspondent pas.",strength:{weak:"Trop courte — utilisez au moins 8 caractères.",fair:"Acceptable — 12 caractères ou plus est plus sûr.",strong:"Phrase secrète robuste."},export:{button:"Exporter le pack",title:"Exporter le pack chiffré",subtitle:"Chiffrez vos clés de fournisseur et tokens d'abonnement dans un fichier portable.",warning:"Ce fichier contient des secrets déchiffrables. Conservez-le en lieu sûr — quiconque possède le fichier et la phrase secrète peut lire vos clés. Une phrase secrète perdue ne peut pas être récupérée.",submit:"Exporter",success:"Pack exporté avec succès.",error:"Échec de l'exportation. Veuillez réessayer."},import:{button:"Importer le pack",title:"Importer le pack chiffré",subtitle:"Restaurez les clés de fournisseur et tokens d'abonnement depuis un pack exporté.",hint:"Entrez la phrase secrète utilisée lors de l'exportation, puis choisissez le fichier.",submit:"Importer",successTitle:"Importation terminée",summary:"{{providerKeys}} clé(s) de fournisseur, {{poolKeys}} clé(s) de pool et {{tokenSets}} jeu(x) de tokens importés.",duplicates:"{{count}} clé(s) de pool déjà présente(s) ignorée(s).",skipped:"Ignoré (aucun fournisseur correspondant) : {{names}}",error:"Phrase secrète incorrecte ou pack corrompu. Aucune modification effectuée."}},searchPlaceholder:"Rechercher des fournisseurs...",emptySearch:"Aucun fournisseur ne correspond à votre recherche.",emptyList:"Aucun fournisseur configuré.",selectPrompt:"Sélectionnez un fournisseur pour afficher les détails",listStatus:"{{count}} modèle(s)",noModels:"Aucun modèle configuré",enabled:"Activé",disabled:"Désactivé",showEnabledOnly:"Afficher uniquement les activés",showAll:"Afficher tous les fournisseurs",dragHandle:"Glisser pour réordonner",reorderFailed:"Échec de l'enregistrement de l'ordre des fournisseurs",credentials:{apiKey:"Clé API",apiBaseUrl:"URL de base de l'API"},filter:{all:"Tous",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Sélectionner un modèle",skipTemplates:"Ignorer, configurer manuellement",name:"Nom *",providerType:"Type",apiType:"Type d'API",apiTypeOptions:{openai:"Complétion OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Format d'API chat/completions OpenAI standard",claudecode:"Format d'API Anthropic Messages (Claude Code)"},chatApiFormat:"Format d'API",chatApiFormatDescription:"Sélectionnez le format d'API correspondant à l'endpoint de votre fournisseur",apiKey:"Clé API",apiKeyPlaceholder:"sk-... ou $ENV_VAR",apiKeyHelper:"Utilisez $NOM_VAR pour référencer des variables d'environnement",apiKeySetPlaceholder:"Clé définie — laisser vide pour la conserver",apiKeyReplaceHelper:"Une clé est stockée de manière sécurisée. Saisissez une nouvelle valeur pour la remplacer, ou laissez vide pour la conserver.",testApiKey:"Tester la clé API",apiUrl:"URL de l'API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Aperçu :",models:"Modèles",modelPlaceholder:"Nom du modèle (ex. : gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"Transformers d'API",transformerConfigDescription:"Configurez les transformers pour adapter les formats de requête/réponse de l'API pour ce fournisseur",transformerConfigNote:"Le daemon applique ces transformers dans la chaîne de requêtes, après le transformer de format du fournisseur (qui gère la conversion du format wire). Les noms de transformers inconnus sont ignorés.",enabled:"Activé",apiVersion:"Version de l'API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Version de l'API Azure OpenAI (ex. : 2024-08-01-preview)",official:"API Anthropic officielle",officialHelper:"Activez si ce fournisseur se connecte directement à l'API Anthropic officielle. Désactivez pour les proxys inverses ou les services tiers.",maxConcurrency:"Requêtes simultanées max.",maxConcurrencyHelper:"Nombre maximum de requêtes API simultanées envoyées à ce fournisseur. Des valeurs plus basses aident à éviter la limitation de débit (erreurs 429). Définissez `-1` pour aucune limite.",codingPlan:{label:"Plan de codage",description:"Utiliser un endpoint d'API distinct pour les plans de codage par abonnement",baseUrl:"URL de base du plan de codage",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Clé API du plan de codage (optionnel)",apiKeyPlaceholder:"Laisser vide pour utiliser la clé API du fournisseur",apiKeyHelper:"Requis uniquement si le plan de codage utilise une clé API différente",tokenPlanHint:"Certains fournisseurs (ex. Xiaomi MiMo) émettent des clés Token Plan avec le préfixe `tp-` — informatif uniquement, non imposé."},selectTypeFirst:"Sélectionner le type de fournisseur",selectTypeFirstDesc:"Choisissez le type de fournisseur que vous souhaitez ajouter",codeProviderNote:"Les fournisseurs Code n'ont besoin que d'une clé API et d'une URL. Les modèles sont gérés par l'Agent Router.",buttons:{cancel:"Annuler",submitAdd:"Ajouter le fournisseur",submitUpdate:"Mettre à jour le fournisseur",continue:"Continuer",back:"Retour"}},details:{noSelection:"Sélectionnez un fournisseur pour afficher les détails",apiKey:"Clé API",apiUrl:"URL de l'API",nameLabel:"Nom du fournisseur",modelsEndpoint:"Endpoint des modèles",modelsEndpointHelper:"Remplacez l'endpoint de découverte si le fournisseur expose un chemin /models personnalisé.",models:"Modèles",transformers:"Transformers",codeProviderNote:"Les fournisseurs Code (comme Claude Code) ne nécessitent pas de configuration de modèle. Les modèles sont automatiquement gérés par l'Agent Router.",buttons:{more:"Paramètres avancés",delete:"Supprimer"}},providerModelSelector:{placeholder:"Sélectionner un fournisseur et un modèle",noProviders:"Aucun fournisseur disponible",noModels:"Aucun modèle configuré"},apiKeyPool:{title:"Pool de clés API",description:"Configurez plusieurs clés API pour l'équilibrage de charge. Chaque session reste associée à une clé pour préserver le cache des prompts.",defaultLabel:"Par défaut",weight:"Poids",noKey:"Aucune clé",labelPlaceholder:"Libellé (ex. : Clé n°1, Production)",addKey:"Ajouter une clé API",add:"Ajouter",empty:"Aucune clé supplémentaire configurée.",statusCoolingDown:"Refroidissement {{time}}",statusAuthFailed:"Échec d'authentification · désactivée",statusDisabled:"Désactivée",statusHealthy:"Opérationnelle",agoSeconds:"il y a {{count}}s",agoMinutes:"il y a {{count}}min",agoHours:"il y a {{count}}h",agoDays:"il y a {{count}}j"},modelsManager:{searchPlaceholder:"Rechercher des modèles...",defaultGroup:"Tous les modèles",add:"Ajouter un modèle",manage:"Gérer",empty:"Aucun modèle dans ce groupe",enabled:"Activé",disabled:"Désactivé",filters:{all:"Tous",vision:"Vision",reasoning:"Raisonnement",free:"Gratuit",tools:"Outils"},manualDialog:{title:"Ajouter un modèle",subtitle:"Ajouter un modèle personnalisé à ce fournisseur",modelId:"ID du modèle",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"L'identifiant exact du modèle utilisé lors des appels API",modelName:"Nom d'affichage",modelNamePlaceholder:"Nom d'affichage convivial (optionnel)",modelNameHelper:"Nom optionnel affiché dans l'interface. Si vide, l'ID du modèle sera utilisé",group:"Groupe",groupPlaceholder:"Sélectionner ou saisir un nom de groupe",submit:"Ajouter",cancel:"Annuler",helper:"Fournissez l'identifiant exact du modèle exposé par l'API du fournisseur."},editDialog:{title:"Modifier le modèle",subtitle:"Modifier les paramètres du modèle",modelId:"ID du modèle",modelIdPlaceholder:"Identifiant du modèle",modelIdHelper:"L'identifiant du modèle utilisé lors des appels API",modelName:"Nom d'affichage",modelNamePlaceholder:"Nom d'affichage convivial",modelNameHelper:"Nom affiché dans l'interface",group:"Groupe",groupPlaceholder:"Sélectionner ou saisir un nom de groupe",submit:"Enregistrer",cancel:"Annuler",vision:"Capacité Vision",visionHint:"Indique si ce modèle prend en charge les entrées image/vision",reasoning:"Modèle de raisonnement",reasoningHint:"Indique si ce modèle prend en charge le mode de réflexion/raisonnement"},manageDialog:{title:"Gérer les modèles",cachedAt:"Mis en cache le {{date}} ({{source}})",refresh:"Actualiser",close:"Fermer",raw:"JSON brut",empty:"Aucun modèle distant disponible.",error:"Échec du chargement des modèles : {{message}}",addFromCatalog:"Ajouter",sourceCache:"cache",sourceNetwork:"en direct",contextLength:"Contexte {{value}} tokens",maxTokens:"Max {{value}} tokens"},messages:{added:"Modèle ajouté.",updated:"Modèle mis à jour.",removed:"Modèle supprimé.",duplicate:"Le modèle existe déjà.",refreshed:"Modèles actualisés",refreshFailed:"Échec de l'actualisation des modèles"},testDialog:{title:"Test de connectivité du modèle",provider:"Fournisseur",model:"Modèle",testing:"Test en cours...",success:"Test réussi",successMessage:"Le modèle est accessible normalement",failure:"Échec du test",aiResponse:"Réponse de l'IA",charCount:"{{count}} caractères",duration:"Durée {{time}}s",close:"Fermer",retest:"Retester",testButton:"Tester le modèle",unsupportedFormat:"Le test n'est pas encore pris en charge pour ce format de fournisseur."}},router:{title:"Configuration du routeur",description:"Configurez le fournisseur/modèle à utiliser pour différents scénarios.",labels:{default:"Par défaut",background:"arrière-plan",think:"réflexion",longContext:"Contexte long",webSearch:"Recherche web",image:"Image",longContextThreshold:"Seuil de contexte long"},helper:{longContextThreshold:"Nombre de tokens avant de basculer vers le modèle à contexte long."},placeholder:{required:"Requis",optional:"Optionnel"}},agentRouter:{title:"Agent Router",description:"Configurez le routage bidirectionnel entre les modes Chat et Code.",searchPlaceholder:"Rechercher des routeurs...",noSearchResults:"Aucun routeur ne correspond à votre recherche.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Routeur Chat vers Code",description:"Utiliser des fournisseurs chat en mode agent/codage",addRouter:"Ajouter un routeur",emptyState:"Aucun routeur Chat→Code configuré. Ajoutez-en un pour utiliser des fournisseurs chat en mode codage.",form:{name:"Nom du routeur",namePlaceholder:"Mon routeur Chat→Code",chatProvider:"Fournisseur Chat",chatProviderPlaceholder:"Sélectionner un fournisseur chat",mode:"Mode",modeSimple:"Simple",modeAdvanced:"Avancé",modeSimpleDesc:"Transmission directe au fournisseur chat",modeAdvancedDesc:"Configurer le mappage des modèles et la gestion du contexte",enabled:"Activé",save:"Enregistrer le routeur",cancel:"Annuler"},list:{provider:"Fournisseur",mode:"Mode",status:"Statut"},mappings:{title:"Mappages de modèles",description:"Mapper les modèles du fournisseur Chat aux modèles du fournisseur Code",count:"mappage(s)",empty:"Aucun mappage de modèle configuré. Ajoutez des mappages pour router les modèles chat vers les fournisseurs code.",addNew:"Ajouter un nouveau mappage",selectSource:"Sélectionner le modèle source (Chat)",selectTarget:"Sélectionner le modèle cible (Code)",targetPlaceholder:"Entrez le nom du modèle Claude Code",notSet:"(Non défini - cliquez pour sélectionner)",add:"Ajouter",edit:"Modifier",done:"Terminé"},advanced:{title:"Configuration avancée",description:"Configurer les modèles pour différents types de tâches",helpText:"Le modèle par défaut est requis. Les autres modèles sont optionnels et se replieront sur le modèle par défaut s'ils ne sont pas configurés.",default:{label:"Par défaut",placeholder:"Sélectionner le modèle par défaut",description:"Modèle principal pour les tâches générales (similaire à Claude Sonnet)"},background:{label:"Arrière-plan",placeholder:"Sélectionner le modèle d'arrière-plan",description:"Modèle léger pour les tâches en arrière-plan (similaire à Claude Haiku)"},think:{label:"Réflexion",placeholder:"Sélectionner le modèle de réflexion",description:"Modèle avancé pour le raisonnement complexe (similaire à Claude Opus)"},image:{label:"Image",placeholder:"Sélectionner le modèle image",description:"Modèle pour les tâches liées aux images avec capacité vision"}}},codeToChat:{title:"Routeur Code vers Chat",description:"Exposer les modèles de plan de codage en mode chat",addRouter:"Ajouter un routeur",emptyState:"Aucun routeur Code→Chat configuré. Ajoutez-en un pour exposer les modèles de plan de codage en mode chat.",form:{name:"Nom du routeur",namePlaceholder:"Mon routeur Code→Chat",codeProvider:"Fournisseur Code",codeProviderPlaceholder:"Sélectionner un fournisseur code",codeProviderHelper:"Sélectionnez le fournisseur Code à utiliser pour la transformation",models:"Modèles de plan de codage",modelsHelper:"Sélectionnez les modèles de plan de codage à exposer",enabled:"Activé",save:"Enregistrer le routeur",cancel:"Annuler"},mappings:{title:"Mappages de modèles",description:"Mapper les modèles du fournisseur Code aux modèles du fournisseur Chat pour les exposer",count:"mappage(s)",empty:"Aucun mappage de modèle configuré. Ajoutez des mappages pour exposer les modèles Code en mode chat.",addNew:"Ajouter un nouveau mappage",selectSource:"Sélectionner le modèle source (Code)",selectTarget:"Sélectionner le modèle cible (Chat)",sourcePlaceholder:"Entrez le nom du modèle source",targetPlaceholder:"Entrez le nom du modèle cible",add:"Ajouter",edit:"Modifier",done:"Terminé"}},transformers:{title:"Transformers",description:"Configurer les transformers pour la conversion des requêtes/réponses",noProvider:"Sélectionnez un fournisseur pour configurer les transformers",empty:"Aucun transformer",count:"{{count}} transformer(s)"},status:{enabled:"Activé",disabled:"Désactivé"},messages:{routerAdded:"Routeur ajouté avec succès",routerUpdated:"Routeur mis à jour avec succès",routerDeleted:"Routeur supprimé avec succès",saveFailed:"Échec de l'enregistrement du routeur"}},presets:{title:"Ajout rapide de fournisseur",added:"Ajouté",add:"Ajouter",features:{search:"Recherche",vision:"Vision",mcp:"MCP",codingPlan:"Plan de codage"}},alerts:{deleteConfirm:"Êtes-vous sûr de vouloir supprimer ce fournisseur ?"},errors:{nameRequired:"Le nom du fournisseur est requis",urlRequired:"L'URL de base de l'API est requise",urlInvalid:"Veuillez entrer une URL valide (ex. : https://api.example.com)",saveFailed:"Échec de l'enregistrement du fournisseur",deleteFailed:"Erreur lors de la suppression du fournisseur. Veuillez réessayer.",toggleFailed:"Erreur lors de l'activation/désactivation du fournisseur. Veuillez réessayer."},openRouter:{title:"Routage des fournisseurs OpenRouter",description:"Configurez la façon dont les requêtes sont routées vers différents fournisseurs sur OpenRouter.",sort:"Stratégie de routage",sortTooltip:"Choisissez comment prioriser les fournisseurs. Auto utilise un équilibrage de charge intelligent.",order:"Ordre de priorité des fournisseurs",orderTooltip:"Spécifiez les fournisseurs à essayer dans l'ordre (ex. : anthropic, openai, together). Appuyez sur Entrée pour ajouter.",orderPlaceholder:"Tapez le slug du fournisseur et appuyez sur Entrée...",allowFallbacks:"Autoriser les replis",allowFallbacksTooltip:"Lorsqu'activé, OpenRouter essaiera des fournisseurs de secours si le principal est indisponible.",requireParameters:"Exiger tous les paramètres",requireParametersTooltip:"Routez uniquement vers des fournisseurs qui prennent en charge tous les paramètres de votre requête.",dataCollection:"Politique de collecte de données",dataCollectionTooltip:"Contrôlez si vous utilisez des fournisseurs susceptibles de stocker ou d'entraîner des modèles sur vos données.",zdr:"Zéro rétention de données",zdrTooltip:"Routez uniquement vers des endpoints avec une politique de zéro rétention de données.",only:"Autoriser uniquement ces fournisseurs",onlyTooltip:"N'utilisez que ces fournisseurs spécifiques. Laissez vide pour autoriser tous les fournisseurs.",onlyPlaceholder:"Tapez le slug du fournisseur et appuyez sur Entrée...",ignore:"Ignorer les fournisseurs",ignoreTooltip:"Ignorez ces fournisseurs lors du routage des requêtes.",ignorePlaceholder:"Tapez le slug du fournisseur et appuyez sur Entrée...",quantizations:"Filtre de quantification",quantizationsTooltip:"N'utilisez que des fournisseurs avec des niveaux de quantification spécifiques. Une précision plus faible peut réduire la qualité mais améliorer la vitesse.",maxPrice:"Prix maximum",maxPriceTooltip:"Définissez des limites de prix maximales par million de tokens. Laissez vide pour aucune limite.",configured:"Configuré"}},Kx={label:"Mode API",standard:"Standard",codingPlan:"Plan de codage",tokenPlan:"Plan de tokens",apiKeyPrefixHint:"Les clés pour ce plan commencent généralement par `{{prefix}}`. Indication uniquement — non imposé.",dashscopeCodingPlanSeparateKey:"Le plan de codage DashScope utilise une clé API distincte de l'endpoint standard.",baiduCodingPlanSeparateKey:"Le plan de codage Qianfan utilise une clé API distincte de l'endpoint standard.",tencentTokenPlanAnthropicOnly:"Le plan de tokens Tencent est exclusivement compatible avec le protocole Anthropic.",xiaomiTokenPlanRegions:"L'URL de base par défaut est `token-plan-cn.*`. Vous pouvez la modifier manuellement en `token-plan-sgp.*` ou `token-plan-ams.*`.",confirmOverwriteTitle:"Changer de mode API ?",confirmOverwriteBody:"Vous avez personnalisé l'URL de l'API ou la clé API. Changer de mode écrasera ces valeurs avec les paramètres par défaut du nouveau mode — ou conservez vos personnalisations en ne mettant à jour que le libellé du mode.",overwriteAndSwitch:"Écraser et changer",keepCustomizations:"Conserver les personnalisations"},Ux={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},Hx={cancel:"Annuler",close:"Fermer",copy:"Copier",delete:"Supprimer",dismiss:"Ignorer",save:"Enregistrer",optional:"optionnel",retry:"Réessayer",loading:"Chargement…"},Fx={common:{learnMore:"Documentation"}},Bx={notSupportedByDaemon:"Pas encore pris en charge par le daemon",discoveryUnsupportedFormat:"La découverte de modèles n'est pas encore prise en charge pour ce format de fournisseur. Ajoutez les modèles manuellement."},Vx={subtitle:"Panneau de contrôle",providers:"Fournisseurs",apiService:"Service API",accounts:"Comptes",codeCli:"Code CLI",settings:"Paramètres",usageStats:"Utilisation",pricing:"Tarifs"},qx={title:"Service API",description:"Configurez le serveur API sortant, le routage des modèles par endpoint et les clés d'accès nommées.",loading:"Chargement de la configuration du serveur…",loadError:"Impossible de charger la configuration du serveur. Vérifiez que le daemon est accessible.",enable:{label:"Activer le serveur sortant",description:"Démarrez le serveur API local qui route les appelants externes via vos fournisseurs."},networkBinding:{label:"Autoriser l'accès LAN",description:"Associez le serveur à votre interface réseau plutôt qu'à la seule boucle locale.",warning:"L'accès LAN expose le serveur API aux autres appareils de votre réseau. Combiné avec le routage par abonnement, les requêtes peuvent consommer votre quota d'abonnement — désactivez cette option sauf si vous faites confiance au réseau."},status:{running:"Serveur en cours d'exécution",stopped:"Serveur arrêté",runningHint:"Le serveur API sortant accepte les requêtes.",stoppedHint:"Activez le serveur pour commencer à accepter les requêtes.",port:"port {{port}}",loopback:"URLs de boucle locale",lan:"URLs LAN"},endpoints:{title:"Routage des endpoints",description:"Choisissez le modèle vers lequel chaque format wire est routé. Le modèle par défaut est défini ici — le serveur est un routeur, pas une application de chat."},endpoint:{name:{chat:"Chat OpenAI",responses:"Réponses OpenAI",messages:"Messages Anthropic",gemini:"Gemini"},defaultModel:"Modèle par défaut",backgroundModel:"Modèle d'arrière-plan",visionModel:"Modèle Vision",noVisionModel:"Aucun",backgroundModelIds:"IDs des modèles d'arrière-plan",backgroundModelIdsPlaceholder:"IDs de modèles séparés par des virgules",modelPlaceholder:"Sélectionner un modèle…",useSubscription:"Utiliser l'abonnement",subscriptionUnsupported:"Le routage par abonnement n'est pas disponible pour cet endpoint."},keys:{title:"Clés d'accès",description:"Clés nommées que les appelants externes envoient en tant que token Bearer. La clé complète n'est affichée qu'une seule fois à la création.",namePlaceholder:"Nom de la clé (ex. : mon-cli)",create:"Créer une clé",empty:"Aucune clé d'accès pour l'instant.",enabled:"Activée",disabled:"Désactivée",revoked:"Révoquée",toggle:"Activer/Désactiver la clé",revoke:"Révoquer",revokeConfirmTitle:"Révoquer cette clé ?",revokeConfirmDesc:"La révocation de « {{name}} » l'empêche immédiatement de s'authentifier. Cette action est irréversible.",created:{title:"Clé créée",warning:"Copiez cette clé maintenant — elle ne sera plus affichée. Conservez-la en lieu sûr.",copy:"Copier",copied:"Copié",dismiss:"Terminé"}}},$x={title:"Comptes et abonnements",description:"Gérez les identifiants d'abonnement que le serveur route. Les tokens sont écrits ici mais jamais affichés en retour.",loading:"Chargement des comptes…",empty:"Aucun fournisseur d'abonnement disponible.",signIn:"Se connecter",oauth:{title:"Se connecter à {{name}}",description:"Ouvrez la page de connexion dans votre navigateur, autorisez, puis collez le code d'autorisation ci-dessous. Le code est transmis uniquement au daemon — le token généré n'est jamais affiché.",openPage:"Ouvrir la page de connexion",codeLabel:"Code d'autorisation",codePlaceholder:"Collez le code ici",submit:"Terminer la connexion"},codexOauth:{title:"Se connecter à {{name}}",description:"Ouvrez la page de connexion dans votre navigateur et autorisez. Le daemon capture automatiquement le résultat — gardez cette fenêtre ouverte jusqu'à la fin. Le token n'est jamais affiché.",waiting:"En attente de la fin de la connexion dans votre navigateur…",failed:"Échec de la connexion. Veuillez réessayer."},clearProvider:"Tout effacer",clearConfirmTitle:"Effacer les comptes {{name}} ?",clearConfirmDesc:"Cela supprime tous les identifiants stockés pour ce fournisseur. Cette action est irréversible.",credential:{ok:"Configuré",notConfigured:"Non configuré"},kind:{"pass-through":"Identifiants pass-through","oauth-bearer":"Bearer OAuth","static-bearer":"Clé bearer statique"},reason:{"missing-credential":"Aucun identifiant stocké.",expired:"Identifiant expiré.","reauth-required":"Ré-authentification requise.","refresh-failed":"Échec du renouvellement du token.","not-refreshable":"L'identifiant ne peut pas être renouvelé.",unknown:"Statut inconnu."},status:{unconfigured:"Non configuré",authorized:"Autorisé",configured:"Configuré",expired:"Expiré",error:"Erreur"},authMethod:{oauth:"OAuth",setup_token:"Token de configuration",manual:"Manuel"},list:{empty:"Aucun compte stocké pour ce fournisseur.",active:"Actif",expiresAt:"Expire le {{value}}",setActive:"Définir comme actif",remove:"Supprimer",removeConfirmTitle:"Supprimer ce compte ?",removeConfirmDesc:"La suppression de « {{name}} » efface son identifiant stocké. Cette action est irréversible.",title:"Comptes"},write:{trigger:"Ajouter un identifiant",title:"Écrire un identifiant {{name}}",description:"Collez un token déjà obtenu. Les champs sont limités à ce que ce fournisseur accepte ; le token est stocké, jamais affiché en retour.",authMethod:"Méthode d'authentification",status:"Statut",subscriptionLevel:"Niveau d'abonnement",subscriptionLevelNone:"Non défini",submit:"Enregistrer l'identifiant"},field:{accessToken:"Token d'accès",refreshToken:"Token de renouvellement",idToken:"Token d'identité",apiKey:"Clé API",expiresAt:"Expire le (ISO)",setupTokenExpiresAt:"Le token de configuration expire le (ISO)",accountId:"ID de compte",email:"E-mail",organizationId:"ID d'organisation",baseUrl:"URL de base",zenBaseUrl:"URL de base Zen"},provider:{claude:{title:"Claude",description:"Identifiants d'abonnement Anthropic routés par le daemon."},codex:{title:"Codex",description:"Identifiants d'abonnement OpenAI Codex routés par le daemon."},gemini:{title:"Gemini",description:"Identifiants d'abonnement Google Gemini routés par le daemon."},opencodego:{title:"OpenCodeGo",description:"Identifiants de clé API statique routés par le daemon."}},authMethodLabel:"Méthode d'autorisation",authMethodDesc:{oauth:"Connectez-vous via votre navigateur ; le daemon capture et stocke le token.",manual:"Collez un token déjà obtenu. Il est stocké, jamais affiché en retour."},actions:{authorize:"Autoriser",enterToken:"Saisir le token",refresh:"Actualiser"},accounts:{addAccount:"Ajouter un compte"},detail:{authMethod:"Méthode d'autorisation",subscriptionLevel:"Niveau d'abonnement",expiresAt:"Expire le",lastRefreshed:"Dernier renouvellement",label:"Libellé du compte",labelPlaceholder:"Nommer ce compte",saveLabel:"Enregistrer le libellé"},oauthFlow:{step1:{title:"Ouvrir la page d'autorisation",desc:"Ouvrez la page de connexion dans votre navigateur."},step2:{title:"Autoriser l'accès",desc:"Connectez-vous et approuvez l'accès pour le fournisseur."},step3:{title:"Copier le code d'autorisation",desc:"La page affiche un code d'autorisation après votre approbation."},step4:{title:"Coller le code",desc:"Collez le code d'autorisation ci-dessous pour terminer. Le code est transmis uniquement au daemon — le token généré n'est jamais affiché."},authorize:"Terminer la connexion",showUrl:"Afficher l'URL d'autorisation"},manual:{title:"Coller l'identifiant",description:"Collez un token déjà obtenu. Les champs sont limités à ce que ce fournisseur accepte ; le token est stocké, jamais affiché en retour.",accessTokenPlaceholder:"Collez le token d'accès",refreshTokenPlaceholder:"Collez le token de renouvellement (optionnel)",hint:"Le token est envoyé au daemon et stocké de manière chiffrée. Il n'est jamais affiché en retour."},openCodeGo:{apiKeyRequired:"Une clé API est requise.",apiKeyPlaceholder:"Collez la clé API",baseUrlPlaceholder:"https://… (optionnel)",zenBaseUrlPlaceholder:"https://… (optionnel)"},info:{title:"À propos des comptes d'abonnement",description:"Les tokens sont écrits dans le daemon et utilisés pour authentifier les requêtes en amont. Ils sont stockés de manière chiffrée et jamais affichés en retour. La suppression d'un compte efface son identifiant stocké."},rename:{failed:"Impossible de renommer le compte."},refresh:{failed:"Impossible de renouveler le token."},errors:{requestFailed:"La requête a échoué. Veuillez réessayer."},syncWarning:{"external-divergent":"Le fichier de connexion de la CLI externe contient des identifiants plus récents que ce compte. Le jeton enregistré pourrait ne plus se rafraîchir — rafraîchissez maintenant ou reconnectez-vous.","external-not-rotated":"Le rafraîchissement a échoué et la CLI externe contient les mêmes identifiants expirés. Veuillez vous reconnecter.","duplicate-token":"Un autre compte partage ces identifiants. Rafraîchir l'un déconnectera l'autre."},importExternal:{detected:"Une connexion CLI {{name}} existante a été détectée sur cette machine.",hint:"Après l'import, cette application la maintient à jour : à chaque rafraîchissement du jeton, le fichier de connexion de la CLI est aussi mis à jour, et la CLI du terminal reste connectée.",button:"Importer la connexion CLI existante"}},_x={title:"Code CLI",description:"Pointez un CLI de codage vers le proxy sortant du daemon. Cette page est en lecture seule — il n'y a rien à configurer ici.",copy:"Copier",copied:"Copié",baseUrl:{title:"URL de base du daemon",description:"L'adresse du proxy à laquelle votre CLI se connecte.",label:"URL de base"},token:{title:"Authentification",hint:"Envoyez 'Authorization: Bearer <votre-token-admin>' pour les routes admin. Le token admin est configuré dans le daemon (son fichier de config ou son environnement) — il n'est jamais affiché ici."},examples:{title:"Exemple d'environnement de lancement",keyNote:"Utilisez une clé d'accès sortante créée sur la page Service API — pas le token admin.",anthropic:"CLI au format Anthropic",openai:"CLI au format OpenAI"},launchDescription:"Lancez un CLI de codage dans un terminal, pointé vers ce daemon. Le daemon injecte l'environnement de redirection et démarre le CLI pour vous.",refresh:"Actualiser",loading:"Détection des CLIs…",cli:{installed:"Installé",notFound:"Introuvable",notFoundHint:"Ce CLI n'est pas dans le PATH de l'hôte daemon. Installez-le, puis actualisez.",install:"Installer",installing:"Installation…",installingHint:"Installation sur l'hôte daemon — cela peut prendre une minute.",launch:"Lancer",launchTitle:"Lancer {{name}}",launchDescription:"Ouvre un nouveau terminal sur l'hôte daemon exécutant ce CLI, routé via le proxy daemon. Choisissez un répertoire de travail optionnel.",cwdLabel:"Répertoire de travail",cwdPlaceholder:"/chemin/vers/votre/projet",runningVia:"En cours · {{provider}} / {{model}}",stop:"Arrêter"},manual:{title:"Configuration manuelle",description:"Vous préférez exécuter le CLI vous-même ? Pointez-le vers le daemon avec ces variables d'environnement.",show:"Afficher",hide:"Masquer"}},Gx={probing:"Vérification du daemon…",spawning:"Démarrage du daemon…",failed:"Le daemon n'a pas pu démarrer",failedHint:"Assurez-vous que Node.js est installé et que le daemon est compilé (dist présent), ou définissez OMNICROSS_DAEMON_ENTRY vers le cli.js du daemon."},Wx={title:"Paramètres",description:"Préférences de l'application de bureau.",desktopOnly:"Les options de démarrage et de barre des tâches s'appliquent uniquement à l'application de bureau.",startup:{title:"Démarrage",autoLaunch:"Lancer au démarrage de session",autoLaunchHint:"Démarrer Omnicross automatiquement lors de la connexion.",startMinimized:"Démarrer réduit dans la barre des tâches",startMinimizedHint:"Lancer en arrière-plan sans ouvrir la fenêtre."},tray:{title:"Barre des tâches",minimizeOnClose:"Réduire dans la barre des tâches à la fermeture",minimizeOnCloseHint:"Fermer la fenêtre la masque dans la barre des tâches au lieu de quitter."},language:{title:"Langue",label:"Langue de l'interface"}},Zx={title:"Statistiques d'utilisation",description:"Statistiques de tokens et de coûts des requêtes servies par le démon.",rangeToday:"Aujourd'hui",range7d:"7 derniers jours",range30d:"30 derniers jours",rangeCustom:"Personnalisé",from:"Du",to:"Au",totalCost:"Coût total",cacheSavings:"Économies de cache",events:"Requêtes",inputTokens:"Tokens d'entrée",outputTokens:"Tokens de sortie",cacheReadTokens:"Lecture cache",cacheWriteTokens:"Écriture cache",reasoningTokens:"Tokens de raisonnement",byModel:"Par modèle",byApiKey:"Par clé API",provider:"Fournisseur",model:"Modèle",cost:"Coût",apiKey:"Clé API",unpriced:"Sans tarif",unpricedHint:"Aucune entrée tarifaire pour ce modèle — ajoutez-en une sur la page Tarifs.",unattributed:"Non attribué",unattributedHint:"Requêtes non liées à une clé API précise. C'est normal tant que l'attribution par clé n'est pas enregistrée.",empty:"Aucune requête sur cette période.",invalidRange:"Sélectionnez une plage de dates valide."},Qx={title:"Tarifs des modèles",description:"Prix des tokens par modèle utilisés pour calculer le coût des requêtes, en USD par million de tokens.",search:"Rechercher un fournisseur ou un modèle…",fetchLatest:"Récupérer les derniers",fetching:"Récupération…",addEntry:"Ajouter une entrée",provider:"Fournisseur",model:"Modèle",inputPrice:"Entrée",outputPrice:"Sortie",cacheReadPrice:"Lecture cache",cacheWritePrice:"Écriture cache",source:"Source",updated:"Mis à jour",userEdited:"modifié",edit:"Modifier",deleteTitle:"Supprimer cette entrée tarifaire ?",empty:"La table des tarifs est vide.",emptyHint:"Récupérez les derniers tarifs pour la remplir.",noMatches:"Aucune entrée ne correspond à votre recherche.",saved:"Entrée tarifaire enregistrée.",saveFailed:"Échec de l'enregistrement : {{message}}",deleteFailed:"Échec de la suppression : {{message}}",alreadyDeleted:"L'entrée n'existait déjà plus.",fetchApplied:"{{count}} entrées mises à jour depuis la source.",fetchFailed:"Échec de la récupération : {{message}}",requiredId:"Requis",invalidPrice:"Saisissez un nombre positif ou nul",conflictTitle:"Résoudre les conflits de tarifs",conflictHint:"Ces entrées ont été modifiées par vous et ont aussi changé à la source. Choisissez ligne par ligne de conserver votre valeur (Ignorer) ou de prendre la nouvelle (Écraser).",current:"Actuel",incoming:"Entrant",overwrite:"Écraser",skip:"Ignorer",overwriteAll:"Tout écraser",skipAll:"Tout ignorer",applyResolutions:"Appliquer",resolved:"{{overwritten}} écrasées, {{skipped}} ignorées.",resolvedWithStale:"{{overwritten}} écrasées, {{skipped}} ignorées. {{stale}} ont changé entre-temps et sont restées intactes.",refreshFailed:"La modification a été appliquée, mais le rechargement de la liste a échoué : {{message}}",sourceBuiltin:"Intégré",sourceLitellm:"LiteLLM",sourceUser:"Utilisateur"},Yx={providerSettings:Ox,apiMode:Kx,presetName:Ux,common:Hx,mediaSettings:Fx,appLocal:Bx,nav:Vx,apiService:qx,accounts:$x,codeCli:_x,daemonStatus:Gx,settings:Wx,usageStats:Zx,pricing:Qx},Xx={loading:"LLM konfiguráció betöltése...",reset:{button:"Alapértékek visszaállítása",confirmTitle:"Visszaállítja az alapértelmezett beállításokat?",confirmBody:"Ez törli a szolgáltatóhoz tartozó testreszabásait, és visszaállítja a beépített alapértelmezéseket. Az API-kulcs és a mentett munkamenetek megmaradnak.",confirmButton:"Alapértékek visszaállítása"},reentryBanner:{message:"{{count}} engedélyezett szolgáltató(k) esetén újra meg kell adni az API-kulcsot. Nyissa meg mindegyiket, és adja meg újra a kulcsot."},migrationPack:{barHint:"Vigye át a szolgáltatói kulcsokat és az előfizetési tokeneket egy másik gépre titkosított csomag segítségével.",passphrase:"Jelmondat",passphrasePlaceholder:"Adjon meg egy jelmondatot",passphraseHint:"Használjon legalább 8 karaktert; 12 vagy több javasolt.",confirm:"Jelmondat megerősítése",confirmPlaceholder:"Írja be újra a jelmondatot",mismatch:"A jelmondatok nem egyeznek.",strength:{weak:"Túl rövid — használjon legalább 8 karaktert.",fair:"Megfelelő — 12 vagy több karakter erősebb.",strong:"Erős jelmondat."},export:{button:"Csomag exportálása",title:"Titkosított csomag exportálása",subtitle:"Titkosítsa a szolgáltatói kulcsokat és az előfizetési tokeneket egy hordozható fájlba.",warning:"Ez a fájl visszafejthető titkokat tartalmaz. Tárolja biztonságosan — bárki, aki rendelkezik a fájllal és a jelmondattal, olvashatja a kulcsait. Az elveszett jelmondat nem állítható vissza.",submit:"Exportálás",success:"A csomag sikeresen exportálva.",error:"Az exportálás sikertelen. Kérjük, próbálja újra."},import:{button:"Csomag importálása",title:"Titkosított csomag importálása",subtitle:"Állítsa vissza a szolgáltatói kulcsokat és az előfizetési tokeneket egy exportált csomagból.",hint:"Adja meg a csomag exportálásakor használt jelmondatot, majd válassza ki a fájlt.",submit:"Importálás",successTitle:"Importálás befejezve",summary:"Importálva: {{providerKeys}} szolgáltatói kulcs, {{poolKeys}} pool-kulcs és {{tokenSets}} tokenszett.",duplicates:"Kihagyva {{count}} már meglévő pool-kulcs.",skipped:"Kihagyva (nincs egyező szolgáltató): {{names}}",error:"Helytelen jelmondat vagy sérült csomag. Semmi sem változott."}},searchPlaceholder:"Szolgáltatók keresése...",emptySearch:"Nincs a keresésnek megfelelő szolgáltató.",emptyList:"Nincs konfigurált szolgáltató.",selectPrompt:"Válasszon egy szolgáltatót a részletek megtekintéséhez",listStatus:"{{count}} modell",noModels:"Nincs konfigurált modell",enabled:"Engedélyezve",disabled:"Letiltva",showEnabledOnly:"Csak engedélyezettek megjelenítése",showAll:"Összes szolgáltató megjelenítése",dragHandle:"Húzza az átrendezéshez",reorderFailed:"A szolgáltatók sorrendjét nem sikerült menteni",credentials:{apiKey:"API-kulcs",apiBaseUrl:"API alap URL"},filter:{all:"Összes",chat:"Chat",code:"Kód"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Sablon kiválasztása",skipTemplates:"Kihagyás, manuális konfigurálás",name:"Név *",providerType:"Típus",apiType:"API típus",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Szabványos OpenAI chat/completions API formátum",claudecode:"Anthropic Messages API formátum (Claude Code)"},chatApiFormat:"API formátum",chatApiFormatDescription:"Válassza ki a szolgáltató végpontjának megfelelő API formátumot",apiKey:"API-kulcs",apiKeyPlaceholder:"sk-... vagy $KÖRNYEZETI_VÁLTOZÓ",apiKeyHelper:"Használja a $VÁLTOZÓ_NEVE formát a környezeti változókra való hivatkozáshoz",apiKeySetPlaceholder:"A kulcs be van állítva — hagyja üresen a megtartáshoz",apiKeyReplaceHelper:"A kulcs biztonságosan tárolva van. Írjon be új értéket a cseréhez, vagy hagyja üresen a megtartáshoz.",testApiKey:"API-kulcs tesztelése",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Előnézet:",models:"Modellek",modelPlaceholder:"Modell neve (pl. gpt-4, claude-3-opus)",transformers:"Transzformátorok",transformerConfig:"API transzformátorok",transformerConfigDescription:"Konfigurálja a transzformátorokat az API kérés/válasz formátumok adaptálásához ennél a szolgáltatónál",transformerConfigNote:"A daemon ezeket a transzformátorokat a kérési láncban alkalmazza, a szolgáltató formátumtranszformátora után (amely a hálózati formátum konverzióját kezeli). Az ismeretlen transzformátorneveket a rendszer kihagyja.",enabled:"Engedélyezve",apiVersion:"API verzió",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API verzió (pl. 2024-08-01-preview)",official:"Hivatalos Anthropic API",officialHelper:"Engedélyezze, ha ez a szolgáltató közvetlenül a hivatalos Anthropic API-hoz csatlakozik. Tiltsa le fordított proxyk vagy harmadik féltől származó szolgáltatások esetén.",maxConcurrency:"Maximális egyidejű kérések",maxConcurrencyHelper:"A szolgáltatónak küldött egyidejű API kérések maximális száma. Az alacsonyabb értékek segítenek elkerülni a sebességkorlátozást (429-es hibák). Állítsa `-1`-re a korlátlan beállításhoz.",codingPlan:{label:"Kódolási terv",description:"Használjon külön API végpontot az előfizetés alapú kódolási tervekhez",baseUrl:"Kódolási terv alap URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kódolási terv API-kulcsa (opcionális)",apiKeyPlaceholder:"Hagyja üresen a szolgáltató API-kulcsának használatához",apiKeyHelper:"Csak akkor szükséges, ha a kódolási terv eltérő API-kulcsot használ",tokenPlanHint:"Egyes szolgáltatók (pl. Xiaomi MiMo) `tp-` előtagú Token Plan kulcsokat bocsátanak ki — csak tájékoztató jellegű, nem kötelező érvényű."},selectTypeFirst:"Válassza ki a szolgáltató típusát",selectTypeFirstDesc:"Válassza ki, milyen típusú szolgáltatót szeretne hozzáadni",codeProviderNote:"A kód-szolgáltatóknak csak API-kulcs és URL szükséges. A modelleket az ügynök-útválasztó kezeli.",buttons:{cancel:"Mégse",submitAdd:"Szolgáltató hozzáadása",submitUpdate:"Szolgáltató frissítése",continue:"Folytatás",back:"Vissza"}},details:{noSelection:"Válasszon egy szolgáltatót a részletek megtekintéséhez",apiKey:"API-kulcs",apiUrl:"API URL",nameLabel:"Szolgáltató neve",modelsEndpoint:"Modellek végpontja",modelsEndpointHelper:"Felülírja a felderítési végpontot, ha a szolgáltató egyéni /models elérési utat biztosít.",models:"Modellek",transformers:"Transzformátorok",codeProviderNote:"A kód-szolgáltatók (mint a Claude Code) nem igényelnek modellkonfigurációt. A modelleket az ügynök-útválasztó automatikusan kezeli.",buttons:{more:"További beállítások",delete:"Törlés"}},providerModelSelector:{placeholder:"Válasszon szolgáltatót és modellt",noProviders:"Nincs elérhető szolgáltató",noModels:"Nincs konfigurált modell"},apiKeyPool:{title:"API-kulcs pool",description:"Konfiguráljon több API-kulcsot a terheléselosztáshoz. Minden munkamenet egy kulcshoz van kötve a prompt gyorsítótár megőrzéséhez.",defaultLabel:"Alapértelmezett",weight:"Súly",noKey:"Nincs kulcs",labelPlaceholder:"Cimke (pl. 1. kulcs, Éles)",addKey:"API-kulcs hozzáadása",add:"Hozzáadás",empty:"Nincsenek további konfigurált kulcsok.",statusCoolingDown:"Lehűlés {{time}}",statusAuthFailed:"Hitelesítés sikertelen · letiltva",statusDisabled:"Letiltva",statusHealthy:"Megfelelő",agoSeconds:"{{count}}mp ezelőtt",agoMinutes:"{{count}}p ezelőtt",agoHours:"{{count}}ó ezelőtt",agoDays:"{{count}}n ezelőtt"},modelsManager:{searchPlaceholder:"Modellek keresése...",defaultGroup:"Összes modell",add:"Modell hozzáadása",manage:"Kezelés",empty:"Ebben a csoportban nincsenek modellek",enabled:"Engedélyezve",disabled:"Letiltva",filters:{all:"Összes",vision:"Látás",reasoning:"Következtetés",free:"Ingyenes",tools:"Eszközök"},manualDialog:{title:"Modell hozzáadása",subtitle:"Egyéni modell hozzáadása ehhez a szolgáltatóhoz",modelId:"Modell azonosítója",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash stb.",modelIdHelper:"Az API hívásakor használt pontos modellazonosító",modelName:"Megjelenített név",modelNamePlaceholder:"Felhasználóbarát megjelenített név (opcionális)",modelNameHelper:"A felületen megjelenített opcionális név. Ha üres, a modell azonosítója kerül felhasználásra",group:"Csoport",groupPlaceholder:"Válasszon vagy adjon meg egy csoportnevet",submit:"Hozzáadás",cancel:"Mégse",helper:"Adja meg a szolgáltató API által megjelenített pontos modellazonosítót."},editDialog:{title:"Modell szerkesztése",subtitle:"Modellbeállítások módosítása",modelId:"Modell azonosítója",modelIdPlaceholder:"Modellazonosító",modelIdHelper:"Az API hívásakor használt modellazonosító",modelName:"Megjelenített név",modelNamePlaceholder:"Felhasználóbarát megjelenített név",modelNameHelper:"A felületen megjelenített név",group:"Csoport",groupPlaceholder:"Válasszon vagy adjon meg egy csoportnevet",submit:"Mentés",cancel:"Mégse",vision:"Látási képesség",visionHint:"Ez a modell támogatja-e a kép/látás bemenetet",reasoning:"Gondolkodási modell",reasoningHint:"Ez a modell támogatja-e a gondolkodási/következtetési módot"},manageDialog:{title:"Modellek kezelése",cachedAt:"Gyorsítótárazva: {{date}} ({{source}})",refresh:"Frissítés",close:"Bezárás",raw:"Nyers JSON",empty:"Nincsenek elérhető távoli modellek.",error:"A modellek betöltése sikertelen: {{message}}",addFromCatalog:"Hozzáadás",sourceCache:"gyorsítótár",sourceNetwork:"élő",contextLength:"Kontextus: {{value}} token",maxTokens:"Max. {{value}} token"},messages:{added:"Modell hozzáadva.",updated:"Modell frissítve.",removed:"Modell eltávolítva.",duplicate:"A modell már létezik.",refreshed:"Modellek frissítve",refreshFailed:"A modellek frissítése sikertelen"},testDialog:{title:"Modell kapcsolattesztelés",provider:"Szolgáltató",model:"Modell",testing:"Tesztelés...",success:"Teszt sikeres",successMessage:"A modell normálisan elérhető",failure:"Teszt sikertelen",aiResponse:"AI válasz",charCount:"{{count}} karakter",duration:"Időtartam: {{time}}s",close:"Bezárás",retest:"Újratesztelés",testButton:"Modell tesztelése",unsupportedFormat:"Az ehhez a szolgáltatói formátumhoz tartozó tesztelés még nem támogatott."}},router:{title:"Útválasztó konfigurációja",description:"Konfigurálja, melyik szolgáltatót/modellt használja különböző forgatókönyvekhez.",labels:{default:"Alapértelmezett",background:"háttér",think:"gondolkodás",longContext:"Hosszú kontextus",webSearch:"Webes keresés",image:"Kép",longContextThreshold:"Hosszú kontextus küszöbértéke"},helper:{longContextThreshold:"A tokenszám, amelynél a hosszú kontextusú modellre vált."},placeholder:{required:"Kötelező",optional:"Opcionális"}},agentRouter:{title:"Ügynök-útválasztó",description:"Konfigurálja a kétirányú útválasztást a Chat és a Kód módok között.",searchPlaceholder:"Útválasztók keresése...",noSearchResults:"Nincs a keresésnek megfelelő útválasztó.",tabs:{chatToCode:"Chat → Kód",codeToChatPlaceholder:"Kód → Chat"},chatToCode:{title:"Chat–Kód útválasztó",description:"Chat-szolgáltatók használata ügynök/kódolási módban",addRouter:"Útválasztó hozzáadása",emptyState:"Nincsenek konfigurált Chat→Kód útválasztók. Adjon hozzá egyet a chat-szolgáltatók kódolási módban való használatához.",form:{name:"Útválasztó neve",namePlaceholder:"Saját Chat→Kód útválasztó",chatProvider:"Chat-szolgáltató",chatProviderPlaceholder:"Válasszon chat-szolgáltatót",mode:"Mód",modeSimple:"Egyszerű",modeAdvanced:"Speciális",modeSimpleDesc:"Közvetlen átvitel a chat-szolgáltatóhoz",modeAdvancedDesc:"Modelltérképezés és kontextuskezelés konfigurálása",enabled:"Engedélyezve",save:"Útválasztó mentése",cancel:"Mégse"},list:{provider:"Szolgáltató",mode:"Mód",status:"Állapot"},mappings:{title:"Modelltérképezések",description:"Chat-szolgáltató modelljei leképezése kód-szolgáltató modelljeire",count:"térképezés",empty:"Nincsenek konfigurált modelltérképezések. Adjon hozzá térképezéseket a chat-modellek kód-szolgáltatókhoz való irányításához.",addNew:"Új térképezés hozzáadása",selectSource:"Forrásmödell kiválasztása (Chat)",selectTarget:"Célmodell kiválasztása (Kód)",targetPlaceholder:"Adja meg a Claude Code modell nevét",notSet:"(Nincs beállítva — kattintson a kiválasztáshoz)",add:"Hozzáadás",edit:"Szerkesztés",done:"Kész"},advanced:{title:"Speciális konfiguráció",description:"Konfigurálja a modelleket különböző feladattípusokhoz",helpText:"Az alapértelmezett modell kötelező. A többi modell opcionális, és ha nincs konfigurálva, visszaáll az alapértelmezettre.",default:{label:"Alapértelmezett",placeholder:"Alapértelmezett modell kiválasztása",description:"Elsődleges modell általános feladatokhoz (hasonló a Claude Sonnethez)"},background:{label:"Háttér",placeholder:"Háttérmodell kiválasztása",description:"Könnyű modell háttérfeladatokhoz (hasonló a Claude Haiku-hoz)"},think:{label:"Gondolkodás",placeholder:"Gondolkodási modell kiválasztása",description:"Fejlett modell összetett következtetéshez (hasonló a Claude Opushoz)"},image:{label:"Kép",placeholder:"Képmodell kiválasztása",description:"Látási képességgel rendelkező modell képekkel kapcsolatos feladatokhoz"}}},codeToChat:{title:"Kód–Chat útválasztó",description:"Kódolási terv modelljei elérhetővé tétele chat módban",addRouter:"Útválasztó hozzáadása",emptyState:"Nincsenek konfigurált Kód→Chat útválasztók. Adjon hozzá egyet a kódolási terv modelljei chat módban való megjelenítéséhez.",form:{name:"Útválasztó neve",namePlaceholder:"Saját Kód→Chat útválasztó",codeProvider:"Kód-szolgáltató",codeProviderPlaceholder:"Válasszon kód-szolgáltatót",codeProviderHelper:"Válassza ki az átalakításhoz használandó kód-szolgáltatót",models:"Kódolási terv modelljei",modelsHelper:"Válassza ki, melyik kódolási terv modelljeit tegye elérhetővé",enabled:"Engedélyezve",save:"Útválasztó mentése",cancel:"Mégse"},mappings:{title:"Modelltérképezések",description:"Kód-szolgáltató modelljei leképezése chat-szolgáltató modelljeire megjelenítéshez",count:"térképezés",empty:"Nincsenek konfigurált modelltérképezések. Adjon hozzá térképezéseket a kódmodellek chat módban való megjelenítéséhez.",addNew:"Új térképezés hozzáadása",selectSource:"Forrásmodell kiválasztása (Kód)",selectTarget:"Célmodell kiválasztása (Chat)",sourcePlaceholder:"Adja meg a forrásmodell nevét",targetPlaceholder:"Adja meg a célmodell nevét",add:"Hozzáadás",edit:"Szerkesztés",done:"Kész"}},transformers:{title:"Transzformátorok",description:"Konfigurálja a transzformátorokat a kérés/válasz konverzióhoz",noProvider:"Válasszon szolgáltatót a transzformátorok konfigurálásához",empty:"Nincsenek transzformátorok",count:"{{count}} transzformátor"},status:{enabled:"Engedélyezve",disabled:"Letiltva"},messages:{routerAdded:"Az útválasztó sikeresen hozzáadva",routerUpdated:"Az útválasztó sikeresen frissítve",routerDeleted:"Az útválasztó sikeresen törölve",saveFailed:"Az útválasztó mentése sikertelen"}},presets:{title:"Szolgáltató gyors hozzáadása",added:"Hozzáadva",add:"Hozzáadás",features:{search:"Keresés",vision:"Látás",mcp:"MCP",codingPlan:"Kódolási terv"}},alerts:{deleteConfirm:"Biztosan törli ezt a szolgáltatót?"},errors:{nameRequired:"A szolgáltató neve kötelező",urlRequired:"Az API alap URL kötelező",urlInvalid:"Adjon meg érvényes URL-t (pl. https://api.example.com)",saveFailed:"A szolgáltató mentése sikertelen",deleteFailed:"Hiba a szolgáltató törlésekor. Kérjük, próbálja újra.",toggleFailed:"Hiba a szolgáltató be-/kikapcsolásakor. Kérjük, próbálja újra."},openRouter:{title:"OpenRouter szolgáltatói útválasztás",description:"Konfigurálja, hogyan irányítódnak a kérések különböző szolgáltatókhoz az OpenRouteren.",sort:"Útválasztási stratégia",sortTooltip:"Válassza ki, hogyan rangsorolja a szolgáltatókat. Az automatikus intelligens terheléselosztást használ.",order:"Szolgáltatói prioritási sorrend",orderTooltip:"Adja meg a sorrendben kipróbálandó szolgáltatókat (pl. anthropic, openai, together). Nyomja meg az Entert a hozzáadáshoz.",orderPlaceholder:"Írja be a szolgáltató azonosítóját és nyomja meg az Entert...",allowFallbacks:"Tartalék lehetőségek engedélyezése",allowFallbacksTooltip:"Ha engedélyezve van, az OpenRouter tartalék szolgáltatókat próbál meg, ha az elsődleges nem elérhető.",requireParameters:"Összes paraméter megkövetelése",requireParametersTooltip:"Csak olyan szolgáltatókhoz irányítson, amelyek a kérés összes paraméterét támogatják.",dataCollection:"Adatgyűjtési szabályzat",dataCollectionTooltip:"Szabályozza, hogy használja-e azokat a szolgáltatókat, amelyek tárolhatják vagy betaníthatják az adatait.",zdr:"Nulla adatmegőrzés",zdrTooltip:"Csak nulla adatmegőrzési szabályzattal rendelkező végpontokhoz irányítson.",only:"Csak engedélyezett szolgáltatók",onlyTooltip:"Csak ezeket a konkrét szolgáltatókat használja. Hagyja üresen az összes engedélyezéséhez.",onlyPlaceholder:"Írja be a szolgáltató azonosítóját és nyomja meg az Entert...",ignore:"Figyelmen kívül hagyott szolgáltatók",ignoreTooltip:"Hagyja ki ezeket a szolgáltatókat a kérések irányításakor.",ignorePlaceholder:"Írja be a szolgáltató azonosítóját és nyomja meg az Entert...",quantizations:"Kvantálási szűrő",quantizationsTooltip:"Csak meghatározott kvantálási szintű szolgáltatókat használjon. Az alacsonyabb pontosság csökkentheti a minőséget, de javíthatja a sebességet.",maxPrice:"Maximális ár",maxPriceTooltip:"Állítson be maximális árhatárokat millió tokenenként. Hagyja üresen a korlátlan beállításhoz.",configured:"Konfigurálva"}},Jx={label:"API mód",standard:"Szabványos",codingPlan:"Kódolási terv",tokenPlan:"Token terv",apiKeyPrefixHint:"Az ehhez a tervhez tartozó kulcsok általában `{{prefix}}` előtaggal kezdődnek. Csak tájékoztató — nem kötelező érvényű.",dashscopeCodingPlanSeparateKey:"A DashScope kódolási terv a szabványos végponttól eltérő API-kulcsot használ.",baiduCodingPlanSeparateKey:"A Qianfan kódolási terv a szabványos végponttól eltérő API-kulcsot használ.",tencentTokenPlanAnthropicOnly:"A Tencent Token Plan csak az Anthropic protokollt támogatja.",xiaomiTokenPlanRegions:"Az alapértelmezett baseUrl: `token-plan-cn.*`. Manuálisan módosítható `token-plan-sgp.*` vagy `token-plan-ams.*` értékre.",confirmOverwriteTitle:"Váltson API módot?",confirmOverwriteBody:"Testreszabta az API URL-t vagy az API-kulcsot. A módváltás ezeket az új mód alapértékeivel írja felül — vagy tartsa meg testreszabásait, és csak a mód címkéjét frissítse.",overwriteAndSwitch:"Felülírás és váltás",keepCustomizations:"Testreszabások megtartása"},ez={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},tz={cancel:"Mégse",close:"Bezárás",copy:"Másolás",delete:"Törlés",dismiss:"Bezárás",save:"Mentés",optional:"opcionális",retry:"Újra",loading:"Betöltés…"},az={common:{learnMore:"Dokumentáció"}},nz={notSupportedByDaemon:"A daemon még nem támogatja",discoveryUnsupportedFormat:"A modellfelderítés ehhez a szolgáltatói formátumhoz még nem támogatott. Adja hozzá a modelleket manuálisan."},oz={subtitle:"Vezérlőpult",providers:"Szolgáltatók",apiService:"API szolgáltatás",accounts:"Fiókok",codeCli:"Code CLI",settings:"Beállítások",usageStats:"Használat",pricing:"Árak"},iz={title:"API szolgáltatás",description:"Konfigurálja a kimenő API-kiszolgálót, a végpontonkénti modellútvonalasztást és a névvel ellátott hozzáférési kulcsokat.",loading:"Kiszolgáló konfiguráció betöltése…",loadError:"A kiszolgáló konfiguráció betöltése sikertelen. Ellenőrizze, hogy a daemon elérhető-e.",enable:{label:"Kimenő kiszolgáló engedélyezése",description:"Indítsa el a helyi API-kiszolgálót, amely a külső hívókat a szolgáltatókon keresztül irányítja."},networkBinding:{label:"LAN-hozzáférés engedélyezése",description:"Kösse a kiszolgálót a hálózati interfészhez, ne csak a loopback interfészhez.",warning:"A LAN-hozzáférés a hálózat többi eszközének teszi ki az API-kiszolgálót. Az előfizetési útválasztással kombinálva a kérések felhasználhatják az előfizetési kvótát — tartsa kikapcsolva, ha nem bízik a hálózatban."},status:{running:"A kiszolgáló fut",stopped:"A kiszolgáló leállítva",runningHint:"A kimenő API-kiszolgáló fogadja a kéréseket.",stoppedHint:"Engedélyezze a kiszolgálót a kérések fogadásának megkezdéséhez.",port:"{{port}} port",loopback:"Loopback URL-ek",lan:"LAN URL-ek"},endpoints:{title:"Végpont-útválasztás",description:"Válassza ki, melyik modellre irányít az egyes hálózati formátum. Az alapértelmezett modell itt kerül figyelembevételre — a kiszolgáló útválasztó, nem chat-alkalmazás."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Alapértelmezett modell",backgroundModel:"Háttérmodell",visionModel:"Látási modell",noVisionModel:"Nincs",backgroundModelIds:"Háttérmodellek azonosítói",backgroundModelIdsPlaceholder:"vesszővel elválasztott modellazonosítók",modelPlaceholder:"Válasszon modellt…",useSubscription:"Előfizetés használata",subscriptionUnsupported:"Az előfizetési útválasztás ehhez a végponthoz nem érhető el."},keys:{title:"Hozzáférési kulcsok",description:"Névvel ellátott kulcsok, amelyeket a külső hívók Bearer tokenként küldenek. A teljes kulcs csak a létrehozáskor jelenik meg.",namePlaceholder:"Kulcs neve (pl. saját-cli)",create:"Kulcs létrehozása",empty:"Még nincsenek hozzáférési kulcsok.",enabled:"Engedélyezve",disabled:"Letiltva",revoked:"Visszavonva",toggle:"Kulcs be-/kikapcsolása",revoke:"Visszavonás",revokeConfirmTitle:"Visszavonja ezt a kulcsot?",revokeConfirmDesc:"A „{{name}}“ visszavonása azonnal megakadályozza a hitelesítését. Ez a művelet nem vonható vissza.",created:{title:"Kulcs létrehozva",warning:"Másolja le ezt a kulcsot most — nem jelenik meg újra. Tárolja biztonságosan.",copy:"Másolás",copied:"Másolva",dismiss:"Kész"}}},rz={title:"Fiókok és előfizetések",description:"Kezelje az előfizetési hitelesítő adatokat, amelyeken keresztül a kiszolgáló irányítja a forgalmat. A tokenek itt kerülnek beírásra, de soha nem jelennek meg újra.",loading:"Fiókok betöltése…",empty:"Nincsenek elérhető előfizetési szolgáltatók.",signIn:"Bejelentkezés",oauth:{title:"Bejelentkezés ide: {{name}}",description:"Nyissa meg a bejelentkezési oldalt a böngészőjében, engedélyezze, majd illessze be az engedélyezési kódot az alábbiakba. A kód csak a daemonhoz kerül — a kiadott token soha nem jelenik meg.",openPage:"Bejelentkezési oldal megnyitása",codeLabel:"Engedélyezési kód",codePlaceholder:"Illessze be a kódot ide",submit:"Bejelentkezés befejezése"},codexOauth:{title:"Bejelentkezés ide: {{name}}",description:"Nyissa meg a bejelentkezési oldalt a böngészőjében, és engedélyezze. A daemon automatikusan rögzíti az eredményt — tartsa nyitva ezt az oldalt, amíg be nem fejeződik. A token soha nem jelenik meg.",waiting:"Várakozás a böngészőbeli bejelentkezés befejezésére…",failed:"A bejelentkezés sikertelen. Kérjük, próbálja újra."},clearProvider:"Összes törlése",clearConfirmTitle:"Törli a {{name}} fiókokat?",clearConfirmDesc:"Ez eltávolítja az összes tárolt hitelesítő adatot ehhez a szolgáltatóhoz. Ez a művelet nem vonható vissza.",credential:{ok:"Konfigurálva",notConfigured:"Nincs konfigurálva"},kind:{"pass-through":"Átmenő hitelesítő adatok","oauth-bearer":"OAuth bearer","static-bearer":"Statikus bearer kulcs"},reason:{"missing-credential":"Nincs tárolt hitelesítő adat.",expired:"A hitelesítő adat lejárt.","reauth-required":"Újrahitelesítés szükséges.","refresh-failed":"A token frissítése sikertelen.","not-refreshable":"A hitelesítő adat nem frissíthető.",unknown:"Az állapot ismeretlen."},status:{unconfigured:"Nincs konfigurálva",authorized:"Engedélyezett",configured:"Konfigurálva",expired:"Lejárt",error:"Hiba"},authMethod:{oauth:"OAuth",setup_token:"Beállítási token",manual:"Manuális"},list:{empty:"Nincsenek tárolt fiókok ehhez a szolgáltatóhoz.",active:"Aktív",expiresAt:"Lejár: {{value}}",setActive:"Aktívra állítás",remove:"Eltávolítás",removeConfirmTitle:"Eltávolítja ezt a fiókot?",removeConfirmDesc:"A „{{name}}“ eltávolítása törli a tárolt hitelesítő adatot. Ez a művelet nem vonható vissza.",title:"Fiókok"},write:{trigger:"Hitelesítő adat hozzáadása",title:"{{name}} hitelesítő adat beírása",description:"Illessze be a már megszerzett token anyagot. A mezők arra korlátozódnak, amit ez a szolgáltató elfogad; a token tárolásra kerül, és soha nem jelenik meg újra.",authMethod:"Hitelesítési módszer",status:"Állapot",subscriptionLevel:"Előfizetési szint",subscriptionLevelNone:"Nincs beállítva",submit:"Hitelesítő adat mentése"},field:{accessToken:"Hozzáférési token",refreshToken:"Frissítési token",idToken:"ID token",apiKey:"API-kulcs",expiresAt:"Lejár (ISO)",setupTokenExpiresAt:"Beállítási token lejárata (ISO)",accountId:"Fiókazonosító",email:"E-mail",organizationId:"Szervezeti azonosító",baseUrl:"Alap URL",zenBaseUrl:"Zen alap URL"},provider:{claude:{title:"Claude",description:"Az Anthropic előfizetési hitelesítő adatai a daemon által irányítva."},codex:{title:"Codex",description:"Az OpenAI Codex előfizetési hitelesítő adatai a daemon által irányítva."},gemini:{title:"Gemini",description:"A Google Gemini előfizetési hitelesítő adatai a daemon által irányítva."},opencodego:{title:"OpenCodeGo",description:"Statikus API-kulcs hitelesítő adatok a daemon által irányítva."}},authMethodLabel:"Engedélyezési módszer",authMethodDesc:{oauth:"Jelentkezzen be a böngészőjén keresztül; a daemon rögzíti és tárolja a tokent.",manual:"Illessze be a már megszerzett tokent. Tárolásra kerül, és soha nem jelenik meg újra."},actions:{authorize:"Engedélyezés",enterToken:"Token megadása",refresh:"Frissítés"},accounts:{addAccount:"Fiók hozzáadása"},detail:{authMethod:"Engedélyezési módszer",subscriptionLevel:"Előfizetési szint",expiresAt:"Lejárat",lastRefreshed:"Utoljára frissítve",label:"Fiók címkéje",labelPlaceholder:"Nevezze el ezt a fiókot",saveLabel:"Címke mentése"},oauthFlow:{step1:{title:"Nyissa meg az engedélyezési oldalt",desc:"Nyissa meg a bejelentkezési oldalt a böngészőjében."},step2:{title:"Engedélyezze a hozzáférést",desc:"Jelentkezzen be, és hagyja jóvá a szolgáltató hozzáférését."},step3:{title:"Másolja le az engedélyezési kódot",desc:"Az oldal megjeleníti az engedélyezési kódot a jóváhagyás után."},step4:{title:"Illessze be a kódot",desc:"Illessze be az engedélyezési kódot az alábbiakba a befejezéshez. A kód csak a daemonhoz kerül — a kiadott token soha nem jelenik meg."},authorize:"Bejelentkezés befejezése",showUrl:"Engedélyezési URL megjelenítése"},manual:{title:"Hitelesítő adat beillesztése",description:"Illessze be a már megszerzett tokent. A mezők arra korlátozódnak, amit ez a szolgáltató elfogad; a token tárolásra kerül, és soha nem jelenik meg újra.",accessTokenPlaceholder:"Illessze be a hozzáférési tokent",refreshTokenPlaceholder:"Illessze be a frissítési tokent (opcionális)",hint:"A token a daemonhoz kerül elküldésre, és titkosítva tárolódik. Soha nem jelenik meg újra."},openCodeGo:{apiKeyRequired:"Az API-kulcs kötelező.",apiKeyPlaceholder:"Illessze be az API-kulcsot",baseUrlPlaceholder:"https://… (opcionális)",zenBaseUrlPlaceholder:"https://… (opcionális)"},info:{title:"Az előfizetési fiókokról",description:"A tokenek a daemonhoz kerülnek beírásra, és upstream kérések hitelesítéséhez használatosak. Titkosítva tárolódnak, és soha nem jelennek meg újra. Egy fiók eltávolítása törli a tárolt hitelesítő adatot."},rename:{failed:"A fiók átnevezése sikertelen."},refresh:{failed:"A token frissítése sikertelen."},errors:{requestFailed:"A kérés sikertelen. Kérjük, próbálja újra."},syncWarning:{"external-divergent":"A külső CLI bejelentkezési fájlja újabb hitelesítő adatokat tartalmaz, mint ez a fiók. A tárolt token frissítése leállhat — frissítsen most, vagy jelentkezzen be újra.","external-not-rotated":"A frissítés nem sikerült, és a külső CLI ugyanazt a lejárt hitelesítő adatot tartalmazza. Jelentkezzen be újra.","duplicate-token":"Egy másik fiók ugyanezeket a hitelesítő adatokat használja. Bármelyik frissítése kijelentkezteti a másikat."},importExternal:{detected:"Ezen a gépen meglévő {{name}} CLI-bejelentkezést találtunk.",hint:"Importálás után ez az alkalmazás tartja frissen: minden token-frissítéskor a CLI bejelentkezési fájlja is frissül, így a terminálban a CLI bejelentkezve marad.",button:"Meglévő CLI-bejelentkezés importálása"}},sz={title:"Code CLI",description:"Irányítsa a kódolási CLI-t a daemon kimenő proxyjára. Ez az oldal csak olvasható — itt nincs mit konfigurálni.",copy:"Másolás",copied:"Másolva",baseUrl:{title:"Daemon alap URL",description:"A proxy-cím, amelyhez a CLI csatlakozik.",label:"Alap URL"},token:{title:"Hitelesítés",hint:"Az adminisztrátori útvonalakhoz küldje el: 'Authorization: Bearer <admin-tokenje>'. Az adminisztrátori token a daemonban van konfigurálva (konfigurációs fájlja vagy környezete) — itt soha nem jelenik meg."},examples:{title:"Példa indítási környezet",keyNote:"Az API szolgáltatás oldalán létrehozott kimenő hozzáférési kulcsot használja — nem az adminisztrátori tokent.",anthropic:"Anthropic formátumú CLI",openai:"OpenAI formátumú CLI"},launchDescription:"Indítson el egy kódolási CLI-t egy terminálban, amely erre a daemonra mutat. A daemon beinjektálja az átirányítási környezeti változókat, és elindítja a CLI-t az Ön helyett.",refresh:"Frissítés",loading:"CLI-k észlelése…",cli:{installed:"Telepítve",notFound:"Nem található",notFoundHint:"Ez a CLI nem szerepel a daemon gazdagépének PATH-jában. Telepítse, majd frissítsen.",install:"Telepítés",installing:"Telepítés…",installingHint:"Telepítés a daemon gazdagépén — ez eltarthat egy percig.",launch:"Indítás",launchTitle:"{{name}} indítása",launchDescription:"Új terminált nyit a daemon gazdagépén, amelyen ez a CLI fut, a daemon proxyn keresztül irányítva. Válasszon opcionális munkakönyvtárat.",cwdLabel:"Munkakönyvtár",cwdPlaceholder:"/elérési/út/a/projekthez",runningVia:"Fut · {{provider}} / {{model}}",stop:"Leállítás"},manual:{title:"Manuális beállítás",description:"Inkább maga futtatná a CLI-t? Irányítsa a daemonra ezekkel a környezeti változókkal.",show:"Megjelenítés",hide:"Elrejtés"}},lz={probing:"Daemon ellenőrzése…",spawning:"Daemon indítása…",failed:"A daemon nem tudott elindulni",failedHint:"Győződjön meg arról, hogy a Node.js telepítve van, és a daemon fel van építve (a dist könyvtár létezik), vagy állítsa az OMNICROSS_DAEMON_ENTRY értékét a daemon cli.js fájljára."},dz={title:"Beállítások",description:"Asztali alkalmazás beállításai.",desktopOnly:"Az indítási és tálca beállítások csak az asztali alkalmazásban érvényesek.",startup:{title:"Indítás",autoLaunch:"Indítás bejelentkezéskor",autoLaunchHint:"Az Omnicross automatikus indítása bejelentkezéskor.",startMinimized:"Minimalizálva indítás a tálcára",startMinimizedHint:"Indítás a háttérben, az ablak megnyitása nélkül."},tray:{title:"Tálca",minimizeOnClose:"Tálcára minimalizálás bezáráskor",minimizeOnCloseHint:"Az ablak bezárása kilépés helyett elrejti azt a tálcára."},language:{title:"Nyelv",label:"Kezelőfelület nyelve"}},cz={title:"Használati statisztika",description:"A démon által kiszolgált kérések token- és költségstatisztikái.",rangeToday:"Ma",range7d:"Elmúlt 7 nap",range30d:"Elmúlt 30 nap",rangeCustom:"Egyéni",from:"Ettől",to:"Eddig",totalCost:"Összköltség",cacheSavings:"Gyorsítótár-megtakarítás",events:"Kérések",inputTokens:"Bemeneti tokenek",outputTokens:"Kimeneti tokenek",cacheReadTokens:"Gyorsítótár-olvasás",cacheWriteTokens:"Gyorsítótár-írás",reasoningTokens:"Gondolkodási tokenek",byModel:"Modellenként",byApiKey:"API-kulcsonként",provider:"Szolgáltató",model:"Modell",cost:"Költség",apiKey:"API-kulcs",unpriced:"Ár nélkül",unpricedHint:"Ehhez a modellhez nincs árbejegyzés — adj hozzá egyet az Árak oldalon.",unattributed:"Nem hozzárendelt",unattributedHint:"Konkrét API-kulcshoz nem kapcsolt kérések. Ez normális, amíg a kulcsonkénti hozzárendelés rögzítése el nem indul.",empty:"Nincs kérés ebben az időszakban.",invalidRange:"Válassz érvényes dátumtartományt."},uz={title:"Modellárak",description:"Modellenkénti tokenárak a kérésköltségek számításához, USD / 1 millió token.",search:"Szolgáltató vagy modell keresése…",fetchLatest:"Legfrissebb lekérése",fetching:"Lekérés…",addEntry:"Bejegyzés hozzáadása",provider:"Szolgáltató",model:"Modell",inputPrice:"Bemenet",outputPrice:"Kimenet",cacheReadPrice:"Gyorsítótár-olvasás",cacheWritePrice:"Gyorsítótár-írás",source:"Forrás",updated:"Frissítve",userEdited:"szerkesztve",edit:"Szerkesztés",deleteTitle:"Törlöd az árbejegyzést?",empty:"Az ártáblázat üres.",emptyHint:"Kérd le a legfrissebb árakat a feltöltéséhez.",noMatches:"Nincs a keresésnek megfelelő bejegyzés.",saved:"Árbejegyzés mentve.",saveFailed:"A mentés sikertelen: {{message}}",deleteFailed:"A törlés sikertelen: {{message}}",alreadyDeleted:"A bejegyzés már nem létezett.",fetchApplied:"{{count}} bejegyzés frissítve a forrásból.",fetchFailed:"A lekérés sikertelen: {{message}}",requiredId:"Kötelező",invalidPrice:"Adj meg nemnegatív számot",conflictTitle:"Árütközések feloldása",conflictHint:"Ezeket a bejegyzéseket te szerkesztetted, és a forrásban is megváltoztak. Soronként válaszd ki, hogy megtartod a saját értéked (Kihagyás) vagy átveszed az újat (Felülírás).",current:"Jelenlegi",incoming:"Bejövő",overwrite:"Felülírás",skip:"Kihagyás",overwriteAll:"Összes felülírása",skipAll:"Összes kihagyása",applyResolutions:"Alkalmaz",resolved:"{{overwritten}} felülírva, {{skipped}} kihagyva.",resolvedWithStale:"{{overwritten}} felülírva, {{skipped}} kihagyva. {{stale}} időközben megváltozott, és érintetlen maradt.",refreshFailed:"A módosítás megtörtént, de a lista újratöltése nem sikerült: {{message}}",sourceBuiltin:"Beépített",sourceLitellm:"LiteLLM",sourceUser:"Felhasználó"},pz={providerSettings:Xx,apiMode:Jx,presetName:ez,common:tz,mediaSettings:az,appLocal:nz,nav:oz,apiService:iz,accounts:rz,codeCli:sz,daemonStatus:lz,settings:dz,usageStats:cz,pricing:uz},mz={loading:"Memuat konfigurasi LLM...",reset:{button:"Pulihkan default",confirmTitle:"Pulihkan pengaturan default?",confirmBody:"Ini akan menghapus kustomisasi Anda untuk penyedia ini sehingga kembali ke default bawaan. API key dan sesi yang tersimpan tetap dipertahankan.",confirmButton:"Pulihkan default"},reentryBanner:{message:"{{count}} penyedia yang aktif perlu memasukkan ulang API key-nya. Buka masing-masing dan tambahkan key-nya kembali."},migrationPack:{barHint:"Pindahkan provider key dan subscription token Anda ke mesin lain dengan paket terenkripsi.",passphrase:"Kata sandi",passphrasePlaceholder:"Masukkan kata sandi",passphraseHint:"Gunakan minimal 8 karakter; disarankan 12 karakter atau lebih.",confirm:"Konfirmasi kata sandi",confirmPlaceholder:"Masukkan ulang kata sandi",mismatch:"Kata sandi tidak cocok.",strength:{weak:"Terlalu pendek — gunakan minimal 8 karakter.",fair:"Cukup — 12 karakter atau lebih lebih aman.",strong:"Kata sandi kuat."},export:{button:"Ekspor paket",title:"Ekspor paket terenkripsi",subtitle:"Enkripsi provider key dan subscription token Anda ke dalam file portabel.",warning:"File ini berisi rahasia yang dapat didekripsi. Simpan dengan aman — siapa pun yang memiliki file dan kata sandi dapat membaca key Anda. Kata sandi yang hilang tidak dapat dipulihkan.",submit:"Ekspor",success:"Paket berhasil diekspor.",error:"Ekspor gagal. Silakan coba lagi."},import:{button:"Impor paket",title:"Impor paket terenkripsi",subtitle:"Pulihkan provider key dan subscription token dari paket yang diekspor.",hint:"Masukkan kata sandi yang digunakan saat mengekspor paket, lalu pilih file.",submit:"Impor",successTitle:"Impor selesai",summary:"Berhasil mengimpor {{providerKeys}} provider key, {{poolKeys}} pool key, dan {{tokenSets}} token set.",duplicates:"Melewati {{count}} pool key yang sudah ada.",skipped:"Dilewati (tidak ada penyedia yang cocok): {{names}}",error:"Kata sandi salah atau paket rusak. Tidak ada yang diubah."}},searchPlaceholder:"Cari penyedia...",emptySearch:"Tidak ada penyedia yang sesuai dengan pencarian Anda.",emptyList:"Belum ada penyedia yang dikonfigurasi.",selectPrompt:"Pilih penyedia untuk melihat detail",listStatus:"{{count}} model",noModels:"Belum ada model yang dikonfigurasi",enabled:"Aktif",disabled:"Nonaktif",showEnabledOnly:"Tampilkan yang aktif saja",showAll:"Tampilkan semua penyedia",dragHandle:"Seret untuk mengurutkan ulang",reorderFailed:"Gagal menyimpan urutan penyedia",credentials:{apiKey:"API Key",apiBaseUrl:"API Base URL"},filter:{all:"Semua",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Pilih Template",skipTemplates:"Lewati, konfigurasi manual",name:"Nama *",providerType:"Tipe",apiType:"Tipe API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Format API OpenAI chat/completions standar",claudecode:"Format Anthropic Messages API (Claude Code)"},chatApiFormat:"Format API",chatApiFormatDescription:"Pilih format API yang sesuai dengan endpoint penyedia Anda",apiKey:"API Key",apiKeyPlaceholder:"sk-... atau $ENV_VAR",apiKeyHelper:"Gunakan $VAR_NAME untuk mereferensikan variabel lingkungan",apiKeySetPlaceholder:"Key sudah diatur — kosongkan untuk tetap menggunakannya",apiKeyReplaceHelper:"Key tersimpan dengan aman. Ketik nilai baru untuk menggantinya, atau kosongkan untuk tetap menggunakannya.",testApiKey:"Uji API Key",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Pratinjau:",models:"Model",modelPlaceholder:"Nama model (mis. gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API Transformers",transformerConfigDescription:"Konfigurasikan transformer untuk menyesuaikan format API request/response untuk penyedia ini",transformerConfigNote:"Daemon menerapkan transformer ini dalam rantai request, setelah format transformer penyedia (yang menangani konversi wire-format). Nama transformer yang tidak dikenal akan dilewati.",enabled:"Aktif",apiVersion:"Versi API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versi Azure OpenAI API (mis. 2024-08-01-preview)",official:"Anthropic API Resmi",officialHelper:"Aktifkan jika penyedia ini terhubung langsung ke Anthropic API resmi. Nonaktifkan untuk reverse proxy atau layanan pihak ketiga.",maxConcurrency:"Maks Permintaan Bersamaan",maxConcurrencyHelper:"Jumlah maksimum API request yang dikirim secara bersamaan ke penyedia ini. Nilai lebih rendah membantu menghindari rate limiting (error 429). Atur `-1` untuk tidak ada batas.",codingPlan:{label:"Coding Plan",description:"Gunakan endpoint API terpisah untuk coding plan berbasis subscription",baseUrl:"Coding Plan Base URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API Key (opsional)",apiKeyPlaceholder:"Kosongkan untuk menggunakan API key penyedia",apiKeyHelper:"Hanya diperlukan jika coding plan menggunakan API key yang berbeda",tokenPlanHint:"Beberapa penyedia (mis. Xiaomi MiMo) menerbitkan Token Plan key dengan awalan `tp-` — hanya informasi, tidak diberlakukan."},selectTypeFirst:"Pilih Tipe Penyedia",selectTypeFirstDesc:"Pilih tipe penyedia yang ingin Anda tambahkan",codeProviderNote:"Code provider hanya memerlukan API Key dan URL. Model dikelola oleh Agent Router.",buttons:{cancel:"Batal",submitAdd:"Tambah Penyedia",submitUpdate:"Perbarui Penyedia",continue:"Lanjutkan",back:"Kembali"}},details:{noSelection:"Pilih penyedia untuk melihat detail",apiKey:"API Key",apiUrl:"API URL",nameLabel:"Nama Penyedia",modelsEndpoint:"Models Endpoint",modelsEndpointHelper:"Timpa endpoint discovery jika penyedia menyediakan path /models kustom.",models:"Model",transformers:"Transformers",codeProviderNote:"Code provider (seperti Claude Code) tidak memerlukan konfigurasi model. Model dikelola secara otomatis oleh Agent Router.",buttons:{more:"Pengaturan Lainnya",delete:"Hapus"}},providerModelSelector:{placeholder:"Pilih penyedia dan model",noProviders:"Tidak ada penyedia",noModels:"Belum ada model yang dikonfigurasi"},apiKeyPool:{title:"API Key Pool",description:"Konfigurasikan beberapa API key untuk load balancing. Setiap sesi terikat pada satu key untuk menjaga prompt cache.",defaultLabel:"Default",weight:"Bobot",noKey:"Tidak ada key",labelPlaceholder:"Label (mis. Key #1, Production)",addKey:"Tambah API Key",add:"Tambah",empty:"Belum ada key tambahan yang dikonfigurasi.",statusCoolingDown:"Mendingin {{time}}",statusAuthFailed:"Autentikasi gagal · dinonaktifkan",statusDisabled:"Nonaktif",statusHealthy:"Sehat",agoSeconds:"{{count}} detik lalu",agoMinutes:"{{count}} menit lalu",agoHours:"{{count}} jam lalu",agoDays:"{{count}} hari lalu"},modelsManager:{searchPlaceholder:"Cari model...",defaultGroup:"Semua Model",add:"Tambah Model",manage:"Kelola",empty:"Tidak ada model dalam grup ini",enabled:"Aktif",disabled:"Nonaktif",filters:{all:"Semua",vision:"Vision",reasoning:"Reasoning",free:"Gratis",tools:"Tools"},manualDialog:{title:"Tambah Model",subtitle:"Tambahkan model kustom ke penyedia ini",modelId:"Model ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, dll.",modelIdHelper:"Identifikator model yang tepat yang digunakan saat memanggil API",modelName:"Nama Tampilan",modelNamePlaceholder:"Nama tampilan yang ramah (opsional)",modelNameHelper:"Nama opsional yang ditampilkan di antarmuka. Jika kosong, Model ID akan digunakan",group:"Grup",groupPlaceholder:"Pilih atau masukkan nama grup",submit:"Tambah",cancel:"Batal",helper:"Berikan identifikator model yang tepat yang disediakan oleh API penyedia."},editDialog:{title:"Edit Model",subtitle:"Ubah pengaturan model",modelId:"Model ID",modelIdPlaceholder:"Identifikator model",modelIdHelper:"Identifikator model yang digunakan saat memanggil API",modelName:"Nama Tampilan",modelNamePlaceholder:"Nama tampilan yang ramah",modelNameHelper:"Nama yang ditampilkan di antarmuka",group:"Grup",groupPlaceholder:"Pilih atau masukkan nama grup",submit:"Simpan",cancel:"Batal",vision:"Kemampuan Vision",visionHint:"Apakah model ini mendukung input gambar/vision",reasoning:"Model Thinking",reasoningHint:"Apakah model ini mendukung mode thinking/reasoning"},manageDialog:{title:"Kelola Model",cachedAt:"Di-cache pada {{date}} ({{source}})",refresh:"Segarkan",close:"Tutup",raw:"Raw JSON",empty:"Tidak ada model jarak jauh yang tersedia.",error:"Gagal memuat model: {{message}}",addFromCatalog:"Tambah",sourceCache:"cache",sourceNetwork:"langsung",contextLength:"Konteks {{value}} token",maxTokens:"Maks {{value}} token"},messages:{added:"Model ditambahkan.",updated:"Model diperbarui.",removed:"Model dihapus.",duplicate:"Model sudah ada.",refreshed:"Model disegarkan",refreshFailed:"Gagal menyegarkan model"},testDialog:{title:"Uji Konektivitas Model",provider:"Penyedia",model:"Model",testing:"Menguji...",success:"Uji Berhasil",successMessage:"Model dapat diakses dengan normal",failure:"Uji Gagal",aiResponse:"Respons AI",charCount:"{{count}} karakter",duration:"Durasi {{time}} detik",close:"Tutup",retest:"Uji ulang",testButton:"Uji model",unsupportedFormat:"Pengujian belum didukung untuk format penyedia ini."}},router:{title:"Konfigurasi Router",description:"Konfigurasikan penyedia/model yang digunakan untuk berbagai skenario.",labels:{default:"Default",background:"Latar belakang",think:"Berpikir",longContext:"Konteks Panjang",webSearch:"Pencarian Web",image:"Gambar",longContextThreshold:"Ambang Konteks Panjang"},helper:{longContextThreshold:"Jumlah token sebelum beralih ke model konteks panjang."},placeholder:{required:"Wajib",optional:"Opsional"}},agentRouter:{title:"Agent Router",description:"Konfigurasikan routing dua arah antara mode Chat dan Code.",searchPlaceholder:"Cari router...",noSearchResults:"Tidak ada router yang sesuai dengan pencarian Anda.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Chat to Code Router",description:"Gunakan chat provider dalam mode agent/coding",addRouter:"Tambah Router",emptyState:"Belum ada Chat→Code router. Tambahkan satu untuk menggunakan chat provider dalam mode coding.",form:{name:"Nama Router",namePlaceholder:"My Chat→Code Router",chatProvider:"Chat Provider",chatProviderPlaceholder:"Pilih chat provider",mode:"Mode",modeSimple:"Sederhana",modeAdvanced:"Lanjutan",modeSimpleDesc:"Terusan langsung ke chat provider",modeAdvancedDesc:"Konfigurasikan pemetaan model dan penanganan konteks",enabled:"Aktif",save:"Simpan Router",cancel:"Batal"},list:{provider:"Penyedia",mode:"Mode",status:"Status"},mappings:{title:"Pemetaan Model",description:"Petakan model Chat provider ke model Code provider",count:"pemetaan",empty:"Belum ada pemetaan model. Tambahkan pemetaan untuk mengarahkan chat model ke code provider.",addNew:"Tambah Pemetaan Baru",selectSource:"Pilih model sumber (Chat)",selectTarget:"Pilih model tujuan (Code)",targetPlaceholder:"Masukkan nama model Claude Code",notSet:"(Belum diatur — klik untuk memilih)",add:"Tambah",edit:"Edit",done:"Selesai"},advanced:{title:"Konfigurasi Lanjutan",description:"Konfigurasikan model untuk berbagai jenis tugas",helpText:"Model default wajib diisi. Model lainnya opsional dan akan kembali ke default jika tidak dikonfigurasi.",default:{label:"Default",placeholder:"Pilih model default",description:"Model utama untuk tugas umum (mirip Claude Sonnet)"},background:{label:"Latar belakang",placeholder:"Pilih model latar belakang",description:"Model ringan untuk tugas latar belakang (mirip Claude Haiku)"},think:{label:"Berpikir",placeholder:"Pilih model think",description:"Model canggih untuk penalaran kompleks (mirip Claude Opus)"},image:{label:"Gambar",placeholder:"Pilih model gambar",description:"Model untuk tugas terkait gambar dengan kemampuan vision"}}},codeToChat:{title:"Code to Chat Router",description:"Tampilkan model Coding Plan dalam mode chat",addRouter:"Tambah Router",emptyState:"Belum ada Code→Chat router. Tambahkan satu untuk menampilkan model Coding Plan dalam mode chat.",form:{name:"Nama Router",namePlaceholder:"My Code→Chat Router",codeProvider:"Code Provider",codeProviderPlaceholder:"Pilih code provider",codeProviderHelper:"Pilih Code provider yang digunakan untuk transformasi",models:"Model Coding Plan",modelsHelper:"Pilih model Coding Plan yang ingin ditampilkan",enabled:"Aktif",save:"Simpan Router",cancel:"Batal"},mappings:{title:"Pemetaan Model",description:"Petakan model Code provider ke model Chat provider untuk ditampilkan",count:"pemetaan",empty:"Belum ada pemetaan model. Tambahkan pemetaan untuk menampilkan model Code dalam mode chat.",addNew:"Tambah Pemetaan Baru",selectSource:"Pilih model sumber (Code)",selectTarget:"Pilih model tujuan (Chat)",sourcePlaceholder:"Masukkan nama model sumber",targetPlaceholder:"Masukkan nama model tujuan",add:"Tambah",edit:"Edit",done:"Selesai"}},transformers:{title:"Transformers",description:"Konfigurasikan transformer untuk konversi request/response",noProvider:"Pilih penyedia untuk mengonfigurasi transformer",empty:"Tidak ada transformer",count:"{{count}} transformer"},status:{enabled:"Aktif",disabled:"Nonaktif"},messages:{routerAdded:"Router berhasil ditambahkan",routerUpdated:"Router berhasil diperbarui",routerDeleted:"Router berhasil dihapus",saveFailed:"Gagal menyimpan router"}},presets:{title:"Tambah Penyedia Cepat",added:"Ditambahkan",add:"Tambah",features:{search:"Pencarian",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"Apakah Anda yakin ingin menghapus penyedia ini?"},errors:{nameRequired:"Nama penyedia wajib diisi",urlRequired:"API Base URL wajib diisi",urlInvalid:"Masukkan URL yang valid (mis. https://api.example.com)",saveFailed:"Gagal menyimpan penyedia",deleteFailed:"Gagal menghapus penyedia. Silakan coba lagi.",toggleFailed:"Gagal mengubah status penyedia. Silakan coba lagi."},openRouter:{title:"Routing Penyedia OpenRouter",description:"Konfigurasikan cara request diarahkan ke penyedia berbeda di OpenRouter.",sort:"Strategi Routing",sortTooltip:"Pilih cara memprioritaskan penyedia. Auto menggunakan load balancing cerdas.",order:"Urutan Prioritas Penyedia",orderTooltip:"Tentukan penyedia yang dicoba secara berurutan (mis. anthropic, openai, together). Tekan Enter untuk menambahkan.",orderPlaceholder:"Ketik slug penyedia dan tekan Enter...",allowFallbacks:"Izinkan Fallback",allowFallbacksTooltip:"Ketika diaktifkan, OpenRouter akan mencoba penyedia cadangan jika penyedia utama tidak tersedia.",requireParameters:"Wajibkan Semua Parameter",requireParametersTooltip:"Hanya arahkan ke penyedia yang mendukung semua parameter dalam request Anda.",dataCollection:"Kebijakan Pengumpulan Data",dataCollectionTooltip:"Kendalikan apakah akan menggunakan penyedia yang mungkin menyimpan atau melatih data Anda.",zdr:"Zero Data Retention",zdrTooltip:"Hanya arahkan ke endpoint dengan kebijakan Zero Data Retention.",only:"Hanya Izinkan Penyedia",onlyTooltip:"Hanya gunakan penyedia tertentu ini. Kosongkan untuk mengizinkan semua penyedia.",onlyPlaceholder:"Ketik slug penyedia dan tekan Enter...",ignore:"Abaikan Penyedia",ignoreTooltip:"Lewati penyedia ini saat mengarahkan request.",ignorePlaceholder:"Ketik slug penyedia dan tekan Enter...",quantizations:"Filter Quantization",quantizationsTooltip:"Hanya gunakan penyedia dengan tingkat quantization tertentu. Presisi lebih rendah mungkin mengurangi kualitas tetapi meningkatkan kecepatan.",maxPrice:"Harga Maksimum",maxPriceTooltip:"Tetapkan batas harga maksimum per juta token. Kosongkan untuk tidak ada batas.",configured:"Dikonfigurasi"}},gz={label:"Mode API",standard:"Standar",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Key untuk paket ini biasanya diawali dengan `{{prefix}}`. Hanya petunjuk — tidak diberlakukan.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan menggunakan API key terpisah dari endpoint standar.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan menggunakan API key terpisah dari endpoint standar.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan hanya mendukung protokol Anthropic.",xiaomiTokenPlanRegions:"baseUrl default adalah `token-plan-cn.*`. Anda dapat mengeditnya secara manual ke `token-plan-sgp.*` atau `token-plan-ams.*`.",confirmOverwriteTitle:"Ganti mode API?",confirmOverwriteBody:"Anda telah menyesuaikan API URL atau API Key. Mengganti mode akan menimpanya dengan default mode baru — atau pertahankan kustomisasi Anda dan hanya perbarui label mode.",overwriteAndSwitch:"Timpa dan ganti",keepCustomizations:"Pertahankan kustomisasi"},hz={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},fz={cancel:"Batal",close:"Tutup",copy:"Salin",delete:"Hapus",dismiss:"Tutup",save:"Simpan",optional:"opsional",retry:"Coba lagi",loading:"Memuat…"},vz={common:{learnMore:"Dokumentasi"}},kz={notSupportedByDaemon:"Belum didukung oleh daemon",discoveryUnsupportedFormat:"Penemuan model belum didukung untuk format penyedia ini. Tambahkan model secara manual."},yz={subtitle:"Panel Kontrol",providers:"Penyedia",apiService:"Layanan API",accounts:"Akun",codeCli:"Code CLI",settings:"Pengaturan",usageStats:"Penggunaan",pricing:"Harga"},bz={title:"Layanan API",description:"Konfigurasikan server API keluar, routing model per endpoint, dan access key bernama.",loading:"Memuat konfigurasi server…",loadError:"Tidak dapat memuat konfigurasi server. Periksa apakah daemon dapat dijangkau.",enable:{label:"Aktifkan server keluar",description:"Mulai server API lokal yang mengarahkan pemanggil eksternal melalui penyedia Anda."},networkBinding:{label:"Izinkan akses LAN",description:"Ikat server ke antarmuka jaringan Anda, bukan hanya loopback.",warning:"Akses LAN mengekspos server API ke perangkat lain di jaringan Anda. Dikombinasikan dengan subscription routing, permintaan dapat mengonsumsi kuota subscription Anda — nonaktifkan kecuali Anda mempercayai jaringan."},status:{running:"Server berjalan",stopped:"Server berhenti",runningHint:"Server API keluar sedang menerima permintaan.",stoppedHint:"Aktifkan server untuk mulai menerima permintaan.",port:"port {{port}}",loopback:"URL Loopback",lan:"URL LAN"},endpoints:{title:"Routing endpoint",description:"Pilih model yang dituju oleh setiap format wire. Model default diintegrasikan di sini — server adalah router, bukan aplikasi chat."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Model default",backgroundModel:"Model latar belakang",visionModel:"Model vision",noVisionModel:"Tidak ada",backgroundModelIds:"ID model latar belakang",backgroundModelIdsPlaceholder:"ID model dipisahkan koma",modelPlaceholder:"Pilih model…",useSubscription:"Gunakan subscription",subscriptionUnsupported:"Routing subscription tidak tersedia untuk endpoint ini."},keys:{title:"Access key",description:"Key bernama yang dikirim pemanggil eksternal sebagai Bearer token. Key lengkap hanya ditampilkan sekali saat dibuat.",namePlaceholder:"Nama key (mis. my-cli)",create:"Buat key",empty:"Belum ada access key.",enabled:"Aktif",disabled:"Nonaktif",revoked:"Dicabut",toggle:"Aktifkan/nonaktifkan key",revoke:"Cabut",revokeConfirmTitle:"Cabut key ini?",revokeConfirmDesc:'Mencabut "{{name}}" segera menghentikan autentikasinya. Tindakan ini tidak dapat dibatalkan.',created:{title:"Key dibuat",warning:"Salin key ini sekarang — tidak akan ditampilkan lagi. Simpan dengan aman.",copy:"Salin",copied:"Disalin",dismiss:"Selesai"}}},Pz={title:"Akun & Subscription",description:"Kelola kredensial subscription yang dirutekan oleh server. Token ditulis di sini tetapi tidak pernah ditampilkan kembali.",loading:"Memuat akun…",empty:"Tidak ada subscription provider yang tersedia.",signIn:"Masuk",oauth:{title:"Masuk ke {{name}}",description:"Buka halaman masuk di browser Anda, otorisasi, lalu tempel authorization code di bawah ini. Code hanya dikirim ke daemon — token yang dihasilkan tidak pernah ditampilkan.",openPage:"Buka halaman masuk",codeLabel:"Authorization code",codePlaceholder:"Tempel code di sini",submit:"Selesaikan masuk"},codexOauth:{title:"Masuk ke {{name}}",description:"Buka halaman masuk di browser Anda dan otorisasi. Daemon akan menangkap hasilnya secara otomatis — biarkan halaman ini terbuka hingga selesai. Token tidak pernah ditampilkan.",waiting:"Menunggu Anda menyelesaikan masuk di browser…",failed:"Masuk gagal. Silakan coba lagi."},clearProvider:"Hapus semua",clearConfirmTitle:"Hapus akun {{name}}?",clearConfirmDesc:"Ini menghapus setiap kredensial yang tersimpan untuk penyedia ini. Tindakan ini tidak dapat dibatalkan.",credential:{ok:"Dikonfigurasi",notConfigured:"Belum dikonfigurasi"},kind:{"pass-through":"Pass-through credentials","oauth-bearer":"OAuth bearer","static-bearer":"Static bearer key"},reason:{"missing-credential":"Tidak ada kredensial tersimpan.",expired:"Kredensial kedaluwarsa.","reauth-required":"Diperlukan autentikasi ulang.","refresh-failed":"Pembaruan token gagal.","not-refreshable":"Kredensial tidak dapat diperbarui.",unknown:"Status tidak diketahui."},status:{unconfigured:"Belum dikonfigurasi",authorized:"Diotorisasi",configured:"Dikonfigurasi",expired:"Kedaluwarsa",error:"Kesalahan"},authMethod:{oauth:"OAuth",setup_token:"Setup token",manual:"Manual"},list:{empty:"Tidak ada akun tersimpan untuk penyedia ini.",active:"Aktif",expiresAt:"Kedaluwarsa {{value}}",setActive:"Jadikan aktif",remove:"Hapus",removeConfirmTitle:"Hapus akun ini?",removeConfirmDesc:'Menghapus "{{name}}" akan menghapus kredensial tersimpannya. Tindakan ini tidak dapat dibatalkan.',title:"Akun"},write:{trigger:"Tambah kredensial",title:"Tulis kredensial {{name}}",description:"Tempel materi token yang sudah diperoleh. Kolom dibatasi sesuai yang diterima penyedia ini; token disimpan, tidak pernah ditampilkan kembali.",authMethod:"Metode autentikasi",status:"Status",subscriptionLevel:"Level subscription",subscriptionLevelNone:"Tidak diatur",submit:"Simpan kredensial"},field:{accessToken:"Access token",refreshToken:"Refresh token",idToken:"ID token",apiKey:"API key",expiresAt:"Kedaluwarsa pada (ISO)",setupTokenExpiresAt:"Setup token kedaluwarsa pada (ISO)",accountId:"Account ID",email:"Email",organizationId:"Organization ID",baseUrl:"Base URL",zenBaseUrl:"Zen base URL"},provider:{claude:{title:"Claude",description:"Kredensial subscription Anthropic yang dirutekan oleh daemon."},codex:{title:"Codex",description:"Kredensial subscription OpenAI Codex yang dirutekan oleh daemon."},gemini:{title:"Gemini",description:"Kredensial subscription Google Gemini yang dirutekan oleh daemon."},opencodego:{title:"OpenCodeGo",description:"Kredensial API-key statis yang dirutekan oleh daemon."}},authMethodLabel:"Metode otorisasi",authMethodDesc:{oauth:"Masuk melalui browser; daemon menangkap dan menyimpan token.",manual:"Tempel token yang sudah diperoleh. Token disimpan, tidak pernah ditampilkan kembali."},actions:{authorize:"Otorisasi",enterToken:"Masukkan token",refresh:"Segarkan"},accounts:{addAccount:"Tambah akun"},detail:{authMethod:"Metode otorisasi",subscriptionLevel:"Level subscription",expiresAt:"Kedaluwarsa",lastRefreshed:"Terakhir diperbarui",label:"Label akun",labelPlaceholder:"Beri nama akun ini",saveLabel:"Simpan label"},oauthFlow:{step1:{title:"Buka halaman otorisasi",desc:"Buka halaman masuk di browser Anda."},step2:{title:"Otorisasi akses",desc:"Masuk dan setujui akses untuk penyedia."},step3:{title:"Salin authorization code",desc:"Halaman menampilkan authorization code setelah Anda menyetujui."},step4:{title:"Tempel code",desc:"Tempel authorization code di bawah untuk menyelesaikan. Code hanya dikirim ke daemon — token yang dihasilkan tidak pernah ditampilkan."},authorize:"Selesaikan masuk",showUrl:"Tampilkan URL otorisasi"},manual:{title:"Tempel kredensial",description:"Tempel token yang sudah diperoleh. Kolom dibatasi sesuai yang diterima penyedia ini; token disimpan, tidak pernah ditampilkan kembali.",accessTokenPlaceholder:"Tempel access token",refreshTokenPlaceholder:"Tempel refresh token (opsional)",hint:"Token dikirim ke daemon dan disimpan terenkripsi. Token tidak pernah ditampilkan kembali."},openCodeGo:{apiKeyRequired:"API key wajib diisi.",apiKeyPlaceholder:"Tempel API key",baseUrlPlaceholder:"https://… (opsional)",zenBaseUrlPlaceholder:"https://… (opsional)"},info:{title:"Tentang akun subscription",description:"Token ditulis ke daemon dan digunakan untuk mengautentikasi permintaan upstream. Token disimpan terenkripsi dan tidak pernah ditampilkan kembali. Menghapus akun akan menghapus kredensial tersimpannya."},rename:{failed:"Tidak dapat mengganti nama akun."},refresh:{failed:"Tidak dapat memperbarui token."},errors:{requestFailed:"Permintaan gagal. Silakan coba lagi."},syncWarning:{"external-divergent":"File login CLI eksternal berisi kredensial yang lebih baru daripada akun ini. Token yang tersimpan mungkin berhenti diperbarui — perbarui sekarang atau masuk lagi.","external-not-rotated":"Pembaruan gagal dan CLI eksternal berisi kredensial kedaluwarsa yang sama. Silakan masuk lagi.","duplicate-token":"Akun lain menggunakan kredensial yang sama. Memperbarui salah satu akan mengeluarkan yang lain."},importExternal:{detected:"Login CLI {{name}} yang sudah ada ditemukan di mesin ini.",hint:"Setelah diimpor, aplikasi ini menjaganya tetap segar: setiap kali token diperbarui, file login CLI juga diperbarui, sehingga CLI di terminal tetap masuk.",button:"Impor login CLI yang ada"}},Az={title:"Code CLI",description:"Arahkan coding CLI ke outbound proxy daemon. Halaman ini hanya baca — tidak ada yang perlu dikonfigurasi di sini.",copy:"Salin",copied:"Disalin",baseUrl:{title:"Daemon base URL",description:"Alamat proxy yang terhubung dengan CLI Anda.",label:"Base URL"},token:{title:"Autentikasi",hint:"Kirim 'Authorization: Bearer <your-admin-token>' untuk route admin. Admin token dikonfigurasi dalam daemon (file konfigurasi atau lingkungan) — tidak ditampilkan di sini."},examples:{title:"Contoh lingkungan peluncuran",keyNote:"Gunakan outbound access key yang dibuat di halaman API Service — bukan admin token.",anthropic:"CLI format Anthropic",openai:"CLI format OpenAI"},launchDescription:"Luncurkan coding CLI di terminal, diarahkan ke daemon ini. Daemon menyuntikkan env redirect dan memulai CLI untuk Anda.",refresh:"Segarkan",loading:"Mendeteksi CLI…",cli:{installed:"Terinstal",notFound:"Tidak ditemukan",notFoundHint:"CLI ini tidak ada di PATH host daemon. Instal terlebih dahulu, lalu segarkan.",install:"Instal",installing:"Menginstal…",installingHint:"Menginstal di host daemon — ini mungkin butuh sebentar.",launch:"Luncurkan",launchTitle:"Luncurkan {{name}}",launchDescription:"Membuka terminal baru di host daemon yang menjalankan CLI ini, dirutekan melalui daemon proxy. Pilih direktori kerja opsional.",cwdLabel:"Direktori kerja",cwdPlaceholder:"/path/to/your/project",runningVia:"Berjalan · {{provider}} / {{model}}",stop:"Hentikan"},manual:{title:"Pengaturan manual",description:"Ingin menjalankan CLI sendiri? Arahkan ke daemon dengan variabel lingkungan ini.",show:"Tampilkan",hide:"Sembunyikan"}},Cz={probing:"Memeriksa daemon…",spawning:"Memulai daemon…",failed:"Daemon tidak dapat dimulai",failedHint:"Pastikan Node.js terinstal dan daemon sudah di-build (dist tersedia), atau atur OMNICROSS_DAEMON_ENTRY ke cli.js daemon."},xz={title:"Pengaturan",description:"Preferensi aplikasi desktop.",desktopOnly:"Opsi Startup dan Tray hanya berlaku di aplikasi desktop.",startup:{title:"Startup",autoLaunch:"Luncurkan saat login",autoLaunchHint:"Mulai Omnicross secara otomatis saat Anda masuk.",startMinimized:"Mulai diminimalkan ke tray",startMinimizedHint:"Jalankan di latar belakang tanpa membuka jendela."},tray:{title:"Tray",minimizeOnClose:"Minimalkan ke tray saat ditutup",minimizeOnCloseHint:"Menutup jendela akan menyembunyikannya ke tray, bukan keluar dari aplikasi."},language:{title:"Bahasa",label:"Bahasa antarmuka"}},zz={title:"Statistik penggunaan",description:"Statistik token dan biaya untuk permintaan yang dilayani daemon.",rangeToday:"Hari ini",range7d:"7 hari terakhir",range30d:"30 hari terakhir",rangeCustom:"Kustom",from:"Dari",to:"Sampai",totalCost:"Total biaya",cacheSavings:"Penghematan cache",events:"Permintaan",inputTokens:"Token masukan",outputTokens:"Token keluaran",cacheReadTokens:"Baca cache",cacheWriteTokens:"Tulis cache",reasoningTokens:"Token penalaran",byModel:"Per model",byApiKey:"Per kunci API",provider:"Penyedia",model:"Model",cost:"Biaya",apiKey:"Kunci API",unpriced:"Tanpa harga",unpricedHint:"Tidak ada entri harga untuk model ini — tambahkan di halaman Harga.",unattributed:"Tidak teratribusi",unattributedHint:"Permintaan yang tidak terkait dengan kunci API tertentu. Ini normal sampai atribusi per kunci mulai dicatat.",empty:"Tidak ada permintaan dalam rentang ini.",invalidRange:"Pilih rentang tanggal yang valid."},Iz={title:"Harga model",description:"Harga token per model untuk menghitung biaya permintaan, dalam USD per 1 juta token.",search:"Cari penyedia atau model…",fetchLatest:"Ambil terbaru",fetching:"Mengambil…",addEntry:"Tambah entri",provider:"Penyedia",model:"Model",inputPrice:"Masukan",outputPrice:"Keluaran",cacheReadPrice:"Baca cache",cacheWritePrice:"Tulis cache",source:"Sumber",updated:"Diperbarui",userEdited:"diedit",edit:"Edit",deleteTitle:"Hapus entri harga ini?",empty:"Tabel harga kosong.",emptyHint:"Ambil harga terbaru untuk mengisinya.",noMatches:"Tidak ada entri yang cocok dengan pencarian.",saved:"Entri harga disimpan.",saveFailed:"Gagal menyimpan: {{message}}",deleteFailed:"Gagal menghapus: {{message}}",alreadyDeleted:"Entri sudah tidak ada.",fetchApplied:"{{count}} entri diperbarui dari sumber.",fetchFailed:"Gagal mengambil: {{message}}",requiredId:"Wajib",invalidPrice:"Masukkan angka non-negatif",conflictTitle:"Selesaikan konflik harga",conflictHint:"Entri ini telah Anda edit dan juga berubah di sumber. Pilih per baris untuk mempertahankan nilai Anda (Lewati) atau mengambil yang baru (Timpa).",current:"Saat ini",incoming:"Masuk",overwrite:"Timpa",skip:"Lewati",overwriteAll:"Timpa semua",skipAll:"Lewati semua",applyResolutions:"Terapkan",resolved:"{{overwritten}} ditimpa, {{skipped}} dilewati.",resolvedWithStale:"{{overwritten}} ditimpa, {{skipped}} dilewati. {{stale}} berubah sementara itu dan dibiarkan utuh.",refreshFailed:"Perubahan telah diterapkan, tetapi gagal memuat ulang daftar: {{message}}",sourceBuiltin:"Bawaan",sourceLitellm:"LiteLLM",sourceUser:"Pengguna"},Sz={providerSettings:mz,apiMode:gz,presetName:hz,common:fz,mediaSettings:vz,appLocal:kz,nav:yz,apiService:bz,accounts:Pz,codeCli:Az,daemonStatus:Cz,settings:xz,usageStats:zz,pricing:Iz},wz={loading:"Caricamento della configurazione LLM...",reset:{button:"Ripristina valori predefiniti",confirmTitle:"Ripristinare le impostazioni predefinite?",confirmBody:"Questa operazione cancella le tue personalizzazioni per questo provider e ripristina i valori predefiniti integrati. La tua chiave API e le sessioni salvate vengono mantenute.",confirmButton:"Ripristina valori predefiniti"},reentryBanner:{message:"{{count}} provider abilitato/i richiede/richiedono la re-immissione della chiave API. Apri ciascuno e aggiungi nuovamente la sua chiave."},migrationPack:{barHint:"Trasferisci le chiavi dei provider e i token di abbonamento su un altro computer tramite un pacchetto crittografato.",passphrase:"Passphrase",passphrasePlaceholder:"Inserisci una passphrase",passphraseHint:"Usa almeno 8 caratteri; 12 o più è consigliato.",confirm:"Conferma passphrase",confirmPlaceholder:"Reinserisci la passphrase",mismatch:"Le passphrase non corrispondono.",strength:{weak:"Troppo corta — usa almeno 8 caratteri.",fair:"Accettabile — 12 o più caratteri è più sicuro.",strong:"Passphrase robusta."},export:{button:"Esporta pacchetto",title:"Esporta pacchetto crittografato",subtitle:"Crittografa le chiavi dei provider e i token di abbonamento in un file portabile.",warning:"Questo file contiene segreti decifrabili. Conservalo al sicuro — chiunque abbia il file e la passphrase può leggere le tue chiavi. Una passphrase persa non può essere recuperata.",submit:"Esporta",success:"Pacchetto esportato con successo.",error:"Esportazione non riuscita. Riprova."},import:{button:"Importa pacchetto",title:"Importa pacchetto crittografato",subtitle:"Ripristina le chiavi dei provider e i token di abbonamento da un pacchetto esportato.",hint:"Inserisci la passphrase usata durante l'esportazione, poi scegli il file.",submit:"Importa",successTitle:"Importazione completata",summary:"Importate {{providerKeys}} chiave/i provider, {{poolKeys}} chiave/i pool e {{tokenSets}} set di token.",duplicates:"Ignorate {{count}} chiave/i pool già presenti.",skipped:"Ignorati (nessun provider corrispondente): {{names}}",error:"Passphrase errata o pacchetto corrotto. Nessuna modifica apportata."}},searchPlaceholder:"Cerca provider...",emptySearch:"Nessun provider corrisponde alla ricerca.",emptyList:"Nessun provider configurato.",selectPrompt:"Seleziona un provider per visualizzare i dettagli",listStatus:"{{count}} modello/i",noModels:"Nessun modello configurato",enabled:"Abilitato",disabled:"Disabilitato",showEnabledOnly:"Mostra solo abilitati",showAll:"Mostra tutti i provider",dragHandle:"Trascina per riordinare",reorderFailed:"Salvataggio dell'ordine dei provider non riuscito",credentials:{apiKey:"Chiave API",apiBaseUrl:"URL base API"},filter:{all:"Tutti",chat:"Chat",code:"Codice"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Seleziona un modello",skipTemplates:"Salta, configura manualmente",name:"Nome *",providerType:"Tipo",apiType:"Tipo API",apiTypeOptions:{openai:"Completamento OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Formato API chat/completions OpenAI standard",claudecode:"Formato API Anthropic Messages (Claude Code)"},chatApiFormat:"Formato API",chatApiFormatDescription:"Seleziona il formato API corrispondente all'endpoint del tuo provider",apiKey:"Chiave API",apiKeyPlaceholder:"sk-... o $ENV_VAR",apiKeyHelper:"Usa $NOME_VAR per fare riferimento a variabili d'ambiente",apiKeySetPlaceholder:"Chiave impostata — lascia vuoto per mantenerla",apiKeyReplaceHelper:"Una chiave è memorizzata in modo sicuro. Digita un nuovo valore per sostituirla, o lascia vuoto per mantenerla.",testApiKey:"Testa chiave API",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Anteprima:",models:"Modelli",modelPlaceholder:"Nome modello (es. gpt-4, claude-3-opus)",transformers:"Transformer",transformerConfig:"Transformer API",transformerConfigDescription:"Configura i transformer per adattare i formati di richiesta/risposta API per questo provider",transformerConfigNote:"Il daemon applica questi transformer nella catena di richieste, dopo il transformer di formato del provider (che gestisce la conversione del formato wire). I nomi di transformer sconosciuti vengono ignorati.",enabled:"Abilitato",apiVersion:"Versione API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versione API Azure OpenAI (es. 2024-08-01-preview)",official:"API Anthropic ufficiale",officialHelper:"Abilita se questo provider si connette direttamente all'API Anthropic ufficiale. Disabilita per proxy inversi o servizi di terze parti.",maxConcurrency:"Richieste simultanee max",maxConcurrencyHelper:"Numero massimo di richieste API simultanee inviate a questo provider. Valori più bassi aiutano ad evitare la limitazione della frequenza (errori 429). Imposta `-1` per nessun limite.",codingPlan:{label:"Piano di codifica",description:"Usa un endpoint API separato per i piani di codifica basati su abbonamento",baseUrl:"URL base piano di codifica",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Chiave API piano di codifica (opzionale)",apiKeyPlaceholder:"Lascia vuoto per usare la chiave API del provider",apiKeyHelper:"Richiesto solo se il piano di codifica usa una chiave API diversa",tokenPlanHint:"Alcuni provider (es. Xiaomi MiMo) emettono chiavi Token Plan con prefisso `tp-` — solo informativo, non imposto."},selectTypeFirst:"Seleziona tipo di provider",selectTypeFirstDesc:"Scegli il tipo di provider che vuoi aggiungere",codeProviderNote:"I provider Code richiedono solo chiave API e URL. I modelli sono gestiti dall'Agent Router.",buttons:{cancel:"Annulla",submitAdd:"Aggiungi provider",submitUpdate:"Aggiorna provider",continue:"Continua",back:"Indietro"}},details:{noSelection:"Seleziona un provider per visualizzare i dettagli",apiKey:"Chiave API",apiUrl:"URL API",nameLabel:"Nome provider",modelsEndpoint:"Endpoint modelli",modelsEndpointHelper:"Sostituisci l'endpoint di scoperta se il provider espone un percorso /models personalizzato.",models:"Modelli",transformers:"Transformer",codeProviderNote:"I provider Code (come Claude Code) non richiedono la configurazione dei modelli. I modelli sono gestiti automaticamente dall'Agent Router.",buttons:{more:"Altre impostazioni",delete:"Elimina"}},providerModelSelector:{placeholder:"Seleziona provider e modello",noProviders:"Nessun provider disponibile",noModels:"Nessun modello configurato"},apiKeyPool:{title:"Pool di chiavi API",description:"Configura più chiavi API per il bilanciamento del carico. Ogni sessione rimane associata a una chiave per preservare la cache dei prompt.",defaultLabel:"Predefinita",weight:"Peso",noKey:"Nessuna chiave",labelPlaceholder:"Etichetta (es. Chiave n°1, Produzione)",addKey:"Aggiungi chiave API",add:"Aggiungi",empty:"Nessuna chiave aggiuntiva configurata.",statusCoolingDown:"Raffreddamento {{time}}",statusAuthFailed:"Autenticazione fallita · disabilitata",statusDisabled:"Disabilitata",statusHealthy:"Operativa",agoSeconds:"{{count}}s fa",agoMinutes:"{{count}}min fa",agoHours:"{{count}}h fa",agoDays:"{{count}}g fa"},modelsManager:{searchPlaceholder:"Cerca modelli...",defaultGroup:"Tutti i modelli",add:"Aggiungi modello",manage:"Gestisci",empty:"Nessun modello in questo gruppo",enabled:"Abilitato",disabled:"Disabilitato",filters:{all:"Tutti",vision:"Vision",reasoning:"Ragionamento",free:"Gratuito",tools:"Strumenti"},manualDialog:{title:"Aggiungi modello",subtitle:"Aggiungi un modello personalizzato a questo provider",modelId:"ID modello",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, ecc.",modelIdHelper:"L'identificatore esatto del modello usato nelle chiamate API",modelName:"Nome visualizzato",modelNamePlaceholder:"Nome visualizzato descrittivo (opzionale)",modelNameHelper:"Nome opzionale mostrato nell'interfaccia. Se vuoto, verrà usato l'ID modello",group:"Gruppo",groupPlaceholder:"Seleziona o inserisci un nome di gruppo",submit:"Aggiungi",cancel:"Annulla",helper:"Fornisci l'identificatore esatto del modello esposto dall'API del provider."},editDialog:{title:"Modifica modello",subtitle:"Modifica le impostazioni del modello",modelId:"ID modello",modelIdPlaceholder:"Identificatore modello",modelIdHelper:"L'identificatore del modello usato nelle chiamate API",modelName:"Nome visualizzato",modelNamePlaceholder:"Nome visualizzato descrittivo",modelNameHelper:"Nome mostrato nell'interfaccia",group:"Gruppo",groupPlaceholder:"Seleziona o inserisci un nome di gruppo",submit:"Salva",cancel:"Annulla",vision:"Capacità Vision",visionHint:"Indica se questo modello supporta input immagine/vision",reasoning:"Modello di ragionamento",reasoningHint:"Indica se questo modello supporta la modalità di pensiero/ragionamento"},manageDialog:{title:"Gestisci modelli",cachedAt:"Memorizzato il {{date}} ({{source}})",refresh:"Aggiorna",close:"Chiudi",raw:"JSON grezzo",empty:"Nessun modello remoto disponibile.",error:"Caricamento modelli non riuscito: {{message}}",addFromCatalog:"Aggiungi",sourceCache:"cache",sourceNetwork:"live",contextLength:"Contesto {{value}} token",maxTokens:"Max {{value}} token"},messages:{added:"Modello aggiunto.",updated:"Modello aggiornato.",removed:"Modello rimosso.",duplicate:"Il modello esiste già.",refreshed:"Modelli aggiornati",refreshFailed:"Aggiornamento modelli non riuscito"},testDialog:{title:"Test di connettività del modello",provider:"Provider",model:"Modello",testing:"Test in corso...",success:"Test riuscito",successMessage:"Il modello è accessibile normalmente",failure:"Test non riuscito",aiResponse:"Risposta AI",charCount:"{{count}} caratteri",duration:"Durata {{time}}s",close:"Chiudi",retest:"Ritesta",testButton:"Testa modello",unsupportedFormat:"Il test non è ancora supportato per questo formato di provider."}},router:{title:"Configurazione router",description:"Configura quale provider/modello usare per i diversi scenari.",labels:{default:"Predefinito",background:"sfondo",think:"ragionamento",longContext:"Contesto lungo",webSearch:"Ricerca web",image:"Immagine",longContextThreshold:"Soglia contesto lungo"},helper:{longContextThreshold:"Conteggio token prima di passare al modello a contesto lungo."},placeholder:{required:"Obbligatorio",optional:"Opzionale"}},agentRouter:{title:"Agent Router",description:"Configura il routing bidirezionale tra le modalità Chat e Codice.",searchPlaceholder:"Cerca router...",noSearchResults:"Nessun router corrisponde alla ricerca.",tabs:{chatToCode:"Chat → Codice",codeToChatPlaceholder:"Codice → Chat"},chatToCode:{title:"Router Chat verso Codice",description:"Usa i provider chat in modalità agente/codifica",addRouter:"Aggiungi router",emptyState:"Nessun router Chat→Codice configurato. Aggiungine uno per usare i provider chat in modalità codifica.",form:{name:"Nome router",namePlaceholder:"Il mio router Chat→Codice",chatProvider:"Provider Chat",chatProviderPlaceholder:"Seleziona un provider chat",mode:"Modalità",modeSimple:"Semplice",modeAdvanced:"Avanzato",modeSimpleDesc:"Passthrough diretto al provider chat",modeAdvancedDesc:"Configura la mappatura dei modelli e la gestione del contesto",enabled:"Abilitato",save:"Salva router",cancel:"Annulla"},list:{provider:"Provider",mode:"Modalità",status:"Stato"},mappings:{title:"Mappature modelli",description:"Mappa i modelli del provider Chat ai modelli del provider Codice",count:"mappatura/e",empty:"Nessuna mappatura di modelli configurata. Aggiungi mappature per instradare i modelli chat verso i provider codice.",addNew:"Aggiungi nuova mappatura",selectSource:"Seleziona modello sorgente (Chat)",selectTarget:"Seleziona modello destinazione (Codice)",targetPlaceholder:"Inserisci il nome del modello Claude Code",notSet:"(Non impostato - clicca per selezionare)",add:"Aggiungi",edit:"Modifica",done:"Fatto"},advanced:{title:"Configurazione avanzata",description:"Configura i modelli per i diversi tipi di attività",helpText:"Il modello predefinito è obbligatorio. Gli altri modelli sono opzionali e torneranno al modello predefinito se non configurati.",default:{label:"Predefinito",placeholder:"Seleziona modello predefinito",description:"Modello principale per attività generali (simile a Claude Sonnet)"},background:{label:"Sfondo",placeholder:"Seleziona modello sfondo",description:"Modello leggero per attività in background (simile a Claude Haiku)"},think:{label:"Ragionamento",placeholder:"Seleziona modello di ragionamento",description:"Modello avanzato per ragionamento complesso (simile a Claude Opus)"},image:{label:"Immagine",placeholder:"Seleziona modello immagine",description:"Modello per attività legate alle immagini con capacità vision"}}},codeToChat:{title:"Router Codice verso Chat",description:"Esponi i modelli del piano di codifica in modalità chat",addRouter:"Aggiungi router",emptyState:"Nessun router Codice→Chat configurato. Aggiungine uno per esporre i modelli del piano di codifica in modalità chat.",form:{name:"Nome router",namePlaceholder:"Il mio router Codice→Chat",codeProvider:"Provider Codice",codeProviderPlaceholder:"Seleziona un provider codice",codeProviderHelper:"Seleziona il provider Codice da usare per la trasformazione",models:"Modelli piano di codifica",modelsHelper:"Seleziona i modelli del piano di codifica da esporre",enabled:"Abilitato",save:"Salva router",cancel:"Annulla"},mappings:{title:"Mappature modelli",description:"Mappa i modelli del provider Codice ai modelli del provider Chat per esporli",count:"mappatura/e",empty:"Nessuna mappatura di modelli configurata. Aggiungi mappature per esporre i modelli Codice in modalità chat.",addNew:"Aggiungi nuova mappatura",selectSource:"Seleziona modello sorgente (Codice)",selectTarget:"Seleziona modello destinazione (Chat)",sourcePlaceholder:"Inserisci il nome del modello sorgente",targetPlaceholder:"Inserisci il nome del modello destinazione",add:"Aggiungi",edit:"Modifica",done:"Fatto"}},transformers:{title:"Transformer",description:"Configura i transformer per la conversione delle richieste/risposte",noProvider:"Seleziona un provider per configurare i transformer",empty:"Nessun transformer",count:"{{count}} transformer/s"},status:{enabled:"Abilitato",disabled:"Disabilitato"},messages:{routerAdded:"Router aggiunto con successo",routerUpdated:"Router aggiornato con successo",routerDeleted:"Router eliminato con successo",saveFailed:"Salvataggio del router non riuscito"}},presets:{title:"Aggiunta rapida provider",added:"Aggiunto",add:"Aggiungi",features:{search:"Ricerca",vision:"Vision",mcp:"MCP",codingPlan:"Piano di codifica"}},alerts:{deleteConfirm:"Sei sicuro di voler eliminare questo provider?"},errors:{nameRequired:"Il nome del provider è obbligatorio",urlRequired:"L'URL base API è obbligatoria",urlInvalid:"Inserisci un URL valido (es. https://api.example.com)",saveFailed:"Salvataggio del provider non riuscito",deleteFailed:"Errore durante l'eliminazione del provider. Riprova.",toggleFailed:"Errore durante l'abilitazione/disabilitazione del provider. Riprova."},openRouter:{title:"Routing provider OpenRouter",description:"Configura come le richieste vengono instradate verso i diversi provider su OpenRouter.",sort:"Strategia di routing",sortTooltip:"Scegli come dare priorità ai provider. Auto usa il bilanciamento del carico intelligente.",order:"Ordine di priorità provider",orderTooltip:"Specifica i provider da provare in ordine (es. anthropic, openai, together). Premi Invio per aggiungere.",orderPlaceholder:"Digita lo slug del provider e premi Invio...",allowFallbacks:"Consenti fallback",allowFallbacksTooltip:"Se abilitato, OpenRouter proverà provider di backup se il principale non è disponibile.",requireParameters:"Richiedi tutti i parametri",requireParametersTooltip:"Instrada solo verso provider che supportano tutti i parametri nella richiesta.",dataCollection:"Politica di raccolta dati",dataCollectionTooltip:"Controlla se usare provider che potrebbero archiviare o addestrare sui tuoi dati.",zdr:"Zero Data Retention",zdrTooltip:"Instrada solo verso endpoint con politica Zero Data Retention.",only:"Consenti solo questi provider",onlyTooltip:"Usa solo questi provider specifici. Lascia vuoto per consentire tutti i provider.",onlyPlaceholder:"Digita lo slug del provider e premi Invio...",ignore:"Ignora provider",ignoreTooltip:"Salta questi provider durante il routing delle richieste.",ignorePlaceholder:"Digita lo slug del provider e premi Invio...",quantizations:"Filtro quantizzazione",quantizationsTooltip:"Usa solo provider con livelli di quantizzazione specifici. Una precisione inferiore può ridurre la qualità ma migliorare la velocità.",maxPrice:"Prezzo massimo",maxPriceTooltip:"Imposta limiti di prezzo massimi per milione di token. Lascia vuoto per nessun limite.",configured:"Configurato"}},Tz={label:"Modalità API",standard:"Standard",codingPlan:"Piano di codifica",tokenPlan:"Piano token",apiKeyPrefixHint:"Le chiavi per questo piano iniziano tipicamente con `{{prefix}}`. Solo indicativo — non imposto.",dashscopeCodingPlanSeparateKey:"Il piano di codifica DashScope usa una chiave API separata dall'endpoint standard.",baiduCodingPlanSeparateKey:"Il piano di codifica Qianfan usa una chiave API separata dall'endpoint standard.",tencentTokenPlanAnthropicOnly:"Il piano token Tencent è esclusivamente compatibile con il protocollo Anthropic.",xiaomiTokenPlanRegions:"L'URL base predefinita è `token-plan-cn.*`. Puoi modificarla manualmente in `token-plan-sgp.*` o `token-plan-ams.*`.",confirmOverwriteTitle:"Cambiare modalità API?",confirmOverwriteBody:"Hai personalizzato l'URL API o la chiave API. Il cambio di modalità sovrascriverà questi valori con i predefiniti della nuova modalità — oppure mantieni le personalizzazioni e aggiorna solo l'etichetta della modalità.",overwriteAndSwitch:"Sovrascrivi e cambia",keepCustomizations:"Mantieni personalizzazioni"},jz={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},Mz={cancel:"Annulla",close:"Chiudi",copy:"Copia",delete:"Elimina",dismiss:"Ignora",save:"Salva",optional:"opzionale",retry:"Riprova",loading:"Caricamento…"},Nz={common:{learnMore:"Documentazione"}},Lz={notSupportedByDaemon:"Non ancora supportato dal daemon",discoveryUnsupportedFormat:"La scoperta dei modelli non è ancora supportata per questo formato di provider. Aggiungi i modelli manualmente."},Rz={subtitle:"Pannello di controllo",providers:"Provider",apiService:"Servizio API",accounts:"Account",codeCli:"Code CLI",settings:"Impostazioni",usageStats:"Utilizzo",pricing:"Prezzi"},Dz={title:"Servizio API",description:"Configura il server API in uscita, il routing dei modelli per endpoint e le chiavi di accesso nominate.",loading:"Caricamento della configurazione del server…",loadError:"Impossibile caricare la configurazione del server. Verifica che il daemon sia raggiungibile.",enable:{label:"Abilita server in uscita",description:"Avvia il server API locale che instrada le chiamate esterne attraverso i tuoi provider."},networkBinding:{label:"Consenti accesso LAN",description:"Associa il server all'interfaccia di rete invece del solo loopback.",warning:"L'accesso LAN espone il server API agli altri dispositivi della rete. Combinato con il routing per abbonamento, le richieste possono consumare la quota di abbonamento — tienilo disabilitato a meno che tu non ti fidi della rete."},status:{running:"Server in esecuzione",stopped:"Server arrestato",runningHint:"Il server API in uscita sta accettando richieste.",stoppedHint:"Abilita il server per iniziare ad accettare richieste.",port:"porta {{port}}",loopback:"URL loopback",lan:"URL LAN"},endpoints:{title:"Routing endpoint",description:"Scegli il modello verso cui viene instradato ogni formato wire. Il modello predefinito è definito qui — il server è un router, non un'app di chat."},endpoint:{name:{chat:"Chat OpenAI",responses:"Risposte OpenAI",messages:"Messaggi Anthropic",gemini:"Gemini"},defaultModel:"Modello predefinito",backgroundModel:"Modello sfondo",visionModel:"Modello Vision",noVisionModel:"Nessuno",backgroundModelIds:"ID modelli sfondo",backgroundModelIdsPlaceholder:"ID modelli separati da virgola",modelPlaceholder:"Seleziona un modello…",useSubscription:"Usa abbonamento",subscriptionUnsupported:"Il routing per abbonamento non è disponibile per questo endpoint."},keys:{title:"Chiavi di accesso",description:"Chiavi nominate che le chiamate esterne inviano come token Bearer. La chiave completa viene mostrata solo una volta alla creazione.",namePlaceholder:"Nome chiave (es. il-mio-cli)",create:"Crea chiave",empty:"Nessuna chiave di accesso ancora.",enabled:"Abilitata",disabled:"Disabilitata",revoked:"Revocata",toggle:"Attiva/disattiva chiave",revoke:"Revoca",revokeConfirmTitle:"Revocare questa chiave?",revokeConfirmDesc:`La revoca di "{{name}}" la blocca immediatamente dall'autenticazione. Questa operazione è irreversibile.`,created:{title:"Chiave creata",warning:"Copia questa chiave ora — non verrà mostrata di nuovo. Conservala al sicuro.",copy:"Copia",copied:"Copiato",dismiss:"Fatto"}}},Ez={title:"Account e abbonamenti",description:"Gestisci le credenziali di abbonamento attraverso cui il server instrada. I token vengono scritti qui ma non vengono mai mostrati.",loading:"Caricamento account…",empty:"Nessun provider di abbonamento disponibile.",signIn:"Accedi",oauth:{title:"Accedi a {{name}}",description:"Apri la pagina di accesso nel tuo browser, autorizza, poi incolla il codice di autorizzazione qui sotto. Il codice viene trasmesso solo al daemon — il token generato non viene mai mostrato.",openPage:"Apri pagina di accesso",codeLabel:"Codice di autorizzazione",codePlaceholder:"Incolla il codice qui",submit:"Completa accesso"},codexOauth:{title:"Accedi a {{name}}",description:"Apri la pagina di accesso nel tuo browser e autorizza. Il daemon cattura automaticamente il risultato — tieni questa finestra aperta fino al completamento. Il token non viene mai mostrato.",waiting:"In attesa del completamento dell'accesso nel browser…",failed:"Accesso non riuscito. Riprova."},clearProvider:"Cancella tutto",clearConfirmTitle:"Cancellare gli account {{name}}?",clearConfirmDesc:"Questa operazione rimuove tutte le credenziali memorizzate per questo provider. È irreversibile.",credential:{ok:"Configurato",notConfigured:"Non configurato"},kind:{"pass-through":"Credenziali pass-through","oauth-bearer":"Bearer OAuth","static-bearer":"Chiave bearer statica"},reason:{"missing-credential":"Nessuna credenziale memorizzata.",expired:"Credenziale scaduta.","reauth-required":"Riautenticazione richiesta.","refresh-failed":"Rinnovo token non riuscito.","not-refreshable":"La credenziale non è rinnovabile.",unknown:"Stato sconosciuto."},status:{unconfigured:"Non configurato",authorized:"Autorizzato",configured:"Configurato",expired:"Scaduto",error:"Errore"},authMethod:{oauth:"OAuth",setup_token:"Token di configurazione",manual:"Manuale"},list:{empty:"Nessun account memorizzato per questo provider.",active:"Attivo",expiresAt:"Scade il {{value}}",setActive:"Imposta attivo",remove:"Rimuovi",removeConfirmTitle:"Rimuovere questo account?",removeConfirmDesc:'La rimozione di "{{name}}" elimina la credenziale memorizzata. Questa operazione è irreversibile.',title:"Account"},write:{trigger:"Aggiungi credenziale",title:"Scrivi credenziale {{name}}",description:"Incolla un token già ottenuto. I campi sono limitati a ciò che questo provider accetta; il token viene memorizzato, mai mostrato.",authMethod:"Metodo di autenticazione",status:"Stato",subscriptionLevel:"Livello abbonamento",subscriptionLevelNone:"Non impostato",submit:"Salva credenziale"},field:{accessToken:"Token di accesso",refreshToken:"Token di rinnovo",idToken:"Token ID",apiKey:"Chiave API",expiresAt:"Scade il (ISO)",setupTokenExpiresAt:"Il token di configurazione scade il (ISO)",accountId:"ID account",email:"E-mail",organizationId:"ID organizzazione",baseUrl:"URL base",zenBaseUrl:"URL base Zen"},provider:{claude:{title:"Claude",description:"Credenziali di abbonamento Anthropic instradate dal daemon."},codex:{title:"Codex",description:"Credenziali di abbonamento OpenAI Codex instradate dal daemon."},gemini:{title:"Gemini",description:"Credenziali di abbonamento Google Gemini instradate dal daemon."},opencodego:{title:"OpenCodeGo",description:"Credenziali con chiave API statica instradate dal daemon."}},authMethodLabel:"Metodo di autorizzazione",authMethodDesc:{oauth:"Accedi tramite il browser; il daemon cattura e memorizza il token.",manual:"Incolla un token già ottenuto. Viene memorizzato, mai mostrato."},actions:{authorize:"Autorizza",enterToken:"Inserisci token",refresh:"Aggiorna"},accounts:{addAccount:"Aggiungi account"},detail:{authMethod:"Metodo di autorizzazione",subscriptionLevel:"Livello abbonamento",expiresAt:"Scade",lastRefreshed:"Ultimo rinnovo",label:"Etichetta account",labelPlaceholder:"Dai un nome a questo account",saveLabel:"Salva etichetta"},oauthFlow:{step1:{title:"Apri la pagina di autorizzazione",desc:"Apri la pagina di accesso nel tuo browser."},step2:{title:"Autorizza l'accesso",desc:"Accedi e approva l'accesso per il provider."},step3:{title:"Copia il codice di autorizzazione",desc:"La pagina mostra un codice di autorizzazione dopo l'approvazione."},step4:{title:"Incolla il codice",desc:"Incolla il codice di autorizzazione qui sotto per completare. Il codice viene trasmesso solo al daemon — il token generato non viene mai mostrato."},authorize:"Completa accesso",showUrl:"Mostra URL di autorizzazione"},manual:{title:"Incolla credenziale",description:"Incolla un token già ottenuto. I campi sono limitati a ciò che questo provider accetta; il token viene memorizzato, mai mostrato.",accessTokenPlaceholder:"Incolla il token di accesso",refreshTokenPlaceholder:"Incolla il token di rinnovo (opzionale)",hint:"Il token viene inviato al daemon e memorizzato in forma crittografata. Non viene mai mostrato."},openCodeGo:{apiKeyRequired:"Una chiave API è obbligatoria.",apiKeyPlaceholder:"Incolla la chiave API",baseUrlPlaceholder:"https://… (opzionale)",zenBaseUrlPlaceholder:"https://… (opzionale)"},info:{title:"Informazioni sugli account di abbonamento",description:"I token vengono scritti nel daemon e usati per autenticare le richieste upstream. Vengono memorizzati in forma crittografata e non vengono mai mostrati. La rimozione di un account elimina la credenziale memorizzata."},rename:{failed:"Impossibile rinominare l'account."},refresh:{failed:"Impossibile rinnovare il token."},errors:{requestFailed:"Richiesta non riuscita. Riprova."},syncWarning:{"external-divergent":"Il file di accesso della CLI esterna contiene credenziali più recenti di questo account. Il token salvato potrebbe non aggiornarsi più: aggiorna ora o accedi di nuovo.","external-not-rotated":"L'aggiornamento non è riuscito e la CLI esterna contiene le stesse credenziali scadute. Accedi di nuovo.","duplicate-token":"Un altro account condivide queste credenziali. Aggiornarne uno disconnetterà l'altro."},importExternal:{detected:"È stato trovato un accesso CLI {{name}} esistente su questa macchina.",hint:"Dopo l'importazione, questa app lo mantiene aggiornato: a ogni rinnovo del token viene aggiornato anche il file di accesso della CLI, così la CLI del terminale resta connessa.",button:"Importa accesso CLI esistente"}},Oz={title:"Code CLI",description:"Punta un CLI di codifica al proxy in uscita del daemon. Questa pagina è di sola lettura — non c'è nulla da configurare qui.",copy:"Copia",copied:"Copiato",baseUrl:{title:"URL base daemon",description:"L'indirizzo proxy a cui si connette il tuo CLI.",label:"URL base"},token:{title:"Autenticazione",hint:"Invia 'Authorization: Bearer <il-tuo-token-admin>' per le route admin. Il token admin è configurato nel daemon (nel file di configurazione o nell'ambiente) — non viene mai mostrato qui."},examples:{title:"Esempio di ambiente di avvio",keyNote:"Usa una chiave di accesso in uscita creata nella pagina Servizio API — non il token admin.",anthropic:"CLI formato Anthropic",openai:"CLI formato OpenAI"},launchDescription:"Avvia un CLI di codifica in un terminale, puntato verso questo daemon. Il daemon inietta l'ambiente di reindirizzamento e avvia il CLI per te.",refresh:"Aggiorna",loading:"Rilevamento CLI…",cli:{installed:"Installato",notFound:"Non trovato",notFoundHint:"Questo CLI non è nel PATH dell'host daemon. Installalo, poi aggiorna.",install:"Installa",installing:"Installazione…",installingHint:"Installazione sull'host daemon — potrebbe richiedere un minuto.",launch:"Avvia",launchTitle:"Avvia {{name}}",launchDescription:"Apre un nuovo terminale sull'host daemon che esegue questo CLI, instradato tramite il proxy daemon. Scegli una directory di lavoro opzionale.",cwdLabel:"Directory di lavoro",cwdPlaceholder:"/percorso/al/tuo/progetto",runningVia:"In esecuzione · {{provider}} / {{model}}",stop:"Arresta"},manual:{title:"Configurazione manuale",description:"Preferisci eseguire il CLI tu stesso? Puntalo al daemon con queste variabili d'ambiente.",show:"Mostra",hide:"Nascondi"}},Kz={probing:"Verifica del daemon…",spawning:"Avvio del daemon…",failed:"Il daemon non è riuscito ad avviarsi",failedHint:"Assicurati che Node.js sia installato e che il daemon sia compilato (dist presente), oppure imposta OMNICROSS_DAEMON_ENTRY sul cli.js del daemon."},Uz={title:"Impostazioni",description:"Preferenze dell'applicazione desktop.",desktopOnly:"Le opzioni di avvio e barra delle applicazioni si applicano solo all'app desktop.",startup:{title:"Avvio",autoLaunch:"Avvia all'accesso",autoLaunchHint:"Avvia Omnicross automaticamente all'accesso.",startMinimized:"Avvia ridotto nella barra delle applicazioni",startMinimizedHint:"Avvia in background senza aprire la finestra."},tray:{title:"Barra delle applicazioni",minimizeOnClose:"Riduci nella barra alla chiusura",minimizeOnCloseHint:"La chiusura della finestra la nasconde nella barra invece di uscire."},language:{title:"Lingua",label:"Lingua dell'interfaccia"}},Hz={title:"Statistiche di utilizzo",description:"Statistiche di token e costi delle richieste servite dal daemon.",rangeToday:"Oggi",range7d:"Ultimi 7 giorni",range30d:"Ultimi 30 giorni",rangeCustom:"Personalizzato",from:"Dal",to:"Al",totalCost:"Costo totale",cacheSavings:"Risparmio cache",events:"Richieste",inputTokens:"Token di input",outputTokens:"Token di output",cacheReadTokens:"Lettura cache",cacheWriteTokens:"Scrittura cache",reasoningTokens:"Token di ragionamento",byModel:"Per modello",byApiKey:"Per chiave API",provider:"Provider",model:"Modello",cost:"Costo",apiKey:"Chiave API",unpriced:"Senza prezzo",unpricedHint:"Non esiste una voce di prezzo per questo modello — aggiungila nella pagina Prezzi.",unattributed:"Non attribuito",unattributedHint:"Richieste non collegate a una chiave API specifica. È normale finché l’attribuzione per chiave non viene registrata.",empty:"Nessuna richiesta in questo intervallo.",invalidRange:"Seleziona un intervallo di date valido."},Fz={title:"Prezzi dei modelli",description:"Prezzi dei token per modello usati per calcolare il costo delle richieste, in USD per milione di token.",search:"Cerca provider o modello…",fetchLatest:"Scarica più recenti",fetching:"Scaricamento…",addEntry:"Aggiungi voce",provider:"Provider",model:"Modello",inputPrice:"Input",outputPrice:"Output",cacheReadPrice:"Lettura cache",cacheWritePrice:"Scrittura cache",source:"Origine",updated:"Aggiornato",userEdited:"modificato",edit:"Modifica",deleteTitle:"Eliminare questa voce di prezzo?",empty:"La tabella dei prezzi è vuota.",emptyHint:"Scarica i prezzi più recenti per popolarla.",noMatches:"Nessuna voce corrisponde alla ricerca.",saved:"Voce di prezzo salvata.",saveFailed:"Salvataggio non riuscito: {{message}}",deleteFailed:"Eliminazione non riuscita: {{message}}",alreadyDeleted:"La voce non esisteva più.",fetchApplied:"{{count}} voci aggiornate dall’origine.",fetchFailed:"Scaricamento non riuscito: {{message}}",requiredId:"Obbligatorio",invalidPrice:"Inserisci un numero non negativo",conflictTitle:"Risolvi i conflitti di prezzo",conflictHint:"Queste voci sono state modificate da te e sono cambiate anche nell’origine. Scegli riga per riga se mantenere il tuo valore (Salta) o adottare quello in arrivo (Sovrascrivi).",current:"Attuale",incoming:"In arrivo",overwrite:"Sovrascrivi",skip:"Salta",overwriteAll:"Sovrascrivi tutto",skipAll:"Salta tutto",applyResolutions:"Applica",resolved:"{{overwritten}} sovrascritte, {{skipped}} saltate.",resolvedWithStale:"{{overwritten}} sovrascritte, {{skipped}} saltate. {{stale}} sono cambiate nel frattempo e sono rimaste intatte.",refreshFailed:"La modifica è stata applicata, ma il ricaricamento dell'elenco non è riuscito: {{message}}",sourceBuiltin:"Integrato",sourceLitellm:"LiteLLM",sourceUser:"Utente"},Bz={providerSettings:wz,apiMode:Tz,presetName:jz,common:Mz,mediaSettings:Nz,appLocal:Lz,nav:Rz,apiService:Dz,accounts:Ez,codeCli:Oz,daemonStatus:Kz,settings:Uz,usageStats:Hz,pricing:Fz},Vz={loading:"LLM 設定を読み込み中...",reset:{button:"デフォルトに戻す",confirmTitle:"デフォルト設定に戻しますか?",confirmBody:"このプロバイダーへのカスタマイズがクリアされ、組み込みのデフォルト設定に戻ります。API キーと保存済みセッションはそのまま保持されます。",confirmButton:"デフォルトに戻す"},reentryBanner:{message:"{{count}} 個の有効なプロバイダーで API キーの再入力が必要です。各プロバイダーを開いてキーを再入力してください。"},migrationPack:{barHint:"暗号化されたパックを使用して、プロバイダーキーとサブスクリプショントークンを別のマシンに移行します。",passphrase:"パスフレーズ",passphrasePlaceholder:"パスフレーズを入力",passphraseHint:"8 文字以上を使用してください。12 文字以上を推奨します。",confirm:"パスフレーズの確認",confirmPlaceholder:"パスフレーズを再入力",mismatch:"パスフレーズが一致しません。",strength:{weak:"短すぎます — 8 文字以上を使用してください。",fair:"OK — 12 文字以上がより安全です。",strong:"強いパスフレーズです。"},export:{button:"パックをエクスポート",title:"暗号化パックをエクスポート",subtitle:"プロバイダーキーとサブスクリプショントークンをポータブルファイルに暗号化します。",warning:"このファイルには復号可能な機密情報が含まれています。大切に保管してください — ファイルとパスフレーズがあれば誰でもキーを読み取れます。パスフレーズを紛失した場合は復旧できません。",submit:"エクスポート",success:"パックのエクスポートに成功しました。",error:"エクスポートに失敗しました。もう一度お試しください。"},import:{button:"パックをインポート",title:"暗号化パックをインポート",subtitle:"エクスポートしたパックからプロバイダーキーとサブスクリプショントークンを復元します。",hint:"パックのエクスポート時に使用したパスフレーズを入力し、ファイルを選択してください。",submit:"インポート",successTitle:"インポート完了",summary:"プロバイダーキー {{providerKeys}} 件、プールキー {{poolKeys}} 件、トークンセット {{tokenSets}} 件をインポートしました。",duplicates:"すでに存在するプールキー {{count}} 件をスキップしました。",skipped:"スキップ(一致するプロバイダーなし): {{names}}",error:"パスフレーズが間違っているか、パックが破損しています。変更は行われませんでした。"}},searchPlaceholder:"プロバイダーを検索...",emptySearch:"検索条件に一致するプロバイダーがありません。",emptyList:"プロバイダーが設定されていません。",selectPrompt:"プロバイダーを選択して詳細を表示",listStatus:"{{count}} 件のモデル",noModels:"モデルが設定されていません",enabled:"有効",disabled:"無効",showEnabledOnly:"有効のみ表示",showAll:"すべてのプロバイダーを表示",dragHandle:"ドラッグして並び替え",reorderFailed:"プロバイダーの順序を保存できませんでした",credentials:{apiKey:"API キー",apiBaseUrl:"API ベース URL"},filter:{all:"すべて",chat:"チャット",code:"コード"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"テンプレートを選択",skipTemplates:"スキップして手動設定",name:"名前 *",providerType:"タイプ",apiType:"API タイプ",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"標準的な OpenAI chat/completions API 形式",claudecode:"Anthropic Messages API 形式(Claude Code)"},chatApiFormat:"API フォーマット",chatApiFormatDescription:"プロバイダーのエンドポイントに合った API フォーマットを選択してください",apiKey:"API キー",apiKeyPlaceholder:"sk-... または $ENV_VAR",apiKeyHelper:"$VAR_NAME を使って環境変数を参照できます",apiKeySetPlaceholder:"キーは設定済みです — 変更しない場合は空欄のままにしてください",apiKeyReplaceHelper:"キーは安全に保存されています。新しい値を入力すると置き換えられます。空欄のままにすると変更されません。",testApiKey:"API キーをテスト",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"プレビュー:",models:"モデル",modelPlaceholder:"モデル名(例: gpt-4、claude-3-opus)",transformers:"トランスフォーマー",transformerConfig:"API トランスフォーマー",transformerConfigDescription:"このプロバイダーの API リクエスト/レスポンス形式を変換するトランスフォーマーを設定します",transformerConfigNote:"デーモンはリクエストチェーン内でこれらのトランスフォーマーをプロバイダーのフォーマットトランスフォーマー(wire フォーマット変換を担当)の後に適用します。不明なトランスフォーマー名はスキップされます。",enabled:"有効",apiVersion:"API バージョン",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI の API バージョン(例: 2024-08-01-preview)",official:"Anthropic 公式 API",officialHelper:"このプロバイダーが Anthropic 公式 API に直接接続する場合は有効にしてください。リバースプロキシやサードパーティサービスの場合は無効にしてください。",maxConcurrency:"最大同時リクエスト数",maxConcurrencyHelper:"このプロバイダーへの最大同時 API リクエスト数。低い値にするとレート制限(429 エラー)を回避しやすくなります。`-1` を設定すると無制限になります。",codingPlan:{label:"Coding Plan",description:"サブスクリプション型 Coding Plan に専用 API エンドポイントを使用します",baseUrl:"Coding Plan ベース URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API キー(任意)",apiKeyPlaceholder:"空欄にするとプロバイダーの API キーを使用します",apiKeyHelper:"Coding Plan が別の API キーを使用する場合のみ必要です",tokenPlanHint:"一部のプロバイダー(例: Xiaomi MiMo)は `tp-` で始まる Token Plan キーを発行しています — 参考情報のみで、強制ではありません。"},selectTypeFirst:"プロバイダータイプを選択",selectTypeFirstDesc:"追加するプロバイダーのタイプを選択してください",codeProviderNote:"Code プロバイダーは API キーと URL のみ必要です。モデルは Agent Router が管理します。",buttons:{cancel:"キャンセル",submitAdd:"プロバイダーを追加",submitUpdate:"プロバイダーを更新",continue:"続行",back:"戻る"}},details:{noSelection:"プロバイダーを選択して詳細を表示",apiKey:"API キー",apiUrl:"API URL",nameLabel:"プロバイダー名",modelsEndpoint:"モデルエンドポイント",modelsEndpointHelper:"プロバイダーがカスタムの /models パスを提供している場合、ここで上書きできます。",models:"モデル",transformers:"トランスフォーマー",codeProviderNote:"Code プロバイダー(Claude Code など)はモデル設定が不要です。モデルは Agent Router によって自動的に管理されます。",buttons:{more:"詳細設定",delete:"削除"}},providerModelSelector:{placeholder:"プロバイダーとモデルを選択",noProviders:"利用可能なプロバイダーがありません",noModels:"設定済みのモデルがありません"},apiKeyPool:{title:"API キープール",description:"負荷分散のために複数の API キーを設定します。プロンプトキャッシュを維持するため、各セッションは 1 つのキーに固定されます。",defaultLabel:"デフォルト",weight:"重み",noKey:"キーなし",labelPlaceholder:"ラベル(例: キー #1、本番環境)",addKey:"API キーを追加",add:"追加",empty:"追加のキーが設定されていません。",statusCoolingDown:"クールダウン中 {{time}}",statusAuthFailed:"認証失敗 · 無効",statusDisabled:"無効",statusHealthy:"正常",agoSeconds:"{{count}} 秒前",agoMinutes:"{{count}} 分前",agoHours:"{{count}} 時間前",agoDays:"{{count}} 日前"},modelsManager:{searchPlaceholder:"モデルを検索...",defaultGroup:"すべてのモデル",add:"モデルを追加",manage:"管理",empty:"このグループにモデルがありません",enabled:"有効",disabled:"無効",filters:{all:"すべて",vision:"ビジョン",reasoning:"推論",free:"無料",tools:"ツール"},manualDialog:{title:"モデルを追加",subtitle:"このプロバイダーにカスタムモデルを追加します",modelId:"モデル ID",modelIdPlaceholder:"gpt-4o、claude-3.5、gemini-2.0-flash など",modelIdHelper:"API 呼び出し時に使用する正確なモデル識別子",modelName:"表示名",modelNamePlaceholder:"わかりやすい表示名(任意)",modelNameHelper:"UI に表示される名前。空欄の場合はモデル ID が使用されます",group:"グループ",groupPlaceholder:"グループ名を選択または入力",submit:"追加",cancel:"キャンセル",helper:"プロバイダー API が返す正確なモデル識別子を入力してください。"},editDialog:{title:"モデルを編集",subtitle:"モデル設定を変更",modelId:"モデル ID",modelIdPlaceholder:"モデル識別子",modelIdHelper:"API 呼び出し時に使用するモデル識別子",modelName:"表示名",modelNamePlaceholder:"わかりやすい表示名",modelNameHelper:"UI に表示される名前",group:"グループ",groupPlaceholder:"グループ名を選択または入力",submit:"保存",cancel:"キャンセル",vision:"ビジョン機能",visionHint:"このモデルが画像/ビジョン入力に対応しているかどうか",reasoning:"思考モデル",reasoningHint:"このモデルが思考/推論モードに対応しているかどうか"},manageDialog:{title:"モデルを管理",cachedAt:"{{date}} にキャッシュ済み({{source}})",refresh:"更新",close:"閉じる",raw:"Raw JSON",empty:"リモートモデルが利用できません。",error:"モデルの読み込みに失敗しました: {{message}}",addFromCatalog:"追加",sourceCache:"キャッシュ",sourceNetwork:"ライブ",contextLength:"コンテキスト {{value}} トークン",maxTokens:"最大 {{value}} トークン"},messages:{added:"モデルを追加しました。",updated:"モデルを更新しました。",removed:"モデルを削除しました。",duplicate:"モデルはすでに存在します。",refreshed:"モデルを更新しました",refreshFailed:"モデルの更新に失敗しました"},testDialog:{title:"モデル接続テスト",provider:"プロバイダー",model:"モデル",testing:"テスト中...",success:"テスト成功",successMessage:"モデルに正常にアクセスできます",failure:"テスト失敗",aiResponse:"AI レスポンス",charCount:"{{count}} 文字",duration:"所要時間 {{time}} 秒",close:"閉じる",retest:"再テスト",testButton:"モデルをテスト",unsupportedFormat:"このプロバイダー形式のテストはまだサポートされていません。"}},router:{title:"ルーター設定",description:"シナリオごとに使用するプロバイダー/モデルを設定します。",labels:{default:"デフォルト",background:"バックグラウンド",think:"思考",longContext:"長いコンテキスト",webSearch:"Web 検索",image:"画像",longContextThreshold:"長いコンテキストのしきい値"},helper:{longContextThreshold:"長いコンテキストモデルに切り替えるトークン数。"},placeholder:{required:"必須",optional:"任意"}},agentRouter:{title:"Agent ルーター",description:"チャットモードとコードモード間の双方向ルーティングを設定します。",searchPlaceholder:"ルーターを検索...",noSearchResults:"検索条件に一致するルーターがありません。",tabs:{chatToCode:"チャット → コード",codeToChatPlaceholder:"コード → チャット"},chatToCode:{title:"チャット → コード ルーター",description:"Agent/コーディングモードでチャットプロバイダーを使用します",addRouter:"ルーターを追加",emptyState:"チャット→コードルーターが設定されていません。コーディングモードでチャットプロバイダーを使用するには追加してください。",form:{name:"ルーター名",namePlaceholder:"マイ チャット→コード ルーター",chatProvider:"チャットプロバイダー",chatProviderPlaceholder:"チャットプロバイダーを選択",mode:"モード",modeSimple:"シンプル",modeAdvanced:"詳細",modeSimpleDesc:"チャットプロバイダーに直接パススルー",modeAdvancedDesc:"モデルマッピングとコンテキスト処理を設定",enabled:"有効",save:"ルーターを保存",cancel:"キャンセル"},list:{provider:"プロバイダー",mode:"モード",status:"ステータス"},mappings:{title:"モデルマッピング",description:"チャットプロバイダーのモデルをコードプロバイダーのモデルにマッピングします",count:"件のマッピング",empty:"モデルマッピングが設定されていません。チャットモデルをコードプロバイダーにルーティングするにはマッピングを追加してください。",addNew:"マッピングを追加",selectSource:"ソースモデルを選択(チャット)",selectTarget:"ターゲットモデルを選択(コード)",targetPlaceholder:"Claude Code モデル名を入力",notSet:"(未設定 - クリックして選択)",add:"追加",edit:"編集",done:"完了"},advanced:{title:"詳細設定",description:"タスクタイプごとにモデルを設定します",helpText:"デフォルトモデルは必須です。その他のモデルは任意で、設定しない場合はデフォルトにフォールバックします。",default:{label:"デフォルト",placeholder:"デフォルトモデルを選択",description:"一般タスク向けの主要モデル(Claude Sonnet 相当)"},background:{label:"バックグラウンド",placeholder:"バックグラウンドモデルを選択",description:"バックグラウンドタスク向けの軽量モデル(Claude Haiku 相当)"},think:{label:"思考",placeholder:"思考モデルを選択",description:"複雑な推論向けの高度なモデル(Claude Opus 相当)"},image:{label:"画像",placeholder:"画像モデルを選択",description:"ビジョン機能を持つ画像関連タスク向けモデル"}}},codeToChat:{title:"コード → チャット ルーター",description:"チャットモードで Coding Plan モデルを公開します",addRouter:"ルーターを追加",emptyState:"コード→チャットルーターが設定されていません。チャットモードで Coding Plan モデルを公開するには追加してください。",form:{name:"ルーター名",namePlaceholder:"マイ コード→チャット ルーター",codeProvider:"コードプロバイダー",codeProviderPlaceholder:"コードプロバイダーを選択",codeProviderHelper:"変換に使用するコードプロバイダーを選択",models:"Coding Plan モデル",modelsHelper:"公開する Coding Plan モデルを選択",enabled:"有効",save:"ルーターを保存",cancel:"キャンセル"},mappings:{title:"モデルマッピング",description:"コードプロバイダーのモデルをチャットプロバイダーのモデルにマッピングして公開します",count:"件のマッピング",empty:"モデルマッピングが設定されていません。チャットモードでコードモデルを公開するにはマッピングを追加してください。",addNew:"マッピングを追加",selectSource:"ソースモデルを選択(コード)",selectTarget:"ターゲットモデルを選択(チャット)",sourcePlaceholder:"ソースモデル名を入力",targetPlaceholder:"ターゲットモデル名を入力",add:"追加",edit:"編集",done:"完了"}},transformers:{title:"トランスフォーマー",description:"リクエスト/レスポンス変換用のトランスフォーマーを設定します",noProvider:"トランスフォーマーを設定するにはプロバイダーを選択してください",empty:"トランスフォーマーがありません",count:"{{count}} 件のトランスフォーマー"},status:{enabled:"有効",disabled:"無効"},messages:{routerAdded:"ルーターを追加しました",routerUpdated:"ルーターを更新しました",routerDeleted:"ルーターを削除しました",saveFailed:"ルーターの保存に失敗しました"}},presets:{title:"プロバイダーをすぐに追加",added:"追加済み",add:"追加",features:{search:"検索",vision:"ビジョン",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"このプロバイダーを削除してもよいですか?"},errors:{nameRequired:"プロバイダー名は必須です",urlRequired:"API ベース URL は必須です",urlInvalid:"有効な URL を入力してください(例: https://api.example.com)",saveFailed:"プロバイダーの保存に失敗しました",deleteFailed:"プロバイダーの削除に失敗しました。もう一度お試しください。",toggleFailed:"プロバイダーの切り替えに失敗しました。もう一度お試しください。"},openRouter:{title:"OpenRouter プロバイダールーティング",description:"OpenRouter でのリクエストのプロバイダーへのルーティング方法を設定します。",sort:"ルーティング戦略",sortTooltip:"プロバイダーの優先順位を選択します。自動はインテリジェントな負荷分散を使用します。",order:"プロバイダー優先順位",orderTooltip:"試行するプロバイダーの順序を指定します(例: anthropic、openai、together)。Enter キーで追加します。",orderPlaceholder:"プロバイダーのスラッグを入力して Enter...",allowFallbacks:"フォールバックを許可",allowFallbacksTooltip:"有効にすると、プライマリが利用できない場合に OpenRouter がバックアッププロバイダーを試みます。",requireParameters:"すべてのパラメーターを要求",requireParametersTooltip:"リクエスト内のすべてのパラメーターをサポートするプロバイダーにのみルーティングします。",dataCollection:"データ収集ポリシー",dataCollectionTooltip:"データを保存またはトレーニングに使用する可能性のあるプロバイダーを使用するかどうかを制御します。",zdr:"ゼロデータ保持",zdrTooltip:"ゼロデータ保持ポリシーのエンドポイントにのみルーティングします。",only:"許可するプロバイダーのみ",onlyTooltip:"これらの特定のプロバイダーのみを使用します。空欄にするとすべてのプロバイダーを許可します。",onlyPlaceholder:"プロバイダーのスラッグを入力して Enter...",ignore:"除外するプロバイダー",ignoreTooltip:"リクエストのルーティング時にこれらのプロバイダーをスキップします。",ignorePlaceholder:"プロバイダーのスラッグを入力して Enter...",quantizations:"量子化フィルター",quantizationsTooltip:"特定の量子化レベルのプロバイダーのみを使用します。精度が低いと品質が下がる場合がありますが、速度が向上します。",maxPrice:"最高価格",maxPriceTooltip:"100 万トークンあたりの最高価格制限を設定します。制限なしの場合は空欄にしてください。",configured:"設定済み"}},qz={label:"API モード",standard:"スタンダード",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"このプランのキーは通常 `{{prefix}}` で始まります。参考情報のみで、強制ではありません。",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan はスタンダードエンドポイントとは別の API キーを使用します。",baiduCodingPlanSeparateKey:"Qianfan Coding Plan はスタンダードエンドポイントとは別の API キーを使用します。",tencentTokenPlanAnthropicOnly:"Tencent Token Plan は Anthropic プロトコルのみ対応しています。",xiaomiTokenPlanRegions:"デフォルトの baseUrl は `token-plan-cn.*` です。`token-plan-sgp.*` または `token-plan-ams.*` に手動で変更することもできます。",confirmOverwriteTitle:"API モードを切り替えますか?",confirmOverwriteBody:"API URL または API キーをカスタマイズしています。モードを切り替えると新しいモードのデフォルト値で上書きされるか、カスタマイズを維持してモードラベルのみ更新されます。",overwriteAndSwitch:"上書きして切り替え",keepCustomizations:"カスタマイズを維持"},$z={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},_z={cancel:"キャンセル",close:"閉じる",copy:"コピー",delete:"削除",dismiss:"閉じる",save:"保存",optional:"任意",retry:"再試行",loading:"読み込み中…"},Gz={common:{learnMore:"ドキュメント"}},Wz={notSupportedByDaemon:"デーモンではまだサポートされていません",discoveryUnsupportedFormat:"このプロバイダー形式ではモデルの自動検出がサポートされていません。モデルを手動で追加してください。"},Zz={subtitle:"コントロールパネル",providers:"プロバイダー",apiService:"API サービス",accounts:"アカウント",codeCli:"Code CLI",settings:"設定",usageStats:"使用状況",pricing:"料金"},Qz={title:"API サービス",description:"アウトバウンド API サーバー、エンドポイントごとのモデルルーティング、および名前付きアクセスキーを設定します。",loading:"サーバー設定を読み込み中…",loadError:"サーバー設定を読み込めませんでした。デーモンに到達できるか確認してください。",enable:{label:"アウトバウンドサーバーを有効化",description:"外部の呼び出し元からのリクエストをプロバイダー経由でルーティングするローカル API サーバーを起動します。"},networkBinding:{label:"LAN アクセスを許可",description:"サーバーをループバックのみでなくネットワークインターフェイスにバインドします。",warning:"LAN アクセスを有効にすると、API サーバーがネットワーク上の他のデバイスにさらされます。サブスクリプションルーティングと組み合わせると、リクエストがサブスクリプションのクォータを消費する可能性があります — ネットワークを信頼できない場合はオフのままにしてください。"},status:{running:"サーバー稼働中",stopped:"サーバー停止中",runningHint:"アウトバウンド API サーバーがリクエストを受け付けています。",stoppedHint:"サーバーを有効にするとリクエストの受け付けが始まります。",port:"ポート {{port}}",loopback:"ループバック URL",lan:"LAN URL"},endpoints:{title:"エンドポイントルーティング",description:"各ワイヤー形式がルーティングするモデルを選択します。デフォルトモデルはここに組み込まれています — このサーバーはルーターであり、チャットアプリではありません。"},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"デフォルトモデル",backgroundModel:"バックグラウンドモデル",visionModel:"ビジョンモデル",noVisionModel:"なし",backgroundModelIds:"バックグラウンドモデル ID",backgroundModelIdsPlaceholder:"カンマ区切りのモデル ID",modelPlaceholder:"モデルを選択…",useSubscription:"サブスクリプションを使用",subscriptionUnsupported:"このエンドポイントではサブスクリプションルーティングを利用できません。"},keys:{title:"アクセスキー",description:"外部の呼び出し元が Bearer トークンとして送信する名前付きキーです。完全なキーは作成時に一度だけ表示されます。",namePlaceholder:"キー名(例: my-cli)",create:"キーを作成",empty:"アクセスキーがまだありません。",enabled:"有効",disabled:"無効",revoked:"失効済み",toggle:"キーを切り替え",revoke:"失効",revokeConfirmTitle:"このキーを失効させますか?",revokeConfirmDesc:"「{{name}}」を失効させると、すぐに認証に使用できなくなります。この操作は元に戻せません。",created:{title:"キーを作成しました",warning:"このキーを今すぐコピーしてください — 再表示されません。安全な場所に保管してください。",copy:"コピー",copied:"コピーしました",dismiss:"完了"}}},Yz={title:"アカウントとサブスクリプション",description:"サーバーがルーティングに使用するサブスクリプション認証情報を管理します。トークンはここに書き込まれますが、表示されることはありません。",loading:"アカウントを読み込み中…",empty:"利用可能なサブスクリプションプロバイダーがありません。",signIn:"サインイン",oauth:{title:"{{name}} にサインイン",description:"ブラウザでサインインページを開いて認証し、認証コードを以下に貼り付けてください。コードはデーモンにのみ送信されます — 発行されたトークンは表示されません。",openPage:"サインインページを開く",codeLabel:"認証コード",codePlaceholder:"ここにコードを貼り付け",submit:"サインインを完了"},codexOauth:{title:"{{name}} にサインイン",description:"ブラウザでサインインページを開いて認証してください。デーモンが自動的に結果を取得します — 完了するまでこのページを開いたままにしてください。トークンは表示されません。",waiting:"ブラウザでのサインインが完了するのを待っています…",failed:"サインインに失敗しました。もう一度お試しください。"},clearProvider:"すべてクリア",clearConfirmTitle:"{{name}} のアカウントをクリアしますか?",clearConfirmDesc:"このプロバイダーに保存されているすべての認証情報が削除されます。この操作は元に戻せません。",credential:{ok:"設定済み",notConfigured:"未設定"},kind:{"pass-through":"パススルー認証情報","oauth-bearer":"OAuth Bearer","static-bearer":"静的 Bearer キー"},reason:{"missing-credential":"認証情報が保存されていません。",expired:"認証情報が期限切れです。","reauth-required":"再認証が必要です。","refresh-failed":"トークンの更新に失敗しました。","not-refreshable":"認証情報は更新できません。",unknown:"状態が不明です。"},status:{unconfigured:"未設定",authorized:"認証済み",configured:"設定済み",expired:"期限切れ",error:"エラー"},authMethod:{oauth:"OAuth",setup_token:"セットアップトークン",manual:"手動"},list:{empty:"このプロバイダーにはアカウントが保存されていません。",active:"アクティブ",expiresAt:"{{value}} に期限切れ",setActive:"アクティブに設定",remove:"削除",removeConfirmTitle:"このアカウントを削除しますか?",removeConfirmDesc:"「{{name}}」を削除すると、保存された認証情報が削除されます。この操作は元に戻せません。",title:"アカウント"},write:{trigger:"認証情報を追加",title:"{{name}} の認証情報を書き込む",description:"取得済みのトークンを貼り付けてください。フィールドはこのプロバイダーが受け付ける内容に限定されています。トークンは保存され、表示されることはありません。",authMethod:"認証方法",status:"ステータス",subscriptionLevel:"サブスクリプションレベル",subscriptionLevelNone:"未設定",submit:"認証情報を保存"},field:{accessToken:"アクセストークン",refreshToken:"リフレッシュトークン",idToken:"ID トークン",apiKey:"API キー",expiresAt:"有効期限(ISO)",setupTokenExpiresAt:"セットアップトークンの有効期限(ISO)",accountId:"アカウント ID",email:"メールアドレス",organizationId:"組織 ID",baseUrl:"ベース URL",zenBaseUrl:"Zen ベース URL"},provider:{claude:{title:"Claude",description:"デーモンによってルーティングされる Anthropic サブスクリプション認証情報。"},codex:{title:"Codex",description:"デーモンによってルーティングされる OpenAI Codex サブスクリプション認証情報。"},gemini:{title:"Gemini",description:"デーモンによってルーティングされる Google Gemini サブスクリプション認証情報。"},opencodego:{title:"OpenCodeGo",description:"デーモンによってルーティングされる静的 API キー認証情報。"}},authMethodLabel:"認証方法",authMethodDesc:{oauth:"ブラウザからサインイン。デーモンがトークンを取得して保存します。",manual:"取得済みのトークンを貼り付けます。保存され、表示されることはありません。"},actions:{authorize:"認証",enterToken:"トークンを入力",refresh:"更新"},accounts:{addAccount:"アカウントを追加"},detail:{authMethod:"認証方法",subscriptionLevel:"サブスクリプションレベル",expiresAt:"有効期限",lastRefreshed:"最終更新",label:"アカウントラベル",labelPlaceholder:"アカウント名を入力",saveLabel:"ラベルを保存"},oauthFlow:{step1:{title:"認証ページを開く",desc:"ブラウザでサインインページを開いてください。"},step2:{title:"アクセスを認証",desc:"サインインしてプロバイダーへのアクセスを承認してください。"},step3:{title:"認証コードをコピー",desc:"承認後、ページに認証コードが表示されます。"},step4:{title:"コードを貼り付け",desc:"認証コードを以下に貼り付けて完了してください。コードはデーモンにのみ送信されます — 発行されたトークンは表示されません。"},authorize:"サインインを完了",showUrl:"認証 URL を表示"},manual:{title:"認証情報を貼り付け",description:"取得済みのトークンを貼り付けてください。フィールドはこのプロバイダーが受け付ける内容に限定されています。トークンは保存され、表示されることはありません。",accessTokenPlaceholder:"アクセストークンを貼り付け",refreshTokenPlaceholder:"リフレッシュトークンを貼り付け(任意)",hint:"トークンはデーモンに送信されて暗号化して保存されます。表示されることはありません。"},openCodeGo:{apiKeyRequired:"API キーが必要です。",apiKeyPlaceholder:"API キーを貼り付け",baseUrlPlaceholder:"https://…(任意)",zenBaseUrlPlaceholder:"https://…(任意)"},info:{title:"サブスクリプションアカウントについて",description:"トークンはデーモンに書き込まれ、上流リクエストの認証に使用されます。暗号化されて保存され、表示されることはありません。アカウントを削除すると、保存された認証情報が削除されます。"},rename:{failed:"アカウント名を変更できませんでした。"},refresh:{failed:"トークンを更新できませんでした。"},errors:{requestFailed:"リクエストに失敗しました。もう一度お試しください。"},syncWarning:{"external-divergent":"外部 CLI のログインファイルには、このアカウントより新しい資格情報があります。保存済みトークンは更新できなくなる可能性があります。今すぐ更新するか、再ログインしてください。","external-not-rotated":"更新に失敗し、外部 CLI にも同じ期限切れの資格情報しかありません。再ログインしてください。","duplicate-token":"別のアカウントがこの資格情報を共有しています。どちらかを更新すると、もう一方が無効になります。"},importExternal:{detected:"このマシンに既存の {{name}} CLI ログインが見つかりました。",hint:"インポート後は本アプリが更新を管理します。トークンを更新するたびに CLI のログインファイルも更新され、ターミナルの CLI はログイン状態を維持します。",button:"既存の CLI ログインをインポート"}},Xz={title:"Code CLI",description:"コーディング CLI をデーモンのアウトバウンドプロキシに向けます。このページは読み取り専用です — ここでは設定するものはありません。",copy:"コピー",copied:"コピーしました",baseUrl:{title:"デーモンベース URL",description:"CLI が接続するプロキシアドレス。",label:"ベース URL"},token:{title:"認証",hint:"管理ルートには 'Authorization: Bearer <管理トークン>' を送信してください。管理トークンはデーモン(設定ファイルまたは環境変数)で設定されています — ここには表示されません。"},examples:{title:"起動環境の例",keyNote:"API サービスページで作成したアウトバウンドアクセスキーを使用してください — 管理トークンではありません。",anthropic:"Anthropic 形式 CLI",openai:"OpenAI 形式 CLI"},launchDescription:"ターミナルでコーディング CLI を起動し、このデーモンに向けます。デーモンがリダイレクト環境変数を注入し、CLI を起動します。",refresh:"更新",loading:"CLI を検出中…",cli:{installed:"インストール済み",notFound:"見つかりません",notFoundHint:"この CLI はデーモンホストの PATH にありません。インストールしてから更新してください。",install:"インストール",installing:"インストール中…",installingHint:"デーモンホストにインストール中です — しばらく時間がかかる場合があります。",launch:"起動",launchTitle:"{{name}} を起動",launchDescription:"デーモンホストで新しいターミナルを開き、この CLI をデーモンプロキシ経由で実行します。作業ディレクトリを任意で指定できます。",cwdLabel:"作業ディレクトリ",cwdPlaceholder:"/path/to/your/project",runningVia:"実行中 · {{provider}} / {{model}}",stop:"停止"},manual:{title:"手動セットアップ",description:"CLI を自分で実行する場合は、これらの環境変数を使ってデーモンに向けてください。",show:"表示",hide:"非表示"}},Jz={probing:"デーモンを確認中…",spawning:"デーモンを起動中…",failed:"デーモンを起動できませんでした",failedHint:"Node.js がインストールされてデーモンがビルドされているか(dist が存在するか)を確認してください。または OMNICROSS_DAEMON_ENTRY にデーモンの cli.js のパスを設定してください。"},eI={title:"設定",description:"デスクトップアプリの環境設定。",desktopOnly:"起動時とトレイのオプションはデスクトップアプリでのみ適用されます。",startup:{title:"起動",autoLaunch:"ログイン時に起動",autoLaunchHint:"サインイン時に Omnicross を自動的に起動します。",startMinimized:"トレイに最小化して起動",startMinimizedHint:"ウィンドウを開かずにバックグラウンドで起動します。"},tray:{title:"トレイ",minimizeOnClose:"閉じるときにトレイに最小化",minimizeOnCloseHint:"ウィンドウを閉じると、終了せずにトレイに隠れます。"},language:{title:"言語",label:"インターフェイス言語"}},tI={title:"使用状況の統計",description:"デーモンが処理したリクエストのトークンとコストの統計。",rangeToday:"今日",range7d:"過去 7 日間",range30d:"過去 30 日間",rangeCustom:"カスタム",from:"開始",to:"終了",totalCost:"合計コスト",cacheSavings:"キャッシュ節約額",events:"リクエスト数",inputTokens:"入力トークン",outputTokens:"出力トークン",cacheReadTokens:"キャッシュ読み取り",cacheWriteTokens:"キャッシュ書き込み",reasoningTokens:"推論トークン",byModel:"モデル別",byApiKey:"API キー別",provider:"プロバイダー",model:"モデル",cost:"コスト",apiKey:"API キー",unpriced:"価格未設定",unpricedHint:"このモデルの料金エントリがありません。「料金」ページで追加してください。",unattributed:"未割り当て",unattributedHint:"特定の API キーに紐付いていないリクエストです。キー単位の記録が有効になるまでは正常な状態です。",empty:"この期間にリクエストはありません。",invalidRange:"有効な日付範囲を選択してください。"},aI={title:"モデル料金",description:"リクエストコストの計算に使うモデル別トークン価格(100 万トークンあたり米ドル)。",search:"プロバイダーまたはモデルを検索…",fetchLatest:"最新を取得",fetching:"取得中…",addEntry:"エントリを追加",provider:"プロバイダー",model:"モデル",inputPrice:"入力",outputPrice:"出力",cacheReadPrice:"キャッシュ読み取り",cacheWritePrice:"キャッシュ書き込み",source:"ソース",updated:"更新日時",userEdited:"編集済み",edit:"編集",deleteTitle:"この料金エントリを削除しますか?",empty:"料金テーブルは空です。",emptyHint:"最新の価格を取得して表を埋めてください。",noMatches:"検索に一致するエントリがありません。",saved:"料金エントリを保存しました。",saveFailed:"保存に失敗しました:{{message}}",deleteFailed:"削除に失敗しました:{{message}}",alreadyDeleted:"このエントリは既に存在しません。",fetchApplied:"ソースから {{count}} 件のエントリを更新しました。",fetchFailed:"取得に失敗しました:{{message}}",requiredId:"必須",invalidPrice:"0 以上の数値を入力してください",conflictTitle:"料金の競合を解決",conflictHint:"これらのエントリはあなたが編集しており、ソース側でも変更されています。行ごとに自分の値を保持(スキップ)するか、ソースの値を採用(上書き)するかを選択してください。",current:"現在",incoming:"ソース値",overwrite:"上書き",skip:"スキップ",overwriteAll:"すべて上書き",skipAll:"すべてスキップ",applyResolutions:"適用",resolved:"{{overwritten}} 件を上書き、{{skipped}} 件をスキップしました。",resolvedWithStale:"{{overwritten}} 件を上書き、{{skipped}} 件をスキップしました。{{stale}} 件はその間に変更されたため、そのまま残しています。",refreshFailed:"変更は適用されましたが、リストの再読み込みに失敗しました:{{message}}",sourceBuiltin:"組み込み",sourceLitellm:"LiteLLM",sourceUser:"ユーザー"},nI={providerSettings:Vz,apiMode:qz,presetName:$z,common:_z,mediaSettings:Gz,appLocal:Wz,nav:Zz,apiService:Qz,accounts:Yz,codeCli:Xz,daemonStatus:Jz,settings:eI,usageStats:tI,pricing:aI},oI={loading:"LLM 설정을 불러오는 중...",reset:{button:"기본값 복원",confirmTitle:"기본 설정으로 복원하시겠습니까?",confirmBody:"이 프로바이더에 대한 사용자 지정 설정이 삭제되고 기본값으로 돌아갑니다. API 키와 저장된 세션은 유지됩니다.",confirmButton:"기본값 복원"},reentryBanner:{message:"활성화된 프로바이더 {{count}}개에 API 키를 다시 입력해야 합니다. 각 프로바이더를 열고 키를 다시 입력하세요."},migrationPack:{barHint:"암호화된 팩을 사용하여 프로바이더 키와 구독 토큰을 다른 기기로 이전합니다.",passphrase:"암호",passphrasePlaceholder:"암호를 입력하세요",passphraseHint:"8자 이상을 사용하세요. 12자 이상을 권장합니다.",confirm:"암호 확인",confirmPlaceholder:"암호를 다시 입력하세요",mismatch:"암호가 일치하지 않습니다.",strength:{weak:"너무 짧습니다 — 8자 이상을 사용하세요.",fair:"적절합니다 — 12자 이상이면 더 안전합니다.",strong:"강력한 암호입니다."},export:{button:"팩 내보내기",title:"암호화된 팩 내보내기",subtitle:"프로바이더 키와 구독 토큰을 이식 가능한 파일로 암호화합니다.",warning:"이 파일에는 복호화 가능한 비밀 정보가 포함되어 있습니다. 안전하게 보관하세요 — 파일과 암호를 모두 가진 사람은 키를 읽을 수 있습니다. 암호를 분실하면 복구할 수 없습니다.",submit:"내보내기",success:"팩을 성공적으로 내보냈습니다.",error:"내보내기에 실패했습니다. 다시 시도하세요."},import:{button:"팩 가져오기",title:"암호화된 팩 가져오기",subtitle:"내보낸 팩에서 프로바이더 키와 구독 토큰을 복원합니다.",hint:"팩을 내보낼 때 사용한 암호를 입력한 후 파일을 선택하세요.",submit:"가져오기",successTitle:"가져오기 완료",summary:"프로바이더 키 {{providerKeys}}개, 풀 키 {{poolKeys}}개, 토큰 세트 {{tokenSets}}개를 가져왔습니다.",duplicates:"이미 존재하는 풀 키 {{count}}개를 건너뛰었습니다.",skipped:"건너뜀 (일치하는 프로바이더 없음): {{names}}",error:"암호가 틀렸거나 팩이 손상되었습니다. 변경된 내용이 없습니다."}},searchPlaceholder:"프로바이더 검색...",emptySearch:"검색 조건에 맞는 프로바이더가 없습니다.",emptyList:"설정된 프로바이더가 없습니다.",selectPrompt:"프로바이더를 선택하여 세부 정보를 확인하세요",listStatus:"모델 {{count}}개",noModels:"설정된 모델이 없습니다",enabled:"활성화",disabled:"비활성화",showEnabledOnly:"활성화된 항목만 표시",showAll:"모든 프로바이더 표시",dragHandle:"드래그하여 순서 변경",reorderFailed:"프로바이더 순서 저장에 실패했습니다",credentials:{apiKey:"API 키",apiBaseUrl:"API 기본 URL"},filter:{all:"전체",chat:"채팅",code:"코드"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"템플릿 선택",skipTemplates:"건너뛰고 직접 설정",name:"이름 *",providerType:"유형",apiType:"API 유형",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"표준 OpenAI chat/completions API 형식",claudecode:"Anthropic Messages API 형식 (Claude Code)"},chatApiFormat:"API 형식",chatApiFormatDescription:"프로바이더 엔드포인트에 맞는 API 형식을 선택하세요",apiKey:"API 키",apiKeyPlaceholder:"sk-... 또는 $ENV_VAR",apiKeyHelper:"$VAR_NAME을 사용하여 환경 변수를 참조할 수 있습니다",apiKeySetPlaceholder:"키가 설정되어 있습니다 — 변경하지 않으려면 빈칸으로 두세요",apiKeyReplaceHelper:"키가 안전하게 저장되어 있습니다. 새 값을 입력하면 교체됩니다. 빈칸으로 두면 변경되지 않습니다.",testApiKey:"API 키 테스트",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"미리보기:",models:"모델",modelPlaceholder:"모델 이름 (예: gpt-4, claude-3-opus)",transformers:"트랜스포머",transformerConfig:"API 트랜스포머",transformerConfigDescription:"이 프로바이더의 API 요청/응답 형식을 변환하는 트랜스포머를 설정합니다",transformerConfigNote:"데몬은 요청 체인에서 프로바이더의 형식 트랜스포머(wire 형식 변환 담당) 이후에 이 트랜스포머들을 적용합니다. 알 수 없는 트랜스포머 이름은 건너뜁니다.",enabled:"활성화",apiVersion:"API 버전",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API 버전 (예: 2024-08-01-preview)",official:"Anthropic 공식 API",officialHelper:"이 프로바이더가 Anthropic 공식 API에 직접 연결하는 경우 활성화하세요. 리버스 프록시나 서드파티 서비스의 경우 비활성화하세요.",maxConcurrency:"최대 동시 요청 수",maxConcurrencyHelper:"이 프로바이더로 전송하는 최대 동시 API 요청 수입니다. 값을 낮추면 속도 제한(429 오류)을 방지하는 데 도움이 됩니다. `-1`로 설정하면 제한이 없습니다.",codingPlan:{label:"Coding Plan",description:"구독 기반 Coding Plan에 별도의 API 엔드포인트를 사용합니다",baseUrl:"Coding Plan 기본 URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API 키 (선택 사항)",apiKeyPlaceholder:"비워두면 프로바이더의 API 키를 사용합니다",apiKeyHelper:"Coding Plan이 다른 API 키를 사용하는 경우에만 필요합니다",tokenPlanHint:"일부 프로바이더(예: Xiaomi MiMo)는 `tp-` 접두사를 가진 Token Plan 키를 발급합니다 — 참고 정보이며 강제 적용되지 않습니다."},selectTypeFirst:"프로바이더 유형 선택",selectTypeFirstDesc:"추가할 프로바이더 유형을 선택하세요",codeProviderNote:"코드 프로바이더는 API 키와 URL만 필요합니다. 모델은 Agent Router가 관리합니다.",buttons:{cancel:"취소",submitAdd:"프로바이더 추가",submitUpdate:"프로바이더 업데이트",continue:"계속",back:"뒤로"}},details:{noSelection:"프로바이더를 선택하여 세부 정보를 확인하세요",apiKey:"API 키",apiUrl:"API URL",nameLabel:"프로바이더 이름",modelsEndpoint:"모델 엔드포인트",modelsEndpointHelper:"프로바이더가 커스텀 /models 경로를 제공하는 경우 여기서 재정의할 수 있습니다.",models:"모델",transformers:"트랜스포머",codeProviderNote:"코드 프로바이더(Claude Code 등)는 모델 설정이 필요 없습니다. 모델은 Agent Router가 자동으로 관리합니다.",buttons:{more:"추가 설정",delete:"삭제"}},providerModelSelector:{placeholder:"프로바이더와 모델 선택",noProviders:"사용 가능한 프로바이더가 없습니다",noModels:"설정된 모델이 없습니다"},apiKeyPool:{title:"API 키 풀",description:"로드 밸런싱을 위해 여러 API 키를 설정합니다. 프롬프트 캐시를 유지하기 위해 각 세션은 하나의 키에 고정됩니다.",defaultLabel:"기본",weight:"가중치",noKey:"키 없음",labelPlaceholder:"레이블 (예: 키 #1, 프로덕션)",addKey:"API 키 추가",add:"추가",empty:"추가 키가 설정되어 있지 않습니다.",statusCoolingDown:"쿨다운 중 {{time}}",statusAuthFailed:"인증 실패 · 비활성화됨",statusDisabled:"비활성화됨",statusHealthy:"정상",agoSeconds:"{{count}}초 전",agoMinutes:"{{count}}분 전",agoHours:"{{count}}시간 전",agoDays:"{{count}}일 전"},modelsManager:{searchPlaceholder:"모델 검색...",defaultGroup:"전체 모델",add:"모델 추가",manage:"관리",empty:"이 그룹에 모델이 없습니다",enabled:"활성화",disabled:"비활성화",filters:{all:"전체",vision:"비전",reasoning:"추론",free:"무료",tools:"도구"},manualDialog:{title:"모델 추가",subtitle:"이 프로바이더에 커스텀 모델을 추가합니다",modelId:"모델 ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash 등",modelIdHelper:"API 호출 시 사용하는 정확한 모델 식별자",modelName:"표시 이름",modelNamePlaceholder:"친숙한 표시 이름 (선택 사항)",modelNameHelper:"UI에 표시되는 이름입니다. 비워두면 모델 ID가 사용됩니다",group:"그룹",groupPlaceholder:"그룹 이름을 선택하거나 입력하세요",submit:"추가",cancel:"취소",helper:"프로바이더 API에서 제공하는 정확한 모델 식별자를 입력하세요."},editDialog:{title:"모델 편집",subtitle:"모델 설정 수정",modelId:"모델 ID",modelIdPlaceholder:"모델 식별자",modelIdHelper:"API 호출 시 사용하는 모델 식별자",modelName:"표시 이름",modelNamePlaceholder:"친숙한 표시 이름",modelNameHelper:"UI에 표시되는 이름",group:"그룹",groupPlaceholder:"그룹 이름을 선택하거나 입력하세요",submit:"저장",cancel:"취소",vision:"비전 기능",visionHint:"이 모델이 이미지/비전 입력을 지원하는지 여부",reasoning:"추론 모델",reasoningHint:"이 모델이 사고/추론 모드를 지원하는지 여부"},manageDialog:{title:"모델 관리",cachedAt:"{{date}} 캐시됨 ({{source}})",refresh:"새로고침",close:"닫기",raw:"Raw JSON",empty:"사용 가능한 원격 모델이 없습니다.",error:"모델 로드에 실패했습니다: {{message}}",addFromCatalog:"추가",sourceCache:"캐시",sourceNetwork:"실시간",contextLength:"컨텍스트 {{value}} 토큰",maxTokens:"최대 {{value}} 토큰"},messages:{added:"모델이 추가되었습니다.",updated:"모델이 업데이트되었습니다.",removed:"모델이 제거되었습니다.",duplicate:"이미 존재하는 모델입니다.",refreshed:"모델이 새로고침되었습니다",refreshFailed:"모델 새로고침에 실패했습니다"},testDialog:{title:"모델 연결 테스트",provider:"프로바이더",model:"모델",testing:"테스트 중...",success:"테스트 성공",successMessage:"모델에 정상적으로 접근할 수 있습니다",failure:"테스트 실패",aiResponse:"AI 응답",charCount:"{{count}}자",duration:"소요 시간 {{time}}초",close:"닫기",retest:"다시 테스트",testButton:"모델 테스트",unsupportedFormat:"이 프로바이더 형식은 아직 테스트를 지원하지 않습니다."}},router:{title:"라우터 설정",description:"상황별로 사용할 프로바이더/모델을 설정합니다.",labels:{default:"기본",background:"백그라운드",think:"추론",longContext:"긴 컨텍스트",webSearch:"웹 검색",image:"이미지",longContextThreshold:"긴 컨텍스트 임계값"},helper:{longContextThreshold:"긴 컨텍스트 모델로 전환하기 전 토큰 수입니다."},placeholder:{required:"필수",optional:"선택 사항"}},agentRouter:{title:"Agent 라우터",description:"채팅 모드와 코드 모드 간의 양방향 라우팅을 설정합니다.",searchPlaceholder:"라우터 검색...",noSearchResults:"검색 조건에 맞는 라우터가 없습니다.",tabs:{chatToCode:"채팅 → 코드",codeToChatPlaceholder:"코드 → 채팅"},chatToCode:{title:"채팅 → 코드 라우터",description:"에이전트/코딩 모드에서 채팅 프로바이더를 사용합니다",addRouter:"라우터 추가",emptyState:"채팅→코드 라우터가 설정되어 있지 않습니다. 코딩 모드에서 채팅 프로바이더를 사용하려면 추가하세요.",form:{name:"라우터 이름",namePlaceholder:"나의 채팅→코드 라우터",chatProvider:"채팅 프로바이더",chatProviderPlaceholder:"채팅 프로바이더를 선택하세요",mode:"모드",modeSimple:"단순",modeAdvanced:"고급",modeSimpleDesc:"채팅 프로바이더로 직접 전달",modeAdvancedDesc:"모델 매핑 및 컨텍스트 처리 설정",enabled:"활성화",save:"라우터 저장",cancel:"취소"},list:{provider:"프로바이더",mode:"모드",status:"상태"},mappings:{title:"모델 매핑",description:"채팅 프로바이더 모델을 코드 프로바이더 모델에 매핑합니다",count:"개 매핑",empty:"모델 매핑이 설정되어 있지 않습니다. 채팅 모델을 코드 프로바이더에 라우팅하려면 매핑을 추가하세요.",addNew:"새 매핑 추가",selectSource:"소스 모델 선택 (채팅)",selectTarget:"대상 모델 선택 (코드)",targetPlaceholder:"Claude Code 모델 이름을 입력하세요",notSet:"(미설정 - 클릭하여 선택)",add:"추가",edit:"편집",done:"완료"},advanced:{title:"고급 설정",description:"작업 유형별로 모델을 설정합니다",helpText:"기본 모델은 필수입니다. 다른 모델은 선택 사항이며 설정하지 않으면 기본 모델로 대체됩니다.",default:{label:"기본",placeholder:"기본 모델을 선택하세요",description:"일반 작업을 위한 기본 모델 (Claude Sonnet 유사)"},background:{label:"백그라운드",placeholder:"백그라운드 모델을 선택하세요",description:"백그라운드 작업을 위한 경량 모델 (Claude Haiku 유사)"},think:{label:"추론",placeholder:"추론 모델을 선택하세요",description:"복잡한 추론을 위한 고급 모델 (Claude Opus 유사)"},image:{label:"이미지",placeholder:"이미지 모델을 선택하세요",description:"비전 기능이 있는 이미지 관련 작업 모델"}}},codeToChat:{title:"코드 → 채팅 라우터",description:"채팅 모드에서 Coding Plan 모델을 노출합니다",addRouter:"라우터 추가",emptyState:"코드→채팅 라우터가 설정되어 있지 않습니다. 채팅 모드에서 Coding Plan 모델을 노출하려면 추가하세요.",form:{name:"라우터 이름",namePlaceholder:"나의 코드→채팅 라우터",codeProvider:"코드 프로바이더",codeProviderPlaceholder:"코드 프로바이더를 선택하세요",codeProviderHelper:"변환에 사용할 코드 프로바이더를 선택하세요",models:"Coding Plan 모델",modelsHelper:"노출할 Coding Plan 모델을 선택하세요",enabled:"활성화",save:"라우터 저장",cancel:"취소"},mappings:{title:"모델 매핑",description:"코드 프로바이더 모델을 채팅 프로바이더 모델에 매핑하여 노출합니다",count:"개 매핑",empty:"모델 매핑이 설정되어 있지 않습니다. 채팅 모드에서 코드 모델을 노출하려면 매핑을 추가하세요.",addNew:"새 매핑 추가",selectSource:"소스 모델 선택 (코드)",selectTarget:"대상 모델 선택 (채팅)",sourcePlaceholder:"소스 모델 이름을 입력하세요",targetPlaceholder:"대상 모델 이름을 입력하세요",add:"추가",edit:"편집",done:"완료"}},transformers:{title:"트랜스포머",description:"요청/응답 변환을 위한 트랜스포머를 설정합니다",noProvider:"트랜스포머를 설정하려면 프로바이더를 선택하세요",empty:"트랜스포머가 없습니다",count:"{{count}}개 트랜스포머"},status:{enabled:"활성화",disabled:"비활성화"},messages:{routerAdded:"라우터가 추가되었습니다",routerUpdated:"라우터가 업데이트되었습니다",routerDeleted:"라우터가 삭제되었습니다",saveFailed:"라우터 저장에 실패했습니다"}},presets:{title:"프로바이더 빠른 추가",added:"추가됨",add:"추가",features:{search:"검색",vision:"비전",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"이 프로바이더를 삭제하시겠습니까?"},errors:{nameRequired:"프로바이더 이름은 필수입니다",urlRequired:"API 기본 URL은 필수입니다",urlInvalid:"유효한 URL을 입력하세요 (예: https://api.example.com)",saveFailed:"프로바이더 저장에 실패했습니다",deleteFailed:"프로바이더 삭제 중 오류가 발생했습니다. 다시 시도하세요.",toggleFailed:"프로바이더 전환 중 오류가 발생했습니다. 다시 시도하세요."},openRouter:{title:"OpenRouter 프로바이더 라우팅",description:"OpenRouter에서 요청을 다른 프로바이더로 라우팅하는 방법을 설정합니다.",sort:"라우팅 전략",sortTooltip:"프로바이더 우선순위를 선택합니다. 자동은 지능형 로드 밸런싱을 사용합니다.",order:"프로바이더 우선순위",orderTooltip:"시도할 프로바이더 순서를 지정합니다 (예: anthropic, openai, together). Enter 키를 눌러 추가하세요.",orderPlaceholder:"프로바이더 슬러그를 입력하고 Enter를 누르세요...",allowFallbacks:"폴백 허용",allowFallbacksTooltip:"활성화하면 기본 프로바이더를 사용할 수 없을 때 OpenRouter가 백업 프로바이더를 시도합니다.",requireParameters:"모든 매개변수 요구",requireParametersTooltip:"요청의 모든 매개변수를 지원하는 프로바이더에만 라우팅합니다.",dataCollection:"데이터 수집 정책",dataCollectionTooltip:"데이터를 저장하거나 학습에 사용할 수 있는 프로바이더 사용 여부를 제어합니다.",zdr:"제로 데이터 보존",zdrTooltip:"제로 데이터 보존 정책이 적용된 엔드포인트에만 라우팅합니다.",only:"허용할 프로바이더만",onlyTooltip:"이 특정 프로바이더만 사용합니다. 비워두면 모든 프로바이더를 허용합니다.",onlyPlaceholder:"프로바이더 슬러그를 입력하고 Enter를 누르세요...",ignore:"제외할 프로바이더",ignoreTooltip:"요청 라우팅 시 이 프로바이더들을 건너뜁니다.",ignorePlaceholder:"프로바이더 슬러그를 입력하고 Enter를 누르세요...",quantizations:"양자화 필터",quantizationsTooltip:"특정 양자화 수준의 프로바이더만 사용합니다. 정밀도가 낮으면 품질이 저하될 수 있지만 속도가 향상됩니다.",maxPrice:"최고 가격",maxPriceTooltip:"백만 토큰당 최고 가격 한도를 설정합니다. 제한 없이 사용하려면 비워두세요.",configured:"설정됨"}},iI={label:"API 모드",standard:"기본",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"이 플랜의 키는 보통 `{{prefix}}`로 시작합니다. 참고용이며 강제 적용되지 않습니다.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan은 기본 엔드포인트와 별도의 API 키를 사용합니다.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan은 기본 엔드포인트와 별도의 API 키를 사용합니다.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan은 Anthropic 프로토콜 전용입니다.",xiaomiTokenPlanRegions:"기본 baseUrl은 `token-plan-cn.*`입니다. `token-plan-sgp.*` 또는 `token-plan-ams.*`로 직접 변경할 수 있습니다.",confirmOverwriteTitle:"API 모드를 전환하시겠습니까?",confirmOverwriteBody:"API URL 또는 API 키가 사용자 지정되어 있습니다. 모드를 전환하면 새 모드의 기본값으로 덮어쓰거나, 사용자 지정은 유지하고 모드 레이블만 변경할 수 있습니다.",overwriteAndSwitch:"덮어쓰고 전환",keepCustomizations:"사용자 지정 유지"},rI={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},sI={cancel:"취소",close:"닫기",copy:"복사",delete:"삭제",dismiss:"닫기",save:"저장",optional:"선택 사항",retry:"다시 시도",loading:"불러오는 중…"},lI={common:{learnMore:"문서"}},dI={notSupportedByDaemon:"데몬에서 아직 지원하지 않습니다",discoveryUnsupportedFormat:"이 프로바이더 형식은 모델 자동 검색을 지원하지 않습니다. 모델을 직접 추가하세요."},cI={subtitle:"제어판",providers:"프로바이더",apiService:"API 서비스",accounts:"계정",codeCli:"Code CLI",settings:"설정",usageStats:"사용량",pricing:"가격"},uI={title:"API 서비스",description:"아웃바운드 API 서버, 엔드포인트별 모델 라우팅, 명명된 액세스 키를 설정합니다.",loading:"서버 설정을 불러오는 중…",loadError:"서버 설정을 불러올 수 없습니다. 데몬에 연결할 수 있는지 확인하세요.",enable:{label:"아웃바운드 서버 활성화",description:"외부 호출자의 요청을 프로바이더를 통해 라우팅하는 로컬 API 서버를 시작합니다."},networkBinding:{label:"LAN 접근 허용",description:"서버를 루프백 전용이 아닌 네트워크 인터페이스에 바인딩합니다.",warning:"LAN 접근을 허용하면 API 서버가 네트워크의 다른 기기에 노출됩니다. 구독 라우팅과 함께 사용하면 요청이 구독 할당량을 소비할 수 있습니다 — 네트워크를 신뢰할 수 없다면 비활성화 상태로 유지하세요."},status:{running:"서버 실행 중",stopped:"서버 중지됨",runningHint:"아웃바운드 API 서버가 요청을 수락하고 있습니다.",stoppedHint:"서버를 활성화하면 요청 수락이 시작됩니다.",port:"포트 {{port}}",loopback:"루프백 URL",lan:"LAN URL"},endpoints:{title:"엔드포인트 라우팅",description:"각 와이어 형식이 라우팅할 모델을 선택합니다. 기본 모델이 여기에 통합됩니다 — 이 서버는 라우터이며 채팅 앱이 아닙니다."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"기본 모델",backgroundModel:"백그라운드 모델",visionModel:"비전 모델",noVisionModel:"없음",backgroundModelIds:"백그라운드 모델 ID",backgroundModelIdsPlaceholder:"쉼표로 구분된 모델 ID",modelPlaceholder:"모델 선택…",useSubscription:"구독 사용",subscriptionUnsupported:"이 엔드포인트는 구독 라우팅을 지원하지 않습니다."},keys:{title:"액세스 키",description:"외부 호출자가 Bearer 토큰으로 전송하는 명명된 키입니다. 전체 키는 생성 시 한 번만 표시됩니다.",namePlaceholder:"키 이름 (예: my-cli)",create:"키 생성",empty:"액세스 키가 없습니다.",enabled:"활성화",disabled:"비활성화",revoked:"취소됨",toggle:"키 전환",revoke:"취소",revokeConfirmTitle:"이 키를 취소하시겠습니까?",revokeConfirmDesc:'"{{name}}"을 취소하면 즉시 인증에 사용할 수 없게 됩니다. 이 작업은 되돌릴 수 없습니다.',created:{title:"키가 생성되었습니다",warning:"지금 이 키를 복사하세요 — 다시 표시되지 않습니다. 안전한 곳에 보관하세요.",copy:"복사",copied:"복사됨",dismiss:"완료"}}},pI={title:"계정 및 구독",description:"서버가 라우팅에 사용하는 구독 자격 증명을 관리합니다. 토큰은 여기에 기록되지만 다시 표시되지 않습니다.",loading:"계정을 불러오는 중…",empty:"사용 가능한 구독 프로바이더가 없습니다.",signIn:"로그인",oauth:{title:"{{name}}에 로그인",description:"브라우저에서 로그인 페이지를 열고 승인한 후 인증 코드를 아래에 붙여넣으세요. 코드는 데몬에만 전달됩니다 — 발급된 토큰은 표시되지 않습니다.",openPage:"로그인 페이지 열기",codeLabel:"인증 코드",codePlaceholder:"여기에 코드를 붙여넣으세요",submit:"로그인 완료"},codexOauth:{title:"{{name}}에 로그인",description:"브라우저에서 로그인 페이지를 열고 승인하세요. 데몬이 자동으로 결과를 캡처합니다 — 완료될 때까지 이 창을 열어 두세요. 토큰은 표시되지 않습니다.",waiting:"브라우저에서 로그인이 완료되기를 기다리는 중…",failed:"로그인에 실패했습니다. 다시 시도하세요."},clearProvider:"모두 지우기",clearConfirmTitle:"{{name}} 계정을 지우시겠습니까?",clearConfirmDesc:"이 프로바이더에 저장된 모든 자격 증명이 제거됩니다. 이 작업은 되돌릴 수 없습니다.",credential:{ok:"설정됨",notConfigured:"설정되지 않음"},kind:{"pass-through":"패스스루 자격 증명","oauth-bearer":"OAuth Bearer","static-bearer":"정적 Bearer 키"},reason:{"missing-credential":"저장된 자격 증명이 없습니다.",expired:"자격 증명이 만료되었습니다.","reauth-required":"재인증이 필요합니다.","refresh-failed":"토큰 갱신에 실패했습니다.","not-refreshable":"자격 증명을 갱신할 수 없습니다.",unknown:"상태를 알 수 없습니다."},status:{unconfigured:"설정되지 않음",authorized:"승인됨",configured:"설정됨",expired:"만료됨",error:"오류"},authMethod:{oauth:"OAuth",setup_token:"설정 토큰",manual:"수동"},list:{empty:"이 프로바이더에 저장된 계정이 없습니다.",active:"활성",expiresAt:"{{value}}에 만료",setActive:"활성으로 설정",remove:"제거",removeConfirmTitle:"이 계정을 제거하시겠습니까?",removeConfirmDesc:'"{{name}}"을 제거하면 저장된 자격 증명이 삭제됩니다. 이 작업은 되돌릴 수 없습니다.',title:"계정"},write:{trigger:"자격 증명 추가",title:"{{name}} 자격 증명 저장",description:"이미 획득한 토큰을 붙여넣으세요. 필드는 이 프로바이더가 허용하는 항목으로 제한됩니다. 토큰은 저장되며 다시 표시되지 않습니다.",authMethod:"인증 방법",status:"상태",subscriptionLevel:"구독 수준",subscriptionLevelNone:"설정되지 않음",submit:"자격 증명 저장"},field:{accessToken:"액세스 토큰",refreshToken:"리프레시 토큰",idToken:"ID 토큰",apiKey:"API 키",expiresAt:"만료 시간 (ISO)",setupTokenExpiresAt:"설정 토큰 만료 시간 (ISO)",accountId:"계정 ID",email:"이메일",organizationId:"조직 ID",baseUrl:"기본 URL",zenBaseUrl:"Zen 기본 URL"},provider:{claude:{title:"Claude",description:"데몬이 라우팅하는 Anthropic 구독 자격 증명입니다."},codex:{title:"Codex",description:"데몬이 라우팅하는 OpenAI Codex 구독 자격 증명입니다."},gemini:{title:"Gemini",description:"데몬이 라우팅하는 Google Gemini 구독 자격 증명입니다."},opencodego:{title:"OpenCodeGo",description:"데몬이 라우팅하는 정적 API 키 자격 증명입니다."}},authMethodLabel:"인증 방법",authMethodDesc:{oauth:"브라우저를 통해 로그인합니다. 데몬이 토큰을 캡처하고 저장합니다.",manual:"이미 획득한 토큰을 붙여넣습니다. 저장되며 다시 표시되지 않습니다."},actions:{authorize:"승인",enterToken:"토큰 입력",refresh:"갱신"},accounts:{addAccount:"계정 추가"},detail:{authMethod:"인증 방법",subscriptionLevel:"구독 수준",expiresAt:"만료",lastRefreshed:"마지막 갱신",label:"계정 레이블",labelPlaceholder:"계정 이름 지정",saveLabel:"레이블 저장"},oauthFlow:{step1:{title:"승인 페이지 열기",desc:"브라우저에서 로그인 페이지를 여세요."},step2:{title:"접근 승인",desc:"로그인하고 프로바이더에 대한 접근을 승인하세요."},step3:{title:"인증 코드 복사",desc:"승인 후 페이지에 인증 코드가 표시됩니다."},step4:{title:"코드 붙여넣기",desc:"완료하려면 아래에 인증 코드를 붙여넣으세요. 코드는 데몬에만 전달됩니다 — 발급된 토큰은 표시되지 않습니다."},authorize:"로그인 완료",showUrl:"승인 URL 표시"},manual:{title:"자격 증명 붙여넣기",description:"이미 획득한 토큰을 붙여넣으세요. 필드는 이 프로바이더가 허용하는 항목으로 제한됩니다. 토큰은 저장되며 다시 표시되지 않습니다.",accessTokenPlaceholder:"액세스 토큰을 붙여넣으세요",refreshTokenPlaceholder:"리프레시 토큰을 붙여넣으세요 (선택 사항)",hint:"토큰은 데몬으로 전송되어 암호화하여 저장됩니다. 다시 표시되지 않습니다."},openCodeGo:{apiKeyRequired:"API 키가 필요합니다.",apiKeyPlaceholder:"API 키를 붙여넣으세요",baseUrlPlaceholder:"https://… (선택 사항)",zenBaseUrlPlaceholder:"https://… (선택 사항)"},info:{title:"구독 계정 정보",description:"토큰은 데몬에 기록되어 업스트림 요청 인증에 사용됩니다. 암호화되어 저장되며 다시 표시되지 않습니다. 계정을 제거하면 저장된 자격 증명이 삭제됩니다."},rename:{failed:"계정 이름을 변경할 수 없습니다."},refresh:{failed:"토큰을 갱신할 수 없습니다."},errors:{requestFailed:"요청에 실패했습니다. 다시 시도하세요."},syncWarning:{"external-divergent":"외부 CLI 로그인 파일에 이 계정보다 최신 자격 증명이 있습니다. 저장된 토큰이 더 이상 갱신되지 않을 수 있습니다. 지금 갱신하거나 다시 로그인하세요.","external-not-rotated":"갱신에 실패했으며 외부 CLI에도 동일한 만료된 자격 증명만 있습니다. 다시 로그인하세요.","duplicate-token":"다른 계정이 이 자격 증명을 공유하고 있습니다. 어느 한쪽을 갱신하면 다른 쪽이 무효화됩니다."},importExternal:{detected:"이 컴퓨터에서 기존 {{name}} CLI 로그인을 발견했습니다.",hint:"가져온 후에는 이 앱이 갱신을 관리합니다. 토큰을 갱신할 때마다 CLI 로그인 파일도 함께 업데이트되어 터미널의 CLI가 로그인 상태를 유지합니다.",button:"기존 CLI 로그인 가져오기"}},mI={title:"Code CLI",description:"코딩 CLI를 데몬의 아웃바운드 프록시에 연결합니다. 이 페이지는 읽기 전용입니다 — 여기서 설정할 내용이 없습니다.",copy:"복사",copied:"복사됨",baseUrl:{title:"데몬 기본 URL",description:"CLI가 연결하는 프록시 주소입니다.",label:"기본 URL"},token:{title:"인증",hint:"관리자 경로에는 'Authorization: Bearer <관리자 토큰>'을 전송하세요. 관리자 토큰은 데몬(설정 파일 또는 환경 변수)에서 설정됩니다 — 여기서는 표시되지 않습니다."},examples:{title:"실행 환경 예시",keyNote:"API 서비스 페이지에서 생성한 아웃바운드 액세스 키를 사용하세요 — 관리자 토큰이 아닙니다.",anthropic:"Anthropic 형식 CLI",openai:"OpenAI 형식 CLI"},launchDescription:"터미널에서 코딩 CLI를 실행하고 이 데몬에 연결합니다. 데몬이 리디렉션 환경 변수를 주입하고 CLI를 시작합니다.",refresh:"새로고침",loading:"CLI 감지 중…",cli:{installed:"설치됨",notFound:"찾을 수 없음",notFoundHint:"이 CLI가 데몬 호스트의 PATH에 없습니다. 설치 후 새로고침하세요.",install:"설치",installing:"설치 중…",installingHint:"데몬 호스트에 설치 중입니다 — 잠시 시간이 걸릴 수 있습니다.",launch:"실행",launchTitle:"{{name}} 실행",launchDescription:"데몬 호스트에서 새 터미널을 열고 이 CLI를 데몬 프록시를 통해 실행합니다. 선택적으로 작업 디렉토리를 지정하세요.",cwdLabel:"작업 디렉토리",cwdPlaceholder:"/path/to/your/project",runningVia:"실행 중 · {{provider}} / {{model}}",stop:"중지"},manual:{title:"수동 설정",description:"직접 CLI를 실행하시겠습니까? 이 환경 변수를 사용하여 데몬에 연결하세요.",show:"표시",hide:"숨기기"}},gI={probing:"데몬 확인 중…",spawning:"데몬 시작 중…",failed:"데몬을 시작할 수 없습니다",failedHint:"Node.js가 설치되어 있고 데몬이 빌드되었는지(dist 존재) 확인하거나, OMNICROSS_DAEMON_ENTRY를 데몬의 cli.js 경로로 설정하세요."},hI={title:"설정",description:"데스크톱 앱 환경 설정입니다.",desktopOnly:"시작 및 트레이 옵션은 데스크톱 앱에서만 적용됩니다.",startup:{title:"시작",autoLaunch:"로그인 시 실행",autoLaunchHint:"로그인 시 Omnicross를 자동으로 시작합니다.",startMinimized:"트레이에 최소화하여 시작",startMinimizedHint:"창을 열지 않고 백그라운드에서 실행합니다."},tray:{title:"트레이",minimizeOnClose:"닫을 때 트레이로 최소화",minimizeOnCloseHint:"창을 닫으면 종료하지 않고 트레이로 숨깁니다."},language:{title:"언어",label:"인터페이스 언어"}},fI={title:"사용량 통계",description:"데몬이 처리한 요청의 토큰 및 비용 통계입니다.",rangeToday:"오늘",range7d:"최근 7일",range30d:"최근 30일",rangeCustom:"사용자 지정",from:"시작",to:"종료",totalCost:"총 비용",cacheSavings:"캐시 절감액",events:"요청 수",inputTokens:"입력 토큰",outputTokens:"출력 토큰",cacheReadTokens:"캐시 읽기",cacheWriteTokens:"캐시 쓰기",reasoningTokens:"추론 토큰",byModel:"모델별",byApiKey:"API 키별",provider:"공급자",model:"모델",cost:"비용",apiKey:"API 키",unpriced:"가격 없음",unpricedHint:"이 모델에 대한 가격 항목이 없습니다. 가격 페이지에서 추가하세요.",unattributed:"미지정",unattributedHint:"특정 API 키에 연결되지 않은 요청입니다. 키별 기록이 도입되기 전까지는 정상적인 상태입니다.",empty:"이 기간에 요청이 없습니다.",invalidRange:"유효한 날짜 범위를 선택하세요."},vI={title:"모델 가격",description:"요청 비용 계산에 사용되는 모델별 토큰 가격(100만 토큰당 USD)입니다.",search:"공급자 또는 모델 검색…",fetchLatest:"최신 가격 가져오기",fetching:"가져오는 중…",addEntry:"항목 추가",provider:"공급자",model:"모델",inputPrice:"입력",outputPrice:"출력",cacheReadPrice:"캐시 읽기",cacheWritePrice:"캐시 쓰기",source:"출처",updated:"업데이트",userEdited:"편집됨",edit:"편집",deleteTitle:"이 가격 항목을 삭제할까요?",empty:"가격 표가 비어 있습니다.",emptyHint:"최신 가격을 가져와 표를 채우세요.",noMatches:"검색과 일치하는 항목이 없습니다.",saved:"가격 항목이 저장되었습니다.",saveFailed:"저장 실패: {{message}}",deleteFailed:"삭제 실패: {{message}}",alreadyDeleted:"항목이 이미 없습니다.",fetchApplied:"출처에서 {{count}}개 항목을 업데이트했습니다.",fetchFailed:"가져오기 실패: {{message}}",requiredId:"필수",invalidPrice:"0 이상의 숫자를 입력하세요",conflictTitle:"가격 충돌 해결",conflictHint:"이 항목들은 사용자가 편집했으며 출처에서도 변경되었습니다. 행마다 내 값을 유지(건너뛰기)할지 출처 값을 적용(덮어쓰기)할지 선택하세요.",current:"현재",incoming:"수신 값",overwrite:"덮어쓰기",skip:"건너뛰기",overwriteAll:"모두 덮어쓰기",skipAll:"모두 건너뛰기",applyResolutions:"적용",resolved:"{{overwritten}}개 덮어씀, {{skipped}}개 건너뜀.",resolvedWithStale:"{{overwritten}}개 덮어씀, {{skipped}}개 건너뜀. {{stale}}개는 그 사이에 변경되어 그대로 두었습니다.",refreshFailed:"변경 사항은 적용되었지만 목록을 다시 불러오지 못했습니다: {{message}}",sourceBuiltin:"기본 제공",sourceLitellm:"LiteLLM",sourceUser:"사용자"},kI={providerSettings:oI,apiMode:iI,presetName:rI,common:sI,mediaSettings:lI,appLocal:dI,nav:cI,apiService:uI,accounts:pI,codeCli:mI,daemonStatus:gI,settings:hI,usageStats:fI,pricing:vI},yI={loading:"Memuatkan konfigurasi LLM...",reset:{button:"Pulihkan lalai",confirmTitle:"Pulihkan tetapan lalai?",confirmBody:"Ini akan mengosongkan penyesuaian anda untuk penyedia ini supaya ia mengikut lalai terbina semula. Kunci API dan sesi tersimpan anda dikekalkan.",confirmButton:"Pulihkan lalai"},reentryBanner:{message:"{{count}} penyedia yang diaktifkan perlu memasukkan semula kunci API mereka. Buka setiap satu dan tambah kuncinya semula."},migrationPack:{barHint:"Pindahkan kunci penyedia dan token langganan anda ke mesin lain dengan pack yang disulitkan.",passphrase:"Frasa laluan",passphrasePlaceholder:"Masukkan frasa laluan",passphraseHint:"Gunakan sekurang-kurangnya 8 aksara; 12 atau lebih adalah disyorkan.",confirm:"Sahkan frasa laluan",confirmPlaceholder:"Masukkan semula frasa laluan",mismatch:"Frasa laluan tidak sepadan.",strength:{weak:"Terlalu pendek — gunakan sekurang-kurangnya 8 aksara.",fair:"OK — 12 aksara atau lebih adalah lebih kuat.",strong:"Frasa laluan kuat."},export:{button:"Eksport pack",title:"Eksport pack yang disulitkan",subtitle:"Sulitkan kunci penyedia dan token langganan anda ke dalam fail mudah alih.",warning:"Fail ini mengandungi rahsia yang boleh dinyahsulit. Simpan dengan selamat — sesiapa yang mempunyai fail dan frasa laluan boleh membaca kunci anda. Frasa laluan yang hilang tidak boleh dipulihkan.",submit:"Eksport",success:"Pack berjaya dieksport.",error:"Eksport gagal. Sila cuba lagi."},import:{button:"Import pack",title:"Import pack yang disulitkan",subtitle:"Pulihkan kunci penyedia dan token langganan daripada pack yang dieksport.",hint:"Masukkan frasa laluan yang digunakan semasa pack dieksport, kemudian pilih fail.",submit:"Import",successTitle:"Import selesai",summary:"Diimport {{providerKeys}} kunci penyedia, {{poolKeys}} kunci pool, dan {{tokenSets}} set token.",duplicates:"Melangkau {{count}} kunci pool yang sudah ada.",skipped:"Dilangkau (tiada penyedia yang sepadan): {{names}}",error:"Frasa laluan salah atau pack rosak. Tiada apa yang diubah."}},searchPlaceholder:"Cari penyedia...",emptySearch:"Tiada penyedia yang sepadan dengan carian anda.",emptyList:"Tiada penyedia dikonfigurasi.",selectPrompt:"Pilih penyedia untuk melihat butiran",listStatus:"{{count}} model",noModels:"Tiada model dikonfigurasi",enabled:"Diaktifkan",disabled:"Dilumpuhkan",showEnabledOnly:"Tunjukkan yang diaktifkan sahaja",showAll:"Tunjukkan semua penyedia",dragHandle:"Seret untuk susun semula",reorderFailed:"Gagal menyimpan susunan penyedia",credentials:{apiKey:"Kunci API",apiBaseUrl:"URL Asas API"},filter:{all:"Semua",chat:"Sembang",code:"Kod"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Pilih Templat",skipTemplates:"Langkau, konfigurasikan secara manual",name:"Nama *",providerType:"Jenis",apiType:"Jenis API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Format API sembang/completions OpenAI standard",claudecode:"Format API Pesan Anthropic (Claude Code)"},chatApiFormat:"Format API",chatApiFormatDescription:"Pilih format API yang sepadan dengan endpoint penyedia anda",apiKey:"Kunci API",apiKeyPlaceholder:"sk-... atau $ENV_VAR",apiKeyHelper:"Gunakan $VAR_NAME untuk merujuk pemboleh ubah persekitaran",apiKeySetPlaceholder:"Kunci telah ditetapkan — biarkan kosong untuk mengekalkannya",apiKeyReplaceHelper:"Kunci disimpan dengan selamat. Taip nilai baharu untuk menggantikannya, atau biarkan kosong untuk mengekalkannya.",testApiKey:"Uji Kunci API",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Pratonton:",models:"Model",modelPlaceholder:"Nama model (cth., gpt-4, claude-3-opus)",transformers:"Transformer",transformerConfig:"Transformer API",transformerConfigDescription:"Konfigurasikan transformer untuk menyesuaikan format permintaan/respons API bagi penyedia ini",transformerConfigNote:"Daemon menggunakan transformer ini dalam rantai permintaan, selepas transformer format penyedia (yang mengendalikan penukaran format wayar). Nama transformer yang tidak dikenali akan dilangkau.",enabled:"Diaktifkan",apiVersion:"Versi API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versi API Azure OpenAI (cth., 2024-08-01-preview)",official:"API Anthropic Rasmi",officialHelper:"Aktifkan jika penyedia ini bersambung terus ke API Anthropic rasmi. Nyahdaya untuk proksi terbalik atau perkhidmatan pihak ketiga.",maxConcurrency:"Maks Permintaan Serentak",maxConcurrencyHelper:"Bilangan maksimum permintaan API serentak yang dihantar ke penyedia ini. Nilai yang lebih rendah membantu mengelakkan had kadar (ralat 429). Tetapkan `-1` untuk tiada had.",codingPlan:{label:"Pelan Pengekodan",description:"Gunakan endpoint API berasingan untuk pelan pengekodan berasaskan langganan",baseUrl:"URL Asas Pelan Pengekodan",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kunci API Pelan Pengekodan (pilihan)",apiKeyPlaceholder:"Biarkan kosong untuk menggunakan kunci API penyedia",apiKeyHelper:"Hanya diperlukan jika pelan pengekodan menggunakan kunci API yang berbeza",tokenPlanHint:"Sesetengah penyedia (cth. Xiaomi MiMo) mengeluarkan kunci Token Plan dengan awalan `tp-` — maklumat sahaja, tidak dikuatkuasakan."},selectTypeFirst:"Pilih Jenis Penyedia",selectTypeFirstDesc:"Pilih jenis penyedia yang ingin anda tambah",codeProviderNote:"Penyedia kod hanya memerlukan Kunci API dan URL. Model diurus oleh Agent Router.",buttons:{cancel:"Batal",submitAdd:"Tambah Penyedia",submitUpdate:"Kemas Kini Penyedia",continue:"Teruskan",back:"Kembali"}},details:{noSelection:"Pilih penyedia untuk melihat butiran",apiKey:"Kunci API",apiUrl:"URL API",nameLabel:"Nama Penyedia",modelsEndpoint:"Endpoint Model",modelsEndpointHelper:"Gantikan endpoint penemuan jika penyedia mendedahkan laluan /models tersuai.",models:"Model",transformers:"Transformer",codeProviderNote:"Penyedia kod (seperti Claude Code) tidak memerlukan konfigurasi model. Model diurus secara automatik oleh Agent Router.",buttons:{more:"Lagi Tetapan",delete:"Padam"}},providerModelSelector:{placeholder:"Pilih penyedia dan model",noProviders:"Tiada penyedia tersedia",noModels:"Tiada model dikonfigurasi"},apiKeyPool:{title:"Pool Kunci API",description:"Konfigurasikan berbilang kunci API untuk pengimbangan beban. Setiap sesi berpegang pada satu kunci untuk mengekalkan cache prompt.",defaultLabel:"Lalai",weight:"Berat",noKey:"Tiada kunci",labelPlaceholder:"Label (cth., Kunci #1, Pengeluaran)",addKey:"Tambah Kunci API",add:"Tambah",empty:"Tiada kunci tambahan dikonfigurasi.",statusCoolingDown:"Menyejuk {{time}}",statusAuthFailed:"Pengesahan gagal · dilumpuhkan",statusDisabled:"Dilumpuhkan",statusHealthy:"Sihat",agoSeconds:"{{count}}s lalu",agoMinutes:"{{count}}m lalu",agoHours:"{{count}}j lalu",agoDays:"{{count}}h lalu"},modelsManager:{searchPlaceholder:"Cari model...",defaultGroup:"Semua Model",add:"Tambah Model",manage:"Urus",empty:"Tiada model dalam kumpulan ini",enabled:"Diaktifkan",disabled:"Dilumpuhkan",filters:{all:"Semua",vision:"Penglihatan",reasoning:"Penaakulan",free:"Percuma",tools:"Alat"},manualDialog:{title:"Tambah Model",subtitle:"Tambah model tersuai ke penyedia ini",modelId:"ID Model",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, dsb.",modelIdHelper:"Pengecam model tepat yang digunakan semasa memanggil API",modelName:"Nama Paparan",modelNamePlaceholder:"Nama paparan mesra (pilihan)",modelNameHelper:"Nama pilihan yang ditunjukkan dalam UI. Jika kosong, ID Model akan digunakan",group:"Kumpulan",groupPlaceholder:"Pilih atau masukkan nama kumpulan",submit:"Tambah",cancel:"Batal",helper:"Berikan pengecam model tepat yang didedahkan oleh API penyedia."},editDialog:{title:"Edit Model",subtitle:"Ubah suai tetapan model",modelId:"ID Model",modelIdPlaceholder:"Pengecam model",modelIdHelper:"Pengecam model yang digunakan semasa memanggil API",modelName:"Nama Paparan",modelNamePlaceholder:"Nama paparan mesra",modelNameHelper:"Nama yang ditunjukkan dalam UI",group:"Kumpulan",groupPlaceholder:"Pilih atau masukkan nama kumpulan",submit:"Simpan",cancel:"Batal",vision:"Keupayaan Penglihatan",visionHint:"Sama ada model ini menyokong input imej/penglihatan",reasoning:"Model Pemikiran",reasoningHint:"Sama ada model ini menyokong mod pemikiran/penaakulan"},manageDialog:{title:"Urus Model",cachedAt:"Cache pada {{date}} ({{source}})",refresh:"Muat Semula",close:"Tutup",raw:"JSON Mentah",empty:"Tiada model jauh tersedia.",error:"Gagal memuatkan model: {{message}}",addFromCatalog:"Tambah",sourceCache:"cache",sourceNetwork:"langsung",contextLength:"Konteks {{value}} token",maxTokens:"Maks {{value}} token"},messages:{added:"Model ditambah.",updated:"Model dikemas kini.",removed:"Model dibuang.",duplicate:"Model sudah wujud.",refreshed:"Model dimuat semula",refreshFailed:"Gagal memuat semula model"},testDialog:{title:"Ujian Ketersambungan Model",provider:"Penyedia",model:"Model",testing:"Menguji...",success:"Ujian Berjaya",successMessage:"Model boleh diakses seperti biasa",failure:"Ujian Gagal",aiResponse:"Respons AI",charCount:"{{count}} aksara",duration:"Tempoh {{time}}s",close:"Tutup",retest:"Uji Semula",testButton:"Uji model",unsupportedFormat:"Pengujian belum disokong untuk format penyedia ini."}},router:{title:"Konfigurasi Router",description:"Konfigurasikan penyedia/model yang akan digunakan untuk senario berbeza.",labels:{default:"Lalai",background:"latar belakang",think:"fikir",longContext:"Konteks Panjang",webSearch:"Carian Web",image:"Imej",longContextThreshold:"Ambang Konteks Panjang"},helper:{longContextThreshold:"Bilangan token sebelum beralih ke model konteks panjang."},placeholder:{required:"Diperlukan",optional:"Pilihan"}},agentRouter:{title:"Agent Router",description:"Konfigurasikan penghalaan dua arah antara mod Sembang dan Kod.",searchPlaceholder:"Cari router...",noSearchResults:"Tiada router yang sepadan dengan carian anda.",tabs:{chatToCode:"Sembang → Kod",codeToChatPlaceholder:"Kod → Sembang"},chatToCode:{title:"Router Sembang ke Kod",description:"Gunakan penyedia sembang dalam mod ejen/pengekodan",addRouter:"Tambah Router",emptyState:"Tiada router Sembang→Kod dikonfigurasi. Tambah satu untuk menggunakan penyedia sembang dalam mod pengekodan.",form:{name:"Nama Router",namePlaceholder:"Router Sembang→Kod Saya",chatProvider:"Penyedia Sembang",chatProviderPlaceholder:"Pilih penyedia sembang",mode:"Mod",modeSimple:"Mudah",modeAdvanced:"Lanjutan",modeSimpleDesc:"Laluan terus ke penyedia sembang",modeAdvancedDesc:"Konfigurasikan pemetaan model dan pengendalian konteks",enabled:"Diaktifkan",save:"Simpan Router",cancel:"Batal"},list:{provider:"Penyedia",mode:"Mod",status:"Status"},mappings:{title:"Pemetaan Model",description:"Petakan model penyedia Sembang ke model penyedia Kod",count:"pemetaan",empty:"Tiada pemetaan model dikonfigurasi. Tambah pemetaan untuk menghalakan model sembang ke penyedia kod.",addNew:"Tambah Pemetaan Baharu",selectSource:"Pilih model sumber (Sembang)",selectTarget:"Pilih model sasaran (Kod)",targetPlaceholder:"Masukkan nama model Claude Code",notSet:"(Tidak ditetapkan - klik untuk memilih)",add:"Tambah",edit:"Edit",done:"Selesai"},advanced:{title:"Konfigurasi Lanjutan",description:"Konfigurasikan model untuk jenis tugas yang berbeza",helpText:"Model lalai diperlukan. Model lain adalah pilihan dan akan menggunakan lalai jika tidak dikonfigurasi.",default:{label:"Lalai",placeholder:"Pilih model lalai",description:"Model utama untuk tugas am (serupa dengan Claude Sonnet)"},background:{label:"Latar Belakang",placeholder:"Pilih model latar belakang",description:"Model ringan untuk tugas latar belakang (serupa dengan Claude Haiku)"},think:{label:"Fikir",placeholder:"Pilih model pemikiran",description:"Model lanjutan untuk penaakulan kompleks (serupa dengan Claude Opus)"},image:{label:"Imej",placeholder:"Pilih model imej",description:"Model untuk tugas berkaitan imej dengan keupayaan penglihatan"}}},codeToChat:{title:"Router Kod ke Sembang",description:"Dedahkan model Pelan Pengekodan dalam mod sembang",addRouter:"Tambah Router",emptyState:"Tiada router Kod→Sembang dikonfigurasi. Tambah satu untuk mendedahkan model Pelan Pengekodan dalam mod sembang.",form:{name:"Nama Router",namePlaceholder:"Router Kod→Sembang Saya",codeProvider:"Penyedia Kod",codeProviderPlaceholder:"Pilih penyedia kod",codeProviderHelper:"Pilih penyedia Kod untuk digunakan dalam transformasi",models:"Model Pelan Pengekodan",modelsHelper:"Pilih model Pelan Pengekodan yang hendak didedahkan",enabled:"Diaktifkan",save:"Simpan Router",cancel:"Batal"},mappings:{title:"Pemetaan Model",description:"Petakan model penyedia Kod ke model penyedia Sembang untuk pendedahan",count:"pemetaan",empty:"Tiada pemetaan model dikonfigurasi. Tambah pemetaan untuk mendedahkan model Kod dalam mod sembang.",addNew:"Tambah Pemetaan Baharu",selectSource:"Pilih model sumber (Kod)",selectTarget:"Pilih model sasaran (Sembang)",sourcePlaceholder:"Masukkan nama model sumber",targetPlaceholder:"Masukkan nama model sasaran",add:"Tambah",edit:"Edit",done:"Selesai"}},transformers:{title:"Transformer",description:"Konfigurasikan transformer untuk penukaran permintaan/respons",noProvider:"Pilih penyedia untuk mengkonfigurasi transformer",empty:"Tiada transformer",count:"{{count}} transformer"},status:{enabled:"Diaktifkan",disabled:"Dilumpuhkan"},messages:{routerAdded:"Router berjaya ditambah",routerUpdated:"Router berjaya dikemas kini",routerDeleted:"Router berjaya dipadam",saveFailed:"Gagal menyimpan router"}},presets:{title:"Tambah Penyedia Pantas",added:"Ditambah",add:"Tambah",features:{search:"Carian",vision:"Penglihatan",mcp:"MCP",codingPlan:"Pelan Pengekodan"}},alerts:{deleteConfirm:"Adakah anda pasti ingin memadam penyedia ini?"},errors:{nameRequired:"Nama penyedia diperlukan",urlRequired:"URL Asas API diperlukan",urlInvalid:"Sila masukkan URL yang sah (cth., https://api.example.com)",saveFailed:"Gagal menyimpan penyedia",deleteFailed:"Ralat memadamkan penyedia. Sila cuba lagi.",toggleFailed:"Ralat menukar status penyedia. Sila cuba lagi."},openRouter:{title:"Penghalaan Penyedia OpenRouter",description:"Konfigurasikan cara permintaan dihalakan ke penyedia berbeza pada OpenRouter.",sort:"Strategi Penghalaan",sortTooltip:"Pilih cara mengutamakan penyedia. Auto menggunakan pengimbangan beban pintar.",order:"Susunan Keutamaan Penyedia",orderTooltip:"Tentukan penyedia yang hendak dicuba mengikut urutan (cth., anthropic, openai, together). Tekan Enter untuk menambah.",orderPlaceholder:"Taip slug penyedia dan tekan Enter...",allowFallbacks:"Benarkan Sandaran",allowFallbacksTooltip:"Apabila diaktifkan, OpenRouter akan mencuba penyedia sandaran jika penyedia utama tidak tersedia.",requireParameters:"Perlukan Semua Parameter",requireParametersTooltip:"Hanya halakan ke penyedia yang menyokong semua parameter dalam permintaan anda.",dataCollection:"Dasar Pengumpulan Data",dataCollectionTooltip:"Kawal sama ada menggunakan penyedia yang mungkin menyimpan atau melatih data anda.",zdr:"Pengekalan Data Sifar",zdrTooltip:"Hanya halakan ke endpoint dengan dasar Pengekalan Data Sifar.",only:"Benarkan Penyedia Ini Sahaja",onlyTooltip:"Hanya gunakan penyedia tertentu ini. Biarkan kosong untuk membenarkan semua penyedia.",onlyPlaceholder:"Taip slug penyedia dan tekan Enter...",ignore:"Abaikan Penyedia",ignoreTooltip:"Langkau penyedia ini semasa menghalakan permintaan.",ignorePlaceholder:"Taip slug penyedia dan tekan Enter...",quantizations:"Penapis Kuantisasi",quantizationsTooltip:"Hanya gunakan penyedia dengan tahap kuantisasi tertentu. Ketepatan yang lebih rendah boleh mengurangkan kualiti tetapi meningkatkan kelajuan.",maxPrice:"Harga Maksimum",maxPriceTooltip:"Tetapkan had harga maksimum bagi setiap juta token. Biarkan kosong untuk tiada had.",configured:"Dikonfigurasi"}},bI={label:"Mod API",standard:"Standard",codingPlan:"Pelan Pengekodan",tokenPlan:"Pelan Token",apiKeyPrefixHint:"Kunci untuk pelan ini biasanya bermula dengan `{{prefix}}`. Petunjuk sahaja — tidak dikuatkuasakan.",dashscopeCodingPlanSeparateKey:"Pelan Pengekodan DashScope menggunakan kunci API berasingan daripada endpoint standard.",baiduCodingPlanSeparateKey:"Pelan Pengekodan Qianfan menggunakan kunci API berasingan daripada endpoint standard.",tencentTokenPlanAnthropicOnly:"Pelan Token Tencent adalah protokol Anthropic sahaja.",xiaomiTokenPlanRegions:"URL asas lalai ialah `token-plan-cn.*`. Anda boleh mengeditnya secara manual ke `token-plan-sgp.*` atau `token-plan-ams.*`.",confirmOverwriteTitle:"Tukar mod API?",confirmOverwriteBody:"Anda telah menyesuaikan URL API atau Kunci API. Menukar mod akan menggantikannya dengan lalai mod baharu — atau kekalkan penyesuaian anda dan hanya kemas kini label mod.",overwriteAndSwitch:"Ganti dan tukar",keepCustomizations:"Kekalkan penyesuaian"},PI={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Pelan Token)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},AI={cancel:"Batal",close:"Tutup",copy:"Salin",delete:"Padam",dismiss:"Tutup",save:"Simpan",optional:"pilihan",retry:"Cuba lagi",loading:"Memuatkan…"},CI={common:{learnMore:"Dokumentasi"}},xI={notSupportedByDaemon:"Belum disokong oleh daemon",discoveryUnsupportedFormat:"Penemuan model belum disokong untuk format penyedia ini. Tambah model secara manual."},zI={subtitle:"Panel Kawalan",providers:"Penyedia",apiService:"Perkhidmatan API",accounts:"Akaun",codeCli:"Code CLI",settings:"Tetapan",usageStats:"Penggunaan",pricing:"Harga"},II={title:"Perkhidmatan API",description:"Konfigurasikan pelayan API keluar, penghalaan model setiap endpoint, dan kunci akses bernama.",loading:"Memuatkan konfigurasi pelayan…",loadError:"Tidak dapat memuatkan konfigurasi pelayan. Pastikan daemon boleh dicapai.",enable:{label:"Aktifkan pelayan keluar",description:"Mulakan pelayan API tempatan yang menghalakan pemanggil luaran melalui penyedia anda."},networkBinding:{label:"Benarkan akses LAN",description:"Ikat pelayan ke antara muka rangkaian anda dan bukan hanya loopback.",warning:"Akses LAN mendedahkan pelayan API kepada peranti lain dalam rangkaian anda. Digabungkan dengan penghalaan langganan, permintaan boleh menggunakan kuota langganan anda — matikan ini melainkan anda mempercayai rangkaian tersebut."},status:{running:"Pelayan berjalan",stopped:"Pelayan berhenti",runningHint:"Pelayan API keluar sedang menerima permintaan.",stoppedHint:"Aktifkan pelayan untuk mula menerima permintaan.",port:"port {{port}}",loopback:"URL Loopback",lan:"URL LAN"},endpoints:{title:"Penghalaan endpoint",description:"Pilih model yang dihalakan oleh setiap format wayar. Model lalai dimasukkan di sini — pelayan adalah router, bukan aplikasi sembang."},endpoint:{name:{chat:"Sembang OpenAI",responses:"Respons OpenAI",messages:"Pesan Anthropic",gemini:"Gemini"},defaultModel:"Model lalai",backgroundModel:"Model latar belakang",visionModel:"Model penglihatan",noVisionModel:"Tiada",backgroundModelIds:"ID model latar belakang",backgroundModelIdsPlaceholder:"id model dipisahkan koma",modelPlaceholder:"Pilih model…",useSubscription:"Gunakan langganan",subscriptionUnsupported:"Penghalaan langganan tidak tersedia untuk endpoint ini."},keys:{title:"Kunci akses",description:"Kunci bernama yang dihantar oleh pemanggil luaran sebagai token Bearer. Kunci penuh hanya ditunjukkan sekali semasa penciptaan.",namePlaceholder:"Nama kunci (cth. my-cli)",create:"Cipta kunci",empty:"Tiada kunci akses lagi.",enabled:"Diaktifkan",disabled:"Dilumpuhkan",revoked:"Dibatalkan",toggle:"Togol kunci",revoke:"Batalkan",revokeConfirmTitle:"Batalkan kunci ini?",revokeConfirmDesc:'Membatalkan "{{name}}" serta-merta menghentikan pengesahannya. Ini tidak boleh dibuat asal.',created:{title:"Kunci dicipta",warning:"Salin kunci ini sekarang — ia tidak akan ditunjukkan lagi. Simpan dengan selamat.",copy:"Salin",copied:"Disalin",dismiss:"Selesai"}}},SI={title:"Akaun & Langganan",description:"Urus kelayakan langganan yang dihalakan oleh pelayan. Token ditulis di sini tetapi tidak pernah dipaparkan semula.",loading:"Memuatkan akaun…",empty:"Tiada penyedia langganan tersedia.",signIn:"Log masuk",oauth:{title:"Log masuk ke {{name}}",description:"Buka halaman log masuk dalam pelayar anda, benarkan, kemudian tampal kod kebenaran di bawah. Kod tersebut hanya melepasi ke daemon — token yang dicetak tidak pernah ditunjukkan.",openPage:"Buka halaman log masuk",codeLabel:"Kod kebenaran",codePlaceholder:"Tampal kod di sini",submit:"Selesaikan log masuk"},codexOauth:{title:"Log masuk ke {{name}}",description:"Buka halaman log masuk dalam pelayar anda dan benarkan. Daemon menangkap hasilnya secara automatik — biarkan ini terbuka sehingga selesai. Token tidak pernah ditunjukkan.",waiting:"Menunggu anda menyelesaikan log masuk dalam pelayar anda…",failed:"Log masuk gagal. Sila cuba lagi."},clearProvider:"Kosongkan semua",clearConfirmTitle:"Kosongkan akaun {{name}}?",clearConfirmDesc:"Ini membuang setiap kelayakan tersimpan untuk penyedia ini. Ini tidak boleh dibuat asal.",credential:{ok:"Dikonfigurasi",notConfigured:"Tidak dikonfigurasi"},kind:{"pass-through":"Kelayakan laluan terus","oauth-bearer":"Bearer OAuth","static-bearer":"Kunci bearer statik"},reason:{"missing-credential":"Tiada kelayakan tersimpan.",expired:"Kelayakan tamat tempoh.","reauth-required":"Pengesahan semula diperlukan.","refresh-failed":"Pembaharuan token gagal.","not-refreshable":"Kelayakan tidak boleh diperbaharui.",unknown:"Status tidak diketahui."},status:{unconfigured:"Tidak dikonfigurasi",authorized:"Dibenarkan",configured:"Dikonfigurasi",expired:"Tamat tempoh",error:"Ralat"},authMethod:{oauth:"OAuth",setup_token:"Token persediaan",manual:"Manual"},list:{empty:"Tiada akaun tersimpan untuk penyedia ini.",active:"Aktif",expiresAt:"Tamat pada {{value}}",setActive:"Tetapkan aktif",remove:"Buang",removeConfirmTitle:"Buang akaun ini?",removeConfirmDesc:'Membuang "{{name}}" akan memadam kelayakan tersimpannya. Ini tidak boleh dibuat asal.',title:"Akaun"},write:{trigger:"Tambah kelayakan",title:"Tulis kelayakan {{name}}",description:"Tampal bahan token yang telah diperoleh. Medan terhad kepada apa yang diterima oleh penyedia ini; token disimpan, tidak pernah ditunjukkan semula.",authMethod:"Kaedah pengesahan",status:"Status",subscriptionLevel:"Tahap langganan",subscriptionLevelNone:"Tidak ditetapkan",submit:"Simpan kelayakan"},field:{accessToken:"Token akses",refreshToken:"Token pembaharuan",idToken:"Token ID",apiKey:"Kunci API",expiresAt:"Tamat pada (ISO)",setupTokenExpiresAt:"Token persediaan tamat pada (ISO)",accountId:"ID Akaun",email:"E-mel",organizationId:"ID Organisasi",baseUrl:"URL Asas",zenBaseUrl:"URL asas Zen"},provider:{claude:{title:"Claude",description:"Kelayakan langganan Anthropic yang dihalakan oleh daemon."},codex:{title:"Codex",description:"Kelayakan langganan OpenAI Codex yang dihalakan oleh daemon."},gemini:{title:"Gemini",description:"Kelayakan langganan Google Gemini yang dihalakan oleh daemon."},opencodego:{title:"OpenCodeGo",description:"Kelayakan kunci API statik yang dihalakan oleh daemon."}},authMethodLabel:"Kaedah kebenaran",authMethodDesc:{oauth:"Log masuk melalui pelayar anda; daemon menangkap dan menyimpan token.",manual:"Tampal token yang telah diperoleh. Ia disimpan, tidak pernah dipaparkan semula."},actions:{authorize:"Benarkan",enterToken:"Masukkan token",refresh:"Muat Semula"},accounts:{addAccount:"Tambah akaun"},detail:{authMethod:"Kaedah kebenaran",subscriptionLevel:"Tahap langganan",expiresAt:"Tamat",lastRefreshed:"Kali terakhir dimuat semula",label:"Label akaun",labelPlaceholder:"Namakan akaun ini",saveLabel:"Simpan label"},oauthFlow:{step1:{title:"Buka halaman kebenaran",desc:"Buka halaman log masuk dalam pelayar anda."},step2:{title:"Benarkan akses",desc:"Log masuk dan luluskan akses untuk penyedia."},step3:{title:"Salin kod kebenaran",desc:"Halaman menunjukkan kod kebenaran selepas anda meluluskan."},step4:{title:"Tampal kod",desc:"Tampal kod kebenaran di bawah untuk selesai. Kod tersebut hanya melepasi ke daemon — token yang dicetak tidak pernah ditunjukkan."},authorize:"Selesaikan log masuk",showUrl:"Tunjukkan URL kebenaran"},manual:{title:"Tampal kelayakan",description:"Tampal token yang telah diperoleh. Medan terhad kepada apa yang diterima oleh penyedia ini; token disimpan, tidak pernah ditunjukkan semula.",accessTokenPlaceholder:"Tampal token akses",refreshTokenPlaceholder:"Tampal token pembaharuan (pilihan)",hint:"Token dihantar ke daemon dan disimpan dalam bentuk disulitkan. Ia tidak pernah dipaparkan semula."},openCodeGo:{apiKeyRequired:"Kunci API diperlukan.",apiKeyPlaceholder:"Tampal kunci API",baseUrlPlaceholder:"https://… (pilihan)",zenBaseUrlPlaceholder:"https://… (pilihan)"},info:{title:"Tentang akaun langganan",description:"Token ditulis ke daemon dan digunakan untuk mengesahkan permintaan hulu. Ia disimpan dalam bentuk disulitkan dan tidak pernah dipaparkan semula. Membuang akaun akan memadam kelayakan tersimpannya."},rename:{failed:"Tidak dapat menamakan semula akaun."},refresh:{failed:"Tidak dapat membaharui token."},errors:{requestFailed:"Permintaan gagal. Sila cuba lagi."},syncWarning:{"external-divergent":"Fail log masuk CLI luaran mengandungi kelayakan yang lebih baharu daripada akaun ini. Token yang disimpan mungkin berhenti dimuat semula — muat semula sekarang atau log masuk semula.","external-not-rotated":"Muat semula gagal dan CLI luaran mengandungi kelayakan tamat tempoh yang sama. Sila log masuk semula.","duplicate-token":"Akaun lain berkongsi kelayakan ini. Memuat semula salah satu akan melog keluar yang satu lagi."},importExternal:{detected:"Log masuk CLI {{name}} sedia ada ditemui pada mesin ini.",hint:"Selepas diimport, aplikasi ini memastikannya sentiasa terkini: setiap kali token dimuat semula, fail log masuk CLI turut dikemas kini, jadi CLI dalam terminal kekal log masuk.",button:"Import log masuk CLI sedia ada"}},wI={title:"Code CLI",description:"Arahkan CLI pengekodan ke proksi keluar daemon. Halaman ini baca sahaja — tiada apa yang perlu dikonfigurasi di sini.",copy:"Salin",copied:"Disalin",baseUrl:{title:"URL asas daemon",description:"Alamat proksi yang disambungkan oleh CLI anda.",label:"URL Asas"},token:{title:"Pengesahan",hint:"Hantar 'Authorization: Bearer <your-admin-token>' untuk laluan admin. Token admin dikonfigurasi dalam daemon (fail konfigurasi atau persekitaran) — ia tidak pernah ditunjukkan di sini."},examples:{title:"Contoh persekitaran pelancaran",keyNote:"Gunakan kunci akses keluar yang dicipta di halaman Perkhidmatan API — bukan token admin.",anthropic:"CLI format Anthropic",openai:"CLI format OpenAI"},launchDescription:"Lancarkan CLI pengekodan dalam terminal, diarahkan ke daemon ini. Daemon menyuntik persekitaran redirect dan memulakan CLI untuk anda.",refresh:"Muat Semula",loading:"Mengesan CLI…",cli:{installed:"Dipasang",notFound:"Tidak dijumpai",notFoundHint:"CLI ini tidak ada dalam PATH hos daemon. Pasangnya, kemudian muat semula.",install:"Pasang",installing:"Memasang…",installingHint:"Memasang pada hos daemon — ini mungkin mengambil masa satu minit.",launch:"Lancarkan",launchTitle:"Lancarkan {{name}}",launchDescription:"Membuka terminal baharu pada hos daemon yang menjalankan CLI ini, dihalakan melalui proksi daemon. Pilih direktori kerja pilihan.",cwdLabel:"Direktori kerja",cwdPlaceholder:"/path/to/your/project",runningVia:"Berjalan · {{provider}} / {{model}}",stop:"Henti"},manual:{title:"Persediaan manual",description:"Ingin menjalankan CLI sendiri? Arahkannya ke daemon dengan pemboleh ubah persekitaran ini.",show:"Tunjuk",hide:"Sembunyikan"}},TI={probing:"Menyemak daemon…",spawning:"Memulakan daemon…",failed:"Daemon tidak dapat dimulakan",failedHint:"Pastikan Node.js dipasang dan daemon telah dibina (dist ada), atau tetapkan OMNICROSS_DAEMON_ENTRY ke cli.js daemon."},jI={title:"Tetapan",description:"Pilihan aplikasi desktop.",desktopOnly:"Pilihan permulaan dan tray hanya terpakai dalam aplikasi desktop.",startup:{title:"Permulaan",autoLaunch:"Lancar semasa log masuk",autoLaunchHint:"Mulakan Omnicross secara automatik semasa anda log masuk.",startMinimized:"Mulakan diminimumkan ke tray",startMinimizedHint:"Lancar dalam latar belakang tanpa membuka tetingkap."},tray:{title:"Tray",minimizeOnClose:"Minimumkan ke tray semasa ditutup",minimizeOnCloseHint:"Menutup tetingkap menyembunyikannya ke tray dan bukannya keluar."},language:{title:"Bahasa",label:"Bahasa antara muka"}},MI={title:"Statistik penggunaan",description:"Statistik token dan kos untuk permintaan yang dilayan oleh daemon.",rangeToday:"Hari ini",range7d:"7 hari lepas",range30d:"30 hari lepas",rangeCustom:"Tersuai",from:"Dari",to:"Hingga",totalCost:"Jumlah kos",cacheSavings:"Penjimatan cache",events:"Permintaan",inputTokens:"Token input",outputTokens:"Token output",cacheReadTokens:"Baca cache",cacheWriteTokens:"Tulis cache",reasoningTokens:"Token penaakulan",byModel:"Mengikut model",byApiKey:"Mengikut kunci API",provider:"Pembekal",model:"Model",cost:"Kos",apiKey:"Kunci API",unpriced:"Tiada harga",unpricedHint:"Tiada entri harga untuk model ini — tambah di halaman Harga.",unattributed:"Tidak diatribusi",unattributedHint:"Permintaan yang tidak dikaitkan dengan kunci API tertentu. Ini normal sehingga atribusi mengikut kunci direkodkan.",empty:"Tiada permintaan dalam julat ini.",invalidRange:"Pilih julat tarikh yang sah."},NI={title:"Harga model",description:"Harga token mengikut model untuk mengira kos permintaan, dalam USD bagi setiap 1 juta token.",search:"Cari pembekal atau model…",fetchLatest:"Dapatkan terkini",fetching:"Mendapatkan…",addEntry:"Tambah entri",provider:"Pembekal",model:"Model",inputPrice:"Input",outputPrice:"Output",cacheReadPrice:"Baca cache",cacheWritePrice:"Tulis cache",source:"Sumber",updated:"Dikemas kini",userEdited:"disunting",edit:"Sunting",deleteTitle:"Padam entri harga ini?",empty:"Jadual harga kosong.",emptyHint:"Dapatkan harga terkini untuk mengisinya.",noMatches:"Tiada entri sepadan dengan carian anda.",saved:"Entri harga disimpan.",saveFailed:"Gagal menyimpan: {{message}}",deleteFailed:"Gagal memadam: {{message}}",alreadyDeleted:"Entri sudah tiada.",fetchApplied:"{{count}} entri dikemas kini daripada sumber.",fetchFailed:"Gagal mendapatkan: {{message}}",requiredId:"Diperlukan",invalidPrice:"Masukkan nombor bukan negatif",conflictTitle:"Selesaikan konflik harga",conflictHint:"Entri ini telah anda sunting dan turut berubah di sumber. Pilih bagi setiap baris sama ada mengekalkan nilai anda (Langkau) atau mengambil yang baharu (Tulis ganti).",current:"Semasa",incoming:"Masuk",overwrite:"Tulis ganti",skip:"Langkau",overwriteAll:"Tulis ganti semua",skipAll:"Langkau semua",applyResolutions:"Guna pakai",resolved:"{{overwritten}} ditulis ganti, {{skipped}} dilangkau.",resolvedWithStale:"{{overwritten}} ditulis ganti, {{skipped}} dilangkau. {{stale}} berubah sementara itu dan dibiarkan utuh.",refreshFailed:"Perubahan telah digunakan, tetapi gagal memuat semula senarai: {{message}}",sourceBuiltin:"Terbina dalam",sourceLitellm:"LiteLLM",sourceUser:"Pengguna"},LI={providerSettings:yI,apiMode:bI,presetName:PI,common:AI,mediaSettings:CI,appLocal:xI,nav:zI,apiService:II,accounts:SI,codeCli:wI,daemonStatus:TI,settings:jI,usageStats:MI,pricing:NI},RI={loading:"Laster LLM-konfigurasjon...",reset:{button:"Gjenopprett standardinnstillinger",confirmTitle:"Gjenopprett standardinnstillinger?",confirmBody:"Dette fjerner tilpasningene dine for denne leverandøren slik at den følger de innebygde standardene igjen. API-nøkkelen din og lagrede sesjoner beholdes.",confirmButton:"Gjenopprett standardinnstillinger"},reentryBanner:{message:"{{count}} aktivert(e) leverandør(er) trenger at API-nøkkelen angis på nytt. Åpne hver enkelt og legg til nøkkelen igjen."},migrationPack:{barHint:"Flytt leverandørnøklene og abonnementstokenene dine til en annen maskin med en kryptert pakke.",passphrase:"Passfrase",passphrasePlaceholder:"Skriv inn en passfrase",passphraseHint:"Bruk minst 8 tegn; 12 eller flere anbefales.",confirm:"Bekreft passfrase",confirmPlaceholder:"Skriv inn passfransen på nytt",mismatch:"Passfrasene stemmer ikke overens.",strength:{weak:"For kort — bruk minst 8 tegn.",fair:"OK — 12 eller flere tegn er sterkere.",strong:"Sterk passfrase."},export:{button:"Eksporter pakke",title:"Eksporter kryptert pakke",subtitle:"Krypter leverandørnøklene og abonnementstokenene dine til en portabel fil.",warning:"Denne filen inneholder dekrypterbare hemmeligheter. Oppbevar den trygt — alle med filen og passfransen kan lese nøklene dine. En mistet passfrase kan ikke gjenopprettes.",submit:"Eksporter",success:"Pakken ble eksportert.",error:"Eksporten mislyktes. Prøv igjen."},import:{button:"Importer pakke",title:"Importer kryptert pakke",subtitle:"Gjenopprett leverandørnøkler og abonnementtoken fra en eksportert pakke.",hint:"Skriv inn passfransen som ble brukt da pakken ble eksportert, og velg deretter filen.",submit:"Importer",successTitle:"Import fullført",summary:"Importerte {{providerKeys}} leverandørnøkkel/nøkler, {{poolKeys}} poolnøkkel/nøkler og {{tokenSets}} tokensett.",duplicates:"Hoppet over {{count}} poolnøkkel/nøkler som allerede finnes.",skipped:"Hoppet over (ingen samsvarende leverandør): {{names}}",error:"Feil passfrase eller skadet pakke. Ingenting ble endret."}},searchPlaceholder:"Søk leverandører...",emptySearch:"Ingen leverandører samsvarer med søket ditt.",emptyList:"Ingen leverandører konfigurert.",selectPrompt:"Velg en leverandør for å se detaljer",listStatus:"{{count}} modell(er)",noModels:"Ingen modeller konfigurert",enabled:"Aktivert",disabled:"Deaktivert",showEnabledOnly:"Vis kun aktiverte",showAll:"Vis alle leverandører",dragHandle:"Dra for å endre rekkefølge",reorderFailed:"Kunne ikke lagre leverandørrekkefølgen",credentials:{apiKey:"API-nøkkel",apiBaseUrl:"API-basis-URL"},filter:{all:"Alle",chat:"Chat",code:"Kode"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Velg en mal",skipTemplates:"Hopp over, konfigurer manuelt",name:"Navn *",providerType:"Type",apiType:"API-type",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standard OpenAI chat/completions API-format",claudecode:"Anthropic Messages API-format (Claude Code)"},chatApiFormat:"API-format",chatApiFormatDescription:"Velg API-formatet som samsvarer med leverandørens endepunkt",apiKey:"API-nøkkel",apiKeyPlaceholder:"sk-... eller $ENV_VAR",apiKeyHelper:"Bruk $VAR_NAME for å referere til miljøvariabler",apiKeySetPlaceholder:"Nøkkel er angitt — la stå tomt for å beholde den",apiKeyReplaceHelper:"En nøkkel er lagret sikkert. Skriv en ny verdi for å erstatte den, eller la stå tomt for å beholde den.",testApiKey:"Test API-nøkkel",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Forhåndsvisning:",models:"Modeller",modelPlaceholder:"Modellnavn (f.eks. gpt-4, claude-3-opus)",transformers:"Transformatorer",transformerConfig:"API-transformatorer",transformerConfigDescription:"Konfigurer transformatorer for å tilpasse API-forespørsel-/svarformater for denne leverandøren",transformerConfigNote:"Daemonen bruker disse transformatorene i forespørselskjeden, etter leverandørens formatransformator (som håndterer konverteringen av trådformatet). Ukjente transformatornavn hoppes over.",enabled:"Aktivert",apiVersion:"API-versjon",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API-versjon (f.eks. 2024-08-01-preview)",official:"Offisielt Anthropic API",officialHelper:"Aktiver hvis denne leverandøren kobler direkte til det offisielle Anthropic API. Deaktiver for omvendte proxyer eller tredjepartstjenester.",maxConcurrency:"Maks samtidige forespørsler",maxConcurrencyHelper:"Maksimalt antall samtidige API-forespørsler sendt til denne leverandøren. Lavere verdier hjelper med å unngå hastighetsbegrensning (429-feil). Angi `-1` for ingen grense.",codingPlan:{label:"Kodingsplan",description:"Bruk et separat API-endepunkt for abonnementsbaserte kodingsplaner",baseUrl:"Kodingsplanens basis-URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kodingsplanens API-nøkkel (valgfritt)",apiKeyPlaceholder:"La stå tomt for å bruke leverandørens API-nøkkel",apiKeyHelper:"Kreves kun hvis kodingsplanen bruker en annen API-nøkkel",tokenPlanHint:"Noen leverandører (f.eks. Xiaomi MiMo) utsteder Token Plan-nøkler med prefiks `tp-` — kun informativt, ikke håndhevet."},selectTypeFirst:"Velg leverandørtype",selectTypeFirstDesc:"Velg hvilken type leverandør du vil legge til",codeProviderNote:"Kodeleverandører trenger bare API-nøkkel og URL. Modeller administreres av agentruteren.",buttons:{cancel:"Avbryt",submitAdd:"Legg til leverandør",submitUpdate:"Oppdater leverandør",continue:"Fortsett",back:"Tilbake"}},details:{noSelection:"Velg en leverandør for å se detaljer",apiKey:"API-nøkkel",apiUrl:"API-URL",nameLabel:"Leverandørnavn",modelsEndpoint:"Modellendepunkt",modelsEndpointHelper:"Overstyr oppdagelsesendepunktet hvis leverandøren eksponerer en egendefinert /models-sti.",models:"Modeller",transformers:"Transformatorer",codeProviderNote:"Kodeleverandører (som Claude Code) krever ikke modellkonfigurasjon. Modeller administreres automatisk av agentruteren.",buttons:{more:"Flere innstillinger",delete:"Slett"}},providerModelSelector:{placeholder:"Velg leverandør og modell",noProviders:"Ingen leverandører tilgjengelig",noModels:"Ingen modeller konfigurert"},apiKeyPool:{title:"API-nøkkelpool",description:"Konfigurer flere API-nøkler for lastbalansering. Hver sesjon holder seg til én nøkkel for å bevare promptbufferen.",defaultLabel:"Standard",weight:"Vekt",noKey:"Ingen nøkkel",labelPlaceholder:"Etikett (f.eks. Nøkkel #1, Produksjon)",addKey:"Legg til API-nøkkel",add:"Legg til",empty:"Ingen ekstra nøkler konfigurert.",statusCoolingDown:"Nedkjøling {{time}}",statusAuthFailed:"Autentisering mislyktes · deaktivert",statusDisabled:"Deaktivert",statusHealthy:"Sunn",agoSeconds:"{{count}}s siden",agoMinutes:"{{count}}m siden",agoHours:"{{count}}t siden",agoDays:"{{count}}d siden"},modelsManager:{searchPlaceholder:"Søk modeller...",defaultGroup:"Alle modeller",add:"Legg til modell",manage:"Administrer",empty:"Ingen modeller i denne gruppen",enabled:"Aktivert",disabled:"Deaktivert",filters:{all:"Alle",vision:"Visjon",reasoning:"Resonnering",free:"Gratis",tools:"Verktøy"},manualDialog:{title:"Legg til modell",subtitle:"Legg til en egendefinert modell til denne leverandøren",modelId:"Modell-ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, osv.",modelIdHelper:"Den nøyaktige modellidentifikatoren som brukes ved kall til API-et",modelName:"Visningsnavn",modelNamePlaceholder:"Vennlig visningsnavn (valgfritt)",modelNameHelper:"Valgfritt navn vist i grensesnittet. Hvis tomt brukes Modell-ID",group:"Gruppe",groupPlaceholder:"Velg eller skriv inn et gruppenavn",submit:"Legg til",cancel:"Avbryt",helper:"Oppgi den nøyaktige modellidentifikatoren eksponert av leverandørens API."},editDialog:{title:"Rediger modell",subtitle:"Endre modellinnstillinger",modelId:"Modell-ID",modelIdPlaceholder:"Modellidentifikator",modelIdHelper:"Modellidentifikatoren som brukes ved kall til API-et",modelName:"Visningsnavn",modelNamePlaceholder:"Vennlig visningsnavn",modelNameHelper:"Navn vist i grensesnittet",group:"Gruppe",groupPlaceholder:"Velg eller skriv inn et gruppenavn",submit:"Lagre",cancel:"Avbryt",vision:"Visjonsfunksjon",visionHint:"Om denne modellen støtter bilde-/visjonsinput",reasoning:"Tenkende modell",reasoningHint:"Om denne modellen støtter tenke-/resonneringsmodus"},manageDialog:{title:"Administrer modeller",cachedAt:"Bufret {{date}} ({{source}})",refresh:"Oppdater",close:"Lukk",raw:"Rå JSON",empty:"Ingen eksterne modeller tilgjengelig.",error:"Kunne ikke laste modeller: {{message}}",addFromCatalog:"Legg til",sourceCache:"buffer",sourceNetwork:"live",contextLength:"Kontekst {{value}} tokens",maxTokens:"Maks {{value}} tokens"},messages:{added:"Modell lagt til.",updated:"Modell oppdatert.",removed:"Modell fjernet.",duplicate:"Modellen finnes allerede.",refreshed:"Modeller oppdatert",refreshFailed:"Kunne ikke oppdatere modeller"},testDialog:{title:"Tilkoblingstest for modell",provider:"Leverandør",model:"Modell",testing:"Tester...",success:"Test vellykket",successMessage:"Modellen kan nås normalt",failure:"Test mislyktes",aiResponse:"AI-svar",charCount:"{{count}} tegn",duration:"Varighet {{time}}s",close:"Lukk",retest:"Test på nytt",testButton:"Test modell",unsupportedFormat:"Testing støttes ikke ennå for dette leverandørformatet."}},router:{title:"Ruterkonfigurasjon",description:"Konfigurer hvilken leverandør/modell som skal brukes for ulike scenarier.",labels:{default:"Standard",background:"bakgrunn",think:"tenke",longContext:"Lang kontekst",webSearch:"Nettsøk",image:"Bilde",longContextThreshold:"Terskel for lang kontekst"},helper:{longContextThreshold:"Antall tokens før bytte til modellen med lang kontekst."},placeholder:{required:"Obligatorisk",optional:"Valgfritt"}},agentRouter:{title:"Agentruter",description:"Konfigurer toveis ruting mellom chat- og kodemodus.",searchPlaceholder:"Søk rutere...",noSearchResults:"Ingen rutere samsvarer med søket ditt.",tabs:{chatToCode:"Chat → Kode",codeToChatPlaceholder:"Kode → Chat"},chatToCode:{title:"Chat til kode-ruter",description:"Bruk chatleverandører i agent-/kodingsmodus",addRouter:"Legg til ruter",emptyState:"Ingen Chat→Kode-rutere konfigurert. Legg til en for å bruke chatleverandører i kodingsmodus.",form:{name:"Ruternavn",namePlaceholder:"Min Chat→Kode-ruter",chatProvider:"Chatleverandør",chatProviderPlaceholder:"Velg en chatleverandør",mode:"Modus",modeSimple:"Enkel",modeAdvanced:"Avansert",modeSimpleDesc:"Direkte gjennomstrømning til chatleverandør",modeAdvancedDesc:"Konfigurer modellmapping og konteksthåndtering",enabled:"Aktivert",save:"Lagre ruter",cancel:"Avbryt"},list:{provider:"Leverandør",mode:"Modus",status:"Status"},mappings:{title:"Modellmappinger",description:"Koble chatleverandørmodeller til kodeleverandørmodeller",count:"mapping(er)",empty:"Ingen modellmappinger konfigurert. Legg til mappinger for å rute chatmodeller til kodeleverandører.",addNew:"Legg til ny mapping",selectSource:"Velg kildemodell (Chat)",selectTarget:"Velg målmodell (Kode)",targetPlaceholder:"Skriv inn Claude Code-modellnavn",notSet:"(Ikke angitt — klikk for å velge)",add:"Legg til",edit:"Rediger",done:"Ferdig"},advanced:{title:"Avansert konfigurasjon",description:"Konfigurer modeller for ulike oppgavetyper",helpText:"Standardmodell er obligatorisk. Andre modeller er valgfrie og faller tilbake til standard hvis ikke konfigurert.",default:{label:"Standard",placeholder:"Velg standardmodell",description:"Primærmodell for generelle oppgaver (lignende Claude Sonnet)"},background:{label:"Bakgrunn",placeholder:"Velg bakgrunnsmodell",description:"Lett modell for bakgrunnsoppgaver (lignende Claude Haiku)"},think:{label:"Tenke",placeholder:"Velg tenkende modell",description:"Avansert modell for kompleks resonnering (lignende Claude Opus)"},image:{label:"Bilde",placeholder:"Velg bildemodell",description:"Modell for bilderelaterte oppgaver med visjonsfunksjon"}}},codeToChat:{title:"Kode til chat-ruter",description:"Eksponer kodingsplanmodeller i chatmodus",addRouter:"Legg til ruter",emptyState:"Ingen Kode→Chat-rutere konfigurert. Legg til en for å eksponere kodingsplanmodeller i chatmodus.",form:{name:"Ruternavn",namePlaceholder:"Min Kode→Chat-ruter",codeProvider:"Kodeleverandør",codeProviderPlaceholder:"Velg en kodeleverandør",codeProviderHelper:"Velg kodeleverandøren som skal brukes til transformasjon",models:"Kodingsplanmodeller",modelsHelper:"Velg hvilke kodingsplanmodeller som skal eksponeres",enabled:"Aktivert",save:"Lagre ruter",cancel:"Avbryt"},mappings:{title:"Modellmappinger",description:"Koble kodeleverandørmodeller til chatleverandørmodeller for eksponering",count:"mapping(er)",empty:"Ingen modellmappinger konfigurert. Legg til mappinger for å eksponere kodemodeller i chatmodus.",addNew:"Legg til ny mapping",selectSource:"Velg kildemodell (Kode)",selectTarget:"Velg målmodell (Chat)",sourcePlaceholder:"Skriv inn kildemodellnavn",targetPlaceholder:"Skriv inn målmodellnavn",add:"Legg til",edit:"Rediger",done:"Ferdig"}},transformers:{title:"Transformatorer",description:"Konfigurer transformatorer for forespørsel-/svarkonvertering",noProvider:"Velg en leverandør for å konfigurere transformatorer",empty:"Ingen transformatorer",count:"{{count}} transformator(er)"},status:{enabled:"Aktivert",disabled:"Deaktivert"},messages:{routerAdded:"Ruter lagt til",routerUpdated:"Ruter oppdatert",routerDeleted:"Ruter slettet",saveFailed:"Kunne ikke lagre ruteren"}},presets:{title:"Legg til leverandør raskt",added:"Lagt til",add:"Legg til",features:{search:"Søk",vision:"Visjon",mcp:"MCP",codingPlan:"Kodingsplan"}},alerts:{deleteConfirm:"Er du sikker på at du vil slette denne leverandøren?"},errors:{nameRequired:"Leverandørnavn er påkrevd",urlRequired:"API-basis-URL er påkrevd",urlInvalid:"Skriv inn en gyldig URL (f.eks. https://api.example.com)",saveFailed:"Kunne ikke lagre leverandøren",deleteFailed:"Feil ved sletting av leverandør. Prøv igjen.",toggleFailed:"Feil ved aktivering/deaktivering av leverandør. Prøv igjen."},openRouter:{title:"OpenRouter-leverandørruting",description:"Konfigurer hvordan forespørsler rutes til ulike leverandører på OpenRouter.",sort:"Rutingstrategi",sortTooltip:"Velg hvordan leverandører skal prioriteres. Auto bruker intelligent lastbalansering.",order:"Leverandørprioriteringsrekkefølge",orderTooltip:"Angi leverandører å prøve i rekkefølge (f.eks. anthropic, openai, together). Trykk Enter for å legge til.",orderPlaceholder:"Skriv leverandørens slug og trykk Enter...",allowFallbacks:"Tillat reserveløsninger",allowFallbacksTooltip:"Når aktivert vil OpenRouter prøve reserveleverandører hvis den primære er utilgjengelig.",requireParameters:"Krev alle parametere",requireParametersTooltip:"Rut bare til leverandører som støtter alle parametere i forespørselen din.",dataCollection:"Datainnsamlingspolicy",dataCollectionTooltip:"Kontroller om leverandører som kan lagre eller trene på dataene dine skal brukes.",zdr:"Null datalagring",zdrTooltip:"Rut bare til endepunkter med policy for null datalagring.",only:"Tillat bare leverandører",onlyTooltip:"Bruk bare disse spesifikke leverandørene. La stå tomt for å tillate alle leverandører.",onlyPlaceholder:"Skriv leverandørens slug og trykk Enter...",ignore:"Ignorer leverandører",ignoreTooltip:"Hopp over disse leverandørene ved ruting av forespørsler.",ignorePlaceholder:"Skriv leverandørens slug og trykk Enter...",quantizations:"Kvantiseringsfilter",quantizationsTooltip:"Bruk bare leverandører med spesifikke kvantiseringsnivåer. Lavere presisjon kan redusere kvaliteten, men forbedre hastigheten.",maxPrice:"Maksimalpris",maxPriceTooltip:"Angi maksimale prisgrenser per million tokens. La stå tomt for ingen grense.",configured:"Konfigurert"}},DI={label:"API-modus",standard:"Standard",codingPlan:"Kodingsplan",tokenPlan:"Tokenplan",apiKeyPrefixHint:"Nøkler for denne planen begynner vanligvis med `{{prefix}}`. Kun informativt — ikke håndhevet.",dashscopeCodingPlanSeparateKey:"DashScope Kodingsplan bruker en separat API-nøkkel fra standardendepunktet.",baiduCodingPlanSeparateKey:"Qianfan Kodingsplan bruker en separat API-nøkkel fra standardendepunktet.",tencentTokenPlanAnthropicOnly:"Tencent Tokenplan er kun Anthropic-protokoll.",xiaomiTokenPlanRegions:"Standard baseUrl er `token-plan-cn.*`. Du kan redigere den manuelt til `token-plan-sgp.*` eller `token-plan-ams.*`.",confirmOverwriteTitle:"Bytte API-modus?",confirmOverwriteBody:"Du har tilpasset API-URL-en eller API-nøkkelen. Bytting av modus vil overskrive dem med den nye modusens standardverdier — eller behold tilpasningene dine og oppdater bare modusetiketten.",overwriteAndSwitch:"Overskriv og bytt",keepCustomizations:"Behold tilpasninger"},EI={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Tokenplan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},OI={cancel:"Avbryt",close:"Lukk",copy:"Kopier",delete:"Slett",dismiss:"Avvis",save:"Lagre",optional:"valgfritt",retry:"Prøv igjen",loading:"Laster…"},KI={common:{learnMore:"Dokumentasjon"}},UI={notSupportedByDaemon:"Støttes ikke ennå av daemonen",discoveryUnsupportedFormat:"Modelloppdagelse støttes ikke ennå for dette leverandørformatet. Legg til modeller manuelt."},HI={subtitle:"Kontrollpanel",providers:"Leverandører",apiService:"API-tjeneste",accounts:"Kontoer",codeCli:"Kode-CLI",settings:"Innstillinger",usageStats:"Bruk",pricing:"Priser"},FI={title:"API-tjeneste",description:"Konfigurer den utgående API-serveren, modellruting per endepunkt og navngitte tilgangsnøkler.",loading:"Laster serverkonfigurasjon…",loadError:"Kunne ikke laste serverkonfigurasjonen. Kontroller at daemonen er nåbar.",enable:{label:"Aktiver utgående server",description:"Start den lokale API-serveren som ruter eksterne anrop gjennom leverandørene dine."},networkBinding:{label:"Tillat LAN-tilgang",description:"Bind serveren til nettverksgrensesnittet ditt i stedet for kun loopback.",warning:"LAN-tilgang eksponerer API-serveren for andre enheter i nettverket ditt. Kombinert med abonnementsruting kan forespørsler forbruke abonnementskvoten din — hold dette av med mindre du stoler på nettverket."},status:{running:"Server kjører",stopped:"Server stoppet",runningHint:"Den utgående API-serveren tar imot forespørsler.",stoppedHint:"Aktiver serveren for å begynne å ta imot forespørsler.",port:"port {{port}}",loopback:"Loopback-URL-er",lan:"LAN-URL-er"},endpoints:{title:"Endepunktruting",description:"Velg modellen hvert trådformat rutes til. Standardmodellen inngår her — serveren er en ruter, ikke en chat-app."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Standardmodell",backgroundModel:"Bakgrunnsmodell",visionModel:"Visjonsmodell",noVisionModel:"Ingen",backgroundModelIds:"Bakgrunnsmodell-ID-er",backgroundModelIdsPlaceholder:"kommaseparerte modell-ID-er",modelPlaceholder:"Velg en modell…",useSubscription:"Bruk abonnement",subscriptionUnsupported:"Abonnementsruting er ikke tilgjengelig for dette endepunktet."},keys:{title:"Tilgangsnøkler",description:"Navngitte nøkler som eksterne anropere sender som en Bearer-token. Den fullstendige nøkkelen vises bare én gang ved opprettelse.",namePlaceholder:"Nøkkelnavn (f.eks. mitt-cli)",create:"Opprett nøkkel",empty:"Ingen tilgangsnøkler ennå.",enabled:"Aktivert",disabled:"Deaktivert",revoked:"Tilbakekalt",toggle:"Slå av/på nøkkel",revoke:"Tilbakekall",revokeConfirmTitle:"Tilbakekalle denne nøkkelen?",revokeConfirmDesc:'Tilbakekalling av "{{name}}" stopper umiddelbart autentisering. Dette kan ikke angres.',created:{title:"Nøkkel opprettet",warning:"Kopier denne nøkkelen nå — den vil ikke vises igjen. Oppbevar den trygt.",copy:"Kopier",copied:"Kopiert",dismiss:"Ferdig"}}},BI={title:"Kontoer og abonnementer",description:"Administrer abonnementslegitimasjonen serveren ruter gjennom. Tokens skrives her, men vises aldri tilbake.",loading:"Laster kontoer…",empty:"Ingen abonnementsleverandører er tilgjengelige.",signIn:"Logg inn",oauth:{title:"Logg inn på {{name}}",description:"Åpne innloggingssiden i nettleseren din, autoriser, og lim deretter inn autorisasjonskoden nedenfor. Koden sendes kun til daemonen — det pregede tokenet vises aldri.",openPage:"Åpne innloggingsside",codeLabel:"Autorisasjonskode",codePlaceholder:"Lim inn koden her",submit:"Fullfør innlogging"},codexOauth:{title:"Logg inn på {{name}}",description:"Åpne innloggingssiden i nettleseren din og autoriser. Daemonen fanger opp resultatet automatisk — hold denne åpen til det er fullført. Tokenet vises aldri.",waiting:"Venter på at du fullfører innloggingen i nettleseren din…",failed:"Innlogging mislyktes. Prøv igjen."},clearProvider:"Fjern alle",clearConfirmTitle:"Fjern {{name}}-kontoer?",clearConfirmDesc:"Dette fjerner alle lagrede legitimasjoner for denne leverandøren. Dette kan ikke angres.",credential:{ok:"Konfigurert",notConfigured:"Ikke konfigurert"},kind:{"pass-through":"Gjennomstrømningslegitimasjon","oauth-bearer":"OAuth bearer","static-bearer":"Statisk bearer-nøkkel"},reason:{"missing-credential":"Ingen legitimasjon lagret.",expired:"Legitimasjonen har utløpt.","reauth-required":"Re-autentisering kreves.","refresh-failed":"Tokenoppdatering mislyktes.","not-refreshable":"Legitimasjonen kan ikke oppdateres.",unknown:"Status ukjent."},status:{unconfigured:"Ukonfigurert",authorized:"Autorisert",configured:"Konfigurert",expired:"Utløpt",error:"Feil"},authMethod:{oauth:"OAuth",setup_token:"Oppsetttoken",manual:"Manuell"},list:{empty:"Ingen kontoer lagret for denne leverandøren.",active:"Aktiv",expiresAt:"Utløper {{value}}",setActive:"Angi som aktiv",remove:"Fjern",removeConfirmTitle:"Fjerne denne kontoen?",removeConfirmDesc:'Fjerning av "{{name}}" sletter den lagrede legitimasjonen. Dette kan ikke angres.',title:"Kontoer"},write:{trigger:"Legg til legitimasjon",title:"Skriv {{name}}-legitimasjon",description:"Lim inn allerede innhentet tokenmateriale. Feltene er begrenset til hva denne leverandøren aksepterer; tokenet lagres, vises aldri tilbake.",authMethod:"Autentiseringsmetode",status:"Status",subscriptionLevel:"Abonnementsnivå",subscriptionLevelNone:"Ikke angitt",submit:"Lagre legitimasjon"},field:{accessToken:"Tilgangstoken",refreshToken:"Oppdateringstoken",idToken:"ID-token",apiKey:"API-nøkkel",expiresAt:"Utløper (ISO)",setupTokenExpiresAt:"Oppsetttoken utløper (ISO)",accountId:"Konto-ID",email:"E-post",organizationId:"Organisasjons-ID",baseUrl:"Basis-URL",zenBaseUrl:"Zen basis-URL"},provider:{claude:{title:"Claude",description:"Anthropic-abonnementslegitimasjon rutet av daemonen."},codex:{title:"Codex",description:"OpenAI Codex-abonnementslegitimasjon rutet av daemonen."},gemini:{title:"Gemini",description:"Google Gemini-abonnementslegitimasjon rutet av daemonen."},opencodego:{title:"OpenCodeGo",description:"Statisk API-nøkkellegitimasjon rutet av daemonen."}},authMethodLabel:"Autorisasjonsmetode",authMethodDesc:{oauth:"Logg inn via nettleseren; daemonen fanger opp og lagrer tokenet.",manual:"Lim inn et allerede innhentet token. Det lagres, vises aldri tilbake."},actions:{authorize:"Autoriser",enterToken:"Skriv inn token",refresh:"Oppdater"},accounts:{addAccount:"Legg til konto"},detail:{authMethod:"Autorisasjonsmetode",subscriptionLevel:"Abonnementsnivå",expiresAt:"Utløper",lastRefreshed:"Sist oppdatert",label:"Kontoetikett",labelPlaceholder:"Gi denne kontoen et navn",saveLabel:"Lagre etikett"},oauthFlow:{step1:{title:"Åpne autorisasjonssiden",desc:"Åpne innloggingssiden i nettleseren din."},step2:{title:"Autoriser tilgang",desc:"Logg inn og godkjenn tilgang for leverandøren."},step3:{title:"Kopier autorisasjonskoden",desc:"Siden viser en autorisasjonskode etter at du godkjenner."},step4:{title:"Lim inn koden",desc:"Lim inn autorisasjonskoden nedenfor for å fullføre. Koden sendes kun til daemonen — det pregede tokenet vises aldri."},authorize:"Fullfør innlogging",showUrl:"Vis autorisasjons-URL"},manual:{title:"Lim inn legitimasjon",description:"Lim inn et allerede innhentet token. Feltene er begrenset til hva denne leverandøren aksepterer; tokenet lagres, vises aldri tilbake.",accessTokenPlaceholder:"Lim inn tilgangstokenet",refreshTokenPlaceholder:"Lim inn oppdateringstokenet (valgfritt)",hint:"Tokenet sendes til daemonen og lagres kryptert. Det vises aldri tilbake."},openCodeGo:{apiKeyRequired:"En API-nøkkel er påkrevd.",apiKeyPlaceholder:"Lim inn API-nøkkelen",baseUrlPlaceholder:"https://… (valgfritt)",zenBaseUrlPlaceholder:"https://… (valgfritt)"},info:{title:"Om abonnementskontoer",description:"Tokens skrives til daemonen og brukes til å autentisere oppstrømsforespørsler. De lagres kryptert og vises aldri tilbake. Fjerning av en konto sletter den lagrede legitimasjonen."},rename:{failed:"Kunne ikke gi nytt navn til kontoen."},refresh:{failed:"Kunne ikke oppdatere tokenet."},errors:{requestFailed:"Forespørselen mislyktes. Prøv igjen."},syncWarning:{"external-divergent":"Den eksterne CLI-påloggingsfilen inneholder nyere legitimasjon enn denne kontoen. Det lagrede tokenet kan slutte å fornyes — forny nå eller logg inn på nytt.","external-not-rotated":"Fornyelsen mislyktes, og den eksterne CLI-en inneholder den samme utløpte legitimasjonen. Logg inn på nytt.","duplicate-token":"En annen konto deler denne legitimasjonen. Fornyelse av den ene logger den andre ut."},importExternal:{detected:"En eksisterende {{name}}-CLI-pålogging ble funnet på denne maskinen.",hint:"Etter importen holder denne appen den oppdatert: ved hver tokenfornyelse oppdateres også CLI-påloggingsfilen, slik at CLI-en i terminalen forblir pålogget.",button:"Importer eksisterende CLI-pålogging"}},VI={title:"Kode-CLI",description:"Pek et kodnings-CLI mot daemonens utgående proxy. Denne siden er skrivebeskyttet — det er ingenting å konfigurere her.",copy:"Kopier",copied:"Kopiert",baseUrl:{title:"Daemonens basis-URL",description:"Proxyadressen CLI-et ditt kobler til.",label:"Basis-URL"},token:{title:"Autentisering",hint:"Send 'Authorization: Bearer <din-admin-token>' for adminruter. Admin-tokenet konfigureres i daemonen (konfigurasjonsfilen eller miljøet) — det vises aldri her."},examples:{title:"Eksempel på startmiljø",keyNote:"Bruk en utgående tilgangsnøkkel opprettet på API-tjenestesiden — ikke admin-tokenet.",anthropic:"Anthropic-format CLI",openai:"OpenAI-format CLI"},launchDescription:"Start et kodnings-CLI i en terminal, pekt mot denne daemonen. Daemonen injiserer omdirigeringsmiljøet og starter CLI-et for deg.",refresh:"Oppdater",loading:"Oppdager CLI-er…",cli:{installed:"Installert",notFound:"Ikke funnet",notFoundHint:"Dette CLI-et finnes ikke i daemonvertens PATH. Installer det, og oppdater deretter.",install:"Installer",installing:"Installerer…",installingHint:"Installerer på daemonverten — dette kan ta et minutt.",launch:"Start",launchTitle:"Start {{name}}",launchDescription:"Åpner en ny terminal på daemonverten som kjører dette CLI-et, rutet gjennom daemonproxyen. Velg en valgfri arbeidsmappe.",cwdLabel:"Arbeidsmappe",cwdPlaceholder:"/sti/til/prosjektet/ditt",runningVia:"Kjører · {{provider}} / {{model}}",stop:"Stopp"},manual:{title:"Manuelt oppsett",description:"Foretrekker du å kjøre CLI-et selv? Pek det mot daemonen med disse miljøvariablene.",show:"Vis",hide:"Skjul"}},qI={probing:"Søker etter daemonen…",spawning:"Starter daemonen…",failed:"Daemonen kunne ikke starte",failedHint:"Kontroller at Node.js er installert og at daemonen er bygget (dist til stede), eller angi OMNICROSS_DAEMON_ENTRY til daemonens cli.js."},$I={title:"Innstillinger",description:"Preferanser for skrivebordsprogrammet.",desktopOnly:"Start- og systemstatusfeltalternativer gjelder bare i skrivebordsprogrammet.",startup:{title:"Oppstart",autoLaunch:"Start ved innlogging",autoLaunchHint:"Start Omnicross automatisk når du logger inn.",startMinimized:"Start minimert til systemstatusfeltet",startMinimizedHint:"Start i bakgrunnen uten å åpne vinduet."},tray:{title:"Systemstatusfelt",minimizeOnClose:"Minimer til systemstatusfeltet ved lukking",minimizeOnCloseHint:"Lukking av vinduet skjuler det i systemstatusfeltet i stedet for å avslutte."},language:{title:"Språk",label:"Grensesnittspråk"}},_I={title:"Bruksstatistikk",description:"Token- og kostnadsstatistikk for forespørsler håndtert av daemonen.",rangeToday:"I dag",range7d:"Siste 7 dager",range30d:"Siste 30 dager",rangeCustom:"Egendefinert",from:"Fra",to:"Til",totalCost:"Total kostnad",cacheSavings:"Cache-besparelse",events:"Forespørsler",inputTokens:"Inndata-token",outputTokens:"Utdata-token",cacheReadTokens:"Cache-lesing",cacheWriteTokens:"Cache-skriving",reasoningTokens:"Resonnering-token",byModel:"Per modell",byApiKey:"Per API-nøkkel",provider:"Leverandør",model:"Modell",cost:"Kostnad",apiKey:"API-nøkkel",unpriced:"Uten pris",unpricedHint:"Det finnes ingen prisoppføring for denne modellen — legg til en på Priser-siden.",unattributed:"Ikke tilordnet",unattributedHint:"Forespørsler som ikke er knyttet til en bestemt API-nøkkel. Dette er forventet til tilordning per nøkkel registreres.",empty:"Ingen forespørsler i dette intervallet.",invalidRange:"Velg et gyldig datointervall."},GI={title:"Modellpriser",description:"Tokenpriser per modell for kostnadsberegning, i USD per million token.",search:"Søk etter leverandør eller modell…",fetchLatest:"Hent siste",fetching:"Henter…",addEntry:"Legg til oppføring",provider:"Leverandør",model:"Modell",inputPrice:"Inndata",outputPrice:"Utdata",cacheReadPrice:"Cache-lesing",cacheWritePrice:"Cache-skriving",source:"Kilde",updated:"Oppdatert",userEdited:"redigert",edit:"Rediger",deleteTitle:"Slette prisoppføringen?",empty:"Pristabellen er tom.",emptyHint:"Hent de nyeste prisene for å fylle den.",noMatches:"Ingen oppføringer samsvarer med søket.",saved:"Prisoppføring lagret.",saveFailed:"Lagring mislyktes: {{message}}",deleteFailed:"Sletting mislyktes: {{message}}",alreadyDeleted:"Oppføringen fantes ikke lenger.",fetchApplied:"{{count}} oppføringer oppdatert fra kilden.",fetchFailed:"Henting mislyktes: {{message}}",requiredId:"Påkrevd",invalidPrice:"Angi et ikke-negativt tall",conflictTitle:"Løs priskonflikter",conflictHint:"Disse oppføringene er redigert av deg og har også endret seg i kilden. Velg per rad om du vil beholde din verdi (Hopp over) eller ta den innkommende (Overskriv).",current:"Gjeldende",incoming:"Innkommende",overwrite:"Overskriv",skip:"Hopp over",overwriteAll:"Overskriv alle",skipAll:"Hopp over alle",applyResolutions:"Bruk",resolved:"{{overwritten}} overskrevet, {{skipped}} hoppet over.",resolvedWithStale:"{{overwritten}} overskrevet, {{skipped}} hoppet over. {{stale}} ble endret i mellomtiden og forble urørt.",refreshFailed:"Endringen ble tatt i bruk, men kunne ikke laste listen på nytt: {{message}}",sourceBuiltin:"Innebygd",sourceLitellm:"LiteLLM",sourceUser:"Bruker"},WI={providerSettings:RI,apiMode:DI,presetName:EI,common:OI,mediaSettings:KI,appLocal:UI,nav:HI,apiService:FI,accounts:BI,codeCli:VI,daemonStatus:qI,settings:$I,usageStats:_I,pricing:GI},ZI={loading:"LLM-configuratie laden...",reset:{button:"Standaardwaarden herstellen",confirmTitle:"Standaardinstellingen herstellen?",confirmBody:"Dit verwijdert uw aanpassingen voor deze provider, zodat hij de ingebouwde standaardwaarden weer volgt. Uw API-sleutel en opgeslagen sessies blijven bewaard.",confirmButton:"Standaardwaarden herstellen"},reentryBanner:{message:"{{count}} actieve provider(s) hebben hun API-sleutel opnieuw nodig. Open elk item en voeg de sleutel opnieuw toe."},migrationPack:{barHint:"Verplaats uw providersleutels en abonnementstokens naar een andere machine met een versleuteld pakket.",passphrase:"Wachtwoordzin",passphrasePlaceholder:"Voer een wachtwoordzin in",passphraseHint:"Gebruik minimaal 8 tekens; 12 of meer wordt aanbevolen.",confirm:"Wachtwoordzin bevestigen",confirmPlaceholder:"Voer de wachtwoordzin opnieuw in",mismatch:"Wachtwoordzinnen komen niet overeen.",strength:{weak:"Te kort — gebruik minimaal 8 tekens.",fair:"Redelijk — 12 of meer tekens is sterker.",strong:"Sterke wachtwoordzin."},export:{button:"Pakket exporteren",title:"Versleuteld pakket exporteren",subtitle:"Versleutel uw providersleutels en abonnementstokens in een overdraagbaar bestand.",warning:"Dit bestand bevat ontsleutelbare geheimen. Bewaar het veilig — iedereen met het bestand en de wachtwoordzin kan uw sleutels lezen. Een verloren wachtwoordzin kan niet worden hersteld.",submit:"Exporteren",success:"Pakket succesvol geëxporteerd.",error:"Export mislukt. Probeer het opnieuw."},import:{button:"Pakket importeren",title:"Versleuteld pakket importeren",subtitle:"Herstel providersleutels en abonnementstokens uit een geëxporteerd pakket.",hint:"Voer de wachtwoordzin in die bij het exporteren is gebruikt en kies het bestand.",submit:"Importeren",successTitle:"Import voltooid",summary:"{{providerKeys}} providersleutel(s), {{poolKeys}} poolsleutel(s) en {{tokenSets}} tokenset(s) geïmporteerd.",duplicates:"{{count}} poolsleutel(s) overgeslagen die al aanwezig waren.",skipped:"Overgeslagen (geen overeenkomende provider): {{names}}",error:"Verkeerde wachtwoordzin of beschadigd pakket. Er is niets gewijzigd."}},searchPlaceholder:"Providers zoeken...",emptySearch:"Geen providers komen overeen met uw zoekopdracht.",emptyList:"Geen providers geconfigureerd.",selectPrompt:"Selecteer een provider om details te bekijken",listStatus:"{{count}} model(len)",noModels:"Geen modellen geconfigureerd",enabled:"Ingeschakeld",disabled:"Uitgeschakeld",showEnabledOnly:"Alleen ingeschakelde tonen",showAll:"Alle providers tonen",dragHandle:"Slepen om te herordenen",reorderFailed:"Volgorde van providers opslaan mislukt",credentials:{apiKey:"API-sleutel",apiBaseUrl:"Basis-URL van API"},filter:{all:"Alle",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Selecteer een sjabloon",skipTemplates:"Overslaan, handmatig configureren",name:"Naam *",providerType:"Type",apiType:"API-type",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standaard OpenAI chat/completions API-formaat",claudecode:"Anthropic Messages API-formaat (Claude Code)"},chatApiFormat:"API-formaat",chatApiFormatDescription:"Selecteer het API-formaat dat overeenkomt met het endpoint van uw provider",apiKey:"API-sleutel",apiKeyPlaceholder:"sk-... of $ENV_VAR",apiKeyHelper:"Gebruik $VAR_NAAM om naar omgevingsvariabelen te verwijzen",apiKeySetPlaceholder:"Sleutel is ingesteld — laat leeg om te bewaren",apiKeyReplaceHelper:"Er is een sleutel veilig opgeslagen. Typ een nieuwe waarde om hem te vervangen of laat leeg om te bewaren.",testApiKey:"API-sleutel testen",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Voorbeeld:",models:"Modellen",modelPlaceholder:"Modelnaam (bijv. gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API-transformers",transformerConfigDescription:"Configureer transformers om API-aanvraag-/responsformaten aan te passen voor deze provider",transformerConfigNote:"De daemon past deze transformers toe in de aanvraagketen, na de formaattransformer van de provider (die de wire-formaatconversie afhandelt). Onbekende transformernamen worden overgeslagen.",enabled:"Ingeschakeld",apiVersion:"API-versie",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API-versie (bijv. 2024-08-01-preview)",official:"Officiële Anthropic API",officialHelper:"Inschakelen als deze provider rechtstreeks verbinding maakt met de officiële Anthropic API. Uitschakelen voor reverse proxies of diensten van derden.",maxConcurrency:"Max. gelijktijdige aanvragen",maxConcurrencyHelper:"Maximaal aantal gelijktijdige API-aanvragen naar deze provider. Lagere waarden helpen tariefbeperking (429-fouten) te voorkomen. Stel `-1` in voor geen limiet.",codingPlan:{label:"Codeerplan",description:"Gebruik een apart API-endpoint voor op abonnement gebaseerde codeerplannen",baseUrl:"Basis-URL van codeerplan",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"API-sleutel van codeerplan (optioneel)",apiKeyPlaceholder:"Leeg laten om API-sleutel van provider te gebruiken",apiKeyHelper:"Alleen vereist als het codeerplan een andere API-sleutel gebruikt",tokenPlanHint:"Sommige providers (bijv. Xiaomi MiMo) geven Token Plan-sleutels uit met een `tp-`-voorvoegsel — alleen informatief, niet afgedwongen."},selectTypeFirst:"Selecteer providertype",selectTypeFirstDesc:"Kies welk type provider u wilt toevoegen",codeProviderNote:"Codeproviders hebben alleen een API-sleutel en URL nodig. Modellen worden beheerd door de Agent Router.",buttons:{cancel:"Annuleren",submitAdd:"Provider toevoegen",submitUpdate:"Provider bijwerken",continue:"Doorgaan",back:"Terug"}},details:{noSelection:"Selecteer een provider om details te bekijken",apiKey:"API-sleutel",apiUrl:"API-URL",nameLabel:"Providernaam",modelsEndpoint:"Modellen-endpoint",modelsEndpointHelper:"Overschrijf het discovery-endpoint als de provider een aangepast /models-pad blootstelt.",models:"Modellen",transformers:"Transformers",codeProviderNote:"Codeproviders (zoals Claude Code) hebben geen modelconfiguratie nodig. Modellen worden automatisch beheerd door de Agent Router.",buttons:{more:"Meer instellingen",delete:"Verwijderen"}},providerModelSelector:{placeholder:"Selecteer provider en model",noProviders:"Geen providers beschikbaar",noModels:"Geen modellen geconfigureerd"},apiKeyPool:{title:"API-sleutelpool",description:"Configureer meerdere API-sleutels voor taakverdeling. Elke sessie gebruikt één sleutel om de promptcache te bewaren.",defaultLabel:"Standaard",weight:"Gewicht",noKey:"Geen sleutel",labelPlaceholder:"Label (bijv. Sleutel #1, Productie)",addKey:"API-sleutel toevoegen",add:"Toevoegen",empty:"Geen extra sleutels geconfigureerd.",statusCoolingDown:"Afkoelen {{time}}",statusAuthFailed:"Authenticatie mislukt · uitgeschakeld",statusDisabled:"Uitgeschakeld",statusHealthy:"Gezond",agoSeconds:"{{count}}s geleden",agoMinutes:"{{count}}m geleden",agoHours:"{{count}}u geleden",agoDays:"{{count}}d geleden"},modelsManager:{searchPlaceholder:"Modellen zoeken...",defaultGroup:"Alle modellen",add:"Model toevoegen",manage:"Beheren",empty:"Geen modellen in deze groep",enabled:"Ingeschakeld",disabled:"Uitgeschakeld",filters:{all:"Alle",vision:"Visie",reasoning:"Redeneren",free:"Gratis",tools:"Tools"},manualDialog:{title:"Model toevoegen",subtitle:"Een aangepast model toevoegen aan deze provider",modelId:"Model-ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, enz.",modelIdHelper:"De exacte modelidentificatie die wordt gebruikt bij het aanroepen van de API",modelName:"Weergavenaam",modelNamePlaceholder:"Gebruiksvriendelijke weergavenaam (optioneel)",modelNameHelper:"Optionele naam weergegeven in de interface. Als leeg, wordt Model-ID gebruikt",group:"Groep",groupPlaceholder:"Selecteer of voer een groepsnaam in",submit:"Toevoegen",cancel:"Annuleren",helper:"Geef de exacte modelidentificatie op die door de provider-API wordt blootgesteld."},editDialog:{title:"Model bewerken",subtitle:"Modelinstellingen aanpassen",modelId:"Model-ID",modelIdPlaceholder:"Modelidentificatie",modelIdHelper:"De modelidentificatie die wordt gebruikt bij het aanroepen van de API",modelName:"Weergavenaam",modelNamePlaceholder:"Gebruiksvriendelijke weergavenaam",modelNameHelper:"Naam weergegeven in de interface",group:"Groep",groupPlaceholder:"Selecteer of voer een groepsnaam in",submit:"Opslaan",cancel:"Annuleren",vision:"Visiecapaciteit",visionHint:"Of dit model afbeeldings-/visie-invoer ondersteunt",reasoning:"Redeneermodel",reasoningHint:"Of dit model denk-/redeneermodus ondersteunt"},manageDialog:{title:"Modellen beheren",cachedAt:"Gecached op {{date}} ({{source}})",refresh:"Vernieuwen",close:"Sluiten",raw:"Ruwe JSON",empty:"Geen externe modellen beschikbaar.",error:"Modellen laden mislukt: {{message}}",addFromCatalog:"Toevoegen",sourceCache:"cache",sourceNetwork:"live",contextLength:"Context {{value}} tokens",maxTokens:"Max. {{value}} tokens"},messages:{added:"Model toegevoegd.",updated:"Model bijgewerkt.",removed:"Model verwijderd.",duplicate:"Model bestaat al.",refreshed:"Modellen vernieuwd",refreshFailed:"Modellen vernieuwen mislukt"},testDialog:{title:"Connectiviteitstest model",provider:"Provider",model:"Model",testing:"Testen...",success:"Test geslaagd",successMessage:"Model is normaal toegankelijk",failure:"Test mislukt",aiResponse:"AI-antwoord",charCount:"{{count}} tekens",duration:"Duur {{time}}s",close:"Sluiten",retest:"Opnieuw testen",testButton:"Model testen",unsupportedFormat:"Testen wordt nog niet ondersteund voor dit providerformaat."}},router:{title:"Routerconfiguratie",description:"Configureer welke provider/welk model voor verschillende scenario's wordt gebruikt.",labels:{default:"Standaard",background:"achtergrond",think:"denken",longContext:"Lange context",webSearch:"Webzoeken",image:"Afbeelding",longContextThreshold:"Drempel lange context"},helper:{longContextThreshold:"Aantal tokens voordat er wordt overgeschakeld naar het lange-contextmodel."},placeholder:{required:"Vereist",optional:"Optioneel"}},agentRouter:{title:"Agent Router",description:"Configureer bidirectionele routering tussen Chat- en Codemodus.",searchPlaceholder:"Routers zoeken...",noSearchResults:"Geen routers komen overeen met uw zoekopdracht.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Chat-naar-Code-router",description:"Chatproviders gebruiken in agent-/coderingsmodus",addRouter:"Router toevoegen",emptyState:"Geen Chat→Code-routers geconfigureerd. Voeg er een toe om chatproviders in coderingsmodus te gebruiken.",form:{name:"Routernaam",namePlaceholder:"Mijn Chat→Code-router",chatProvider:"Chatprovider",chatProviderPlaceholder:"Selecteer een chatprovider",mode:"Modus",modeSimple:"Eenvoudig",modeAdvanced:"Geavanceerd",modeSimpleDesc:"Directe doorvoer naar chatprovider",modeAdvancedDesc:"Modeltoewijzing en contextverwerking configureren",enabled:"Ingeschakeld",save:"Router opslaan",cancel:"Annuleren"},list:{provider:"Provider",mode:"Modus",status:"Status"},mappings:{title:"Modeltoewijzingen",description:"Chatprovidermodellen toewijzen aan codeprovidermodellen",count:"toewijzing(en)",empty:"Geen modeltoewijzingen geconfigureerd. Voeg toewijzingen toe om chatmodellen naar codeproviders te routeren.",addNew:"Nieuwe toewijzing toevoegen",selectSource:"Bronmodel selecteren (Chat)",selectTarget:"Doelmodel selecteren (Code)",targetPlaceholder:"Claude Code-modelnaam invoeren",notSet:"(Niet ingesteld — klik om te selecteren)",add:"Toevoegen",edit:"Bewerken",done:"Klaar"},advanced:{title:"Geavanceerde configuratie",description:"Modellen configureren voor verschillende taaktypen",helpText:"Standaardmodel is vereist. Andere modellen zijn optioneel en vallen terug op standaard als niet geconfigureerd.",default:{label:"Standaard",placeholder:"Standaardmodel selecteren",description:"Primair model voor algemene taken (vergelijkbaar met Claude Sonnet)"},background:{label:"Achtergrond",placeholder:"Achtergrondmodel selecteren",description:"Lichtgewicht model voor achtergrondtaken (vergelijkbaar met Claude Haiku)"},think:{label:"Denken",placeholder:"Denkmodel selecteren",description:"Geavanceerd model voor complexe redenering (vergelijkbaar met Claude Opus)"},image:{label:"Afbeelding",placeholder:"Afbeeldingsmodel selecteren",description:"Model voor afbeeldingsgerelateerde taken met visiecapaciteit"}}},codeToChat:{title:"Code-naar-Chat-router",description:"Codeerplanmodellen blootstellen in chatmodus",addRouter:"Router toevoegen",emptyState:"Geen Code→Chat-routers geconfigureerd. Voeg er een toe om codeerplanmodellen in chatmodus bloot te stellen.",form:{name:"Routernaam",namePlaceholder:"Mijn Code→Chat-router",codeProvider:"Codeprovider",codeProviderPlaceholder:"Selecteer een codeprovider",codeProviderHelper:"Selecteer de codeprovider voor transformatie",models:"Codeerplanmodellen",modelsHelper:"Selecteer welke codeerplanmodellen worden blootgesteld",enabled:"Ingeschakeld",save:"Router opslaan",cancel:"Annuleren"},mappings:{title:"Modeltoewijzingen",description:"Codeprovidermodellen toewijzen aan chatprovidermodellen voor blootstelling",count:"toewijzing(en)",empty:"Geen modeltoewijzingen geconfigureerd. Voeg toewijzingen toe om codemodellen in chatmodus bloot te stellen.",addNew:"Nieuwe toewijzing toevoegen",selectSource:"Bronmodel selecteren (Code)",selectTarget:"Doelmodel selecteren (Chat)",sourcePlaceholder:"Bronmodelnaam invoeren",targetPlaceholder:"Doelmodelnaam invoeren",add:"Toevoegen",edit:"Bewerken",done:"Klaar"}},transformers:{title:"Transformers",description:"Transformers configureren voor aanvraag-/responsconversie",noProvider:"Selecteer een provider om transformers te configureren",empty:"Geen transformers",count:"{{count}} transformer(s)"},status:{enabled:"Ingeschakeld",disabled:"Uitgeschakeld"},messages:{routerAdded:"Router succesvol toegevoegd",routerUpdated:"Router succesvol bijgewerkt",routerDeleted:"Router succesvol verwijderd",saveFailed:"Router opslaan mislukt"}},presets:{title:"Provider snel toevoegen",added:"Toegevoegd",add:"Toevoegen",features:{search:"Zoeken",vision:"Visie",mcp:"MCP",codingPlan:"Codeerplan"}},alerts:{deleteConfirm:"Weet u zeker dat u deze provider wilt verwijderen?"},errors:{nameRequired:"Providernaam is vereist",urlRequired:"Basis-URL van API is vereist",urlInvalid:"Voer een geldige URL in (bijv. https://api.example.com)",saveFailed:"Provider opslaan mislukt",deleteFailed:"Fout bij verwijderen van provider. Probeer het opnieuw.",toggleFailed:"Fout bij in-/uitschakelen van provider. Probeer het opnieuw."},openRouter:{title:"OpenRouter-providerroutering",description:"Configureer hoe aanvragen worden gerouteerd naar verschillende providers op OpenRouter.",sort:"Routeringsstrategie",sortTooltip:"Kies hoe providers worden geprioriteerd. Automatisch gebruikt intelligente taakverdeling.",order:"Volgorde van providerprioriteit",orderTooltip:"Geef providers op die in volgorde worden geprobeerd (bijv. anthropic, openai, together). Druk op Enter om toe te voegen.",orderPlaceholder:"Typ de provider-slug en druk op Enter...",allowFallbacks:"Fallbacks toestaan",allowFallbacksTooltip:"Wanneer ingeschakeld, probeert OpenRouter reserveproviders als de primaire niet beschikbaar is.",requireParameters:"Alle parameters vereisen",requireParametersTooltip:"Alleen routeren naar providers die alle parameters in uw aanvraag ondersteunen.",dataCollection:"Beleid gegevensverzameling",dataCollectionTooltip:"Bepaal of providers worden gebruikt die uw gegevens mogelijk opslaan of hierop trainen.",zdr:"Nul gegevensbewaring",zdrTooltip:"Alleen routeren naar endpoints met beleid voor nul gegevensbewaring.",only:"Alleen providers toestaan",onlyTooltip:"Gebruik alleen deze specifieke providers. Laat leeg om alle providers toe te staan.",onlyPlaceholder:"Typ de provider-slug en druk op Enter...",ignore:"Providers negeren",ignoreTooltip:"Sla deze providers over bij het routeren van aanvragen.",ignorePlaceholder:"Typ de provider-slug en druk op Enter...",quantizations:"Kwantisatiefilter",quantizationsTooltip:"Gebruik alleen providers met specifieke kwantisatieniveaus. Lagere precisie kan de kwaliteit verminderen maar de snelheid verbeteren.",maxPrice:"Maximumprijs",maxPriceTooltip:"Stel maximale prijslimieten per miljoen tokens in. Laat leeg voor geen limiet.",configured:"Geconfigureerd"}},QI={label:"API-modus",standard:"Standaard",codingPlan:"Codeerplan",tokenPlan:"Tokenplan",apiKeyPrefixHint:"Sleutels voor dit plan beginnen doorgaans met `{{prefix}}`. Alleen indicatief — niet afgedwongen.",dashscopeCodingPlanSeparateKey:"DashScope Codeerplan gebruikt een aparte API-sleutel van het standaard-endpoint.",baiduCodingPlanSeparateKey:"Qianfan Codeerplan gebruikt een aparte API-sleutel van het standaard-endpoint.",tencentTokenPlanAnthropicOnly:"Tencent Tokenplan is alleen Anthropic-protocol.",xiaomiTokenPlanRegions:"Standaard baseUrl is `token-plan-cn.*`. U kunt het handmatig bewerken naar `token-plan-sgp.*` of `token-plan-ams.*`.",confirmOverwriteTitle:"API-modus wisselen?",confirmOverwriteBody:"U heeft de API-URL of API-sleutel aangepast. Wisselen van modus overschrijft ze met de standaardwaarden van de nieuwe modus — of bewaar uw aanpassingen en update alleen het modusLabel.",overwriteAndSwitch:"Overschrijven en wisselen",keepCustomizations:"Aanpassingen bewaren"},YI={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Tokenplan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},XI={cancel:"Annuleren",close:"Sluiten",copy:"Kopiëren",delete:"Verwijderen",dismiss:"Sluiten",save:"Opslaan",optional:"optioneel",retry:"Opnieuw proberen",loading:"Laden…"},JI={common:{learnMore:"Documentatie"}},eS={notSupportedByDaemon:"Nog niet ondersteund door de daemon",discoveryUnsupportedFormat:"Modeldetectie wordt nog niet ondersteund voor dit providerformaat. Voeg modellen handmatig toe."},tS={subtitle:"Configuratiescherm",providers:"Providers",apiService:"API-service",accounts:"Accounts",codeCli:"Code CLI",settings:"Instellingen",usageStats:"Gebruik",pricing:"Prijzen"},aS={title:"API-service",description:"Configureer de uitgaande API-server, modelroutering per endpoint en benoemde toegangssleutels.",loading:"Serverconfiguratie laden…",loadError:"Serverconfiguratie kon niet worden geladen. Controleer of de daemon bereikbaar is.",enable:{label:"Uitgaande server inschakelen",description:"De lokale API-server starten die externe aanroepen via uw providers routeert."},networkBinding:{label:"LAN-toegang toestaan",description:"De server binden aan uw netwerkinterface in plaats van alleen loopback.",warning:"LAN-toegang stelt de API-server bloot aan andere apparaten op uw netwerk. In combinatie met abonnementsroutering kunnen aanvragen uw abonnementsquotum verbruiken — schakel dit uit tenzij u het netwerk vertrouwt."},status:{running:"Server actief",stopped:"Server gestopt",runningHint:"De uitgaande API-server accepteert aanvragen.",stoppedHint:"Schakel de server in om aanvragen te accepteren.",port:"poort {{port}}",loopback:"Loopback-URL's",lan:"LAN-URL's"},endpoints:{title:"Endpointroutering",description:"Kies het model waarnaar elk wire-formaat routeert. Het standaardmodel wordt hier ingesteld — de server is een router, geen chatapplicatie."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Standaardmodel",backgroundModel:"Achtergrondmodel",visionModel:"Visiemodel",noVisionModel:"Geen",backgroundModelIds:"Achtergrondmodel-ID's",backgroundModelIdsPlaceholder:"door komma's gescheiden model-ID's",modelPlaceholder:"Selecteer een model…",useSubscription:"Abonnement gebruiken",subscriptionUnsupported:"Abonnementsroutering is niet beschikbaar voor dit endpoint."},keys:{title:"Toegangssleutels",description:"Benoemde sleutels die externe aanroepers als Bearer-token sturen. De volledige sleutel wordt slechts eenmaal getoond bij aanmaak.",namePlaceholder:"Sleutelnaam (bijv. mijn-cli)",create:"Sleutel aanmaken",empty:"Nog geen toegangssleutels.",enabled:"Ingeschakeld",disabled:"Uitgeschakeld",revoked:"Ingetrokken",toggle:"Sleutel in-/uitschakelen",revoke:"Intrekken",revokeConfirmTitle:"Deze sleutel intrekken?",revokeConfirmDesc:'Het intrekken van "{{name}}" stopt de authenticatie onmiddellijk. Dit kan niet ongedaan worden gemaakt.',created:{title:"Sleutel aangemaakt",warning:"Kopieer deze sleutel nu — hij wordt niet opnieuw getoond. Bewaar hem veilig.",copy:"Kopiëren",copied:"Gekopieerd",dismiss:"Klaar"}}},nS={title:"Accounts en abonnementen",description:"Beheer de abonnementsreferenties waardoorheen de server routeert. Tokens worden hier geschreven maar nooit teruggetoond.",loading:"Accounts laden…",empty:"Geen abonnementsproviders beschikbaar.",signIn:"Aanmelden",oauth:{title:"Aanmelden bij {{name}}",description:"Open de aanmeldingspagina in uw browser, autoriseer en plak de autorisatiecode hieronder. De code gaat alleen naar de daemon — het aangemaakte token wordt nooit getoond.",openPage:"Aanmeldingspagina openen",codeLabel:"Autorisatiecode",codePlaceholder:"Plak de code hier",submit:"Aanmelden voltooien"},codexOauth:{title:"Aanmelden bij {{name}}",description:"Open de aanmeldingspagina in uw browser en autoriseer. De daemon legt het resultaat automatisch vast — houd dit open tot het voltooid is. Het token wordt nooit getoond.",waiting:"Wachten tot u aanmelden in uw browser voltooit…",failed:"Aanmelden mislukt. Probeer het opnieuw."},clearProvider:"Alles wissen",clearConfirmTitle:"{{name}}-accounts wissen?",clearConfirmDesc:"Dit verwijdert alle opgeslagen referenties voor deze provider. Dit kan niet ongedaan worden gemaakt.",credential:{ok:"Geconfigureerd",notConfigured:"Niet geconfigureerd"},kind:{"pass-through":"Doorvoereferenties","oauth-bearer":"OAuth-bearer","static-bearer":"Statische bearer-sleutel"},reason:{"missing-credential":"Geen referentie opgeslagen.",expired:"Referentie verlopen.","reauth-required":"Herauthenticatie vereist.","refresh-failed":"Token vernieuwen mislukt.","not-refreshable":"Referentie kan niet worden vernieuwd.",unknown:"Status onbekend."},status:{unconfigured:"Niet geconfigureerd",authorized:"Geautoriseerd",configured:"Geconfigureerd",expired:"Verlopen",error:"Fout"},authMethod:{oauth:"OAuth",setup_token:"Installatietoken",manual:"Handmatig"},list:{empty:"Geen accounts opgeslagen voor deze provider.",active:"Actief",expiresAt:"Verloopt {{value}}",setActive:"Actief instellen",remove:"Verwijderen",removeConfirmTitle:"Dit account verwijderen?",removeConfirmDesc:'Het verwijderen van "{{name}}" verwijdert de opgeslagen referentie. Dit kan niet ongedaan worden gemaakt.',title:"Accounts"},write:{trigger:"Referentie toevoegen",title:"{{name}}-referentie schrijven",description:"Plak reeds verkregen tokenmateriaal. Velden zijn beperkt tot wat deze provider accepteert; het token wordt opgeslagen, nooit teruggetoond.",authMethod:"Authenticatiemethode",status:"Status",subscriptionLevel:"Abonnementsniveau",subscriptionLevelNone:"Niet ingesteld",submit:"Referentie opslaan"},field:{accessToken:"Toegangstoken",refreshToken:"Vernieuwingstoken",idToken:"ID-token",apiKey:"API-sleutel",expiresAt:"Verloopt op (ISO)",setupTokenExpiresAt:"Installatietoken verloopt op (ISO)",accountId:"Account-ID",email:"E-mailadres",organizationId:"Organisatie-ID",baseUrl:"Basis-URL",zenBaseUrl:"Zen basis-URL"},provider:{claude:{title:"Claude",description:"Anthropic-abonnementsreferenties gerouteerd door de daemon."},codex:{title:"Codex",description:"OpenAI Codex-abonnementsreferenties gerouteerd door de daemon."},gemini:{title:"Gemini",description:"Google Gemini-abonnementsreferenties gerouteerd door de daemon."},opencodego:{title:"OpenCodeGo",description:"Statische API-sleutelreferenties gerouteerd door de daemon."}},authMethodLabel:"Autorisatiemethode",authMethodDesc:{oauth:"Meld u aan via uw browser; de daemon legt het token vast en slaat het op.",manual:"Plak een reeds verkregen token. Het wordt opgeslagen, nooit teruggetoond."},actions:{authorize:"Autoriseren",enterToken:"Token invoeren",refresh:"Vernieuwen"},accounts:{addAccount:"Account toevoegen"},detail:{authMethod:"Autorisatiemethode",subscriptionLevel:"Abonnementsniveau",expiresAt:"Verloopt",lastRefreshed:"Laatst vernieuwd",label:"Accountlabel",labelPlaceholder:"Geef dit account een naam",saveLabel:"Label opslaan"},oauthFlow:{step1:{title:"De autorisatiepagina openen",desc:"Open de aanmeldingspagina in uw browser."},step2:{title:"Toegang autoriseren",desc:"Meld u aan en keur toegang goed voor de provider."},step3:{title:"De autorisatiecode kopiëren",desc:"De pagina toont een autorisatiecode nadat u goedkeuring geeft."},step4:{title:"De code plakken",desc:"Plak de autorisatiecode hieronder om te voltooien. De code gaat alleen naar de daemon — het aangemaakte token wordt nooit getoond."},authorize:"Aanmelden voltooien",showUrl:"Autorisatie-URL tonen"},manual:{title:"Referentie plakken",description:"Plak een reeds verkregen token. Velden zijn beperkt tot wat deze provider accepteert; het token wordt opgeslagen, nooit teruggetoond.",accessTokenPlaceholder:"Plak het toegangstoken",refreshTokenPlaceholder:"Plak het vernieuwingstoken (optioneel)",hint:"Het token wordt naar de daemon gestuurd en versleuteld opgeslagen. Het wordt nooit teruggetoond."},openCodeGo:{apiKeyRequired:"Een API-sleutel is vereist.",apiKeyPlaceholder:"Plak de API-sleutel",baseUrlPlaceholder:"https://… (optioneel)",zenBaseUrlPlaceholder:"https://… (optioneel)"},info:{title:"Over abonnementsaccounts",description:"Tokens worden naar de daemon geschreven en gebruikt om upstream-aanvragen te authenticeren. Ze worden versleuteld opgeslagen en nooit teruggetoond. Het verwijderen van een account verwijdert de opgeslagen referentie."},rename:{failed:"Account kon niet worden hernoemd."},refresh:{failed:"Token kon niet worden vernieuwd."},errors:{requestFailed:"Aanvraag mislukt. Probeer het opnieuw."},syncWarning:{"external-divergent":"Het externe CLI-aanmeldbestand bevat nieuwere referenties dan dit account. Het opgeslagen token kan mogelijk niet meer worden vernieuwd — vernieuw nu of meld u opnieuw aan.","external-not-rotated":"Vernieuwen is mislukt en de externe CLI bevat dezelfde verlopen referenties. Meld u opnieuw aan.","duplicate-token":"Een ander account deelt deze referenties. Het vernieuwen van het ene account meldt het andere af."},importExternal:{detected:"Er is een bestaande {{name}}-CLI-aanmelding gevonden op deze machine.",hint:"Na het importeren houdt deze app deze actueel: bij elke tokenvernieuwing wordt ook het CLI-aanmeldbestand bijgewerkt, zodat de CLI in de terminal aangemeld blijft.",button:"Bestaande CLI-aanmelding importeren"}},oS={title:"Code CLI",description:"Wijs een codeer-CLI naar de uitgaande proxy van de daemon. Deze pagina is alleen-lezen — er is niets te configureren.",copy:"Kopiëren",copied:"Gekopieerd",baseUrl:{title:"Daemon basis-URL",description:"Het proxyadres waarmee uw CLI verbinding maakt.",label:"Basis-URL"},token:{title:"Authenticatie",hint:"Stuur 'Authorization: Bearer <uw-beheertoken>' voor beheerdersroutes. Het beheertoken wordt geconfigureerd in de daemon (configuratiebestand of omgeving) — het wordt hier nooit getoond."},examples:{title:"Voorbeeldstartomgeving",keyNote:"Gebruik een uitgaande toegangssleutel die is aangemaakt op de API-servicepagina — niet het beheertoken.",anthropic:"Anthropic-formaat CLI",openai:"OpenAI-formaat CLI"},launchDescription:"Start een codeer-CLI in een terminal, gericht op deze daemon. De daemon injecteert de omleidingsomgeving en start de CLI voor u.",refresh:"Vernieuwen",loading:"CLI's detecteren…",cli:{installed:"Geïnstalleerd",notFound:"Niet gevonden",notFoundHint:"Deze CLI staat niet op het PATH van de daemonhost. Installeer het en vernieuw.",install:"Installeren",installing:"Installeren…",installingHint:"Installeren op de daemonhost — dit kan even duren.",launch:"Starten",launchTitle:"{{name}} starten",launchDescription:"Opent een nieuwe terminal op de daemonhost waarop deze CLI wordt uitgevoerd, gerouteerd via de daemonproxy. Kies een optionele werkmap.",cwdLabel:"Werkmap",cwdPlaceholder:"/pad/naar/uw/project",runningVia:"Actief · {{provider}} / {{model}}",stop:"Stoppen"},manual:{title:"Handmatige installatie",description:"Wilt u de CLI zelf uitvoeren? Wijs hem naar de daemon met deze omgevingsvariabelen.",show:"Tonen",hide:"Verbergen"}},iS={probing:"Daemon controleren…",spawning:"Daemon starten…",failed:"De daemon kon niet worden gestart",failedHint:"Zorg ervoor dat Node.js is geïnstalleerd en de daemon is gebouwd (dist aanwezig), of stel OMNICROSS_DAEMON_ENTRY in op de cli.js van de daemon."},rS={title:"Instellingen",description:"Voorkeuren voor desktopapplicatie.",desktopOnly:"Opstartopties en systeemvakopties zijn alleen van toepassing in de desktopapplicatie.",startup:{title:"Opstarten",autoLaunch:"Starten bij aanmelden",autoLaunchHint:"Omnicross automatisch starten wanneer u aanmeldt.",startMinimized:"Geminimaliseerd opstarten naar systeemvak",startMinimizedHint:"Starten op de achtergrond zonder het venster te openen."},tray:{title:"Systeemvak",minimizeOnClose:"Minimaliseren naar systeemvak bij sluiten",minimizeOnCloseHint:"Het venster sluiten verbergt het naar het systeemvak in plaats van af te sluiten."},language:{title:"Taal",label:"Interfacetaal"}},sS={title:"Gebruiksstatistieken",description:"Token- en kostenstatistieken van door de daemon afgehandelde verzoeken.",rangeToday:"Vandaag",range7d:"Laatste 7 dagen",range30d:"Laatste 30 dagen",rangeCustom:"Aangepast",from:"Van",to:"Tot",totalCost:"Totale kosten",cacheSavings:"Cachebesparing",events:"Verzoeken",inputTokens:"Invoertokens",outputTokens:"Uitvoertokens",cacheReadTokens:"Cache lezen",cacheWriteTokens:"Cache schrijven",reasoningTokens:"Redeneertokens",byModel:"Per model",byApiKey:"Per API-sleutel",provider:"Provider",model:"Model",cost:"Kosten",apiKey:"API-sleutel",unpriced:"Zonder prijs",unpricedHint:"Er bestaat geen prijsvermelding voor dit model — voeg er een toe op de Prijzen-pagina.",unattributed:"Niet toegewezen",unattributedHint:"Verzoeken die niet aan een specifieke API-sleutel zijn gekoppeld. Dit is normaal totdat toewijzing per sleutel wordt vastgelegd.",empty:"Geen verzoeken in dit bereik.",invalidRange:"Selecteer een geldig datumbereik."},lS={title:"Modelprijzen",description:"Tokenprijzen per model voor het berekenen van verzoekkosten, in USD per miljoen tokens.",search:"Zoek provider of model…",fetchLatest:"Nieuwste ophalen",fetching:"Ophalen…",addEntry:"Vermelding toevoegen",provider:"Provider",model:"Model",inputPrice:"Invoer",outputPrice:"Uitvoer",cacheReadPrice:"Cache lezen",cacheWritePrice:"Cache schrijven",source:"Bron",updated:"Bijgewerkt",userEdited:"bewerkt",edit:"Bewerken",deleteTitle:"Prijsvermelding verwijderen?",empty:"De prijstabel is leeg.",emptyHint:"Haal de nieuwste prijzen op om de tabel te vullen.",noMatches:"Geen vermeldingen komen overeen met je zoekopdracht.",saved:"Prijsvermelding opgeslagen.",saveFailed:"Opslaan mislukt: {{message}}",deleteFailed:"Verwijderen mislukt: {{message}}",alreadyDeleted:"De vermelding bestond al niet meer.",fetchApplied:"{{count}} vermeldingen bijgewerkt vanaf de bron.",fetchFailed:"Ophalen mislukt: {{message}}",requiredId:"Verplicht",invalidPrice:"Voer een niet-negatief getal in",conflictTitle:"Prijsconflicten oplossen",conflictHint:"Deze vermeldingen zijn door jou bewerkt en ook in de bron gewijzigd. Kies per rij of je jouw waarde behoudt (Overslaan) of de nieuwe overneemt (Overschrijven).",current:"Huidig",incoming:"Inkomend",overwrite:"Overschrijven",skip:"Overslaan",overwriteAll:"Alles overschrijven",skipAll:"Alles overslaan",applyResolutions:"Toepassen",resolved:"{{overwritten}} overschreven, {{skipped}} overgeslagen.",resolvedWithStale:"{{overwritten}} overschreven, {{skipped}} overgeslagen. {{stale}} zijn ondertussen gewijzigd en bleven onaangeroerd.",refreshFailed:"De wijziging is toegepast, maar het herladen van de lijst is mislukt: {{message}}",sourceBuiltin:"Ingebouwd",sourceLitellm:"LiteLLM",sourceUser:"Gebruiker"},dS={providerSettings:ZI,apiMode:QI,presetName:YI,common:XI,mediaSettings:JI,appLocal:eS,nav:tS,apiService:aS,accounts:nS,codeCli:oS,daemonStatus:iS,settings:rS,usageStats:sS,pricing:lS},cS={loading:"Ładowanie konfiguracji LLM...",reset:{button:"Przywróć ustawienia domyślne",confirmTitle:"Przywrócić ustawienia domyślne?",confirmBody:"Spowoduje to wyczyszczenie Twoich dostosowań dla tego dostawcy i powrót do wbudowanych ustawień domyślnych. Klucz API i zapisane sesje zostaną zachowane.",confirmButton:"Przywróć ustawienia domyślne"},reentryBanner:{message:"{{count}} włączony(-ch) dostawca(-ów) wymaga ponownego wprowadzenia klucza API. Otwórz każdego z nich i wprowadź klucz ponownie."},migrationPack:{barHint:"Przenieś klucze dostawcy i tokeny subskrypcji na inną maszynę za pomocą zaszyfrowanego pakietu.",passphrase:"Hasło",passphrasePlaceholder:"Wprowadź hasło",passphraseHint:"Użyj co najmniej 8 znaków; zalecane jest 12 lub więcej.",confirm:"Potwierdź hasło",confirmPlaceholder:"Wprowadź hasło ponownie",mismatch:"Hasła nie są zgodne.",strength:{weak:"Zbyt krótkie — użyj co najmniej 8 znaków.",fair:"W porządku — 12 lub więcej znaków jest mocniejsze.",strong:"Silne hasło."},export:{button:"Eksportuj pakiet",title:"Eksportuj zaszyfrowany pakiet",subtitle:"Zaszyfruj klucze dostawcy i tokeny subskrypcji do przenośnego pliku.",warning:"Ten plik zawiera możliwe do odszyfrowania dane poufne. Przechowuj go bezpiecznie — każdy, kto ma ten plik i hasło, może odczytać Twoje klucze. Utraconego hasła nie można odzyskać.",submit:"Eksportuj",success:"Pakiet wyeksportowany pomyślnie.",error:"Eksport nie powiódł się. Spróbuj ponownie."},import:{button:"Importuj pakiet",title:"Importuj zaszyfrowany pakiet",subtitle:"Przywróć klucze dostawcy i tokeny subskrypcji z wyeksportowanego pakietu.",hint:"Wprowadź hasło użyte podczas eksportu pakietu, a następnie wybierz plik.",submit:"Importuj",successTitle:"Import zakończony",summary:"Zaimportowano {{providerKeys}} klucz(e) dostawcy, {{poolKeys}} klucz(e) puli i {{tokenSets}} zestaw(y) tokenów.",duplicates:"Pominięto {{count}} klucz(e) puli, które już istnieją.",skipped:"Pominięto (brak pasującego dostawcy): {{names}}",error:"Błędne hasło lub uszkodzony pakiet. Nic nie zostało zmienione."}},searchPlaceholder:"Szukaj dostawców...",emptySearch:"Brak dostawców pasujących do wyszukiwania.",emptyList:"Brak skonfigurowanych dostawców.",selectPrompt:"Wybierz dostawcę, aby zobaczyć szczegóły",listStatus:"{{count}} model(e/i)",noModels:"Brak skonfigurowanych modeli",enabled:"Włączony",disabled:"Wyłączony",showEnabledOnly:"Pokaż tylko włączone",showAll:"Pokaż wszystkich dostawców",dragHandle:"Przeciągnij, aby zmienić kolejność",reorderFailed:"Nie udało się zapisać kolejności dostawców",credentials:{apiKey:"Klucz API",apiBaseUrl:"Bazowy URL API"},filter:{all:"Wszystkie",chat:"Czat",code:"Kod"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Wybierz szablon",skipTemplates:"Pomiń, skonfiguruj ręcznie",name:"Nazwa *",providerType:"Typ",apiType:"Typ API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standardowy format API czat/completions OpenAI",claudecode:"Format Anthropic Messages API (Claude Code)"},chatApiFormat:"Format API",chatApiFormatDescription:"Wybierz format API odpowiadający punktowi końcowemu Twojego dostawcy",apiKey:"Klucz API",apiKeyPlaceholder:"sk-... lub $ZMIENNA_ENV",apiKeyHelper:"Użyj $NAZWA_ZMIENNEJ, aby odwołać się do zmiennych środowiskowych",apiKeySetPlaceholder:"Klucz jest ustawiony — pozostaw puste, aby go zachować",apiKeyReplaceHelper:"Klucz jest bezpiecznie przechowywany. Wpisz nową wartość, aby go zastąpić, lub pozostaw puste, aby zachować.",testApiKey:"Testuj klucz API",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Podgląd:",models:"Modele",modelPlaceholder:"Nazwa modelu (np. gpt-4, claude-3-opus)",transformers:"Transformery",transformerConfig:"Transformery API",transformerConfigDescription:"Skonfiguruj transformery, aby dostosować formaty żądań/odpowiedzi API dla tego dostawcy",transformerConfigNote:"Daemon stosuje te transformery w łańcuchu żądań, po transformerze formatu dostawcy (który obsługuje konwersję formatu przesyłania). Nieznane nazwy transformerów są pomijane.",enabled:"Włączony",apiVersion:"Wersja API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Wersja Azure OpenAI API (np. 2024-08-01-preview)",official:"Oficjalny Anthropic API",officialHelper:"Włącz, jeśli ten dostawca łączy się bezpośrednio z oficjalnym Anthropic API. Wyłącz dla proxy zwrotnych lub usług zewnętrznych.",maxConcurrency:"Maks. równoległe żądania",maxConcurrencyHelper:"Maksymalna liczba równoległych żądań API wysyłanych do tego dostawcy. Niższe wartości pomagają uniknąć ograniczania przepustowości (błędy 429). Ustaw `-1`, aby nie ograniczać.",codingPlan:{label:"Plan kodowania",description:"Użyj oddzielnego punktu końcowego API dla planów kodowania opartych na subskrypcji",baseUrl:"Bazowy URL planu kodowania",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Klucz API planu kodowania (opcjonalny)",apiKeyPlaceholder:"Pozostaw puste, aby użyć klucza API dostawcy",apiKeyHelper:"Wymagany tylko wtedy, gdy plan kodowania używa innego klucza API",tokenPlanHint:"Niektórzy dostawcy (np. Xiaomi MiMo) wydają klucze Token Plan z prefiksem `tp-` — tylko informacyjnie, nieegzekwowane."},selectTypeFirst:"Wybierz typ dostawcy",selectTypeFirstDesc:"Wybierz, jaki typ dostawcy chcesz dodać",codeProviderNote:"Dostawcy kodu wymagają tylko klucza API i adresu URL. Modele są zarządzane przez router agentów.",buttons:{cancel:"Anuluj",submitAdd:"Dodaj dostawcę",submitUpdate:"Zaktualizuj dostawcę",continue:"Kontynuuj",back:"Wstecz"}},details:{noSelection:"Wybierz dostawcę, aby zobaczyć szczegóły",apiKey:"Klucz API",apiUrl:"URL API",nameLabel:"Nazwa dostawcy",modelsEndpoint:"Punkt końcowy modeli",modelsEndpointHelper:"Zastąp punkt końcowy wykrywania, jeśli dostawca udostępnia niestandardową ścieżkę /models.",models:"Modele",transformers:"Transformery",codeProviderNote:"Dostawcy kodu (np. Claude Code) nie wymagają konfiguracji modeli. Modele są automatycznie zarządzane przez router agentów.",buttons:{more:"Więcej ustawień",delete:"Usuń"}},providerModelSelector:{placeholder:"Wybierz dostawcę i model",noProviders:"Brak dostępnych dostawców",noModels:"Brak skonfigurowanych modeli"},apiKeyPool:{title:"Pula kluczy API",description:"Skonfiguruj wiele kluczy API do równoważenia obciążenia. Każda sesja jest przypisana do jednego klucza, aby zachować pamięć podręczną promptów.",defaultLabel:"Domyślny",weight:"Waga",noKey:"Brak klucza",labelPlaceholder:"Etykieta (np. Klucz #1, Produkcja)",addKey:"Dodaj klucz API",add:"Dodaj",empty:"Brak dodatkowych kluczy.",statusCoolingDown:"Oczekiwanie {{time}}",statusAuthFailed:"Uwierzytelnianie nie powiodło się · wyłączony",statusDisabled:"Wyłączony",statusHealthy:"Sprawny",agoSeconds:"{{count}}s temu",agoMinutes:"{{count}}m temu",agoHours:"{{count}}h temu",agoDays:"{{count}}d temu"},modelsManager:{searchPlaceholder:"Szukaj modeli...",defaultGroup:"Wszystkie modele",add:"Dodaj model",manage:"Zarządzaj",empty:"Brak modeli w tej grupie",enabled:"Włączony",disabled:"Wyłączony",filters:{all:"Wszystkie",vision:"Widzenie",reasoning:"Rozumowanie",free:"Bezpłatne",tools:"Narzędzia"},manualDialog:{title:"Dodaj model",subtitle:"Dodaj niestandardowy model do tego dostawcy",modelId:"ID modelu",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash itp.",modelIdHelper:"Dokładny identyfikator modelu używany podczas wywoływania API",modelName:"Nazwa wyświetlana",modelNamePlaceholder:"Przyjazna nazwa wyświetlana (opcjonalna)",modelNameHelper:"Opcjonalna nazwa wyświetlana w interfejsie. Jeśli puste, zostanie użyte ID modelu",group:"Grupa",groupPlaceholder:"Wybierz lub wpisz nazwę grupy",submit:"Dodaj",cancel:"Anuluj",helper:"Podaj dokładny identyfikator modelu udostępniony przez API dostawcy."},editDialog:{title:"Edytuj model",subtitle:"Modyfikuj ustawienia modelu",modelId:"ID modelu",modelIdPlaceholder:"Identyfikator modelu",modelIdHelper:"Identyfikator modelu używany podczas wywoływania API",modelName:"Nazwa wyświetlana",modelNamePlaceholder:"Przyjazna nazwa wyświetlana",modelNameHelper:"Nazwa wyświetlana w interfejsie",group:"Grupa",groupPlaceholder:"Wybierz lub wpisz nazwę grupy",submit:"Zapisz",cancel:"Anuluj",vision:"Możliwość widzenia",visionHint:"Czy ten model obsługuje wejście obrazu/widzenia",reasoning:"Model myślenia",reasoningHint:"Czy ten model obsługuje tryb myślenia/rozumowania"},manageDialog:{title:"Zarządzaj modelami",cachedAt:"W pamięci podręcznej o {{date}} ({{source}})",refresh:"Odśwież",close:"Zamknij",raw:"Surowy JSON",empty:"Brak dostępnych modeli zdalnych.",error:"Nie udało się załadować modeli: {{message}}",addFromCatalog:"Dodaj",sourceCache:"pamięć podręczna",sourceNetwork:"na żywo",contextLength:"Kontekst {{value}} tokenów",maxTokens:"Maks. {{value}} tokenów"},messages:{added:"Model dodany.",updated:"Model zaktualizowany.",removed:"Model usunięty.",duplicate:"Model już istnieje.",refreshed:"Modele odświeżone",refreshFailed:"Nie udało się odświeżyć modeli"},testDialog:{title:"Test łączności modelu",provider:"Dostawca",model:"Model",testing:"Testowanie...",success:"Test zakończony sukcesem",successMessage:"Dostęp do modelu jest możliwy",failure:"Test nie powiódł się",aiResponse:"Odpowiedź AI",charCount:"{{count}} znaków",duration:"Czas {{time}}s",close:"Zamknij",retest:"Testuj ponownie",testButton:"Testuj model",unsupportedFormat:"Testowanie nie jest jeszcze obsługiwane dla tego formatu dostawcy."}},router:{title:"Konfiguracja routera",description:"Skonfiguruj, którego dostawcy/modelu używać w różnych scenariuszach.",labels:{default:"Domyślny",background:"tło",think:"myślenie",longContext:"Długi kontekst",webSearch:"Wyszukiwanie w internecie",image:"Obraz",longContextThreshold:"Próg długiego kontekstu"},helper:{longContextThreshold:"Liczba tokenów, po której następuje przełączenie na model długiego kontekstu."},placeholder:{required:"Wymagane",optional:"Opcjonalne"}},agentRouter:{title:"Router agentów",description:"Skonfiguruj dwukierunkowe routing między trybami Czat i Kod.",searchPlaceholder:"Szukaj routerów...",noSearchResults:"Brak routerów pasujących do wyszukiwania.",tabs:{chatToCode:"Czat → Kod",codeToChatPlaceholder:"Kod → Czat"},chatToCode:{title:"Router Czat do Kod",description:"Używaj dostawców czatu w trybie agenta/kodowania",addRouter:"Dodaj router",emptyState:"Brak skonfigurowanych routerów Czat→Kod. Dodaj jeden, aby używać dostawców czatu w trybie kodowania.",form:{name:"Nazwa routera",namePlaceholder:"Mój router Czat→Kod",chatProvider:"Dostawca czatu",chatProviderPlaceholder:"Wybierz dostawcę czatu",mode:"Tryb",modeSimple:"Prosty",modeAdvanced:"Zaawansowany",modeSimpleDesc:"Bezpośrednie przekazanie do dostawcy czatu",modeAdvancedDesc:"Konfiguracja mapowania modeli i obsługi kontekstu",enabled:"Włączony",save:"Zapisz router",cancel:"Anuluj"},list:{provider:"Dostawca",mode:"Tryb",status:"Status"},mappings:{title:"Mapowania modeli",description:"Mapuj modele dostawcy czatu na modele dostawcy kodu",count:"mapowanie(-ń)",empty:"Brak skonfigurowanych mapowań modeli. Dodaj mapowania, aby kierować modele czatu do dostawców kodu.",addNew:"Dodaj nowe mapowanie",selectSource:"Wybierz model źródłowy (Czat)",selectTarget:"Wybierz model docelowy (Kod)",targetPlaceholder:"Wpisz nazwę modelu Claude Code",notSet:"(Nieustawiony — kliknij, aby wybrać)",add:"Dodaj",edit:"Edytuj",done:"Gotowe"},advanced:{title:"Zaawansowana konfiguracja",description:"Skonfiguruj modele dla różnych typów zadań",helpText:"Model domyślny jest wymagany. Pozostałe modele są opcjonalne i w razie braku konfiguracji przejdą do domyślnego.",default:{label:"Domyślny",placeholder:"Wybierz model domyślny",description:"Główny model do ogólnych zadań (podobny do Claude Sonnet)"},background:{label:"Tło",placeholder:"Wybierz model tła",description:"Lekki model do zadań w tle (podobny do Claude Haiku)"},think:{label:"Myślenie",placeholder:"Wybierz model myślenia",description:"Zaawansowany model do złożonego rozumowania (podobny do Claude Opus)"},image:{label:"Obraz",placeholder:"Wybierz model obrazu",description:"Model do zadań związanych z obrazem z możliwością widzenia"}}},codeToChat:{title:"Router Kod do Czat",description:"Udostępniaj modele planu kodowania w trybie czatu",addRouter:"Dodaj router",emptyState:"Brak skonfigurowanych routerów Kod→Czat. Dodaj jeden, aby udostępnić modele planu kodowania w trybie czatu.",form:{name:"Nazwa routera",namePlaceholder:"Mój router Kod→Czat",codeProvider:"Dostawca kodu",codeProviderPlaceholder:"Wybierz dostawcę kodu",codeProviderHelper:"Wybierz dostawcę kodu do użycia przy transformacji",models:"Modele planu kodowania",modelsHelper:"Wybierz, które modele planu kodowania udostępnić",enabled:"Włączony",save:"Zapisz router",cancel:"Anuluj"},mappings:{title:"Mapowania modeli",description:"Mapuj modele dostawcy kodu na modele dostawcy czatu do udostępnienia",count:"mapowanie(-ń)",empty:"Brak skonfigurowanych mapowań modeli. Dodaj mapowania, aby udostępnić modele kodu w trybie czatu.",addNew:"Dodaj nowe mapowanie",selectSource:"Wybierz model źródłowy (Kod)",selectTarget:"Wybierz model docelowy (Czat)",sourcePlaceholder:"Wpisz nazwę modelu źródłowego",targetPlaceholder:"Wpisz nazwę modelu docelowego",add:"Dodaj",edit:"Edytuj",done:"Gotowe"}},transformers:{title:"Transformery",description:"Skonfiguruj transformery do konwersji żądań/odpowiedzi",noProvider:"Wybierz dostawcę, aby skonfigurować transformery",empty:"Brak transformerów",count:"{{count}} transformer(y/ów)"},status:{enabled:"Włączony",disabled:"Wyłączony"},messages:{routerAdded:"Router dodany pomyślnie",routerUpdated:"Router zaktualizowany pomyślnie",routerDeleted:"Router usunięty pomyślnie",saveFailed:"Nie udało się zapisać routera"}},presets:{title:"Szybkie dodawanie dostawcy",added:"Dodano",add:"Dodaj",features:{search:"Wyszukiwanie",vision:"Widzenie",mcp:"MCP",codingPlan:"Plan kodowania"}},alerts:{deleteConfirm:"Czy na pewno chcesz usunąć tego dostawcę?"},errors:{nameRequired:"Nazwa dostawcy jest wymagana",urlRequired:"Bazowy URL API jest wymagany",urlInvalid:"Wprowadź prawidłowy URL (np. https://api.example.com)",saveFailed:"Nie udało się zapisać dostawcy",deleteFailed:"Błąd podczas usuwania dostawcy. Spróbuj ponownie.",toggleFailed:"Błąd podczas przełączania dostawcy. Spróbuj ponownie."},openRouter:{title:"Routing dostawców OpenRouter",description:"Skonfiguruj, jak żądania są kierowane do różnych dostawców w OpenRouter.",sort:"Strategia routingu",sortTooltip:"Wybierz sposób priorytetyzowania dostawców. Auto używa inteligentnego równoważenia obciążenia.",order:"Kolejność priorytetów dostawców",orderTooltip:"Określ dostawców do wypróbowania w kolejności (np. anthropic, openai, together). Naciśnij Enter, aby dodać.",orderPlaceholder:"Wpisz identyfikator dostawcy i naciśnij Enter...",allowFallbacks:"Zezwól na zapasowe",allowFallbacksTooltip:"Po włączeniu OpenRouter będzie próbował zapasowych dostawców, jeśli główny jest niedostępny.",requireParameters:"Wymagaj wszystkich parametrów",requireParametersTooltip:"Kieruj tylko do dostawców obsługujących wszystkie parametry w żądaniu.",dataCollection:"Polityka zbierania danych",dataCollectionTooltip:"Kontroluj, czy używać dostawców, którzy mogą przechowywać lub trenować na Twoich danych.",zdr:"Zerowe przechowywanie danych",zdrTooltip:"Kieruj tylko do punktów końcowych z polityką zerowego przechowywania danych.",only:"Dozwoleni dostawcy",onlyTooltip:"Używaj tylko tych konkretnych dostawców. Pozostaw puste, aby zezwolić na wszystkich.",onlyPlaceholder:"Wpisz identyfikator dostawcy i naciśnij Enter...",ignore:"Ignorowani dostawcy",ignoreTooltip:"Pomijaj tych dostawców podczas kierowania żądań.",ignorePlaceholder:"Wpisz identyfikator dostawcy i naciśnij Enter...",quantizations:"Filtr kwantyzacji",quantizationsTooltip:"Używaj tylko dostawców z określonymi poziomami kwantyzacji. Niższa precyzja może obniżyć jakość, ale zwiększyć szybkość.",maxPrice:"Cena maksymalna",maxPriceTooltip:"Ustaw maksymalne limity cen za milion tokenów. Pozostaw puste, aby nie ograniczać.",configured:"Skonfigurowane"}},uS={label:"Tryb API",standard:"Standardowy",codingPlan:"Plan kodowania",tokenPlan:"Plan tokenów",apiKeyPrefixHint:"Klucze do tego planu zazwyczaj zaczynają się od `{{prefix}}`. Tylko wskazówka — nieegzekwowane.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan używa osobnego klucza API niż standardowy punkt końcowy.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan używa osobnego klucza API niż standardowy punkt końcowy.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan obsługuje tylko protokół Anthropic.",xiaomiTokenPlanRegions:"Domyślny baseUrl to `token-plan-cn.*`. Możesz go ręcznie zmienić na `token-plan-sgp.*` lub `token-plan-ams.*`.",confirmOverwriteTitle:"Przełączyć tryb API?",confirmOverwriteBody:"Dostosowałeś URL API lub klucz API. Przełączenie trybu nadpisze je wartościami domyślnymi nowego trybu — lub zachowaj swoje dostosowania i zaktualizuj tylko etykietę trybu.",overwriteAndSwitch:"Nadpisz i przełącz",keepCustomizations:"Zachowaj dostosowania"},pS={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},mS={cancel:"Anuluj",close:"Zamknij",copy:"Kopiuj",delete:"Usuń",dismiss:"Odrzuć",save:"Zapisz",optional:"opcjonalne",retry:"Ponów",loading:"Ładowanie…"},gS={common:{learnMore:"Dokumentacja"}},hS={notSupportedByDaemon:"Nie jest jeszcze obsługiwane przez daemon",discoveryUnsupportedFormat:"Wykrywanie modeli nie jest jeszcze obsługiwane dla tego formatu dostawcy. Dodaj modele ręcznie."},fS={subtitle:"Panel sterowania",providers:"Dostawcy",apiService:"Usługa API",accounts:"Konta",codeCli:"Code CLI",settings:"Ustawienia",usageStats:"Użycie",pricing:"Cennik"},vS={title:"Usługa API",description:"Skonfiguruj wychodzący serwer API, routing modeli per punkt końcowy i nazwane klucze dostępu.",loading:"Ładowanie konfiguracji serwera…",loadError:"Nie udało się załadować konfiguracji serwera. Sprawdź, czy daemon jest dostępny.",enable:{label:"Włącz serwer wychodzący",description:"Uruchom lokalny serwer API, który kieruje zewnętrznych klientów przez Twoich dostawców."},networkBinding:{label:"Zezwól na dostęp z sieci LAN",description:"Powiąż serwer z interfejsem sieciowym zamiast tylko z pętlą zwrotną.",warning:"Dostęp z sieci LAN naraża serwer API na inne urządzenia w sieci. W połączeniu z routingiem subskrypcji żądania mogą zużywać limit subskrypcji — wyłącz tę opcję, jeśli nie ufasz sieci."},status:{running:"Serwer działa",stopped:"Serwer zatrzymany",runningHint:"Wychodzący serwer API przyjmuje żądania.",stoppedHint:"Włącz serwer, aby zacząć przyjmować żądania.",port:"port {{port}}",loopback:"Adresy URL pętli zwrotnej",lan:"Adresy URL LAN"},endpoints:{title:"Routing punktów końcowych",description:"Wybierz model, do którego kieruje każdy format przesyłania. Domyślny model jest tutaj uwzględniony — serwer jest routerem, nie aplikacją czatu."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Model domyślny",backgroundModel:"Model tła",visionModel:"Model widzenia",noVisionModel:"Brak",backgroundModelIds:"ID modeli tła",backgroundModelIdsPlaceholder:"ID modeli oddzielone przecinkami",modelPlaceholder:"Wybierz model…",useSubscription:"Używaj subskrypcji",subscriptionUnsupported:"Routing subskrypcji nie jest dostępny dla tego punktu końcowego."},keys:{title:"Klucze dostępu",description:"Nazwane klucze, które zewnętrzni klienci wysyłają jako token Bearer. Pełny klucz jest pokazywany tylko raz przy tworzeniu.",namePlaceholder:"Nazwa klucza (np. moje-cli)",create:"Utwórz klucz",empty:"Brak kluczy dostępu.",enabled:"Włączony",disabled:"Wyłączony",revoked:"Unieważniony",toggle:"Przełącz klucz",revoke:"Unieważnij",revokeConfirmTitle:"Unieważnić ten klucz?",revokeConfirmDesc:"Unieważnienie „{{name}}“ natychmiast uniemożliwia jego uwierzytelnianie. Tej operacji nie można cofnąć.",created:{title:"Klucz utworzony",warning:"Skopiuj ten klucz teraz — nie zostanie ponownie pokazany. Przechowuj go bezpiecznie.",copy:"Kopiuj",copied:"Skopiowano",dismiss:"Gotowe"}}},kS={title:"Konta i subskrypcje",description:"Zarządzaj poświadczeniami subskrypcji, przez które serwer kieruje ruch. Tokeny są tu zapisywane, ale nigdy nie są wyświetlane ponownie.",loading:"Ładowanie kont…",empty:"Brak dostępnych dostawców subskrypcji.",signIn:"Zaloguj się",oauth:{title:"Zaloguj się do {{name}}",description:"Otwórz stronę logowania w przeglądarce, autoryzuj, a następnie wklej poniżej kod autoryzacji. Kod trafia tylko do daemona — wygenerowany token nigdy nie jest pokazywany.",openPage:"Otwórz stronę logowania",codeLabel:"Kod autoryzacji",codePlaceholder:"Wklej kod tutaj",submit:"Zakończ logowanie"},codexOauth:{title:"Zaloguj się do {{name}}",description:"Otwórz stronę logowania w przeglądarce i autoryzuj. Daemon automatycznie przechwyci wynik — pozostaw tę stronę otwartą do czasu zakończenia. Token nigdy nie jest pokazywany.",waiting:"Oczekiwanie na zakończenie logowania w przeglądarce…",failed:"Logowanie nie powiodło się. Spróbuj ponownie."},clearProvider:"Wyczyść wszystkie",clearConfirmTitle:"Wyczyścić konta {{name}}?",clearConfirmDesc:"Spowoduje to usunięcie wszystkich przechowywanych poświadczeń dla tego dostawcy. Tej operacji nie można cofnąć.",credential:{ok:"Skonfigurowane",notConfigured:"Nieskonfigurowane"},kind:{"pass-through":"Poświadczenia przekazywane","oauth-bearer":"Bearer OAuth","static-bearer":"Statyczny klucz Bearer"},reason:{"missing-credential":"Brak zapisanego poświadczenia.",expired:"Poświadczenie wygasło.","reauth-required":"Wymagane ponowne uwierzytelnienie.","refresh-failed":"Odświeżenie tokenu nie powiodło się.","not-refreshable":"Poświadczenie nie może być odświeżone.",unknown:"Nieznany status."},status:{unconfigured:"Nieskonfigurowane",authorized:"Autoryzowane",configured:"Skonfigurowane",expired:"Wygasłe",error:"Błąd"},authMethod:{oauth:"OAuth",setup_token:"Token konfiguracyjny",manual:"Ręcznie"},list:{empty:"Brak przechowywanych kont dla tego dostawcy.",active:"Aktywne",expiresAt:"Wygasa {{value}}",setActive:"Ustaw jako aktywne",remove:"Usuń",removeConfirmTitle:"Usunąć to konto?",removeConfirmDesc:"Usunięcie „{{name}}“ usuwa zapisane poświadczenie. Tej operacji nie można cofnąć.",title:"Konta"},write:{trigger:"Dodaj poświadczenie",title:"Zapisz poświadczenie {{name}}",description:"Wklej już uzyskany materiał tokenu. Pola są ograniczone do tego, co ten dostawca akceptuje; token jest przechowywany i nigdy nie jest pokazywany ponownie.",authMethod:"Metoda uwierzytelniania",status:"Status",subscriptionLevel:"Poziom subskrypcji",subscriptionLevelNone:"Nieustawione",submit:"Zapisz poświadczenie"},field:{accessToken:"Token dostępu",refreshToken:"Token odświeżania",idToken:"Token ID",apiKey:"Klucz API",expiresAt:"Wygasa o (ISO)",setupTokenExpiresAt:"Token konfiguracyjny wygasa o (ISO)",accountId:"ID konta",email:"E-mail",organizationId:"ID organizacji",baseUrl:"Bazowy URL",zenBaseUrl:"Zen bazowy URL"},provider:{claude:{title:"Claude",description:"Poświadczenia subskrypcji Anthropic kierowane przez daemon."},codex:{title:"Codex",description:"Poświadczenia subskrypcji OpenAI Codex kierowane przez daemon."},gemini:{title:"Gemini",description:"Poświadczenia subskrypcji Google Gemini kierowane przez daemon."},opencodego:{title:"OpenCodeGo",description:"Statyczne poświadczenia klucza API kierowane przez daemon."}},authMethodLabel:"Metoda autoryzacji",authMethodDesc:{oauth:"Zaloguj się przez przeglądarkę; daemon przechwytuje i przechowuje token.",manual:"Wklej już uzyskany token. Jest przechowywany i nigdy nie jest wyświetlany ponownie."},actions:{authorize:"Autoryzuj",enterToken:"Wprowadź token",refresh:"Odśwież"},accounts:{addAccount:"Dodaj konto"},detail:{authMethod:"Metoda autoryzacji",subscriptionLevel:"Poziom subskrypcji",expiresAt:"Wygasa",lastRefreshed:"Ostatnio odświeżone",label:"Etykieta konta",labelPlaceholder:"Nazwij to konto",saveLabel:"Zapisz etykietę"},oauthFlow:{step1:{title:"Otwórz stronę autoryzacji",desc:"Otwórz stronę logowania w przeglądarce."},step2:{title:"Autoryzuj dostęp",desc:"Zaloguj się i zatwierdź dostęp dla dostawcy."},step3:{title:"Skopiuj kod autoryzacji",desc:"Strona pokazuje kod autoryzacji po zatwierdzeniu."},step4:{title:"Wklej kod",desc:"Wklej kod autoryzacji poniżej, aby zakończyć. Kod trafia tylko do daemona — wygenerowany token nigdy nie jest pokazywany."},authorize:"Zakończ logowanie",showUrl:"Pokaż URL autoryzacji"},manual:{title:"Wklej poświadczenie",description:"Wklej już uzyskany token. Pola są ograniczone do tego, co ten dostawca akceptuje; token jest przechowywany i nigdy nie jest pokazywany ponownie.",accessTokenPlaceholder:"Wklej token dostępu",refreshTokenPlaceholder:"Wklej token odświeżania (opcjonalny)",hint:"Token jest wysyłany do daemona i przechowywany w postaci zaszyfrowanej. Nigdy nie jest wyświetlany ponownie."},openCodeGo:{apiKeyRequired:"Klucz API jest wymagany.",apiKeyPlaceholder:"Wklej klucz API",baseUrlPlaceholder:"https://… (opcjonalny)",zenBaseUrlPlaceholder:"https://… (opcjonalny)"},info:{title:"Informacje o kontach subskrypcji",description:"Tokeny są zapisywane do daemona i używane do uwierzytelniania żądań upstream. Są przechowywane w postaci zaszyfrowanej i nigdy nie są wyświetlane ponownie. Usunięcie konta usuwa jego zapisane poświadczenie."},rename:{failed:"Nie udało się zmienić nazwy konta."},refresh:{failed:"Nie udało się odświeżyć tokenu."},errors:{requestFailed:"Żądanie nie powiodło się. Spróbuj ponownie."},syncWarning:{"external-divergent":"Plik logowania zewnętrznego CLI zawiera nowsze dane uwierzytelniające niż to konto. Zapisany token może przestać się odświeżać — odśwież teraz lub zaloguj się ponownie.","external-not-rotated":"Odświeżanie nie powiodło się, a zewnętrzne CLI zawiera te same wygasłe dane uwierzytelniające. Zaloguj się ponownie.","duplicate-token":"Inne konto używa tych samych danych uwierzytelniających. Odświeżenie jednego z nich wyloguje drugie."},importExternal:{detected:"Na tym komputerze znaleziono istniejące logowanie CLI {{name}}.",hint:"Po zaimportowaniu ta aplikacja dba o jego aktualność: przy każdym odświeżeniu tokenu aktualizowany jest też plik logowania CLI, więc CLI w terminalu pozostaje zalogowane.",button:"Importuj istniejące logowanie CLI"}},yS={title:"Code CLI",description:"Skieruj CLI do kodowania na wychodzące proxy daemona. Ta strona jest tylko do odczytu — nie ma tu nic do skonfigurowania.",copy:"Kopiuj",copied:"Skopiowano",baseUrl:{title:"Bazowy URL daemona",description:"Adres proxy, z którym łączy się Twoje CLI.",label:"Bazowy URL"},token:{title:"Uwierzytelnianie",hint:"Wyślij 'Authorization: Bearer <twój-token-administratora>' dla tras administracyjnych. Token administratora jest konfigurowany w daemonie (plik konfiguracyjny lub środowisko) — nigdy nie jest pokazywany tutaj."},examples:{title:"Przykładowe środowisko uruchomienia",keyNote:"Użyj klucza dostępu wychodzącego utworzonego na stronie usługi API — nie tokenu administratora.",anthropic:"CLI w formacie Anthropic",openai:"CLI w formacie OpenAI"},launchDescription:"Uruchom CLI do kodowania w terminalu, skierowane na ten daemon. Daemon wstrzykuje przekierowanie środowiska i uruchamia CLI za Ciebie.",refresh:"Odśwież",loading:"Wykrywanie CLI…",cli:{installed:"Zainstalowane",notFound:"Nie znaleziono",notFoundHint:"To CLI nie jest w PATH hosta daemona. Zainstaluj je, a następnie odśwież.",install:"Zainstaluj",installing:"Instalowanie…",installingHint:"Instalowanie na hoście daemona — może to chwilę potrwać.",launch:"Uruchom",launchTitle:"Uruchom {{name}}",launchDescription:"Otwiera nowy terminal na hoście daemona uruchamiający to CLI, kierowane przez proxy daemona. Wybierz opcjonalny katalog roboczy.",cwdLabel:"Katalog roboczy",cwdPlaceholder:"/ścieżka/do/projektu",runningVia:"Działa · {{provider}} / {{model}}",stop:"Zatrzymaj"},manual:{title:"Ręczna konfiguracja",description:"Wolisz uruchomić CLI samodzielnie? Skieruj je na daemon za pomocą tych zmiennych środowiskowych.",show:"Pokaż",hide:"Ukryj"}},bS={probing:"Sprawdzanie daemona…",spawning:"Uruchamianie daemona…",failed:"Daemon nie mógł się uruchomić",failedHint:"Upewnij się, że Node.js jest zainstalowany i daemon jest zbudowany (dist obecny), lub ustaw OMNICROSS_DAEMON_ENTRY na cli.js daemona."},PS={title:"Ustawienia",description:"Preferencje aplikacji desktopowej.",desktopOnly:"Opcje uruchamiania i zasobnika systemowego dotyczą tylko aplikacji desktopowej.",startup:{title:"Uruchamianie",autoLaunch:"Uruchamiaj przy logowaniu",autoLaunchHint:"Uruchamiaj Omnicross automatycznie po zalogowaniu.",startMinimized:"Uruchom zminimalizowany do zasobnika",startMinimizedHint:"Uruchom w tle bez otwierania okna."},tray:{title:"Zasobnik systemowy",minimizeOnClose:"Minimalizuj do zasobnika przy zamknięciu",minimizeOnCloseHint:"Zamknięcie okna ukrywa je w zasobniku zamiast wychodzić."},language:{title:"Język",label:"Język interfejsu"}},AS={title:"Statystyki użycia",description:"Statystyki tokenów i kosztów żądań obsłużonych przez demona.",rangeToday:"Dzisiaj",range7d:"Ostatnie 7 dni",range30d:"Ostatnie 30 dni",rangeCustom:"Niestandardowy",from:"Od",to:"Do",totalCost:"Koszt łączny",cacheSavings:"Oszczędności cache",events:"Żądania",inputTokens:"Tokeny wejściowe",outputTokens:"Tokeny wyjściowe",cacheReadTokens:"Odczyt cache",cacheWriteTokens:"Zapis cache",reasoningTokens:"Tokeny rozumowania",byModel:"Wg modelu",byApiKey:"Wg klucza API",provider:"Dostawca",model:"Model",cost:"Koszt",apiKey:"Klucz API",unpriced:"Bez ceny",unpricedHint:"Brak wpisu cenowego dla tego modelu — dodaj go na stronie Cennik.",unattributed:"Nieprzypisane",unattributedHint:"Żądania niepowiązane z konkretnym kluczem API. To normalne, dopóki przypisanie per klucz nie jest rejestrowane.",empty:"Brak żądań w tym zakresie.",invalidRange:"Wybierz prawidłowy zakres dat."},CS={title:"Cennik modeli",description:"Ceny tokenów per model używane do obliczania kosztów żądań, w USD za 1 mln tokenów.",search:"Szukaj dostawcy lub modelu…",fetchLatest:"Pobierz najnowsze",fetching:"Pobieranie…",addEntry:"Dodaj wpis",provider:"Dostawca",model:"Model",inputPrice:"Wejście",outputPrice:"Wyjście",cacheReadPrice:"Odczyt cache",cacheWritePrice:"Zapis cache",source:"Źródło",updated:"Zaktualizowano",userEdited:"edytowano",edit:"Edytuj",deleteTitle:"Usunąć wpis cenowy?",empty:"Tabela cen jest pusta.",emptyHint:"Pobierz najnowsze ceny, aby ją wypełnić.",noMatches:"Brak wpisów pasujących do wyszukiwania.",saved:"Wpis cenowy zapisany.",saveFailed:"Zapis nie powiódł się: {{message}}",deleteFailed:"Usuwanie nie powiodło się: {{message}}",alreadyDeleted:"Wpisu już nie było.",fetchApplied:"Zaktualizowano {{count}} wpisów ze źródła.",fetchFailed:"Pobieranie nie powiodło się: {{message}}",requiredId:"Wymagane",invalidPrice:"Wprowadź liczbę nieujemną",conflictTitle:"Rozwiąż konflikty cen",conflictHint:"Te wpisy zostały edytowane przez Ciebie i zmieniły się też w źródle. Wybierz dla każdego wiersza: zachować swoją wartość (Pomiń) czy przyjąć nową (Nadpisz).",current:"Bieżące",incoming:"Przychodzące",overwrite:"Nadpisz",skip:"Pomiń",overwriteAll:"Nadpisz wszystko",skipAll:"Pomiń wszystko",applyResolutions:"Zastosuj",resolved:"Nadpisano: {{overwritten}}, pominięto: {{skipped}}.",resolvedWithStale:"Nadpisano: {{overwritten}}, pominięto: {{skipped}}. {{stale}} zmieniły się w międzyczasie i pozostały nietknięte.",refreshFailed:"Zmiana została zastosowana, ale nie udało się ponownie wczytać listy: {{message}}",sourceBuiltin:"Wbudowane",sourceLitellm:"LiteLLM",sourceUser:"Użytkownik"},xS={providerSettings:cS,apiMode:uS,presetName:pS,common:mS,mediaSettings:gS,appLocal:hS,nav:fS,apiService:vS,accounts:kS,codeCli:yS,daemonStatus:bS,settings:PS,usageStats:AS,pricing:CS},zS={loading:"Carregando configuração do LLM...",reset:{button:"Restaurar padrões",confirmTitle:"Restaurar configurações padrão?",confirmBody:"Isso apaga suas personalizações para este provedor e volta aos padrões integrados. Sua chave de API e sessões salvas são mantidas.",confirmButton:"Restaurar padrões"},reentryBanner:{message:"{{count}} provedor(es) habilitado(s) precisam que a chave de API seja reinserida. Abra cada um e adicione a chave novamente."},migrationPack:{barHint:"Mova suas chaves de provedor e tokens de assinatura para outro computador com um pacote criptografado.",passphrase:"Senha",passphrasePlaceholder:"Digite uma senha",passphraseHint:"Use pelo menos 8 caracteres; 12 ou mais é recomendado.",confirm:"Confirmar senha",confirmPlaceholder:"Digite a senha novamente",mismatch:"As senhas não coincidem.",strength:{weak:"Muito curta — use pelo menos 8 caracteres.",fair:"Aceitável — 12 ou mais caracteres é mais seguro.",strong:"Senha forte."},export:{button:"Exportar pacote",title:"Exportar pacote criptografado",subtitle:"Criptografe suas chaves de provedor e tokens de assinatura em um arquivo portátil.",warning:"Este arquivo contém segredos descriptografáveis. Guarde-o com segurança — qualquer pessoa com o arquivo e a senha pode ler suas chaves. Uma senha perdida não pode ser recuperada.",submit:"Exportar",success:"Pacote exportado com sucesso.",error:"Falha ao exportar. Por favor, tente novamente."},import:{button:"Importar pacote",title:"Importar pacote criptografado",subtitle:"Restaure chaves de provedor e tokens de assinatura de um pacote exportado.",hint:"Digite a senha usada ao exportar o pacote e escolha o arquivo.",submit:"Importar",successTitle:"Importação concluída",summary:"Importados {{providerKeys}} chave(s) de provedor, {{poolKeys}} chave(s) de pool e {{tokenSets}} conjunto(s) de tokens.",duplicates:"{{count}} chave(s) de pool já existentes foram ignoradas.",skipped:"Ignorado (sem provedor correspondente): {{names}}",error:"Senha incorreta ou pacote corrompido. Nenhuma alteração foi feita."}},searchPlaceholder:"Pesquisar provedores...",emptySearch:"Nenhum provedor corresponde à sua pesquisa.",emptyList:"Nenhum provedor configurado.",selectPrompt:"Selecione um provedor para ver os detalhes",listStatus:"{{count}} modelo(s)",noModels:"Nenhum modelo configurado",enabled:"Habilitado",disabled:"Desabilitado",showEnabledOnly:"Mostrar apenas habilitados",showAll:"Mostrar todos os provedores",dragHandle:"Arraste para reordenar",reorderFailed:"Falha ao salvar a ordem dos provedores",credentials:{apiKey:"Chave de API",apiBaseUrl:"URL base da API"},filter:{all:"Todos",chat:"Chat",code:"Código"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Selecione um modelo",skipTemplates:"Pular, configurar manualmente",name:"Nome *",providerType:"Tipo",apiType:"Tipo de API",apiTypeOptions:{openai:"Conclusão OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Formato padrão de API chat/completions da OpenAI",claudecode:"Formato de API de mensagens da Anthropic (Claude Code)"},chatApiFormat:"Formato de API",chatApiFormatDescription:"Selecione o formato de API que corresponde ao endpoint do seu provedor",apiKey:"Chave de API",apiKeyPlaceholder:"sk-... ou $ENV_VAR",apiKeyHelper:"Use $VAR_NAME para referenciar variáveis de ambiente",apiKeySetPlaceholder:"Chave configurada — deixe em branco para mantê-la",apiKeyReplaceHelper:"Uma chave está armazenada com segurança. Digite um novo valor para substituí-la ou deixe em branco para mantê-la.",testApiKey:"Testar chave de API",apiUrl:"URL da API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Prévia:",models:"Modelos",modelPlaceholder:"Nome do modelo (ex.: gpt-4, claude-3-opus)",transformers:"Transformadores",transformerConfig:"Transformadores de API",transformerConfigDescription:"Configure transformadores para adaptar os formatos de requisição/resposta da API deste provedor",transformerConfigNote:"O daemon aplica esses transformadores na cadeia de requisições, após o transformador de formato do provedor (que cuida da conversão do formato de rede). Nomes de transformadores desconhecidos são ignorados.",enabled:"Habilitado",apiVersion:"Versão da API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versão da API do Azure OpenAI (ex.: 2024-08-01-preview)",official:"API oficial da Anthropic",officialHelper:"Habilite se este provedor se conecta diretamente à API oficial da Anthropic. Desative para proxies reversos ou serviços de terceiros.",maxConcurrency:"Máximo de requisições simultâneas",maxConcurrencyHelper:"Número máximo de requisições de API simultâneas enviadas a este provedor. Valores menores ajudam a evitar limitação de taxa (erros 429). Defina `-1` para sem limite.",codingPlan:{label:"Plano de codificação",description:"Usar um endpoint de API separado para planos de codificação baseados em assinatura",baseUrl:"URL base do plano de codificação",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Chave de API do plano de codificação (opcional)",apiKeyPlaceholder:"Deixe vazio para usar a chave de API do provedor",apiKeyHelper:"Necessária apenas se o plano de codificação usar uma chave de API diferente",tokenPlanHint:"Alguns provedores (ex.: Xiaomi MiMo) emitem chaves de Plano de tokens com o prefixo `tp-` — apenas informativo, não aplicado."},selectTypeFirst:"Selecione o tipo de provedor",selectTypeFirstDesc:"Escolha que tipo de provedor deseja adicionar",codeProviderNote:"Provedores de código precisam apenas de chave de API e URL. Os modelos são gerenciados pelo roteador de agentes.",buttons:{cancel:"Cancelar",submitAdd:"Adicionar provedor",submitUpdate:"Atualizar provedor",continue:"Continuar",back:"Voltar"}},details:{noSelection:"Selecione um provedor para ver os detalhes",apiKey:"Chave de API",apiUrl:"URL da API",nameLabel:"Nome do provedor",modelsEndpoint:"Endpoint de modelos",modelsEndpointHelper:"Substitua o endpoint de descoberta se o provedor expuser um caminho /models personalizado.",models:"Modelos",transformers:"Transformadores",codeProviderNote:"Provedores de código (como Claude Code) não requerem configuração de modelos. Os modelos são gerenciados automaticamente pelo roteador de agentes.",buttons:{more:"Mais configurações",delete:"Excluir"}},providerModelSelector:{placeholder:"Selecione provedor e modelo",noProviders:"Nenhum provedor disponível",noModels:"Nenhum modelo configurado"},apiKeyPool:{title:"Pool de chaves de API",description:"Configure várias chaves de API para balanceamento de carga. Cada sessão fica vinculada a uma chave para preservar o cache de prompts.",defaultLabel:"Padrão",weight:"Peso",noKey:"Sem chave",labelPlaceholder:"Rótulo (ex.: Chave nº 1, Produção)",addKey:"Adicionar chave de API",add:"Adicionar",empty:"Nenhuma chave adicional configurada.",statusCoolingDown:"Resfriando {{time}}",statusAuthFailed:"Falha na autenticação · desabilitada",statusDisabled:"Desabilitada",statusHealthy:"Saudável",agoSeconds:"há {{count}}s",agoMinutes:"há {{count}}m",agoHours:"há {{count}}h",agoDays:"há {{count}}d"},modelsManager:{searchPlaceholder:"Pesquisar modelos...",defaultGroup:"Todos os modelos",add:"Adicionar modelo",manage:"Gerenciar",empty:"Nenhum modelo neste grupo",enabled:"Habilitado",disabled:"Desabilitado",filters:{all:"Todos",vision:"Visão",reasoning:"Raciocínio",free:"Gratuito",tools:"Ferramentas"},manualDialog:{title:"Adicionar modelo",subtitle:"Adicione um modelo personalizado a este provedor",modelId:"ID do modelo",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"O identificador exato do modelo usado ao chamar a API",modelName:"Nome de exibição",modelNamePlaceholder:"Nome amigável (opcional)",modelNameHelper:"Nome opcional exibido na interface. Se vazio, o ID do modelo será usado",group:"Grupo",groupPlaceholder:"Selecione ou digite um nome de grupo",submit:"Adicionar",cancel:"Cancelar",helper:"Forneça o identificador exato do modelo exposto pela API do provedor."},editDialog:{title:"Editar modelo",subtitle:"Modificar as configurações do modelo",modelId:"ID do modelo",modelIdPlaceholder:"Identificador do modelo",modelIdHelper:"O identificador do modelo usado ao chamar a API",modelName:"Nome de exibição",modelNamePlaceholder:"Nome amigável",modelNameHelper:"Nome exibido na interface",group:"Grupo",groupPlaceholder:"Selecione ou digite um nome de grupo",submit:"Salvar",cancel:"Cancelar",vision:"Capacidade de visão",visionHint:"Se este modelo suporta entrada de imagens/visão",reasoning:"Modelo de raciocínio",reasoningHint:"Se este modelo suporta o modo de raciocínio/pensamento"},manageDialog:{title:"Gerenciar modelos",cachedAt:"Em cache em {{date}} ({{source}})",refresh:"Atualizar",close:"Fechar",raw:"JSON bruto",empty:"Nenhum modelo remoto disponível.",error:"Falha ao carregar modelos: {{message}}",addFromCatalog:"Adicionar",sourceCache:"cache",sourceNetwork:"ao vivo",contextLength:"Contexto de {{value}} tokens",maxTokens:"Máx. {{value}} tokens"},messages:{added:"Modelo adicionado.",updated:"Modelo atualizado.",removed:"Modelo removido.",duplicate:"O modelo já existe.",refreshed:"Modelos atualizados",refreshFailed:"Falha ao atualizar modelos"},testDialog:{title:"Teste de conectividade do modelo",provider:"Provedor",model:"Modelo",testing:"Testando...",success:"Teste bem-sucedido",successMessage:"O modelo pode ser acessado normalmente",failure:"Teste falhou",aiResponse:"Resposta da IA",charCount:"{{count}} caracteres",duration:"Duração {{time}}s",close:"Fechar",retest:"Testar novamente",testButton:"Testar modelo",unsupportedFormat:"Os testes ainda não são suportados para este formato de provedor."}},router:{title:"Configuração do roteador",description:"Configure qual provedor/modelo usar para cada cenário.",labels:{default:"Padrão",background:"plano de fundo",think:"raciocínio",longContext:"Contexto longo",webSearch:"Pesquisa na web",image:"Imagem",longContextThreshold:"Limiar de contexto longo"},helper:{longContextThreshold:"Quantidade de tokens antes de mudar para o modelo de contexto longo."},placeholder:{required:"Obrigatório",optional:"Opcional"}},agentRouter:{title:"Roteador de agentes",description:"Configure o roteamento bidirecional entre os modos Chat e Código.",searchPlaceholder:"Pesquisar roteadores...",noSearchResults:"Nenhum roteador corresponde à sua pesquisa.",tabs:{chatToCode:"Chat → Código",codeToChatPlaceholder:"Código → Chat"},chatToCode:{title:"Roteador de Chat para Código",description:"Usar provedores de chat no modo agente/codificação",addRouter:"Adicionar roteador",emptyState:"Nenhum roteador Chat→Código configurado. Adicione um para usar provedores de chat no modo de codificação.",form:{name:"Nome do roteador",namePlaceholder:"Meu roteador Chat→Código",chatProvider:"Provedor de chat",chatProviderPlaceholder:"Selecione um provedor de chat",mode:"Modo",modeSimple:"Simples",modeAdvanced:"Avançado",modeSimpleDesc:"Passagem direta para o provedor de chat",modeAdvancedDesc:"Configurar mapeamento de modelos e tratamento de contexto",enabled:"Habilitado",save:"Salvar roteador",cancel:"Cancelar"},list:{provider:"Provedor",mode:"Modo",status:"Status"},mappings:{title:"Mapeamentos de modelos",description:"Mapeie modelos do provedor de Chat para modelos do provedor de Código",count:"mapeamento(s)",empty:"Nenhum mapeamento de modelo configurado. Adicione mapeamentos para rotear modelos de chat a provedores de código.",addNew:"Adicionar novo mapeamento",selectSource:"Selecione o modelo de origem (Chat)",selectTarget:"Selecione o modelo de destino (Código)",targetPlaceholder:"Digite o nome do modelo do Claude Code",notSet:"(Não definido — clique para selecionar)",add:"Adicionar",edit:"Editar",done:"Concluído"},advanced:{title:"Configuração avançada",description:"Configurar modelos para diferentes tipos de tarefas",helpText:"O modelo padrão é obrigatório. Os outros modelos são opcionais e usarão o padrão se não configurados.",default:{label:"Padrão",placeholder:"Selecione o modelo padrão",description:"Modelo principal para tarefas gerais (semelhante ao Claude Sonnet)"},background:{label:"Plano de fundo",placeholder:"Selecione o modelo de plano de fundo",description:"Modelo leve para tarefas em segundo plano (semelhante ao Claude Haiku)"},think:{label:"Raciocínio",placeholder:"Selecione o modelo de raciocínio",description:"Modelo avançado para raciocínio complexo (semelhante ao Claude Opus)"},image:{label:"Imagem",placeholder:"Selecione o modelo de imagem",description:"Modelo para tarefas relacionadas a imagens com capacidade de visão"}}},codeToChat:{title:"Roteador de Código para Chat",description:"Expor modelos do Plano de codificação no modo chat",addRouter:"Adicionar roteador",emptyState:"Nenhum roteador Código→Chat configurado. Adicione um para expor modelos do Plano de codificação no modo chat.",form:{name:"Nome do roteador",namePlaceholder:"Meu roteador Código→Chat",codeProvider:"Provedor de código",codeProviderPlaceholder:"Selecione um provedor de código",codeProviderHelper:"Selecione o provedor de código a ser usado para transformação",models:"Modelos do plano de codificação",modelsHelper:"Selecione quais modelos do Plano de codificação deseja expor",enabled:"Habilitado",save:"Salvar roteador",cancel:"Cancelar"},mappings:{title:"Mapeamentos de modelos",description:"Mapeie modelos do provedor de Código para modelos do provedor de Chat para exposição",count:"mapeamento(s)",empty:"Nenhum mapeamento de modelo configurado. Adicione mapeamentos para expor modelos de código no modo chat.",addNew:"Adicionar novo mapeamento",selectSource:"Selecione o modelo de origem (Código)",selectTarget:"Selecione o modelo de destino (Chat)",sourcePlaceholder:"Digite o nome do modelo de origem",targetPlaceholder:"Digite o nome do modelo de destino",add:"Adicionar",edit:"Editar",done:"Concluído"}},transformers:{title:"Transformadores",description:"Configure transformadores para conversão de requisições/respostas",noProvider:"Selecione um provedor para configurar os transformadores",empty:"Sem transformadores",count:"{{count}} transformador(es)"},status:{enabled:"Habilitado",disabled:"Desabilitado"},messages:{routerAdded:"Roteador adicionado com sucesso",routerUpdated:"Roteador atualizado com sucesso",routerDeleted:"Roteador excluído com sucesso",saveFailed:"Falha ao salvar o roteador"}},presets:{title:"Adicionar provedor rapidamente",added:"Adicionado",add:"Adicionar",features:{search:"Pesquisa",vision:"Visão",mcp:"MCP",codingPlan:"Plano de codificação"}},alerts:{deleteConfirm:"Tem certeza que deseja excluir este provedor?"},errors:{nameRequired:"O nome do provedor é obrigatório",urlRequired:"A URL base da API é obrigatória",urlInvalid:"Digite uma URL válida (ex.: https://api.example.com)",saveFailed:"Falha ao salvar o provedor",deleteFailed:"Erro ao excluir o provedor. Por favor, tente novamente.",toggleFailed:"Erro ao ativar/desativar o provedor. Por favor, tente novamente."},openRouter:{title:"Roteamento de provedores do OpenRouter",description:"Configure como as requisições são roteadas para diferentes provedores no OpenRouter.",sort:"Estratégia de roteamento",sortTooltip:"Escolha como priorizar os provedores. Auto usa balanceamento de carga inteligente.",order:"Ordem de prioridade dos provedores",orderTooltip:"Especifique os provedores a tentar em ordem (ex.: anthropic, openai, together). Pressione Enter para adicionar.",orderPlaceholder:"Digite o slug do provedor e pressione Enter...",allowFallbacks:"Permitir alternativas",allowFallbacksTooltip:"Quando habilitado, o OpenRouter tentará provedores de backup se o principal estiver indisponível.",requireParameters:"Exigir todos os parâmetros",requireParametersTooltip:"Rotear apenas para provedores que suportam todos os parâmetros da sua requisição.",dataCollection:"Política de coleta de dados",dataCollectionTooltip:"Controle se provedores que podem armazenar ou treinar com seus dados são usados.",zdr:"Retenção zero de dados",zdrTooltip:"Rotear apenas para endpoints com política de retenção zero de dados.",only:"Usar apenas estes provedores",onlyTooltip:"Usar somente estes provedores específicos. Deixe vazio para permitir todos os provedores.",onlyPlaceholder:"Digite o slug do provedor e pressione Enter...",ignore:"Ignorar provedores",ignoreTooltip:"Pular estes provedores ao rotear requisições.",ignorePlaceholder:"Digite o slug do provedor e pressione Enter...",quantizations:"Filtro de quantização",quantizationsTooltip:"Usar apenas provedores com níveis de quantização específicos. Menor precisão pode reduzir a qualidade mas melhorar a velocidade.",maxPrice:"Preço máximo",maxPriceTooltip:"Defina limites de preço máximo por milhão de tokens. Deixe vazio para sem limite.",configured:"Configurado"}},IS={label:"Modo de API",standard:"Padrão",codingPlan:"Plano de codificação",tokenPlan:"Plano de tokens",apiKeyPrefixHint:"As chaves deste plano geralmente começam com `{{prefix}}`. Apenas informativo — não aplicado.",dashscopeCodingPlanSeparateKey:"O Plano de codificação do DashScope usa uma chave de API separada do endpoint padrão.",baiduCodingPlanSeparateKey:"O Plano de codificação do Qianfan usa uma chave de API separada do endpoint padrão.",tencentTokenPlanAnthropicOnly:"O Plano de tokens da Tencent é compatível apenas com o protocolo Anthropic.",xiaomiTokenPlanRegions:"A baseUrl padrão é `token-plan-cn.*`. Você pode editá-la manualmente para `token-plan-sgp.*` ou `token-plan-ams.*`.",confirmOverwriteTitle:"Alterar o modo de API?",confirmOverwriteBody:"Você personalizou a URL da API ou a chave de API. Trocar de modo as substituirá pelos padrões do novo modo — ou mantenha suas personalizações e apenas atualize o rótulo do modo.",overwriteAndSwitch:"Substituir e trocar",keepCustomizations:"Manter personalizações"},SS={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Plano de tokens)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},wS={cancel:"Cancelar",close:"Fechar",copy:"Copiar",delete:"Excluir",dismiss:"Dispensar",save:"Salvar",optional:"opcional",retry:"Tentar novamente",loading:"Carregando…"},TS={common:{learnMore:"Documentação"}},jS={notSupportedByDaemon:"Ainda não suportado pelo daemon",discoveryUnsupportedFormat:"A descoberta de modelos ainda não é suportada para este formato de provedor. Adicione os modelos manualmente."},MS={subtitle:"Painel de controle",providers:"Provedores",apiService:"Serviço de API",accounts:"Contas",codeCli:"CLI de código",settings:"Configurações",usageStats:"Uso",pricing:"Preços"},NS={title:"Serviço de API",description:"Configure o servidor de API de saída, o roteamento de modelos por endpoint e as chaves de acesso nomeadas.",loading:"Carregando configuração do servidor…",loadError:"Não foi possível carregar a configuração do servidor. Verifique se o daemon está acessível.",enable:{label:"Habilitar servidor de saída",description:"Inicia o servidor de API local que roteia chamadas externas pelos seus provedores."},networkBinding:{label:"Permitir acesso pela rede local",description:"Vincule o servidor à sua interface de rede em vez de apenas ao loopback.",warning:"O acesso pela rede local expõe o servidor de API a outros dispositivos na sua rede. Combinado com o roteamento de assinaturas, as requisições podem consumir sua cota de assinatura — mantenha desabilitado a menos que confie na rede."},status:{running:"Servidor em execução",stopped:"Servidor parado",runningHint:"O servidor de API de saída está aceitando requisições.",stoppedHint:"Habilite o servidor para começar a aceitar requisições.",port:"porta {{port}}",loopback:"URLs de loopback",lan:"URLs de rede local"},endpoints:{title:"Roteamento de endpoints",description:"Escolha o modelo para o qual cada formato de rede roteia. O modelo padrão é configurado aqui — o servidor é um roteador, não um app de chat."},endpoint:{name:{chat:"Chat da OpenAI",responses:"Respostas da OpenAI",messages:"Mensagens da Anthropic",gemini:"Gemini"},defaultModel:"Modelo padrão",backgroundModel:"Modelo de plano de fundo",visionModel:"Modelo de visão",noVisionModel:"Nenhum",backgroundModelIds:"IDs de modelos de plano de fundo",backgroundModelIdsPlaceholder:"IDs de modelos separados por vírgula",modelPlaceholder:"Selecione um modelo…",useSubscription:"Usar assinatura",subscriptionUnsupported:"O roteamento por assinatura não está disponível para este endpoint."},keys:{title:"Chaves de acesso",description:"Chaves nomeadas que clientes externos enviam como token Bearer. A chave completa é exibida apenas uma vez ao criar.",namePlaceholder:"Nome da chave (ex.: meu-cli)",create:"Criar chave",empty:"Nenhuma chave de acesso ainda.",enabled:"Habilitada",disabled:"Desabilitada",revoked:"Revogada",toggle:"Ativar/desativar chave",revoke:"Revogar",revokeConfirmTitle:"Revogar esta chave?",revokeConfirmDesc:'Revogar "{{name}}" impede imediatamente sua autenticação. Isso não pode ser desfeito.',created:{title:"Chave criada",warning:"Copie esta chave agora — ela não será exibida novamente. Armazene-a com segurança.",copy:"Copiar",copied:"Copiado",dismiss:"Concluído"}}},LS={title:"Contas e assinaturas",description:"Gerencie as credenciais de assinatura pelas quais o servidor roteia. Os tokens são registrados aqui, mas nunca exibidos novamente.",loading:"Carregando contas…",empty:"Nenhum provedor de assinatura disponível.",signIn:"Entrar",oauth:{title:"Entrar em {{name}}",description:"Abra a página de login no seu navegador, autorize e cole o código de autorização abaixo. O código vai apenas para o daemon — o token gerado nunca é exibido.",openPage:"Abrir página de login",codeLabel:"Código de autorização",codePlaceholder:"Cole o código aqui",submit:"Concluir login"},codexOauth:{title:"Entrar em {{name}}",description:"Abra a página de login no seu navegador e autorize. O daemon captura o resultado automaticamente — mantenha esta janela aberta até concluir. O token nunca é exibido.",waiting:"Aguardando você concluir o login no seu navegador…",failed:"Falha no login. Por favor, tente novamente."},clearProvider:"Limpar tudo",clearConfirmTitle:"Limpar contas de {{name}}?",clearConfirmDesc:"Isso remove todas as credenciais armazenadas para este provedor. Isso não pode ser desfeito.",credential:{ok:"Configurada",notConfigured:"Não configurada"},kind:{"pass-through":"Credenciais de passagem direta","oauth-bearer":"Bearer OAuth","static-bearer":"Chave bearer estática"},reason:{"missing-credential":"Nenhuma credencial armazenada.",expired:"Credencial expirada.","reauth-required":"Reautenticação necessária.","refresh-failed":"Falha ao renovar o token.","not-refreshable":"A credencial não pode ser renovada.",unknown:"Status desconhecido."},status:{unconfigured:"Não configurada",authorized:"Autorizada",configured:"Configurada",expired:"Expirada",error:"Erro"},authMethod:{oauth:"OAuth",setup_token:"Token de configuração",manual:"Manual"},list:{empty:"Nenhuma conta armazenada para este provedor.",active:"Ativa",expiresAt:"Expira {{value}}",setActive:"Definir como ativa",remove:"Remover",removeConfirmTitle:"Remover esta conta?",removeConfirmDesc:'Remover "{{name}}" exclui a credencial armazenada. Isso não pode ser desfeito.',title:"Contas"},write:{trigger:"Adicionar credencial",title:"Gravar credencial de {{name}}",description:"Cole o material do token já obtido. Os campos são limitados ao que este provedor aceita; o token é armazenado e nunca exibido novamente.",authMethod:"Método de autenticação",status:"Status",subscriptionLevel:"Nível de assinatura",subscriptionLevelNone:"Não definido",submit:"Salvar credencial"},field:{accessToken:"Token de acesso",refreshToken:"Token de atualização",idToken:"Token de ID",apiKey:"Chave de API",expiresAt:"Expira em (ISO)",setupTokenExpiresAt:"Token de configuração expira em (ISO)",accountId:"ID da conta",email:"E-mail",organizationId:"ID da organização",baseUrl:"URL base",zenBaseUrl:"URL base do Zen"},provider:{claude:{title:"Claude",description:"Credenciais de assinatura da Anthropic roteadas pelo daemon."},codex:{title:"Codex",description:"Credenciais de assinatura do OpenAI Codex roteadas pelo daemon."},gemini:{title:"Gemini",description:"Credenciais de assinatura do Google Gemini roteadas pelo daemon."},opencodego:{title:"OpenCodeGo",description:"Credenciais de chave de API estática roteadas pelo daemon."}},authMethodLabel:"Método de autorização",authMethodDesc:{oauth:"Entre pelo seu navegador; o daemon captura e armazena o token.",manual:"Cole um token já obtido. Ele é armazenado e nunca exibido novamente."},actions:{authorize:"Autorizar",enterToken:"Inserir token",refresh:"Atualizar"},accounts:{addAccount:"Adicionar conta"},detail:{authMethod:"Método de autorização",subscriptionLevel:"Nível de assinatura",expiresAt:"Expira",lastRefreshed:"Última atualização",label:"Rótulo da conta",labelPlaceholder:"Dê um nome a esta conta",saveLabel:"Salvar rótulo"},oauthFlow:{step1:{title:"Abra a página de autorização",desc:"Abra a página de login no seu navegador."},step2:{title:"Autorize o acesso",desc:"Entre e aprove o acesso para o provedor."},step3:{title:"Copie o código de autorização",desc:"A página exibe um código de autorização após sua aprovação."},step4:{title:"Cole o código",desc:"Cole o código de autorização abaixo para concluir. O código vai apenas para o daemon — o token gerado nunca é exibido."},authorize:"Concluir login",showUrl:"Mostrar URL de autorização"},manual:{title:"Colar credencial",description:"Cole um token já obtido. Os campos são limitados ao que este provedor aceita; o token é armazenado e nunca exibido novamente.",accessTokenPlaceholder:"Cole o token de acesso",refreshTokenPlaceholder:"Cole o token de atualização (opcional)",hint:"O token é enviado ao daemon e armazenado criptografado. Nunca é exibido novamente."},openCodeGo:{apiKeyRequired:"Uma chave de API é necessária.",apiKeyPlaceholder:"Cole a chave de API",baseUrlPlaceholder:"https://… (opcional)",zenBaseUrlPlaceholder:"https://… (opcional)"},info:{title:"Sobre contas de assinatura",description:"Os tokens são gravados no daemon e usados para autenticar requisições de destino. São armazenados criptografados e nunca exibidos novamente. Remover uma conta exclui sua credencial armazenada."},rename:{failed:"Não foi possível renomear a conta."},refresh:{failed:"Não foi possível atualizar o token."},errors:{requestFailed:"A requisição falhou. Por favor, tente novamente."},syncWarning:{"external-divergent":"O arquivo de login da CLI externa contém credenciais mais recentes que esta conta. O token armazenado pode parar de ser renovado — renove agora ou entre novamente.","external-not-rotated":"A renovação falhou e a CLI externa contém a mesma credencial expirada. Entre novamente.","duplicate-token":"Outra conta compartilha esta credencial. Renovar qualquer uma delas desconectará a outra."},importExternal:{detected:"Um login de CLI do {{name}} existente foi encontrado nesta máquina.",hint:"Após a importação, este aplicativo o mantém atualizado: a cada renovação do token, o arquivo de login da CLI também é atualizado, e a CLI do terminal permanece conectada.",button:"Importar login de CLI existente"}},RS={title:"CLI de código",description:"Aponte uma CLI de codificação para o proxy de saída do daemon. Esta página é somente leitura — não há nada a configurar aqui.",copy:"Copiar",copied:"Copiado",baseUrl:{title:"URL base do daemon",description:"O endereço do proxy ao qual sua CLI se conecta.",label:"URL base"},token:{title:"Autenticação",hint:"Envie 'Authorization: Bearer <seu-token-de-admin>' para rotas administrativas. O token de admin é configurado no daemon (seu arquivo de configuração ou ambiente) — nunca é exibido aqui."},examples:{title:"Exemplo de ambiente de lançamento",keyNote:"Use uma chave de acesso de saída criada na página do Serviço de API — não o token de admin.",anthropic:"CLI no formato Anthropic",openai:"CLI no formato OpenAI"},launchDescription:"Lance uma CLI de codificação em um terminal apontado para este daemon. O daemon injeta o ambiente de redirecionamento e inicia a CLI automaticamente.",refresh:"Atualizar",loading:"Detectando CLIs…",cli:{installed:"Instalada",notFound:"Não encontrada",notFoundHint:"Esta CLI não está no PATH do host do daemon. Instale-a e atualize.",install:"Instalar",installing:"Instalando…",installingHint:"Instalando no host do daemon — isso pode levar um momento.",launch:"Iniciar",launchTitle:"Iniciar {{name}}",launchDescription:"Abre um novo terminal no host do daemon executando esta CLI, roteada pelo proxy do daemon. Escolha um diretório de trabalho opcional.",cwdLabel:"Diretório de trabalho",cwdPlaceholder:"/caminho/para/seu/projeto",runningVia:"Em execução · {{provider}} / {{model}}",stop:"Parar"},manual:{title:"Configuração manual",description:"Prefere executar a CLI você mesmo? Aponte-a para o daemon com estas variáveis de ambiente.",show:"Mostrar",hide:"Ocultar"}},DS={probing:"Verificando se o daemon está disponível…",spawning:"Iniciando o daemon…",failed:"O daemon não pôde ser iniciado",failedHint:"Certifique-se de que o Node.js está instalado e o daemon está compilado (dist presente), ou defina OMNICROSS_DAEMON_ENTRY para o cli.js do daemon."},ES={title:"Configurações",description:"Preferências do aplicativo desktop.",desktopOnly:"As opções de inicialização e bandeja se aplicam apenas no aplicativo desktop.",startup:{title:"Inicialização",autoLaunch:"Iniciar ao fazer login",autoLaunchHint:"Inicia o Omnicross automaticamente quando você faz login.",startMinimized:"Iniciar minimizado na bandeja",startMinimizedHint:"Abre em segundo plano sem exibir a janela."},tray:{title:"Bandeja do sistema",minimizeOnClose:"Minimizar para a bandeja ao fechar",minimizeOnCloseHint:"Fechar a janela a oculta na bandeja em vez de sair."},language:{title:"Idioma",label:"Idioma da interface"}},OS={title:"Estatísticas de uso",description:"Estatísticas de tokens e custos das solicitações atendidas pelo daemon.",rangeToday:"Hoje",range7d:"Últimos 7 dias",range30d:"Últimos 30 dias",rangeCustom:"Personalizado",from:"De",to:"Até",totalCost:"Custo total",cacheSavings:"Economia de cache",events:"Solicitações",inputTokens:"Tokens de entrada",outputTokens:"Tokens de saída",cacheReadTokens:"Leitura de cache",cacheWriteTokens:"Gravação de cache",reasoningTokens:"Tokens de raciocínio",byModel:"Por modelo",byApiKey:"Por chave de API",provider:"Provedor",model:"Modelo",cost:"Custo",apiKey:"Chave de API",unpriced:"Sem preço",unpricedHint:"Não existe entrada de preço para este modelo — adicione uma na página de Preços.",unattributed:"Não atribuído",unattributedHint:"Solicitações não vinculadas a uma chave de API específica. Isso é esperado até que a atribuição por chave seja registrada.",empty:"Nenhuma solicitação neste período.",invalidRange:"Selecione um intervalo de datas válido."},KS={title:"Preços de modelos",description:"Preços de tokens por modelo usados para calcular o custo das solicitações, em USD por milhão de tokens.",search:"Pesquisar provedor ou modelo…",fetchLatest:"Buscar mais recentes",fetching:"Buscando…",addEntry:"Adicionar entrada",provider:"Provedor",model:"Modelo",inputPrice:"Entrada",outputPrice:"Saída",cacheReadPrice:"Leitura de cache",cacheWritePrice:"Gravação de cache",source:"Fonte",updated:"Atualizado",userEdited:"editado",edit:"Editar",deleteTitle:"Excluir esta entrada de preço?",empty:"A tabela de preços está vazia.",emptyHint:"Busque os preços mais recentes para preenchê-la.",noMatches:"Nenhuma entrada corresponde à sua pesquisa.",saved:"Entrada de preço salva.",saveFailed:"Falha ao salvar: {{message}}",deleteFailed:"Falha ao excluir: {{message}}",alreadyDeleted:"A entrada já não existia.",fetchApplied:"{{count}} entradas atualizadas a partir da fonte.",fetchFailed:"Falha ao buscar: {{message}}",requiredId:"Obrigatório",invalidPrice:"Insira um número não negativo",conflictTitle:"Resolver conflitos de preços",conflictHint:"Estas entradas foram editadas por você e também mudaram na fonte. Escolha por linha se mantém seu valor (Ignorar) ou adota o novo (Sobrescrever).",current:"Atual",incoming:"Recebido",overwrite:"Sobrescrever",skip:"Ignorar",overwriteAll:"Sobrescrever tudo",skipAll:"Ignorar tudo",applyResolutions:"Aplicar",resolved:"{{overwritten}} sobrescritas, {{skipped}} ignoradas.",resolvedWithStale:"{{overwritten}} sobrescritas, {{skipped}} ignoradas. {{stale}} mudaram nesse meio-tempo e ficaram intactas.",refreshFailed:"A alteração foi aplicada, mas falhou ao recarregar a lista: {{message}}",sourceBuiltin:"Integrado",sourceLitellm:"LiteLLM",sourceUser:"Usuário"},US={providerSettings:zS,apiMode:IS,presetName:SS,common:wS,mediaSettings:TS,appLocal:jS,nav:MS,apiService:NS,accounts:LS,codeCli:RS,daemonStatus:DS,settings:ES,usageStats:OS,pricing:KS},HS={loading:"A carregar configuração LLM...",reset:{button:"Restaurar predefinições",confirmTitle:"Restaurar definições predefinidas?",confirmBody:"Isto limpa as suas personalizações para este fornecedor, que volta a seguir as predefinições incorporadas. A sua chave API e sessões guardadas são mantidas.",confirmButton:"Restaurar predefinições"},reentryBanner:{message:"{{count}} fornecedor(es) activo(s) necessitam que a chave API seja introduzida novamente. Abra cada um e adicione novamente a respectiva chave."},migrationPack:{barHint:"Mova as suas chaves de fornecedor e tokens de subscrição para outra máquina com um pacote encriptado.",passphrase:"Frase-passe",passphrasePlaceholder:"Introduza uma frase-passe",passphraseHint:"Utilize pelo menos 8 caracteres; recomenda-se 12 ou mais.",confirm:"Confirmar frase-passe",confirmPlaceholder:"Reintroduza a frase-passe",mismatch:"As frases-passe não coincidem.",strength:{weak:"Demasiado curta — utilize pelo menos 8 caracteres.",fair:"Razoável — 12 ou mais caracteres é mais seguro.",strong:"Frase-passe forte."},export:{button:"Exportar pacote",title:"Exportar pacote encriptado",subtitle:"Encripte as suas chaves de fornecedor e tokens de subscrição num ficheiro portátil.",warning:"Este ficheiro contém segredos desencriptáveis. Mantenha-o em segurança — qualquer pessoa com o ficheiro e a frase-passe pode ler as suas chaves. Uma frase-passe perdida não pode ser recuperada.",submit:"Exportar",success:"Pacote exportado com sucesso.",error:"A exportação falhou. Por favor tente novamente."},import:{button:"Importar pacote",title:"Importar pacote encriptado",subtitle:"Restaure chaves de fornecedor e tokens de subscrição a partir de um pacote exportado.",hint:"Introduza a frase-passe utilizada quando o pacote foi exportado e escolha o ficheiro.",submit:"Importar",successTitle:"Importação concluída",summary:"Importadas {{providerKeys}} chave(s) de fornecedor, {{poolKeys}} chave(s) de conjunto e {{tokenSets}} conjunto(s) de tokens.",duplicates:"Ignoradas {{count}} chave(s) de conjunto já presentes.",skipped:"Ignorado (sem fornecedor correspondente): {{names}}",error:"Frase-passe incorrecta ou pacote corrompido. Nada foi alterado."}},searchPlaceholder:"Pesquisar fornecedores...",emptySearch:"Nenhum fornecedor corresponde à sua pesquisa.",emptyList:"Nenhum fornecedor configurado.",selectPrompt:"Seleccione um fornecedor para ver os detalhes",listStatus:"{{count}} modelo(s)",noModels:"Nenhum modelo configurado",enabled:"Activo",disabled:"Inactivo",showEnabledOnly:"Mostrar apenas activos",showAll:"Mostrar todos os fornecedores",dragHandle:"Arrastar para reordenar",reorderFailed:"Falha ao guardar a ordem dos fornecedores",credentials:{apiKey:"Chave API",apiBaseUrl:"URL base da API"},filter:{all:"Todos",chat:"Chat",code:"Código"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Seleccionar um modelo",skipTemplates:"Ignorar, configurar manualmente",name:"Nome *",providerType:"Tipo",apiType:"Tipo de API",apiTypeOptions:{openai:"Conclusão OpenAI",claudecode:"Claude Code"},apiTypeDescription:{openai:"Formato padrão de API de chat/completions OpenAI",claudecode:"Formato de API de mensagens Anthropic (Claude Code)"},chatApiFormat:"Formato de API",chatApiFormatDescription:"Seleccione o formato de API que corresponde ao endpoint do seu fornecedor",apiKey:"Chave API",apiKeyPlaceholder:"sk-... ou $VAR_AMBIENTE",apiKeyHelper:"Utilize $NOME_VAR para referenciar variáveis de ambiente",apiKeySetPlaceholder:"Chave definida — deixe em branco para manter",apiKeyReplaceHelper:"Existe uma chave armazenada de forma segura. Digite um novo valor para substituir ou deixe em branco para manter.",testApiKey:"Testar chave API",apiUrl:"URL da API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Pré-visualização:",models:"Modelos",modelPlaceholder:"Nome do modelo (ex.: gpt-4, claude-3-opus)",transformers:"Transformadores",transformerConfig:"Transformadores de API",transformerConfigDescription:"Configure transformadores para adaptar os formatos de pedido/resposta da API para este fornecedor",transformerConfigNote:"O daemon aplica estes transformadores na cadeia de pedidos, após o transformador de formato do fornecedor (que trata da conversão do formato wire). Nomes de transformadores desconhecidos são ignorados.",enabled:"Activo",apiVersion:"Versão da API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versão da API Azure OpenAI (ex.: 2024-08-01-preview)",official:"API Anthropic oficial",officialHelper:"Active se este fornecedor se ligar directamente à API Anthropic oficial. Desactive para proxies inversos ou serviços de terceiros.",maxConcurrency:"Máximo de pedidos simultâneos",maxConcurrencyHelper:"Número máximo de pedidos API simultâneos enviados para este fornecedor. Valores mais baixos ajudam a evitar limitação de taxa (erros 429). Defina `-1` para sem limite.",codingPlan:{label:"Plano de programação",description:"Utilizar um endpoint de API separado para planos de programação baseados em subscrição",baseUrl:"URL base do plano de programação",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Chave API do plano de programação (opcional)",apiKeyPlaceholder:"Deixar vazio para usar a chave API do fornecedor",apiKeyHelper:"Apenas necessário se o plano de programação utilizar uma chave API diferente",tokenPlanHint:"Alguns fornecedores (ex.: Xiaomi MiMo) emitem chaves Token Plan com prefixo `tp-` — apenas informativo, não é aplicado."},selectTypeFirst:"Seleccionar tipo de fornecedor",selectTypeFirstDesc:"Escolha o tipo de fornecedor que pretende adicionar",codeProviderNote:"Os fornecedores de código apenas necessitam de chave API e URL. Os modelos são geridos pelo Router de Agente.",buttons:{cancel:"Cancelar",submitAdd:"Adicionar fornecedor",submitUpdate:"Actualizar fornecedor",continue:"Continuar",back:"Voltar"}},details:{noSelection:"Seleccione um fornecedor para ver os detalhes",apiKey:"Chave API",apiUrl:"URL da API",nameLabel:"Nome do fornecedor",modelsEndpoint:"Endpoint de modelos",modelsEndpointHelper:"Substitua o endpoint de descoberta se o fornecedor expuser um caminho /models personalizado.",models:"Modelos",transformers:"Transformadores",codeProviderNote:"Os fornecedores de código (como o Claude Code) não necessitam de configuração de modelos. Os modelos são automaticamente geridos pelo Router de Agente.",buttons:{more:"Mais definições",delete:"Eliminar"}},providerModelSelector:{placeholder:"Seleccionar fornecedor e modelo",noProviders:"Nenhum fornecedor disponível",noModels:"Nenhum modelo configurado"},apiKeyPool:{title:"Conjunto de chaves API",description:"Configure múltiplas chaves API para balanceamento de carga. Cada sessão mantém uma chave para preservar a cache de prompts.",defaultLabel:"Predefinição",weight:"Peso",noKey:"Sem chave",labelPlaceholder:"Etiqueta (ex.: Chave nº 1, Produção)",addKey:"Adicionar chave API",add:"Adicionar",empty:"Nenhuma chave adicional configurada.",statusCoolingDown:"Em arrefecimento {{time}}",statusAuthFailed:"Autenticação falhada · inactivo",statusDisabled:"Inactivo",statusHealthy:"Operacional",agoSeconds:"há {{count}}s",agoMinutes:"há {{count}}m",agoHours:"há {{count}}h",agoDays:"há {{count}}d"},modelsManager:{searchPlaceholder:"Pesquisar modelos...",defaultGroup:"Todos os modelos",add:"Adicionar modelo",manage:"Gerir",empty:"Nenhum modelo neste grupo",enabled:"Activo",disabled:"Inactivo",filters:{all:"Todos",vision:"Visão",reasoning:"Raciocínio",free:"Gratuito",tools:"Ferramentas"},manualDialog:{title:"Adicionar modelo",subtitle:"Adicionar um modelo personalizado a este fornecedor",modelId:"ID do modelo",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, etc.",modelIdHelper:"O identificador exacto do modelo utilizado ao chamar a API",modelName:"Nome de apresentação",modelNamePlaceholder:"Nome de apresentação amigável (opcional)",modelNameHelper:"Nome opcional mostrado na interface. Se vazio, será utilizado o ID do modelo",group:"Grupo",groupPlaceholder:"Seleccionar ou introduzir um nome de grupo",submit:"Adicionar",cancel:"Cancelar",helper:"Forneça o identificador exacto do modelo exposto pela API do fornecedor."},editDialog:{title:"Editar modelo",subtitle:"Modificar definições do modelo",modelId:"ID do modelo",modelIdPlaceholder:"Identificador do modelo",modelIdHelper:"O identificador do modelo utilizado ao chamar a API",modelName:"Nome de apresentação",modelNamePlaceholder:"Nome de apresentação amigável",modelNameHelper:"Nome mostrado na interface",group:"Grupo",groupPlaceholder:"Seleccionar ou introduzir um nome de grupo",submit:"Guardar",cancel:"Cancelar",vision:"Capacidade de visão",visionHint:"Se este modelo suporta entrada de imagem/visão",reasoning:"Modelo de raciocínio",reasoningHint:"Se este modelo suporta modo de pensamento/raciocínio"},manageDialog:{title:"Gerir modelos",cachedAt:"Em cache a {{date}} ({{source}})",refresh:"Actualizar",close:"Fechar",raw:"JSON em bruto",empty:"Nenhum modelo remoto disponível.",error:"Falha ao carregar modelos: {{message}}",addFromCatalog:"Adicionar",sourceCache:"cache",sourceNetwork:"em directo",contextLength:"Contexto {{value}} tokens",maxTokens:"Máx. {{value}} tokens"},messages:{added:"Modelo adicionado.",updated:"Modelo actualizado.",removed:"Modelo removido.",duplicate:"O modelo já existe.",refreshed:"Modelos actualizados",refreshFailed:"Falha ao actualizar modelos"},testDialog:{title:"Teste de conectividade do modelo",provider:"Fornecedor",model:"Modelo",testing:"A testar...",success:"Teste bem-sucedido",successMessage:"O modelo pode ser acedido normalmente",failure:"Teste falhado",aiResponse:"Resposta da IA",charCount:"{{count}} caracteres",duration:"Duração {{time}}s",close:"Fechar",retest:"Testar novamente",testButton:"Testar modelo",unsupportedFormat:"O teste ainda não é suportado para este formato de fornecedor."}},router:{title:"Configuração do router",description:"Configure o fornecedor/modelo a utilizar para diferentes cenários.",labels:{default:"Predefinição",background:"segundo plano",think:"raciocínio",longContext:"Contexto longo",webSearch:"Pesquisa web",image:"Imagem",longContextThreshold:"Limiar de contexto longo"},helper:{longContextThreshold:"Contagem de tokens antes de mudar para o modelo de contexto longo."},placeholder:{required:"Obrigatório",optional:"Opcional"}},agentRouter:{title:"Router de agente",description:"Configure o encaminhamento bidirecional entre os modos Chat e Código.",searchPlaceholder:"Pesquisar routers...",noSearchResults:"Nenhum router corresponde à sua pesquisa.",tabs:{chatToCode:"Chat → Código",codeToChatPlaceholder:"Código → Chat"},chatToCode:{title:"Router de Chat para Código",description:"Utilizar fornecedores de chat no modo agente/programação",addRouter:"Adicionar router",emptyState:"Nenhum router Chat→Código configurado. Adicione um para utilizar fornecedores de chat no modo de programação.",form:{name:"Nome do router",namePlaceholder:"O meu router Chat→Código",chatProvider:"Fornecedor de chat",chatProviderPlaceholder:"Seleccionar um fornecedor de chat",mode:"Modo",modeSimple:"Simples",modeAdvanced:"Avançado",modeSimpleDesc:"Passagem directa para o fornecedor de chat",modeAdvancedDesc:"Configurar mapeamento de modelos e tratamento de contexto",enabled:"Activo",save:"Guardar router",cancel:"Cancelar"},list:{provider:"Fornecedor",mode:"Modo",status:"Estado"},mappings:{title:"Mapeamentos de modelos",description:"Mapear modelos do fornecedor de chat para modelos do fornecedor de código",count:"mapeamento(s)",empty:"Nenhum mapeamento de modelos configurado. Adicione mapeamentos para encaminhar modelos de chat para fornecedores de código.",addNew:"Adicionar novo mapeamento",selectSource:"Seleccionar modelo de origem (Chat)",selectTarget:"Seleccionar modelo de destino (Código)",targetPlaceholder:"Introduzir nome do modelo Claude Code",notSet:"(Não definido — clique para seleccionar)",add:"Adicionar",edit:"Editar",done:"Concluído"},advanced:{title:"Configuração avançada",description:"Configurar modelos para diferentes tipos de tarefas",helpText:"O modelo predefinido é obrigatório. Os outros modelos são opcionais e reverterão para o predefinido se não configurados.",default:{label:"Predefinição",placeholder:"Seleccionar modelo predefinido",description:"Modelo principal para tarefas gerais (semelhante ao Claude Sonnet)"},background:{label:"Segundo plano",placeholder:"Seleccionar modelo de segundo plano",description:"Modelo leve para tarefas em segundo plano (semelhante ao Claude Haiku)"},think:{label:"Raciocínio",placeholder:"Seleccionar modelo de raciocínio",description:"Modelo avançado para raciocínio complexo (semelhante ao Claude Opus)"},image:{label:"Imagem",placeholder:"Seleccionar modelo de imagem",description:"Modelo para tarefas relacionadas com imagens com capacidade de visão"}}},codeToChat:{title:"Router de Código para Chat",description:"Expor modelos do Plano de Programação no modo chat",addRouter:"Adicionar router",emptyState:"Nenhum router Código→Chat configurado. Adicione um para expor modelos do Plano de Programação no modo chat.",form:{name:"Nome do router",namePlaceholder:"O meu router Código→Chat",codeProvider:"Fornecedor de código",codeProviderPlaceholder:"Seleccionar um fornecedor de código",codeProviderHelper:"Seleccionar o fornecedor de código a utilizar para a transformação",models:"Modelos do plano de programação",modelsHelper:"Seleccionar quais os modelos do Plano de Programação a expor",enabled:"Activo",save:"Guardar router",cancel:"Cancelar"},mappings:{title:"Mapeamentos de modelos",description:"Mapear modelos do fornecedor de código para modelos do fornecedor de chat para exposição",count:"mapeamento(s)",empty:"Nenhum mapeamento de modelos configurado. Adicione mapeamentos para expor modelos de Código no modo chat.",addNew:"Adicionar novo mapeamento",selectSource:"Seleccionar modelo de origem (Código)",selectTarget:"Seleccionar modelo de destino (Chat)",sourcePlaceholder:"Introduzir nome do modelo de origem",targetPlaceholder:"Introduzir nome do modelo de destino",add:"Adicionar",edit:"Editar",done:"Concluído"}},transformers:{title:"Transformadores",description:"Configurar transformadores para conversão de pedido/resposta",noProvider:"Seleccione um fornecedor para configurar transformadores",empty:"Nenhum transformador",count:"{{count}} transformador(es)"},status:{enabled:"Activo",disabled:"Inactivo"},messages:{routerAdded:"Router adicionado com sucesso",routerUpdated:"Router actualizado com sucesso",routerDeleted:"Router eliminado com sucesso",saveFailed:"Falha ao guardar o router"}},presets:{title:"Adicionar fornecedor rapidamente",added:"Adicionado",add:"Adicionar",features:{search:"Pesquisa",vision:"Visão",mcp:"MCP",codingPlan:"Plano de programação"}},alerts:{deleteConfirm:"Tem a certeza de que pretende eliminar este fornecedor?"},errors:{nameRequired:"O nome do fornecedor é obrigatório",urlRequired:"O URL base da API é obrigatório",urlInvalid:"Introduza um URL válido (ex.: https://api.example.com)",saveFailed:"Falha ao guardar o fornecedor",deleteFailed:"Erro ao eliminar o fornecedor. Por favor tente novamente.",toggleFailed:"Erro ao alternar o fornecedor. Por favor tente novamente."},openRouter:{title:"Encaminhamento de fornecedores OpenRouter",description:"Configure como os pedidos são encaminhados para diferentes fornecedores no OpenRouter.",sort:"Estratégia de encaminhamento",sortTooltip:"Escolha como priorizar os fornecedores. Automático utiliza balanceamento de carga inteligente.",order:"Ordem de prioridade dos fornecedores",orderTooltip:"Especifique fornecedores para tentar por ordem (ex.: anthropic, openai, together). Prima Enter para adicionar.",orderPlaceholder:"Escreva o slug do fornecedor e prima Enter...",allowFallbacks:"Permitir fallbacks",allowFallbacksTooltip:"Quando activo, o OpenRouter tentará fornecedores de reserva se o principal estiver indisponível.",requireParameters:"Exigir todos os parâmetros",requireParametersTooltip:"Encaminhar apenas para fornecedores que suportem todos os parâmetros do seu pedido.",dataCollection:"Política de recolha de dados",dataCollectionTooltip:"Controle se utiliza fornecedores que possam armazenar ou treinar com os seus dados.",zdr:"Retenção zero de dados",zdrTooltip:"Encaminhar apenas para endpoints com política de retenção zero de dados.",only:"Permitir apenas fornecedores",onlyTooltip:"Utilizar apenas estes fornecedores específicos. Deixe vazio para permitir todos.",onlyPlaceholder:"Escreva o slug do fornecedor e prima Enter...",ignore:"Ignorar fornecedores",ignoreTooltip:"Ignorar estes fornecedores ao encaminhar pedidos.",ignorePlaceholder:"Escreva o slug do fornecedor e prima Enter...",quantizations:"Filtro de quantização",quantizationsTooltip:"Utilizar apenas fornecedores com níveis de quantização específicos. Menor precisão pode reduzir qualidade mas melhorar velocidade.",maxPrice:"Preço máximo",maxPriceTooltip:"Defina limites de preço máximo por milhão de tokens. Deixe vazio para sem limite.",configured:"Configurado"}},FS={label:"Modo de API",standard:"Padrão",codingPlan:"Plano de programação",tokenPlan:"Plano de tokens",apiKeyPrefixHint:"As chaves para este plano começam tipicamente com `{{prefix}}`. Apenas indicativo — não é aplicado.",dashscopeCodingPlanSeparateKey:"O Plano de Programação DashScope utiliza uma chave API separada do endpoint padrão.",baiduCodingPlanSeparateKey:"O Plano de Programação Qianfan utiliza uma chave API separada do endpoint padrão.",tencentTokenPlanAnthropicOnly:"O Plano de Tokens Tencent é apenas para protocolo Anthropic.",xiaomiTokenPlanRegions:"O baseUrl predefinido é `token-plan-cn.*`. Pode editá-lo manualmente para `token-plan-sgp.*` ou `token-plan-ams.*`.",confirmOverwriteTitle:"Mudar modo de API?",confirmOverwriteBody:"Personalizou o URL da API ou a Chave API. Mudar de modo irá substituí-los pelos predefinidos do novo modo — ou mantenha as suas personalizações e actualize apenas a etiqueta do modo.",overwriteAndSwitch:"Substituir e mudar",keepCustomizations:"Manter personalizações"},BS={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Plano de Tokens)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},VS={cancel:"Cancelar",close:"Fechar",copy:"Copiar",delete:"Eliminar",dismiss:"Dispensar",save:"Guardar",optional:"opcional",retry:"Tentar novamente",loading:"A carregar…"},qS={common:{learnMore:"Documentação"}},$S={notSupportedByDaemon:"Ainda não suportado pelo daemon",discoveryUnsupportedFormat:"A descoberta de modelos ainda não é suportada para este formato de fornecedor. Adicione modelos manualmente."},_S={subtitle:"Painel de controlo",providers:"Fornecedores",apiService:"Serviço de API",accounts:"Contas",codeCli:"Code CLI",settings:"Definições",usageStats:"Uso",pricing:"Preços"},GS={title:"Serviço de API",description:"Configure o servidor de API de saída, o encaminhamento de modelos por endpoint e as chaves de acesso com nome.",loading:"A carregar configuração do servidor…",loadError:"Não foi possível carregar a configuração do servidor. Verifique se o daemon está acessível.",enable:{label:"Activar servidor de saída",description:"Iniciar o servidor de API local que encaminha chamadas externas através dos seus fornecedores."},networkBinding:{label:"Permitir acesso LAN",description:"Ligar o servidor à interface de rede em vez de apenas ao loopback.",warning:"O acesso LAN expõe o servidor de API a outros dispositivos na sua rede. Combinado com encaminhamento de subscrição, os pedidos podem consumir a sua quota de subscrição — mantenha esta opção desactivada a não ser que confie na rede."},status:{running:"Servidor em execução",stopped:"Servidor parado",runningHint:"O servidor de API de saída está a aceitar pedidos.",stoppedHint:"Active o servidor para começar a aceitar pedidos.",port:"porta {{port}}",loopback:"URLs de loopback",lan:"URLs de LAN"},endpoints:{title:"Encaminhamento de endpoints",description:"Escolha o modelo para o qual cada formato wire encaminha. O modelo predefinido é configurado aqui — o servidor é um router, não uma aplicação de chat."},endpoint:{name:{chat:"Chat OpenAI",responses:"Respostas OpenAI",messages:"Mensagens Anthropic",gemini:"Gemini"},defaultModel:"Modelo predefinido",backgroundModel:"Modelo de segundo plano",visionModel:"Modelo de visão",noVisionModel:"Nenhum",backgroundModelIds:"IDs do modelo de segundo plano",backgroundModelIdsPlaceholder:"IDs de modelos separados por vírgula",modelPlaceholder:"Seleccionar um modelo…",useSubscription:"Utilizar subscrição",subscriptionUnsupported:"O encaminhamento por subscrição não está disponível para este endpoint."},keys:{title:"Chaves de acesso",description:"Chaves com nome que os clientes externos enviam como token Bearer. A chave completa é mostrada apenas uma vez na criação.",namePlaceholder:"Nome da chave (ex.: o-meu-cli)",create:"Criar chave",empty:"Nenhuma chave de acesso ainda.",enabled:"Activa",disabled:"Inactiva",revoked:"Revogada",toggle:"Alternar chave",revoke:"Revogar",revokeConfirmTitle:"Revogar esta chave?",revokeConfirmDesc:'Revogar "{{name}}" impede imediatamente a sua autenticação. Esta acção não pode ser desfeita.',created:{title:"Chave criada",warning:"Copie esta chave agora — não será mostrada novamente. Guarde-a em segurança.",copy:"Copiar",copied:"Copiado",dismiss:"Concluído"}}},WS={title:"Contas e subscrições",description:"Gira as credenciais de subscrição através das quais o servidor encaminha. Os tokens são escritos aqui mas nunca são mostrados novamente.",loading:"A carregar contas…",empty:"Não há fornecedores de subscrição disponíveis.",signIn:"Iniciar sessão",oauth:{title:"Iniciar sessão em {{name}}",description:"Abra a página de início de sessão no seu browser, autorize e cole o código de autorização abaixo. O código é enviado apenas para o daemon — o token gerado nunca é mostrado.",openPage:"Abrir página de início de sessão",codeLabel:"Código de autorização",codePlaceholder:"Cole o código aqui",submit:"Concluir início de sessão"},codexOauth:{title:"Iniciar sessão em {{name}}",description:"Abra a página de início de sessão no seu browser e autorize. O daemon captura o resultado automaticamente — mantenha isto aberto até concluir. O token nunca é mostrado.",waiting:"À espera que conclua o início de sessão no browser…",failed:"Início de sessão falhado. Por favor tente novamente."},clearProvider:"Limpar tudo",clearConfirmTitle:"Limpar contas {{name}}?",clearConfirmDesc:"Isto remove todas as credenciais armazenadas para este fornecedor. Esta acção não pode ser desfeita.",credential:{ok:"Configurado",notConfigured:"Não configurado"},kind:{"pass-through":"Credenciais de passagem directa","oauth-bearer":"Bearer OAuth","static-bearer":"Chave bearer estática"},reason:{"missing-credential":"Nenhuma credencial armazenada.",expired:"Credencial expirada.","reauth-required":"Re-autenticação necessária.","refresh-failed":"Falha na actualização do token.","not-refreshable":"A credencial não pode ser actualizada.",unknown:"Estado desconhecido."},status:{unconfigured:"Não configurado",authorized:"Autorizado",configured:"Configurado",expired:"Expirado",error:"Erro"},authMethod:{oauth:"OAuth",setup_token:"Token de configuração",manual:"Manual"},list:{empty:"Nenhuma conta armazenada para este fornecedor.",active:"Activa",expiresAt:"Expira em {{value}}",setActive:"Definir como activa",remove:"Remover",removeConfirmTitle:"Remover esta conta?",removeConfirmDesc:'Remover "{{name}}" elimina a credencial armazenada. Esta acção não pode ser desfeita.',title:"Contas"},write:{trigger:"Adicionar credencial",title:"Escrever credencial {{name}}",description:"Cole o material de token já obtido. Os campos estão limitados ao que este fornecedor aceita; o token é armazenado, nunca mostrado novamente.",authMethod:"Método de autenticação",status:"Estado",subscriptionLevel:"Nível de subscrição",subscriptionLevelNone:"Não definido",submit:"Guardar credencial"},field:{accessToken:"Token de acesso",refreshToken:"Token de actualização",idToken:"Token de identidade",apiKey:"Chave API",expiresAt:"Expira em (ISO)",setupTokenExpiresAt:"Token de configuração expira em (ISO)",accountId:"ID da conta",email:"E-mail",organizationId:"ID da organização",baseUrl:"URL base",zenBaseUrl:"URL base Zen"},provider:{claude:{title:"Claude",description:"Credenciais de subscrição Anthropic encaminhadas pelo daemon."},codex:{title:"Codex",description:"Credenciais de subscrição OpenAI Codex encaminhadas pelo daemon."},gemini:{title:"Gemini",description:"Credenciais de subscrição Google Gemini encaminhadas pelo daemon."},opencodego:{title:"OpenCodeGo",description:"Credenciais de chave API estática encaminhadas pelo daemon."}},authMethodLabel:"Método de autorização",authMethodDesc:{oauth:"Inicie sessão através do browser; o daemon captura e armazena o token.",manual:"Cole um token já obtido. É armazenado, nunca mostrado novamente."},actions:{authorize:"Autorizar",enterToken:"Introduzir token",refresh:"Actualizar"},accounts:{addAccount:"Adicionar conta"},detail:{authMethod:"Método de autorização",subscriptionLevel:"Nível de subscrição",expiresAt:"Expira em",lastRefreshed:"Última actualização",label:"Etiqueta da conta",labelPlaceholder:"Dar um nome a esta conta",saveLabel:"Guardar etiqueta"},oauthFlow:{step1:{title:"Abrir a página de autorização",desc:"Abra a página de início de sessão no seu browser."},step2:{title:"Autorizar acesso",desc:"Inicie sessão e aprove o acesso para o fornecedor."},step3:{title:"Copiar o código de autorização",desc:"A página mostra um código de autorização após a aprovação."},step4:{title:"Colar o código",desc:"Cole o código de autorização abaixo para concluir. O código é enviado apenas para o daemon — o token gerado nunca é mostrado."},authorize:"Concluir início de sessão",showUrl:"Mostrar URL de autorização"},manual:{title:"Colar credencial",description:"Cole um token já obtido. Os campos estão limitados ao que este fornecedor aceita; o token é armazenado, nunca mostrado novamente.",accessTokenPlaceholder:"Cole o token de acesso",refreshTokenPlaceholder:"Cole o token de actualização (opcional)",hint:"O token é enviado para o daemon e armazenado encriptado. Nunca é mostrado novamente."},openCodeGo:{apiKeyRequired:"É necessária uma chave API.",apiKeyPlaceholder:"Cole a chave API",baseUrlPlaceholder:"https://… (opcional)",zenBaseUrlPlaceholder:"https://… (opcional)"},info:{title:"Sobre contas de subscrição",description:"Os tokens são escritos no daemon e utilizados para autenticar pedidos upstream. São armazenados encriptados e nunca mostrados novamente. Remover uma conta elimina a credencial armazenada."},rename:{failed:"Não foi possível renomear a conta."},refresh:{failed:"Não foi possível actualizar o token."},errors:{requestFailed:"Pedido falhado. Por favor tente novamente."},syncWarning:{"external-divergent":"O ficheiro de início de sessão da CLI externa contém credenciais mais recentes do que esta conta. O token guardado pode deixar de ser renovado — renove agora ou inicie sessão novamente.","external-not-rotated":"A renovação falhou e a CLI externa contém a mesma credencial expirada. Inicie sessão novamente.","duplicate-token":"Outra conta partilha esta credencial. Renovar qualquer uma delas termina a sessão da outra."},importExternal:{detected:"Foi encontrado um início de sessão de CLI do {{name}} nesta máquina.",hint:"Após a importação, esta aplicação mantém-no atualizado: a cada renovação do token, o ficheiro de início de sessão da CLI também é atualizado, e a CLI do terminal mantém a sessão.",button:"Importar início de sessão de CLI existente"}},ZS={title:"Code CLI",description:"Aponte um CLI de programação para o proxy de saída do daemon. Esta página é apenas de leitura — não há nada a configurar aqui.",copy:"Copiar",copied:"Copiado",baseUrl:{title:"URL base do daemon",description:"O endereço do proxy ao qual o seu CLI se liga.",label:"URL base"},token:{title:"Autenticação",hint:"Envie 'Authorization: Bearer <o-seu-token-admin>' para rotas de administração. O token admin é configurado no daemon (ficheiro de configuração ou variável de ambiente) — nunca é mostrado aqui."},examples:{title:"Ambiente de lançamento de exemplo",keyNote:"Utilize uma chave de acesso de saída criada na página Serviço de API — não o token de administração.",anthropic:"CLI formato Anthropic",openai:"CLI formato OpenAI"},launchDescription:"Lance um CLI de programação num terminal, apontado para este daemon. O daemon injeta o ambiente de redireccionamento e inicia o CLI por si.",refresh:"Actualizar",loading:"A detectar CLIs…",cli:{installed:"Instalado",notFound:"Não encontrado",notFoundHint:"Este CLI não está no PATH do host do daemon. Instale-o e actualize.",install:"Instalar",installing:"A instalar…",installingHint:"A instalar no host do daemon — pode demorar um momento.",launch:"Lançar",launchTitle:"Lançar {{name}}",launchDescription:"Abre um novo terminal no host do daemon a executar este CLI, encaminhado através do proxy do daemon. Escolha um directório de trabalho opcional.",cwdLabel:"Directório de trabalho",cwdPlaceholder:"/caminho/para/o/seu/projecto",runningVia:"Em execução · {{provider}} / {{model}}",stop:"Parar"},manual:{title:"Configuração manual",description:"Prefere executar o CLI manualmente? Aponte-o para o daemon com estas variáveis de ambiente.",show:"Mostrar",hide:"Ocultar"}},QS={probing:"A verificar o daemon…",spawning:"A iniciar o daemon…",failed:"O daemon não pôde iniciar",failedHint:"Certifique-se de que o Node.js está instalado e o daemon está compilado (dist presente), ou defina OMNICROSS_DAEMON_ENTRY para o cli.js do daemon."},YS={title:"Definições",description:"Preferências da aplicação de ambiente de trabalho.",desktopOnly:"As opções de arranque e tabuleiro do sistema aplicam-se apenas na aplicação de ambiente de trabalho.",startup:{title:"Arranque",autoLaunch:"Iniciar ao entrar",autoLaunchHint:"Iniciar o Omnicross automaticamente quando iniciar sessão.",startMinimized:"Iniciar minimizado para o tabuleiro",startMinimizedHint:"Iniciar em segundo plano sem abrir a janela."},tray:{title:"Tabuleiro do sistema",minimizeOnClose:"Minimizar para o tabuleiro ao fechar",minimizeOnCloseHint:"Fechar a janela oculta-a no tabuleiro em vez de sair."},language:{title:"Idioma",label:"Idioma da interface"}},XS={title:"Estatísticas de uso",description:"Estatísticas de tokens e custos dos pedidos servidos pelo daemon.",rangeToday:"Hoje",range7d:"Últimos 7 dias",range30d:"Últimos 30 dias",rangeCustom:"Personalizado",from:"De",to:"Até",totalCost:"Custo total",cacheSavings:"Economia de cache",events:"Pedidos",inputTokens:"Tokens de entrada",outputTokens:"Tokens de saída",cacheReadTokens:"Leitura de cache",cacheWriteTokens:"Gravação de cache",reasoningTokens:"Tokens de raciocínio",byModel:"Por modelo",byApiKey:"Por chave de API",provider:"Provedor",model:"Modelo",cost:"Custo",apiKey:"Chave de API",unpriced:"Sem preço",unpricedHint:"Não existe entrada de preço para este modelo — adicione uma na página de Preços.",unattributed:"Não atribuído",unattributedHint:"Pedidos não associados a uma chave de API específica. É o esperado até a atribuição por chave ser registada.",empty:"Nenhum pedido neste período.",invalidRange:"Selecione um intervalo de datas válido."},JS={title:"Preços de modelos",description:"Preços de tokens por modelo usados para calcular o custo dos pedidos, em USD por milhão de tokens.",search:"Pesquisar provedor ou modelo…",fetchLatest:"Buscar mais recentes",fetching:"Buscando…",addEntry:"Adicionar entrada",provider:"Provedor",model:"Modelo",inputPrice:"Entrada",outputPrice:"Saída",cacheReadPrice:"Leitura de cache",cacheWritePrice:"Gravação de cache",source:"Fonte",updated:"Atualizado",userEdited:"editado",edit:"Editar",deleteTitle:"Excluir esta entrada de preço?",empty:"A tabela de preços está vazia.",emptyHint:"Busque os preços mais recentes para preenchê-la.",noMatches:"Nenhuma entrada corresponde à sua pesquisa.",saved:"Entrada de preço guardada.",saveFailed:"Falha ao guardar: {{message}}",deleteFailed:"Falha ao excluir: {{message}}",alreadyDeleted:"A entrada já não existia.",fetchApplied:"{{count}} entradas atualizadas a partir da fonte.",fetchFailed:"Falha ao buscar: {{message}}",requiredId:"Obrigatório",invalidPrice:"Insira um número não negativo",conflictTitle:"Resolver conflitos de preços",conflictHint:"Estas entradas foram editadas por você e também mudaram na fonte. Escolha por linha se mantém seu valor (Ignorar) ou adota o novo (Sobrescrever).",current:"Atual",incoming:"Recebido",overwrite:"Sobrescrever",skip:"Ignorar",overwriteAll:"Sobrescrever tudo",skipAll:"Ignorar tudo",applyResolutions:"Aplicar",resolved:"{{overwritten}} sobrescritas, {{skipped}} ignoradas.",resolvedWithStale:"{{overwritten}} sobrescritas, {{skipped}} ignoradas. {{stale}} mudaram nesse meio-tempo e ficaram intactas.",refreshFailed:"A alteração foi aplicada, mas falhou ao recarregar a lista: {{message}}",sourceBuiltin:"Integrado",sourceLitellm:"LiteLLM",sourceUser:"Utilizador"},ew={providerSettings:HS,apiMode:FS,presetName:BS,common:VS,mediaSettings:qS,appLocal:$S,nav:_S,apiService:GS,accounts:WS,codeCli:ZS,daemonStatus:QS,settings:YS,usageStats:XS,pricing:JS},tw={loading:"Se încarcă configurația LLM...",reset:{button:"Restaurare implicite",confirmTitle:"Restaurați setările implicite?",confirmBody:"Aceasta șterge personalizările tale pentru acest furnizor și revine la valorile implicite încorporate. Cheia API și sesiunile salvate sunt păstrate.",confirmButton:"Restaurare implicite"},reentryBanner:{message:"{{count}} furnizor(i) activ(i) necesită reintroducerea cheii API. Deschide fiecare și adaugă cheia din nou."},migrationPack:{barHint:"Mută cheile furnizorilor și tokenurile de abonament pe alt dispozitiv cu un pachet criptat.",passphrase:"Frază de acces",passphrasePlaceholder:"Introduceți fraza de acces",passphraseHint:"Folosiți cel puțin 8 caractere; se recomandă 12 sau mai multe.",confirm:"Confirmare frază de acces",confirmPlaceholder:"Reintroduceți fraza de acces",mismatch:"Frazele de acces nu coincid.",strength:{weak:"Prea scurtă — folosiți cel puțin 8 caractere.",fair:"Acceptabilă — 12 sau mai multe caractere este mai sigur.",strong:"Frază de acces puternică."},export:{button:"Exportă pachetul",title:"Exportă pachet criptat",subtitle:"Criptați cheile furnizorilor și tokenurile de abonament într-un fișier portabil.",warning:"Acest fișier conține secrete decriptabile. Păstrați-l în siguranță — oricine are fișierul și fraza de acces vă poate citi cheile. O frază de acces pierdută nu poate fi recuperată.",submit:"Exportă",success:"Pachetul a fost exportat cu succes.",error:"Exportul a eșuat. Vă rugăm să încercați din nou."},import:{button:"Importă pachetul",title:"Importă pachet criptat",subtitle:"Restaurați cheile furnizorilor și tokenurile de abonament dintr-un pachet exportat.",hint:"Introduceți fraza de acces folosită la exportul pachetului, apoi alegeți fișierul.",submit:"Importă",successTitle:"Import finalizat",summary:"Au fost importate {{providerKeys}} cheie/chei furnizor, {{poolKeys}} cheie/chei pool și {{tokenSets}} set(uri) de tokenuri.",duplicates:"S-au omis {{count}} cheie/chei pool deja existente.",skipped:"Omis (furnizor incompatibil): {{names}}",error:"Frază de acces greșită sau pachet corupt. Nu s-a modificat nimic."}},searchPlaceholder:"Caută furnizori...",emptySearch:"Niciun furnizor nu corespunde căutării.",emptyList:"Niciun furnizor configurat.",selectPrompt:"Selectați un furnizor pentru a vedea detaliile",listStatus:"{{count}} model(e)",noModels:"Niciun model configurat",enabled:"Activat",disabled:"Dezactivat",showEnabledOnly:"Afișează doar activele",showAll:"Afișează toți furnizorii",dragHandle:"Trageți pentru a reordona",reorderFailed:"Salvarea ordinii furnizorilor a eșuat",credentials:{apiKey:"Cheie API",apiBaseUrl:"URL de bază API"},filter:{all:"Toate",chat:"Chat",code:"Cod"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Selectați un șablon",skipTemplates:"Omiteți, configurați manual",name:"Nume *",providerType:"Tip",apiType:"Tip API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Format API standard OpenAI chat/completions",claudecode:"Format Anthropic Messages API (Claude Code)"},chatApiFormat:"Format API",chatApiFormatDescription:"Selectați formatul API care corespunde endpoint-ului furnizorului dvs.",apiKey:"Cheie API",apiKeyPlaceholder:"sk-... sau $ENV_VAR",apiKeyHelper:"Folosiți $VAR_NAME pentru a referenția variabile de mediu",apiKeySetPlaceholder:"Cheia este setată — lăsați gol pentru a o păstra",apiKeyReplaceHelper:"O cheie este stocată în siguranță. Introduceți o valoare nouă pentru a o înlocui, sau lăsați gol pentru a o păstra.",testApiKey:"Testează cheia API",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Previzualizare:",models:"Modele",modelPlaceholder:"Numele modelului (ex.: gpt-4, claude-3-opus)",transformers:"Transformatoare",transformerConfig:"Transformatoare API",transformerConfigDescription:"Configurați transformatoare pentru adaptarea formatelor de cerere/răspuns API pentru acest furnizor",transformerConfigNote:"Daemon-ul aplică aceste transformatoare în lanțul de cereri, după transformatorul de format al furnizorului (care gestionează conversia formatului wire). Numele de transformatoare necunoscute sunt ignorate.",enabled:"Activat",apiVersion:"Versiune API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Versiunea Azure OpenAI API (ex.: 2024-08-01-preview)",official:"API oficial Anthropic",officialHelper:"Activați dacă acest furnizor se conectează direct la API-ul oficial Anthropic. Dezactivați pentru proxy-uri inverse sau servicii terțe.",maxConcurrency:"Număr maxim de cereri concurente",maxConcurrencyHelper:"Numărul maxim de cereri API concurente trimise acestui furnizor. Valorile mai mici ajută la evitarea limitării ratei (erori 429). Setați `-1` pentru nicio limită.",codingPlan:{label:"Plan de programare",description:"Utilizați un endpoint API separat pentru planurile de programare bazate pe abonament",baseUrl:"URL de bază plan programare",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Cheie API plan programare (opțional)",apiKeyPlaceholder:"Lăsați gol pentru a utiliza cheia API a furnizorului",apiKeyHelper:"Necesară doar dacă planul de programare folosește o altă cheie API",tokenPlanHint:"Unii furnizori (ex.: Xiaomi MiMo) emit chei Token Plan cu prefixul `tp-` — informativ, nu impus."},selectTypeFirst:"Selectați tipul furnizorului",selectTypeFirstDesc:"Alegeți tipul de furnizor pe care doriți să îl adăugați",codeProviderNote:"Furnizorii de cod necesită doar cheie API și URL. Modelele sunt gestionate de Agent Router.",buttons:{cancel:"Anulare",submitAdd:"Adaugă furnizor",submitUpdate:"Actualizează furnizor",continue:"Continuare",back:"Înapoi"}},details:{noSelection:"Selectați un furnizor pentru a vedea detaliile",apiKey:"Cheie API",apiUrl:"URL API",nameLabel:"Nume furnizor",modelsEndpoint:"Endpoint modele",modelsEndpointHelper:"Înlocuiți endpoint-ul de descoperire dacă furnizorul expune un path /models personalizat.",models:"Modele",transformers:"Transformatoare",codeProviderNote:"Furnizorii de cod (precum Claude Code) nu necesită configurarea modelelor. Modelele sunt gestionate automat de Agent Router.",buttons:{more:"Mai multe setări",delete:"Ștergere"}},providerModelSelector:{placeholder:"Selectați furnizorul și modelul",noProviders:"Niciun furnizor disponibil",noModels:"Niciun model configurat"},apiKeyPool:{title:"Pool de chei API",description:"Configurați mai multe chei API pentru echilibrarea sarcinii. Fiecare sesiune rămâne la o singură cheie pentru a păstra memoria cache a prompturilor.",defaultLabel:"Implicit",weight:"Pondere",noKey:"Nicio cheie",labelPlaceholder:"Etichetă (ex.: Cheia #1, Producție)",addKey:"Adaugă cheie API",add:"Adaugă",empty:"Nicio cheie suplimentară configurată.",statusCoolingDown:"Perioadă de răcire {{time}}",statusAuthFailed:"Autentificare eșuată · dezactivat",statusDisabled:"Dezactivat",statusHealthy:"Funcțional",agoSeconds:"acum {{count}}s",agoMinutes:"acum {{count}}m",agoHours:"acum {{count}}h",agoDays:"acum {{count}}z"},modelsManager:{searchPlaceholder:"Caută modele...",defaultGroup:"Toate modelele",add:"Adaugă model",manage:"Gestionare",empty:"Niciun model în acest grup",enabled:"Activat",disabled:"Dezactivat",filters:{all:"Toate",vision:"Viziune",reasoning:"Raționament",free:"Gratuit",tools:"Instrumente"},manualDialog:{title:"Adaugă model",subtitle:"Adăugați un model personalizat acestui furnizor",modelId:"ID model",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash etc.",modelIdHelper:"Identificatorul exact al modelului folosit la apelarea API-ului",modelName:"Nume afișat",modelNamePlaceholder:"Nume afișat prietenos (opțional)",modelNameHelper:"Nume opțional afișat în interfață. Dacă este gol, se va folosi ID-ul modelului",group:"Grup",groupPlaceholder:"Selectați sau introduceți un nume de grup",submit:"Adaugă",cancel:"Anulare",helper:"Furnizați identificatorul exact al modelului expus de API-ul furnizorului."},editDialog:{title:"Editare model",subtitle:"Modificați setările modelului",modelId:"ID model",modelIdPlaceholder:"Identificator model",modelIdHelper:"Identificatorul modelului folosit la apelarea API-ului",modelName:"Nume afișat",modelNamePlaceholder:"Nume afișat prietenos",modelNameHelper:"Numele afișat în interfață",group:"Grup",groupPlaceholder:"Selectați sau introduceți un nume de grup",submit:"Salvare",cancel:"Anulare",vision:"Capacitate de viziune",visionHint:"Dacă modelul suportă input imagine/viziune",reasoning:"Model de raționament",reasoningHint:"Dacă modelul suportă modul de gândire/raționament"},manageDialog:{title:"Gestionare modele",cachedAt:"Stocat în cache la {{date}} ({{source}})",refresh:"Reîmprospătare",close:"Închidere",raw:"JSON brut",empty:"Niciun model remote disponibil.",error:"Încărcarea modelelor a eșuat: {{message}}",addFromCatalog:"Adaugă",sourceCache:"cache",sourceNetwork:"live",contextLength:"Context {{value}} tokenuri",maxTokens:"Max {{value}} tokenuri"},messages:{added:"Model adăugat.",updated:"Model actualizat.",removed:"Model eliminat.",duplicate:"Modelul există deja.",refreshed:"Modele reîmprospătate",refreshFailed:"Reîmprospătarea modelelor a eșuat"},testDialog:{title:"Test conectivitate model",provider:"Furnizor",model:"Model",testing:"Se testează...",success:"Test reușit",successMessage:"Modelul este accesibil normal",failure:"Test eșuat",aiResponse:"Răspuns AI",charCount:"{{count}} caractere",duration:"Durată {{time}}s",close:"Închidere",retest:"Retestare",testButton:"Testează modelul",unsupportedFormat:"Testarea nu este suportată încă pentru acest format de furnizor."}},router:{title:"Configurare router",description:"Configurați furnizorul/modelul utilizat pentru diferite scenarii.",labels:{default:"Implicit",background:"fundal",think:"gândire",longContext:"Context lung",webSearch:"Căutare web",image:"Imagine",longContextThreshold:"Prag context lung"},helper:{longContextThreshold:"Numărul de tokenuri înainte de comutarea la modelul cu context lung."},placeholder:{required:"Obligatoriu",optional:"Opțional"}},agentRouter:{title:"Agent Router",description:"Configurați rutarea bidirecțională între modurile Chat și Cod.",searchPlaceholder:"Caută routere...",noSearchResults:"Niciun router nu corespunde căutării.",tabs:{chatToCode:"Chat → Cod",codeToChatPlaceholder:"Cod → Chat"},chatToCode:{title:"Router Chat → Cod",description:"Utilizați furnizori de chat în modul agent/programare",addRouter:"Adaugă router",emptyState:"Niciun router Chat→Cod configurat. Adăugați unul pentru a utiliza furnizori de chat în modul programare.",form:{name:"Nume router",namePlaceholder:"Routerul meu Chat→Cod",chatProvider:"Furnizor chat",chatProviderPlaceholder:"Selectați un furnizor chat",mode:"Mod",modeSimple:"Simplu",modeAdvanced:"Avansat",modeSimpleDesc:"Redirecționare directă către furnizorul chat",modeAdvancedDesc:"Configurați maparea modelelor și gestionarea contextului",enabled:"Activat",save:"Salvare router",cancel:"Anulare"},list:{provider:"Furnizor",mode:"Mod",status:"Stare"},mappings:{title:"Mapări modele",description:"Mapați modelele furnizorului chat la modelele furnizorului de cod",count:"mapare(ări)",empty:"Nicio mapare de modele configurată. Adăugați mapări pentru a ruta modelele chat către furnizori de cod.",addNew:"Adaugă mapare nouă",selectSource:"Selectați modelul sursă (Chat)",selectTarget:"Selectați modelul țintă (Cod)",targetPlaceholder:"Introduceți numele modelului Claude Code",notSet:"(Nesetat - faceți clic pentru a selecta)",add:"Adaugă",edit:"Editare",done:"Gata"},advanced:{title:"Configurare avansată",description:"Configurați modele pentru diferite tipuri de sarcini",helpText:"Modelul implicit este obligatoriu. Celelalte modele sunt opționale și vor reveni la implicit dacă nu sunt configurate.",default:{label:"Implicit",placeholder:"Selectați modelul implicit",description:"Modelul principal pentru sarcini generale (similar cu Claude Sonnet)"},background:{label:"Fundal",placeholder:"Selectați modelul de fundal",description:"Model ușor pentru sarcini de fundal (similar cu Claude Haiku)"},think:{label:"Gândire",placeholder:"Selectați modelul de gândire",description:"Model avansat pentru raționament complex (similar cu Claude Opus)"},image:{label:"Imagine",placeholder:"Selectați modelul de imagine",description:"Model pentru sarcini legate de imagini cu capacitate de viziune"}}},codeToChat:{title:"Router Cod → Chat",description:"Expuneți modelele din planul de programare în modul chat",addRouter:"Adaugă router",emptyState:"Niciun router Cod→Chat configurat. Adăugați unul pentru a expune modelele din planul de programare în modul chat.",form:{name:"Nume router",namePlaceholder:"Routerul meu Cod→Chat",codeProvider:"Furnizor cod",codeProviderPlaceholder:"Selectați un furnizor de cod",codeProviderHelper:"Selectați furnizorul de cod utilizat pentru transformare",models:"Modele plan programare",modelsHelper:"Selectați modelele din planul de programare pe care doriți să le expuneți",enabled:"Activat",save:"Salvare router",cancel:"Anulare"},mappings:{title:"Mapări modele",description:"Mapați modelele furnizorului de cod la modelele furnizorului chat pentru expunere",count:"mapare(ări)",empty:"Nicio mapare de modele configurată. Adăugați mapări pentru a expune modelele de cod în modul chat.",addNew:"Adaugă mapare nouă",selectSource:"Selectați modelul sursă (Cod)",selectTarget:"Selectați modelul țintă (Chat)",sourcePlaceholder:"Introduceți numele modelului sursă",targetPlaceholder:"Introduceți numele modelului țintă",add:"Adaugă",edit:"Editare",done:"Gata"}},transformers:{title:"Transformatoare",description:"Configurați transformatoare pentru conversia cererilor/răspunsurilor",noProvider:"Selectați un furnizor pentru a configura transformatoarele",empty:"Niciun transformator",count:"{{count}} transformator(oare)"},status:{enabled:"Activat",disabled:"Dezactivat"},messages:{routerAdded:"Routerul a fost adăugat cu succes",routerUpdated:"Routerul a fost actualizat cu succes",routerDeleted:"Routerul a fost șters cu succes",saveFailed:"Salvarea routerului a eșuat"}},presets:{title:"Adaugă furnizor rapid",added:"Adăugat",add:"Adaugă",features:{search:"Căutare",vision:"Viziune",mcp:"MCP",codingPlan:"Plan programare"}},alerts:{deleteConfirm:"Sigur doriți să ștergeți acest furnizor?"},errors:{nameRequired:"Numele furnizorului este obligatoriu",urlRequired:"URL-ul de bază API este obligatoriu",urlInvalid:"Introduceți un URL valid (ex.: https://api.example.com)",saveFailed:"Salvarea furnizorului a eșuat",deleteFailed:"Eroare la ștergerea furnizorului. Vă rugăm să încercați din nou.",toggleFailed:"Eroare la comutarea furnizorului. Vă rugăm să încercați din nou."},openRouter:{title:"Rutare furnizor OpenRouter",description:"Configurați modul în care cererile sunt rutate către diferiți furnizori pe OpenRouter.",sort:"Strategie de rutare",sortTooltip:"Alegeți cum să prioritizați furnizorii. Auto folosește echilibrarea inteligentă a sarcinii.",order:"Ordinea priorității furnizorilor",orderTooltip:"Specificați furnizorii de încercat în ordine (ex.: anthropic, openai, together). Apăsați Enter pentru a adăuga.",orderPlaceholder:"Introduceți slug-ul furnizorului și apăsați Enter...",allowFallbacks:"Permite rezerve",allowFallbacksTooltip:"Când este activat, OpenRouter va încerca furnizori de rezervă dacă cel principal nu este disponibil.",requireParameters:"Necesită toți parametrii",requireParametersTooltip:"Rutați doar către furnizori care suportă toți parametrii din cererea dvs.",dataCollection:"Politică de colectare date",dataCollectionTooltip:"Controlați dacă să utilizați furnizori care pot stoca sau antrena pe datele dvs.",zdr:"Zero retenție date",zdrTooltip:"Rutați doar către endpoint-uri cu politică Zero Data Retention.",only:"Permite doar anumiți furnizori",onlyTooltip:"Utilizați doar acești furnizori specifici. Lăsați gol pentru a permite toți furnizorii.",onlyPlaceholder:"Introduceți slug-ul furnizorului și apăsați Enter...",ignore:"Ignoră furnizori",ignoreTooltip:"Săriți peste acești furnizori la rutarea cererilor.",ignorePlaceholder:"Introduceți slug-ul furnizorului și apăsați Enter...",quantizations:"Filtru cuantizare",quantizationsTooltip:"Utilizați doar furnizori cu niveluri specifice de cuantizare. Precizia mai mică poate reduce calitatea, dar îmbunătățește viteza.",maxPrice:"Preț maxim",maxPriceTooltip:"Setați limite maxime de preț per milion de tokenuri. Lăsați gol pentru nicio limită.",configured:"Configurat"}},aw={label:"Mod API",standard:"Standard",codingPlan:"Plan programare",tokenPlan:"Plan tokenuri",apiKeyPrefixHint:"Cheile pentru acest plan încep de obicei cu `{{prefix}}`. Doar indicativ — nu este impus.",dashscopeCodingPlanSeparateKey:"Planul de programare DashScope folosește o cheie API separată față de endpoint-ul standard.",baiduCodingPlanSeparateKey:"Planul de programare Qianfan folosește o cheie API separată față de endpoint-ul standard.",tencentTokenPlanAnthropicOnly:"Planul de tokenuri Tencent este exclusiv protocolul Anthropic.",xiaomiTokenPlanRegions:"URL-ul de bază implicit este `token-plan-cn.*`. Îl puteți edita manual la `token-plan-sgp.*` sau `token-plan-ams.*`.",confirmOverwriteTitle:"Schimbați modul API?",confirmOverwriteBody:"Ați personalizat URL-ul API sau cheia API. Schimbarea modului le va suprascrie cu valorile implicite ale noului mod — sau puteți păstra personalizările și actualiza doar eticheta modului.",overwriteAndSwitch:"Suprascriere și schimbare",keepCustomizations:"Păstrare personalizări"},nw={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Plan tokenuri)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},ow={cancel:"Anulare",close:"Închidere",copy:"Copiere",delete:"Ștergere",dismiss:"Respingere",save:"Salvare",optional:"opțional",retry:"Reîncearcă",loading:"Se încarcă…"},iw={common:{learnMore:"Documentație"}},rw={notSupportedByDaemon:"Nesuportat încă de daemon",discoveryUnsupportedFormat:"Descoperirea modelelor nu este suportată pentru acest format de furnizor. Adăugați modele manual."},sw={subtitle:"Panou de control",providers:"Furnizori",apiService:"Serviciu API",accounts:"Conturi",codeCli:"CLI programare",settings:"Setări",usageStats:"Utilizare",pricing:"Prețuri"},lw={title:"Serviciu API",description:"Configurați serverul API de ieșire, rutarea modelelor per endpoint și cheile de acces cu nume.",loading:"Se încarcă configurația serverului…",loadError:"Configurația serverului nu a putut fi încărcată. Verificați dacă daemon-ul este accesibil.",enable:{label:"Activează serverul de ieșire",description:"Porniți serverul API local care rutează apelatorii externi prin furnizorii dvs."},networkBinding:{label:"Permite acces LAN",description:"Legați serverul la interfața de rețea în loc de loopback.",warning:"Accesul LAN expune serverul API altor dispozitive din rețea. Combinat cu rutarea abonamentului, cererile pot consuma cota abonamentului — lăsați dezactivat dacă nu aveți încredere în rețea."},status:{running:"Server activ",stopped:"Server oprit",runningHint:"Serverul API de ieșire acceptă cereri.",stoppedHint:"Activați serverul pentru a începe acceptarea cererilor.",port:"port {{port}}",loopback:"URL-uri loopback",lan:"URL-uri LAN"},endpoints:{title:"Rutare endpoint-uri",description:"Alegeți modelul la care este rutat fiecare format wire. Modelul implicit se integrează aici — serverul este un router, nu o aplicație de chat."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Model implicit",backgroundModel:"Model de fundal",visionModel:"Model de viziune",noVisionModel:"Niciunul",backgroundModelIds:"ID-uri model de fundal",backgroundModelIdsPlaceholder:"id-uri modele separate prin virgulă",modelPlaceholder:"Selectați un model…",useSubscription:"Folosiți abonament",subscriptionUnsupported:"Rutarea prin abonament nu este disponibilă pentru acest endpoint."},keys:{title:"Chei de acces",description:"Chei cu nume trimise de apelatorii externi ca token Bearer. Cheia completă este afișată o singură dată la creare.",namePlaceholder:"Numele cheii (ex.: cli-ul-meu)",create:"Creare cheie",empty:"Nicio cheie de acces încă.",enabled:"Activat",disabled:"Dezactivat",revoked:"Revocat",toggle:"Comutare cheie",revoke:"Revocare",revokeConfirmTitle:"Revocați această cheie?",revokeConfirmDesc:'Revocarea "{{name}}" oprește imediat autentificarea. Această acțiune nu poate fi anulată.',created:{title:"Cheie creată",warning:"Copiați această cheie acum — nu va mai fi afișată. Stocați-o în siguranță.",copy:"Copiere",copied:"Copiat",dismiss:"Gata"}}},dw={title:"Conturi și abonamente",description:"Gestionați acreditările de abonament prin care serverul rutează. Tokenurile sunt scrise aici, dar nu sunt afișate înapoi.",loading:"Se încarcă conturile…",empty:"Niciun furnizor de abonament disponibil.",signIn:"Autentificare",oauth:{title:"Autentificare în {{name}}",description:"Deschideți pagina de autentificare în browser, autorizați, apoi lipiți codul de autorizare mai jos. Codul ajunge doar la daemon — tokenul emis nu este afișat niciodată.",openPage:"Deschide pagina de autentificare",codeLabel:"Cod de autorizare",codePlaceholder:"Lipiți codul aici",submit:"Finalizare autentificare"},codexOauth:{title:"Autentificare în {{name}}",description:"Deschideți pagina de autentificare în browser și autorizați. Daemon-ul captează rezultatul automat — lăsați această fereastră deschisă până la finalizare. Tokenul nu este afișat niciodată.",waiting:"Se așteaptă finalizarea autentificării în browser…",failed:"Autentificarea a eșuat. Vă rugăm să încercați din nou."},clearProvider:"Șterge tot",clearConfirmTitle:"Ștergeți conturile {{name}}?",clearConfirmDesc:"Aceasta elimină toate acreditările stocate pentru acest furnizor. Această acțiune nu poate fi anulată.",credential:{ok:"Configurat",notConfigured:"Neconfigurat"},kind:{"pass-through":"Acreditări pass-through","oauth-bearer":"Bearer OAuth","static-bearer":"Cheie Bearer statică"},reason:{"missing-credential":"Nicio acreditare stocată.",expired:"Acreditarea a expirat.","reauth-required":"Reautentificare necesară.","refresh-failed":"Reîmprospătarea tokenului a eșuat.","not-refreshable":"Acreditarea nu poate fi reîmprospătată.",unknown:"Stare necunoscută."},status:{unconfigured:"Neconfigurat",authorized:"Autorizat",configured:"Configurat",expired:"Expirat",error:"Eroare"},authMethod:{oauth:"OAuth",setup_token:"Token de configurare",manual:"Manual"},list:{empty:"Niciun cont stocat pentru acest furnizor.",active:"Activ",expiresAt:"Expiră {{value}}",setActive:"Setează ca activ",remove:"Eliminare",removeConfirmTitle:"Eliminați acest cont?",removeConfirmDesc:'Eliminarea "{{name}}" șterge acreditarea stocată. Această acțiune nu poate fi anulată.',title:"Conturi"},write:{trigger:"Adaugă acreditare",title:"Scrie acreditare {{name}}",description:"Lipiți materialul de token deja obținut. Câmpurile sunt limitate la ce acceptă acest furnizor; tokenul este stocat, nu este afișat înapoi.",authMethod:"Metodă de autentificare",status:"Stare",subscriptionLevel:"Nivel abonament",subscriptionLevelNone:"Nesetat",submit:"Salvare acreditare"},field:{accessToken:"Token de acces",refreshToken:"Token de reîmprospătare",idToken:"Token de identitate",apiKey:"Cheie API",expiresAt:"Expiră la (ISO)",setupTokenExpiresAt:"Tokenul de configurare expiră la (ISO)",accountId:"ID cont",email:"E-mail",organizationId:"ID organizație",baseUrl:"URL de bază",zenBaseUrl:"URL de bază Zen"},provider:{claude:{title:"Claude",description:"Acreditări de abonament Anthropic rutate de daemon."},codex:{title:"Codex",description:"Acreditări de abonament OpenAI Codex rutate de daemon."},gemini:{title:"Gemini",description:"Acreditări de abonament Google Gemini rutate de daemon."},opencodego:{title:"OpenCodeGo",description:"Acreditări cu cheie API statică rutate de daemon."}},authMethodLabel:"Metodă de autorizare",authMethodDesc:{oauth:"Autentificați-vă prin browser; daemon-ul captează și stochează tokenul.",manual:"Lipiți un token deja obținut. Este stocat, nu este afișat înapoi."},actions:{authorize:"Autorizare",enterToken:"Introduceți tokenul",refresh:"Reîmprospătare"},accounts:{addAccount:"Adaugă cont"},detail:{authMethod:"Metodă de autorizare",subscriptionLevel:"Nivel abonament",expiresAt:"Expiră",lastRefreshed:"Ultima reîmprospătare",label:"Etichetă cont",labelPlaceholder:"Denumiți acest cont",saveLabel:"Salvare etichetă"},oauthFlow:{step1:{title:"Deschideți pagina de autorizare",desc:"Deschideți pagina de autentificare în browser."},step2:{title:"Autorizați accesul",desc:"Autentificați-vă și aprobați accesul pentru furnizor."},step3:{title:"Copiați codul de autorizare",desc:"Pagina afișează un cod de autorizare după aprobare."},step4:{title:"Lipiți codul",desc:"Lipiți codul de autorizare mai jos pentru a finaliza. Codul ajunge doar la daemon — tokenul emis nu este afișat niciodată."},authorize:"Finalizare autentificare",showUrl:"Afișează URL de autorizare"},manual:{title:"Lipire acreditare",description:"Lipiți un token deja obținut. Câmpurile sunt limitate la ce acceptă acest furnizor; tokenul este stocat, nu este afișat înapoi.",accessTokenPlaceholder:"Lipiți tokenul de acces",refreshTokenPlaceholder:"Lipiți tokenul de reîmprospătare (opțional)",hint:"Tokenul este trimis la daemon și stocat criptat. Nu este afișat înapoi."},openCodeGo:{apiKeyRequired:"O cheie API este necesară.",apiKeyPlaceholder:"Lipiți cheia API",baseUrlPlaceholder:"https://… (opțional)",zenBaseUrlPlaceholder:"https://… (opțional)"},info:{title:"Despre conturile de abonament",description:"Tokenurile sunt scrise în daemon și folosite pentru autentificarea cererilor upstream. Sunt stocate criptat și nu sunt afișate înapoi. Eliminarea unui cont șterge acreditarea stocată."},rename:{failed:"Redenumirea contului a eșuat."},refresh:{failed:"Reîmprospătarea tokenului a eșuat."},errors:{requestFailed:"Cererea a eșuat. Vă rugăm să încercați din nou."},syncWarning:{"external-divergent":"Fișierul de autentificare al CLI-ului extern conține acreditări mai noi decât acest cont. Tokenul stocat ar putea să nu se mai reîmprospăteze — reîmprospătați acum sau autentificați-vă din nou.","external-not-rotated":"Reîmprospătarea a eșuat, iar CLI-ul extern conține aceleași acreditări expirate. Autentificați-vă din nou.","duplicate-token":"Un alt cont folosește aceleași acreditări. Reîmprospătarea unuia îl va deconecta pe celălalt."},importExternal:{detected:"A fost găsită o autentificare CLI {{name}} existentă pe această mașină.",hint:"După import, această aplicație o menține actualizată: la fiecare reîmprospătare a tokenului se actualizează și fișierul de autentificare al CLI-ului, astfel încât CLI-ul din terminal rămâne conectat.",button:"Importă autentificarea CLI existentă"}},cw={title:"CLI programare",description:"Îndreptați un CLI de programare către proxy-ul de ieșire al daemon-ului. Această pagină este doar pentru citire — nu există nimic de configurat aici.",copy:"Copiere",copied:"Copiat",baseUrl:{title:"URL de bază daemon",description:"Adresa proxy la care se conectează CLI-ul dvs.",label:"URL de bază"},token:{title:"Autentificare",hint:"Trimiteți 'Authorization: Bearer <tokenul-admin>' pentru rutele de administrare. Tokenul admin este configurat în daemon (fișierul de configurare sau variabile de mediu) — nu este afișat aici."},examples:{title:"Exemplu de mediu de lansare",keyNote:"Folosiți o cheie de acces de ieșire creată pe pagina Serviciu API — nu tokenul admin.",anthropic:"CLI format Anthropic",openai:"CLI format OpenAI"},launchDescription:"Lansați un CLI de programare într-un terminal, îndreptat către acest daemon. Daemon-ul injectează env-ul de redirecționare și pornește CLI-ul pentru dvs.",refresh:"Reîmprospătare",loading:"Se detectează CLI-urile…",cli:{installed:"Instalat",notFound:"Negăsit",notFoundHint:"Acest CLI nu se află în PATH-ul gazdei daemon. Instalați-l, apoi reîmprospătați.",install:"Instalare",installing:"Se instalează…",installingHint:"Se instalează pe gazda daemon — poate dura un minut.",launch:"Lansare",launchTitle:"Lansare {{name}}",launchDescription:"Deschide un terminal nou pe gazda daemon care rulează acest CLI, rutat prin proxy-ul daemon. Alegeți un director de lucru opțional.",cwdLabel:"Director de lucru",cwdPlaceholder:"/cale/catre/proiect",runningVia:"Rulează · {{provider}} / {{model}}",stop:"Oprire"},manual:{title:"Configurare manuală",description:"Preferați să rulați CLI-ul singur? Îndreptați-l către daemon cu aceste variabile de mediu.",show:"Afișare",hide:"Ascundere"}},uw={probing:"Se verifică daemon-ul…",spawning:"Se pornește daemon-ul…",failed:"Daemon-ul nu a putut porni",failedHint:"Asigurați-vă că Node.js este instalat și daemon-ul este compilat (dist prezent), sau setați OMNICROSS_DAEMON_ENTRY la calea cli.js a daemon-ului."},pw={title:"Setări",description:"Preferințe aplicație desktop.",desktopOnly:"Opțiunile de pornire și tavă se aplică doar în aplicația desktop.",startup:{title:"Pornire",autoLaunch:"Lansare la autentificare",autoLaunchHint:"Porniți Omnicross automat când vă autentificați.",startMinimized:"Porniți minimizat în tavă",startMinimizedHint:"Lansați în fundal fără a deschide fereastra."},tray:{title:"Tavă sistem",minimizeOnClose:"Minimizați în tavă la închidere",minimizeOnCloseHint:"Închiderea ferestrei o ascunde în tavă în loc să închidă aplicația."},language:{title:"Limbă",label:"Limba interfeței"}},mw={title:"Statistici de utilizare",description:"Statistici de tokeni și costuri pentru cererile servite de daemon.",rangeToday:"Astăzi",range7d:"Ultimele 7 zile",range30d:"Ultimele 30 de zile",rangeCustom:"Personalizat",from:"De la",to:"Până la",totalCost:"Cost total",cacheSavings:"Economii cache",events:"Cereri",inputTokens:"Tokeni de intrare",outputTokens:"Tokeni de ieșire",cacheReadTokens:"Citire cache",cacheWriteTokens:"Scriere cache",reasoningTokens:"Tokeni de raționament",byModel:"Pe model",byApiKey:"Pe cheie API",provider:"Furnizor",model:"Model",cost:"Cost",apiKey:"Cheie API",unpriced:"Fără preț",unpricedHint:"Nu există o intrare de preț pentru acest model — adaugă una pe pagina Prețuri.",unattributed:"Neatribuit",unattributedHint:"Cereri nelegate de o cheie API anume. Este normal până când atribuirea per cheie este înregistrată.",empty:"Nicio cerere în acest interval.",invalidRange:"Selectează un interval de date valid."},gw={title:"Prețurile modelelor",description:"Prețurile tokenilor per model folosite la calculul costului cererilor, în USD per milion de tokeni.",search:"Caută furnizor sau model…",fetchLatest:"Preia cele mai noi",fetching:"Se preia…",addEntry:"Adaugă intrare",provider:"Furnizor",model:"Model",inputPrice:"Intrare",outputPrice:"Ieșire",cacheReadPrice:"Citire cache",cacheWritePrice:"Scriere cache",source:"Sursă",updated:"Actualizat",userEdited:"editat",edit:"Editează",deleteTitle:"Ștergi intrarea de preț?",empty:"Tabelul de prețuri este gol.",emptyHint:"Preia cele mai noi prețuri pentru a-l popula.",noMatches:"Nicio intrare nu corespunde căutării.",saved:"Intrarea de preț a fost salvată.",saveFailed:"Salvarea a eșuat: {{message}}",deleteFailed:"Ștergerea a eșuat: {{message}}",alreadyDeleted:"Intrarea nu mai exista.",fetchApplied:"{{count}} intrări actualizate din sursă.",fetchFailed:"Preluarea a eșuat: {{message}}",requiredId:"Obligatoriu",invalidPrice:"Introdu un număr nenegativ",conflictTitle:"Rezolvă conflictele de preț",conflictHint:"Aceste intrări au fost editate de tine și s-au schimbat și la sursă. Alege pe fiecare rând dacă păstrezi valoarea ta (Omite) sau o preiei pe cea nouă (Suprascrie).",current:"Curent",incoming:"Primit",overwrite:"Suprascrie",skip:"Omite",overwriteAll:"Suprascrie tot",skipAll:"Omite tot",applyResolutions:"Aplică",resolved:"{{overwritten}} suprascrise, {{skipped}} omise.",resolvedWithStale:"{{overwritten}} suprascrise, {{skipped}} omise. {{stale}} s-au schimbat între timp și au rămas neatinse.",refreshFailed:"Modificarea a fost aplicată, dar reîncărcarea listei a eșuat: {{message}}",sourceBuiltin:"Încorporat",sourceLitellm:"LiteLLM",sourceUser:"Utilizator"},hw={providerSettings:tw,apiMode:aw,presetName:nw,common:ow,mediaSettings:iw,appLocal:rw,nav:sw,apiService:lw,accounts:dw,codeCli:cw,daemonStatus:uw,settings:pw,usageStats:mw,pricing:gw},fw={loading:"Загрузка конфигурации LLM...",reset:{button:"Восстановить настройки по умолчанию",confirmTitle:"Восстановить настройки по умолчанию?",confirmBody:"Это сбросит ваши настройки для данного провайдера, и он снова будет следовать встроенным значениям по умолчанию. Ваш API-ключ и сохранённые сессии сохранятся.",confirmButton:"Восстановить настройки по умолчанию"},reentryBanner:{message:"{{count}} включённый(-х) провайдер(-ов) требует повторного ввода API-ключа. Откройте каждый из них и добавьте ключ снова."},migrationPack:{barHint:"Перенесите ключи провайдеров и токены подписок на другой компьютер с помощью зашифрованного пакета.",passphrase:"Парольная фраза",passphrasePlaceholder:"Введите парольную фразу",passphraseHint:"Используйте не менее 8 символов; рекомендуется 12 и более.",confirm:"Подтвердить парольную фразу",confirmPlaceholder:"Введите парольную фразу повторно",mismatch:"Парольные фразы не совпадают.",strength:{weak:"Слишком короткая — используйте не менее 8 символов.",fair:"Нормально — 12 и более символов надёжнее.",strong:"Надёжная парольная фраза."},export:{button:"Экспортировать пакет",title:"Экспорт зашифрованного пакета",subtitle:"Зашифруйте ваши ключи провайдеров и токены подписок в переносимый файл.",warning:"Этот файл содержит расшифровываемые секреты. Храните его в надёжном месте — любой, кто имеет файл и парольную фразу, сможет прочитать ваши ключи. Утерянная парольная фраза не может быть восстановлена.",submit:"Экспортировать",success:"Пакет успешно экспортирован.",error:"Экспорт не удался. Пожалуйста, попробуйте снова."},import:{button:"Импортировать пакет",title:"Импорт зашифрованного пакета",subtitle:"Восстановите ключи провайдеров и токены подписок из экспортированного пакета.",hint:"Введите парольную фразу, использованную при экспорте пакета, затем выберите файл.",submit:"Импортировать",successTitle:"Импорт завершён",summary:"Импортировано {{providerKeys}} ключ(-ей) провайдера, {{poolKeys}} ключ(-ей) пула и {{tokenSets}} набор(-ов) токенов.",duplicates:"Пропущено {{count}} ключ(-ей) пула, уже присутствующих.",skipped:"Пропущено (нет соответствующего провайдера): {{names}}",error:"Неверная парольная фраза или повреждённый пакет. Ничего не изменено."}},searchPlaceholder:"Поиск провайдеров...",emptySearch:"Ни один провайдер не соответствует запросу.",emptyList:"Провайдеры не настроены.",selectPrompt:"Выберите провайдера для просмотра подробностей",listStatus:"{{count}} модел(-ей)",noModels:"Модели не настроены",enabled:"Включён",disabled:"Отключён",showEnabledOnly:"Показать только включённые",showAll:"Показать всех провайдеров",dragHandle:"Перетащите для изменения порядка",reorderFailed:"Не удалось сохранить порядок провайдеров",credentials:{apiKey:"API-ключ",apiBaseUrl:"Базовый URL API"},filter:{all:"Все",chat:"Чат",code:"Код"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Выберите шаблон",skipTemplates:"Пропустить, настроить вручную",name:"Название *",providerType:"Тип",apiType:"Тип API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Стандартный формат API OpenAI chat/completions",claudecode:"Формат API Anthropic Messages (Claude Code)"},chatApiFormat:"Формат API",chatApiFormatDescription:"Выберите формат API, соответствующий конечной точке вашего провайдера",apiKey:"API-ключ",apiKeyPlaceholder:"sk-... или $ENV_VAR",apiKeyHelper:"Используйте $VAR_NAME для ссылки на переменные среды",apiKeySetPlaceholder:"Ключ задан — оставьте пустым, чтобы сохранить текущий",apiKeyReplaceHelper:"Ключ надёжно сохранён. Введите новое значение для замены или оставьте поле пустым.",testApiKey:"Проверить API-ключ",apiUrl:"URL API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Предпросмотр:",models:"Модели",modelPlaceholder:"Название модели (например, gpt-4, claude-3-opus)",transformers:"Трансформеры",transformerConfig:"Трансформеры API",transformerConfigDescription:"Настройте трансформеры для адаптации форматов запросов/ответов API для этого провайдера",transformerConfigNote:"Демон применяет эти трансформеры в цепочке запросов, после трансформера формата провайдера (который обрабатывает преобразование формата передачи данных). Неизвестные имена трансформеров пропускаются.",enabled:"Включён",apiVersion:"Версия API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Версия API Azure OpenAI (например, 2024-08-01-preview)",official:"Официальный Anthropic API",officialHelper:"Включите, если этот провайдер подключается напрямую к официальному Anthropic API. Отключите для обратных прокси или сторонних сервисов.",maxConcurrency:"Макс. одновременных запросов",maxConcurrencyHelper:"Максимальное количество одновременных API-запросов к этому провайдеру. Меньшие значения помогают избежать ограничений частоты запросов (ошибки 429). Установите `-1` для отключения ограничения.",codingPlan:{label:"Тарифный план кодирования",description:"Использовать отдельную конечную точку API для тарифных планов кодирования по подписке",baseUrl:"Базовый URL плана кодирования",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"API-ключ плана кодирования (необязательно)",apiKeyPlaceholder:"Оставьте пустым для использования API-ключа провайдера",apiKeyHelper:"Требуется только если план кодирования использует отдельный API-ключ",tokenPlanHint:"Некоторые провайдеры (например, Xiaomi MiMo) выдают ключи Token Plan с префиксом `tp-` — только для информации, не проверяется."},selectTypeFirst:"Выберите тип провайдера",selectTypeFirstDesc:"Выберите тип провайдера, который хотите добавить",codeProviderNote:"Провайдерам кода нужны только API-ключ и URL. Модели управляются маршрутизатором агентов.",buttons:{cancel:"Отмена",submitAdd:"Добавить провайдера",submitUpdate:"Обновить провайдера",continue:"Продолжить",back:"Назад"}},details:{noSelection:"Выберите провайдера для просмотра подробностей",apiKey:"API-ключ",apiUrl:"URL API",nameLabel:"Название провайдера",modelsEndpoint:"Конечная точка моделей",modelsEndpointHelper:"Переопределите конечную точку обнаружения, если провайдер использует нестандартный путь /models.",models:"Модели",transformers:"Трансформеры",codeProviderNote:"Провайдеры кода (например, Claude Code) не требуют настройки моделей. Модели автоматически управляются маршрутизатором агентов.",buttons:{more:"Дополнительные настройки",delete:"Удалить"}},providerModelSelector:{placeholder:"Выберите провайдера и модель",noProviders:"Нет доступных провайдеров",noModels:"Модели не настроены"},apiKeyPool:{title:"Пул API-ключей",description:"Настройте несколько API-ключей для балансировки нагрузки. Каждая сессия привязывается к одному ключу для сохранения кэша промптов.",defaultLabel:"По умолчанию",weight:"Вес",noKey:"Без ключа",labelPlaceholder:"Метка (например, Ключ №1, Основной)",addKey:"Добавить API-ключ",add:"Добавить",empty:"Дополнительные ключи не настроены.",statusCoolingDown:"Восстановление {{time}}",statusAuthFailed:"Ошибка аутентификации · отключён",statusDisabled:"Отключён",statusHealthy:"Работает",agoSeconds:"{{count}} с назад",agoMinutes:"{{count}} мин назад",agoHours:"{{count}} ч назад",agoDays:"{{count}} д назад"},modelsManager:{searchPlaceholder:"Поиск моделей...",defaultGroup:"Все модели",add:"Добавить модель",manage:"Управление",empty:"В этой группе нет моделей",enabled:"Включена",disabled:"Отключена",filters:{all:"Все",vision:"Зрение",reasoning:"Рассуждение",free:"Бесплатные",tools:"Инструменты"},manualDialog:{title:"Добавить модель",subtitle:"Добавьте пользовательскую модель к этому провайдеру",modelId:"Идентификатор модели",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash и т.д.",modelIdHelper:"Точный идентификатор модели, используемый при вызове API",modelName:"Отображаемое название",modelNamePlaceholder:"Понятное отображаемое название (необязательно)",modelNameHelper:"Необязательное название, отображаемое в интерфейсе. Если пусто, будет использован идентификатор модели",group:"Группа",groupPlaceholder:"Выберите или введите название группы",submit:"Добавить",cancel:"Отмена",helper:"Укажите точный идентификатор модели, предоставляемый API провайдера."},editDialog:{title:"Редактировать модель",subtitle:"Изменить настройки модели",modelId:"Идентификатор модели",modelIdPlaceholder:"Идентификатор модели",modelIdHelper:"Идентификатор модели, используемый при вызове API",modelName:"Отображаемое название",modelNamePlaceholder:"Понятное отображаемое название",modelNameHelper:"Название, отображаемое в интерфейсе",group:"Группа",groupPlaceholder:"Выберите или введите название группы",submit:"Сохранить",cancel:"Отмена",vision:"Поддержка зрения",visionHint:"Поддерживает ли эта модель ввод изображений",reasoning:"Модель с цепочкой рассуждений",reasoningHint:"Поддерживает ли эта модель режим рассуждения"},manageDialog:{title:"Управление моделями",cachedAt:"Кэшировано {{date}} ({{source}})",refresh:"Обновить",close:"Закрыть",raw:"Необработанный JSON",empty:"Удалённые модели недоступны.",error:"Не удалось загрузить модели: {{message}}",addFromCatalog:"Добавить",sourceCache:"кэш",sourceNetwork:"сеть",contextLength:"Контекст {{value}} токенов",maxTokens:"Макс. {{value}} токенов"},messages:{added:"Модель добавлена.",updated:"Модель обновлена.",removed:"Модель удалена.",duplicate:"Модель уже существует.",refreshed:"Модели обновлены",refreshFailed:"Не удалось обновить модели"},testDialog:{title:"Проверка подключения к модели",provider:"Провайдер",model:"Модель",testing:"Проверка...",success:"Проверка успешна",successMessage:"Модель доступна и работает нормально",failure:"Проверка не удалась",aiResponse:"Ответ ИИ",charCount:"{{count}} симв.",duration:"Длительность {{time}} с",close:"Закрыть",retest:"Повторить проверку",testButton:"Проверить модель",unsupportedFormat:"Проверка для этого формата провайдера пока не поддерживается."}},router:{title:"Конфигурация маршрутизатора",description:"Настройте, какой провайдер/модель использовать для разных сценариев.",labels:{default:"По умолчанию",background:"фоновый",think:"рассуждение",longContext:"Длинный контекст",webSearch:"Веб-поиск",image:"Изображение",longContextThreshold:"Порог длинного контекста"},helper:{longContextThreshold:"Количество токенов для переключения на модель с длинным контекстом."},placeholder:{required:"Обязательно",optional:"Необязательно"}},agentRouter:{title:"Маршрутизатор агентов",description:"Настройте двунаправленную маршрутизацию между режимами чата и кода.",searchPlaceholder:"Поиск маршрутизаторов...",noSearchResults:"Ни один маршрутизатор не соответствует запросу.",tabs:{chatToCode:"Чат → Код",codeToChatPlaceholder:"Код → Чат"},chatToCode:{title:"Маршрутизатор Чат → Код",description:"Использовать провайдеров чата в режиме агента/кодирования",addRouter:"Добавить маршрутизатор",emptyState:"Маршрутизаторы Чат→Код не настроены. Добавьте один, чтобы использовать провайдеров чата в режиме кодирования.",form:{name:"Название маршрутизатора",namePlaceholder:"Мой маршрутизатор Чат→Код",chatProvider:"Провайдер чата",chatProviderPlaceholder:"Выберите провайдера чата",mode:"Режим",modeSimple:"Простой",modeAdvanced:"Расширенный",modeSimpleDesc:"Прямой проброс к провайдеру чата",modeAdvancedDesc:"Настроить сопоставление моделей и обработку контекста",enabled:"Включён",save:"Сохранить маршрутизатор",cancel:"Отмена"},list:{provider:"Провайдер",mode:"Режим",status:"Статус"},mappings:{title:"Сопоставления моделей",description:"Сопоставьте модели провайдера чата с моделями провайдера кода",count:"сопоставлений(-е)",empty:"Сопоставления моделей не настроены. Добавьте сопоставления для маршрутизации моделей чата к провайдерам кода.",addNew:"Добавить новое сопоставление",selectSource:"Выберите исходную модель (Чат)",selectTarget:"Выберите целевую модель (Код)",targetPlaceholder:"Введите название модели Claude Code",notSet:"(Не задано — нажмите для выбора)",add:"Добавить",edit:"Изменить",done:"Готово"},advanced:{title:"Расширенная конфигурация",description:"Настройте модели для разных типов задач",helpText:"Модель по умолчанию обязательна. Остальные модели необязательны — при отсутствии настройки будет использована модель по умолчанию.",default:{label:"По умолчанию",placeholder:"Выберите модель по умолчанию",description:"Основная модель для общих задач (аналог Claude Sonnet)"},background:{label:"Фоновая",placeholder:"Выберите фоновую модель",description:"Лёгкая модель для фоновых задач (аналог Claude Haiku)"},think:{label:"Рассуждение",placeholder:"Выберите модель рассуждения",description:"Продвинутая модель для сложных рассуждений (аналог Claude Opus)"},image:{label:"Изображение",placeholder:"Выберите модель для изображений",description:"Модель для задач, связанных с изображениями, с поддержкой зрения"}}},codeToChat:{title:"Маршрутизатор Код → Чат",description:"Отображать модели тарифного плана кодирования в режиме чата",addRouter:"Добавить маршрутизатор",emptyState:"Маршрутизаторы Код→Чат не настроены. Добавьте один, чтобы отображать модели тарифного плана кодирования в режиме чата.",form:{name:"Название маршрутизатора",namePlaceholder:"Мой маршрутизатор Код→Чат",codeProvider:"Провайдер кода",codeProviderPlaceholder:"Выберите провайдера кода",codeProviderHelper:"Выберите провайдера кода для преобразования",models:"Модели тарифного плана кодирования",modelsHelper:"Выберите модели тарифного плана кодирования для отображения",enabled:"Включён",save:"Сохранить маршрутизатор",cancel:"Отмена"},mappings:{title:"Сопоставления моделей",description:"Сопоставьте модели провайдера кода с моделями провайдера чата для отображения",count:"сопоставлений(-е)",empty:"Сопоставления моделей не настроены. Добавьте сопоставления для отображения моделей кода в режиме чата.",addNew:"Добавить новое сопоставление",selectSource:"Выберите исходную модель (Код)",selectTarget:"Выберите целевую модель (Чат)",sourcePlaceholder:"Введите название исходной модели",targetPlaceholder:"Введите название целевой модели",add:"Добавить",edit:"Изменить",done:"Готово"}},transformers:{title:"Трансформеры",description:"Настройте трансформеры для преобразования запросов/ответов",noProvider:"Выберите провайдера для настройки трансформеров",empty:"Трансформеры отсутствуют",count:"{{count}} трансформер(-ов)"},status:{enabled:"Включён",disabled:"Отключён"},messages:{routerAdded:"Маршрутизатор успешно добавлен",routerUpdated:"Маршрутизатор успешно обновлён",routerDeleted:"Маршрутизатор успешно удалён",saveFailed:"Не удалось сохранить маршрутизатор"}},presets:{title:"Быстрое добавление провайдера",added:"Добавлен",add:"Добавить",features:{search:"Поиск",vision:"Зрение",mcp:"MCP",codingPlan:"План кодирования"}},alerts:{deleteConfirm:"Вы уверены, что хотите удалить этого провайдера?"},errors:{nameRequired:"Название провайдера обязательно",urlRequired:"Базовый URL API обязателен",urlInvalid:"Введите корректный URL (например, https://api.example.com)",saveFailed:"Не удалось сохранить провайдера",deleteFailed:"Ошибка при удалении провайдера. Пожалуйста, попробуйте снова.",toggleFailed:"Ошибка при изменении состояния провайдера. Пожалуйста, попробуйте снова."},openRouter:{title:"Маршрутизация провайдеров OpenRouter",description:"Настройте маршрутизацию запросов к различным провайдерам через OpenRouter.",sort:"Стратегия маршрутизации",sortTooltip:"Выберите приоритет провайдеров. Авто использует интеллектуальную балансировку нагрузки.",order:"Порядок приоритета провайдеров",orderTooltip:"Укажите провайдеров для последовательного перебора (например, anthropic, openai, together). Нажмите Enter для добавления.",orderPlaceholder:"Введите идентификатор провайдера и нажмите Enter...",allowFallbacks:"Разрешить запасные варианты",allowFallbacksTooltip:"При включении OpenRouter будет пробовать резервных провайдеров, если основной недоступен.",requireParameters:"Требовать все параметры",requireParametersTooltip:"Маршрутизировать только к провайдерам, поддерживающим все параметры запроса.",dataCollection:"Политика сбора данных",dataCollectionTooltip:"Управление использованием провайдеров, которые могут хранить или использовать ваши данные для обучения.",zdr:"Нулевое хранение данных",zdrTooltip:"Маршрутизировать только к конечным точкам с политикой нулевого хранения данных.",only:"Только разрешённые провайдеры",onlyTooltip:"Использовать только указанных провайдеров. Оставьте пустым для использования всех провайдеров.",onlyPlaceholder:"Введите идентификатор провайдера и нажмите Enter...",ignore:"Игнорировать провайдеров",ignoreTooltip:"Пропускать этих провайдеров при маршрутизации запросов.",ignorePlaceholder:"Введите идентификатор провайдера и нажмите Enter...",quantizations:"Фильтр квантизации",quantizationsTooltip:"Использовать только провайдеров с указанными уровнями квантизации. Более низкая точность может снизить качество, но повысить скорость.",maxPrice:"Максимальная цена",maxPriceTooltip:"Установите максимальные ценовые лимиты за миллион токенов. Оставьте пустым для отключения ограничения.",configured:"Настроено"}},vw={label:"Режим API",standard:"Стандартный",codingPlan:"План кодирования",tokenPlan:"Токенный план",apiKeyPrefixHint:"Ключи для этого плана обычно начинаются с `{{prefix}}`. Только подсказка — не проверяется.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan использует отдельный API-ключ от стандартной конечной точки.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan использует отдельный API-ключ от стандартной конечной точки.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan работает только по протоколу Anthropic.",xiaomiTokenPlanRegions:"Базовый URL по умолчанию — `token-plan-cn.*`. Можно вручную изменить на `token-plan-sgp.*` или `token-plan-ams.*`.",confirmOverwriteTitle:"Сменить режим API?",confirmOverwriteBody:"Вы настроили пользовательский URL API или API-ключ. Смена режима перезапишет их значениями по умолчанию нового режима — либо сохраните ваши настройки и обновите только метку режима.",overwriteAndSwitch:"Перезаписать и переключить",keepCustomizations:"Сохранить настройки"},kw={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},yw={cancel:"Отмена",close:"Закрыть",copy:"Копировать",delete:"Удалить",dismiss:"Закрыть",save:"Сохранить",optional:"необязательно",retry:"Повторить",loading:"Загрузка…"},bw={common:{learnMore:"Документация"}},Pw={notSupportedByDaemon:"Пока не поддерживается демоном",discoveryUnsupportedFormat:"Обнаружение моделей не поддерживается для этого формата провайдера. Добавьте модели вручную."},Aw={subtitle:"Панель управления",providers:"Провайдеры",apiService:"API-сервис",accounts:"Аккаунты",codeCli:"Code CLI",settings:"Настройки",usageStats:"Использование",pricing:"Цены"},Cw={title:"API-сервис",description:"Настройте исходящий API-сервер, маршрутизацию моделей по конечным точкам и именованные ключи доступа.",loading:"Загрузка конфигурации сервера…",loadError:"Не удалось загрузить конфигурацию сервера. Убедитесь, что демон доступен.",enable:{label:"Включить исходящий сервер",description:"Запустить локальный API-сервер, маршрутизирующий внешние запросы через ваших провайдеров."},networkBinding:{label:"Разрешить доступ из локальной сети",description:"Привязать сервер к сетевому интерфейсу вместо только loopback.",warning:"Доступ из локальной сети открывает API-сервер для других устройств в вашей сети. В сочетании с маршрутизацией подписок запросы могут расходовать квоту подписки — оставляйте выключенным, если не доверяете сети."},status:{running:"Сервер работает",stopped:"Сервер остановлен",runningHint:"Исходящий API-сервер принимает запросы.",stoppedHint:"Включите сервер для начала приёма запросов.",port:"порт {{port}}",loopback:"URL loopback",lan:"URL локальной сети"},endpoints:{title:"Маршрутизация конечных точек",description:"Выберите модель для каждого формата передачи данных. Модель по умолчанию учитывается здесь — сервер является маршрутизатором, а не чат-приложением."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Модель по умолчанию",backgroundModel:"Фоновая модель",visionModel:"Модель зрения",noVisionModel:"Нет",backgroundModelIds:"Идентификаторы фоновых моделей",backgroundModelIdsPlaceholder:"идентификаторы моделей через запятую",modelPlaceholder:"Выберите модель…",useSubscription:"Использовать подписку",subscriptionUnsupported:"Маршрутизация по подписке недоступна для этой конечной точки."},keys:{title:"Ключи доступа",description:"Именованные ключи, которые внешние клиенты передают в качестве Bearer-токена. Полный ключ отображается только один раз при создании.",namePlaceholder:"Название ключа (например, my-cli)",create:"Создать ключ",empty:"Ключей доступа пока нет.",enabled:"Активен",disabled:"Отключён",revoked:"Отозван",toggle:"Включить/отключить ключ",revoke:"Отозвать",revokeConfirmTitle:"Отозвать этот ключ?",revokeConfirmDesc:"Отзыв ключа «{{name}}» немедленно прекратит его использование для аутентификации. Это действие нельзя отменить.",created:{title:"Ключ создан",warning:"Скопируйте ключ сейчас — он больше не будет отображаться. Храните его в надёжном месте.",copy:"Копировать",copied:"Скопировано",dismiss:"Готово"}}},xw={title:"Аккаунты и подписки",description:"Управляйте учётными данными подписок, через которые маршрутизирует сервер. Токены записываются здесь, но никогда не отображаются обратно.",loading:"Загрузка аккаунтов…",empty:"Нет доступных провайдеров подписок.",signIn:"Войти",oauth:{title:"Войти в {{name}}",description:"Откройте страницу входа в браузере, авторизуйтесь, затем вставьте код авторизации ниже. Код передаётся только демону — созданный токен никогда не отображается.",openPage:"Открыть страницу входа",codeLabel:"Код авторизации",codePlaceholder:"Вставьте код сюда",submit:"Завершить вход"},codexOauth:{title:"Войти в {{name}}",description:"Откройте страницу входа в браузере и авторизуйтесь. Демон автоматически получит результат — не закрывайте эту страницу до завершения. Токен никогда не отображается.",waiting:"Ожидание завершения входа в браузере…",failed:"Вход не выполнен. Пожалуйста, попробуйте снова."},clearProvider:"Очистить всё",clearConfirmTitle:"Очистить аккаунты {{name}}?",clearConfirmDesc:"Это удалит все сохранённые учётные данные для этого провайдера. Это действие нельзя отменить.",credential:{ok:"Настроено",notConfigured:"Не настроено"},kind:{"pass-through":"Сквозные учётные данные","oauth-bearer":"OAuth Bearer","static-bearer":"Статический Bearer-ключ"},reason:{"missing-credential":"Учётные данные не сохранены.",expired:"Срок действия учётных данных истёк.","reauth-required":"Требуется повторная аутентификация.","refresh-failed":"Обновление токена не удалось.","not-refreshable":"Учётные данные не обновляемые.",unknown:"Статус неизвестен."},status:{unconfigured:"Не настроено",authorized:"Авторизовано",configured:"Настроено",expired:"Истёк",error:"Ошибка"},authMethod:{oauth:"OAuth",setup_token:"Токен установки",manual:"Вручную"},list:{empty:"Для этого провайдера нет сохранённых аккаунтов.",active:"Активный",expiresAt:"Истекает {{value}}",setActive:"Сделать активным",remove:"Удалить",removeConfirmTitle:"Удалить этот аккаунт?",removeConfirmDesc:"Удаление «{{name}}» сотрёт сохранённые учётные данные. Это действие нельзя отменить.",title:"Аккаунты"},write:{trigger:"Добавить учётные данные",title:"Записать учётные данные {{name}}",description:"Вставьте уже полученные данные токена. Поля ограничены тем, что принимает этот провайдер; токен сохраняется и никогда не отображается обратно.",authMethod:"Метод аутентификации",status:"Статус",subscriptionLevel:"Уровень подписки",subscriptionLevelNone:"Не задан",submit:"Сохранить учётные данные"},field:{accessToken:"Токен доступа",refreshToken:"Токен обновления",idToken:"ID-токен",apiKey:"API-ключ",expiresAt:"Истекает (ISO)",setupTokenExpiresAt:"Токен установки истекает (ISO)",accountId:"Идентификатор аккаунта",email:"Электронная почта",organizationId:"Идентификатор организации",baseUrl:"Базовый URL",zenBaseUrl:"Zen базовый URL"},provider:{claude:{title:"Claude",description:"Учётные данные подписки Anthropic, маршрутизируемые демоном."},codex:{title:"Codex",description:"Учётные данные подписки OpenAI Codex, маршрутизируемые демоном."},gemini:{title:"Gemini",description:"Учётные данные подписки Google Gemini, маршрутизируемые демоном."},opencodego:{title:"OpenCodeGo",description:"Статические учётные данные API-ключа, маршрутизируемые демоном."}},authMethodLabel:"Метод авторизации",authMethodDesc:{oauth:"Войдите через браузер; демон захватит и сохранит токен.",manual:"Вставьте уже полученный токен. Он сохраняется и никогда не отображается обратно."},actions:{authorize:"Авторизовать",enterToken:"Ввести токен",refresh:"Обновить"},accounts:{addAccount:"Добавить аккаунт"},detail:{authMethod:"Метод авторизации",subscriptionLevel:"Уровень подписки",expiresAt:"Истекает",lastRefreshed:"Последнее обновление",label:"Метка аккаунта",labelPlaceholder:"Назовите этот аккаунт",saveLabel:"Сохранить метку"},oauthFlow:{step1:{title:"Откройте страницу авторизации",desc:"Откройте страницу входа в браузере."},step2:{title:"Авторизуйте доступ",desc:"Войдите и разрешите доступ для провайдера."},step3:{title:"Скопируйте код авторизации",desc:"Страница отобразит код авторизации после подтверждения."},step4:{title:"Вставьте код",desc:"Вставьте код авторизации ниже для завершения. Код передаётся только демону — созданный токен никогда не отображается."},authorize:"Завершить вход",showUrl:"Показать URL авторизации"},manual:{title:"Вставить учётные данные",description:"Вставьте уже полученный токен. Поля ограничены тем, что принимает этот провайдер; токен сохраняется и никогда не отображается обратно.",accessTokenPlaceholder:"Вставьте токен доступа",refreshTokenPlaceholder:"Вставьте токен обновления (необязательно)",hint:"Токен отправляется демону и хранится в зашифрованном виде. Он никогда не отображается обратно."},openCodeGo:{apiKeyRequired:"Требуется API-ключ.",apiKeyPlaceholder:"Вставьте API-ключ",baseUrlPlaceholder:"https://… (необязательно)",zenBaseUrlPlaceholder:"https://… (необязательно)"},info:{title:"Об аккаунтах подписок",description:"Токены записываются в демон и используются для аутентификации запросов. Они хранятся в зашифрованном виде и никогда не отображаются обратно. Удаление аккаунта удаляет сохранённые учётные данные."},rename:{failed:"Не удалось переименовать аккаунт."},refresh:{failed:"Не удалось обновить токен."},errors:{requestFailed:"Запрос не выполнен. Пожалуйста, попробуйте снова."},syncWarning:{"external-divergent":"Файл входа внешней CLI содержит более новые учётные данные, чем этот аккаунт. Сохранённый токен может перестать обновляться — обновите сейчас или войдите заново.","external-not-rotated":"Обновление не удалось, и во внешней CLI хранятся те же просроченные учётные данные. Войдите заново.","duplicate-token":"Другой аккаунт использует те же учётные данные. Обновление одного из них приведёт к выходу другого."},importExternal:{detected:"На этом компьютере найден существующий вход в CLI {{name}}.",hint:"После импорта это приложение поддерживает его актуальность: при каждом обновлении токена файл входа CLI тоже обновляется, и CLI в терминале остаётся авторизованной.",button:"Импортировать существующий вход CLI"}},zw={title:"Code CLI",description:"Направьте CLI для кодирования на исходящий прокси демона. Эта страница только для чтения — здесь нечего настраивать.",copy:"Копировать",copied:"Скопировано",baseUrl:{title:"Базовый URL демона",description:"Адрес прокси, к которому подключается ваш CLI.",label:"Базовый URL"},token:{title:"Аутентификация",hint:"Отправляйте 'Authorization: Bearer <ваш-admin-токен>' для административных маршрутов. Административный токен настраивается в демоне (в файле конфигурации или переменных среды) — он никогда не отображается здесь."},examples:{title:"Пример переменных среды для запуска",keyNote:"Используйте ключ исходящего доступа, созданный на странице API-сервиса, — не административный токен.",anthropic:"CLI в формате Anthropic",openai:"CLI в формате OpenAI"},launchDescription:"Запустите CLI для кодирования в терминале, направленный на этот демон. Демон вводит переменные среды перенаправления и запускает CLI за вас.",refresh:"Обновить",loading:"Обнаружение CLI…",cli:{installed:"Установлен",notFound:"Не найден",notFoundHint:"Этот CLI не обнаружен в PATH хоста демона. Установите его, затем обновите.",install:"Установить",installing:"Установка…",installingHint:"Установка на хосте демона — это может занять минуту.",launch:"Запустить",launchTitle:"Запустить {{name}}",launchDescription:"Открывает новый терминал на хосте демона с этим CLI, маршрутизированным через прокси демона. Выберите необязательную рабочую директорию.",cwdLabel:"Рабочая директория",cwdPlaceholder:"/path/to/your/project",runningVia:"Выполняется · {{provider}} / {{model}}",stop:"Остановить"},manual:{title:"Ручная настройка",description:"Предпочитаете запускать CLI самостоятельно? Направьте его на демон с помощью этих переменных среды.",show:"Показать",hide:"Скрыть"}},Iw={probing:"Проверка наличия демона…",spawning:"Запуск демона…",failed:"Не удалось запустить демон",failedHint:"Убедитесь, что Node.js установлен и демон собран (наличие dist), или задайте OMNICROSS_DAEMON_ENTRY для указания на cli.js демона."},Sw={title:"Настройки",description:"Настройки десктопного приложения.",desktopOnly:"Параметры автозапуска и системного лотка применяются только в десктопном приложении.",startup:{title:"Автозапуск",autoLaunch:"Запускать при входе в систему",autoLaunchHint:"Автоматически запускать Omnicross при входе в систему.",startMinimized:"Запускать свёрнутым в системный лоток",startMinimizedHint:"Запускать в фоновом режиме без открытия окна."},tray:{title:"Системный лоток",minimizeOnClose:"Сворачивать в лоток при закрытии",minimizeOnCloseHint:"При закрытии окно скрывается в системный лоток вместо выхода из программы."},language:{title:"Язык",label:"Язык интерфейса"}},ww={title:"Статистика использования",description:"Статистика токенов и затрат по запросам, обслуженным демоном.",rangeToday:"Сегодня",range7d:"Последние 7 дней",range30d:"Последние 30 дней",rangeCustom:"Произвольный",from:"С",to:"По",totalCost:"Общая стоимость",cacheSavings:"Экономия кэша",events:"Запросы",inputTokens:"Входные токены",outputTokens:"Выходные токены",cacheReadTokens:"Чтение кэша",cacheWriteTokens:"Запись кэша",reasoningTokens:"Токены рассуждений",byModel:"По моделям",byApiKey:"По API-ключам",provider:"Провайдер",model:"Модель",cost:"Стоимость",apiKey:"API-ключ",unpriced:"Без цены",unpricedHint:"Для этой модели нет записи о цене — добавьте её на странице «Цены».",unattributed:"Без привязки",unattributedHint:"Запросы, не связанные с конкретным API-ключом. Это нормально, пока привязка по ключам не записывается.",empty:"Нет запросов за этот период.",invalidRange:"Выберите корректный диапазон дат."},Tw={title:"Цены моделей",description:"Цены токенов по моделям для расчёта стоимости запросов, в долларах США за 1 млн токенов.",search:"Поиск провайдера или модели…",fetchLatest:"Получить актуальные",fetching:"Получение…",addEntry:"Добавить запись",provider:"Провайдер",model:"Модель",inputPrice:"Вход",outputPrice:"Выход",cacheReadPrice:"Чтение кэша",cacheWritePrice:"Запись кэша",source:"Источник",updated:"Обновлено",userEdited:"изменено",edit:"Изменить",deleteTitle:"Удалить запись о цене?",empty:"Таблица цен пуста.",emptyHint:"Получите актуальные цены, чтобы её заполнить.",noMatches:"Нет записей, соответствующих поиску.",saved:"Запись о цене сохранена.",saveFailed:"Не удалось сохранить: {{message}}",deleteFailed:"Не удалось удалить: {{message}}",alreadyDeleted:"Записи уже не было.",fetchApplied:"Обновлено записей из источника: {{count}}.",fetchFailed:"Не удалось получить: {{message}}",requiredId:"Обязательно",invalidPrice:"Введите неотрицательное число",conflictTitle:"Разрешить конфликты цен",conflictHint:"Эти записи редактировались вами и одновременно изменились в источнике. Для каждой строки выберите: сохранить ваше значение (Пропустить) или принять новое (Перезаписать).",current:"Текущее",incoming:"Входящее",overwrite:"Перезаписать",skip:"Пропустить",overwriteAll:"Перезаписать все",skipAll:"Пропустить все",applyResolutions:"Применить",resolved:"Перезаписано: {{overwritten}}, пропущено: {{skipped}}.",resolvedWithStale:"Перезаписано: {{overwritten}}, пропущено: {{skipped}}. {{stale}} изменились тем временем и остались нетронутыми.",refreshFailed:"Изменение применено, но не удалось перезагрузить список: {{message}}",sourceBuiltin:"Встроенный",sourceLitellm:"LiteLLM",sourceUser:"Пользователь"},jw={providerSettings:fw,apiMode:vw,presetName:kw,common:yw,mediaSettings:bw,appLocal:Pw,nav:Aw,apiService:Cw,accounts:xw,codeCli:zw,daemonStatus:Iw,settings:Sw,usageStats:ww,pricing:Tw},Mw={loading:"Läser in LLM-konfiguration...",reset:{button:"Återställ standardvärden",confirmTitle:"Återställ standardinställningar?",confirmBody:"Detta rensar dina anpassningar för den här leverantören så att den följer de inbyggda standardvärdena igen. Din API-nyckel och sparade sessioner behålls.",confirmButton:"Återställ standardvärden"},reentryBanner:{message:"{{count}} aktiverad/aktiverade leverantör(er) behöver sin API-nyckel angiven på nytt. Öppna varje leverantör och lägg till nyckeln igen."},migrationPack:{barHint:"Flytta dina leverantörnycklar och prenumerationstoken till en annan dator med ett krypterat paket.",passphrase:"Lösenfras",passphrasePlaceholder:"Ange en lösenfras",passphraseHint:"Använd minst 8 tecken; 12 eller fler rekommenderas.",confirm:"Bekräfta lösenfras",confirmPlaceholder:"Ange lösenfransen igen",mismatch:"Lösenfraserna stämmer inte överens.",strength:{weak:"För kort — använd minst 8 tecken.",fair:"OK — 12 eller fler tecken är starkare.",strong:"Stark lösenfras."},export:{button:"Exportera paket",title:"Exportera krypterat paket",subtitle:"Kryptera dina leverantörnycklar och prenumerationstoken till en portabel fil.",warning:"Den här filen innehåller dekrypterbara hemligheter. Förvara den säkert — alla med filen och lösenfransen kan läsa dina nycklar. En förlorad lösenfras kan inte återställas.",submit:"Exportera",success:"Paketet exporterades.",error:"Exporten misslyckades. Försök igen."},import:{button:"Importera paket",title:"Importera krypterat paket",subtitle:"Återställ leverantörnycklar och prenumerationstoken från ett exporterat paket.",hint:"Ange lösenfransen som användes när paketet exporterades och välj sedan filen.",submit:"Importera",successTitle:"Import klar",summary:"Importerade {{providerKeys}} leverantörnyckel/nycklar, {{poolKeys}} poolnyckel/nycklar och {{tokenSets}} tokenuppsättning/uppsättningar.",duplicates:"Hoppade över {{count}} poolnyckel/nycklar som redan finns.",skipped:"Hoppade över (ingen matchande leverantör): {{names}}",error:"Fel lösenfras eller skadat paket. Ingenting ändrades."}},searchPlaceholder:"Sök leverantörer...",emptySearch:"Inga leverantörer matchar din sökning.",emptyList:"Inga leverantörer konfigurerade.",selectPrompt:"Välj en leverantör för att visa detaljer",listStatus:"{{count}} modell(er)",noModels:"Inga modeller konfigurerade",enabled:"Aktiverad",disabled:"Inaktiverad",showEnabledOnly:"Visa endast aktiverade",showAll:"Visa alla leverantörer",dragHandle:"Dra för att ändra ordning",reorderFailed:"Det gick inte att spara leverantörsordningen",credentials:{apiKey:"API-nyckel",apiBaseUrl:"API-bas-URL"},filter:{all:"Alla",chat:"Chatt",code:"Kod"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Välj en mall",skipTemplates:"Hoppa över, konfigurera manuellt",name:"Namn *",providerType:"Typ",apiType:"API-typ",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standardformat för OpenAI chat/completions API",claudecode:"Anthropic Messages API-format (Claude Code)"},chatApiFormat:"API-format",chatApiFormatDescription:"Välj det API-format som matchar leverantörens slutpunkt",apiKey:"API-nyckel",apiKeyPlaceholder:"sk-... eller $ENV_VAR",apiKeyHelper:"Använd $VAR_NAME för att referera till miljövariabler",apiKeySetPlaceholder:"Nyckel är angiven — lämna tomt för att behålla den",apiKeyReplaceHelper:"En nyckel är lagrad säkert. Skriv ett nytt värde för att ersätta den, eller lämna tomt för att behålla den.",testApiKey:"Testa API-nyckel",apiUrl:"API-URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Förhandsgranskning:",models:"Modeller",modelPlaceholder:"Modellnamn (t.ex. gpt-4, claude-3-opus)",transformers:"Transformatorer",transformerConfig:"API-transformatorer",transformerConfigDescription:"Konfigurera transformatorer för att anpassa API-förfrågnings-/svarsformat för den här leverantören",transformerConfigNote:"Daemonen tillämpar dessa transformatorer i förfrågningskedjan, efter leverantörens formatransformator (som hanterar konverteringen av trådformatet). Okända transformatornamn hoppas över.",enabled:"Aktiverad",apiVersion:"API-version",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API-version (t.ex. 2024-08-01-preview)",official:"Officiellt Anthropic API",officialHelper:"Aktivera om den här leverantören ansluter direkt till det officiella Anthropic API. Inaktivera för omvända proxyer eller tjänster från tredje part.",maxConcurrency:"Max samtidiga förfrågningar",maxConcurrencyHelper:"Maximalt antal samtidiga API-förfrågningar som skickas till den här leverantören. Lägre värden hjälper till att undvika hastighetsbegränsning (429-fel). Ange `-1` för ingen begränsning.",codingPlan:{label:"Kodningsplan",description:"Använd en separat API-slutpunkt för prenumerationsbaserade kodningsplaner",baseUrl:"Kodningsplanens bas-URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kodningsplanens API-nyckel (valfritt)",apiKeyPlaceholder:"Lämna tomt för att använda leverantörens API-nyckel",apiKeyHelper:"Krävs bara om kodningsplanen använder en annan API-nyckel",tokenPlanHint:"Vissa leverantörer (t.ex. Xiaomi MiMo) utfärdar Token Plan-nycklar med prefixet `tp-` — informativt, inte obligatoriskt."},selectTypeFirst:"Välj leverantörstyp",selectTypeFirstDesc:"Välj vilken typ av leverantör du vill lägga till",codeProviderNote:"Kodleverantörer behöver bara API-nyckel och URL. Modeller hanteras av agentrouter.",buttons:{cancel:"Avbryt",submitAdd:"Lägg till leverantör",submitUpdate:"Uppdatera leverantör",continue:"Fortsätt",back:"Tillbaka"}},details:{noSelection:"Välj en leverantör för att visa detaljer",apiKey:"API-nyckel",apiUrl:"API-URL",nameLabel:"Leverantörnamn",modelsEndpoint:"Modellslutpunkt",modelsEndpointHelper:"Åsidosätt identifieringsslutpunkten om leverantören exponerar en anpassad /models-sökväg.",models:"Modeller",transformers:"Transformatorer",codeProviderNote:"Kodleverantörer (som Claude Code) kräver inte modellkonfiguration. Modeller hanteras automatiskt av agentrouter.",buttons:{more:"Fler inställningar",delete:"Ta bort"}},providerModelSelector:{placeholder:"Välj leverantör och modell",noProviders:"Inga leverantörer tillgängliga",noModels:"Inga modeller konfigurerade"},apiKeyPool:{title:"API-nyckelpool",description:"Konfigurera flera API-nycklar för lastbalansering. Varje session håller sig till en nyckel för att bevara promptcachen.",defaultLabel:"Standard",weight:"Vikt",noKey:"Ingen nyckel",labelPlaceholder:"Etikett (t.ex. Nyckel #1, Produktion)",addKey:"Lägg till API-nyckel",add:"Lägg till",empty:"Inga extra nycklar konfigurerade.",statusCoolingDown:"Nedkylning {{time}}",statusAuthFailed:"Autentisering misslyckades · inaktiverad",statusDisabled:"Inaktiverad",statusHealthy:"Felfri",agoSeconds:"{{count}}s sedan",agoMinutes:"{{count}}m sedan",agoHours:"{{count}}h sedan",agoDays:"{{count}}d sedan"},modelsManager:{searchPlaceholder:"Sök modeller...",defaultGroup:"Alla modeller",add:"Lägg till modell",manage:"Hantera",empty:"Inga modeller i den här gruppen",enabled:"Aktiverad",disabled:"Inaktiverad",filters:{all:"Alla",vision:"Vision",reasoning:"Resonemang",free:"Gratis",tools:"Verktyg"},manualDialog:{title:"Lägg till modell",subtitle:"Lägg till en anpassad modell till den här leverantören",modelId:"Modell-ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, osv.",modelIdHelper:"Den exakta modellidentifieraren som används vid anrop av API:et",modelName:"Visningsnamn",modelNamePlaceholder:"Vänligt visningsnamn (valfritt)",modelNameHelper:"Valfritt namn som visas i gränssnittet. Om tomt används Modell-ID",group:"Grupp",groupPlaceholder:"Välj eller ange ett gruppnamn",submit:"Lägg till",cancel:"Avbryt",helper:"Ange den exakta modellidentifieraren som exponeras av leverantörens API."},editDialog:{title:"Redigera modell",subtitle:"Ändra modellinställningar",modelId:"Modell-ID",modelIdPlaceholder:"Modellidentifierare",modelIdHelper:"Modellidentifieraren som används vid anrop av API:et",modelName:"Visningsnamn",modelNamePlaceholder:"Vänligt visningsnamn",modelNameHelper:"Namn som visas i gränssnittet",group:"Grupp",groupPlaceholder:"Välj eller ange ett gruppnamn",submit:"Spara",cancel:"Avbryt",vision:"Visionsfunktion",visionHint:"Om den här modellen stöder bild-/visionsinmatning",reasoning:"Tänkandemodell",reasoningHint:"Om den här modellen stöder tänkande/resonemang"},manageDialog:{title:"Hantera modeller",cachedAt:"Cachad {{date}} ({{source}})",refresh:"Uppdatera",close:"Stäng",raw:"Rå JSON",empty:"Inga fjärrmodeller tillgängliga.",error:"Det gick inte att läsa in modeller: {{message}}",addFromCatalog:"Lägg till",sourceCache:"cache",sourceNetwork:"live",contextLength:"Kontext {{value}} token",maxTokens:"Max {{value}} token"},messages:{added:"Modell tillagd.",updated:"Modell uppdaterad.",removed:"Modell borttagen.",duplicate:"Modellen finns redan.",refreshed:"Modeller uppdaterade",refreshFailed:"Det gick inte att uppdatera modeller"},testDialog:{title:"Anslutningstest för modell",provider:"Leverantör",model:"Modell",testing:"Testar...",success:"Test lyckat",successMessage:"Modellen kan nås normalt",failure:"Test misslyckades",aiResponse:"AI-svar",charCount:"{{count}} tecken",duration:"Varaktighet {{time}}s",close:"Stäng",retest:"Testa igen",testButton:"Testa modell",unsupportedFormat:"Testning stöds inte ännu för det här leverantörformatet."}},router:{title:"Routerkonfiguration",description:"Konfigurera vilken leverantör/modell som ska användas för olika scenarier.",labels:{default:"Standard",background:"bakgrund",think:"tänka",longContext:"Lång kontext",webSearch:"Webbsökning",image:"Bild",longContextThreshold:"Tröskel för lång kontext"},helper:{longContextThreshold:"Antal token innan byte till modellen med lång kontext."},placeholder:{required:"Obligatorisk",optional:"Valfri"}},agentRouter:{title:"Agentrouter",description:"Konfigurera dubbelriktad routing mellan chatt- och kodläge.",searchPlaceholder:"Sök routrar...",noSearchResults:"Inga routrar matchar din sökning.",tabs:{chatToCode:"Chatt → Kod",codeToChatPlaceholder:"Kod → Chatt"},chatToCode:{title:"Chatt till kod-router",description:"Använd chattleverantörer i agent-/kodningsläge",addRouter:"Lägg till router",emptyState:"Inga Chatt→Kod-routrar konfigurerade. Lägg till en för att använda chattleverantörer i kodningsläge.",form:{name:"Routernamn",namePlaceholder:"Min Chatt→Kod-router",chatProvider:"Chattleverantör",chatProviderPlaceholder:"Välj en chattleverantör",mode:"Läge",modeSimple:"Enkelt",modeAdvanced:"Avancerat",modeSimpleDesc:"Direktgenomströmning till chattleverantör",modeAdvancedDesc:"Konfigurera modellmappning och kontexthantering",enabled:"Aktiverad",save:"Spara router",cancel:"Avbryt"},list:{provider:"Leverantör",mode:"Läge",status:"Status"},mappings:{title:"Modellmappningar",description:"Mappa chattleverantörmodeller till kodleverantörmodeller",count:"mappning(ar)",empty:"Inga modellmappningar konfigurerade. Lägg till mappningar för att routa chattmodeller till kodleverantörer.",addNew:"Lägg till ny mappning",selectSource:"Välj källmodell (Chatt)",selectTarget:"Välj målmodell (Kod)",targetPlaceholder:"Ange Claude Code-modellnamn",notSet:"(Ej angiven — klicka för att välja)",add:"Lägg till",edit:"Redigera",done:"Klar"},advanced:{title:"Avancerad konfiguration",description:"Konfigurera modeller för olika uppgiftstyper",helpText:"Standardmodell krävs. Övriga modeller är valfria och återgår till standard om de inte är konfigurerade.",default:{label:"Standard",placeholder:"Välj standardmodell",description:"Primär modell för allmänna uppgifter (liknande Claude Sonnet)"},background:{label:"Bakgrund",placeholder:"Välj bakgrundsmodell",description:"Lättviktsmodell för bakgrundsuppgifter (liknande Claude Haiku)"},think:{label:"Tänka",placeholder:"Välj tänkandemodell",description:"Avancerad modell för komplexa resonemang (liknande Claude Opus)"},image:{label:"Bild",placeholder:"Välj bildmodell",description:"Modell för bildrelaterade uppgifter med visionsfunktion"}}},codeToChat:{title:"Kod till chatt-router",description:"Exponera kodningsplanmodeller i chattläge",addRouter:"Lägg till router",emptyState:"Inga Kod→Chatt-routrar konfigurerade. Lägg till en för att exponera kodningsplanmodeller i chattläge.",form:{name:"Routernamn",namePlaceholder:"Min Kod→Chatt-router",codeProvider:"Kodleverantör",codeProviderPlaceholder:"Välj en kodleverantör",codeProviderHelper:"Välj kodleverantören som ska användas för transformation",models:"Kodningsplanmodeller",modelsHelper:"Välj vilka kodningsplanmodeller som ska exponeras",enabled:"Aktiverad",save:"Spara router",cancel:"Avbryt"},mappings:{title:"Modellmappningar",description:"Mappa kodleverantörmodeller till chattleverantörmodeller för exponering",count:"mappning(ar)",empty:"Inga modellmappningar konfigurerade. Lägg till mappningar för att exponera kodmodeller i chattläge.",addNew:"Lägg till ny mappning",selectSource:"Välj källmodell (Kod)",selectTarget:"Välj målmodell (Chatt)",sourcePlaceholder:"Ange källmodellnamn",targetPlaceholder:"Ange målmodellnamn",add:"Lägg till",edit:"Redigera",done:"Klar"}},transformers:{title:"Transformatorer",description:"Konfigurera transformatorer för konvertering av förfrågningar/svar",noProvider:"Välj en leverantör för att konfigurera transformatorer",empty:"Inga transformatorer",count:"{{count}} transformator(er)"},status:{enabled:"Aktiverad",disabled:"Inaktiverad"},messages:{routerAdded:"Router tillagd",routerUpdated:"Router uppdaterad",routerDeleted:"Router borttagen",saveFailed:"Det gick inte att spara routern"}},presets:{title:"Snabblägg till leverantör",added:"Tillagd",add:"Lägg till",features:{search:"Sökning",vision:"Vision",mcp:"MCP",codingPlan:"Kodningsplan"}},alerts:{deleteConfirm:"Är du säker på att du vill ta bort den här leverantören?"},errors:{nameRequired:"Leverantörnamn krävs",urlRequired:"API-bas-URL krävs",urlInvalid:"Ange en giltig URL (t.ex. https://api.example.com)",saveFailed:"Det gick inte att spara leverantören",deleteFailed:"Fel vid borttagning av leverantör. Försök igen.",toggleFailed:"Fel vid aktivering/inaktivering av leverantör. Försök igen."},openRouter:{title:"OpenRouter-leverantörsrouting",description:"Konfigurera hur förfrågningar routas till olika leverantörer på OpenRouter.",sort:"Routingstrategi",sortTooltip:"Välj hur leverantörer ska prioriteras. Auto använder intelligent lastbalansering.",order:"Leverantörsprioriteringsordning",orderTooltip:"Ange leverantörer att prova i ordning (t.ex. anthropic, openai, together). Tryck Enter för att lägga till.",orderPlaceholder:"Skriv leverantörens slug och tryck Enter...",allowFallbacks:"Tillåt reservalternativ",allowFallbacksTooltip:"När aktiverat försöker OpenRouter med reservleverantörer om den primära är otillgänglig.",requireParameters:"Kräv alla parametrar",requireParametersTooltip:"Routa bara till leverantörer som stöder alla parametrar i din förfrågan.",dataCollection:"Datainsamlingspolicy",dataCollectionTooltip:"Styr om leverantörer som kan lagra eller träna på dina data ska användas.",zdr:"Noll datalagring",zdrTooltip:"Routa bara till slutpunkter med policy för noll datalagring.",only:"Tillåt bara leverantörer",onlyTooltip:"Använd bara dessa specifika leverantörer. Lämna tomt för att tillåta alla leverantörer.",onlyPlaceholder:"Skriv leverantörens slug och tryck Enter...",ignore:"Ignorera leverantörer",ignoreTooltip:"Hoppa över dessa leverantörer vid routing av förfrågningar.",ignorePlaceholder:"Skriv leverantörens slug och tryck Enter...",quantizations:"Kvantiseringsfilter",quantizationsTooltip:"Använd bara leverantörer med specifika kvantiseringsnivåer. Lägre precision kan minska kvaliteten men förbättra hastigheten.",maxPrice:"Maximalt pris",maxPriceTooltip:"Ange maximala prisgränser per miljon token. Lämna tomt för ingen gräns.",configured:"Konfigurerad"}},Nw={label:"API-läge",standard:"Standard",codingPlan:"Kodningsplan",tokenPlan:"Tokenplan",apiKeyPrefixHint:"Nycklar för den här planen börjar vanligtvis med `{{prefix}}`. Endast information — inte obligatoriskt.",dashscopeCodingPlanSeparateKey:"DashScope Kodningsplan använder en separat API-nyckel från standardslutpunkten.",baiduCodingPlanSeparateKey:"Qianfan Kodningsplan använder en separat API-nyckel från standardslutpunkten.",tencentTokenPlanAnthropicOnly:"Tencent Tokenplan är endast Anthropic-protokoll.",xiaomiTokenPlanRegions:"Standard baseUrl är `token-plan-cn.*`. Du kan redigera det manuellt till `token-plan-sgp.*` eller `token-plan-ams.*`.",confirmOverwriteTitle:"Byta API-läge?",confirmOverwriteBody:"Du har anpassat API-URL:en eller API-nyckeln. Byte av läge skriver över dem med det nya lägets standardvärden — eller behåll dina anpassningar och uppdatera bara lägeetiketten.",overwriteAndSwitch:"Skriv över och byt",keepCustomizations:"Behåll anpassningar"},Lw={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Tokenplan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},Rw={cancel:"Avbryt",close:"Stäng",copy:"Kopiera",delete:"Ta bort",dismiss:"Avfärda",save:"Spara",optional:"valfritt",retry:"Försök igen",loading:"Läser in…"},Dw={common:{learnMore:"Dokumentation"}},Ew={notSupportedByDaemon:"Stöds inte ännu av daemonen",discoveryUnsupportedFormat:"Modellupptäckning stöds inte ännu för det här leverantörformatet. Lägg till modeller manuellt."},Ow={subtitle:"Kontrollpanel",providers:"Leverantörer",apiService:"API-tjänst",accounts:"Konton",codeCli:"Kod-CLI",settings:"Inställningar",usageStats:"Användning",pricing:"Priser"},Kw={title:"API-tjänst",description:"Konfigurera den utgående API-servern, modellrouting per slutpunkt och namngivna åtkomstnycklar.",loading:"Läser in serverkonfiguration…",loadError:"Det gick inte att läsa in serverkonfigurationen. Kontrollera att daemonen är nåbar.",enable:{label:"Aktivera utgående server",description:"Starta den lokala API-servern som routar externa anrop genom dina leverantörer."},networkBinding:{label:"Tillåt LAN-åtkomst",description:"Bind servern till ditt nätverksgränssnitt istället för bara loopback.",warning:"LAN-åtkomst exponerar API-servern för andra enheter i ditt nätverk. I kombination med prenumerationsrouting kan förfrågningar förbruka din prenumerationskvot — håll detta av om du inte litar på nätverket."},status:{running:"Server körs",stopped:"Server stoppad",runningHint:"Den utgående API-servern tar emot förfrågningar.",stoppedHint:"Aktivera servern för att börja ta emot förfrågningar.",port:"port {{port}}",loopback:"Loopback-URL:er",lan:"LAN-URL:er"},endpoints:{title:"Slutpunktsrouting",description:"Välj modell för varje trådformat. Standardmodellen ingår här — servern är en router, inte en chattapp."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Standardmodell",backgroundModel:"Bakgrundsmodell",visionModel:"Visionsmodell",noVisionModel:"Ingen",backgroundModelIds:"Bakgrundsmodell-ID:n",backgroundModelIdsPlaceholder:"kommaseparerade modell-ID:n",modelPlaceholder:"Välj en modell…",useSubscription:"Använd prenumeration",subscriptionUnsupported:"Prenumerationsrouting är inte tillgänglig för den här slutpunkten."},keys:{title:"Åtkomstnycklar",description:"Namngivna nycklar som externa anropare skickar som en Bearer-token. Den fullständiga nyckeln visas bara en gång vid skapandet.",namePlaceholder:"Nyckelnamn (t.ex. mitt-cli)",create:"Skapa nyckel",empty:"Inga åtkomstnycklar ännu.",enabled:"Aktiverad",disabled:"Inaktiverad",revoked:"Återkallad",toggle:"Växla nyckel",revoke:"Återkalla",revokeConfirmTitle:"Återkalla den här nyckeln?",revokeConfirmDesc:'Återkallande av "{{name}}" stoppar omedelbart autentisering. Detta kan inte ångras.',created:{title:"Nyckel skapad",warning:"Kopiera den här nyckeln nu — den visas inte igen. Förvara den säkert.",copy:"Kopiera",copied:"Kopierad",dismiss:"Klar"}}},Uw={title:"Konton och prenumerationer",description:"Hantera prenumerationsuppgifterna som servern routar genom. Token skrivs här men visas aldrig tillbaka.",loading:"Läser in konton…",empty:"Inga prenumerationsleverantörer är tillgängliga.",signIn:"Logga in",oauth:{title:"Logga in på {{name}}",description:"Öppna inloggningssidan i din webbläsare, auktorisera och klistra sedan in auktoriseringskoden nedan. Koden skickas bara till daemonen — den präglade token visas aldrig.",openPage:"Öppna inloggningssida",codeLabel:"Auktoriseringskod",codePlaceholder:"Klistra in koden här",submit:"Slutför inloggning"},codexOauth:{title:"Logga in på {{name}}",description:"Öppna inloggningssidan i din webbläsare och auktorisera. Daemonen fångar resultatet automatiskt — håll den här öppen tills det är klart. Token visas aldrig.",waiting:"Väntar på att du ska slutföra inloggningen i din webbläsare…",failed:"Inloggning misslyckades. Försök igen."},clearProvider:"Rensa alla",clearConfirmTitle:"Rensa {{name}}-konton?",clearConfirmDesc:"Detta tar bort alla lagrade uppgifter för den här leverantören. Detta kan inte ångras.",credential:{ok:"Konfigurerad",notConfigured:"Inte konfigurerad"},kind:{"pass-through":"Genomströmningsuppgifter","oauth-bearer":"OAuth bearer","static-bearer":"Statisk bearer-nyckel"},reason:{"missing-credential":"Ingen uppgift lagrad.",expired:"Uppgiften har gått ut.","reauth-required":"Omautentisering krävs.","refresh-failed":"Tokenuppdatering misslyckades.","not-refreshable":"Uppgiften kan inte uppdateras.",unknown:"Status okänd."},status:{unconfigured:"Okonfigurerad",authorized:"Auktoriserad",configured:"Konfigurerad",expired:"Utgången",error:"Fel"},authMethod:{oauth:"OAuth",setup_token:"Installationstoken",manual:"Manuell"},list:{empty:"Inga konton lagrade för den här leverantören.",active:"Aktiv",expiresAt:"Går ut {{value}}",setActive:"Ange som aktiv",remove:"Ta bort",removeConfirmTitle:"Ta bort det här kontot?",removeConfirmDesc:'Borttagning av "{{name}}" raderar dess lagrade uppgifter. Detta kan inte ångras.',title:"Konton"},write:{trigger:"Lägg till uppgift",title:"Ange {{name}}-uppgifter",description:"Klistra in redan erhållet token-material. Fälten är begränsade till vad den här leverantören accepterar; token lagras, visas aldrig tillbaka.",authMethod:"Autentiseringsmetod",status:"Status",subscriptionLevel:"Prenumerationsnivå",subscriptionLevelNone:"Inte angiven",submit:"Spara uppgifter"},field:{accessToken:"Åtkomsttoken",refreshToken:"Uppdateringstoken",idToken:"ID-token",apiKey:"API-nyckel",expiresAt:"Går ut (ISO)",setupTokenExpiresAt:"Installationstoken går ut (ISO)",accountId:"Konto-ID",email:"E-post",organizationId:"Organisations-ID",baseUrl:"Bas-URL",zenBaseUrl:"Zen bas-URL"},provider:{claude:{title:"Claude",description:"Anthropic-prenumerationsuppgifter routade av daemonen."},codex:{title:"Codex",description:"OpenAI Codex-prenumerationsuppgifter routade av daemonen."},gemini:{title:"Gemini",description:"Google Gemini-prenumerationsuppgifter routade av daemonen."},opencodego:{title:"OpenCodeGo",description:"Statiska API-nyckeluppgifter routade av daemonen."}},authMethodLabel:"Auktoriseringsmetod",authMethodDesc:{oauth:"Logga in via webbläsaren; daemonen fångar och lagrar token.",manual:"Klistra in en redan erhållen token. Den lagras, visas aldrig tillbaka."},actions:{authorize:"Auktorisera",enterToken:"Ange token",refresh:"Uppdatera"},accounts:{addAccount:"Lägg till konto"},detail:{authMethod:"Auktoriseringsmetod",subscriptionLevel:"Prenumerationsnivå",expiresAt:"Går ut",lastRefreshed:"Senast uppdaterad",label:"Kontoetikett",labelPlaceholder:"Ge det här kontot ett namn",saveLabel:"Spara etikett"},oauthFlow:{step1:{title:"Öppna auktoriseringssidan",desc:"Öppna inloggningssidan i din webbläsare."},step2:{title:"Auktorisera åtkomst",desc:"Logga in och godkänn åtkomst för leverantören."},step3:{title:"Kopiera auktoriseringskoden",desc:"Sidan visar en auktoriseringskod när du godkänner."},step4:{title:"Klistra in koden",desc:"Klistra in auktoriseringskoden nedan för att slutföra. Koden skickas bara till daemonen — den präglade token visas aldrig."},authorize:"Slutför inloggning",showUrl:"Visa auktoriserings-URL"},manual:{title:"Klistra in uppgifter",description:"Klistra in en redan erhållen token. Fälten är begränsade till vad den här leverantören accepterar; token lagras, visas aldrig tillbaka.",accessTokenPlaceholder:"Klistra in åtkomsttoken",refreshTokenPlaceholder:"Klistra in uppdateringstoken (valfritt)",hint:"Token skickas till daemonen och lagras krypterat. Den visas aldrig tillbaka."},openCodeGo:{apiKeyRequired:"En API-nyckel krävs.",apiKeyPlaceholder:"Klistra in API-nyckeln",baseUrlPlaceholder:"https://… (valfritt)",zenBaseUrlPlaceholder:"https://… (valfritt)"},info:{title:"Om prenumerationskonton",description:"Token skrivs till daemonen och används för att autentisera uppströmsförfrågningar. De lagras krypterat och visas aldrig tillbaka. Borttagning av ett konto raderar dess lagrade uppgifter."},rename:{failed:"Det gick inte att byta namn på kontot."},refresh:{failed:"Det gick inte att uppdatera token."},errors:{requestFailed:"Förfrågan misslyckades. Försök igen."},syncWarning:{"external-divergent":"Den externa CLI-inloggningsfilen innehåller nyare autentiseringsuppgifter än det här kontot. Den sparade token kanske inte längre kan uppdateras — uppdatera nu eller logga in igen.","external-not-rotated":"Uppdateringen misslyckades och den externa CLI:n innehåller samma utgångna autentiseringsuppgifter. Logga in igen.","duplicate-token":"Ett annat konto delar dessa autentiseringsuppgifter. Att uppdatera det ena loggar ut det andra."},importExternal:{detected:"En befintlig {{name}}-CLI-inloggning hittades på den här datorn.",hint:"Efter importen håller den här appen den uppdaterad: vid varje tokenuppdatering uppdateras även CLI-inloggningsfilen, så CLI:n i terminalen förblir inloggad.",button:"Importera befintlig CLI-inloggning"}},Hw={title:"Kod-CLI",description:"Peka ett kodnings-CLI mot daemonens utgående proxy. Den här sidan är skrivskyddad — det finns inget att konfigurera här.",copy:"Kopiera",copied:"Kopierad",baseUrl:{title:"Daemonens bas-URL",description:"Proxyadressen som ditt CLI ansluter till.",label:"Bas-URL"},token:{title:"Autentisering",hint:"Skicka 'Authorization: Bearer <din-admin-token>' för adminrutter. Admin-token konfigureras i daemonen (dess konfigurationsfil eller miljö) — den visas aldrig här."},examples:{title:"Exempelstartmiljö",keyNote:"Använd en utgående åtkomstnyckel skapad på API-tjänstsidan — inte admin-token.",anthropic:"Anthropic-format CLI",openai:"OpenAI-format CLI"},launchDescription:"Starta ett kodnings-CLI i en terminal, pekat mot den här daemonen. Daemonen injicerar omdirigeringsmiljön och startar CLI:t åt dig.",refresh:"Uppdatera",loading:"Identifierar CLI:er…",cli:{installed:"Installerad",notFound:"Hittades inte",notFoundHint:"Det här CLI:t finns inte i daemonvärdens PATH. Installera det och uppdatera sedan.",install:"Installera",installing:"Installerar…",installingHint:"Installerar på daemonvärden — det kan ta en minut.",launch:"Starta",launchTitle:"Starta {{name}}",launchDescription:"Öppnar en ny terminal på daemonvärden som kör detta CLI, routed via daemonproxy. Välj en valfri arbetskatalog.",cwdLabel:"Arbetskatalog",cwdPlaceholder:"/sökväg/till/ditt/projekt",runningVia:"Körs · {{provider}} / {{model}}",stop:"Stoppa"},manual:{title:"Manuell inställning",description:"Föredrar du att köra CLI:t själv? Peka det mot daemonen med dessa miljövariabler.",show:"Visa",hide:"Dölj"}},Fw={probing:"Söker efter daemonen…",spawning:"Startar daemonen…",failed:"Daemonen kunde inte starta",failedHint:"Kontrollera att Node.js är installerat och att daemonen är byggd (dist finns), eller ange OMNICROSS_DAEMON_ENTRY till daemonens cli.js."},Bw={title:"Inställningar",description:"Skrivbordsprogramsinställningar.",desktopOnly:"Start- och fältikonsalternativ gäller bara i skrivbordsappen.",startup:{title:"Start",autoLaunch:"Starta vid inloggning",autoLaunchHint:"Starta Omnicross automatiskt när du loggar in.",startMinimized:"Starta minimerad i fältet",startMinimizedHint:"Starta i bakgrunden utan att öppna fönstret."},tray:{title:"Fältikon",minimizeOnClose:"Minimera till fältet vid stängning",minimizeOnCloseHint:"Stängning av fönstret döljer det i fältet istället för att avsluta."},language:{title:"Språk",label:"Gränssnittsspråk"}},Vw={title:"Användningsstatistik",description:"Token- och kostnadsstatistik för förfrågningar som demonen hanterat.",rangeToday:"Idag",range7d:"Senaste 7 dagarna",range30d:"Senaste 30 dagarna",rangeCustom:"Anpassad",from:"Från",to:"Till",totalCost:"Total kostnad",cacheSavings:"Cachebesparing",events:"Förfrågningar",inputTokens:"Indatatoken",outputTokens:"Utdatatoken",cacheReadTokens:"Cacheläsning",cacheWriteTokens:"Cacheskrivning",reasoningTokens:"Resonemangstoken",byModel:"Per modell",byApiKey:"Per API-nyckel",provider:"Leverantör",model:"Modell",cost:"Kostnad",apiKey:"API-nyckel",unpriced:"Utan pris",unpricedHint:"Det finns ingen prispost för denna modell — lägg till en på sidan Priser.",unattributed:"Ej tilldelad",unattributedHint:"Förfrågningar som inte är kopplade till en specifik API-nyckel. Detta är förväntat tills tilldelning per nyckel registreras.",empty:"Inga förfrågningar i detta intervall.",invalidRange:"Välj ett giltigt datumintervall."},qw={title:"Modellpriser",description:"Tokenpriser per modell för kostnadsberäkning, i USD per miljon token.",search:"Sök leverantör eller modell…",fetchLatest:"Hämta senaste",fetching:"Hämtar…",addEntry:"Lägg till post",provider:"Leverantör",model:"Modell",inputPrice:"Indata",outputPrice:"Utdata",cacheReadPrice:"Cacheläsning",cacheWritePrice:"Cacheskrivning",source:"Källa",updated:"Uppdaterad",userEdited:"redigerad",edit:"Redigera",deleteTitle:"Ta bort prisposten?",empty:"Pristabellen är tom.",emptyHint:"Hämta de senaste priserna för att fylla den.",noMatches:"Inga poster matchar din sökning.",saved:"Prisposten sparades.",saveFailed:"Det gick inte att spara: {{message}}",deleteFailed:"Det gick inte att ta bort: {{message}}",alreadyDeleted:"Posten fanns inte längre.",fetchApplied:"{{count}} poster uppdaterades från källan.",fetchFailed:"Hämtningen misslyckades: {{message}}",requiredId:"Obligatoriskt",invalidPrice:"Ange ett icke-negativt tal",conflictTitle:"Lös prislkonflikter",conflictHint:"Dessa poster har redigerats av dig och ändrats i källan. Välj per rad om du vill behålla ditt värde (Hoppa över) eller ta det inkommande (Skriv över).",current:"Aktuellt",incoming:"Inkommande",overwrite:"Skriv över",skip:"Hoppa över",overwriteAll:"Skriv över alla",skipAll:"Hoppa över alla",applyResolutions:"Tillämpa",resolved:"{{overwritten}} överskrivna, {{skipped}} överhoppade.",resolvedWithStale:"{{overwritten}} överskrivna, {{skipped}} överhoppade. {{stale}} ändrades under tiden och lämnades orörda.",refreshFailed:"Ändringen tillämpades, men det gick inte att läsa om listan: {{message}}",sourceBuiltin:"Inbyggd",sourceLitellm:"LiteLLM",sourceUser:"Användare"},$w={providerSettings:Mw,apiMode:Nw,presetName:Lw,common:Rw,mediaSettings:Dw,appLocal:Ew,nav:Ow,apiService:Kw,accounts:Uw,codeCli:Hw,daemonStatus:Fw,settings:Bw,usageStats:Vw,pricing:qw},_w={loading:"กำลังโหลดการตั้งค่า LLM...",reset:{button:"คืนค่าเริ่มต้น",confirmTitle:"คืนค่าการตั้งค่าเริ่มต้น?",confirmBody:"การดำเนินการนี้จะล้างการปรับแต่งของคุณสำหรับผู้ให้บริการนี้ และกลับไปใช้ค่าเริ่มต้นที่ติดตั้งมา API key และเซสชันที่บันทึกไว้จะยังคงอยู่",confirmButton:"คืนค่าเริ่มต้น"},reentryBanner:{message:"ผู้ให้บริการที่เปิดใช้งาน {{count}} รายการต้องกรอก API key ใหม่อีกครั้ง กรุณาเปิดแต่ละรายการและเพิ่ม key อีกครั้ง"},migrationPack:{barHint:"ย้าย provider key และ subscription token ของคุณไปยังเครื่องอื่นด้วยแพ็กเข้ารหัส",passphrase:"รหัสผ่าน",passphrasePlaceholder:"ใส่รหัสผ่าน",passphraseHint:"ใช้อย่างน้อย 8 ตัวอักษร แนะนำให้ใช้ 12 ตัวขึ้นไป",confirm:"ยืนยันรหัสผ่าน",confirmPlaceholder:"ใส่รหัสผ่านอีกครั้ง",mismatch:"รหัสผ่านไม่ตรงกัน",strength:{weak:"สั้นเกินไป — ใช้อย่างน้อย 8 ตัวอักษร",fair:"พอใช้ได้ — 12 ตัวขึ้นไปจะปลอดภัยกว่า",strong:"รหัสผ่านแข็งแกร่ง"},export:{button:"ส่งออกแพ็ก",title:"ส่งออกแพ็กเข้ารหัส",subtitle:"เข้ารหัส provider key และ subscription token ของคุณเป็นไฟล์พกพา",warning:"ไฟล์นี้มีข้อมูลลับที่สามารถถอดรหัสได้ เก็บรักษาให้ปลอดภัย — ผู้ใดที่มีไฟล์และรหัสผ่านสามารถอ่าน key ของคุณได้ หากลืมรหัสผ่านจะไม่สามารถกู้คืนได้",submit:"ส่งออก",success:"ส่งออกแพ็กสำเร็จ",error:"การส่งออกล้มเหลว กรุณาลองใหม่อีกครั้ง"},import:{button:"นำเข้าแพ็ก",title:"นำเข้าแพ็กเข้ารหัส",subtitle:"กู้คืน provider key และ subscription token จากแพ็กที่ส่งออกไว้",hint:"ใส่รหัสผ่านที่ใช้ตอนส่งออกแพ็ก จากนั้นเลือกไฟล์",submit:"นำเข้า",successTitle:"นำเข้าสำเร็จ",summary:"นำเข้า provider key {{providerKeys}} รายการ, pool key {{poolKeys}} รายการ และ token set {{tokenSets}} รายการ",duplicates:"ข้าม pool key {{count}} รายการที่มีอยู่แล้ว",skipped:"ข้าม (ไม่พบ provider ที่ตรงกัน): {{names}}",error:"รหัสผ่านไม่ถูกต้องหรือแพ็กเสียหาย ไม่มีการเปลี่ยนแปลงใดๆ"}},searchPlaceholder:"ค้นหาผู้ให้บริการ...",emptySearch:"ไม่พบผู้ให้บริการที่ตรงกับการค้นหา",emptyList:"ยังไม่มีผู้ให้บริการที่ตั้งค่าไว้",selectPrompt:"เลือกผู้ให้บริการเพื่อดูรายละเอียด",listStatus:"{{count}} โมเดล",noModels:"ยังไม่มีโมเดลที่ตั้งค่าไว้",enabled:"เปิดใช้งาน",disabled:"ปิดใช้งาน",showEnabledOnly:"แสดงเฉพาะที่เปิดใช้งาน",showAll:"แสดงผู้ให้บริการทั้งหมด",dragHandle:"ลากเพื่อจัดเรียง",reorderFailed:"บันทึกลำดับผู้ให้บริการไม่สำเร็จ",credentials:{apiKey:"API Key",apiBaseUrl:"API Base URL"},filter:{all:"ทั้งหมด",chat:"แชท",code:"โค้ด"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"เลือกเทมเพลต",skipTemplates:"ข้าม ตั้งค่าเอง",name:"ชื่อ *",providerType:"ประเภท",apiType:"ประเภท API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"รูปแบบ API มาตรฐาน OpenAI chat/completions",claudecode:"รูปแบบ Anthropic Messages API (Claude Code)"},chatApiFormat:"รูปแบบ API",chatApiFormatDescription:"เลือกรูปแบบ API ที่ตรงกับ endpoint ของผู้ให้บริการ",apiKey:"API Key",apiKeyPlaceholder:"sk-... หรือ $ENV_VAR",apiKeyHelper:"ใช้ $VAR_NAME เพื่ออ้างอิงตัวแปรสภาพแวดล้อม",apiKeySetPlaceholder:"ตั้ง key ไว้แล้ว — เว้นว่างเพื่อคงไว้",apiKeyReplaceHelper:"มี key ถูกเก็บไว้อย่างปลอดภัย พิมพ์ค่าใหม่เพื่อแทนที่ หรือเว้นว่างเพื่อคงไว้",testApiKey:"ทดสอบ API Key",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"ตัวอย่าง:",models:"โมเดล",modelPlaceholder:"ชื่อโมเดล (เช่น gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API Transformers",transformerConfigDescription:"ตั้งค่า transformer เพื่อปรับรูปแบบ API request/response สำหรับผู้ให้บริการนี้",transformerConfigNote:"daemon จะใช้ transformer เหล่านี้ในลำดับ request หลังจาก format transformer ของผู้ให้บริการ (ที่จัดการการแปลง wire-format) ชื่อ transformer ที่ไม่รู้จักจะถูกข้าม",enabled:"เปิดใช้งาน",apiVersion:"เวอร์ชัน API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"เวอร์ชัน Azure OpenAI API (เช่น 2024-08-01-preview)",official:"Anthropic API อย่างเป็นทางการ",officialHelper:"เปิดใช้หากผู้ให้บริการนี้เชื่อมต่อโดยตรงกับ Anthropic API อย่างเป็นทางการ ปิดสำหรับ reverse proxy หรือบริการของบุคคลที่สาม",maxConcurrency:"จำนวน Request พร้อมกันสูงสุด",maxConcurrencyHelper:"จำนวน API request สูงสุดที่ส่งไปยังผู้ให้บริการนี้พร้อมกัน ค่าต่ำกว่าช่วยหลีกเลี่ยง rate limiting (ข้อผิดพลาด 429) ตั้ง `-1` เพื่อไม่จำกัด",codingPlan:{label:"Coding Plan",description:"ใช้ API endpoint แยกต่างหากสำหรับ coding plan แบบ subscription",baseUrl:"Coding Plan Base URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API Key (ไม่บังคับ)",apiKeyPlaceholder:"เว้นว่างเพื่อใช้ API key ของผู้ให้บริการ",apiKeyHelper:"จำเป็นเฉพาะเมื่อ coding plan ใช้ API key ที่แตกต่างออกไป",tokenPlanHint:"ผู้ให้บริการบางราย (เช่น Xiaomi MiMo) ออก Token Plan key ที่มีคำนำหน้า `tp-` — เป็นข้อมูลอ้างอิงเท่านั้น ไม่มีการบังคับใช้"},selectTypeFirst:"เลือกประเภทผู้ให้บริการ",selectTypeFirstDesc:"เลือกประเภทผู้ให้บริการที่ต้องการเพิ่ม",codeProviderNote:"Code provider ต้องการเพียง API Key และ URL โมเดลถูกจัดการโดย Agent Router",buttons:{cancel:"ยกเลิก",submitAdd:"เพิ่มผู้ให้บริการ",submitUpdate:"อัปเดตผู้ให้บริการ",continue:"ถัดไป",back:"ย้อนกลับ"}},details:{noSelection:"เลือกผู้ให้บริการเพื่อดูรายละเอียด",apiKey:"API Key",apiUrl:"API URL",nameLabel:"ชื่อผู้ให้บริการ",modelsEndpoint:"Models Endpoint",modelsEndpointHelper:"แทนที่ endpoint การค้นพบหากผู้ให้บริการเปิดเผย path /models แบบกำหนดเอง",models:"โมเดล",transformers:"Transformers",codeProviderNote:"Code provider (เช่น Claude Code) ไม่จำเป็นต้องตั้งค่าโมเดล โมเดลถูกจัดการโดยอัตโนมัติผ่าน Agent Router",buttons:{more:"การตั้งค่าเพิ่มเติม",delete:"ลบ"}},providerModelSelector:{placeholder:"เลือกผู้ให้บริการและโมเดล",noProviders:"ไม่มีผู้ให้บริการ",noModels:"ยังไม่มีโมเดลที่ตั้งค่าไว้"},apiKeyPool:{title:"API Key Pool",description:"ตั้งค่า API key หลายรายการสำหรับ load balancing แต่ละเซสชันจะยึดกับ key เดิมเพื่อรักษา prompt cache",defaultLabel:"ค่าเริ่มต้น",weight:"น้ำหนัก",noKey:"ไม่มี key",labelPlaceholder:"ป้ายกำกับ (เช่น Key #1, Production)",addKey:"เพิ่ม API Key",add:"เพิ่ม",empty:"ยังไม่มี key เพิ่มเติมที่ตั้งค่าไว้",statusCoolingDown:"กำลังพัก {{time}}",statusAuthFailed:"การยืนยันตัวตนล้มเหลว · ปิดใช้งาน",statusDisabled:"ปิดใช้งาน",statusHealthy:"ปกติ",agoSeconds:"{{count}} วินาทีที่แล้ว",agoMinutes:"{{count}} นาทีที่แล้ว",agoHours:"{{count}} ชั่วโมงที่แล้ว",agoDays:"{{count}} วันที่แล้ว"},modelsManager:{searchPlaceholder:"ค้นหาโมเดล...",defaultGroup:"โมเดลทั้งหมด",add:"เพิ่มโมเดล",manage:"จัดการ",empty:"ไม่มีโมเดลในกลุ่มนี้",enabled:"เปิดใช้งาน",disabled:"ปิดใช้งาน",filters:{all:"ทั้งหมด",vision:"Vision",reasoning:"Reasoning",free:"ฟรี",tools:"Tools"},manualDialog:{title:"เพิ่มโมเดล",subtitle:"เพิ่มโมเดลแบบกำหนดเองสำหรับผู้ให้บริการนี้",modelId:"Model ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash ฯลฯ",modelIdHelper:"ตัวระบุโมเดลที่แน่ชัดที่ใช้เมื่อเรียก API",modelName:"ชื่อที่แสดง",modelNamePlaceholder:"ชื่อที่แสดงในหน้าจอ (ไม่บังคับ)",modelNameHelper:"ชื่อเสริมที่แสดงในหน้าจอ หากเว้นว่างจะใช้ Model ID",group:"กลุ่ม",groupPlaceholder:"เลือกหรือพิมพ์ชื่อกลุ่ม",submit:"เพิ่ม",cancel:"ยกเลิก",helper:"ระบุตัวระบุโมเดลที่แน่ชัดที่ผู้ให้บริการ API เปิดเผย"},editDialog:{title:"แก้ไขโมเดล",subtitle:"แก้ไขการตั้งค่าโมเดล",modelId:"Model ID",modelIdPlaceholder:"ตัวระบุโมเดล",modelIdHelper:"ตัวระบุโมเดลที่ใช้เมื่อเรียก API",modelName:"ชื่อที่แสดง",modelNamePlaceholder:"ชื่อที่แสดงในหน้าจอ",modelNameHelper:"ชื่อที่แสดงในหน้าจอ",group:"กลุ่ม",groupPlaceholder:"เลือกหรือพิมพ์ชื่อกลุ่ม",submit:"บันทึก",cancel:"ยกเลิก",vision:"ความสามารถ Vision",visionHint:"โมเดลนี้รองรับการรับรูปภาพหรือไม่",reasoning:"โมเดล Thinking",reasoningHint:"โมเดลนี้รองรับโหมด thinking/reasoning หรือไม่"},manageDialog:{title:"จัดการโมเดล",cachedAt:"แคชเมื่อ {{date}} ({{source}})",refresh:"รีเฟรช",close:"ปิด",raw:"Raw JSON",empty:"ไม่มีโมเดลระยะไกล",error:"โหลดโมเดลไม่สำเร็จ: {{message}}",addFromCatalog:"เพิ่ม",sourceCache:"แคช",sourceNetwork:"สด",contextLength:"Context {{value}} token",maxTokens:"สูงสุด {{value}} token"},messages:{added:"เพิ่มโมเดลแล้ว",updated:"อัปเดตโมเดลแล้ว",removed:"ลบโมเดลแล้ว",duplicate:"มีโมเดลนี้อยู่แล้ว",refreshed:"รีเฟรชโมเดลแล้ว",refreshFailed:"รีเฟรชโมเดลไม่สำเร็จ"},testDialog:{title:"ทดสอบการเชื่อมต่อโมเดล",provider:"ผู้ให้บริการ",model:"โมเดล",testing:"กำลังทดสอบ...",success:"ทดสอบสำเร็จ",successMessage:"สามารถเข้าถึงโมเดลได้ปกติ",failure:"ทดสอบไม่สำเร็จ",aiResponse:"การตอบสนองของ AI",charCount:"{{count}} ตัวอักษร",duration:"ใช้เวลา {{time}} วินาที",close:"ปิด",retest:"ทดสอบใหม่",testButton:"ทดสอบโมเดล",unsupportedFormat:"ยังไม่รองรับการทดสอบสำหรับรูปแบบผู้ให้บริการนี้"}},router:{title:"การตั้งค่า Router",description:"ตั้งค่าผู้ให้บริการ/โมเดลที่ใช้สำหรับแต่ละสถานการณ์",labels:{default:"ค่าเริ่มต้น",background:"พื้นหลัง",think:"คิด",longContext:"Context ยาว",webSearch:"ค้นหาเว็บ",image:"รูปภาพ",longContextThreshold:"เกณฑ์ Context ยาว"},helper:{longContextThreshold:"จำนวน token ก่อนเปลี่ยนไปใช้โมเดล long-context"},placeholder:{required:"จำเป็น",optional:"ไม่บังคับ"}},agentRouter:{title:"Agent Router",description:"ตั้งค่าการ routing แบบสองทิศทางระหว่างโหมดแชทและโค้ด",searchPlaceholder:"ค้นหา router...",noSearchResults:"ไม่พบ router ที่ตรงกับการค้นหา",tabs:{chatToCode:"แชท → โค้ด",codeToChatPlaceholder:"โค้ด → แชท"},chatToCode:{title:"Chat to Code Router",description:"ใช้ chat provider ในโหมด agent/coding",addRouter:"เพิ่ม Router",emptyState:"ยังไม่มี Chat→Code router เพิ่มรายการเพื่อใช้ chat provider ในโหมด coding",form:{name:"ชื่อ Router",namePlaceholder:"My Chat→Code Router",chatProvider:"Chat Provider",chatProviderPlaceholder:"เลือก chat provider",mode:"โหมด",modeSimple:"แบบง่าย",modeAdvanced:"ขั้นสูง",modeSimpleDesc:"ส่งต่อตรงไปยัง chat provider",modeAdvancedDesc:"ตั้งค่า model mapping และการจัดการ context",enabled:"เปิดใช้งาน",save:"บันทึก Router",cancel:"ยกเลิก"},list:{provider:"ผู้ให้บริการ",mode:"โหมด",status:"สถานะ"},mappings:{title:"การจับคู่โมเดล",description:"จับคู่โมเดลของ Chat provider กับโมเดลของ Code provider",count:"การจับคู่",empty:"ยังไม่มีการจับคู่โมเดล เพิ่มการจับคู่เพื่อ route chat model ไปยัง code provider",addNew:"เพิ่มการจับคู่ใหม่",selectSource:"เลือกโมเดลต้นทาง (แชท)",selectTarget:"เลือกโมเดลปลายทาง (โค้ด)",targetPlaceholder:"ใส่ชื่อโมเดล Claude Code",notSet:"(ยังไม่ได้ตั้งค่า — คลิกเพื่อเลือก)",add:"เพิ่ม",edit:"แก้ไข",done:"เสร็จสิ้น"},advanced:{title:"การตั้งค่าขั้นสูง",description:"ตั้งค่าโมเดลสำหรับแต่ละประเภทงาน",helpText:"โมเดลเริ่มต้นจำเป็นต้องตั้งค่า โมเดลอื่นเป็นตัวเลือกและจะใช้โมเดลเริ่มต้นหากไม่ได้ตั้งค่า",default:{label:"ค่าเริ่มต้น",placeholder:"เลือกโมเดลเริ่มต้น",description:"โมเดลหลักสำหรับงานทั่วไป (คล้าย Claude Sonnet)"},background:{label:"พื้นหลัง",placeholder:"เลือกโมเดลพื้นหลัง",description:"โมเดลเบาสำหรับงานพื้นหลัง (คล้าย Claude Haiku)"},think:{label:"คิด",placeholder:"เลือกโมเดล think",description:"โมเดลขั้นสูงสำหรับการใช้เหตุผลซับซ้อน (คล้าย Claude Opus)"},image:{label:"รูปภาพ",placeholder:"เลือกโมเดลรูปภาพ",description:"โมเดลสำหรับงานที่เกี่ยวกับรูปภาพที่มีความสามารถ vision"}}},codeToChat:{title:"Code to Chat Router",description:"เปิดเผยโมเดล Coding Plan ในโหมดแชท",addRouter:"เพิ่ม Router",emptyState:"ยังไม่มี Code→Chat router เพิ่มรายการเพื่อเปิดเผยโมเดล Coding Plan ในโหมดแชท",form:{name:"ชื่อ Router",namePlaceholder:"My Code→Chat Router",codeProvider:"Code Provider",codeProviderPlaceholder:"เลือก code provider",codeProviderHelper:"เลือก Code provider ที่ใช้สำหรับการแปลง",models:"โมเดล Coding Plan",modelsHelper:"เลือกโมเดล Coding Plan ที่ต้องการเปิดเผย",enabled:"เปิดใช้งาน",save:"บันทึก Router",cancel:"ยกเลิก"},mappings:{title:"การจับคู่โมเดล",description:"จับคู่โมเดลของ Code provider กับโมเดลของ Chat provider เพื่อเปิดเผย",count:"การจับคู่",empty:"ยังไม่มีการจับคู่โมเดล เพิ่มการจับคู่เพื่อเปิดเผยโมเดล Code ในโหมดแชท",addNew:"เพิ่มการจับคู่ใหม่",selectSource:"เลือกโมเดลต้นทาง (โค้ด)",selectTarget:"เลือกโมเดลปลายทาง (แชท)",sourcePlaceholder:"ใส่ชื่อโมเดลต้นทาง",targetPlaceholder:"ใส่ชื่อโมเดลปลายทาง",add:"เพิ่ม",edit:"แก้ไข",done:"เสร็จสิ้น"}},transformers:{title:"Transformers",description:"ตั้งค่า transformer สำหรับการแปลง request/response",noProvider:"เลือกผู้ให้บริการเพื่อตั้งค่า transformer",empty:"ไม่มี transformer",count:"{{count}} transformer"},status:{enabled:"เปิดใช้งาน",disabled:"ปิดใช้งาน"},messages:{routerAdded:"เพิ่ม router สำเร็จ",routerUpdated:"อัปเดต router สำเร็จ",routerDeleted:"ลบ router สำเร็จ",saveFailed:"บันทึก router ไม่สำเร็จ"}},presets:{title:"เพิ่มผู้ให้บริการด่วน",added:"เพิ่มแล้ว",add:"เพิ่ม",features:{search:"ค้นหา",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"คุณแน่ใจหรือไม่ว่าต้องการลบผู้ให้บริการนี้?"},errors:{nameRequired:"กรุณาระบุชื่อผู้ให้บริการ",urlRequired:"กรุณาระบุ API Base URL",urlInvalid:"กรุณาใส่ URL ที่ถูกต้อง (เช่น https://api.example.com)",saveFailed:"บันทึกผู้ให้บริการไม่สำเร็จ",deleteFailed:"ลบผู้ให้บริการไม่สำเร็จ กรุณาลองใหม่อีกครั้ง",toggleFailed:"เปลี่ยนสถานะผู้ให้บริการไม่สำเร็จ กรุณาลองใหม่อีกครั้ง"},openRouter:{title:"การ Routing ของ OpenRouter Provider",description:"ตั้งค่าวิธี route request ไปยังผู้ให้บริการต่างๆ บน OpenRouter",sort:"กลยุทธ์การ Routing",sortTooltip:"เลือกวิธีจัดลำดับความสำคัญของผู้ให้บริการ Auto ใช้ load balancing อัจฉริยะ",order:"ลำดับความสำคัญของผู้ให้บริการ",orderTooltip:"ระบุผู้ให้บริการที่ต้องการลองตามลำดับ (เช่น anthropic, openai, together) กด Enter เพื่อเพิ่ม",orderPlaceholder:"พิมพ์ slug ผู้ให้บริการและกด Enter...",allowFallbacks:"อนุญาต Fallback",allowFallbacksTooltip:"เมื่อเปิดใช้งาน OpenRouter จะลองใช้ผู้ให้บริการสำรองหากผู้ให้บริการหลักไม่พร้อมใช้งาน",requireParameters:"บังคับใช้พารามิเตอร์ทั้งหมด",requireParametersTooltip:"Route เฉพาะไปยังผู้ให้บริการที่รองรับพารามิเตอร์ทั้งหมดใน request ของคุณ",dataCollection:"นโยบายการเก็บข้อมูล",dataCollectionTooltip:"ควบคุมการใช้ผู้ให้บริการที่อาจเก็บหรือฝึกโมเดลบนข้อมูลของคุณ",zdr:"Zero Data Retention",zdrTooltip:"Route เฉพาะไปยัง endpoint ที่มีนโยบาย Zero Data Retention",only:"อนุญาตเฉพาะผู้ให้บริการ",onlyTooltip:"ใช้เฉพาะผู้ให้บริการที่ระบุ เว้นว่างเพื่ออนุญาตทั้งหมด",onlyPlaceholder:"พิมพ์ slug ผู้ให้บริการและกด Enter...",ignore:"ข้ามผู้ให้บริการ",ignoreTooltip:"ข้ามผู้ให้บริการเหล่านี้เมื่อ route request",ignorePlaceholder:"พิมพ์ slug ผู้ให้บริการและกด Enter...",quantizations:"ตัวกรอง Quantization",quantizationsTooltip:"ใช้เฉพาะผู้ให้บริการที่มีระดับ quantization ที่กำหนด ความแม่นยำต่ำกว่าอาจลดคุณภาพแต่เพิ่มความเร็ว",maxPrice:"ราคาสูงสุด",maxPriceTooltip:"ตั้งราคาสูงสุดต่อล้าน token เว้นว่างเพื่อไม่จำกัด",configured:"ตั้งค่าแล้ว"}},Gw={label:"โหมด API",standard:"มาตรฐาน",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Key สำหรับแผนนี้มักขึ้นต้นด้วย `{{prefix}}` เป็นเพียงคำแนะนำ ไม่มีการบังคับใช้",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan ใช้ API key แยกต่างหากจาก endpoint มาตรฐาน",baiduCodingPlanSeparateKey:"Qianfan Coding Plan ใช้ API key แยกต่างหากจาก endpoint มาตรฐาน",tencentTokenPlanAnthropicOnly:"Tencent Token Plan รองรับเฉพาะโปรโตคอล Anthropic",xiaomiTokenPlanRegions:"baseUrl เริ่มต้นคือ `token-plan-cn.*` คุณสามารถแก้ไขเป็น `token-plan-sgp.*` หรือ `token-plan-ams.*` ได้",confirmOverwriteTitle:"เปลี่ยนโหมด API?",confirmOverwriteBody:"คุณได้ปรับแต่ง API URL หรือ API Key แล้ว การเปลี่ยนโหมดจะเขียนทับด้วยค่าเริ่มต้นของโหมดใหม่ — หรือคงการปรับแต่งไว้และอัปเดตเฉพาะป้ายกำกับโหมด",overwriteAndSwitch:"เขียนทับและเปลี่ยน",keepCustomizations:"คงการปรับแต่งไว้"},Ww={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},Zw={cancel:"ยกเลิก",close:"ปิด",copy:"คัดลอก",delete:"ลบ",dismiss:"ปิด",save:"บันทึก",optional:"ไม่บังคับ",retry:"ลองใหม่",loading:"กำลังโหลด…"},Qw={common:{learnMore:"เอกสาร"}},Yw={notSupportedByDaemon:"daemon ยังไม่รองรับฟีเจอร์นี้",discoveryUnsupportedFormat:"ยังไม่รองรับการค้นพบโมเดลสำหรับรูปแบบผู้ให้บริการนี้ กรุณาเพิ่มโมเดลด้วยตนเอง"},Xw={subtitle:"แผงควบคุม",providers:"ผู้ให้บริการ",apiService:"บริการ API",accounts:"บัญชี",codeCli:"Code CLI",settings:"การตั้งค่า",usageStats:"การใช้งาน",pricing:"ราคา"},Jw={title:"บริการ API",description:"ตั้งค่าเซิร์ฟเวอร์ API ขาออก การ routing โมเดลแต่ละ endpoint และ access key ที่ตั้งชื่อ",loading:"กำลังโหลดการตั้งค่าเซิร์ฟเวอร์…",loadError:"โหลดการตั้งค่าเซิร์ฟเวอร์ไม่สำเร็จ กรุณาตรวจสอบว่า daemon เข้าถึงได้",enable:{label:"เปิดใช้งานเซิร์ฟเวอร์ขาออก",description:"เริ่ม API เซิร์ฟเวอร์ภายในที่ route ผู้โทรภายนอกผ่านผู้ให้บริการของคุณ"},networkBinding:{label:"อนุญาตการเข้าถึง LAN",description:"ผูก server กับ network interface แทน loopback เท่านั้น",warning:"การเข้าถึง LAN เปิดเผย API server ให้อุปกรณ์อื่นในเครือข่ายของคุณ เมื่อรวมกับ subscription routing request อาจใช้โควต้า subscription ของคุณ — ปิดไว้หากไม่ไว้วางใจเครือข่าย"},status:{running:"เซิร์ฟเวอร์ทำงาน",stopped:"เซิร์ฟเวอร์หยุดทำงาน",runningHint:"API เซิร์ฟเวอร์ขาออกกำลังรับ request",stoppedHint:"เปิดใช้งานเซิร์ฟเวอร์เพื่อเริ่มรับ request",port:"พอร์ต {{port}}",loopback:"Loopback URL",lan:"LAN URL"},endpoints:{title:"การ routing ของ Endpoint",description:"เลือกโมเดลที่แต่ละ wire format route ไป โมเดลเริ่มต้นจะรวมอยู่ที่นี่ — server คือ router ไม่ใช่แอปแชท"},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"โมเดลเริ่มต้น",backgroundModel:"โมเดลพื้นหลัง",visionModel:"โมเดล Vision",noVisionModel:"ไม่มี",backgroundModelIds:"ID โมเดลพื้นหลัง",backgroundModelIdsPlaceholder:"ID โมเดลคั่นด้วยจุลภาค",modelPlaceholder:"เลือกโมเดล…",useSubscription:"ใช้ subscription",subscriptionUnsupported:"ยังไม่รองรับ subscription routing สำหรับ endpoint นี้"},keys:{title:"Access key",description:"Key ที่ตั้งชื่อให้ผู้โทรภายนอกส่งเป็น Bearer token key เต็มจะแสดงเพียงครั้งเดียวเมื่อสร้าง",namePlaceholder:"ชื่อ key (เช่น my-cli)",create:"สร้าง key",empty:"ยังไม่มี access key",enabled:"เปิดใช้งาน",disabled:"ปิดใช้งาน",revoked:"ถูกเพิกถอน",toggle:"สลับ key",revoke:"เพิกถอน",revokeConfirmTitle:"เพิกถอน key นี้?",revokeConfirmDesc:'การเพิกถอน "{{name}}" จะหยุดการยืนยันตัวตนทันที ไม่สามารถยกเลิกการดำเนินการนี้ได้',created:{title:"สร้าง key แล้ว",warning:"คัดลอก key นี้ทันที — จะไม่แสดงอีกครั้ง เก็บรักษาให้ปลอดภัย",copy:"คัดลอก",copied:"คัดลอกแล้ว",dismiss:"เสร็จสิ้น"}}},eT={title:"บัญชีและ Subscription",description:"จัดการ subscription credential ที่เซิร์ฟเวอร์ route ผ่าน Token จะถูกเขียนที่นี่แต่จะไม่แสดงกลับมา",loading:"กำลังโหลดบัญชี…",empty:"ไม่มี subscription provider ที่พร้อมใช้งาน",signIn:"เข้าสู่ระบบ",oauth:{title:"เข้าสู่ระบบ {{name}}",description:"เปิดหน้าเข้าสู่ระบบในเบราว์เซอร์ อนุญาต จากนั้นวาง authorization code ด้านล่าง code จะส่งถึง daemon เท่านั้น — token ที่สร้างจะไม่ถูกแสดง",openPage:"เปิดหน้าเข้าสู่ระบบ",codeLabel:"Authorization code",codePlaceholder:"วาง code ที่นี่",submit:"ยืนยันการเข้าสู่ระบบ"},codexOauth:{title:"เข้าสู่ระบบ {{name}}",description:"เปิดหน้าเข้าสู่ระบบในเบราว์เซอร์และอนุญาต daemon จะรับผลลัพธ์โดยอัตโนมัติ — เปิดหน้านี้ไว้จนกว่าจะเสร็จสิ้น token จะไม่ถูกแสดง",waiting:"กำลังรอให้คุณเข้าสู่ระบบในเบราว์เซอร์…",failed:"การเข้าสู่ระบบล้มเหลว กรุณาลองใหม่อีกครั้ง"},clearProvider:"ล้างทั้งหมด",clearConfirmTitle:"ล้างบัญชี {{name}}?",clearConfirmDesc:"การดำเนินการนี้จะลบ credential ทั้งหมดที่เก็บไว้สำหรับผู้ให้บริการนี้ ไม่สามารถยกเลิกได้",credential:{ok:"ตั้งค่าแล้ว",notConfigured:"ยังไม่ได้ตั้งค่า"},kind:{"pass-through":"Pass-through credentials","oauth-bearer":"OAuth bearer","static-bearer":"Static bearer key"},reason:{"missing-credential":"ไม่มี credential ที่เก็บไว้",expired:"Credential หมดอายุแล้ว","reauth-required":"จำเป็นต้องยืนยันตัวตนใหม่","refresh-failed":"การรีเฟรช token ล้มเหลว","not-refreshable":"Credential ไม่สามารถรีเฟรชได้",unknown:"สถานะไม่ทราบ"},status:{unconfigured:"ยังไม่ได้ตั้งค่า",authorized:"ได้รับอนุญาต",configured:"ตั้งค่าแล้ว",expired:"หมดอายุ",error:"ข้อผิดพลาด"},authMethod:{oauth:"OAuth",setup_token:"Setup token",manual:"ด้วยตนเอง"},list:{empty:"ไม่มีบัญชีที่เก็บไว้สำหรับผู้ให้บริการนี้",active:"ใช้งานอยู่",expiresAt:"หมดอายุ {{value}}",setActive:"ตั้งเป็นใช้งาน",remove:"ลบ",removeConfirmTitle:"ลบบัญชีนี้?",removeConfirmDesc:'การลบ "{{name}}" จะลบ credential ที่เก็บไว้ ไม่สามารถยกเลิกได้',title:"บัญชี"},write:{trigger:"เพิ่ม credential",title:"เขียน credential ของ {{name}}",description:"วาง token material ที่ได้รับมาแล้ว ฟิลด์จำกัดเฉพาะที่ผู้ให้บริการรับ token จะถูกเก็บไว้และไม่แสดงกลับมา",authMethod:"วิธีการยืนยันตัวตน",status:"สถานะ",subscriptionLevel:"ระดับ subscription",subscriptionLevelNone:"ไม่ได้ตั้งค่า",submit:"บันทึก credential"},field:{accessToken:"Access token",refreshToken:"Refresh token",idToken:"ID token",apiKey:"API key",expiresAt:"หมดอายุเมื่อ (ISO)",setupTokenExpiresAt:"Setup token หมดอายุเมื่อ (ISO)",accountId:"Account ID",email:"อีเมล",organizationId:"Organization ID",baseUrl:"Base URL",zenBaseUrl:"Zen base URL"},provider:{claude:{title:"Claude",description:"Anthropic subscription credential ที่ route ผ่าน daemon"},codex:{title:"Codex",description:"OpenAI Codex subscription credential ที่ route ผ่าน daemon"},gemini:{title:"Gemini",description:"Google Gemini subscription credential ที่ route ผ่าน daemon"},opencodego:{title:"OpenCodeGo",description:"Static API-key credential ที่ route ผ่าน daemon"}},authMethodLabel:"วิธีการยืนยันตัวตน",authMethodDesc:{oauth:"เข้าสู่ระบบผ่านเบราว์เซอร์ daemon จะรับและเก็บ token",manual:"วาง token ที่ได้รับมาแล้ว จะถูกเก็บไว้และไม่แสดงกลับมา"},actions:{authorize:"อนุญาต",enterToken:"ใส่ token",refresh:"รีเฟรช"},accounts:{addAccount:"เพิ่มบัญชี"},detail:{authMethod:"วิธีการยืนยันตัวตน",subscriptionLevel:"ระดับ subscription",expiresAt:"หมดอายุ",lastRefreshed:"รีเฟรชล่าสุด",label:"ป้ายกำกับบัญชี",labelPlaceholder:"ตั้งชื่อบัญชีนี้",saveLabel:"บันทึกป้ายกำกับ"},oauthFlow:{step1:{title:"เปิดหน้าการอนุญาต",desc:"เปิดหน้าเข้าสู่ระบบในเบราว์เซอร์ของคุณ"},step2:{title:"อนุญาตการเข้าถึง",desc:"เข้าสู่ระบบและอนุมัติการเข้าถึงสำหรับผู้ให้บริการ"},step3:{title:"คัดลอก authorization code",desc:"หน้าจอจะแสดง authorization code หลังจากที่คุณอนุมัติ"},step4:{title:"วาง code",desc:"วาง authorization code ด้านล่างเพื่อเสร็จสิ้น code จะส่งถึง daemon เท่านั้น — token ที่สร้างจะไม่ถูกแสดง"},authorize:"ยืนยันการเข้าสู่ระบบ",showUrl:"แสดง URL การอนุญาต"},manual:{title:"วาง credential",description:"วาง token ที่ได้รับมาแล้ว ฟิลด์จำกัดเฉพาะที่ผู้ให้บริการรับ token จะถูกเก็บไว้และไม่แสดงกลับมา",accessTokenPlaceholder:"วาง access token",refreshTokenPlaceholder:"วาง refresh token (ไม่บังคับ)",hint:"Token จะถูกส่งถึง daemon และเก็บไว้อย่างเข้ารหัส จะไม่แสดงกลับมา"},openCodeGo:{apiKeyRequired:"จำเป็นต้องใส่ API key",apiKeyPlaceholder:"วาง API key",baseUrlPlaceholder:"https://… (ไม่บังคับ)",zenBaseUrlPlaceholder:"https://… (ไม่บังคับ)"},info:{title:"เกี่ยวกับ subscription account",description:"Token จะถูกเขียนไปยัง daemon และใช้เพื่อยืนยันตัวตนกับ upstream request จะถูกเก็บไว้อย่างเข้ารหัสและไม่แสดงกลับมา การลบบัญชีจะลบ credential ที่เก็บไว้"},rename:{failed:"ไม่สามารถเปลี่ยนชื่อบัญชีได้"},refresh:{failed:"ไม่สามารถรีเฟรช token ได้"},errors:{requestFailed:"Request ล้มเหลว กรุณาลองใหม่อีกครั้ง"},syncWarning:{"external-divergent":"ไฟล์เข้าสู่ระบบของ CLI ภายนอกมีข้อมูลรับรองที่ใหม่กว่าบัญชีนี้ โทเค็นที่บันทึกไว้อาจหยุดรีเฟรช — รีเฟรชตอนนี้หรือเข้าสู่ระบบอีกครั้ง","external-not-rotated":"การรีเฟรชล้มเหลว และ CLI ภายนอกมีข้อมูลรับรองที่หมดอายุเดียวกัน โปรดเข้าสู่ระบบอีกครั้ง","duplicate-token":"บัญชีอื่นใช้ข้อมูลรับรองนี้ร่วมกัน การรีเฟรชบัญชีใดบัญชีหนึ่งจะทำให้อีกบัญชีถูกออกจากระบบ"},importExternal:{detected:"พบการเข้าสู่ระบบ CLI ของ {{name}} ที่มีอยู่บนเครื่องนี้",hint:"หลังนำเข้า แอปนี้จะคอยอัปเดตให้: ทุกครั้งที่รีเฟรชโทเค็น ไฟล์เข้าสู่ระบบของ CLI จะถูกอัปเดตด้วย ทำให้ CLI ในเทอร์มินัลยังคงเข้าสู่ระบบอยู่",button:"นำเข้าการเข้าสู่ระบบ CLI ที่มีอยู่"}},tT={title:"Code CLI",description:"เชื่อมต่อ coding CLI กับ outbound proxy ของ daemon หน้านี้เป็นแบบอ่านอย่างเดียว — ไม่มีการตั้งค่าที่นี่",copy:"คัดลอก",copied:"คัดลอกแล้ว",baseUrl:{title:"Daemon base URL",description:"ที่อยู่ proxy ที่ CLI ของคุณเชื่อมต่อ",label:"Base URL"},token:{title:"การยืนยันตัวตน",hint:"ส่ง 'Authorization: Bearer <your-admin-token>' สำหรับ admin route Admin token ถูกตั้งค่าใน daemon (ไฟล์ config หรือ environment) — จะไม่แสดงที่นี่"},examples:{title:"ตัวอย่าง launch environment",keyNote:"ใช้ outbound access key ที่สร้างในหน้า API Service — ไม่ใช่ admin token",anthropic:"CLI รูปแบบ Anthropic",openai:"CLI รูปแบบ OpenAI"},launchDescription:"เปิด coding CLI ในเทอร์มินัล โดยชี้ไปที่ daemon นี้ daemon จะฉีด env redirect และเริ่ม CLI ให้คุณ",refresh:"รีเฟรช",loading:"กำลังตรวจสอบ CLI…",cli:{installed:"ติดตั้งแล้ว",notFound:"ไม่พบ",notFoundHint:"CLI นี้ไม่อยู่ใน PATH ของ daemon host ติดตั้งก่อนแล้วรีเฟรช",install:"ติดตั้ง",installing:"กำลังติดตั้ง…",installingHint:"กำลังติดตั้งบน daemon host — อาจใช้เวลาสักครู่",launch:"เปิด",launchTitle:"เปิด {{name}}",launchDescription:"เปิดเทอร์มินัลใหม่บน daemon host ที่รัน CLI นี้ route ผ่าน daemon proxy เลือก working directory เสริม",cwdLabel:"Working directory",cwdPlaceholder:"/path/to/your/project",runningVia:"กำลังทำงาน · {{provider}} / {{model}}",stop:"หยุด"},manual:{title:"ตั้งค่าด้วยตนเอง",description:"ต้องการรัน CLI เอง? ชี้ไปที่ daemon ด้วยตัวแปร env เหล่านี้",show:"แสดง",hide:"ซ่อน"}},aT={probing:"กำลังตรวจสอบ daemon…",spawning:"กำลังเริ่ม daemon…",failed:"ไม่สามารถเริ่ม daemon ได้",failedHint:"ตรวจสอบว่าติดตั้ง Node.js แล้วและ daemon ถูก build แล้ว (มีโฟลเดอร์ dist) หรือตั้งค่า OMNICROSS_DAEMON_ENTRY ชี้ไปที่ cli.js ของ daemon"},nT={title:"การตั้งค่า",description:"การตั้งค่าแอป desktop",desktopOnly:"ตัวเลือก Startup และ Tray ใช้ได้เฉพาะในแอป desktop",startup:{title:"Startup",autoLaunch:"เปิดเมื่อล็อกอิน",autoLaunchHint:"เริ่ม Omnicross อัตโนมัติเมื่อคุณลงชื่อเข้าใช้",startMinimized:"เริ่มแบบย่อในถาด",startMinimizedHint:"เปิดในพื้นหลังโดยไม่เปิดหน้าต่าง"},tray:{title:"Tray",minimizeOnClose:"ย่อลงถาดเมื่อปิด",minimizeOnCloseHint:"การปิดหน้าต่างจะซ่อนไว้ในถาดแทนการออกจากโปรแกรม"},language:{title:"ภาษา",label:"ภาษาของหน้าจอ"}},oT={title:"สถิติการใช้งาน",description:"สถิติโทเคนและค่าใช้จ่ายของคำขอที่เดมอนให้บริการ",rangeToday:"วันนี้",range7d:"7 วันที่ผ่านมา",range30d:"30 วันที่ผ่านมา",rangeCustom:"กำหนดเอง",from:"จาก",to:"ถึง",totalCost:"ค่าใช้จ่ายรวม",cacheSavings:"ประหยัดจากแคช",events:"คำขอ",inputTokens:"โทเคนอินพุต",outputTokens:"โทเคนเอาต์พุต",cacheReadTokens:"อ่านแคช",cacheWriteTokens:"เขียนแคช",reasoningTokens:"โทเคนการคิดวิเคราะห์",byModel:"ตามโมเดล",byApiKey:"ตามคีย์ API",provider:"ผู้ให้บริการ",model:"โมเดล",cost:"ค่าใช้จ่าย",apiKey:"คีย์ API",unpriced:"ไม่มีราคา",unpricedHint:"ไม่มีรายการราคาสำหรับโมเดลนี้ — เพิ่มได้ที่หน้าราคา",unattributed:"ไม่ระบุที่มา",unattributedHint:"คำขอที่ไม่เชื่อมโยงกับคีย์ API ใดโดยเฉพาะ ถือเป็นเรื่องปกติจนกว่าจะมีการบันทึกที่มาตามคีย์",empty:"ไม่มีคำขอในช่วงนี้",invalidRange:"เลือกช่วงวันที่ที่ถูกต้อง"},iT={title:"ราคาโมเดล",description:"ราคาโทเคนต่อโมเดลที่ใช้คำนวณค่าใช้จ่ายของคำขอ หน่วยเป็น USD ต่อ 1 ล้านโทเคน",search:"ค้นหาผู้ให้บริการหรือโมเดล…",fetchLatest:"ดึงข้อมูลล่าสุด",fetching:"กำลังดึง…",addEntry:"เพิ่มรายการ",provider:"ผู้ให้บริการ",model:"โมเดล",inputPrice:"อินพุต",outputPrice:"เอาต์พุต",cacheReadPrice:"อ่านแคช",cacheWritePrice:"เขียนแคช",source:"แหล่งที่มา",updated:"อัปเดตเมื่อ",userEdited:"แก้ไขแล้ว",edit:"แก้ไข",deleteTitle:"ลบรายการราคานี้?",empty:"ตารางราคาว่างเปล่า",emptyHint:"ดึงราคาล่าสุดเพื่อเติมข้อมูล",noMatches:"ไม่มีรายการที่ตรงกับการค้นหา",saved:"บันทึกรายการราคาแล้ว",saveFailed:"บันทึกล้มเหลว: {{message}}",deleteFailed:"ลบล้มเหลว: {{message}}",alreadyDeleted:"รายการถูกลบไปแล้ว",fetchApplied:"อัปเดต {{count}} รายการจากแหล่งที่มา",fetchFailed:"ดึงข้อมูลล้มเหลว: {{message}}",requiredId:"จำเป็น",invalidPrice:"กรอกตัวเลขที่ไม่ติดลบ",conflictTitle:"แก้ไขข้อขัดแย้งของราคา",conflictHint:"รายการเหล่านี้ถูกคุณแก้ไขและมีการเปลี่ยนแปลงที่แหล่งที่มาด้วย เลือกทีละแถวว่าจะเก็บค่าของคุณ (ข้าม) หรือใช้ค่าที่เข้ามา (เขียนทับ)",current:"ปัจจุบัน",incoming:"ที่เข้ามา",overwrite:"เขียนทับ",skip:"ข้าม",overwriteAll:"เขียนทับทั้งหมด",skipAll:"ข้ามทั้งหมด",applyResolutions:"นำไปใช้",resolved:"เขียนทับ {{overwritten}} รายการ ข้าม {{skipped}} รายการ",resolvedWithStale:"เขียนทับ {{overwritten}} รายการ ข้าม {{skipped}} รายการ มี {{stale}} รายการถูกแก้ไขระหว่างนั้นและไม่ถูกแตะต้อง",refreshFailed:"นำการเปลี่ยนแปลงไปใช้แล้ว แต่โหลดรายการใหม่ไม่สำเร็จ: {{message}}",sourceBuiltin:"ในตัว",sourceLitellm:"LiteLLM",sourceUser:"ผู้ใช้"},rT={providerSettings:_w,apiMode:Gw,presetName:Ww,common:Zw,mediaSettings:Qw,appLocal:Yw,nav:Xw,apiService:Jw,accounts:eT,codeCli:tT,daemonStatus:aT,settings:nT,usageStats:oT,pricing:iT},sT={loading:"LLM yapılandırması yükleniyor...",reset:{button:"Varsayılanları geri yükle",confirmTitle:"Varsayılan ayarlar geri yüklensin mi?",confirmBody:"Bu işlem, bu sağlayıcı için özelleştirmelerinizi temizler ve yerleşik varsayılanlara geri döner. API anahtarınız ve kaydedilen oturumlarınız korunur.",confirmButton:"Varsayılanları geri yükle"},reentryBanner:{message:"{{count}} etkin sağlayıcının API anahtarının yeniden girilmesi gerekiyor. Her birini açıp anahtarı tekrar ekleyin."},migrationPack:{barHint:"Sağlayıcı anahtarlarınızı ve abonelik tokenlarınızı şifreli bir paket ile başka bir makineye taşıyın.",passphrase:"Parola",passphrasePlaceholder:"Bir parola girin",passphraseHint:"En az 8 karakter kullanın; 12 veya daha fazlası önerilir.",confirm:"Parolayı onayla",confirmPlaceholder:"Parolayı yeniden girin",mismatch:"Parolalar eşleşmiyor.",strength:{weak:"Çok kısa — en az 8 karakter kullanın.",fair:"Yeterli — 12 veya daha fazla karakter daha güvenli.",strong:"Güçlü parola."},export:{button:"Paketi dışa aktar",title:"Şifreli paketi dışa aktar",subtitle:"Sağlayıcı anahtarlarınızı ve abonelik tokenlarınızı taşınabilir bir dosyaya şifreleyin.",warning:"Bu dosya çözülebilir gizli bilgiler içerir. Güvende tutun — dosya ve parolaya sahip herkes anahtarlarınızı okuyabilir. Kaybedilen parola kurtarılamaz.",submit:"Dışa Aktar",success:"Paket başarıyla dışa aktarıldı.",error:"Dışa aktarma başarısız. Lütfen tekrar deneyin."},import:{button:"Paketi içe aktar",title:"Şifreli paketi içe aktar",subtitle:"Dışa aktarılan paketten sağlayıcı anahtarlarını ve abonelik tokenlarını geri yükleyin.",hint:"Paketin dışa aktarılmasında kullanılan parolayı girin, ardından dosyayı seçin.",submit:"İçe Aktar",successTitle:"İçe aktarma tamamlandı",summary:"{{providerKeys}} sağlayıcı anahtarı, {{poolKeys}} havuz anahtarı ve {{tokenSets}} token seti içe aktarıldı.",duplicates:"Zaten mevcut olan {{count}} havuz anahtarı atlandı.",skipped:"Atlandı (eşleşen sağlayıcı yok): {{names}}",error:"Yanlış parola veya bozuk paket. Hiçbir şey değiştirilmedi."}},searchPlaceholder:"Sağlayıcıları ara...",emptySearch:"Aramanızla eşleşen sağlayıcı yok.",emptyList:"Yapılandırılmış sağlayıcı yok.",selectPrompt:"Ayrıntıları görüntülemek için bir sağlayıcı seçin",listStatus:"{{count}} model",noModels:"Yapılandırılmış model yok",enabled:"Etkin",disabled:"Devre dışı",showEnabledOnly:"Yalnızca etkinleri göster",showAll:"Tüm sağlayıcıları göster",dragHandle:"Yeniden sıralamak için sürükleyin",reorderFailed:"Sağlayıcı sırası kaydedilemedi",credentials:{apiKey:"API Anahtarı",apiBaseUrl:"API Temel URL'si"},filter:{all:"Tümü",chat:"Sohbet",code:"Kod"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Şablon Seçin",skipTemplates:"Atla, manuel yapılandır",name:"Ad *",providerType:"Tür",apiType:"API Türü",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Standart OpenAI chat/completions API formatı",claudecode:"Anthropic Messages API formatı (Claude Code)"},chatApiFormat:"API Formatı",chatApiFormatDescription:"Sağlayıcınızın endpoint'iyle eşleşen API formatını seçin",apiKey:"API Anahtarı",apiKeyPlaceholder:"sk-... veya $ENV_VAR",apiKeyHelper:"Ortam değişkenlerine başvurmak için $VAR_NAME kullanın",apiKeySetPlaceholder:"Anahtar ayarlandı — korumak için boş bırakın",apiKeyReplaceHelper:"Bir anahtar güvenli şekilde saklandı. Değiştirmek için yeni bir değer yazın veya korumak için boş bırakın.",testApiKey:"API Anahtarını Test Et",apiUrl:"API URL'si *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Önizleme:",models:"Modeller",modelPlaceholder:"Model adı (örn. gpt-4, claude-3-opus)",transformers:"Dönüştürücüler",transformerConfig:"API Dönüştürücüleri",transformerConfigDescription:"Bu sağlayıcı için API istek/yanıt formatlarını uyarlamak üzere dönüştürücüleri yapılandırın",transformerConfigNote:"Daemon, bu dönüştürücüleri istek zincirinde, sağlayıcının format dönüştürücüsünden (wire-format dönüşümünü yönetir) sonra uygular. Bilinmeyen dönüştürücü adları atlanır.",enabled:"Etkin",apiVersion:"API Sürümü",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API sürümü (örn. 2024-08-01-preview)",official:"Resmi Anthropic API",officialHelper:"Bu sağlayıcı doğrudan resmi Anthropic API'ye bağlanıyorsa etkinleştirin. Ters proxy'ler veya üçüncü taraf hizmetler için devre dışı bırakın.",maxConcurrency:"Maks Eş Zamanlı İstek",maxConcurrencyHelper:"Bu sağlayıcıya gönderilen maksimum eş zamanlı API isteği sayısı. Düşük değerler hız sınırlamalarından (429 hatası) kaçınmaya yardımcı olur. Sınır yok için `-1` ayarlayın.",codingPlan:{label:"Kodlama Planı",description:"Abonelik tabanlı kodlama planları için ayrı bir API endpoint'i kullanın",baseUrl:"Kodlama Planı Temel URL'si",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Kodlama Planı API Anahtarı (isteğe bağlı)",apiKeyPlaceholder:"Sağlayıcının API anahtarını kullanmak için boş bırakın",apiKeyHelper:"Yalnızca kodlama planı farklı bir API anahtarı kullanıyorsa gereklidir",tokenPlanHint:"Bazı sağlayıcılar (örn. Xiaomi MiMo) `tp-` önekiyle Token Plan anahtarları verir — yalnızca bilgilendirme amaçlı, zorunlu değil."},selectTypeFirst:"Sağlayıcı Türünü Seçin",selectTypeFirstDesc:"Eklemek istediğiniz sağlayıcı türünü seçin",codeProviderNote:"Kod sağlayıcıları yalnızca API Anahtarı ve URL gerektirir. Modeller Agent Router tarafından yönetilir.",buttons:{cancel:"İptal",submitAdd:"Sağlayıcı Ekle",submitUpdate:"Sağlayıcıyı Güncelle",continue:"Devam",back:"Geri"}},details:{noSelection:"Ayrıntıları görüntülemek için bir sağlayıcı seçin",apiKey:"API Anahtarı",apiUrl:"API URL'si",nameLabel:"Sağlayıcı Adı",modelsEndpoint:"Modeller Endpoint'i",modelsEndpointHelper:"Sağlayıcı özel bir /models yolu sunuyorsa keşif endpoint'ini geçersiz kılın.",models:"Modeller",transformers:"Dönüştürücüler",codeProviderNote:"Kod sağlayıcıları (Claude Code gibi) model yapılandırması gerektirmez. Modeller Agent Router tarafından otomatik olarak yönetilir.",buttons:{more:"Daha Fazla Ayar",delete:"Sil"}},providerModelSelector:{placeholder:"Sağlayıcı ve model seçin",noProviders:"Kullanılabilir sağlayıcı yok",noModels:"Yapılandırılmış model yok"},apiKeyPool:{title:"API Anahtarı Havuzu",description:"Yük dengeleme için birden fazla API anahtarı yapılandırın. Her oturum, istem önbelleğini korumak için bir anahtara bağlı kalır.",defaultLabel:"Varsayılan",weight:"Ağırlık",noKey:"Anahtar yok",labelPlaceholder:"Etiket (örn. Anahtar #1, Üretim)",addKey:"API Anahtarı Ekle",add:"Ekle",empty:"Ek anahtar yapılandırılmamış.",statusCoolingDown:"Soğuyor {{time}}",statusAuthFailed:"Kimlik doğrulama başarısız · devre dışı",statusDisabled:"Devre Dışı",statusHealthy:"Sağlıklı",agoSeconds:"{{count}}s önce",agoMinutes:"{{count}}d önce",agoHours:"{{count}}s önce",agoDays:"{{count}}g önce"},modelsManager:{searchPlaceholder:"Modelleri ara...",defaultGroup:"Tüm Modeller",add:"Model Ekle",manage:"Yönet",empty:"Bu grupta model yok",enabled:"Etkin",disabled:"Devre dışı",filters:{all:"Tümü",vision:"Görsel",reasoning:"Akıl Yürütme",free:"Ücretsiz",tools:"Araçlar"},manualDialog:{title:"Model Ekle",subtitle:"Bu sağlayıcıya özel model ekleyin",modelId:"Model Kimliği",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash vb.",modelIdHelper:"API çağrılırken kullanılan tam model tanımlayıcısı",modelName:"Görünen Ad",modelNamePlaceholder:"Kolay görünen ad (isteğe bağlı)",modelNameHelper:"Arayüzde gösterilen isteğe bağlı ad. Boşsa Model Kimliği kullanılır",group:"Grup",groupPlaceholder:"Bir grup adı seçin veya girin",submit:"Ekle",cancel:"İptal",helper:"Sağlayıcı API'si tarafından sunulan tam model tanımlayıcısını girin."},editDialog:{title:"Modeli Düzenle",subtitle:"Model ayarlarını değiştir",modelId:"Model Kimliği",modelIdPlaceholder:"Model tanımlayıcısı",modelIdHelper:"API çağrılırken kullanılan model tanımlayıcısı",modelName:"Görünen Ad",modelNamePlaceholder:"Kolay görünen ad",modelNameHelper:"Arayüzde gösterilen ad",group:"Grup",groupPlaceholder:"Bir grup adı seçin veya girin",submit:"Kaydet",cancel:"İptal",vision:"Görsel Yetenek",visionHint:"Bu modelin görüntü/görsel girişi destekleyip desteklemediği",reasoning:"Düşünme Modeli",reasoningHint:"Bu modelin düşünme/akıl yürütme modunu destekleyip desteklemediği"},manageDialog:{title:"Modelleri Yönet",cachedAt:"{{date}} tarihinde önbelleğe alındı ({{source}})",refresh:"Yenile",close:"Kapat",raw:"Ham JSON",empty:"Uzak model mevcut değil.",error:"Modeller yüklenemedi: {{message}}",addFromCatalog:"Ekle",sourceCache:"önbellek",sourceNetwork:"canlı",contextLength:"Bağlam {{value}} token",maxTokens:"Maks {{value}} token"},messages:{added:"Model eklendi.",updated:"Model güncellendi.",removed:"Model kaldırıldı.",duplicate:"Model zaten mevcut.",refreshed:"Modeller yenilendi",refreshFailed:"Modeller yenilenemedi"},testDialog:{title:"Model Bağlantı Testi",provider:"Sağlayıcı",model:"Model",testing:"Test ediliyor...",success:"Test Başarılı",successMessage:"Modele normal şekilde erişilebiliyor",failure:"Test Başarısız",aiResponse:"AI Yanıtı",charCount:"{{count}} karakter",duration:"Süre {{time}}s",close:"Kapat",retest:"Yeniden Test Et",testButton:"Modeli test et",unsupportedFormat:"Bu sağlayıcı formatı için test henüz desteklenmiyor."}},router:{title:"Router Yapılandırması",description:"Farklı senaryolarda kullanılacak sağlayıcı/modeli yapılandırın.",labels:{default:"Varsayılan",background:"arka plan",think:"düşünme",longContext:"Uzun Bağlam",webSearch:"Web Arama",image:"Görüntü",longContextThreshold:"Uzun Bağlam Eşiği"},helper:{longContextThreshold:"Uzun bağlam modeline geçmeden önce token sayısı."},placeholder:{required:"Zorunlu",optional:"İsteğe bağlı"}},agentRouter:{title:"Agent Router",description:"Sohbet ve Kod modları arasında çift yönlü yönlendirmeyi yapılandırın.",searchPlaceholder:"Router'ları ara...",noSearchResults:"Aramanızla eşleşen router yok.",tabs:{chatToCode:"Sohbet → Kod",codeToChatPlaceholder:"Kod → Sohbet"},chatToCode:{title:"Sohbet'ten Koda Router",description:"Ajan/kodlama modunda sohbet sağlayıcılarını kullanın",addRouter:"Router Ekle",emptyState:"Sohbet→Kod router'ı yapılandırılmamış. Kodlama modunda sohbet sağlayıcılarını kullanmak için bir tane ekleyin.",form:{name:"Router Adı",namePlaceholder:"Sohbet→Kod Router'ım",chatProvider:"Sohbet Sağlayıcısı",chatProviderPlaceholder:"Bir sohbet sağlayıcısı seçin",mode:"Mod",modeSimple:"Basit",modeAdvanced:"Gelişmiş",modeSimpleDesc:"Sohbet sağlayıcısına doğrudan iletim",modeAdvancedDesc:"Model eşlemesini ve bağlam işlemeyi yapılandırın",enabled:"Etkin",save:"Router'ı Kaydet",cancel:"İptal"},list:{provider:"Sağlayıcı",mode:"Mod",status:"Durum"},mappings:{title:"Model Eşlemeleri",description:"Sohbet sağlayıcısı modellerini Kod sağlayıcısı modelleriyle eşleyin",count:"eşleme",empty:"Model eşlemesi yapılandırılmamış. Sohbet modellerini kod sağlayıcılarına yönlendirmek için eşleme ekleyin.",addNew:"Yeni Eşleme Ekle",selectSource:"Kaynak modeli seçin (Sohbet)",selectTarget:"Hedef modeli seçin (Kod)",targetPlaceholder:"Claude Code model adını girin",notSet:"(Ayarlanmadı - seçmek için tıklayın)",add:"Ekle",edit:"Düzenle",done:"Tamam"},advanced:{title:"Gelişmiş Yapılandırma",description:"Farklı görev türleri için modelleri yapılandırın",helpText:"Varsayılan model zorunludur. Diğer modeller isteğe bağlıdır ve yapılandırılmamışsa varsayılana geri döner.",default:{label:"Varsayılan",placeholder:"Varsayılan modeli seçin",description:"Genel görevler için birincil model (Claude Sonnet'e benzer)"},background:{label:"Arka Plan",placeholder:"Arka plan modelini seçin",description:"Arka plan görevleri için hafif model (Claude Haiku'ya benzer)"},think:{label:"Düşünme",placeholder:"Düşünme modelini seçin",description:"Karmaşık akıl yürütme için gelişmiş model (Claude Opus'a benzer)"},image:{label:"Görüntü",placeholder:"Görüntü modelini seçin",description:"Görsel yeteneğiyle görüntü ile ilgili görevler için model"}}},codeToChat:{title:"Koddan Sohbete Router",description:"Kodlama Planı modellerini sohbet modunda göster",addRouter:"Router Ekle",emptyState:"Kod→Sohbet router'ı yapılandırılmamış. Kodlama Planı modellerini sohbet modunda göstermek için bir tane ekleyin.",form:{name:"Router Adı",namePlaceholder:"Kod→Sohbet Router'ım",codeProvider:"Kod Sağlayıcısı",codeProviderPlaceholder:"Bir kod sağlayıcısı seçin",codeProviderHelper:"Dönüşüm için kullanılacak Kod sağlayıcısını seçin",models:"Kodlama Planı Modelleri",modelsHelper:"Gösterilecek Kodlama Planı modellerini seçin",enabled:"Etkin",save:"Router'ı Kaydet",cancel:"İptal"},mappings:{title:"Model Eşlemeleri",description:"Kod sağlayıcısı modellerini göstermek için Sohbet sağlayıcısı modelleriyle eşleyin",count:"eşleme",empty:"Model eşlemesi yapılandırılmamış. Kod modellerini sohbet modunda göstermek için eşleme ekleyin.",addNew:"Yeni Eşleme Ekle",selectSource:"Kaynak modeli seçin (Kod)",selectTarget:"Hedef modeli seçin (Sohbet)",sourcePlaceholder:"Kaynak model adını girin",targetPlaceholder:"Hedef model adını girin",add:"Ekle",edit:"Düzenle",done:"Tamam"}},transformers:{title:"Dönüştürücüler",description:"İstek/yanıt dönüşümü için dönüştürücüleri yapılandırın",noProvider:"Dönüştürücüleri yapılandırmak için bir sağlayıcı seçin",empty:"Dönüştürücü yok",count:"{{count}} dönüştürücü"},status:{enabled:"Etkin",disabled:"Devre dışı"},messages:{routerAdded:"Router başarıyla eklendi",routerUpdated:"Router başarıyla güncellendi",routerDeleted:"Router başarıyla silindi",saveFailed:"Router kaydedilemedi"}},presets:{title:"Hızlı Sağlayıcı Ekle",added:"Eklendi",add:"Ekle",features:{search:"Arama",vision:"Görsel",mcp:"MCP",codingPlan:"Kodlama Planı"}},alerts:{deleteConfirm:"Bu sağlayıcıyı silmek istediğinizden emin misiniz?"},errors:{nameRequired:"Sağlayıcı adı zorunludur",urlRequired:"API Temel URL'si zorunludur",urlInvalid:"Lütfen geçerli bir URL girin (örn. https://api.example.com)",saveFailed:"Sağlayıcı kaydedilemedi",deleteFailed:"Sağlayıcı silinirken hata oluştu. Lütfen tekrar deneyin.",toggleFailed:"Sağlayıcı durumu değiştirilirken hata oluştu. Lütfen tekrar deneyin."},openRouter:{title:"OpenRouter Sağlayıcı Yönlendirmesi",description:"İsteklerin OpenRouter'daki farklı sağlayıcılara nasıl yönlendirileceğini yapılandırın.",sort:"Yönlendirme Stratejisi",sortTooltip:"Sağlayıcıların nasıl önceliklendirileceğini seçin. Otomatik, akıllı yük dengeleme kullanır.",order:"Sağlayıcı Öncelik Sırası",orderTooltip:"Sırayla denenecek sağlayıcıları belirtin (örn. anthropic, openai, together). Eklemek için Enter'a basın.",orderPlaceholder:"Sağlayıcı slug'ını yazıp Enter'a basın...",allowFallbacks:"Yedeklere İzin Ver",allowFallbacksTooltip:"Etkinleştirildiğinde, birincil sağlayıcı kullanılamıyorsa OpenRouter yedek sağlayıcıları dener.",requireParameters:"Tüm Parametreleri Zorunlu Kıl",requireParametersTooltip:"Yalnızca isteklerinizdeki tüm parametreleri destekleyen sağlayıcılara yönlendir.",dataCollection:"Veri Toplama Politikası",dataCollectionTooltip:"Verilerinizi saklayabilecek veya üzerinde eğitim yapabilecek sağlayıcıların kullanılıp kullanılmayacağını kontrol edin.",zdr:"Sıfır Veri Saklama",zdrTooltip:"Yalnızca Sıfır Veri Saklama politikasına sahip endpoint'lere yönlendir.",only:"Yalnızca Bu Sağlayıcılara İzin Ver",onlyTooltip:"Yalnızca bu belirli sağlayıcıları kullanın. Tüm sağlayıcılara izin vermek için boş bırakın.",onlyPlaceholder:"Sağlayıcı slug'ını yazıp Enter'a basın...",ignore:"Sağlayıcıları Yoksay",ignoreTooltip:"İstekleri yönlendirirken bu sağlayıcıları atlayın.",ignorePlaceholder:"Sağlayıcı slug'ını yazıp Enter'a basın...",quantizations:"Niceleme Filtresi",quantizationsTooltip:"Yalnızca belirli niceleme düzeylerine sahip sağlayıcıları kullanın. Daha düşük hassasiyet kaliteyi düşürebilir ancak hızı artırabilir.",maxPrice:"Maksimum Fiyat",maxPriceTooltip:"Milyon token başına maksimum fiyat sınırlarını ayarlayın. Sınır yok için boş bırakın.",configured:"Yapılandırıldı"}},lT={label:"API Modu",standard:"Standart",codingPlan:"Kodlama Planı",tokenPlan:"Token Planı",apiKeyPrefixHint:"Bu plan için anahtarlar genellikle `{{prefix}}` ile başlar. Yalnızca ipucu — zorunlu değil.",dashscopeCodingPlanSeparateKey:"DashScope Kodlama Planı, standart endpoint'ten ayrı bir API anahtarı kullanır.",baiduCodingPlanSeparateKey:"Qianfan Kodlama Planı, standart endpoint'ten ayrı bir API anahtarı kullanır.",tencentTokenPlanAnthropicOnly:"Tencent Token Planı yalnızca Anthropic protokolüdür.",xiaomiTokenPlanRegions:"Varsayılan baseUrl `token-plan-cn.*`'dir. Manuel olarak `token-plan-sgp.*` veya `token-plan-ams.*` olarak düzenleyebilirsiniz.",confirmOverwriteTitle:"API modu değiştirilsin mi?",confirmOverwriteBody:"API URL'sini veya API Anahtarını özelleştirdiniz. Mod değiştirildiğinde bunların üzerine yeni modun varsayılanları yazılır — veya özelleştirmelerinizi koruyarak yalnızca mod etiketini güncelleyin.",overwriteAndSwitch:"Üzerine yaz ve değiştir",keepCustomizations:"Özelleştirmeleri koru"},dT={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Planı)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},cT={cancel:"İptal",close:"Kapat",copy:"Kopyala",delete:"Sil",dismiss:"Kapat",save:"Kaydet",optional:"isteğe bağlı",retry:"Yeniden dene",loading:"Yükleniyor…"},uT={common:{learnMore:"Belgeler"}},pT={notSupportedByDaemon:"Daemon tarafından henüz desteklenmiyor",discoveryUnsupportedFormat:"Bu sağlayıcı formatı için model keşfi henüz desteklenmiyor. Modelleri manuel olarak ekleyin."},mT={subtitle:"Kontrol Paneli",providers:"Sağlayıcılar",apiService:"API Hizmeti",accounts:"Hesaplar",codeCli:"Code CLI",settings:"Ayarlar",usageStats:"Kullanım",pricing:"Fiyatlar"},gT={title:"API Hizmeti",description:"Giden API sunucusunu, endpoint bazında model yönlendirmesini ve adlandırılmış erişim anahtarlarını yapılandırın.",loading:"Sunucu yapılandırması yükleniyor…",loadError:"Sunucu yapılandırması yüklenemedi. Daemon'a erişilebildiğinden emin olun.",enable:{label:"Giden sunucuyu etkinleştir",description:"Harici çağrıcıları sağlayıcılarınız aracılığıyla yönlendiren yerel API sunucusunu başlatın."},networkBinding:{label:"LAN erişimine izin ver",description:"Sunucuyu yalnızca geri döngü yerine ağ arayüzünüze bağlayın.",warning:"LAN erişimi, API sunucusunu ağınızdaki diğer cihazlara açar. Abonelik yönlendirmesiyle birleştiğinde, istekler abonelik kotanızı tüketebilir — ağa güvenmiyorsanız bunu kapalı tutun."},status:{running:"Sunucu çalışıyor",stopped:"Sunucu durduruldu",runningHint:"Giden API sunucusu istekleri kabul ediyor.",stoppedHint:"İstekleri kabul etmeye başlamak için sunucuyu etkinleştirin.",port:"port {{port}}",loopback:"Geri Döngü URL'leri",lan:"LAN URL'leri"},endpoints:{title:"Endpoint yönlendirmesi",description:"Her wire formatının yönlendireceği modeli seçin. Varsayılan model burada belirlenir — sunucu bir router'dır, sohbet uygulaması değil."},endpoint:{name:{chat:"OpenAI Sohbet",responses:"OpenAI Yanıtları",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Varsayılan model",backgroundModel:"Arka plan modeli",visionModel:"Görsel model",noVisionModel:"Yok",backgroundModelIds:"Arka plan model kimlikleri",backgroundModelIdsPlaceholder:"virgülle ayrılmış model kimlikleri",modelPlaceholder:"Bir model seçin…",useSubscription:"Abonelik kullan",subscriptionUnsupported:"Bu endpoint için abonelik yönlendirmesi mevcut değil."},keys:{title:"Erişim anahtarları",description:"Harici çağrıcıların Bearer token olarak gönderdiği adlandırılmış anahtarlar. Tam anahtar yalnızca oluşturulurken bir kez gösterilir.",namePlaceholder:"Anahtar adı (örn. my-cli)",create:"Anahtar oluştur",empty:"Henüz erişim anahtarı yok.",enabled:"Etkin",disabled:"Devre dışı",revoked:"İptal edildi",toggle:"Anahtarı aç/kapat",revoke:"İptal et",revokeConfirmTitle:"Bu anahtar iptal edilsin mi?",revokeConfirmDesc:'"{{name}}" iptal edildiğinde kimlik doğrulaması hemen durur. Bu işlem geri alınamaz.',created:{title:"Anahtar oluşturuldu",warning:"Bu anahtarı şimdi kopyalayın — bir daha gösterilmeyecek. Güvenli bir yerde saklayın.",copy:"Kopyala",copied:"Kopyalandı",dismiss:"Tamam"}}},hT={title:"Hesaplar ve Abonelikler",description:"Sunucunun üzerinden yönlendirdiği abonelik kimlik bilgilerini yönetin. Tokenlar buraya yazılır ancak hiçbir zaman geri görüntülenmez.",loading:"Hesaplar yükleniyor…",empty:"Kullanılabilir abonelik sağlayıcısı yok.",signIn:"Giriş yap",oauth:{title:"{{name}}'e giriş yap",description:"Tarayıcınızda giriş sayfasını açın, yetkilendirin, ardından yetkilendirme kodunu aşağıya yapıştırın. Kod yalnızca daemon'a iletilir — oluşturulan token hiçbir zaman gösterilmez.",openPage:"Giriş sayfasını aç",codeLabel:"Yetkilendirme kodu",codePlaceholder:"Kodu buraya yapıştırın",submit:"Girişi tamamla"},codexOauth:{title:"{{name}}'e giriş yap",description:"Tarayıcınızda giriş sayfasını açın ve yetkilendirin. Daemon sonucu otomatik olarak yakalar — tamamlanana kadar bu sayfayı açık tutun. Token hiçbir zaman gösterilmez.",waiting:"Tarayıcınızda girişi tamamlamanızı bekliyoruz…",failed:"Giriş başarısız. Lütfen tekrar deneyin."},clearProvider:"Tümünü temizle",clearConfirmTitle:"{{name}} hesapları temizlensin mi?",clearConfirmDesc:"Bu işlem, bu sağlayıcı için depolanan tüm kimlik bilgilerini kaldırır. Bu işlem geri alınamaz.",credential:{ok:"Yapılandırıldı",notConfigured:"Yapılandırılmadı"},kind:{"pass-through":"Geçiş kimlik bilgileri","oauth-bearer":"OAuth bearer","static-bearer":"Statik bearer anahtarı"},reason:{"missing-credential":"Kimlik bilgisi saklanmamış.",expired:"Kimlik bilgisi süresi doldu.","reauth-required":"Yeniden kimlik doğrulama gerekli.","refresh-failed":"Token yenileme başarısız.","not-refreshable":"Kimlik bilgisi yenilenemiyor.",unknown:"Durum bilinmiyor."},status:{unconfigured:"Yapılandırılmadı",authorized:"Yetkilendirildi",configured:"Yapılandırıldı",expired:"Süresi doldu",error:"Hata"},authMethod:{oauth:"OAuth",setup_token:"Kurulum token'ı",manual:"Manuel"},list:{empty:"Bu sağlayıcı için kayıtlı hesap yok.",active:"Aktif",expiresAt:"{{value}} tarihinde sona eriyor",setActive:"Aktif olarak ayarla",remove:"Kaldır",removeConfirmTitle:"Bu hesap kaldırılsın mı?",removeConfirmDesc:'"{{name}}" kaldırıldığında saklanan kimlik bilgisi silinir. Bu işlem geri alınamaz.',title:"Hesaplar"},write:{trigger:"Kimlik bilgisi ekle",title:"{{name}} kimlik bilgisini yaz",description:"Önceden edinilmiş token materyalini yapıştırın. Alanlar bu sağlayıcının kabul ettiğiyle sınırlıdır; token saklanır, geri görüntülenmez.",authMethod:"Kimlik doğrulama yöntemi",status:"Durum",subscriptionLevel:"Abonelik düzeyi",subscriptionLevelNone:"Ayarlanmadı",submit:"Kimlik bilgisini kaydet"},field:{accessToken:"Erişim token'ı",refreshToken:"Yenileme token'ı",idToken:"Kimlik token'ı",apiKey:"API anahtarı",expiresAt:"Sona erme tarihi (ISO)",setupTokenExpiresAt:"Kurulum token'ı sona erme tarihi (ISO)",accountId:"Hesap Kimliği",email:"E-posta",organizationId:"Kuruluş Kimliği",baseUrl:"Temel URL",zenBaseUrl:"Zen temel URL'si"},provider:{claude:{title:"Claude",description:"Daemon tarafından yönlendirilen Anthropic abonelik kimlik bilgileri."},codex:{title:"Codex",description:"Daemon tarafından yönlendirilen OpenAI Codex abonelik kimlik bilgileri."},gemini:{title:"Gemini",description:"Daemon tarafından yönlendirilen Google Gemini abonelik kimlik bilgileri."},opencodego:{title:"OpenCodeGo",description:"Daemon tarafından yönlendirilen statik API anahtarı kimlik bilgileri."}},authMethodLabel:"Yetkilendirme yöntemi",authMethodDesc:{oauth:"Tarayıcınız üzerinden giriş yapın; daemon token'ı yakalar ve saklar.",manual:"Önceden edinilmiş token'ı yapıştırın. Saklanır, hiçbir zaman görüntülenmez."},actions:{authorize:"Yetkilendir",enterToken:"Token gir",refresh:"Yenile"},accounts:{addAccount:"Hesap ekle"},detail:{authMethod:"Yetkilendirme yöntemi",subscriptionLevel:"Abonelik düzeyi",expiresAt:"Sona erme",lastRefreshed:"Son yenileme",label:"Hesap etiketi",labelPlaceholder:"Bu hesabı adlandırın",saveLabel:"Etiketi kaydet"},oauthFlow:{step1:{title:"Yetkilendirme sayfasını açın",desc:"Tarayıcınızda giriş sayfasını açın."},step2:{title:"Erişimi yetkilendirin",desc:"Giriş yapın ve sağlayıcı için erişimi onaylayın."},step3:{title:"Yetkilendirme kodunu kopyalayın",desc:"Onaylamanızın ardından sayfa bir yetkilendirme kodu gösterir."},step4:{title:"Kodu yapıştırın",desc:"Tamamlamak için yetkilendirme kodunu aşağıya yapıştırın. Kod yalnızca daemon'a iletilir — oluşturulan token hiçbir zaman gösterilmez."},authorize:"Girişi tamamla",showUrl:"Yetkilendirme URL'sini göster"},manual:{title:"Kimlik bilgisi yapıştır",description:"Önceden edinilmiş token'ı yapıştırın. Alanlar bu sağlayıcının kabul ettiğiyle sınırlıdır; token saklanır, geri görüntülenmez.",accessTokenPlaceholder:"Erişim token'ını yapıştırın",refreshTokenPlaceholder:"Yenileme token'ını yapıştırın (isteğe bağlı)",hint:"Token, daemon'a gönderilir ve şifreli olarak saklanır. Hiçbir zaman geri görüntülenmez."},openCodeGo:{apiKeyRequired:"API anahtarı zorunludur.",apiKeyPlaceholder:"API anahtarını yapıştırın",baseUrlPlaceholder:"https://… (isteğe bağlı)",zenBaseUrlPlaceholder:"https://… (isteğe bağlı)"},info:{title:"Abonelik hesapları hakkında",description:"Tokenlar daemon'a yazılır ve yukarı akış isteklerini doğrulamak için kullanılır. Şifreli olarak saklanır ve hiçbir zaman geri görüntülenmez. Bir hesabın kaldırılması, saklanan kimlik bilgisini siler."},rename:{failed:"Hesap yeniden adlandırılamadı."},refresh:{failed:"Token yenilenemedi."},errors:{requestFailed:"İstek başarısız. Lütfen tekrar deneyin."},syncWarning:{"external-divergent":"Harici CLI oturum açma dosyası bu hesaptan daha yeni kimlik bilgileri içeriyor. Kayıtlı belirteç yenilenemeyebilir — şimdi yenileyin veya yeniden oturum açın.","external-not-rotated":"Yenileme başarısız oldu ve harici CLI aynı süresi dolmuş kimlik bilgilerini içeriyor. Lütfen yeniden oturum açın.","duplicate-token":"Başka bir hesap bu kimlik bilgilerini paylaşıyor. Birini yenilemek diğerinin oturumunu kapatır."},importExternal:{detected:"Bu makinede mevcut bir {{name}} CLI oturumu bulundu.",hint:"İçe aktardıktan sonra bu uygulama onu güncel tutar: her belirteç yenilemesinde CLI oturum dosyası da güncellenir, böylece terminaldeki CLI oturumu açık kalır.",button:"Mevcut CLI oturumunu içe aktar"}},fT={title:"Code CLI",description:"Bir kodlama CLI'ını daemon'un giden proxy'sine yönlendirin. Bu sayfa salt okunur — burada yapılandırılacak bir şey yok.",copy:"Kopyala",copied:"Kopyalandı",baseUrl:{title:"Daemon temel URL'si",description:"CLI'ınızın bağlandığı proxy adresi.",label:"Temel URL"},token:{title:"Kimlik Doğrulama",hint:"Yönetici rotaları için 'Authorization: Bearer <your-admin-token>' gönderin. Yönetici token'ı daemon'da (yapılandırma dosyası veya ortam) yapılandırılır — burada hiçbir zaman gösterilmez."},examples:{title:"Örnek başlatma ortamı",keyNote:"API Hizmeti sayfasında oluşturulan giden erişim anahtarını kullanın — yönetici token'ını değil.",anthropic:"Anthropic formatlı CLI",openai:"OpenAI formatlı CLI"},launchDescription:"Bu daemon'a yönlendirilmiş bir kodlama CLI'ını terminalde başlatın. Daemon, yönlendirme ortamını enjekte eder ve CLI'ı sizin için başlatır.",refresh:"Yenile",loading:"CLI'lar algılanıyor…",cli:{installed:"Yüklü",notFound:"Bulunamadı",notFoundHint:"Bu CLI, daemon ana makinesinin PATH'inde yok. Yükleyin, ardından yenileyin.",install:"Yükle",installing:"Yükleniyor…",installingHint:"Daemon ana makinesine yükleniyor — bu bir dakika sürebilir.",launch:"Başlat",launchTitle:"{{name}}'i Başlat",launchDescription:"Daemon proxy'si üzerinden yönlendirilen bu CLI'ı çalıştıran daemon ana makinesinde yeni bir terminal açar. İsteğe bağlı çalışma dizini seçin.",cwdLabel:"Çalışma dizini",cwdPlaceholder:"/path/to/your/project",runningVia:"Çalışıyor · {{provider}} / {{model}}",stop:"Durdur"},manual:{title:"Manuel kurulum",description:"CLI'ı kendiniz mi çalıştırmak istiyorsunuz? Bu ortam değişkenleriyle daemon'a yönlendirin.",show:"Göster",hide:"Gizle"}},vT={probing:"Daemon aranıyor…",spawning:"Daemon başlatılıyor…",failed:"Daemon başlatılamadı",failedHint:"Node.js'nin yüklü olduğundan ve daemon'un derlendiğinden (dist mevcut) emin olun ya da OMNICROSS_DAEMON_ENTRY'yi daemon'un cli.js dosyasına ayarlayın."},kT={title:"Ayarlar",description:"Masaüstü uygulaması tercihleri.",desktopOnly:"Başlangıç ve sistem tepsisi seçenekleri yalnızca masaüstü uygulamasında geçerlidir.",startup:{title:"Başlangıç",autoLaunch:"Oturum açıldığında başlat",autoLaunchHint:"Oturum açtığınızda Omnicross'u otomatik olarak başlatın.",startMinimized:"Sistem tepsisine küçültülmüş başlat",startMinimizedHint:"Pencereyi açmadan arka planda başlatın."},tray:{title:"Sistem Tepsisi",minimizeOnClose:"Kapatıldığında sistem tepsisine küçült",minimizeOnCloseHint:"Pencere kapatıldığında çıkmak yerine sistem tepsisine gizlenir."},language:{title:"Dil",label:"Arayüz dili"}},yT={title:"Kullanım istatistikleri",description:"Daemon tarafından sunulan isteklerin token ve maliyet istatistikleri.",rangeToday:"Bugün",range7d:"Son 7 gün",range30d:"Son 30 gün",rangeCustom:"Özel",from:"Başlangıç",to:"Bitiş",totalCost:"Toplam maliyet",cacheSavings:"Önbellek tasarrufu",events:"İstekler",inputTokens:"Girdi tokenları",outputTokens:"Çıktı tokenları",cacheReadTokens:"Önbellek okuma",cacheWriteTokens:"Önbellek yazma",reasoningTokens:"Akıl yürütme tokenları",byModel:"Modele göre",byApiKey:"API anahtarına göre",provider:"Sağlayıcı",model:"Model",cost:"Maliyet",apiKey:"API anahtarı",unpriced:"Fiyatsız",unpricedHint:"Bu model için fiyat kaydı yok — Fiyatlar sayfasından ekleyin.",unattributed:"Atanmamış",unattributedHint:"Belirli bir API anahtarına bağlı olmayan istekler. Anahtar bazlı atama kaydedilene kadar bu beklenen durumdur.",empty:"Bu aralıkta istek yok.",invalidRange:"Geçerli bir tarih aralığı seçin."},bT={title:"Model fiyatları",description:"İstek maliyetlerini hesaplamak için kullanılan model başına token fiyatları, 1 milyon token başına USD.",search:"Sağlayıcı veya model ara…",fetchLatest:"En yenileri getir",fetching:"Getiriliyor…",addEntry:"Kayıt ekle",provider:"Sağlayıcı",model:"Model",inputPrice:"Girdi",outputPrice:"Çıktı",cacheReadPrice:"Önbellek okuma",cacheWritePrice:"Önbellek yazma",source:"Kaynak",updated:"Güncellendi",userEdited:"düzenlendi",edit:"Düzenle",deleteTitle:"Fiyat kaydı silinsin mi?",empty:"Fiyat tablosu boş.",emptyHint:"Doldurmak için en yeni fiyatları getirin.",noMatches:"Aramanızla eşleşen kayıt yok.",saved:"Fiyat kaydı kaydedildi.",saveFailed:"Kaydetme başarısız: {{message}}",deleteFailed:"Silme başarısız: {{message}}",alreadyDeleted:"Kayıt zaten yoktu.",fetchApplied:"Kaynaktan {{count}} kayıt güncellendi.",fetchFailed:"Getirme başarısız: {{message}}",requiredId:"Zorunlu",invalidPrice:"Negatif olmayan bir sayı girin",conflictTitle:"Fiyat çakışmalarını çöz",conflictHint:"Bu kayıtlar sizin tarafınızdan düzenlendi ve kaynakta da değişti. Her satır için kendi değerinizi koruyup korumayacağınızı (Atla) veya geleni alacağınızı (Üzerine yaz) seçin.",current:"Mevcut",incoming:"Gelen",overwrite:"Üzerine yaz",skip:"Atla",overwriteAll:"Tümünün üzerine yaz",skipAll:"Tümünü atla",applyResolutions:"Uygula",resolved:"{{overwritten}} üzerine yazıldı, {{skipped}} atlandı.",resolvedWithStale:"{{overwritten}} üzerine yazıldı, {{skipped}} atlandı. {{stale}} bu sırada değişti ve dokunulmadan bırakıldı.",refreshFailed:"Değişiklik uygulandı ancak liste yeniden yüklenemedi: {{message}}",sourceBuiltin:"Yerleşik",sourceLitellm:"LiteLLM",sourceUser:"Kullanıcı"},PT={providerSettings:sT,apiMode:lT,presetName:dT,common:cT,mediaSettings:uT,appLocal:pT,nav:mT,apiService:gT,accounts:hT,codeCli:fT,daemonStatus:vT,settings:kT,usageStats:yT,pricing:bT},AT={loading:"Завантаження конфігурації LLM...",reset:{button:"Відновити налаштування за замовчуванням",confirmTitle:"Відновити налаштування за замовчуванням?",confirmBody:"Це скине ваші налаштування для цього провайдера, і він знову слідуватиме вбудованим значенням за замовчуванням. Ваш API-ключ та збережені сесії залишаться.",confirmButton:"Відновити налаштування за замовчуванням"},reentryBanner:{message:"{{count}} увімкнений(-их) провайдер(-ів) потребує повторного введення API-ключа. Відкрийте кожен із них і знову додайте ключ."},migrationPack:{barHint:"Перенесіть ключі провайдерів та токени підписок на інший комп'ютер за допомогою зашифрованого пакету.",passphrase:"Парольна фраза",passphrasePlaceholder:"Введіть парольну фразу",passphraseHint:"Використовуйте щонайменше 8 символів; рекомендується 12 і більше.",confirm:"Підтвердити парольну фразу",confirmPlaceholder:"Введіть парольну фразу ще раз",mismatch:"Парольні фрази не збігаються.",strength:{weak:"Занадто коротка — використовуйте щонайменше 8 символів.",fair:"Нормально — 12 і більше символів надійніше.",strong:"Надійна парольна фраза."},export:{button:"Експортувати пакет",title:"Експорт зашифрованого пакету",subtitle:"Зашифруйте ваші ключі провайдерів та токени підписок у переносний файл.",warning:"Цей файл містить розшифровувані секрети. Зберігайте його в безпечному місці — будь-хто, хто має файл і парольну фразу, зможе прочитати ваші ключі. Втрачена парольна фраза не може бути відновлена.",submit:"Експортувати",success:"Пакет успішно експортовано.",error:"Експорт не вдався. Будь ласка, спробуйте знову."},import:{button:"Імпортувати пакет",title:"Імпорт зашифрованого пакету",subtitle:"Відновіть ключі провайдерів та токени підписок з експортованого пакету.",hint:"Введіть парольну фразу, використану при експорті пакету, потім виберіть файл.",submit:"Імпортувати",successTitle:"Імпорт завершено",summary:"Імпортовано {{providerKeys}} ключ(-ів) провайдера, {{poolKeys}} ключ(-ів) пулу та {{tokenSets}} набір(-ів) токенів.",duplicates:"Пропущено {{count}} ключ(-ів) пулу, що вже існують.",skipped:"Пропущено (немає відповідного провайдера): {{names}}",error:"Неправильна парольна фраза або пошкоджений пакет. Нічого не змінено."}},searchPlaceholder:"Пошук провайдерів...",emptySearch:"Жоден провайдер не відповідає запиту.",emptyList:"Провайдери не налаштовані.",selectPrompt:"Виберіть провайдера для перегляду деталей",listStatus:"{{count}} модел(-ей)",noModels:"Моделі не налаштовані",enabled:"Увімкнено",disabled:"Вимкнено",showEnabledOnly:"Показати лише увімкнені",showAll:"Показати всіх провайдерів",dragHandle:"Перетягніть для зміни порядку",reorderFailed:"Не вдалося зберегти порядок провайдерів",credentials:{apiKey:"API-ключ",apiBaseUrl:"Базова URL-адреса API"},filter:{all:"Всі",chat:"Чат",code:"Код"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Виберіть шаблон",skipTemplates:"Пропустити, налаштувати вручну",name:"Назва *",providerType:"Тип",apiType:"Тип API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Стандартний формат API OpenAI chat/completions",claudecode:"Формат API Anthropic Messages (Claude Code)"},chatApiFormat:"Формат API",chatApiFormatDescription:"Виберіть формат API, що відповідає кінцевій точці вашого провайдера",apiKey:"API-ключ",apiKeyPlaceholder:"sk-... або $ENV_VAR",apiKeyHelper:"Використовуйте $VAR_NAME для посилання на змінні середовища",apiKeySetPlaceholder:"Ключ задано — залиште порожнім для збереження поточного",apiKeyReplaceHelper:"Ключ надійно збережено. Введіть нове значення для заміни або залиште поле порожнім.",testApiKey:"Перевірити API-ключ",apiUrl:"URL-адреса API *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Попередній перегляд:",models:"Моделі",modelPlaceholder:"Назва моделі (наприклад, gpt-4, claude-3-opus)",transformers:"Трансформери",transformerConfig:"Трансформери API",transformerConfigDescription:"Налаштуйте трансформери для адаптації форматів запитів/відповідей API для цього провайдера",transformerConfigNote:"Демон застосовує ці трансформери в ланцюжку запитів, після трансформера формату провайдера (який обробляє перетворення формату передачі даних). Невідомі імена трансформерів пропускаються.",enabled:"Увімкнено",apiVersion:"Версія API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Версія API Azure OpenAI (наприклад, 2024-08-01-preview)",official:"Офіційний Anthropic API",officialHelper:"Увімкніть, якщо цей провайдер підключається безпосередньо до офіційного Anthropic API. Вимкніть для зворотних проксі або сторонніх сервісів.",maxConcurrency:"Макс. одночасних запитів",maxConcurrencyHelper:"Максимальна кількість одночасних API-запитів до цього провайдера. Менші значення допомагають уникнути обмежень частоти запитів (помилки 429). Встановіть `-1` для відключення обмеження.",codingPlan:{label:"Тарифний план кодування",description:"Використовувати окрему кінцеву точку API для тарифних планів кодування за підпискою",baseUrl:"Базова URL-адреса плану кодування",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"API-ключ плану кодування (необов'язково)",apiKeyPlaceholder:"Залиште порожнім для використання API-ключа провайдера",apiKeyHelper:"Потрібен лише якщо план кодування використовує окремий API-ключ",tokenPlanHint:"Деякі провайдери (наприклад, Xiaomi MiMo) видають ключі Token Plan з префіксом `tp-` — тільки для інформації, не перевіряється."},selectTypeFirst:"Виберіть тип провайдера",selectTypeFirstDesc:"Виберіть тип провайдера, який хочете додати",codeProviderNote:"Провайдерам коду потрібні лише API-ключ та URL. Моделі керуються маршрутизатором агентів.",buttons:{cancel:"Скасувати",submitAdd:"Додати провайдера",submitUpdate:"Оновити провайдера",continue:"Продовжити",back:"Назад"}},details:{noSelection:"Виберіть провайдера для перегляду деталей",apiKey:"API-ключ",apiUrl:"URL-адреса API",nameLabel:"Назва провайдера",modelsEndpoint:"Кінцева точка моделей",modelsEndpointHelper:"Замініть кінцеву точку виявлення, якщо провайдер використовує нестандартний шлях /models.",models:"Моделі",transformers:"Трансформери",codeProviderNote:"Провайдери коду (наприклад, Claude Code) не потребують налаштування моделей. Моделі автоматично керуються маршрутизатором агентів.",buttons:{more:"Додаткові налаштування",delete:"Видалити"}},providerModelSelector:{placeholder:"Виберіть провайдера та модель",noProviders:"Немає доступних провайдерів",noModels:"Моделі не налаштовані"},apiKeyPool:{title:"Пул API-ключів",description:"Налаштуйте кілька API-ключів для балансування навантаження. Кожна сесія прив'язується до одного ключа для збереження кешу промптів.",defaultLabel:"За замовчуванням",weight:"Вага",noKey:"Без ключа",labelPlaceholder:"Мітка (наприклад, Ключ №1, Основний)",addKey:"Додати API-ключ",add:"Додати",empty:"Додаткові ключі не налаштовані.",statusCoolingDown:"Відновлення {{time}}",statusAuthFailed:"Помилка автентифікації · вимкнено",statusDisabled:"Вимкнено",statusHealthy:"Працює",agoSeconds:"{{count}} с тому",agoMinutes:"{{count}} хв тому",agoHours:"{{count}} год тому",agoDays:"{{count}} д тому"},modelsManager:{searchPlaceholder:"Пошук моделей...",defaultGroup:"Всі моделі",add:"Додати модель",manage:"Управління",empty:"У цій групі немає моделей",enabled:"Увімкнено",disabled:"Вимкнено",filters:{all:"Всі",vision:"Зір",reasoning:"Міркування",free:"Безкоштовні",tools:"Інструменти"},manualDialog:{title:"Додати модель",subtitle:"Додайте власну модель до цього провайдера",modelId:"Ідентифікатор моделі",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash тощо",modelIdHelper:"Точний ідентифікатор моделі, що використовується при виклику API",modelName:"Відображувана назва",modelNamePlaceholder:"Зрозуміла відображувана назва (необов'язково)",modelNameHelper:"Необов'язкова назва, що відображається в інтерфейсі. Якщо порожньо, буде використано ідентифікатор моделі",group:"Група",groupPlaceholder:"Виберіть або введіть назву групи",submit:"Додати",cancel:"Скасувати",helper:"Вкажіть точний ідентифікатор моделі, що надається API провайдера."},editDialog:{title:"Редагувати модель",subtitle:"Змінити налаштування моделі",modelId:"Ідентифікатор моделі",modelIdPlaceholder:"Ідентифікатор моделі",modelIdHelper:"Ідентифікатор моделі, що використовується при виклику API",modelName:"Відображувана назва",modelNamePlaceholder:"Зрозуміла відображувана назва",modelNameHelper:"Назва, що відображається в інтерфейсі",group:"Група",groupPlaceholder:"Виберіть або введіть назву групи",submit:"Зберегти",cancel:"Скасувати",vision:"Підтримка зору",visionHint:"Чи підтримує ця модель введення зображень",reasoning:"Модель з ланцюжком міркувань",reasoningHint:"Чи підтримує ця модель режим міркування"},manageDialog:{title:"Управління моделями",cachedAt:"Кешовано {{date}} ({{source}})",refresh:"Оновити",close:"Закрити",raw:"Необроблений JSON",empty:"Видалені моделі недоступні.",error:"Не вдалося завантажити моделі: {{message}}",addFromCatalog:"Додати",sourceCache:"кеш",sourceNetwork:"мережа",contextLength:"Контекст {{value}} токенів",maxTokens:"Макс. {{value}} токенів"},messages:{added:"Модель додано.",updated:"Модель оновлено.",removed:"Модель видалено.",duplicate:"Модель вже існує.",refreshed:"Моделі оновлено",refreshFailed:"Не вдалося оновити моделі"},testDialog:{title:"Перевірка підключення до моделі",provider:"Провайдер",model:"Модель",testing:"Перевірка...",success:"Перевірка успішна",successMessage:"Модель доступна і працює нормально",failure:"Перевірка не вдалася",aiResponse:"Відповідь ШІ",charCount:"{{count}} симв.",duration:"Тривалість {{time}} с",close:"Закрити",retest:"Повторити перевірку",testButton:"Перевірити модель",unsupportedFormat:"Перевірка для цього формату провайдера поки не підтримується."}},router:{title:"Конфігурація маршрутизатора",description:"Налаштуйте, який провайдер/модель використовувати для різних сценаріїв.",labels:{default:"За замовчуванням",background:"фоновий",think:"міркування",longContext:"Довгий контекст",webSearch:"Веб-пошук",image:"Зображення",longContextThreshold:"Поріг довгого контексту"},helper:{longContextThreshold:"Кількість токенів для перемикання на модель із довгим контекстом."},placeholder:{required:"Обов'язково",optional:"Необов'язково"}},agentRouter:{title:"Маршрутизатор агентів",description:"Налаштуйте двонаправлену маршрутизацію між режимами чату та коду.",searchPlaceholder:"Пошук маршрутизаторів...",noSearchResults:"Жоден маршрутизатор не відповідає запиту.",tabs:{chatToCode:"Чат → Код",codeToChatPlaceholder:"Код → Чат"},chatToCode:{title:"Маршрутизатор Чат → Код",description:"Використовувати провайдерів чату в режимі агента/кодування",addRouter:"Додати маршрутизатор",emptyState:"Маршрутизатори Чат→Код не налаштовані. Додайте один, щоб використовувати провайдерів чату в режимі кодування.",form:{name:"Назва маршрутизатора",namePlaceholder:"Мій маршрутизатор Чат→Код",chatProvider:"Провайдер чату",chatProviderPlaceholder:"Виберіть провайдера чату",mode:"Режим",modeSimple:"Простий",modeAdvanced:"Розширений",modeSimpleDesc:"Пряме проксіювання до провайдера чату",modeAdvancedDesc:"Налаштувати зіставлення моделей та обробку контексту",enabled:"Увімкнено",save:"Зберегти маршрутизатор",cancel:"Скасувати"},list:{provider:"Провайдер",mode:"Режим",status:"Статус"},mappings:{title:"Зіставлення моделей",description:"Зіставте моделі провайдера чату з моделями провайдера коду",count:"зіставлень(-ня)",empty:"Зіставлення моделей не налаштовані. Додайте зіставлення для маршрутизації моделей чату до провайдерів коду.",addNew:"Додати нове зіставлення",selectSource:"Виберіть вихідну модель (Чат)",selectTarget:"Виберіть цільову модель (Код)",targetPlaceholder:"Введіть назву моделі Claude Code",notSet:"(Не задано — натисніть для вибору)",add:"Додати",edit:"Редагувати",done:"Готово"},advanced:{title:"Розширена конфігурація",description:"Налаштуйте моделі для різних типів завдань",helpText:"Модель за замовчуванням є обов'язковою. Інші моделі необов'язкові — за відсутності налаштування буде використана модель за замовчуванням.",default:{label:"За замовчуванням",placeholder:"Виберіть модель за замовчуванням",description:"Основна модель для загальних завдань (аналог Claude Sonnet)"},background:{label:"Фонова",placeholder:"Виберіть фонову модель",description:"Легка модель для фонових завдань (аналог Claude Haiku)"},think:{label:"Міркування",placeholder:"Виберіть модель міркування",description:"Просунута модель для складних міркувань (аналог Claude Opus)"},image:{label:"Зображення",placeholder:"Виберіть модель для зображень",description:"Модель для завдань із зображеннями з підтримкою зору"}}},codeToChat:{title:"Маршрутизатор Код → Чат",description:"Відображати моделі тарифного плану кодування в режимі чату",addRouter:"Додати маршрутизатор",emptyState:"Маршрутизатори Код→Чат не налаштовані. Додайте один, щоб відображати моделі тарифного плану кодування в режимі чату.",form:{name:"Назва маршрутизатора",namePlaceholder:"Мій маршрутизатор Код→Чат",codeProvider:"Провайдер коду",codeProviderPlaceholder:"Виберіть провайдера коду",codeProviderHelper:"Виберіть провайдера коду для перетворення",models:"Моделі тарифного плану кодування",modelsHelper:"Виберіть моделі тарифного плану кодування для відображення",enabled:"Увімкнено",save:"Зберегти маршрутизатор",cancel:"Скасувати"},mappings:{title:"Зіставлення моделей",description:"Зіставте моделі провайдера коду з моделями провайдера чату для відображення",count:"зіставлень(-ня)",empty:"Зіставлення моделей не налаштовані. Додайте зіставлення для відображення моделей коду в режимі чату.",addNew:"Додати нове зіставлення",selectSource:"Виберіть вихідну модель (Код)",selectTarget:"Виберіть цільову модель (Чат)",sourcePlaceholder:"Введіть назву вихідної моделі",targetPlaceholder:"Введіть назву цільової моделі",add:"Додати",edit:"Редагувати",done:"Готово"}},transformers:{title:"Трансформери",description:"Налаштуйте трансформери для перетворення запитів/відповідей",noProvider:"Виберіть провайдера для налаштування трансформерів",empty:"Трансформери відсутні",count:"{{count}} трансформер(-ів)"},status:{enabled:"Увімкнено",disabled:"Вимкнено"},messages:{routerAdded:"Маршрутизатор успішно додано",routerUpdated:"Маршрутизатор успішно оновлено",routerDeleted:"Маршрутизатор успішно видалено",saveFailed:"Не вдалося зберегти маршрутизатор"}},presets:{title:"Швидке додавання провайдера",added:"Додано",add:"Додати",features:{search:"Пошук",vision:"Зір",mcp:"MCP",codingPlan:"План кодування"}},alerts:{deleteConfirm:"Ви впевнені, що хочете видалити цього провайдера?"},errors:{nameRequired:"Назва провайдера є обов'язковою",urlRequired:"Базова URL-адреса API є обов'язковою",urlInvalid:"Введіть коректну URL-адресу (наприклад, https://api.example.com)",saveFailed:"Не вдалося зберегти провайдера",deleteFailed:"Помилка при видаленні провайдера. Будь ласка, спробуйте знову.",toggleFailed:"Помилка при зміні стану провайдера. Будь ласка, спробуйте знову."},openRouter:{title:"Маршрутизація провайдерів OpenRouter",description:"Налаштуйте маршрутизацію запитів до різних провайдерів через OpenRouter.",sort:"Стратегія маршрутизації",sortTooltip:"Виберіть пріоритет провайдерів. Авто використовує інтелектуальне балансування навантаження.",order:"Порядок пріоритету провайдерів",orderTooltip:"Вкажіть провайдерів для послідовного перебору (наприклад, anthropic, openai, together). Натисніть Enter для додавання.",orderPlaceholder:"Введіть ідентифікатор провайдера та натисніть Enter...",allowFallbacks:"Дозволити запасні варіанти",allowFallbacksTooltip:"При увімкненні OpenRouter спробує резервних провайдерів, якщо основний недоступний.",requireParameters:"Вимагати всі параметри",requireParametersTooltip:"Маршрутизувати лише до провайдерів, що підтримують усі параметри запиту.",dataCollection:"Політика збору даних",dataCollectionTooltip:"Управління використанням провайдерів, які можуть зберігати або використовувати ваші дані для навчання.",zdr:"Нульове зберігання даних",zdrTooltip:"Маршрутизувати лише до кінцевих точок з політикою нульового зберігання даних.",only:"Лише дозволені провайдери",onlyTooltip:"Використовувати лише вказаних провайдерів. Залиште порожнім для використання всіх провайдерів.",onlyPlaceholder:"Введіть ідентифікатор провайдера та натисніть Enter...",ignore:"Ігнорувати провайдерів",ignoreTooltip:"Пропускати цих провайдерів при маршрутизації запитів.",ignorePlaceholder:"Введіть ідентифікатор провайдера та натисніть Enter...",quantizations:"Фільтр квантизації",quantizationsTooltip:"Використовувати лише провайдерів із вказаними рівнями квантизації. Нижча точність може знизити якість, але підвищити швидкість.",maxPrice:"Максимальна ціна",maxPriceTooltip:"Встановіть максимальні цінові ліміти за мільйон токенів. Залиште порожнім для відключення обмеження.",configured:"Налаштовано"}},CT={label:"Режим API",standard:"Стандартний",codingPlan:"План кодування",tokenPlan:"Токенний план",apiKeyPrefixHint:"Ключі для цього плану зазвичай починаються з `{{prefix}}`. Лише підказка — не перевіряється.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan використовує окремий API-ключ від стандартної кінцевої точки.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan використовує окремий API-ключ від стандартної кінцевої точки.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan працює лише за протоколом Anthropic.",xiaomiTokenPlanRegions:"Базова URL-адреса за замовчуванням — `token-plan-cn.*`. Можна вручну змінити на `token-plan-sgp.*` або `token-plan-ams.*`.",confirmOverwriteTitle:"Змінити режим API?",confirmOverwriteBody:"Ви налаштували власну URL-адресу API або API-ключ. Зміна режиму перезапише їх значеннями за замовчуванням нового режиму — або збережіть ваші налаштування і оновіть лише мітку режиму.",overwriteAndSwitch:"Перезаписати та переключити",keepCustomizations:"Зберегти налаштування"},xT={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},zT={cancel:"Скасувати",close:"Закрити",copy:"Копіювати",delete:"Видалити",dismiss:"Закрити",save:"Зберегти",optional:"необов'язково",retry:"Повторити",loading:"Завантаження…"},IT={common:{learnMore:"Документація"}},ST={notSupportedByDaemon:"Поки не підтримується демоном",discoveryUnsupportedFormat:"Виявлення моделей не підтримується для цього формату провайдера. Додайте моделі вручну."},wT={subtitle:"Панель керування",providers:"Провайдери",apiService:"API-сервіс",accounts:"Облікові записи",codeCli:"Code CLI",settings:"Налаштування",usageStats:"Використання",pricing:"Ціни"},TT={title:"API-сервіс",description:"Налаштуйте вихідний API-сервер, маршрутизацію моделей за кінцевими точками та іменовані ключі доступу.",loading:"Завантаження конфігурації сервера…",loadError:"Не вдалося завантажити конфігурацію сервера. Переконайтеся, що демон доступний.",enable:{label:"Увімкнути вихідний сервер",description:"Запустити локальний API-сервер, що маршрутизує зовнішні запити через ваших провайдерів."},networkBinding:{label:"Дозволити доступ з локальної мережі",description:"Прив'язати сервер до мережевого інтерфейсу замість лише loopback.",warning:"Доступ з локальної мережі відкриває API-сервер для інших пристроїв у вашій мережі. У поєднанні з маршрутизацією підписок запити можуть витрачати квоту підписки — залишайте вимкненим, якщо не довіряєте мережі."},status:{running:"Сервер працює",stopped:"Сервер зупинено",runningHint:"Вихідний API-сервер приймає запити.",stoppedHint:"Увімкніть сервер для початку прийому запитів.",port:"порт {{port}}",loopback:"URL-адреси loopback",lan:"URL-адреси локальної мережі"},endpoints:{title:"Маршрутизація кінцевих точок",description:"Виберіть модель для кожного формату передачі даних. Модель за замовчуванням враховується тут — сервер є маршрутизатором, а не чат-застосунком."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Модель за замовчуванням",backgroundModel:"Фонова модель",visionModel:"Модель зору",noVisionModel:"Немає",backgroundModelIds:"Ідентифікатори фонових моделей",backgroundModelIdsPlaceholder:"ідентифікатори моделей через кому",modelPlaceholder:"Виберіть модель…",useSubscription:"Використовувати підписку",subscriptionUnsupported:"Маршрутизація за підпискою недоступна для цієї кінцевої точки."},keys:{title:"Ключі доступу",description:"Іменовані ключі, які зовнішні клієнти передають як Bearer-токен. Повний ключ відображається лише один раз при створенні.",namePlaceholder:"Назва ключа (наприклад, my-cli)",create:"Створити ключ",empty:"Ключів доступу поки немає.",enabled:"Активний",disabled:"Вимкнено",revoked:"Відкликано",toggle:"Увімкнути/вимкнути ключ",revoke:"Відкликати",revokeConfirmTitle:"Відкликати цей ключ?",revokeConfirmDesc:"Відкликання ключа «{{name}}» негайно припинить його використання для автентифікації. Цю дію не можна скасувати.",created:{title:"Ключ створено",warning:"Скопіюйте ключ зараз — він більше не відображатиметься. Зберігайте його в надійному місці.",copy:"Копіювати",copied:"Скопійовано",dismiss:"Готово"}}},jT={title:"Облікові записи та підписки",description:"Керуйте обліковими даними підписок, через які маршрутизує сервер. Токени записуються тут, але ніколи не відображаються назад.",loading:"Завантаження облікових записів…",empty:"Немає доступних провайдерів підписок.",signIn:"Увійти",oauth:{title:"Увійти до {{name}}",description:"Відкрийте сторінку входу в браузері, авторизуйтесь, потім вставте код авторизації нижче. Код передається лише демону — створений токен ніколи не відображається.",openPage:"Відкрити сторінку входу",codeLabel:"Код авторизації",codePlaceholder:"Вставте код сюди",submit:"Завершити вхід"},codexOauth:{title:"Увійти до {{name}}",description:"Відкрийте сторінку входу в браузері та авторизуйтесь. Демон автоматично отримає результат — не закривайте цю сторінку до завершення. Токен ніколи не відображається.",waiting:"Очікування завершення входу в браузері…",failed:"Вхід не виконано. Будь ласка, спробуйте знову."},clearProvider:"Очистити все",clearConfirmTitle:"Очистити облікові записи {{name}}?",clearConfirmDesc:"Це видалить усі збережені облікові дані для цього провайдера. Цю дію не можна скасувати.",credential:{ok:"Налаштовано",notConfigured:"Не налаштовано"},kind:{"pass-through":"Наскрізні облікові дані","oauth-bearer":"OAuth Bearer","static-bearer":"Статичний Bearer-ключ"},reason:{"missing-credential":"Облікові дані не збережено.",expired:"Термін дії облікових даних закінчився.","reauth-required":"Потрібна повторна автентифікація.","refresh-failed":"Оновлення токена не вдалося.","not-refreshable":"Облікові дані не оновлювані.",unknown:"Статус невідомий."},status:{unconfigured:"Не налаштовано",authorized:"Авторизовано",configured:"Налаштовано",expired:"Закінчився",error:"Помилка"},authMethod:{oauth:"OAuth",setup_token:"Токен налаштування",manual:"Вручну"},list:{empty:"Для цього провайдера немає збережених облікових записів.",active:"Активний",expiresAt:"Закінчується {{value}}",setActive:"Зробити активним",remove:"Видалити",removeConfirmTitle:"Видалити цей обліковий запис?",removeConfirmDesc:"Видалення «{{name}}» стере збережені облікові дані. Цю дію не можна скасувати.",title:"Облікові записи"},write:{trigger:"Додати облікові дані",title:"Записати облікові дані {{name}}",description:"Вставте вже отримані дані токена. Поля обмежені тим, що приймає цей провайдер; токен зберігається і ніколи не відображається назад.",authMethod:"Метод автентифікації",status:"Статус",subscriptionLevel:"Рівень підписки",subscriptionLevelNone:"Не задано",submit:"Зберегти облікові дані"},field:{accessToken:"Токен доступу",refreshToken:"Токен оновлення",idToken:"ID-токен",apiKey:"API-ключ",expiresAt:"Закінчується (ISO)",setupTokenExpiresAt:"Токен налаштування закінчується (ISO)",accountId:"Ідентифікатор облікового запису",email:"Електронна пошта",organizationId:"Ідентифікатор організації",baseUrl:"Базова URL-адреса",zenBaseUrl:"Zen базова URL-адреса"},provider:{claude:{title:"Claude",description:"Облікові дані підписки Anthropic, маршрутизовані демоном."},codex:{title:"Codex",description:"Облікові дані підписки OpenAI Codex, маршрутизовані демоном."},gemini:{title:"Gemini",description:"Облікові дані підписки Google Gemini, маршрутизовані демоном."},opencodego:{title:"OpenCodeGo",description:"Статичні облікові дані API-ключа, маршрутизовані демоном."}},authMethodLabel:"Метод авторизації",authMethodDesc:{oauth:"Увійдіть через браузер; демон захопить і збереже токен.",manual:"Вставте вже отриманий токен. Він зберігається і ніколи не відображається назад."},actions:{authorize:"Авторизувати",enterToken:"Ввести токен",refresh:"Оновити"},accounts:{addAccount:"Додати обліковий запис"},detail:{authMethod:"Метод авторизації",subscriptionLevel:"Рівень підписки",expiresAt:"Закінчується",lastRefreshed:"Останнє оновлення",label:"Мітка облікового запису",labelPlaceholder:"Назвіть цей обліковий запис",saveLabel:"Зберегти мітку"},oauthFlow:{step1:{title:"Відкрийте сторінку авторизації",desc:"Відкрийте сторінку входу в браузері."},step2:{title:"Авторизуйте доступ",desc:"Увійдіть та дозвольте доступ для провайдера."},step3:{title:"Скопіюйте код авторизації",desc:"Сторінка відобразить код авторизації після підтвердження."},step4:{title:"Вставте код",desc:"Вставте код авторизації нижче для завершення. Код передається лише демону — створений токен ніколи не відображається."},authorize:"Завершити вхід",showUrl:"Показати URL-адресу авторизації"},manual:{title:"Вставити облікові дані",description:"Вставте вже отриманий токен. Поля обмежені тим, що приймає цей провайдер; токен зберігається і ніколи не відображається назад.",accessTokenPlaceholder:"Вставте токен доступу",refreshTokenPlaceholder:"Вставте токен оновлення (необов'язково)",hint:"Токен надсилається демону і зберігається в зашифрованому вигляді. Він ніколи не відображається назад."},openCodeGo:{apiKeyRequired:"Потрібен API-ключ.",apiKeyPlaceholder:"Вставте API-ключ",baseUrlPlaceholder:"https://… (необов'язково)",zenBaseUrlPlaceholder:"https://… (необов'язково)"},info:{title:"Про облікові записи підписок",description:"Токени записуються до демона і використовуються для автентифікації запитів. Вони зберігаються в зашифрованому вигляді і ніколи не відображаються назад. Видалення облікового запису видаляє збережені облікові дані."},rename:{failed:"Не вдалося перейменувати обліковий запис."},refresh:{failed:"Не вдалося оновити токен."},errors:{requestFailed:"Запит не виконано. Будь ласка, спробуйте знову."},syncWarning:{"external-divergent":"Файл входу зовнішнього CLI містить новіші облікові дані, ніж цей акаунт. Збережений токен може перестати оновлюватися — оновіть зараз або увійдіть знову.","external-not-rotated":"Оновлення не вдалося, і зовнішній CLI містить ті самі прострочені облікові дані. Увійдіть знову.","duplicate-token":"Інший акаунт використовує ті самі облікові дані. Оновлення одного з них призведе до виходу іншого."},importExternal:{detected:"На цьому комп’ютері знайдено наявний вхід CLI {{name}}.",hint:"Після імпорту цей застосунок підтримує його актуальність: під час кожного оновлення токена файл входу CLI також оновлюється, і CLI в терміналі залишається авторизованим.",button:"Імпортувати наявний вхід CLI"}},MT={title:"Code CLI",description:"Спрямуйте CLI для кодування на вихідний проксі демона. Ця сторінка лише для читання — тут нічого налаштовувати.",copy:"Копіювати",copied:"Скопійовано",baseUrl:{title:"Базова URL-адреса демона",description:"Адреса проксі, до якої підключається ваш CLI.",label:"Базова URL-адреса"},token:{title:"Автентифікація",hint:"Надсилайте 'Authorization: Bearer <ваш-admin-токен>' для адміністративних маршрутів. Адміністративний токен налаштовується в демоні (у файлі конфігурації або змінних середовища) — він ніколи не відображається тут."},examples:{title:"Приклад змінних середовища для запуску",keyNote:"Використовуйте ключ вихідного доступу, створений на сторінці API-сервісу, — не адміністративний токен.",anthropic:"CLI у форматі Anthropic",openai:"CLI у форматі OpenAI"},launchDescription:"Запустіть CLI для кодування в терміналі, спрямованому на цей демон. Демон вводить змінні середовища перенаправлення і запускає CLI за вас.",refresh:"Оновити",loading:"Виявлення CLI…",cli:{installed:"Встановлено",notFound:"Не знайдено",notFoundHint:"Цей CLI не виявлено в PATH хоста демона. Встановіть його, потім оновіть.",install:"Встановити",installing:"Встановлення…",installingHint:"Встановлення на хості демона — це може зайняти хвилину.",launch:"Запустити",launchTitle:"Запустити {{name}}",launchDescription:"Відкриває новий термінал на хості демона з цим CLI, маршрутизованим через проксі демона. Виберіть необов'язковий робочий каталог.",cwdLabel:"Робочий каталог",cwdPlaceholder:"/path/to/your/project",runningVia:"Виконується · {{provider}} / {{model}}",stop:"Зупинити"},manual:{title:"Ручне налаштування",description:"Надаєте перевагу самостійному запуску CLI? Спрямуйте його на демон за допомогою цих змінних середовища.",show:"Показати",hide:"Сховати"}},NT={probing:"Перевірка наявності демона…",spawning:"Запуск демона…",failed:"Не вдалося запустити демон",failedHint:"Переконайтеся, що Node.js встановлено і демон зібрано (наявність dist), або задайте OMNICROSS_DAEMON_ENTRY для вказівки на cli.js демона."},LT={title:"Налаштування",description:"Налаштування десктопного застосунку.",desktopOnly:"Параметри автозапуску та системного трею застосовуються лише в десктопному застосунку.",startup:{title:"Автозапуск",autoLaunch:"Запускати при вході в систему",autoLaunchHint:"Автоматично запускати Omnicross при вході в систему.",startMinimized:"Запускати згорнутим у системний трей",startMinimizedHint:"Запускати у фоновому режимі без відкриття вікна."},tray:{title:"Системний трей",minimizeOnClose:"Згортати в трей при закритті",minimizeOnCloseHint:"При закритті вікно ховається в системний трей замість виходу з програми."},language:{title:"Мова",label:"Мова інтерфейсу"}},RT={title:"Статистика використання",description:"Статистика токенів і витрат за запитами, обслугованими демоном.",rangeToday:"Сьогодні",range7d:"Останні 7 днів",range30d:"Останні 30 днів",rangeCustom:"Власний",from:"З",to:"По",totalCost:"Загальна вартість",cacheSavings:"Економія кешу",events:"Запити",inputTokens:"Вхідні токени",outputTokens:"Вихідні токени",cacheReadTokens:"Читання кешу",cacheWriteTokens:"Запис кешу",reasoningTokens:"Токени міркувань",byModel:"За моделями",byApiKey:"За API-ключами",provider:"Провайдер",model:"Модель",cost:"Вартість",apiKey:"API-ключ",unpriced:"Без ціни",unpricedHint:"Для цієї моделі немає запису ціни — додайте його на сторінці «Ціни».",unattributed:"Без привʼязки",unattributedHint:"Запити, не повʼязані з конкретним API-ключем. Це нормально, доки привʼязка за ключами не записується.",empty:"Немає запитів за цей період.",invalidRange:"Виберіть коректний діапазон дат."},DT={title:"Ціни моделей",description:"Ціни токенів за моделями для розрахунку вартості запитів, у доларах США за 1 млн токенів.",search:"Пошук провайдера або моделі…",fetchLatest:"Отримати останні",fetching:"Отримання…",addEntry:"Додати запис",provider:"Провайдер",model:"Модель",inputPrice:"Вхід",outputPrice:"Вихід",cacheReadPrice:"Читання кешу",cacheWritePrice:"Запис кешу",source:"Джерело",updated:"Оновлено",userEdited:"змінено",edit:"Редагувати",deleteTitle:"Видалити запис ціни?",empty:"Таблиця цін порожня.",emptyHint:"Отримайте останні ціни, щоб її заповнити.",noMatches:"Немає записів, що відповідають пошуку.",saved:"Запис ціни збережено.",saveFailed:"Не вдалося зберегти: {{message}}",deleteFailed:"Не вдалося видалити: {{message}}",alreadyDeleted:"Запису вже не було.",fetchApplied:"Оновлено записів із джерела: {{count}}.",fetchFailed:"Не вдалося отримати: {{message}}",requiredId:"Обовʼязково",invalidPrice:"Введіть невідʼємне число",conflictTitle:"Розвʼязати конфлікти цін",conflictHint:"Ці записи редагували ви, і вони також змінилися в джерелі. Для кожного рядка виберіть: зберегти своє значення (Пропустити) чи прийняти нове (Перезаписати).",current:"Поточне",incoming:"Вхідне",overwrite:"Перезаписати",skip:"Пропустити",overwriteAll:"Перезаписати все",skipAll:"Пропустити все",applyResolutions:"Застосувати",resolved:"Перезаписано: {{overwritten}}, пропущено: {{skipped}}.",resolvedWithStale:"Перезаписано: {{overwritten}}, пропущено: {{skipped}}. {{stale}} змінилися тим часом і залишилися недоторканими.",refreshFailed:"Зміну застосовано, але не вдалося перезавантажити список: {{message}}",sourceBuiltin:"Вбудований",sourceLitellm:"LiteLLM",sourceUser:"Користувач"},ET={providerSettings:AT,apiMode:CT,presetName:xT,common:zT,mediaSettings:IT,appLocal:ST,nav:wT,apiService:TT,accounts:jT,codeCli:MT,daemonStatus:NT,settings:LT,usageStats:RT,pricing:DT},OT={loading:"Đang tải cấu hình LLM...",reset:{button:"Khôi phục mặc định",confirmTitle:"Khôi phục cài đặt mặc định?",confirmBody:"Thao tác này sẽ xóa các tùy chỉnh của bạn cho nhà cung cấp này và quay về mặc định tích hợp sẵn. API key và phiên đã lưu vẫn được giữ nguyên.",confirmButton:"Khôi phục mặc định"},reentryBanner:{message:"{{count}} nhà cung cấp đang bật cần nhập lại API key. Hãy mở từng nhà cung cấp và thêm key vào."},migrationPack:{barHint:"Chuyển provider key và subscription token của bạn sang máy khác bằng gói mã hóa.",passphrase:"Cụm mật khẩu",passphrasePlaceholder:"Nhập cụm mật khẩu",passphraseHint:"Dùng ít nhất 8 ký tự; khuyến nghị 12 ký tự trở lên.",confirm:"Xác nhận cụm mật khẩu",confirmPlaceholder:"Nhập lại cụm mật khẩu",mismatch:"Cụm mật khẩu không khớp.",strength:{weak:"Quá ngắn — dùng ít nhất 8 ký tự.",fair:"Ổn — 12 ký tự trở lên sẽ mạnh hơn.",strong:"Cụm mật khẩu mạnh."},export:{button:"Xuất gói",title:"Xuất gói mã hóa",subtitle:"Mã hóa provider key và subscription token của bạn thành một tệp di động.",warning:"Tệp này chứa dữ liệu bí mật có thể giải mã. Hãy bảo quản cẩn thận — bất kỳ ai có tệp và cụm mật khẩu đều có thể đọc key của bạn. Cụm mật khẩu bị mất không thể khôi phục.",submit:"Xuất",success:"Xuất gói thành công.",error:"Xuất thất bại. Vui lòng thử lại."},import:{button:"Nhập gói",title:"Nhập gói mã hóa",subtitle:"Khôi phục provider key và subscription token từ gói đã xuất.",hint:"Nhập cụm mật khẩu đã dùng khi xuất gói, rồi chọn tệp.",submit:"Nhập",successTitle:"Nhập hoàn tất",summary:"Đã nhập {{providerKeys}} provider key, {{poolKeys}} pool key và {{tokenSets}} token set.",duplicates:"Bỏ qua {{count}} pool key đã tồn tại.",skipped:"Bỏ qua (không tìm thấy nhà cung cấp phù hợp): {{names}}",error:"Sai cụm mật khẩu hoặc gói bị hỏng. Không có gì thay đổi."}},searchPlaceholder:"Tìm kiếm nhà cung cấp...",emptySearch:"Không tìm thấy nhà cung cấp nào phù hợp.",emptyList:"Chưa có nhà cung cấp nào được cấu hình.",selectPrompt:"Chọn nhà cung cấp để xem chi tiết",listStatus:"{{count}} mô hình",noModels:"Chưa có mô hình nào được cấu hình",enabled:"Đã bật",disabled:"Đã tắt",showEnabledOnly:"Chỉ hiển thị đang bật",showAll:"Hiển thị tất cả nhà cung cấp",dragHandle:"Kéo để sắp xếp lại",reorderFailed:"Không thể lưu thứ tự nhà cung cấp",credentials:{apiKey:"API Key",apiBaseUrl:"API Base URL"},filter:{all:"Tất cả",chat:"Chat",code:"Code"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"Chọn mẫu",skipTemplates:"Bỏ qua, tự cấu hình",name:"Tên *",providerType:"Loại",apiType:"Loại API",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"Định dạng API OpenAI chat/completions chuẩn",claudecode:"Định dạng Anthropic Messages API (Claude Code)"},chatApiFormat:"Định dạng API",chatApiFormatDescription:"Chọn định dạng API phù hợp với endpoint của nhà cung cấp",apiKey:"API Key",apiKeyPlaceholder:"sk-... hoặc $ENV_VAR",apiKeyHelper:"Dùng $VAR_NAME để tham chiếu biến môi trường",apiKeySetPlaceholder:"Đã đặt key — để trống để giữ nguyên",apiKeyReplaceHelper:"Đã có key được lưu an toàn. Nhập giá trị mới để thay thế, hoặc để trống để giữ nguyên.",testApiKey:"Kiểm tra API Key",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"Xem trước:",models:"Mô hình",modelPlaceholder:"Tên mô hình (VD: gpt-4, claude-3-opus)",transformers:"Transformers",transformerConfig:"API Transformers",transformerConfigDescription:"Cấu hình transformer để điều chỉnh định dạng API request/response cho nhà cung cấp này",transformerConfigNote:"Daemon áp dụng các transformer này trong chuỗi request, sau format transformer của nhà cung cấp (xử lý chuyển đổi wire-format). Tên transformer không nhận dạng được sẽ bị bỏ qua.",enabled:"Đã bật",apiVersion:"Phiên bản API",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Phiên bản Azure OpenAI API (VD: 2024-08-01-preview)",official:"Anthropic API chính thức",officialHelper:"Bật nếu nhà cung cấp này kết nối trực tiếp với Anthropic API chính thức. Tắt cho reverse proxy hoặc dịch vụ bên thứ ba.",maxConcurrency:"Số yêu cầu đồng thời tối đa",maxConcurrencyHelper:"Số lượng API request tối đa gửi đồng thời đến nhà cung cấp này. Giá trị thấp hơn giúp tránh rate limiting (lỗi 429). Đặt `-1` để không giới hạn.",codingPlan:{label:"Coding Plan",description:"Dùng endpoint API riêng cho coding plan theo subscription",baseUrl:"Coding Plan Base URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API Key (tùy chọn)",apiKeyPlaceholder:"Để trống để dùng API key của nhà cung cấp",apiKeyHelper:"Chỉ cần khi coding plan dùng API key khác",tokenPlanHint:"Một số nhà cung cấp (VD: Xiaomi MiMo) cấp Token Plan key với tiền tố `tp-` — chỉ để tham khảo, không bắt buộc."},selectTypeFirst:"Chọn loại nhà cung cấp",selectTypeFirstDesc:"Chọn loại nhà cung cấp bạn muốn thêm",codeProviderNote:"Code provider chỉ cần API Key và URL. Mô hình được quản lý bởi Agent Router.",buttons:{cancel:"Hủy",submitAdd:"Thêm nhà cung cấp",submitUpdate:"Cập nhật nhà cung cấp",continue:"Tiếp tục",back:"Quay lại"}},details:{noSelection:"Chọn nhà cung cấp để xem chi tiết",apiKey:"API Key",apiUrl:"API URL",nameLabel:"Tên nhà cung cấp",modelsEndpoint:"Models Endpoint",modelsEndpointHelper:"Ghi đè endpoint khám phá nếu nhà cung cấp cung cấp path /models tùy chỉnh.",models:"Mô hình",transformers:"Transformers",codeProviderNote:"Code provider (như Claude Code) không cần cấu hình mô hình. Mô hình được quản lý tự động bởi Agent Router.",buttons:{more:"Cài đặt thêm",delete:"Xóa"}},providerModelSelector:{placeholder:"Chọn nhà cung cấp và mô hình",noProviders:"Không có nhà cung cấp",noModels:"Chưa có mô hình nào được cấu hình"},apiKeyPool:{title:"API Key Pool",description:"Cấu hình nhiều API key để load balancing. Mỗi phiên gắn với một key để duy trì prompt cache.",defaultLabel:"Mặc định",weight:"Trọng số",noKey:"Không có key",labelPlaceholder:"Nhãn (VD: Key #1, Production)",addKey:"Thêm API Key",add:"Thêm",empty:"Chưa có key bổ sung nào được cấu hình.",statusCoolingDown:"Đang nghỉ {{time}}",statusAuthFailed:"Xác thực thất bại · đã tắt",statusDisabled:"Đã tắt",statusHealthy:"Hoạt động tốt",agoSeconds:"{{count}} giây trước",agoMinutes:"{{count}} phút trước",agoHours:"{{count}} giờ trước",agoDays:"{{count}} ngày trước"},modelsManager:{searchPlaceholder:"Tìm kiếm mô hình...",defaultGroup:"Tất cả mô hình",add:"Thêm mô hình",manage:"Quản lý",empty:"Không có mô hình nào trong nhóm này",enabled:"Đã bật",disabled:"Đã tắt",filters:{all:"Tất cả",vision:"Vision",reasoning:"Reasoning",free:"Miễn phí",tools:"Tools"},manualDialog:{title:"Thêm mô hình",subtitle:"Thêm mô hình tùy chỉnh cho nhà cung cấp này",modelId:"Model ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash, v.v.",modelIdHelper:"Mã định danh mô hình chính xác dùng khi gọi API",modelName:"Tên hiển thị",modelNamePlaceholder:"Tên hiển thị thân thiện (tùy chọn)",modelNameHelper:"Tên tùy chọn hiển thị trong giao diện. Nếu để trống sẽ dùng Model ID",group:"Nhóm",groupPlaceholder:"Chọn hoặc nhập tên nhóm",submit:"Thêm",cancel:"Hủy",helper:"Cung cấp mã định danh mô hình chính xác mà API nhà cung cấp cung cấp."},editDialog:{title:"Chỉnh sửa mô hình",subtitle:"Sửa đổi cài đặt mô hình",modelId:"Model ID",modelIdPlaceholder:"Mã định danh mô hình",modelIdHelper:"Mã định danh mô hình dùng khi gọi API",modelName:"Tên hiển thị",modelNamePlaceholder:"Tên hiển thị thân thiện",modelNameHelper:"Tên hiển thị trong giao diện",group:"Nhóm",groupPlaceholder:"Chọn hoặc nhập tên nhóm",submit:"Lưu",cancel:"Hủy",vision:"Khả năng Vision",visionHint:"Mô hình này có hỗ trợ đầu vào hình ảnh/vision không",reasoning:"Mô hình Thinking",reasoningHint:"Mô hình này có hỗ trợ chế độ thinking/reasoning không"},manageDialog:{title:"Quản lý mô hình",cachedAt:"Đã cache lúc {{date}} ({{source}})",refresh:"Làm mới",close:"Đóng",raw:"Raw JSON",empty:"Không có mô hình từ xa.",error:"Tải mô hình thất bại: {{message}}",addFromCatalog:"Thêm",sourceCache:"cache",sourceNetwork:"trực tiếp",contextLength:"Context {{value}} token",maxTokens:"Tối đa {{value}} token"},messages:{added:"Đã thêm mô hình.",updated:"Đã cập nhật mô hình.",removed:"Đã xóa mô hình.",duplicate:"Mô hình đã tồn tại.",refreshed:"Đã làm mới mô hình",refreshFailed:"Làm mới mô hình thất bại"},testDialog:{title:"Kiểm tra kết nối mô hình",provider:"Nhà cung cấp",model:"Mô hình",testing:"Đang kiểm tra...",success:"Kiểm tra thành công",successMessage:"Mô hình có thể truy cập bình thường",failure:"Kiểm tra thất bại",aiResponse:"Phản hồi AI",charCount:"{{count}} ký tự",duration:"Thời gian {{time}} giây",close:"Đóng",retest:"Kiểm tra lại",testButton:"Kiểm tra mô hình",unsupportedFormat:"Chưa hỗ trợ kiểm tra cho định dạng nhà cung cấp này."}},router:{title:"Cấu hình Router",description:"Cấu hình nhà cung cấp/mô hình dùng cho từng tình huống.",labels:{default:"Mặc định",background:"Nền",think:"Suy nghĩ",longContext:"Context dài",webSearch:"Tìm kiếm web",image:"Hình ảnh",longContextThreshold:"Ngưỡng context dài"},helper:{longContextThreshold:"Số lượng token trước khi chuyển sang mô hình long-context."},placeholder:{required:"Bắt buộc",optional:"Tùy chọn"}},agentRouter:{title:"Agent Router",description:"Cấu hình định tuyến hai chiều giữa chế độ Chat và Code.",searchPlaceholder:"Tìm kiếm router...",noSearchResults:"Không tìm thấy router nào phù hợp.",tabs:{chatToCode:"Chat → Code",codeToChatPlaceholder:"Code → Chat"},chatToCode:{title:"Chat to Code Router",description:"Dùng chat provider trong chế độ agent/coding",addRouter:"Thêm Router",emptyState:"Chưa có Chat→Code router. Thêm một router để dùng chat provider trong chế độ coding.",form:{name:"Tên Router",namePlaceholder:"My Chat→Code Router",chatProvider:"Chat Provider",chatProviderPlaceholder:"Chọn chat provider",mode:"Chế độ",modeSimple:"Đơn giản",modeAdvanced:"Nâng cao",modeSimpleDesc:"Chuyển thẳng đến chat provider",modeAdvancedDesc:"Cấu hình ánh xạ mô hình và xử lý context",enabled:"Đã bật",save:"Lưu Router",cancel:"Hủy"},list:{provider:"Nhà cung cấp",mode:"Chế độ",status:"Trạng thái"},mappings:{title:"Ánh xạ mô hình",description:"Ánh xạ mô hình Chat provider sang mô hình Code provider",count:"ánh xạ",empty:"Chưa có ánh xạ mô hình. Thêm ánh xạ để định tuyến chat model đến code provider.",addNew:"Thêm ánh xạ mới",selectSource:"Chọn mô hình nguồn (Chat)",selectTarget:"Chọn mô hình đích (Code)",targetPlaceholder:"Nhập tên mô hình Claude Code",notSet:"(Chưa đặt — nhấp để chọn)",add:"Thêm",edit:"Sửa",done:"Xong"},advanced:{title:"Cấu hình nâng cao",description:"Cấu hình mô hình cho từng loại tác vụ",helpText:"Mô hình mặc định là bắt buộc. Các mô hình khác là tùy chọn và sẽ dùng mặc định nếu không được cấu hình.",default:{label:"Mặc định",placeholder:"Chọn mô hình mặc định",description:"Mô hình chính cho tác vụ thông thường (tương tự Claude Sonnet)"},background:{label:"Nền",placeholder:"Chọn mô hình nền",description:"Mô hình nhẹ cho tác vụ nền (tương tự Claude Haiku)"},think:{label:"Suy nghĩ",placeholder:"Chọn mô hình think",description:"Mô hình nâng cao cho lập luận phức tạp (tương tự Claude Opus)"},image:{label:"Hình ảnh",placeholder:"Chọn mô hình hình ảnh",description:"Mô hình cho tác vụ liên quan đến hình ảnh với khả năng vision"}}},codeToChat:{title:"Code to Chat Router",description:"Hiển thị mô hình Coding Plan trong chế độ chat",addRouter:"Thêm Router",emptyState:"Chưa có Code→Chat router. Thêm một router để hiển thị mô hình Coding Plan trong chế độ chat.",form:{name:"Tên Router",namePlaceholder:"My Code→Chat Router",codeProvider:"Code Provider",codeProviderPlaceholder:"Chọn code provider",codeProviderHelper:"Chọn Code provider dùng để chuyển đổi",models:"Mô hình Coding Plan",modelsHelper:"Chọn mô hình Coding Plan muốn hiển thị",enabled:"Đã bật",save:"Lưu Router",cancel:"Hủy"},mappings:{title:"Ánh xạ mô hình",description:"Ánh xạ mô hình Code provider sang mô hình Chat provider để hiển thị",count:"ánh xạ",empty:"Chưa có ánh xạ mô hình. Thêm ánh xạ để hiển thị mô hình Code trong chế độ chat.",addNew:"Thêm ánh xạ mới",selectSource:"Chọn mô hình nguồn (Code)",selectTarget:"Chọn mô hình đích (Chat)",sourcePlaceholder:"Nhập tên mô hình nguồn",targetPlaceholder:"Nhập tên mô hình đích",add:"Thêm",edit:"Sửa",done:"Xong"}},transformers:{title:"Transformers",description:"Cấu hình transformer để chuyển đổi request/response",noProvider:"Chọn nhà cung cấp để cấu hình transformer",empty:"Không có transformer",count:"{{count}} transformer"},status:{enabled:"Đã bật",disabled:"Đã tắt"},messages:{routerAdded:"Đã thêm router thành công",routerUpdated:"Đã cập nhật router thành công",routerDeleted:"Đã xóa router thành công",saveFailed:"Lưu router thất bại"}},presets:{title:"Thêm nhà cung cấp nhanh",added:"Đã thêm",add:"Thêm",features:{search:"Tìm kiếm",vision:"Vision",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"Bạn có chắc muốn xóa nhà cung cấp này không?"},errors:{nameRequired:"Tên nhà cung cấp là bắt buộc",urlRequired:"API Base URL là bắt buộc",urlInvalid:"Vui lòng nhập URL hợp lệ (VD: https://api.example.com)",saveFailed:"Lưu nhà cung cấp thất bại",deleteFailed:"Lỗi khi xóa nhà cung cấp. Vui lòng thử lại.",toggleFailed:"Lỗi khi thay đổi trạng thái nhà cung cấp. Vui lòng thử lại."},openRouter:{title:"Định tuyến OpenRouter Provider",description:"Cấu hình cách định tuyến request đến các nhà cung cấp khác nhau trên OpenRouter.",sort:"Chiến lược định tuyến",sortTooltip:"Chọn cách ưu tiên nhà cung cấp. Auto dùng load balancing thông minh.",order:"Thứ tự ưu tiên nhà cung cấp",orderTooltip:"Chỉ định nhà cung cấp cần thử theo thứ tự (VD: anthropic, openai, together). Nhấn Enter để thêm.",orderPlaceholder:"Nhập slug nhà cung cấp và nhấn Enter...",allowFallbacks:"Cho phép Fallback",allowFallbacksTooltip:"Khi bật, OpenRouter sẽ thử nhà cung cấp dự phòng nếu nhà cung cấp chính không khả dụng.",requireParameters:"Yêu cầu tất cả tham số",requireParametersTooltip:"Chỉ định tuyến đến nhà cung cấp hỗ trợ tất cả tham số trong request của bạn.",dataCollection:"Chính sách thu thập dữ liệu",dataCollectionTooltip:"Kiểm soát việc dùng nhà cung cấp có thể lưu hoặc huấn luyện trên dữ liệu của bạn.",zdr:"Zero Data Retention",zdrTooltip:"Chỉ định tuyến đến endpoint có chính sách Zero Data Retention.",only:"Chỉ cho phép nhà cung cấp",onlyTooltip:"Chỉ dùng các nhà cung cấp cụ thể này. Để trống để cho phép tất cả.",onlyPlaceholder:"Nhập slug nhà cung cấp và nhấn Enter...",ignore:"Bỏ qua nhà cung cấp",ignoreTooltip:"Bỏ qua các nhà cung cấp này khi định tuyến request.",ignorePlaceholder:"Nhập slug nhà cung cấp và nhấn Enter...",quantizations:"Bộ lọc Quantization",quantizationsTooltip:"Chỉ dùng nhà cung cấp có mức quantization cụ thể. Độ chính xác thấp hơn có thể giảm chất lượng nhưng tăng tốc độ.",maxPrice:"Giá tối đa",maxPriceTooltip:"Đặt giới hạn giá tối đa trên mỗi triệu token. Để trống để không giới hạn.",configured:"Đã cấu hình"}},KT={label:"Chế độ API",standard:"Chuẩn",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"Key cho gói này thường bắt đầu bằng `{{prefix}}`. Chỉ để gợi ý — không bắt buộc.",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan dùng API key riêng biệt với endpoint chuẩn.",baiduCodingPlanSeparateKey:"Qianfan Coding Plan dùng API key riêng biệt với endpoint chuẩn.",tencentTokenPlanAnthropicOnly:"Tencent Token Plan chỉ hỗ trợ giao thức Anthropic.",xiaomiTokenPlanRegions:"baseUrl mặc định là `token-plan-cn.*`. Bạn có thể chỉnh thủ công thành `token-plan-sgp.*` hoặc `token-plan-ams.*`.",confirmOverwriteTitle:"Chuyển chế độ API?",confirmOverwriteBody:"Bạn đã tùy chỉnh API URL hoặc API Key. Chuyển chế độ sẽ ghi đè bằng giá trị mặc định của chế độ mới — hoặc giữ nguyên tùy chỉnh và chỉ cập nhật nhãn chế độ.",overwriteAndSwitch:"Ghi đè và chuyển",keepCustomizations:"Giữ nguyên tùy chỉnh"},UT={zhipu:"z.ai",zhipuBigmodel:"Zhipu GLM",volcengine:"Volcengine Ark",dashscope:"Alibaba DashScope",tencent:"Tencent Hunyuan",tencentAnthropic:"Tencent Hunyuan (Token Plan)",baidu:"Baidu Qianfan",kuaishou:"Kuaishou KwaiKAT",mthreads:"Moore Threads",xiaomiMimoOpenai:"Xiaomi MiMo (OpenAI)",xiaomiMimoAnthropic:"Xiaomi MiMo (Anthropic)"},HT={cancel:"Hủy",close:"Đóng",copy:"Sao chép",delete:"Xóa",dismiss:"Bỏ qua",save:"Lưu",optional:"tùy chọn",retry:"Thử lại",loading:"Đang tải…"},FT={common:{learnMore:"Tài liệu"}},BT={notSupportedByDaemon:"Daemon chưa hỗ trợ tính năng này",discoveryUnsupportedFormat:"Chưa hỗ trợ khám phá mô hình cho định dạng nhà cung cấp này. Hãy thêm mô hình thủ công."},VT={subtitle:"Bảng điều khiển",providers:"Nhà cung cấp",apiService:"Dịch vụ API",accounts:"Tài khoản",codeCli:"Code CLI",settings:"Cài đặt",usageStats:"Sử dụng",pricing:"Bảng giá"},qT={title:"Dịch vụ API",description:"Cấu hình máy chủ API đầu ra, định tuyến mô hình theo endpoint và access key được đặt tên.",loading:"Đang tải cấu hình máy chủ…",loadError:"Không thể tải cấu hình máy chủ. Kiểm tra xem daemon có thể truy cập không.",enable:{label:"Bật máy chủ đầu ra",description:"Khởi động API server nội bộ định tuyến người gọi bên ngoài qua các nhà cung cấp của bạn."},networkBinding:{label:"Cho phép truy cập LAN",description:"Gắn máy chủ vào giao diện mạng thay vì chỉ loopback.",warning:"Truy cập LAN sẽ để lộ API server cho các thiết bị khác trên mạng của bạn. Khi kết hợp với định tuyến subscription, các request có thể tiêu thụ hạn ngạch subscription — hãy tắt trừ khi bạn tin tưởng mạng."},status:{running:"Máy chủ đang chạy",stopped:"Máy chủ đã dừng",runningHint:"API server đầu ra đang chấp nhận request.",stoppedHint:"Bật máy chủ để bắt đầu chấp nhận request.",port:"cổng {{port}}",loopback:"URL Loopback",lan:"URL LAN"},endpoints:{title:"Định tuyến Endpoint",description:"Chọn mô hình mà mỗi wire format định tuyến đến. Mô hình mặc định được tích hợp ở đây — máy chủ là router, không phải ứng dụng chat."},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"Mô hình mặc định",backgroundModel:"Mô hình nền",visionModel:"Mô hình Vision",noVisionModel:"Không có",backgroundModelIds:"ID mô hình nền",backgroundModelIdsPlaceholder:"ID mô hình cách nhau bằng dấu phẩy",modelPlaceholder:"Chọn mô hình…",useSubscription:"Dùng subscription",subscriptionUnsupported:"Định tuyến subscription không khả dụng cho endpoint này."},keys:{title:"Access key",description:"Key được đặt tên để người gọi bên ngoài gửi dưới dạng Bearer token. Key đầy đủ chỉ hiển thị một lần khi tạo.",namePlaceholder:"Tên key (VD: my-cli)",create:"Tạo key",empty:"Chưa có access key nào.",enabled:"Đã bật",disabled:"Đã tắt",revoked:"Đã thu hồi",toggle:"Bật/tắt key",revoke:"Thu hồi",revokeConfirmTitle:"Thu hồi key này?",revokeConfirmDesc:'Thu hồi "{{name}}" sẽ ngay lập tức ngừng xác thực. Không thể hoàn tác.',created:{title:"Đã tạo key",warning:"Sao chép key này ngay — sẽ không hiển thị lại. Hãy lưu trữ an toàn.",copy:"Sao chép",copied:"Đã sao chép",dismiss:"Xong"}}},$T={title:"Tài khoản & Subscription",description:"Quản lý thông tin xác thực subscription mà máy chủ định tuyến qua. Token được ghi ở đây nhưng không bao giờ hiển thị lại.",loading:"Đang tải tài khoản…",empty:"Không có subscription provider nào khả dụng.",signIn:"Đăng nhập",oauth:{title:"Đăng nhập vào {{name}}",description:"Mở trang đăng nhập trong trình duyệt, ủy quyền, rồi dán authorization code bên dưới. Code chỉ được gửi đến daemon — token được tạo ra sẽ không hiển thị.",openPage:"Mở trang đăng nhập",codeLabel:"Authorization code",codePlaceholder:"Dán code vào đây",submit:"Hoàn tất đăng nhập"},codexOauth:{title:"Đăng nhập vào {{name}}",description:"Mở trang đăng nhập trong trình duyệt và ủy quyền. Daemon sẽ tự động nhận kết quả — giữ trang này mở cho đến khi hoàn tất. Token sẽ không được hiển thị.",waiting:"Đang chờ bạn hoàn tất đăng nhập trên trình duyệt…",failed:"Đăng nhập thất bại. Vui lòng thử lại."},clearProvider:"Xóa tất cả",clearConfirmTitle:"Xóa tài khoản {{name}}?",clearConfirmDesc:"Thao tác này xóa mọi thông tin xác thực đã lưu cho nhà cung cấp này. Không thể hoàn tác.",credential:{ok:"Đã cấu hình",notConfigured:"Chưa cấu hình"},kind:{"pass-through":"Pass-through credentials","oauth-bearer":"OAuth bearer","static-bearer":"Static bearer key"},reason:{"missing-credential":"Không có thông tin xác thực đã lưu.",expired:"Thông tin xác thực đã hết hạn.","reauth-required":"Cần xác thực lại.","refresh-failed":"Làm mới token thất bại.","not-refreshable":"Thông tin xác thực không thể làm mới.",unknown:"Trạng thái không xác định."},status:{unconfigured:"Chưa cấu hình",authorized:"Đã ủy quyền",configured:"Đã cấu hình",expired:"Đã hết hạn",error:"Lỗi"},authMethod:{oauth:"OAuth",setup_token:"Setup token",manual:"Thủ công"},list:{empty:"Không có tài khoản nào được lưu cho nhà cung cấp này.",active:"Đang hoạt động",expiresAt:"Hết hạn {{value}}",setActive:"Đặt làm hoạt động",remove:"Xóa",removeConfirmTitle:"Xóa tài khoản này?",removeConfirmDesc:'Xóa "{{name}}" sẽ xóa thông tin xác thực đã lưu. Không thể hoàn tác.',title:"Tài khoản"},write:{trigger:"Thêm thông tin xác thực",title:"Ghi thông tin xác thực {{name}}",description:"Dán token material đã có sẵn. Các trường bị giới hạn ở những gì nhà cung cấp chấp nhận; token được lưu trữ, không hiển thị lại.",authMethod:"Phương thức xác thực",status:"Trạng thái",subscriptionLevel:"Cấp subscription",subscriptionLevelNone:"Chưa đặt",submit:"Lưu thông tin xác thực"},field:{accessToken:"Access token",refreshToken:"Refresh token",idToken:"ID token",apiKey:"API key",expiresAt:"Hết hạn lúc (ISO)",setupTokenExpiresAt:"Setup token hết hạn lúc (ISO)",accountId:"Account ID",email:"Email",organizationId:"Organization ID",baseUrl:"Base URL",zenBaseUrl:"Zen base URL"},provider:{claude:{title:"Claude",description:"Thông tin xác thực subscription Anthropic được định tuyến qua daemon."},codex:{title:"Codex",description:"Thông tin xác thực subscription OpenAI Codex được định tuyến qua daemon."},gemini:{title:"Gemini",description:"Thông tin xác thực subscription Google Gemini được định tuyến qua daemon."},opencodego:{title:"OpenCodeGo",description:"Thông tin xác thực API-key tĩnh được định tuyến qua daemon."}},authMethodLabel:"Phương thức ủy quyền",authMethodDesc:{oauth:"Đăng nhập qua trình duyệt; daemon nhận và lưu trữ token.",manual:"Dán token đã có sẵn. Token được lưu trữ, không hiển thị lại."},actions:{authorize:"Ủy quyền",enterToken:"Nhập token",refresh:"Làm mới"},accounts:{addAccount:"Thêm tài khoản"},detail:{authMethod:"Phương thức ủy quyền",subscriptionLevel:"Cấp subscription",expiresAt:"Hết hạn",lastRefreshed:"Làm mới lần cuối",label:"Nhãn tài khoản",labelPlaceholder:"Đặt tên tài khoản này",saveLabel:"Lưu nhãn"},oauthFlow:{step1:{title:"Mở trang ủy quyền",desc:"Mở trang đăng nhập trong trình duyệt của bạn."},step2:{title:"Ủy quyền truy cập",desc:"Đăng nhập và phê duyệt quyền truy cập cho nhà cung cấp."},step3:{title:"Sao chép authorization code",desc:"Trang sẽ hiển thị authorization code sau khi bạn phê duyệt."},step4:{title:"Dán code",desc:"Dán authorization code bên dưới để hoàn tất. Code chỉ được gửi đến daemon — token được tạo ra sẽ không hiển thị."},authorize:"Hoàn tất đăng nhập",showUrl:"Hiển thị URL ủy quyền"},manual:{title:"Dán thông tin xác thực",description:"Dán token đã có sẵn. Các trường bị giới hạn ở những gì nhà cung cấp chấp nhận; token được lưu trữ, không hiển thị lại.",accessTokenPlaceholder:"Dán access token",refreshTokenPlaceholder:"Dán refresh token (tùy chọn)",hint:"Token được gửi đến daemon và lưu trữ mã hóa. Sẽ không hiển thị lại."},openCodeGo:{apiKeyRequired:"API key là bắt buộc.",apiKeyPlaceholder:"Dán API key",baseUrlPlaceholder:"https://… (tùy chọn)",zenBaseUrlPlaceholder:"https://… (tùy chọn)"},info:{title:"Về tài khoản subscription",description:"Token được ghi vào daemon và dùng để xác thực các request upstream. Chúng được lưu trữ mã hóa và không hiển thị lại. Xóa tài khoản sẽ xóa thông tin xác thực đã lưu."},rename:{failed:"Không thể đổi tên tài khoản."},refresh:{failed:"Không thể làm mới token."},errors:{requestFailed:"Yêu cầu thất bại. Vui lòng thử lại."},syncWarning:{"external-divergent":"Tệp đăng nhập của CLI bên ngoài chứa thông tin xác thực mới hơn tài khoản này. Token đã lưu có thể không làm mới được nữa — hãy làm mới ngay hoặc đăng nhập lại.","external-not-rotated":"Làm mới thất bại và CLI bên ngoài chứa cùng thông tin xác thực đã hết hạn. Vui lòng đăng nhập lại.","duplicate-token":"Một tài khoản khác đang dùng chung thông tin xác thực này. Làm mới một trong hai sẽ khiến tài khoản còn lại bị đăng xuất."},importExternal:{detected:"Đã tìm thấy phiên đăng nhập CLI {{name}} hiện có trên máy này.",hint:"Sau khi nhập, ứng dụng này sẽ giữ cho nó luôn mới: mỗi lần làm mới token, tệp đăng nhập của CLI cũng được cập nhật, nên CLI trong terminal vẫn đăng nhập.",button:"Nhập phiên đăng nhập CLI hiện có"}},_T={title:"Code CLI",description:"Kết nối coding CLI với outbound proxy của daemon. Trang này chỉ đọc — không có gì để cấu hình ở đây.",copy:"Sao chép",copied:"Đã sao chép",baseUrl:{title:"Daemon base URL",description:"Địa chỉ proxy mà CLI của bạn kết nối đến.",label:"Base URL"},token:{title:"Xác thực",hint:"Gửi 'Authorization: Bearer <your-admin-token>' cho các route admin. Admin token được cấu hình trong daemon (tệp config hoặc môi trường) — không hiển thị ở đây."},examples:{title:"Ví dụ môi trường khởi chạy",keyNote:"Dùng outbound access key được tạo trên trang API Service — không phải admin token.",anthropic:"CLI định dạng Anthropic",openai:"CLI định dạng OpenAI"},launchDescription:"Khởi chạy coding CLI trong terminal, trỏ đến daemon này. Daemon sẽ tự động thêm biến môi trường redirect và khởi động CLI cho bạn.",refresh:"Làm mới",loading:"Đang phát hiện CLI…",cli:{installed:"Đã cài đặt",notFound:"Không tìm thấy",notFoundHint:"CLI này không có trong PATH của daemon host. Hãy cài đặt rồi làm mới.",install:"Cài đặt",installing:"Đang cài đặt…",installingHint:"Đang cài đặt trên daemon host — có thể mất vài phút.",launch:"Khởi chạy",launchTitle:"Khởi chạy {{name}}",launchDescription:"Mở terminal mới trên daemon host chạy CLI này, định tuyến qua daemon proxy. Chọn thư mục làm việc tùy chọn.",cwdLabel:"Thư mục làm việc",cwdPlaceholder:"/path/to/your/project",runningVia:"Đang chạy · {{provider}} / {{model}}",stop:"Dừng"},manual:{title:"Cài đặt thủ công",description:"Muốn tự chạy CLI? Trỏ đến daemon với các biến môi trường này.",show:"Hiện",hide:"Ẩn"}},GT={probing:"Đang kiểm tra daemon…",spawning:"Đang khởi động daemon…",failed:"Không thể khởi động daemon",failedHint:"Đảm bảo Node.js đã được cài đặt và daemon đã được build (có thư mục dist), hoặc đặt OMNICROSS_DAEMON_ENTRY trỏ đến cli.js của daemon."},WT={title:"Cài đặt",description:"Tùy chọn ứng dụng desktop.",desktopOnly:"Tùy chọn Startup và Tray chỉ áp dụng trong ứng dụng desktop.",startup:{title:"Khởi động",autoLaunch:"Khởi chạy khi đăng nhập",autoLaunchHint:"Tự động khởi động Omnicross khi bạn đăng nhập.",startMinimized:"Khởi động thu nhỏ vào khay",startMinimizedHint:"Chạy ngầm mà không mở cửa sổ."},tray:{title:"Khay hệ thống",minimizeOnClose:"Thu nhỏ vào khay khi đóng",minimizeOnCloseHint:"Đóng cửa sổ sẽ ẩn vào khay thay vì thoát chương trình."},language:{title:"Ngôn ngữ",label:"Ngôn ngữ giao diện"}},ZT={title:"Thống kê sử dụng",description:"Thống kê token và chi phí của các yêu cầu do daemon phục vụ.",rangeToday:"Hôm nay",range7d:"7 ngày qua",range30d:"30 ngày qua",rangeCustom:"Tùy chỉnh",from:"Từ",to:"Đến",totalCost:"Tổng chi phí",cacheSavings:"Tiết kiệm nhờ bộ nhớ đệm",events:"Yêu cầu",inputTokens:"Token đầu vào",outputTokens:"Token đầu ra",cacheReadTokens:"Đọc bộ nhớ đệm",cacheWriteTokens:"Ghi bộ nhớ đệm",reasoningTokens:"Token suy luận",byModel:"Theo mô hình",byApiKey:"Theo khóa API",provider:"Nhà cung cấp",model:"Mô hình",cost:"Chi phí",apiKey:"Khóa API",unpriced:"Chưa có giá",unpricedHint:"Chưa có mục giá cho mô hình này — hãy thêm ở trang Bảng giá.",unattributed:"Chưa gán",unattributedHint:"Các yêu cầu không gắn với khóa API cụ thể. Điều này là bình thường cho đến khi việc gán theo khóa được ghi nhận.",empty:"Không có yêu cầu nào trong khoảng này.",invalidRange:"Chọn khoảng ngày hợp lệ."},QT={title:"Giá mô hình",description:"Giá token theo mô hình dùng để tính chi phí yêu cầu, tính bằng USD trên 1 triệu token.",search:"Tìm nhà cung cấp hoặc mô hình…",fetchLatest:"Lấy mới nhất",fetching:"Đang lấy…",addEntry:"Thêm mục",provider:"Nhà cung cấp",model:"Mô hình",inputPrice:"Đầu vào",outputPrice:"Đầu ra",cacheReadPrice:"Đọc bộ nhớ đệm",cacheWritePrice:"Ghi bộ nhớ đệm",source:"Nguồn",updated:"Cập nhật",userEdited:"đã sửa",edit:"Sửa",deleteTitle:"Xóa mục giá này?",empty:"Bảng giá đang trống.",emptyHint:"Lấy giá mới nhất để điền bảng.",noMatches:"Không có mục nào khớp với tìm kiếm.",saved:"Đã lưu mục giá.",saveFailed:"Lưu thất bại: {{message}}",deleteFailed:"Xóa thất bại: {{message}}",alreadyDeleted:"Mục này đã không còn.",fetchApplied:"Đã cập nhật {{count}} mục từ nguồn.",fetchFailed:"Lấy thất bại: {{message}}",requiredId:"Bắt buộc",invalidPrice:"Nhập số không âm",conflictTitle:"Giải quyết xung đột giá",conflictHint:"Các mục này do bạn chỉnh sửa và cũng thay đổi ở nguồn. Chọn theo từng hàng: giữ giá trị của bạn (Bỏ qua) hoặc lấy giá trị mới (Ghi đè).",current:"Hiện tại",incoming:"Mới đến",overwrite:"Ghi đè",skip:"Bỏ qua",overwriteAll:"Ghi đè tất cả",skipAll:"Bỏ qua tất cả",applyResolutions:"Áp dụng",resolved:"Đã ghi đè {{overwritten}}, bỏ qua {{skipped}}.",resolvedWithStale:"Đã ghi đè {{overwritten}}, bỏ qua {{skipped}}. {{stale}} đã thay đổi trong lúc đó và được giữ nguyên.",refreshFailed:"Đã áp dụng thay đổi, nhưng tải lại danh sách thất bại: {{message}}",sourceBuiltin:"Tích hợp sẵn",sourceLitellm:"LiteLLM",sourceUser:"Người dùng"},YT={providerSettings:OT,apiMode:KT,presetName:UT,common:HT,mediaSettings:FT,appLocal:BT,nav:VT,apiService:qT,accounts:$T,codeCli:_T,daemonStatus:GT,settings:WT,usageStats:ZT,pricing:QT},XT={loading:"正在加载 LLM 配置...",reset:{button:"恢复默认",confirmTitle:"恢复默认设置?",confirmBody:"这将清除你对该提供商的自定义修改,使其重新跟随内置默认值。你的 API 密钥和已保存的会话不会受影响。",confirmButton:"恢复默认"},reentryBanner:{message:"有 {{count}} 个已启用的提供商需要重新填写 API 密钥。请逐个打开并重新填入密钥。"},migrationPack:{barHint:"用加密迁移包将提供商密钥和订阅令牌迁移到另一台设备。",passphrase:"口令",passphrasePlaceholder:"请输入口令",passphraseHint:"至少 8 个字符,建议 12 个或以上。",confirm:"确认口令",confirmPlaceholder:"再次输入口令",mismatch:"两次输入的口令不一致。",strength:{weak:"太短——请至少使用 8 个字符。",fair:"可以——12 个或以上字符更安全。",strong:"口令强度高。"},export:{button:"导出迁移包",title:"导出加密迁移包",subtitle:"将提供商密钥和订阅令牌加密为一个可携带的文件。",warning:"此文件包含可解密的机密,请妥善保管——任何人只要同时拥有此文件和口令,就能读取你的密钥。口令一旦丢失将无法恢复。",submit:"导出",success:"迁移包已成功导出。",error:"导出失败,请重试。"},import:{button:"导入迁移包",title:"导入加密迁移包",subtitle:"从导出的迁移包中恢复提供商密钥和订阅令牌。",hint:"请输入导出迁移包时使用的口令,然后选择文件。",submit:"导入",successTitle:"导入完成",summary:"已导入 {{providerKeys}} 个提供商密钥、{{poolKeys}} 个密钥池条目和 {{tokenSets}} 组令牌。",duplicates:"已跳过 {{count}} 个已存在的密钥池条目。",skipped:"已跳过(无匹配的提供商):{{names}}",error:"口令错误或迁移包已损坏,未做任何更改。"}},searchPlaceholder:"搜索提供商...",emptySearch:"没有符合搜索条件的提供商。",emptyList:"尚未配置提供商。",selectPrompt:"选择一个提供商以查看详情",listStatus:"共 {{count}} 个模型",noModels:"未配置模型",enabled:"已启用",disabled:"已禁用",showEnabledOnly:"仅显示已启用",showAll:"显示全部",dragHandle:"拖拽调整顺序",reorderFailed:"保存排序失败",credentials:{apiKey:"API Key",apiBaseUrl:"API 地址"},filter:{all:"全部",chat:"对话",code:"代码"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"选择模板",skipTemplates:"跳过,手动配置",name:"名称 *",providerType:"类型",apiType:"API 类型",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"遵循 OpenAI Chat/Completions API 格式",claudecode:"Anthropic Messages API 格式(Claude Code)"},chatApiFormat:"API 格式",chatApiFormatDescription:"选择与您提供商端点匹配的 API 格式",apiKey:"API Key",apiKeyPlaceholder:"sk-... 或 $ENV_VAR",apiKeyHelper:"可使用 $VAR_NAME 引用环境变量",apiKeySetPlaceholder:"密钥已设置 — 留空则保持不变",apiKeyReplaceHelper:"密钥已安全存储。输入新值可替换,留空则保持不变。",testApiKey:"测试 API Key",apiUrl:"API 地址 *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"预览:",models:"模型列表",modelPlaceholder:"模型名称(如 gpt-4、claude-3-opus)",transformers:"Transformers",transformerConfig:"API 转换器",transformerConfigDescription:"配置转换器以适配此提供商的 API 请求/响应格式",transformerConfigNote:"守护进程会在请求链中应用这些转换器,位于提供商格式转换器(负责线路格式转换)之后。未知的转换器名称会被跳过。",enabled:"已启用",apiVersion:"API 版本",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI 的 API 版本号(如 2024-08-01-preview)",official:"Anthropic 官方 API",officialHelper:"如果该提供商直接连接 Anthropic 官方 API,请启用。反向代理或第三方服务请禁用。",maxConcurrency:"最大并发请求数",maxConcurrencyHelper:"向该提供商发送的最大并发 API 请求数。较低的值有助于避免速率限制(429 错误)。填 `-1` 表示不限制。",codingPlan:{label:"Coding Plan",description:"使用订阅制 Coding Plan 的独立 API 地址",baseUrl:"Coding Plan 接口地址",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API 密钥(可选)",apiKeyPlaceholder:"留空则使用提供商的 API 密钥",apiKeyHelper:"仅当 Coding Plan 使用不同的 API 密钥时才需要",tokenPlanHint:"部分提供商(如小米 MiMo)的 Token Plan 密钥以 `tp-` 开头 —— 仅为提示,不会强制校验。"},selectTypeFirst:"选择提供商类型",selectTypeFirstDesc:"选择您要添加的提供商类型",codeProviderNote:"Code 提供商只需要 API Key 和 URL。模型由 Agent Router 管理。",buttons:{cancel:"取消",submitAdd:"添加提供商",submitUpdate:"更新提供商",continue:"继续",back:"返回"}},details:{noSelection:"选择一个提供商查看详情",apiKey:"API Key",apiUrl:"API 地址",nameLabel:"提供商名称",modelsEndpoint:"模型列表接口",modelsEndpointHelper:"若服务端提供自定义 /models 路径,可在这里覆盖。",models:"模型",transformers:"Transformers",codeProviderNote:"代码类型提供商(如 Claude Code)无需配置模型。模型由 Agent 路由自动管理。",buttons:{more:"更多设置",delete:"删除"}},providerModelSelector:{placeholder:"选择提供商和模型",noProviders:"暂无可用提供商",noModels:"暂无已配置模型"},apiKeyPool:{title:"API Key 池",description:"配置多个 API Key 实现负载均衡。每个会话绑定一个 Key 以保留 Prompt Cache。",defaultLabel:"默认",weight:"权重",noKey:"无密钥",labelPlaceholder:"标签(如 Key #1、生产环境)",addKey:"添加 API Key",add:"添加",empty:"未配置额外的 Key。",statusCoolingDown:"限流冷却 {{time}}",statusAuthFailed:"鉴权失败 · 已禁用",statusDisabled:"已禁用",statusHealthy:"正常",agoSeconds:"{{count}} 秒前",agoMinutes:"{{count}} 分钟前",agoHours:"{{count}} 小时前",agoDays:"{{count}} 天前"},modelsManager:{searchPlaceholder:"搜索模型...",defaultGroup:"全部模型",add:"添加模型",manage:"管理",empty:"该分组暂无模型",enabled:"已启用",disabled:"已禁用",filters:{all:"全部",vision:"视觉",reasoning:"推理",free:"免费",tools:"工具"},manualDialog:{title:"添加模型",subtitle:"为此提供商添加自定义模型",modelId:"模型 ID",modelIdPlaceholder:"gpt-4o, claude-3.5, gemini-2.0-flash 等",modelIdHelper:"调用 API 时使用的精确模型标识符",modelName:"展示名称",modelNamePlaceholder:"友好的展示名称(可选)",modelNameHelper:"在界面中显示的名称,留空则使用模型 ID",group:"分组",groupPlaceholder:"选择或输入分组名称",submit:"添加",cancel:"取消",helper:"请填写提供商 API 返回的模型标识。"},editDialog:{title:"编辑模型",subtitle:"修改模型设置",modelId:"模型 ID",modelIdPlaceholder:"模型标识符",modelIdHelper:"调用 API 时使用的模型标识符",modelName:"展示名称",modelNamePlaceholder:"友好的展示名称",modelNameHelper:"在界面中显示的名称",group:"分组",groupPlaceholder:"选择或输入分组名称",submit:"保存",cancel:"取消",vision:"视觉能力",visionHint:"此模型是否支持图片/视觉输入",reasoning:"思考模型",reasoningHint:"此模型是否支持思考/推理模式"},manageDialog:{title:"模型管理",cachedAt:"缓存时间 {{date}}({{source}})",refresh:"刷新",close:"关闭",raw:"原始 JSON",empty:"暂无可用模型。",error:"加载失败:{{message}}",addFromCatalog:"添加",sourceCache:"缓存",sourceNetwork:"实时",contextLength:"上下文 {{value}} Token",maxTokens:"输出上限 {{value}} Token"},messages:{added:"模型已添加。",updated:"模型已更新。",removed:"模型已移除。",duplicate:"模型已存在。",refreshed:"模型已刷新",refreshFailed:"模型刷新失败"},testDialog:{title:"模型连通性测试",provider:"提供商",model:"测试模型",testing:"正在测试...",success:"测试成功",successMessage:"模型可以正常访问",failure:"测试失败",aiResponse:"AI 响应",charCount:"{{count}} 字符",duration:"耗时 {{time}}s",close:"关闭",retest:"重新测试",testButton:"测试模型",unsupportedFormat:"暂不支持测试该提供商格式。"}},router:{title:"路由配置",description:"为不同场景配置使用的提供商/模型。",labels:{default:"默认",background:"后台",think:"思考",longContext:"长上下文",webSearch:"联网搜索",image:"图像",longContextThreshold:"长上下文阈值"},helper:{longContextThreshold:"超过该 token 数后自动切换到长上下文模型。"},placeholder:{required:"必填",optional:"可选"}},agentRouter:{title:"Agent 路由",description:"配置聊天模式与代码模式之间的双向路由。",searchPlaceholder:"搜索路由...",noSearchResults:"没有匹配的路由。",tabs:{chatToCode:"聊天 → 代码",codeToChatPlaceholder:"代码 → 聊天"},chatToCode:{title:"聊天转代码路由",description:"在 Agent/代码模式中使用聊天提供商",addRouter:"添加路由",emptyState:"尚未配置聊天→代码路由。添加一个以在代码模式中使用聊天提供商。",form:{name:"路由名称",namePlaceholder:"我的聊天→代码路由",chatProvider:"聊天提供商",chatProviderPlaceholder:"选择聊天提供商",mode:"模式",modeSimple:"简单",modeAdvanced:"高级",modeSimpleDesc:"直接转发到聊天提供商",modeAdvancedDesc:"配置模型映射和上下文处理",enabled:"启用",save:"保存路由",cancel:"取消"},list:{provider:"提供商",mode:"模式",status:"状态"},mappings:{title:"模型映射",description:"将聊天提供商模型映射到代码提供商模型",count:"个映射",empty:"尚未配置模型映射。添加映射以将聊天模型路由到代码提供商。",addNew:"添加新映射",selectSource:"选择源模型(聊天)",selectTarget:"选择目标模型(代码)",targetPlaceholder:"输入 Claude Code 模型名称",notSet:"(未设置 - 点击选择)",add:"添加",edit:"编辑",done:"完成"},advanced:{title:"高级配置",description:"为不同任务类型配置模型",helpText:"默认模型为必填项。其他模型为可选,如未配置将回退到默认模型。",default:{label:"默认",placeholder:"选择默认模型",description:"通用任务的主要模型(类似 Claude Sonnet)"},background:{label:"后台",placeholder:"选择后台模型",description:"后台任务的轻量模型(类似 Claude Haiku)"},think:{label:"思考",placeholder:"选择思考模型",description:"复杂推理的高级模型(类似 Claude Opus)"},image:{label:"图像",placeholder:"选择图像模型",description:"具有视觉能力的图像相关任务模型"}}},codeToChat:{title:"代码转聊天路由",description:"在聊天模式中暴露 Coding Plan 模型",addRouter:"添加路由",emptyState:"尚未配置代码→聊天路由。添加一个以在聊天模式中暴露 Coding Plan 模型。",form:{name:"路由名称",namePlaceholder:"我的代码→聊天路由",codeProvider:"代码提供商",codeProviderPlaceholder:"选择代码提供商",codeProviderHelper:"选择用于转换的代码提供商",models:"Coding Plan 模型",modelsHelper:"选择要暴露的 Coding Plan 模型",enabled:"启用",save:"保存路由",cancel:"取消"},mappings:{title:"模型映射",description:"将代码提供商模型映射到聊天提供商模型以供暴露",count:"个映射",empty:"尚未配置模型映射。添加映射以在聊天模式中暴露代码模型。",addNew:"添加新映射",selectSource:"选择源模型(代码)",selectTarget:"选择目标模型(聊天)",sourcePlaceholder:"输入源模型名称",targetPlaceholder:"输入目标模型名称",add:"添加",edit:"编辑",done:"完成"}},transformers:{title:"Transformers",description:"配置请求/响应转换器",noProvider:"请先选择一个提供商来配置转换器",empty:"无转换器",count:"{{count}} 个转换器"},status:{enabled:"已启用",disabled:"已禁用"},messages:{routerAdded:"路由添加成功",routerUpdated:"路由更新成功",routerDeleted:"路由删除成功",saveFailed:"保存路由失败"}},presets:{title:"快速添加提供商",added:"已添加",add:"添加",features:{search:"搜索",vision:"视觉",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"确定要删除该提供商吗?"},errors:{nameRequired:"提供商名称不能为空",urlRequired:"API 地址不能为空",urlInvalid:"请输入有效的 URL 地址(例如 https://api.example.com)",saveFailed:"保存提供商失败",deleteFailed:"删除提供商失败,请重试。",toggleFailed:"切换提供商状态失败,请重试。"},openRouter:{title:"OpenRouter 提供商路由",description:"配置 OpenRouter 如何将请求路由到不同的提供商。",sort:"路由策略",sortTooltip:"选择提供商优先级。自动模式使用智能负载均衡。",order:"提供商优先顺序",orderTooltip:"指定尝试的提供商顺序(如 anthropic、openai、together)。按回车添加。",orderPlaceholder:"输入提供商标识并按回车...",allowFallbacks:"允许回退",allowFallbacksTooltip:"启用后,如果主提供商不可用,OpenRouter 会尝试备用提供商。",requireParameters:"要求支持所有参数",requireParametersTooltip:"仅路由到支持请求中所有参数的提供商。",dataCollection:"数据收集策略",dataCollectionTooltip:"控制是否使用可能存储或训练数据的提供商。",zdr:"零数据保留",zdrTooltip:"仅路由到具有零数据保留策略的端点。",only:"仅允许的提供商",onlyTooltip:"仅使用这些特定提供商。留空则允许所有提供商。",onlyPlaceholder:"输入提供商标识并按回车...",ignore:"忽略的提供商",ignoreTooltip:"路由请求时跳过这些提供商。",ignorePlaceholder:"输入提供商标识并按回车...",quantizations:"量化过滤",quantizationsTooltip:"仅使用具有特定量化级别的提供商。较低精度可能降低质量但提高速度。",maxPrice:"最高价格",maxPriceTooltip:"设置每百万 token 的最高价格限制。留空表示无限制。",configured:"已配置"}},JT={label:"API 模式",standard:"按量付费",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"该 plan 的 API Key 通常以 `{{prefix}}` 开头。仅为提示,不强制校验。",dashscopeCodingPlanSeparateKey:"百炼 Coding Plan 使用独立 API Key(与按量付费端点的 Key 不通用)。",baiduCodingPlanSeparateKey:"千帆 Coding Plan 使用独立 API Key(与按量付费端点的 Key 不通用)。",tencentTokenPlanAnthropicOnly:"腾讯云 Token Plan 仅支持 Anthropic 协议。",xiaomiTokenPlanRegions:"默认 baseUrl 是 `token-plan-cn.*`,可手动改为 `token-plan-sgp.*` 或 `token-plan-ams.*`。",confirmOverwriteTitle:"切换 API 模式?",confirmOverwriteBody:"你修改过 API URL 或 API Key。切换模式可以覆盖为新模式的默认值,或保留你的自定义只切换模式标签。",overwriteAndSwitch:"覆盖并切换",keepCustomizations:"保留自定义"},ej={zhipu:"z.ai",zhipuBigmodel:"智谱 GLM",volcengine:"火山方舟",dashscope:"阿里云百炼",tencent:"腾讯云混元",tencentAnthropic:"腾讯云混元 (Token Plan)",baidu:"百度千帆",kuaishou:"快手 KwaiKAT",mthreads:"摩尔线程",xiaomiMimoOpenai:"小米 MiMo (OpenAI)",xiaomiMimoAnthropic:"小米 MiMo (Anthropic)"},tj={cancel:"取消",close:"关闭",copy:"复制",delete:"删除",dismiss:"忽略",save:"保存",optional:"可选",retry:"重试",loading:"加载中…"},aj={common:{learnMore:"文档"}},nj={notSupportedByDaemon:"守护进程暂不支持此项",discoveryUnsupportedFormat:"当前提供商格式暂不支持模型发现,请手动添加模型。"},oj={subtitle:"控制面板",providers:"提供商",apiService:"API 服务",accounts:"账户",codeCli:"Code CLI",settings:"设置",usageStats:"用量统计",pricing:"模型价格"},ij={title:"API 服务",description:"配置对外 API 服务器、各端点的模型路由以及命名访问密钥。",loading:"正在加载服务器配置…",loadError:"无法加载服务器配置。请检查守护进程是否可达。",enable:{label:"启用对外服务器",description:"启动本地 API 服务器,将外部调用方的请求经由你的提供商路由。"},networkBinding:{label:"允许局域网访问",description:"将服务器绑定到网络接口,而不仅限于回环地址。",warning:"局域网访问会把 API 服务器暴露给网络中的其他设备。若同时启用订阅路由,请求可能消耗你的订阅额度——除非你信任该网络,否则请保持关闭。"},status:{running:"服务器运行中",stopped:"服务器已停止",runningHint:"对外 API 服务器正在接收请求。",stoppedHint:"启用服务器以开始接收请求。",port:"端口 {{port}}",loopback:"回环地址",lan:"局域网地址"},endpoints:{title:"端点路由",description:"为每种线路格式选择路由到的模型。默认模型已并入此处——该服务器是路由器,而非聊天应用。"},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"默认模型",backgroundModel:"后台模型",visionModel:"视觉模型",noVisionModel:"无",backgroundModelIds:"后台模型 ID",backgroundModelIdsPlaceholder:"以逗号分隔的模型 id",modelPlaceholder:"选择模型…",useSubscription:"使用订阅",subscriptionUnsupported:"此端点不支持订阅路由。"},keys:{title:"访问密钥",description:"外部调用方作为 Bearer 令牌发送的命名密钥。完整密钥仅在创建时显示一次。",namePlaceholder:"密钥名称(如 my-cli)",create:"创建密钥",empty:"尚无访问密钥。",enabled:"已启用",disabled:"已禁用",revoked:"已吊销",toggle:"切换密钥",revoke:"吊销",revokeConfirmTitle:"吊销此密钥?",revokeConfirmDesc:"吊销“{{name}}”后它将立即无法用于认证。此操作不可撤销。",created:{title:"密钥已创建",warning:"请立即复制此密钥——它不会再次显示。请妥善保存。",copy:"复制",copied:"已复制",dismiss:"完成"}}},rj={title:"账户与订阅",description:"管理服务器路由所使用的订阅凭据。令牌在此写入,但绝不会回显。",loading:"正在加载账户…",empty:"暂无可用的订阅提供商。",signIn:"登录",oauth:{title:"登录 {{name}}",description:"在浏览器中打开登录页面,授权后将授权码粘贴到下方。授权码仅传入守护进程——签发的令牌不会回显。",openPage:"打开登录页面",codeLabel:"授权码",codePlaceholder:"在此粘贴授权码",submit:"完成登录"},codexOauth:{title:"登录 {{name}}",description:"在浏览器中打开登录页面并授权。守护进程会自动捕获结果——请在完成前保持此窗口打开。令牌不会回显。",waiting:"正在等待你在浏览器中完成登录……",failed:"登录失败,请重试。"},clearProvider:"全部清除",clearConfirmTitle:"清除 {{name}} 的账户?",clearConfirmDesc:"这将移除该提供商存储的全部凭据。此操作不可撤销。",credential:{ok:"已配置",notConfigured:"未配置"},kind:{"pass-through":"透传凭据","oauth-bearer":"OAuth Bearer","static-bearer":"静态 Bearer 密钥"},reason:{"missing-credential":"未存储凭据。",expired:"凭据已过期。","reauth-required":"需要重新认证。","refresh-failed":"令牌刷新失败。","not-refreshable":"凭据不可刷新。",unknown:"状态未知。"},status:{unconfigured:"未配置",authorized:"已授权",configured:"已配置",expired:"已过期",error:"错误"},authMethod:{oauth:"OAuth",setup_token:"Setup 令牌",manual:"手动"},list:{empty:"该提供商尚未存储任何账户。",active:"活动",expiresAt:"{{value}} 过期",setActive:"设为活动",remove:"移除",removeConfirmTitle:"移除此账户?",removeConfirmDesc:"移除“{{name}}”将删除其存储的凭据。此操作不可撤销。",title:"账户"},write:{trigger:"添加凭据",title:"写入 {{name}} 凭据",description:"粘贴已获取的令牌信息。字段仅限该提供商接受的内容;令牌将被存储,绝不回显。",authMethod:"认证方式",status:"状态",subscriptionLevel:"订阅等级",subscriptionLevelNone:"未设置",submit:"保存凭据"},field:{accessToken:"Access Token",refreshToken:"Refresh Token",idToken:"ID Token",apiKey:"API 密钥",expiresAt:"过期时间(ISO)",setupTokenExpiresAt:"Setup 令牌过期时间(ISO)",accountId:"账户 ID",email:"邮箱",organizationId:"组织 ID",baseUrl:"基础 URL",zenBaseUrl:"Zen 基础 URL"},provider:{claude:{title:"Claude",description:"由守护进程路由的 Anthropic 订阅凭据。"},codex:{title:"Codex",description:"由守护进程路由的 OpenAI Codex 订阅凭据。"},gemini:{title:"Gemini",description:"由守护进程路由的 Google Gemini 订阅凭据。"},opencodego:{title:"OpenCodeGo",description:"由守护进程路由的静态 API 密钥凭据。"}},authMethodLabel:"授权方式",authMethodDesc:{oauth:"通过浏览器登录;守护进程会捕获并存储令牌。",manual:"粘贴已获取的令牌。它将被存储,绝不回显。"},actions:{authorize:"授权",enterToken:"输入令牌",refresh:"刷新"},accounts:{addAccount:"添加账户"},detail:{authMethod:"授权方式",subscriptionLevel:"订阅等级",expiresAt:"过期时间",lastRefreshed:"上次刷新",label:"账户标签",labelPlaceholder:"为该账户命名",saveLabel:"保存标签"},oauthFlow:{step1:{title:"打开授权页面",desc:"在浏览器中打开登录页面。"},step2:{title:"授权访问",desc:"登录并批准该提供商的访问权限。"},step3:{title:"复制授权码",desc:"批准后页面会显示一个授权码。"},step4:{title:"粘贴授权码",desc:"将授权码粘贴到下方以完成。授权码仅传入守护进程——签发的令牌不会显示。"},authorize:"完成登录",showUrl:"显示授权 URL"},manual:{title:"粘贴凭据",description:"粘贴已获取的令牌。字段仅限该提供商接受的内容;令牌将被存储,绝不回显。",accessTokenPlaceholder:"粘贴 Access Token",refreshTokenPlaceholder:"粘贴 Refresh Token(可选)",hint:"令牌将发送至守护进程并加密存储,绝不回显。"},openCodeGo:{apiKeyRequired:"需要 API 密钥。",apiKeyPlaceholder:"粘贴 API 密钥",baseUrlPlaceholder:"https://……(可选)",zenBaseUrlPlaceholder:"https://……(可选)"},info:{title:"关于订阅账户",description:"令牌写入守护进程并用于对上游请求进行认证。它们以加密形式存储,绝不回显。移除账户会删除其存储的凭据。"},rename:{failed:"无法重命名账户。"},refresh:{failed:"无法刷新令牌。"},errors:{requestFailed:"请求失败,请重试。"},syncWarning:{"external-divergent":"外部 CLI 登录文件中的凭据比此账号更新,已存储的令牌可能无法再刷新——请立即刷新或重新登录。","external-not-rotated":"刷新失败,且外部 CLI 中保存的是同一个已过期凭据。请重新登录。","duplicate-token":"另一个账号与此账号共用同一凭据,刷新任意一个都会使另一个失效。"},importExternal:{detected:"检测到本机已有 {{name}} CLI 登录。",hint:"导入后由本程序负责保鲜:每次刷新令牌都会同步更新 CLI 登录文件,终端里的 CLI 保持登录不掉线。",button:"导入现有 CLI 登录"}},sj={title:"Code CLI",description:"将编码 CLI 指向守护进程的对外代理。此页面为只读——无需在此配置任何内容。",copy:"复制",copied:"已复制",baseUrl:{title:"守护进程基础 URL",description:"你的 CLI 连接的代理地址。",label:"基础 URL"},token:{title:"认证",hint:"对管理路由请发送 'Authorization: Bearer <你的管理令牌>'。管理令牌在守护进程中配置(其配置文件或环境变量)——此处绝不显示。"},examples:{title:"示例启动环境",keyNote:"请使用在 API 服务页面创建的对外访问密钥——而非管理令牌。",anthropic:"Anthropic 格式 CLI",openai:"OpenAI 格式 CLI"},launchDescription:"在终端中启动编码 CLI,并指向此守护进程。守护进程会注入重定向环境变量并为你启动 CLI。",refresh:"刷新",loading:"正在检测 CLI……",cli:{installed:"已安装",notFound:"未找到",notFoundHint:"该 CLI 不在守护进程主机的 PATH 上。请先安装,然后刷新。",install:"安装",installing:"安装中…",installingHint:"正在守护进程主机上安装,可能需要一分钟。",launch:"启动",launchTitle:"启动 {{name}}",launchDescription:"在守护进程主机上打开一个新终端运行该 CLI,并经由守护进程代理路由。可选填工作目录。",cwdLabel:"工作目录",cwdPlaceholder:"/path/to/your/project",runningVia:"运行中 · {{provider}} / {{model}}",stop:"停止"},manual:{title:"手动设置",description:"想自己运行 CLI?用这些环境变量把它指向守护进程。",show:"展开",hide:"收起"}},lj={probing:"正在检测守护进程…",spawning:"正在启动守护进程…",failed:"守护进程启动失败",failedHint:"请确认已安装 Node.js 且守护进程已构建(dist 存在),或将 OMNICROSS_DAEMON_ENTRY 设为守护进程的 cli.js 路径。"},dj={title:"设置",description:"桌面应用偏好设置。",desktopOnly:"开机启动与托盘选项仅在桌面应用中生效。",startup:{title:"启动",autoLaunch:"开机启动",autoLaunchHint:"登录系统时自动启动 Omnicross。",startMinimized:"启动时最小化到托盘",startMinimizedHint:"在后台启动,不打开窗口。"},tray:{title:"托盘",minimizeOnClose:"关闭时最小化到托盘",minimizeOnCloseHint:"关闭窗口时隐藏到托盘,而不是退出应用。"},language:{title:"语言",label:"界面语言"}},cj={title:"用量统计",description:"守护进程处理的请求的 Token 与费用统计。",rangeToday:"今天",range7d:"最近 7 天",range30d:"最近 30 天",rangeCustom:"自定义",from:"开始",to:"结束",totalCost:"总费用",cacheSavings:"缓存节省",events:"请求数",inputTokens:"输入 Token",outputTokens:"输出 Token",cacheReadTokens:"缓存读取",cacheWriteTokens:"缓存写入",reasoningTokens:"推理 Token",byModel:"按模型",byApiKey:"按 API 密钥",provider:"提供商",model:"模型",cost:"费用",apiKey:"API 密钥",unpriced:"无价格",unpricedHint:"该模型没有价格条目 — 请在“模型价格”页面添加。",unattributed:"未归属",unattributedHint:"未关联到具体 API 密钥的请求。在按密钥归属记录上线之前,这是正常现象。",empty:"该时间范围内没有请求。",invalidRange:"请选择有效的日期范围。"},uj={title:"模型价格",description:"用于计算请求费用的每模型 Token 价格(美元 / 每 100 万 Token)。",search:"搜索提供商或模型…",fetchLatest:"获取最新价格",fetching:"获取中…",addEntry:"添加条目",provider:"提供商",model:"模型",inputPrice:"输入",outputPrice:"输出",cacheReadPrice:"缓存读取",cacheWritePrice:"缓存写入",source:"来源",updated:"更新时间",userEdited:"已编辑",edit:"编辑",deleteTitle:"删除该价格条目?",empty:"价格表为空。",emptyHint:"获取最新价格以填充表格。",noMatches:"没有匹配的条目。",saved:"价格条目已保存。",saveFailed:"保存失败:{{message}}",deleteFailed:"删除失败:{{message}}",alreadyDeleted:"该条目已不存在。",fetchApplied:"已从来源更新 {{count}} 个条目。",fetchFailed:"获取失败:{{message}}",requiredId:"必填",invalidPrice:"请输入非负数字",conflictTitle:"解决价格冲突",conflictHint:"这些条目既被你编辑过,又在来源处发生了变化。请逐行选择保留你的值(跳过)或采用来源值(覆盖)。",current:"当前",incoming:"来源值",overwrite:"覆盖",skip:"跳过",overwriteAll:"全部覆盖",skipAll:"全部跳过",applyResolutions:"应用",resolved:"已覆盖 {{overwritten}} 项,跳过 {{skipped}} 项。",resolvedWithStale:"已覆盖 {{overwritten}} 项,跳过 {{skipped}} 项。{{stale}} 项在此期间已被修改,保持不变。",refreshFailed:"更改已生效,但刷新列表失败:{{message}}",sourceBuiltin:"内置",sourceLitellm:"LiteLLM",sourceUser:"用户"},pj={providerSettings:XT,apiMode:JT,presetName:ej,common:tj,mediaSettings:aj,appLocal:nj,nav:oj,apiService:ij,accounts:rj,codeCli:sj,daemonStatus:lj,settings:dj,usageStats:cj,pricing:uj},mj={loading:"正在載入 LLM 設定...",reset:{button:"還原預設值",confirmTitle:"還原預設設定?",confirmBody:"這將清除您對此提供者的自訂設定,使其重新套用內建的預設值。您的 API 金鑰與已儲存的工作階段不受影響。",confirmButton:"還原預設值"},reentryBanner:{message:"有 {{count}} 個已啟用的提供者需要重新輸入 API 金鑰。請逐一開啟並重新填入金鑰。"},migrationPack:{barHint:"使用加密的遷移套件,將提供者金鑰與訂閱權杖移轉至另一台裝置。",passphrase:"密碼短語",passphrasePlaceholder:"請輸入密碼短語",passphraseHint:"請使用至少 8 個字元,建議 12 個或以上。",confirm:"確認密碼短語",confirmPlaceholder:"請再次輸入密碼短語",mismatch:"兩次輸入的密碼短語不一致。",strength:{weak:"太短——請使用至少 8 個字元。",fair:"尚可——12 個或以上字元更安全。",strong:"密碼短語強度高。"},export:{button:"匯出套件",title:"匯出加密套件",subtitle:"將提供者金鑰與訂閱權杖加密為可攜式檔案。",warning:"此檔案包含可解密的機密資訊,請妥善保管——任何人只要同時持有此檔案與密碼短語,即可讀取您的金鑰。密碼短語一旦遺失將無法復原。",submit:"匯出",success:"套件匯出成功。",error:"匯出失敗,請再試一次。"},import:{button:"匯入套件",title:"匯入加密套件",subtitle:"從已匯出的套件中還原提供者金鑰與訂閱權杖。",hint:"請輸入匯出套件時使用的密碼短語,然後選擇檔案。",submit:"匯入",successTitle:"匯入完成",summary:"已匯入 {{providerKeys}} 個提供者金鑰、{{poolKeys}} 個金鑰池項目及 {{tokenSets}} 組權杖。",duplicates:"已略過 {{count}} 個已存在的金鑰池項目。",skipped:"已略過(無匹配的提供者):{{names}}",error:"密碼短語錯誤或套件已損毀,未做任何變更。"}},searchPlaceholder:"搜尋提供者...",emptySearch:"找不到符合搜尋條件的提供者。",emptyList:"尚未設定任何提供者。",selectPrompt:"選取提供者以檢視詳細資訊",listStatus:"共 {{count}} 個模型",noModels:"未設定模型",enabled:"已啟用",disabled:"已停用",showEnabledOnly:"僅顯示已啟用",showAll:"顯示所有提供者",dragHandle:"拖曳以重新排序",reorderFailed:"儲存提供者排序失敗",credentials:{apiKey:"API 金鑰",apiBaseUrl:"API 基礎 URL"},filter:{all:"全部",chat:"對話",code:"程式碼"},tags:{openai:"OpenAI",anthropic:"Anthropic",gemini:"Google Gemini",claudeCode:"Claude Code",grok:"Grok",azureOpenai:"Azure OpenAI",openaiResponse:"OpenAI Responses"},form:{templateLabel:"選取範本",skipTemplates:"略過,手動設定",name:"名稱 *",providerType:"類型",apiType:"API 類型",apiTypeOptions:{openai:"OpenAI Completion",claudecode:"Claude Code"},apiTypeDescription:{openai:"標準 OpenAI chat/completions API 格式",claudecode:"Anthropic Messages API 格式(Claude Code)"},chatApiFormat:"API 格式",chatApiFormatDescription:"請選取符合您提供者端點的 API 格式",apiKey:"API 金鑰",apiKeyPlaceholder:"sk-... 或 $ENV_VAR",apiKeyHelper:"可使用 $VAR_NAME 參照環境變數",apiKeySetPlaceholder:"金鑰已設定——留空則保持不變",apiKeyReplaceHelper:"金鑰已安全儲存。輸入新值可替換,留空則保持不變。",testApiKey:"測試 API 金鑰",apiUrl:"API URL *",apiUrlPlaceholder:"https://api.example.com/v1/chat/completions",apiUrlPreview:"預覽:",models:"模型",modelPlaceholder:"模型名稱(如 gpt-4、claude-3-opus)",transformers:"轉換器",transformerConfig:"API 轉換器",transformerConfigDescription:"設定轉換器以適配此提供者的 API 請求/回應格式",transformerConfigNote:"Daemon 會在請求鏈中將這些轉換器套用於提供者格式轉換器(負責 wire 格式轉換)之後。未知的轉換器名稱將被略過。",enabled:"已啟用",apiVersion:"API 版本",apiVersionPlaceholder:"2024-08-01-preview",apiVersionHelper:"Azure OpenAI API 版本(如 2024-08-01-preview)",official:"Anthropic 官方 API",officialHelper:"若此提供者直接連線至 Anthropic 官方 API,請啟用。反向代理或第三方服務請停用。",maxConcurrency:"最大並行請求數",maxConcurrencyHelper:"傳送至此提供者的最大並行 API 請求數。較低的值有助於避免速率限制(429 錯誤)。設定 `-1` 表示不限制。",codingPlan:{label:"Coding Plan",description:"為訂閱制 Coding Plan 使用獨立的 API 端點",baseUrl:"Coding Plan 基礎 URL",baseUrlPlaceholder:"https://api.example.com/v1",apiKey:"Coding Plan API 金鑰(選填)",apiKeyPlaceholder:"留空則使用提供者的 API 金鑰",apiKeyHelper:"僅在 Coding Plan 使用不同 API 金鑰時才需要填寫",tokenPlanHint:"部分提供者(如小米 MiMo)的 Token Plan 金鑰以 `tp-` 開頭——僅供參考,不會強制驗證。"},selectTypeFirst:"選取提供者類型",selectTypeFirstDesc:"選取您要新增的提供者類型",codeProviderNote:"程式碼提供者只需填入 API 金鑰與 URL。模型由 Agent Router 管理。",buttons:{cancel:"取消",submitAdd:"新增提供者",submitUpdate:"更新提供者",continue:"繼續",back:"返回"}},details:{noSelection:"選取提供者以檢視詳細資訊",apiKey:"API 金鑰",apiUrl:"API URL",nameLabel:"提供者名稱",modelsEndpoint:"模型端點",modelsEndpointHelper:"若提供者開放了自訂的 /models 路徑,可在此覆寫探索端點。",models:"模型",transformers:"轉換器",codeProviderNote:"程式碼提供者(如 Claude Code)不需要設定模型。模型由 Agent Router 自動管理。",buttons:{more:"更多設定",delete:"刪除"}},providerModelSelector:{placeholder:"選取提供者與模型",noProviders:"目前沒有可用的提供者",noModels:"尚未設定模型"},apiKeyPool:{title:"API 金鑰池",description:"設定多個 API 金鑰以進行負載平衡。每個工作階段會固定使用一個金鑰以保留提示快取。",defaultLabel:"預設",weight:"權重",noKey:"無金鑰",labelPlaceholder:"標籤(如 金鑰 #1、正式環境)",addKey:"新增 API 金鑰",add:"新增",empty:"尚未設定其他金鑰。",statusCoolingDown:"冷卻中 {{time}}",statusAuthFailed:"驗證失敗 · 已停用",statusDisabled:"已停用",statusHealthy:"正常",agoSeconds:"{{count}} 秒前",agoMinutes:"{{count}} 分鐘前",agoHours:"{{count}} 小時前",agoDays:"{{count}} 天前"},modelsManager:{searchPlaceholder:"搜尋模型...",defaultGroup:"所有模型",add:"新增模型",manage:"管理",empty:"此群組中沒有模型",enabled:"已啟用",disabled:"已停用",filters:{all:"全部",vision:"視覺",reasoning:"推理",free:"免費",tools:"工具"},manualDialog:{title:"新增模型",subtitle:"為此提供者新增自訂模型",modelId:"模型 ID",modelIdPlaceholder:"gpt-4o、claude-3.5、gemini-2.0-flash 等",modelIdHelper:"呼叫 API 時使用的精確模型識別碼",modelName:"顯示名稱",modelNamePlaceholder:"易識別的顯示名稱(選填)",modelNameHelper:"顯示於介面中的名稱。留空則使用模型 ID",group:"群組",groupPlaceholder:"選取或輸入群組名稱",submit:"新增",cancel:"取消",helper:"請填入提供者 API 所使用的精確模型識別碼。"},editDialog:{title:"編輯模型",subtitle:"修改模型設定",modelId:"模型 ID",modelIdPlaceholder:"模型識別碼",modelIdHelper:"呼叫 API 時使用的模型識別碼",modelName:"顯示名稱",modelNamePlaceholder:"易識別的顯示名稱",modelNameHelper:"顯示於介面中的名稱",group:"群組",groupPlaceholder:"選取或輸入群組名稱",submit:"儲存",cancel:"取消",vision:"視覺能力",visionHint:"此模型是否支援圖片/視覺輸入",reasoning:"推理模型",reasoningHint:"此模型是否支援思考/推理模式"},manageDialog:{title:"管理模型",cachedAt:"快取時間 {{date}}({{source}})",refresh:"重新整理",close:"關閉",raw:"原始 JSON",empty:"目前沒有可用的遠端模型。",error:"載入模型失敗:{{message}}",addFromCatalog:"新增",sourceCache:"快取",sourceNetwork:"即時",contextLength:"上下文 {{value}} 個 token",maxTokens:"最多 {{value}} 個 token"},messages:{added:"模型已新增。",updated:"模型已更新。",removed:"模型已移除。",duplicate:"模型已存在。",refreshed:"模型已重新整理",refreshFailed:"模型重新整理失敗"},testDialog:{title:"模型連線測試",provider:"提供者",model:"模型",testing:"測試中...",success:"測試成功",successMessage:"模型可正常存取",failure:"測試失敗",aiResponse:"AI 回應",charCount:"{{count}} 個字元",duration:"耗時 {{time}} 秒",close:"關閉",retest:"重新測試",testButton:"測試模型",unsupportedFormat:"此提供者格式目前不支援測試。"}},router:{title:"路由設定",description:"為不同情境設定要使用的提供者/模型。",labels:{default:"預設",background:"背景",think:"思考",longContext:"長上下文",webSearch:"網路搜尋",image:"圖像",longContextThreshold:"長上下文閾值"},helper:{longContextThreshold:"超過此 token 數後切換至長上下文模型。"},placeholder:{required:"必填",optional:"選填"}},agentRouter:{title:"Agent 路由",description:"設定對話模式與程式碼模式之間的雙向路由。",searchPlaceholder:"搜尋路由...",noSearchResults:"找不到符合搜尋條件的路由。",tabs:{chatToCode:"對話 → 程式碼",codeToChatPlaceholder:"程式碼 → 對話"},chatToCode:{title:"對話轉程式碼路由",description:"在 Agent/程式碼模式中使用對話提供者",addRouter:"新增路由",emptyState:"尚未設定對話→程式碼路由。請新增一個以在程式碼模式中使用對話提供者。",form:{name:"路由名稱",namePlaceholder:"我的對話→程式碼路由",chatProvider:"對話提供者",chatProviderPlaceholder:"選取對話提供者",mode:"模式",modeSimple:"簡單",modeAdvanced:"進階",modeSimpleDesc:"直接傳遞至對話提供者",modeAdvancedDesc:"設定模型對應與上下文處理",enabled:"啟用",save:"儲存路由",cancel:"取消"},list:{provider:"提供者",mode:"模式",status:"狀態"},mappings:{title:"模型對應",description:"將對話提供者的模型對應至程式碼提供者的模型",count:"個對應",empty:"尚未設定模型對應。請新增對應以將對話模型路由至程式碼提供者。",addNew:"新增對應",selectSource:"選取來源模型(對話)",selectTarget:"選取目標模型(程式碼)",targetPlaceholder:"輸入 Claude Code 模型名稱",notSet:"(未設定——點擊選取)",add:"新增",edit:"編輯",done:"完成"},advanced:{title:"進階設定",description:"為不同任務類型設定模型",helpText:"預設模型為必填。其他模型為選填,若未設定將回退至預設模型。",default:{label:"預設",placeholder:"選取預設模型",description:"一般任務的主要模型(類似 Claude Sonnet)"},background:{label:"背景",placeholder:"選取背景模型",description:"背景任務的輕量模型(類似 Claude Haiku)"},think:{label:"思考",placeholder:"選取思考模型",description:"複雜推理的進階模型(類似 Claude Opus)"},image:{label:"圖像",placeholder:"選取圖像模型",description:"具備視覺能力的圖像相關任務模型"}}},codeToChat:{title:"程式碼轉對話路由",description:"在對話模式中公開 Coding Plan 模型",addRouter:"新增路由",emptyState:"尚未設定程式碼→對話路由。請新增一個以在對話模式中公開 Coding Plan 模型。",form:{name:"路由名稱",namePlaceholder:"我的程式碼→對話路由",codeProvider:"程式碼提供者",codeProviderPlaceholder:"選取程式碼提供者",codeProviderHelper:"選取用於轉換的程式碼提供者",models:"Coding Plan 模型",modelsHelper:"選取要公開的 Coding Plan 模型",enabled:"啟用",save:"儲存路由",cancel:"取消"},mappings:{title:"模型對應",description:"將程式碼提供者的模型對應至對話提供者的模型以供公開",count:"個對應",empty:"尚未設定模型對應。請新增對應以在對話模式中公開程式碼模型。",addNew:"新增對應",selectSource:"選取來源模型(程式碼)",selectTarget:"選取目標模型(對話)",sourcePlaceholder:"輸入來源模型名稱",targetPlaceholder:"輸入目標模型名稱",add:"新增",edit:"編輯",done:"完成"}},transformers:{title:"轉換器",description:"設定請求/回應轉換用的轉換器",noProvider:"請先選取提供者以設定轉換器",empty:"沒有轉換器",count:"{{count}} 個轉換器"},status:{enabled:"已啟用",disabled:"已停用"},messages:{routerAdded:"路由新增成功",routerUpdated:"路由更新成功",routerDeleted:"路由刪除成功",saveFailed:"儲存路由失敗"}},presets:{title:"快速新增提供者",added:"已新增",add:"新增",features:{search:"搜尋",vision:"視覺",mcp:"MCP",codingPlan:"Coding Plan"}},alerts:{deleteConfirm:"確定要刪除此提供者嗎?"},errors:{nameRequired:"提供者名稱為必填",urlRequired:"API 基礎 URL 為必填",urlInvalid:"請輸入有效的 URL(如 https://api.example.com)",saveFailed:"儲存提供者失敗",deleteFailed:"刪除提供者時發生錯誤,請再試一次。",toggleFailed:"切換提供者狀態時發生錯誤,請再試一次。"},openRouter:{title:"OpenRouter 提供者路由",description:"設定 OpenRouter 如何將請求路由至不同的提供者。",sort:"路由策略",sortTooltip:"選取提供者優先順序。自動模式使用智慧負載平衡。",order:"提供者優先順序",orderTooltip:"指定嘗試的提供者順序(如 anthropic、openai、together)。按 Enter 新增。",orderPlaceholder:"輸入提供者 slug 後按 Enter...",allowFallbacks:"允許備援",allowFallbacksTooltip:"啟用後,若主要提供者無法使用,OpenRouter 將嘗試備援提供者。",requireParameters:"要求支援所有參數",requireParametersTooltip:"僅路由至支援請求中所有參數的提供者。",dataCollection:"資料收集原則",dataCollectionTooltip:"控制是否使用可能儲存或訓練您資料的提供者。",zdr:"零資料保留",zdrTooltip:"僅路由至具有零資料保留原則的端點。",only:"僅允許的提供者",onlyTooltip:"僅使用這些特定提供者。留空則允許所有提供者。",onlyPlaceholder:"輸入提供者 slug 後按 Enter...",ignore:"排除的提供者",ignoreTooltip:"路由請求時略過這些提供者。",ignorePlaceholder:"輸入提供者 slug 後按 Enter...",quantizations:"量化篩選器",quantizationsTooltip:"僅使用具有特定量化等級的提供者。較低精度可能降低品質但提升速度。",maxPrice:"最高價格",maxPriceTooltip:"設定每百萬 token 的最高價格上限。留空表示不限制。",configured:"已設定"}},gj={label:"API 模式",standard:"標準",codingPlan:"Coding Plan",tokenPlan:"Token Plan",apiKeyPrefixHint:"此方案的金鑰通常以 `{{prefix}}` 開頭。僅供參考,不會強制驗證。",dashscopeCodingPlanSeparateKey:"DashScope Coding Plan 使用獨立 API 金鑰,與標準端點的金鑰不通用。",baiduCodingPlanSeparateKey:"Qianfan Coding Plan 使用獨立 API 金鑰,與標準端點的金鑰不通用。",tencentTokenPlanAnthropicOnly:"Tencent Token Plan 僅支援 Anthropic 協定。",xiaomiTokenPlanRegions:"預設 baseUrl 為 `token-plan-cn.*`,可手動更改為 `token-plan-sgp.*` 或 `token-plan-ams.*`。",confirmOverwriteTitle:"切換 API 模式?",confirmOverwriteBody:"您已自訂 API URL 或 API 金鑰。切換模式可覆蓋為新模式的預設值,或保留您的自訂設定僅變更模式標籤。",overwriteAndSwitch:"覆蓋並切換",keepCustomizations:"保留自訂設定"},hj={zhipu:"z.ai",zhipuBigmodel:"智譜 GLM",volcengine:"火山方舟",dashscope:"阿里雲百煉",tencent:"騰訊混元",tencentAnthropic:"騰訊混元 (Token Plan)",baidu:"百度千帆",kuaishou:"快手 KwaiKAT",mthreads:"摩爾線程",xiaomiMimoOpenai:"小米 MiMo (OpenAI)",xiaomiMimoAnthropic:"小米 MiMo (Anthropic)"},fj={cancel:"取消",close:"關閉",copy:"複製",delete:"刪除",dismiss:"關閉",save:"儲存",optional:"選填",retry:"重試",loading:"載入中…"},vj={common:{learnMore:"文件"}},kj={notSupportedByDaemon:"Daemon 尚未支援此功能",discoveryUnsupportedFormat:"此提供者格式目前不支援自動探索模型,請手動新增模型。"},yj={subtitle:"控制台",providers:"提供者",apiService:"API 服務",accounts:"帳號",codeCli:"Code CLI",settings:"設定",usageStats:"用量統計",pricing:"模型價格"},bj={title:"API 服務",description:"設定對外 API 伺服器、各端點的模型路由及命名存取金鑰。",loading:"正在載入伺服器設定…",loadError:"無法載入伺服器設定。請確認 Daemon 是否可正常連線。",enable:{label:"啟用對外伺服器",description:"啟動本機 API 伺服器,將外部呼叫者的請求透過您的提供者進行路由。"},networkBinding:{label:"允許區域網路存取",description:"將伺服器繫結至網路介面,而非僅限回環位址。",warning:"允許區域網路存取將使 API 伺服器對網路中的其他裝置開放。若同時啟用訂閱路由,請求可能消耗您的訂閱配額——除非您信任該網路,否則請保持關閉。"},status:{running:"伺服器執行中",stopped:"伺服器已停止",runningHint:"對外 API 伺服器正在接受請求。",stoppedHint:"啟用伺服器以開始接受請求。",port:"連接埠 {{port}}",loopback:"回環位址 URL",lan:"區域網路 URL"},endpoints:{title:"端點路由",description:"為每種 wire 格式選擇路由目標模型。預設模型已整合於此——此伺服器是路由器,而非對話應用程式。"},endpoint:{name:{chat:"OpenAI Chat",responses:"OpenAI Responses",messages:"Anthropic Messages",gemini:"Gemini"},defaultModel:"預設模型",backgroundModel:"背景模型",visionModel:"視覺模型",noVisionModel:"無",backgroundModelIds:"背景模型 ID",backgroundModelIdsPlaceholder:"以逗號分隔的模型 ID",modelPlaceholder:"選取模型…",useSubscription:"使用訂閱",subscriptionUnsupported:"此端點不支援訂閱路由。"},keys:{title:"存取金鑰",description:"外部呼叫者以 Bearer token 形式傳送的命名金鑰。完整金鑰僅在建立時顯示一次。",namePlaceholder:"金鑰名稱(如 my-cli)",create:"建立金鑰",empty:"尚無存取金鑰。",enabled:"已啟用",disabled:"已停用",revoked:"已撤銷",toggle:"切換金鑰",revoke:"撤銷",revokeConfirmTitle:"撤銷此金鑰?",revokeConfirmDesc:"撤銷「{{name}}」後,它將立即無法用於驗證。此操作無法復原。",created:{title:"金鑰已建立",warning:"請立即複製此金鑰——它不會再次顯示。請妥善保管。",copy:"複製",copied:"已複製",dismiss:"完成"}}},Pj={title:"帳號與訂閱",description:"管理伺服器路由所使用的訂閱憑證。權杖在此寫入,但不會回顯。",loading:"正在載入帳號…",empty:"目前沒有可用的訂閱提供者。",signIn:"登入",oauth:{title:"登入 {{name}}",description:"在瀏覽器中開啟登入頁面,授權後將授權碼貼至下方。授權碼僅傳送至 Daemon——簽發的權杖不會回顯。",openPage:"開啟登入頁面",codeLabel:"授權碼",codePlaceholder:"請在此貼上授權碼",submit:"完成登入"},codexOauth:{title:"登入 {{name}}",description:"在瀏覽器中開啟登入頁面並完成授權。Daemon 會自動擷取結果——在完成前請保持此視窗開啟。權杖不會回顯。",waiting:"正在等待您在瀏覽器中完成登入……",failed:"登入失敗,請再試一次。"},clearProvider:"全部清除",clearConfirmTitle:"清除 {{name}} 的帳號?",clearConfirmDesc:"這將移除此提供者儲存的所有憑證。此操作無法復原。",credential:{ok:"已設定",notConfigured:"未設定"},kind:{"pass-through":"透傳憑證","oauth-bearer":"OAuth Bearer","static-bearer":"靜態 Bearer 金鑰"},reason:{"missing-credential":"未儲存憑證。",expired:"憑證已過期。","reauth-required":"需要重新驗證。","refresh-failed":"權杖更新失敗。","not-refreshable":"憑證無法更新。",unknown:"狀態未知。"},status:{unconfigured:"未設定",authorized:"已授權",configured:"已設定",expired:"已過期",error:"錯誤"},authMethod:{oauth:"OAuth",setup_token:"設定權杖",manual:"手動"},list:{empty:"此提供者尚未儲存任何帳號。",active:"使用中",expiresAt:"{{value}} 到期",setActive:"設為使用中",remove:"移除",removeConfirmTitle:"移除此帳號?",removeConfirmDesc:"移除「{{name}}」將刪除其儲存的憑證。此操作無法復原。",title:"帳號"},write:{trigger:"新增憑證",title:"寫入 {{name}} 憑證",description:"貼入已取得的權杖資訊。欄位僅限此提供者接受的內容;權杖將被儲存,不會回顯。",authMethod:"驗證方法",status:"狀態",subscriptionLevel:"訂閱等級",subscriptionLevelNone:"未設定",submit:"儲存憑證"},field:{accessToken:"存取權杖",refreshToken:"更新權杖",idToken:"ID 權杖",apiKey:"API 金鑰",expiresAt:"到期時間(ISO)",setupTokenExpiresAt:"設定權杖到期時間(ISO)",accountId:"帳號 ID",email:"電子郵件",organizationId:"組織 ID",baseUrl:"基礎 URL",zenBaseUrl:"Zen 基礎 URL"},provider:{claude:{title:"Claude",description:"由 Daemon 路由的 Anthropic 訂閱憑證。"},codex:{title:"Codex",description:"由 Daemon 路由的 OpenAI Codex 訂閱憑證。"},gemini:{title:"Gemini",description:"由 Daemon 路由的 Google Gemini 訂閱憑證。"},opencodego:{title:"OpenCodeGo",description:"由 Daemon 路由的靜態 API 金鑰憑證。"}},authMethodLabel:"授權方式",authMethodDesc:{oauth:"透過瀏覽器登入;Daemon 會擷取並儲存權杖。",manual:"貼入已取得的權杖。它將被儲存,不會回顯。"},actions:{authorize:"授權",enterToken:"輸入權杖",refresh:"重新整理"},accounts:{addAccount:"新增帳號"},detail:{authMethod:"授權方式",subscriptionLevel:"訂閱等級",expiresAt:"到期時間",lastRefreshed:"上次更新",label:"帳號標籤",labelPlaceholder:"為此帳號命名",saveLabel:"儲存標籤"},oauthFlow:{step1:{title:"開啟授權頁面",desc:"在瀏覽器中開啟登入頁面。"},step2:{title:"授權存取",desc:"登入並核准此提供者的存取權限。"},step3:{title:"複製授權碼",desc:"核准後,頁面將顯示授權碼。"},step4:{title:"貼上授權碼",desc:"將授權碼貼至下方以完成。授權碼僅傳送至 Daemon——簽發的權杖不會顯示。"},authorize:"完成登入",showUrl:"顯示授權 URL"},manual:{title:"貼上憑證",description:"貼入已取得的權杖。欄位僅限此提供者接受的內容;權杖將被儲存,不會回顯。",accessTokenPlaceholder:"貼上存取權杖",refreshTokenPlaceholder:"貼上更新權杖(選填)",hint:"權杖將傳送至 Daemon 並加密儲存,不會回顯。"},openCodeGo:{apiKeyRequired:"需要 API 金鑰。",apiKeyPlaceholder:"貼上 API 金鑰",baseUrlPlaceholder:"https://…(選填)",zenBaseUrlPlaceholder:"https://…(選填)"},info:{title:"關於訂閱帳號",description:"權杖寫入 Daemon 後用於驗證上游請求。它們以加密方式儲存,不會回顯。移除帳號將刪除其儲存的憑證。"},rename:{failed:"無法重新命名帳號。"},refresh:{failed:"無法更新權杖。"},errors:{requestFailed:"請求失敗,請再試一次。"},syncWarning:{"external-divergent":"外部 CLI 登入檔案中的憑證比此帳號更新,已儲存的權杖可能無法再重新整理——請立即重新整理或重新登入。","external-not-rotated":"重新整理失敗,且外部 CLI 中保存的是同一個已過期憑證。請重新登入。","duplicate-token":"另一個帳號與此帳號共用同一憑證,重新整理任一帳號都會使另一個失效。"},importExternal:{detected:"偵測到本機已有 {{name}} CLI 登入。",hint:"匯入後由本程式負責保鮮:每次重新整理權杖都會同步更新 CLI 登入檔案,終端機裡的 CLI 保持登入不中斷。",button:"匯入現有 CLI 登入"}},Aj={title:"Code CLI",description:"將程式碼 CLI 指向 Daemon 的對外代理。此頁面為唯讀——無需在此進行任何設定。",copy:"複製",copied:"已複製",baseUrl:{title:"Daemon 基礎 URL",description:"您的 CLI 所連線的代理位址。",label:"基礎 URL"},token:{title:"驗證",hint:"管理路由請傳送 'Authorization: Bearer <您的管理權杖>'。管理權杖在 Daemon 中設定(設定檔或環境變數)——此處不會顯示。"},examples:{title:"啟動環境範例",keyNote:"請使用在 API 服務頁面建立的對外存取金鑰——而非管理權杖。",anthropic:"Anthropic 格式 CLI",openai:"OpenAI 格式 CLI"},launchDescription:"在終端機中啟動程式碼 CLI,並指向此 Daemon。Daemon 會注入重新導向的環境變數並為您啟動 CLI。",refresh:"重新整理",loading:"正在偵測 CLI…",cli:{installed:"已安裝",notFound:"找不到",notFoundHint:"此 CLI 不在 Daemon 主機的 PATH 中。請先安裝,然後重新整理。",install:"安裝",installing:"安裝中…",installingHint:"正在 Daemon 主機上安裝,可能需要一點時間。",launch:"啟動",launchTitle:"啟動 {{name}}",launchDescription:"在 Daemon 主機上開啟新的終端機視窗執行此 CLI,並透過 Daemon 代理路由。可選填工作目錄。",cwdLabel:"工作目錄",cwdPlaceholder:"/path/to/your/project",runningVia:"執行中 · {{provider}} / {{model}}",stop:"停止"},manual:{title:"手動設定",description:"想自行執行 CLI?請使用這些環境變數將其指向 Daemon。",show:"顯示",hide:"隱藏"}},Cj={probing:"正在檢查 Daemon…",spawning:"正在啟動 Daemon…",failed:"Daemon 無法啟動",failedHint:"請確認已安裝 Node.js 且 Daemon 已建置(dist 存在),或將 OMNICROSS_DAEMON_ENTRY 設定為 Daemon 的 cli.js 路徑。"},xj={title:"設定",description:"桌面應用程式偏好設定。",desktopOnly:"啟動與系統匣選項僅適用於桌面應用程式。",startup:{title:"啟動",autoLaunch:"登入時自動啟動",autoLaunchHint:"登入系統時自動啟動 Omnicross。",startMinimized:"啟動時最小化至系統匣",startMinimizedHint:"在背景啟動,不開啟視窗。"},tray:{title:"系統匣",minimizeOnClose:"關閉時最小化至系統匣",minimizeOnCloseHint:"關閉視窗時隱藏至系統匣,而非結束應用程式。"},language:{title:"語言",label:"介面語言"}},zj={title:"用量統計",description:"守護程序處理的請求的 Token 與費用統計。",rangeToday:"今天",range7d:"最近 7 天",range30d:"最近 30 天",rangeCustom:"自訂",from:"開始",to:"結束",totalCost:"總費用",cacheSavings:"快取節省",events:"請求數",inputTokens:"輸入 Token",outputTokens:"輸出 Token",cacheReadTokens:"快取讀取",cacheWriteTokens:"快取寫入",reasoningTokens:"推理 Token",byModel:"依模型",byApiKey:"依 API 金鑰",provider:"供應商",model:"模型",cost:"費用",apiKey:"API 金鑰",unpriced:"無價格",unpricedHint:"此模型沒有價格條目 — 請在「模型價格」頁面新增。",unattributed:"未歸屬",unattributedHint:"未關聯到特定 API 金鑰的請求。在按金鑰歸屬記錄上線之前,這是正常現象。",empty:"此時間範圍內沒有請求。",invalidRange:"請選擇有效的日期範圍。"},Ij={title:"模型價格",description:"用於計算請求費用的每模型 Token 價格(美元 / 每 100 萬 Token)。",search:"搜尋供應商或模型…",fetchLatest:"取得最新價格",fetching:"取得中…",addEntry:"新增條目",provider:"供應商",model:"模型",inputPrice:"輸入",outputPrice:"輸出",cacheReadPrice:"快取讀取",cacheWritePrice:"快取寫入",source:"來源",updated:"更新時間",userEdited:"已編輯",edit:"編輯",deleteTitle:"刪除此價格條目?",empty:"價格表為空。",emptyHint:"取得最新價格以填入表格。",noMatches:"沒有符合的條目。",saved:"價格條目已儲存。",saveFailed:"儲存失敗:{{message}}",deleteFailed:"刪除失敗:{{message}}",alreadyDeleted:"此條目已不存在。",fetchApplied:"已從來源更新 {{count}} 個條目。",fetchFailed:"取得失敗:{{message}}",requiredId:"必填",invalidPrice:"請輸入非負數字",conflictTitle:"解決價格衝突",conflictHint:"這些條目既被你編輯過,又在來源處發生了變化。請逐列選擇保留你的值(略過)或採用來源值(覆寫)。",current:"目前",incoming:"來源值",overwrite:"覆寫",skip:"略過",overwriteAll:"全部覆寫",skipAll:"全部略過",applyResolutions:"套用",resolved:"已覆寫 {{overwritten}} 項,略過 {{skipped}} 項。",resolvedWithStale:"已覆寫 {{overwritten}} 項,略過 {{skipped}} 項。{{stale}} 項在此期間已被修改,保持不變。",refreshFailed:"變更已生效,但重新整理列表失敗:{{message}}",sourceBuiltin:"內建",sourceLitellm:"LiteLLM",sourceUser:"使用者"},Sj={providerSettings:mj,apiMode:gj,presetName:hj,common:fj,mediaSettings:vj,appLocal:kj,nav:yj,apiService:bj,accounts:Pj,codeCli:Aj,daemonStatus:Cj,settings:xj,usageStats:zj,pricing:Ij},xh="omnicross.lang",zh={ar:{translation:dA},bg:{translation:xA},cs:{translation:UA},da:{translation:eC},de:{translation:hC},el:{translation:jC},en:{translation:$C},"es-419":{translation:rx},"es-ES":{translation:Px},fi:{translation:Ex},fr:{translation:Yx},hu:{translation:pz},id:{translation:Sz},it:{translation:Bz},ja:{translation:nI},ko:{translation:kI},ms:{translation:LI},nb:{translation:WI},nl:{translation:dS},pl:{translation:xS},"pt-BR":{translation:US},"pt-PT":{translation:ew},ro:{translation:hw},ru:{translation:jw},sv:{translation:$w},th:{translation:rT},tr:{translation:PT},uk:{translation:ET},vi:{translation:YT},zh:{translation:pj},"zh-Hant":{translation:Sj}},wj=[{code:"en",nativeName:"English"},{code:"zh",nativeName:"简体中文"},{code:"zh-Hant",nativeName:"繁體中文"},{code:"ja",nativeName:"日本語"},{code:"ko",nativeName:"한국어"},{code:"fr",nativeName:"Français"},{code:"de",nativeName:"Deutsch"},{code:"it",nativeName:"Italiano"},{code:"es-ES",nativeName:"Español (España)"},{code:"es-419",nativeName:"Español (Latinoamérica)"},{code:"pt-BR",nativeName:"Português (Brasil)"},{code:"pt-PT",nativeName:"Português (Portugal)"},{code:"nl",nativeName:"Nederlands"},{code:"da",nativeName:"Dansk"},{code:"sv",nativeName:"Svenska"},{code:"nb",nativeName:"Norsk bokmål"},{code:"fi",nativeName:"Suomi"},{code:"pl",nativeName:"Polski"},{code:"cs",nativeName:"Čeština"},{code:"hu",nativeName:"Magyar"},{code:"ro",nativeName:"Română"},{code:"bg",nativeName:"Български"},{code:"ru",nativeName:"Русский"},{code:"uk",nativeName:"Українська"},{code:"el",nativeName:"Ελληνικά"},{code:"tr",nativeName:"Türkçe"},{code:"ar",nativeName:"العربية"},{code:"th",nativeName:"ไทย"},{code:"vi",nativeName:"Tiếng Việt"},{code:"id",nativeName:"Bahasa Indonesia"},{code:"ms",nativeName:"Bahasa Melayu"}];function No(e){return Object.prototype.hasOwnProperty.call(zh,e)}function Tj(e){const t=e.toLowerCase();if(t.startsWith("zh"))return t.includes("tw")||t.includes("hk")||t.includes("mo")||t.includes("hant")?"zh-Hant":"zh";if(t.startsWith("pt"))return t.startsWith("pt-pt")?"pt-PT":"pt-BR";if(t.startsWith("es"))return t==="es"||t.startsWith("es-es")?"es-ES":"es-419";if(t.startsWith("no")||t.startsWith("nn"))return"nb";const a=t.split("-")[0];return No(a)?a:null}function jj(){try{const t=localStorage.getItem(xh);if(t&&No(t))return t}catch{}const e=typeof navigator<"u"?navigator.language:"en";return Tj(e)??"en"}function Mj(){return ie.isInitialized||ie.use(ny).init({resources:zh,lng:jj(),fallbackLng:"en",interpolation:{escapeValue:!1},returnNull:!1}),ie}function Nj(e){ie.changeLanguage(e);try{localStorage.setItem(xh,e)}catch{}}function le(e,t,a){typeof a=="string"&&a.length>0&&(e[t]=a)}function Lj(e){const t={authMethod:e.authMethod,status:e.status};return e.subscriptionLevel&&(t.subscriptionLevel=e.subscriptionLevel),le(t,"accessToken",e.accessToken),le(t,"refreshToken",e.refreshToken),le(t,"expiresAt",e.expiresAt),le(t,"setupTokenExpiresAt",e.setupTokenExpiresAt),le(t,"lastRefreshedAt",e.lastRefreshedAt),le(t,"errorMessage",e.errorMessage),Array.isArray(e.scopes)&&e.scopes.length>0&&(t.scopes=e.scopes),typeof e.isSetupToken=="boolean"&&(t.isSetupToken=e.isSetupToken),t}function Rj(e){const t={authMethod:e.authMethod,status:e.status};return le(t,"accessToken",e.accessToken),le(t,"refreshToken",e.refreshToken),le(t,"idToken",e.idToken),le(t,"expiresAt",e.expiresAt),le(t,"accountId",e.accountId),le(t,"email",e.email),le(t,"organizationId",e.organizationId),le(t,"lastRefreshedAt",e.lastRefreshedAt),le(t,"errorMessage",e.errorMessage),t}function Dj(e){const t={authMethod:e.authMethod,status:e.status};return le(t,"accessToken",e.accessToken),le(t,"refreshToken",e.refreshToken),le(t,"expiresAt",e.expiresAt),le(t,"lastRefreshedAt",e.lastRefreshedAt),le(t,"errorMessage",e.errorMessage),t}function Ej(e){const t={authMethod:"manual",status:e.status};return le(t,"apiKey",e.apiKey),le(t,"baseUrl",e.baseUrl),le(t,"zenBaseUrl",e.zenBaseUrl),le(t,"lastRefreshedAt",e.lastRefreshedAt),le(t,"errorMessage",e.errorMessage),t}function Bu(e){switch(e.providerId){case"claude":return Lj(e.input);case"codex":return Rj(e.input);case"gemini":return Dj(e.input);case"opencodego":return Ej(e.input)}}function Oj(){return{async list(){try{return await H.get("/accounts")}catch{return{accounts:[],providerAccounts:{claude:[],codex:[],gemini:[],opencodego:[]}}}},async writeTokens(e){try{const t=Bu(e);return{success:!0,status:(await H.put(`/accounts/${encodeURIComponent(e.providerId)}`,t)).account}}catch(t){return{success:!1,message:t instanceof Error?t.message:"failed to write tokens"}}},async appendTokens(e,t){try{const a=Bu(e);return t&&t.length>0&&(a.label=t),{success:!0,status:(await H.post(`/accounts/${encodeURIComponent(e.providerId)}/accounts`,a)).account}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to add account"}}},async refreshProvider(e){try{const t=await H.post(`/accounts/${encodeURIComponent(e)}/refresh`);return{success:!0,ok:t.ok,status:t.account}}catch(t){return{success:!1,ok:!1,message:t instanceof Error?t.message:"failed to refresh token"}}},async renameAccount(e,t,a){try{return await H.post(`/accounts/${encodeURIComponent(e)}/${encodeURIComponent(t)}/label`,{label:a}),{success:!0}}catch(n){return{success:!1,message:n instanceof Error?n.message:"failed to rename account"}}},async setActive(e,t){try{return await H.put(`/accounts/${encodeURIComponent(e)}/active`,{id:t}),{success:!0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to set active account"}}},async removeAccount(e,t){try{return await H.delete(`/accounts/${encodeURIComponent(e)}/${encodeURIComponent(t)}`),{success:!0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to remove account"}}},async clearProvider(e){try{return await H.delete(`/accounts/${encodeURIComponent(e)}`),{success:!0}}catch(t){return{success:!1,message:t instanceof Error?t.message:"failed to clear provider"}}},async startOAuth(e){return H.post(`/accounts/${encodeURIComponent(e)}/oauth/start`)},async completeOAuth(e,t){try{const a={sessionId:t.sessionId,code:t.code};return t.label&&t.label.length>0&&(a.label=t.label),{success:!0,status:(await H.post(`/accounts/${encodeURIComponent(e)}/oauth/complete`,a)).account}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to complete sign-in"}}},async importExternalCli(e,t){try{const a={};return t&&t.length>0&&(a.label=t),await H.post(`/accounts/${encodeURIComponent(e)}/import-external`,a),{success:!0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to import CLI login"}}},async pollCodexOAuth(e){return H.get(`/accounts/codex/oauth/${encodeURIComponent(e)}/status`)}}}function Kj(){return{async list(){try{return(await H.get("/cli")).clis}catch{return[]}},async install(e){try{return await H.post(`/cli/${encodeURIComponent(e)}/install`,{}),{success:!0}}catch(t){return{success:!1,message:t instanceof Error?t.message:"failed to install CLI"}}},async launch(e,t){try{return{success:!0,...await H.post(`/cli/${encodeURIComponent(e)}/launch`,t??{})}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to launch CLI"}}},async sessions(){try{return(await H.get("/cli/sessions")).sessions}catch{return[]}},async stop(e){try{return await H.delete(`/cli/sessions/${encodeURIComponent(e)}`),{success:!0}}catch(t){return{success:!1,message:t instanceof Error?t.message:"failed to stop launch"}}}}}function Uj(e){return e==="gemini"?"google":e}function Ll(e){return e==="google"?"gemini":e==="anthropic"?"anthropic":"openai"}function Za(e){const t=Uj(e.apiFormat),a={id:e.id,name:e.name??e.id,apiFormat:t,api_base_url:e.baseUrl,api_key:"",hasKey:e.hasApiKey,models:e.models??[],enabled:e.enabled!==!1};return e.isOfficial!==void 0&&(a.isOfficial=e.isOfficial),e.apiVersion!==void 0&&(a.apiVersion=e.apiVersion),e.maxConcurrency!==void 0&&(a.maxConcurrency=e.maxConcurrency),e.modelsEndpoint!==void 0&&(a.modelsEndpoint=e.modelsEndpoint),e.modelConfigs!==void 0&&(a.modelConfigs=e.modelConfigs),e.transformer!==void 0&&(a.transformer=e.transformer),e.codingPlan!==void 0&&(a.codingPlan={enabled:e.codingPlan.enabled,baseUrl:e.codingPlan.baseUrl,apiKey:"",note:e.codingPlan.note,hasApiKey:e.codingPlan.hasApiKey}),e.apiModes!==void 0&&(a.apiModes=e.apiModes.map(n=>({id:n.id,label:n.label,baseUrl:n.baseUrl,apiKeyPrefix:n.apiKeyPrefix,note:n.note}))),e.selectedApiModeId!==void 0&&(a.selectedApiModeId=e.selectedApiModeId),a}function Vu(e){const t={};if(e.id!==void 0&&(t.id=e.id),typeof e.name=="string"&&e.name.length>0&&(t.name=e.name),e.apiFormat!==void 0&&(t.apiFormat=Ll(e.apiFormat)),e.api_base_url!==void 0&&(t.baseUrl=e.api_base_url),e.models!==void 0&&(t.models=e.models),e.modelConfigs!==void 0&&(t.modelConfigs=e.modelConfigs),typeof e.api_key=="string"&&e.api_key.trim().length>0&&(t.apiKey=e.api_key),typeof e.enabled=="boolean"&&(t.enabled=e.enabled),typeof e.isOfficial=="boolean"&&(t.isOfficial=e.isOfficial),typeof e.apiVersion=="string"?t.apiVersion=e.apiVersion:e.apiVersion===null&&(t.apiVersion=null),typeof e.modelsEndpoint=="string"?t.modelsEndpoint=e.modelsEndpoint:e.modelsEndpoint===null&&(t.modelsEndpoint=null),typeof e.maxConcurrency=="number"?t.maxConcurrency=e.maxConcurrency:e.maxConcurrency===null&&(t.maxConcurrency=null),e.transformer!==void 0&&(t.transformer=e.transformer),e.codingPlan){const a={enabled:!!e.codingPlan.enabled};typeof e.codingPlan.baseUrl=="string"&&(a.baseUrl=e.codingPlan.baseUrl),typeof e.codingPlan.note=="string"&&(a.note=e.codingPlan.note),typeof e.codingPlan.apiKey=="string"&&e.codingPlan.apiKey.trim().length>0&&(a.apiKey=e.codingPlan.apiKey),t.codingPlan=a}return typeof e.selectedApiModeId=="string"?t.selectedApiModeId=e.selectedApiModeId:e.selectedApiModeId===null&&(t.selectedApiModeId=null),t}function $n(e){return{success:!0,provider:e}}function _n(e){return{success:!1,message:e instanceof Error?e.message:"request failed"}}function Hj(e,t,a){if(t.unsupportedFormat)return{success:!1,source:"network",endpoint:e,models:[],unsupportedFormat:!0,error:a};if(t.error)return{success:!1,source:"network",endpoint:e,models:[],error:t.error};const n=(t.models??[]).map(o=>({id:o,name:o}));return{success:!0,source:"network",endpoint:e,models:n,fetchedAt:new Date().toISOString()}}function Fj(e){return{async getProviders(){return((await H.get("/providers")).providers??[]).map(Za)},async getProvider(t){try{const n=((await H.get("/providers")).providers??[]).find(o=>o.id===t);return n?Za(n):null}catch{return null}},async revealProviderKey(t){try{return{success:!0,apiKey:(await H.get(`/providers/${encodeURIComponent(t)}/reveal-key`)).apiKey??""}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to reveal key"}}},async addProvider(t){try{const a=Vu(t);a.id||(a.id=Bj(t.name)||`provider-${Date.now()}`);const n=await H.post("/providers",a);return $n(Za(n.provider))}catch(a){return a instanceof cr&&a.status===409?{success:!1,message:a.message}:_n(a)}},async updateProvider(t){try{const a=Vu(t);if(delete a.id,a.apiFormat===void 0||a.baseUrl===void 0){const o=await this.getProvider(t.id);o&&(a.apiFormat===void 0&&(a.apiFormat=Ll(o.apiFormat)),a.baseUrl===void 0&&(a.baseUrl=o.api_base_url))}const n=await H.put(`/providers/${encodeURIComponent(t.id)}`,a);return $n(Za(n.provider))}catch(a){return _n(a)}},async deleteProvider(t){try{return await H.delete(`/providers/${encodeURIComponent(t)}`),{success:!0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"delete failed"}}},async toggleProvider(t,a){try{const n=await this.getProvider(t);if(!n)return{success:!1,message:`provider '${t}' not found`};const o=await H.put(`/providers/${encodeURIComponent(t)}`,{apiFormat:Ll(n.apiFormat),baseUrl:n.api_base_url,enabled:a});return $n(Za(o.provider))}catch(n){return _n(n)}},async reorderProviders(t){try{return await H.post("/providers/reorder",{order:t}),{success:!0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"reorder failed"}}},async resetProvider(t){try{const a=await this.getProvider(t);return a?$n(a):{success:!1,message:`provider '${t}' not found`}}catch(a){return _n(a)}},async discoverModels(t,a){const n=`/providers/${t}/discover-models`;try{const o=await H.post(`/providers/${encodeURIComponent(t)}/discover-models`);return Hj(n,o,e)}catch(o){return{success:!1,source:"network",endpoint:n,models:[],error:o instanceof Error?o.message:"discovery failed"}}},async testModel(t,a){try{return await H.post(`/providers/${encodeURIComponent(t)}/test`,{model:a})}catch(n){return{ok:!1,message:n instanceof Error?n.message:"test failed"}}},async addFromPreset({presetId:t,apiKey:a,enabled:n}){try{const i=(await this.getPresets()).find(d=>d.presetId===t||d.id===t);if(!i)return{success:!1,message:`preset '${t}' not found`};const s={id:i.id,apiFormat:i.apiFormat,baseUrl:i.baseUrl,models:i.models??[]};typeof a=="string"&&a.trim().length>0&&(s.apiKey=a),typeof n=="boolean"&&(s.enabled=n);const l=await H.post("/providers",s);return $n(Za(l.provider))}catch(o){return o instanceof cr&&o.status===409?{success:!1,message:o.message}:_n(o)}},async getApiKeys(t){try{return((await H.get(`/providers/${encodeURIComponent(t)}/keys`)).keys??[]).map((n,o)=>Cs(t,n,o))}catch{return[]}},async getKeyHealth(t){try{const a=await H.get(`/providers/${encodeURIComponent(t)}/keys`),n={};for(const o of a.keys??[])o.health?.cooldown&&(n[o.id]={until:o.health.cooldown.until,errors:o.health.cooldown.errors,lastStatus:o.health.cooldown.lastStatus});return n}catch{return{}}},async addApiKey(t){try{const n=(await H.post(`/providers/${encodeURIComponent(t.providerId)}/keys`,{label:t.label,weight:t.weight,enabled:t.enabled,apiKey:t.apiKey})).keys??[],o=n[n.length-1];return{success:!0,entry:o?Cs(t.providerId,o,n.length-1):void 0}}catch(a){return{success:!1,message:a instanceof Error?a.message:"add key failed"}}},async updateApiKey(t,a,n){try{const o={};n.label!==void 0&&(o.label=n.label),n.weight!==void 0&&(o.weight=n.weight),n.enabled!==void 0&&(o.enabled=n.enabled),typeof n.apiKey=="string"&&n.apiKey.trim().length>0&&(o.apiKey=n.apiKey);const s=(await H.put(`/providers/${encodeURIComponent(t)}/keys/${encodeURIComponent(a)}`,o)).keys??[],l=s.findIndex(c=>c.id===a);return{success:!0,entry:l>=0?Cs(t,s[l],l):void 0}}catch(o){return{success:!1,message:o instanceof Error?o.message:"update key failed"}}},async deleteApiKey(t,a){try{return await H.delete(`/providers/${encodeURIComponent(t)}/keys/${encodeURIComponent(a)}`),{success:!0}}catch(n){return{success:!1,message:n instanceof Error?n.message:"delete key failed"}}},async toggleApiKey(t,a,n){try{return await H.post(`/providers/${encodeURIComponent(t)}/keys/${encodeURIComponent(a)}/enabled`,{enabled:n}),{success:!0}}catch(o){return{success:!1,message:o instanceof Error?o.message:"toggle key failed"}}},async getPresets(){try{return(await H.get("/presets")).presets??[]}catch{return[]}}}}function Cs(e,t,a){const n=t.health?.autoDisabled;return{id:t.id,providerId:e,label:t.label,apiKey:"",hasKey:!!t.apiKeyMasked,keyHint:t.apiKeyMasked||void 0,enabled:t.enabled,weight:t.weight,sortOrder:a,disabledReason:n?.reason==="auth_failure"?"auth_failure":n?"auto_disabled":null,lastErrorStatus:n?.status??null,lastErrorAt:n?.at??null}}function Bj(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Vj(){return{async exportPack(e){try{const t=await H.post("/export",{passphrase:e});return{success:!0,pack:t.pack,version:t.version}}catch(t){return{success:!1,message:t instanceof Error?t.message:"export failed"}}},async importPack(e){try{const t={blob:e.blob,passphrase:e.passphrase};return e.mode&&(t.mode=e.mode),{success:!0,counts:await H.post("/import",t)}}catch(t){return{success:!1,message:t instanceof Error?t.message:"import failed"}}}}}function Gn(e,t){return{success:!1,message:e instanceof Error?e.message:t}}function qj(e,t){let a=!1;const n=e.endpoints.map(o=>o.endpoint===t.endpoint?(a=!0,t):o);return a||n.push(t),n}function $j(){let e=null;return{async getConfig(){try{const t=await H.get("/server");return e=t.server,t.server}catch{return null}},async getStatus(){try{return await H.get("/status")}catch{return null}},async setEnabled(t){try{return e=(await H.put("/server",{enabled:t})).server,{success:!0}}catch(a){return Gn(a,"failed to update server state")}},async setNetworkBinding(t){try{return e=(await H.put("/server",{networkBinding:t})).server,{success:!0}}catch(a){return Gn(a,"failed to update network binding")}},async updateEndpoint(t){try{let a=e;try{const i=await H.get("/server");a=i.server,e=i.server}catch{}if(!a)return{success:!1,message:"server config not loaded"};const n=qj(a,t);return e=(await H.put("/server",{endpoints:n})).server,{success:!0}}catch(a){return Gn(a,"failed to update endpoint routing")}},async listKeys(){try{return(await H.get("/keys")).keys??[]}catch{return[]}},async createKey(t){try{return{success:!0,created:await H.post("/keys",{name:t})}}catch(a){return{success:!1,message:a instanceof Error?a.message:"failed to create key"}}},async revokeKey(t){try{return(await H.post(`/keys/${encodeURIComponent(t)}/revoke`)).ok?{success:!0}:{success:!1,message:"key not found"}}catch(a){return Gn(a,"failed to revoke key")}},async setKeyEnabled(t,a){try{return(await H.post(`/keys/${encodeURIComponent(t)}/enabled`,{enabled:a})).ok?{success:!0}:{success:!1,message:"key not found"}}catch(n){return Gn(n,"failed to update key state")}}}}function _j(){const t=ie.t.bind(ie)("appLocal.discoveryUnsupportedFormat");return typeof t=="string"?t:"Model discovery is not supported for this provider format yet."}const Gj=Fj(_j()),Wj=$j(),Zj=Oj(),Qj=Vj(),Yj=Kj(),K={llmConfig:Gj,apiService:Wj,accounts:Zj,migration:Qj,cli:Yj},Xj={accounts:[],providerAccounts:{claude:[],codex:[],gemini:[],opencodego:[]}};function Jj(){const[e,t]=g.useState(!0),[a,n]=g.useState(Xj),[o,i]=g.useState(!1),[s,l]=g.useState(null),d=g.useCallback(async()=>{const I=await K.accounts.list();n(I)},[]);g.useEffect(()=>{let I=!1;return(async()=>{t(!0);const C=await K.accounts.list();I||(n(C),t(!1))})(),()=>{I=!0}},[]);const c=g.useCallback(async I=>{i(!0),l(null);try{const C=await K.accounts.writeTokens(I);return C.success?(await d(),{success:!0}):(l(C.message??"request failed"),{success:!1,message:C.message})}finally{i(!1)}},[d]),u=g.useCallback(async(I,C)=>{i(!0),l(null);try{const S=await K.accounts.appendTokens(I,C);return S.success?(await d(),{success:!0}):(l(S.message??"request failed"),{success:!1,message:S.message})}finally{i(!1)}},[d]),p=g.useCallback(async I=>{i(!0),l(null);try{const C=await I();C.success?await d():l(C.message??"request failed")}finally{i(!1)}},[d]),m=g.useCallback(async(I,C)=>{await p(()=>K.accounts.setActive(I,C))},[p]),f=g.useCallback(async(I,C)=>{await p(()=>K.accounts.removeAccount(I,C))},[p]),P=g.useCallback(async I=>{await p(()=>K.accounts.clearProvider(I))},[p]),y=g.useCallback(async(I,C,S)=>{i(!0),l(null);try{const L=await K.accounts.renameAccount(I,C,S);return L.success?(await d(),{success:!0}):(l(L.message??"request failed"),{success:!1,message:L.message})}finally{i(!1)}},[d]),A=g.useCallback(async I=>{i(!0),l(null);try{const C=await K.accounts.refreshProvider(I);return C.success||l(C.message??"request failed"),await d(),C}finally{i(!1)}},[d]),h=g.useCallback(async I=>{i(!0),l(null);try{return await K.accounts.startOAuth(I)}catch(C){return l(C instanceof Error?C.message:"failed to start sign-in"),null}finally{i(!1)}},[]),k=g.useCallback(async(I,C)=>{i(!0),l(null);try{const S=await K.accounts.completeOAuth(I,C);return S.success?(await d(),{success:!0}):(l(S.message??"request failed"),{success:!1,message:S.message})}finally{i(!1)}},[d]),v=g.useCallback(I=>K.accounts.pollCodexOAuth(I),[]),b=g.useCallback(async I=>{i(!0),l(null);try{const C=await K.accounts.importExternalCli(I);return C.success?(await d(),{success:!0}):(l(C.message??"request failed"),{success:!1,message:C.message})}finally{i(!1)}},[d]),z=g.useCallback(()=>l(null),[]);return{loading:e,data:a,busy:o,error:s,clearError:z,refresh:d,writeTokens:c,appendTokens:u,setActive:m,removeAccount:f,renameAccount:y,refreshProvider:A,clearProvider:P,startOAuth:h,completeOAuth:k,pollCodexOAuth:v,importExternalCli:b}}function eM(){const e=$(),t=Jj(),{loading:a,data:n}=t,o=i=>{const s=n.providerAccounts[i.providerId]??[];return i.providerId==="opencodego"?r.jsx(zP,{entry:i,accounts:s,accountsApi:t},i.providerId):r.jsx(CP,{entry:i,accounts:s,accountsApi:t},i.providerId)};return r.jsx("div",{className:"flex h-full flex-col overflow-hidden",children:r.jsx(ha,{className:"flex-1",children:r.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 px-6 py-6",children:[r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Mk,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{children:[r.jsx("h2",{className:"text-base font-semibold text-foreground",children:e("accounts.title")}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("accounts.description")})]})]})}),a?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("accounts.loading")}):n.accounts.length===0?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("accounts.empty")}):r.jsx("div",{className:"space-y-4",children:n.accounts.map(o)}),r.jsxs("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:[r.jsx("h3",{className:"mb-2 text-base font-semibold text-foreground",children:e("accounts.info.title")}),r.jsx("p",{className:"text-sm text-muted-foreground",children:e("accounts.info.description")})]})]})})})}const Jt=g.forwardRef(({icon:e,label:t,description:a,children:n,variant:o="default",className:i},s)=>{const l=o==="compact";return r.jsxs("div",{ref:s,className:G("flex items-center justify-between rounded-md border border-border/60 bg-surface-0/60",l?"gap-2 p-2":"gap-3 px-3 py-2",i),children:[r.jsxs("div",{className:G("min-w-0",e&&"flex items-center gap-3"),children:[e?r.jsx("span",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-border bg-surface-0/70 wallpaper-blur text-text-muted",children:r.jsx(e,{className:"h-4 w-4",strokeWidth:1.5})}):null,r.jsxs("div",{className:"min-w-0",children:[r.jsx("div",{className:"text-sm font-medium text-foreground",children:t}),a?r.jsx("div",{className:"text-xs text-text-muted",children:a}):null]})]}),n?r.jsx("div",{className:"shrink-0",children:n}):null]})});Jt.displayName="SettingRow";const tM=g.forwardRef(({label:e,description:t,valueDisplay:a,children:n,className:o},i)=>r.jsxs("div",{ref:i,className:G("rounded-md border border-border/60 bg-surface-0/60 px-3 py-2 space-y-1.5",o),children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{className:"min-w-0",children:[r.jsx("div",{className:"text-sm font-medium text-foreground",children:e}),t?r.jsx("div",{className:"text-xs text-text-muted",children:t}):null]}),r.jsx("span",{className:"text-sm text-muted-foreground tabular-nums w-12 text-right shrink-0",children:a})]}),n]}));tM.displayName="SettingSliderRow";const me=g.forwardRef(({checked:e,defaultChecked:t,onCheckedChange:a,disabled:n,className:o,id:i,name:s,...l},d)=>{const[c,u]=g.useState(t??!1),p=e!==void 0,m=p?e:c,f=()=>{if(n)return;const P=!m;p||u(P),a?.(P)};return r.jsx("button",{ref:d,type:"button",role:"switch","aria-checked":m,"data-state":m?"checked":"unchecked",disabled:n,id:i,name:s,onClick:f,className:G("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background","disabled:cursor-not-allowed disabled:opacity-50",m?"bg-primary":"bg-input",o),...l,children:r.jsx("span",{"data-state":m?"checked":"unchecked",className:G("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform",m?"translate-x-4":"translate-x-0")})})});me.displayName="Switch";const xs="__none__";function aM(e){return e==="messages"||e==="responses"}function nM({endpoint:e,modelOptions:t,busy:a,onChange:n}){const o=$(),i=aM(e.endpoint),s=g.useMemo(()=>t.map(u=>({value:u.value,label:u.label})),[t]),l=g.useMemo(()=>[{value:xs,label:o("apiService.endpoint.noVisionModel")},...s],[s,o]),d=(e.backgroundModelIds??[]).join(", "),c=u=>{const p=u.split(",").map(m=>m.trim()).filter(m=>m.length>0);n({...e,backgroundModelIds:p})};return r.jsxs("div",{className:"rounded-md border border-border/60 bg-surface-0/60 p-4 space-y-3",children:[r.jsxs("div",{className:"flex items-center justify-between gap-3",children:[r.jsx("div",{className:"text-sm font-semibold uppercase tracking-wide text-foreground",children:o(`apiService.endpoint.name.${e.endpoint}`)}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"text-xs text-muted-foreground",children:o("apiService.endpoint.useSubscription")}),r.jsx(me,{checked:i?e.useSubscription:!1,disabled:a||!i,onCheckedChange:u=>n({...e,useSubscription:u}),"aria-label":o("apiService.endpoint.useSubscription")})]})]}),i?null:r.jsx("p",{className:"text-xs text-muted-foreground",children:o("apiService.endpoint.subscriptionUnsupported")}),r.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:o("apiService.endpoint.defaultModel")}),r.jsx(Lt,{value:e.defaultModel,options:s,placeholder:o("apiService.endpoint.modelPlaceholder"),disabled:a,onChange:u=>n({...e,defaultModel:u}),size:"sm"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:o("apiService.endpoint.backgroundModel")}),r.jsx(Lt,{value:e.backgroundModel,options:s,placeholder:o("apiService.endpoint.modelPlaceholder"),disabled:a,onChange:u=>n({...e,backgroundModel:u}),size:"sm"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:o("apiService.endpoint.visionModel")}),r.jsx(Lt,{value:e.visionModel?e.visionModel:xs,options:l,placeholder:o("apiService.endpoint.noVisionModel"),disabled:a,onChange:u=>{const p={...e};u===xs?delete p.visionModel:p.visionModel=u,n(p)},size:"sm"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:o("apiService.endpoint.backgroundModelIds")}),r.jsx(V,{density:"compact",value:d,placeholder:o("apiService.endpoint.backgroundModelIdsPlaceholder"),disabled:a,onChange:u=>c(u.target.value),onBlur:u=>c(u.target.value)})]})]})]})}function oM(e){const t=[];for(const a of e)for(const n of a.models??[])t.push({value:`${a.id},${n}`,label:`${a.id} / ${n}`});return t}function iM(){const[e,t]=g.useState(!0),[a,n]=g.useState(null),[o,i]=g.useState(null),[s,l]=g.useState([]),[d,c]=g.useState([]),[u,p]=g.useState(!1),[m,f]=g.useState(null),[P,y]=g.useState(null),A=g.useCallback(async()=>{const[T,M,D]=await Promise.all([K.apiService.getConfig(),K.apiService.getStatus(),K.apiService.listKeys()]);n(T),i(M),l(D)},[]);g.useEffect(()=>{let T=!1;return(async()=>{t(!0);const[M,D,Q,W]=await Promise.all([K.apiService.getConfig(),K.apiService.getStatus(),K.apiService.listKeys(),K.llmConfig.getProviders().catch(()=>[])]);T||(n(M),i(D),l(Q),c(W),t(!1))})(),()=>{T=!0}},[]);const h=g.useCallback(async T=>{p(!0),f(null);try{const M=await T();return M.success?(await A(),!0):(f(M.message??"request failed"),!1)}finally{p(!1)}},[A]),k=g.useCallback(async T=>{await h(()=>K.apiService.setEnabled(T))},[h]),v=g.useCallback(async T=>{await h(()=>K.apiService.setNetworkBinding(T))},[h]),b=g.useCallback(async T=>{await h(()=>K.apiService.updateEndpoint(T))},[h]),z=g.useCallback(async T=>{p(!0),f(null);try{const M=await K.apiService.createKey(T);return M.success?(y(M.created),l(await K.apiService.listKeys()),!0):(f(M.message),!1)}finally{p(!1)}},[]),I=g.useCallback(async T=>{p(!0),f(null);try{const M=await K.apiService.revokeKey(T);M.success||f(M.message??"request failed"),l(await K.apiService.listKeys())}finally{p(!1)}},[]),C=g.useCallback(async(T,M)=>{p(!0),f(null);try{const D=await K.apiService.setKeyEnabled(T,M);D.success||f(D.message??"request failed"),l(await K.apiService.listKeys())}finally{p(!1)}},[]),S=g.useMemo(()=>oM(d),[d]),L=g.useCallback(()=>y(null),[]);return{loading:e,config:a,status:o,keys:s,modelOptions:S,busy:u,error:m,createdKey:P,dismissCreatedKey:L,setEnabled:k,setNetworkBinding:v,updateEndpoint:b,createKey:z,revokeKey:I,setKeyEnabled:C}}const rM=Og("inline-flex items-center gap-1 rounded-md border px-2 py-0.5 text-[11px] font-medium uppercase tracking-[0.08em] text-text-muted transition-colors select-none",{variants:{variant:{default:"border-primary/50 bg-primary-soft/35 text-primary",secondary:"border-border bg-surface-2 text-text-muted",destructive:"border-destructive/60 bg-destructive/15 text-destructive",outline:"border-border bg-surface-1/60 text-text-muted",success:"border-success/60 bg-success/15 text-success"}},defaultVariants:{variant:"default"}});function Be({className:e,variant:t,...a}){return r.jsx("div",{className:G(rM({variant:t}),e),...a})}function sM({created:e,onDismiss:t}){const a=$(),[n,o]=g.useState(!1),i=()=>{navigator.clipboard?.writeText(e.plaintextOnce).then(()=>{o(!0),window.setTimeout(()=>o(!1),1500)})};return r.jsxs("div",{className:"rounded-md border border-primary/50 bg-primary-soft/20 p-3 space-y-2",role:"status",children:[r.jsx("div",{className:"text-sm font-medium text-foreground",children:a("apiService.keys.created.title")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:a("apiService.keys.created.warning")}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("code",{className:"min-w-0 flex-1 truncate rounded bg-surface-2/70 px-2 py-1.5 text-xs text-foreground",children:e.plaintextOnce}),r.jsxs(R,{variant:"outline",size:"sm",onClick:i,children:[n?r.jsx(Ln,{className:"h-3.5 w-3.5 text-success"}):r.jsx(Lr,{className:"h-3.5 w-3.5"}),a(n?"apiService.keys.created.copied":"apiService.keys.created.copy")]})]}),r.jsx("div",{className:"flex justify-end",children:r.jsx(R,{variant:"ghost",size:"sm",onClick:t,children:a("apiService.keys.created.dismiss")})})]})}function lM({keys:e,busy:t,createdKey:a,onCreate:n,onRevoke:o,onToggle:i,onDismissCreated:s}){const l=$(),[d,c]=g.useState(""),[u,p]=g.useState(null),m=async()=>{const f=d.trim();if(!f)return;await n(f)&&c("")};return r.jsxs("section",{className:"space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(Dd,{className:"h-4 w-4 text-primary","aria-hidden":"true"}),r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:l("apiService.keys.title")})]}),r.jsx("p",{className:"text-xs text-muted-foreground",children:l("apiService.keys.description")}),a?r.jsx(sM,{created:a,onDismiss:s}):null,r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(V,{density:"compact",value:d,placeholder:l("apiService.keys.namePlaceholder"),disabled:t,onChange:f=>c(f.target.value),onKeyDown:f=>{f.key==="Enter"&&m()}}),r.jsxs(R,{variant:"default",size:"sm",disabled:t||!d.trim(),onClick:()=>void m(),children:[r.jsx(Ra,{className:"h-3.5 w-3.5"}),l("apiService.keys.create")]})]}),e.length===0?r.jsx("p",{className:"rounded-md border border-dashed border-border/60 px-3 py-4 text-center text-xs text-muted-foreground",children:l("apiService.keys.empty")}):r.jsx("ul",{className:"space-y-2",children:e.map(f=>r.jsxs("li",{className:"flex items-center gap-3 rounded-md border border-border/60 bg-surface-0/60 px-3 py-2",children:[r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"truncate text-sm font-medium text-foreground",children:f.name}),f.revoked?r.jsx(Be,{variant:"destructive",children:l("apiService.keys.revoked")}):f.enabled?r.jsx(Be,{variant:"success",children:l("apiService.keys.enabled")}):r.jsx(Be,{variant:"secondary",children:l("apiService.keys.disabled")})]}),r.jsxs("code",{className:"text-xs text-muted-foreground",children:[f.keyPrefix,"…"]})]}),f.revoked?null:r.jsx(me,{checked:f.enabled,disabled:t,onCheckedChange:P=>void i(f.id,P),"aria-label":l("apiService.keys.toggle")}),f.revoked?null:r.jsx(R,{variant:"ghost",size:"icon",className:"h-7 w-7",disabled:t,onClick:()=>p(f),"aria-label":l("apiService.keys.revoke"),children:r.jsx(In,{className:"h-3.5 w-3.5 text-destructive"})})]},f.id))}),r.jsx(Kr,{open:u!==null,onOpenChange:f=>{f||p(null)},title:l("apiService.keys.revokeConfirmTitle"),description:u?l("apiService.keys.revokeConfirmDesc",{name:u.name}):void 0,confirmLabel:l("apiService.keys.revoke"),cancelLabel:l("common.cancel"),variant:"destructive",onConfirm:()=>{u&&o(u.id),p(null)}})]})}const dM=["chat","responses","messages","gemini"];function cM({label:e,url:t}){const[a,n]=g.useState(!1),o=()=>{navigator.clipboard?.writeText(t).then(()=>{n(!0),window.setTimeout(()=>n(!1),1200)})};return r.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[r.jsx("span",{className:"w-20 shrink-0 font-medium uppercase tracking-wide text-muted-foreground",children:e}),r.jsx("code",{className:"min-w-0 flex-1 truncate rounded bg-surface-2/60 px-2 py-1 text-foreground",title:t,children:t}),r.jsx(R,{variant:"ghost",size:"icon",className:"h-6 w-6 shrink-0",onClick:o,"aria-label":e,children:r.jsx(Lr,{className:G("h-3.5 w-3.5",a&&"text-success")})})]})}function qu({title:e,formats:t}){return r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-xs font-semibold text-foreground",children:e}),dM.map(a=>r.jsx(cM,{label:a,url:t[a]},a))]})}function uM({status:e}){const t=$(),a=!!e?.running;return r.jsxs("div",{className:"rounded-md border border-border/60 bg-surface-0/60 p-4 space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-3",children:[a?r.jsx(Cg,{className:"h-5 w-5 shrink-0 text-success","aria-hidden":"true"}):r.jsx(wg,{className:"h-5 w-5 shrink-0 text-muted-foreground","aria-hidden":"true"}),r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"text-sm font-medium text-foreground",children:t(a?"apiService.status.running":"apiService.status.stopped")}),a&&e?.port?r.jsx(Be,{variant:"success",children:t("apiService.status.port",{port:e.port})}):null]}),r.jsx("p",{className:"text-xs text-muted-foreground",children:t(a?"apiService.status.runningHint":"apiService.status.stoppedHint")})]})]}),a&&(e?.formats||e?.lanFormats)?r.jsxs("div",{className:"grid gap-4 border-t border-border/50 pt-3 sm:grid-cols-2",children:[e?.formats?r.jsx(qu,{title:t("apiService.status.loopback"),formats:e.formats}):null,e?.lanFormats?r.jsx(qu,{title:t("apiService.status.lan"),formats:e.lanFormats}):null]}):null]})}function pM(){const e=$(),{loading:t,config:a,status:n,keys:o,modelOptions:i,busy:s,error:l,createdKey:d,dismissCreatedKey:c,setEnabled:u,setNetworkBinding:p,updateEndpoint:m,createKey:f,revokeKey:P,setKeyEnabled:y}=iM();return r.jsxs("div",{className:"flex h-full flex-col overflow-hidden",children:[r.jsxs("header",{className:"border-b border-border/60 px-6 py-4",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(Ed,{className:"h-5 w-5 text-primary","aria-hidden":"true"}),r.jsx("h2",{className:"text-lg font-semibold text-foreground",children:e("apiService.title")})]}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("apiService.description")})]}),r.jsx(ha,{className:"flex-1",children:r.jsx("div",{className:"mx-auto max-w-3xl space-y-5 px-6 py-5",children:t?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("apiService.loading")}):a?r.jsxs(r.Fragment,{children:[r.jsx(uM,{status:n}),l?r.jsx("p",{className:"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:l}):null,r.jsxs("div",{className:"space-y-2",children:[r.jsx(Jt,{label:e("apiService.enable.label"),description:e("apiService.enable.description"),children:r.jsx(me,{checked:a.enabled,disabled:s,onCheckedChange:A=>void u(A),"aria-label":e("apiService.enable.label")})}),r.jsx(Jt,{label:e("apiService.networkBinding.label"),description:e("apiService.networkBinding.description"),children:r.jsx(me,{checked:a.networkBinding,disabled:s,onCheckedChange:A=>void p(A),"aria-label":e("apiService.networkBinding.label")})})]}),a.networkBinding?r.jsxs("div",{className:"flex items-start gap-2 rounded-md border border-warning/40 bg-warning/10 px-3 py-2 text-xs text-foreground",children:[r.jsx(Kd,{className:"mt-0.5 h-4 w-4 shrink-0 text-warning","aria-hidden":"true"}),r.jsx("span",{children:e("apiService.networkBinding.warning")})]}):null,r.jsx(lM,{keys:o,busy:s,createdKey:d,onCreate:f,onRevoke:P,onToggle:y,onDismissCreated:c}),r.jsxs("section",{className:"space-y-3",children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("apiService.endpoints.title")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:e("apiService.endpoints.description")}),r.jsx("div",{className:"space-y-3",children:a.endpoints.map(A=>r.jsx(nM,{endpoint:A,modelOptions:i,busy:s,onChange:h=>void m(h)},A.endpoint))})]})]}):r.jsx("p",{className:"text-sm text-destructive",children:e("apiService.loadError")})})})]})}function mM({cli:e,sessions:t,busy:a,onInstall:n,onLaunch:o,onStop:i}){const s=$(),[l,d]=g.useState(!1),[c,u]=g.useState(""),[p,m]=g.useState(!1),[f,P]=g.useState(!1),y=async()=>{P(!0);try{await n()}finally{P(!1)}},A=async()=>{m(!0);try{(await o({cwd:c.trim()||void 0})).success&&(d(!1),u(""))}finally{m(!1)}};return r.jsxs("section",{className:"space-y-3 rounded-xl border border-border/70 bg-surface-1/60 p-4",children:[r.jsxs("div",{className:"flex items-center justify-between gap-3",children:[r.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[r.jsx("div",{className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Od,{className:"h-4 w-4 text-muted-foreground"})}),r.jsxs("div",{className:"min-w-0",children:[r.jsx("h3",{className:"text-sm font-medium text-foreground",children:e.displayName}),r.jsx("p",{className:"truncate font-mono text-xs text-muted-foreground",children:e.command})]})]}),r.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[e.installed?r.jsx(Be,{variant:"success",children:s("codeCli.cli.installed")}):r.jsx(Be,{variant:"secondary",children:s("codeCli.cli.notFound")}),e.installed?r.jsxs(R,{size:"sm",variant:"default",disabled:a,onClick:()=>d(!0),children:[r.jsx(zl,{className:"h-3.5 w-3.5"}),s("codeCli.cli.launch")]}):e.installable?r.jsxs(R,{size:"sm",variant:"outline",disabled:a||f,onClick:()=>void y(),children:[f?r.jsx(La,{className:"h-3.5 w-3.5 animate-spin"}):r.jsx(Rd,{className:"h-3.5 w-3.5"}),s(f?"codeCli.cli.installing":"codeCli.cli.install")]}):null]})]}),e.installed?null:r.jsx("p",{className:"text-xs text-muted-foreground",children:s(f?"codeCli.cli.installingHint":"codeCli.cli.notFoundHint")}),t.length>0?r.jsx("ul",{className:"space-y-1.5",children:t.map(h=>r.jsxs("li",{className:"flex items-center justify-between gap-3 rounded-md border border-border/50 bg-surface-0/60 px-3 py-1.5",children:[r.jsxs("div",{className:"flex min-w-0 items-center gap-2 text-xs",children:[r.jsx("span",{className:"inline-flex h-2 w-2 shrink-0 rounded-full bg-success","aria-hidden":"true"}),r.jsx("span",{className:"truncate text-muted-foreground",children:s("codeCli.cli.runningVia",{provider:h.providerId,model:h.model})})]}),r.jsxs(R,{size:"sm",variant:"outline",disabled:a,onClick:()=>i(h.id),className:"shrink-0",children:[r.jsx(Bk,{className:"h-3.5 w-3.5"}),s("codeCli.cli.stop")]})]},h.id))}):null,r.jsx(Ft,{open:l,onOpenChange:d,children:r.jsxs(xt,{className:"max-w-md",children:[r.jsxs(zt,{children:[r.jsx(It,{children:s("codeCli.cli.launchTitle",{name:e.displayName})}),r.jsx(Vt,{children:s("codeCli.cli.launchDescription")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-xs font-medium text-muted-foreground",children:[s("codeCli.cli.cwdLabel")," ",r.jsxs("span",{className:"font-normal text-muted-foreground/80",children:["(",s("common.optional"),")"]})]}),r.jsx(V,{value:c,placeholder:s("codeCli.cli.cwdPlaceholder"),onChange:h=>u(h.target.value),autoComplete:"off"})]}),r.jsxs(Bt,{className:"gap-2 sm:gap-0",children:[r.jsx(R,{variant:"secondary",onClick:()=>d(!1),disabled:p,children:s("common.cancel")}),r.jsxs(R,{variant:"default",onClick:()=>void A(),disabled:p,children:[p?r.jsx(La,{className:"h-3.5 w-3.5 animate-spin"}):r.jsx(zl,{className:"h-3.5 w-3.5"}),s("codeCli.cli.launch")]})]})]})})]})}function gM(){const[e,t]=g.useState(!0),[a,n]=g.useState([]),[o,i]=g.useState([]),[s,l]=g.useState(!1),[d,c]=g.useState(null),u=g.useCallback(async()=>{const[y,A]=await Promise.all([K.cli.list(),K.cli.sessions()]);n(y),i(A)},[]);g.useEffect(()=>{let y=!1;return(async()=>{t(!0);const[A,h]=await Promise.all([K.cli.list(),K.cli.sessions()]);y||(n(A),i(h),t(!1))})(),()=>{y=!0}},[]);const p=g.useCallback(async y=>{l(!0),c(null);try{const A=await K.cli.install(y);return A.success?await u():c(A.message??"install failed"),A}finally{l(!1)}},[u]),m=g.useCallback(async(y,A)=>{l(!0),c(null);try{const h=await K.cli.launch(y,A);return h.success?await u():c(h.message??"launch failed"),h}finally{l(!1)}},[u]),f=g.useCallback(async y=>{l(!0),c(null);try{const A=await K.cli.stop(y);A.success||c(A.message??"failed to stop"),await u()}finally{l(!1)}},[u]),P=g.useCallback(()=>c(null),[]);return{loading:e,clis:a,sessions:o,busy:s,error:d,clearError:P,refresh:u,install:p,launch:m,stop:f}}function zs({label:e,value:t}){const a=$(),[n,o]=g.useState(!1),i=()=>{navigator.clipboard?.writeText(t).then(()=>{o(!0),window.setTimeout(()=>o(!1),1500)})};return r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:e}),r.jsxs(R,{variant:"ghost",size:"sm",onClick:i,children:[n?r.jsx(Ln,{className:"h-3.5 w-3.5 text-success"}):r.jsx(Lr,{className:"h-3.5 w-3.5"}),a(n?"codeCli.copied":"codeCli.copy")]})]}),r.jsx("pre",{className:"overflow-auto whitespace-pre rounded-md border border-border bg-surface-0/60 px-3 py-2 font-mono text-xs text-foreground",children:t})]})}function hM(){const e=$(),{loading:t,clis:a,sessions:n,busy:o,error:i,refresh:s,install:l,launch:d,stop:c}=gM(),[u,p]=g.useState(!1),m=g.useCallback(()=>void s(),[s]),f=[`ANTHROPIC_BASE_URL=${Sa}`,"ANTHROPIC_API_KEY=<your-outbound-key>"].join(`
340
- `),P=[`OPENAI_BASE_URL=${Sa}`,"OPENAI_API_KEY=<your-outbound-key>"].join(`
341
- `);return r.jsx("div",{className:"flex h-full flex-col overflow-hidden",children:r.jsx(ha,{className:"flex-1",children:r.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 px-6 py-6",children:[r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:r.jsxs("div",{className:"flex items-start justify-between gap-4",children:[r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Od,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{children:[r.jsx("h2",{className:"text-base font-semibold text-foreground",children:e("codeCli.title")}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("codeCli.launchDescription")})]})]}),r.jsx("button",{type:"button",onClick:m,className:"rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-surface-2 hover:text-foreground","aria-label":e("codeCli.refresh"),children:r.jsx(Fo,{className:`h-4 w-4 ${t?"animate-spin":""}`})})]})}),i?r.jsx("div",{className:"rounded-md bg-destructive/10 px-4 py-3 text-sm text-destructive",children:i}):null,t?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("codeCli.loading")}):r.jsx("div",{className:"space-y-3",children:a.map(y=>r.jsx(mM,{cli:y,sessions:n.filter(A=>A.cli===y.id),busy:o,onInstall:()=>l(y.id),onLaunch:A=>d(y.id,A),onStop:A=>void c(A)},y.id))}),r.jsxs("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:[r.jsxs("button",{type:"button",className:"flex w-full items-center justify-between text-left",onClick:()=>p(y=>!y),"aria-expanded":u,children:[r.jsxs("div",{children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("codeCli.manual.title")}),r.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:e("codeCli.manual.description")})]}),r.jsx("span",{className:"text-xs text-muted-foreground",children:e(u?"codeCli.manual.hide":"codeCli.manual.show")})]}),u?r.jsxs("div",{className:"mt-3 space-y-3 border-t border-border/40 pt-3",children:[r.jsx(zs,{label:e("codeCli.baseUrl.label"),value:Sa}),r.jsx("p",{className:"text-xs text-muted-foreground",children:e("codeCli.token.hint")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:e("codeCli.examples.keyNote")}),r.jsx(zs,{label:e("codeCli.examples.anthropic"),value:f}),r.jsx(zs,{label:e("codeCli.examples.openai"),value:P})]}):null]})]})})})}function $u(e){const t=e.trim();if(t==="")return null;const a=Number(t);return Number.isFinite(a)&&a>=0?a:null}function fM(e){const t={},a=e.providerId.trim(),n=e.modelId.trim();a||(t.providerId="pricing.requiredId"),n||(t.modelId="pricing.requiredId");const o=$u(e.inputPricePer1m);o===null&&(t.inputPricePer1m="pricing.invalidPrice");const i=$u(e.outputPricePer1m);i===null&&(t.outputPricePer1m="pricing.invalidPrice");const s=(c,u)=>{if(c.trim()==="")return null;const p=Number(c.trim());return!Number.isFinite(p)||p<0?(t[u]="pricing.invalidPrice",null):p},l=s(e.cacheReadPricePer1m,"cacheReadPricePer1m"),d=s(e.cacheWritePricePer1m,"cacheWritePricePer1m");return Object.keys(t).length>0?{ok:!1,errors:t}:{ok:!0,errors:t,input:{providerId:a,modelId:n,inputPricePer1m:o,outputPricePer1m:i,cacheReadPricePer1m:l,cacheWritePricePer1m:d}}}function vM(e){return{providerId:e.providerId,modelId:e.modelId,inputPricePer1m:String(e.inputPricePer1m),outputPricePer1m:String(e.outputPricePer1m),cacheReadPricePer1m:e.cacheReadPricePer1m===null?"":String(e.cacheReadPricePer1m),cacheWritePricePer1m:e.cacheWritePricePer1m===null?"":String(e.cacheWritePricePer1m)}}const kM={providerId:"",modelId:"",inputPricePer1m:"",outputPricePer1m:"",cacheReadPricePer1m:"",cacheWritePricePer1m:""};function yM(e,t){const a=t.trim().toLowerCase();return a?e.filter(n=>n.providerId.toLowerCase().includes(a)||n.modelId.toLowerCase().includes(a)):e}function wn(e){return`${e.providerId}\0${e.modelId}`}function bM(e){const t={};for(const a of e)t[wn(a)]="skip";return t}function PM(e,t,a){return{...e,[t]:a}}function AM(e,t){const a={};for(const n of e)a[wn(n)]=t;return a}function CM(e,t){return e.map(a=>({providerId:a.providerId,modelId:a.modelId,action:t[wn(a)]??"skip",incoming:a.incoming}))}function _u(e,t){const a=n=>n==null?"—":new Intl.NumberFormat(t,{minimumFractionDigits:2,maximumFractionDigits:4}).format(n);return`${a(e.inputPricePer1m)} / ${a(e.outputPricePer1m)} / ${a(e.cacheReadPricePer1m)} / ${a(e.cacheWritePricePer1m)}`}function xM({state:e,onDecision:t,onSetAll:a,onSubmit:n,onCancel:o}){const i=$(),s=ie.language||"en",l=d=>{const c=wn(d),u=e.decisions[c]??"skip",p=(m,f)=>r.jsx("button",{type:"button","aria-pressed":u===m,disabled:e.submitting,onClick:()=>t(c,m),className:G("rounded-md border px-2 py-1 text-xs transition-colors",u===m?"border-primary bg-primary-soft/40 text-primary":"border-border text-muted-foreground hover:text-foreground"),children:i(f)});return r.jsxs("span",{className:"inline-flex items-center gap-1",children:[p("skip","pricing.skip"),p("overwrite","pricing.overwrite")]})};return r.jsx(Ft,{open:!0,onOpenChange:d=>{!d&&!e.submitting&&o()},children:r.jsxs(xt,{className:"max-w-2xl",children:[r.jsxs(zt,{children:[r.jsx(It,{children:i("pricing.conflictTitle")}),r.jsx(Vt,{children:i("pricing.conflictHint")})]}),r.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[r.jsx(R,{size:"xs",variant:"secondary",disabled:e.submitting,onClick:()=>a("overwrite"),children:i("pricing.overwriteAll")}),r.jsx(R,{size:"xs",variant:"secondary",disabled:e.submitting,onClick:()=>a("skip"),children:i("pricing.skipAll")})]}),r.jsx("div",{className:"max-h-80 space-y-2 overflow-y-auto pr-1",children:e.conflicts.map(d=>{const c=wn(d);return r.jsxs("div",{className:"rounded-lg border border-border/70 bg-surface-1/60 px-3 py-2",children:[r.jsxs("div",{className:"flex items-center justify-between gap-2",children:[r.jsxs("p",{className:"min-w-0 break-all text-sm font-medium text-foreground",children:[d.providerId," / ",d.modelId]}),l(d)]}),r.jsxs("div",{className:"mt-1.5 grid grid-cols-1 gap-1 text-xs sm:grid-cols-2",children:[r.jsxs("p",{className:"text-muted-foreground",children:[r.jsxs("span",{className:"font-medium",children:[i("pricing.current"),":"]})," ",r.jsx("span",{className:"tabular-nums",children:_u(d.current,s)})]}),r.jsxs("p",{className:"text-muted-foreground",children:[r.jsxs("span",{className:"font-medium",children:[i("pricing.incoming"),":"]})," ",r.jsx("span",{className:"tabular-nums",children:_u(d.incoming,s)})]})]})]},c)})}),e.submitError?r.jsx("p",{className:"mt-2 text-sm text-destructive",children:e.submitError}):null,r.jsxs(Bt,{className:"gap-2",children:[r.jsx(R,{variant:"secondary",disabled:e.submitting,onClick:o,children:i("common.cancel")}),r.jsx(R,{disabled:e.submitting,onClick:n,children:i("pricing.applyResolutions")})]})]})})}const zM=[{field:"inputPricePer1m",labelKey:"pricing.inputPrice"},{field:"outputPricePer1m",labelKey:"pricing.outputPrice"},{field:"cacheReadPricePer1m",labelKey:"pricing.cacheReadPrice"},{field:"cacheWritePricePer1m",labelKey:"pricing.cacheWritePrice"}];function Ih({initial:e,idsLocked:t,busy:a,onSave:n,onCancel:o}){const i=$(),s=g.useId(),l=y=>`${s}-${y}`,[d,c]=g.useState(e),[u,p]=g.useState({}),m=y=>A=>{c(h=>({...h,[y]:A.target.value})),p(h=>({...h,[y]:void 0}))},f=()=>{const y=fM(d);if(!y.ok||!y.input){p(y.errors);return}n(y.input)},P=y=>u[y]?r.jsx("p",{className:"mt-0.5 text-xs text-destructive",children:i(u[y])}):null;return r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[r.jsxs("div",{children:[r.jsx("label",{htmlFor:l("providerId"),className:"mb-1 block text-xs text-muted-foreground",children:i("pricing.provider")}),r.jsx(V,{id:l("providerId"),density:"compact",value:d.providerId,disabled:!!t,onChange:m("providerId")}),P("providerId")]}),r.jsxs("div",{children:[r.jsx("label",{htmlFor:l("modelId"),className:"mb-1 block text-xs text-muted-foreground",children:i("pricing.model")}),r.jsx(V,{id:l("modelId"),density:"compact",value:d.modelId,disabled:!!t,onChange:m("modelId")}),P("modelId")]})]}),r.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:zM.map(({field:y,labelKey:A})=>r.jsxs("div",{children:[r.jsx("label",{htmlFor:l(y),className:"mb-1 block text-xs text-muted-foreground",children:i(A)}),r.jsx(V,{id:l(y),density:"compact",inputMode:"decimal",placeholder:y.startsWith("cache")?i("common.optional"):void 0,value:d[y],onChange:m(y)}),P(y)]},y))}),r.jsxs("div",{className:"flex items-center justify-end gap-2",children:[r.jsx(R,{size:"sm",variant:"secondary",onClick:o,disabled:a,children:i("common.cancel")}),r.jsx(R,{size:"sm",onClick:f,disabled:a,children:i("common.save")})]})]})}const IM={builtin:"pricing.sourceBuiltin",litellm:"pricing.sourceLitellm",user:"pricing.sourceUser"},Wn="px-3 py-2 text-left text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground",ki="px-3 py-2 text-right text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground",yi="px-3 py-2 text-sm text-foreground",bi="px-3 py-2 text-right text-sm tabular-nums text-foreground";function Pi(e,t){return e===null?"—":new Intl.NumberFormat(t,{minimumFractionDigits:2,maximumFractionDigits:4}).format(e)}function SM({entries:e,busy:t,onSave:a,onDelete:n}){const o=$(),i=ie.language||"en",[s,l]=g.useState(null),[d,c]=g.useState(null),u=async p=>{await a(p)&&l(null)};return r.jsxs("div",{className:"overflow-x-auto rounded-lg border border-border/70",children:[r.jsxs("table",{className:"w-full border-collapse bg-surface-1/40",children:[r.jsx("thead",{className:"border-b border-border/60",children:r.jsxs("tr",{children:[r.jsx("th",{className:Wn,children:o("pricing.provider")}),r.jsx("th",{className:Wn,children:o("pricing.model")}),r.jsx("th",{className:ki,children:o("pricing.inputPrice")}),r.jsx("th",{className:ki,children:o("pricing.outputPrice")}),r.jsx("th",{className:ki,children:o("pricing.cacheReadPrice")}),r.jsx("th",{className:ki,children:o("pricing.cacheWritePrice")}),r.jsx("th",{className:Wn,children:o("pricing.source")}),r.jsx("th",{className:Wn,children:o("pricing.updated")}),r.jsx("th",{className:Wn})]})}),r.jsx("tbody",{children:e.map(p=>{const m=wn(p),f=s===m;return r.jsxs(Mt.Fragment,{children:[r.jsxs("tr",{className:"border-b border-border/40 last:border-b-0",children:[r.jsx("td",{className:yi,children:p.providerId}),r.jsx("td",{className:`${yi} break-all`,children:p.modelId}),r.jsx("td",{className:bi,children:Pi(p.inputPricePer1m,i)}),r.jsx("td",{className:bi,children:Pi(p.outputPricePer1m,i)}),r.jsx("td",{className:bi,children:Pi(p.cacheReadPricePer1m,i)}),r.jsx("td",{className:bi,children:Pi(p.cacheWritePricePer1m,i)}),r.jsx("td",{className:yi,children:r.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[r.jsx("span",{className:"text-xs text-muted-foreground",children:o(IM[p.source])}),p.userEdited?r.jsx(Be,{children:o("pricing.userEdited")}):null]})}),r.jsx("td",{className:`${yi} whitespace-nowrap text-xs text-muted-foreground`,children:new Date(p.updatedAt).toLocaleString(i)}),r.jsx("td",{className:"px-2 py-2 text-right",children:r.jsxs("span",{className:"inline-flex items-center gap-1",children:[r.jsx(R,{size:"icon",variant:"ghost","aria-label":o("pricing.edit"),disabled:t,onClick:()=>l(f?null:m),children:r.jsx(Ok,{className:"h-3.5 w-3.5"})}),r.jsx(R,{size:"icon",variant:"ghost","aria-label":o("common.delete"),disabled:t,onClick:()=>c(p),children:r.jsx(In,{className:"h-3.5 w-3.5"})})]})})]}),f?r.jsx("tr",{className:"border-b border-border/40 bg-surface-2/30 last:border-b-0",children:r.jsx("td",{colSpan:9,className:"px-4 py-3",children:r.jsx(Ih,{initial:vM(p),idsLocked:!0,busy:t,onSave:P=>void u(P),onCancel:()=>l(null)})})}):null]},m)})})]}),r.jsx(Kr,{open:d!==null,onOpenChange:p=>{p||c(null)},title:o("pricing.deleteTitle"),description:d?`${d.providerId} / ${d.modelId}`:void 0,confirmLabel:o("common.delete"),cancelLabel:o("common.cancel"),onConfirm:()=>{d&&n(d.providerId,d.modelId)}})]})}function Vd(e){return`?${new URLSearchParams({startTs:String(e.startTs),endTs:String(e.endTs)}).toString()}`}function wM(e){return H.get(`/usage/totals${Vd(e)}`)}function TM(e){return H.get(`/usage/by-model${Vd(e)}`)}function jM(e){return H.get(`/usage/by-api-key${Vd(e)}`)}async function MM(){return(await H.get("/pricing")).entries}async function NM(e){return(await H.put("/pricing",e)).entry}async function LM(e,t){const a=new URLSearchParams({providerId:e,modelId:t});return(await H.delete(`/pricing?${a.toString()}`)).deleted}function RM(){return H.post("/pricing/fetch-latest")}function DM(e){return H.post("/pricing/resolve-conflicts",{resolutions:e})}function EM(){const[e,t]=g.useState(!0),[a,n]=g.useState(null),[o,i]=g.useState([]),[s,l]=g.useState(""),[d,c]=g.useState(!1),[u,p]=g.useState(!1),[m,f]=g.useState(null),[P,y]=g.useState(null),A=g.useCallback(async()=>{i(await MM())},[]),h=g.useCallback(async()=>{n(null);try{await A()}catch(M){n(M instanceof Error?M.message:"request failed")}finally{t(!1)}},[A]);g.useEffect(()=>{h()},[h]);const k=g.useMemo(()=>yM(o,s),[o,s]),v=g.useCallback(async M=>{c(!0),f(null);try{await NM(M)}catch(D){return f({kind:"error",messageKey:"pricing.saveFailed",params:{message:D instanceof Error?D.message:"request failed"}}),c(!1),!1}try{return await A(),f({kind:"success",messageKey:"pricing.saved"}),!0}catch(D){return f({kind:"error",messageKey:"pricing.refreshFailed",params:{message:D instanceof Error?D.message:"request failed"}}),!1}finally{c(!1)}},[A]),b=g.useCallback(async(M,D)=>{c(!0),f(null);let Q;try{Q=await LM(M,D)}catch(W){f({kind:"error",messageKey:"pricing.deleteFailed",params:{message:W instanceof Error?W.message:"request failed"}}),c(!1);return}try{await A(),Q||f({kind:"info",messageKey:"pricing.alreadyDeleted"})}catch(W){f({kind:"error",messageKey:"pricing.refreshFailed",params:{message:W instanceof Error?W.message:"request failed"}})}finally{c(!1)}},[A]),z=g.useCallback(async()=>{p(!0),f(null);let M;try{M=await RM()}catch(D){f({kind:"error",messageKey:"pricing.fetchFailed",params:{message:D instanceof Error?D.message:"request failed"}}),p(!1);return}try{await A(),f({kind:"success",messageKey:"pricing.fetchApplied",params:{count:M.appliedCount}})}catch(D){f({kind:"error",messageKey:"pricing.refreshFailed",params:{message:D instanceof Error?D.message:"request failed"}})}finally{p(!1)}M.conflicts.length>0&&y({conflicts:M.conflicts,decisions:bM(M.conflicts),submitting:!1,submitError:null})},[A]),I=g.useCallback((M,D)=>{y(Q=>Q&&{...Q,decisions:PM(Q.decisions,M,D)})},[]),C=g.useCallback(M=>{y(D=>D&&{...D,decisions:AM(D.conflicts,M)})},[]),S=g.useCallback(async()=>{let M=null;if(y(J=>(M=J,J&&{...J,submitting:!0,submitError:null})),!M)return;const{conflicts:D,decisions:Q}=M;let W;try{W=await DM(CM(D,Q))}catch(J){const ye=J instanceof Error?J.message:"request failed";y(ve=>ve&&{...ve,submitting:!1,submitError:ye});return}y(null);try{await A(),f(W.staleCount>0?{kind:"warning",messageKey:"pricing.resolvedWithStale",params:{overwritten:W.overwrittenCount,skipped:W.skippedCount,stale:W.staleCount}}:{kind:"success",messageKey:"pricing.resolved",params:{overwritten:W.overwrittenCount,skipped:W.skippedCount}})}catch(J){f({kind:"error",messageKey:"pricing.refreshFailed",params:{message:J instanceof Error?J.message:"request failed"}})}},[A]),L=g.useCallback(()=>y(null),[]),T=g.useCallback(()=>f(null),[]);return{loading:e,error:a,entries:o,filtered:k,search:s,setSearch:l,busy:d,fetching:u,notice:m,dismissNotice:T,reload:h,saveEntry:v,removeEntry:b,fetchLatest:z,conflictDialog:P,setConflictDecision:I,setAllConflictDecisions:C,submitConflicts:S,cancelConflicts:L}}const OM={success:"border-success/60 bg-success/10 text-success",info:"border-border bg-surface-2/60 text-foreground",warning:"border-amber-500/60 bg-amber-500/10 text-amber-500",error:"border-destructive/60 bg-destructive/10 text-destructive"};function KM(){const e=$(),t=EM(),[a,n]=g.useState(!1),o=async s=>{await t.saveEntry(s)&&n(!1)},i=r.jsxs(R,{size:"sm",disabled:t.fetching||t.busy,onClick:()=>void t.fetchLatest(),children:[r.jsx(Fo,{className:G("h-3.5 w-3.5",t.fetching&&"animate-spin")}),t.fetching?e("pricing.fetching"):e("pricing.fetchLatest")]});return r.jsxs("div",{className:"flex h-full flex-col overflow-hidden",children:[r.jsx(ha,{className:"flex-1",children:r.jsxs("div",{className:"mx-auto max-w-5xl space-y-4 px-6 py-6",children:[r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(Ag,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsx("h2",{className:"text-base font-semibold text-foreground",children:e("pricing.title")}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("pricing.description")}),r.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[r.jsx(V,{density:"compact",className:"w-64",placeholder:e("pricing.search"),value:t.search,onChange:s=>t.setSearch(s.target.value)}),i,r.jsxs(R,{size:"sm",variant:"secondary",disabled:t.busy,onClick:()=>n(!0),children:[r.jsx(Ra,{className:"h-3.5 w-3.5"}),e("pricing.addEntry")]})]})]})]})}),t.notice?r.jsxs("div",{className:G("flex items-center justify-between gap-3 rounded-lg border px-4 py-2.5",OM[t.notice.kind]),children:[r.jsx("p",{className:"text-sm",children:e(t.notice.messageKey,t.notice.params)}),r.jsx(R,{size:"xs",variant:"ghost",onClick:t.dismissNotice,children:e("common.dismiss")})]}):null,t.error?r.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-lg border border-destructive/60 bg-destructive/10 px-4 py-3",children:[r.jsx("p",{className:"text-sm text-destructive",children:t.error}),r.jsx(R,{size:"sm",variant:"outline",onClick:()=>void t.reload(),children:e("common.retry")})]}):null,!t.error&&t.loading?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("common.loading")}):null,!t.error&&!t.loading&&t.entries.length===0?r.jsxs("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-8 text-center",children:[r.jsx("p",{className:"text-sm text-muted-foreground",children:e("pricing.empty")}),r.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:e("pricing.emptyHint")}),r.jsx("div",{className:"mt-4 flex justify-center",children:i})]}):null,!t.error&&!t.loading&&t.entries.length>0?t.filtered.length===0?r.jsx("p",{className:"px-1 text-sm text-muted-foreground",children:e("pricing.noMatches")}):r.jsx(SM,{entries:t.filtered,busy:t.busy,onSave:t.saveEntry,onDelete:(s,l)=>void t.removeEntry(s,l)}):null]})}),r.jsx(Ft,{open:a,onOpenChange:n,children:r.jsxs(xt,{className:"max-w-xl",children:[r.jsx(zt,{children:r.jsx(It,{children:e("pricing.addEntry")})}),r.jsx(Ih,{initial:kM,busy:t.busy,onSave:s=>void o(s),onCancel:()=>n(!1)})]})}),t.conflictDialog?r.jsx(xM,{state:t.conflictDialog,onDecision:t.setConflictDecision,onSetAll:t.setAllConflictDecisions,onSubmit:()=>void t.submitConflicts(),onCancel:t.cancelConflicts}):null]})}const Sh=8,UM=12;function HM(e){return e.length<Sh?"weak":e.length<UM?"fair":"strong"}function FM({open:e,onClose:t}){const a=$(),[n,o]=g.useState(""),[i,s]=g.useState(""),[l,d]=g.useState(null),[c,u]=g.useState(!1),[p,m]=g.useState(null),f=g.useMemo(()=>HM(n),[n]),P=i.length>0&&n!==i,y=n.length>=Sh&&n===i&&!c;g.useEffect(()=>{e||(o(""),s(""),d(null),m(null),u(!1))},[e]);const A=async()=>{u(!0),m(null);const v=await K.migration.exportPack(n);u(!1),v.success&&v.pack?d(v.pack):m(v.message||a("providerSettings.migrationPack.export.error"))},h=()=>{if(!l)return;const v=new Blob([l],{type:"application/octet-stream"}),b=URL.createObjectURL(v),z=document.createElement("a");z.href=b,z.download="omnicross-migration-pack.txt",z.click(),URL.revokeObjectURL(b)},k=()=>{l&&navigator.clipboard?.writeText(l)};return r.jsx(Ft,{open:e,onOpenChange:v=>!v&&t(),children:r.jsxs(xt,{className:"max-w-lg",children:[r.jsxs(zt,{children:[r.jsx(It,{children:a("providerSettings.migrationPack.export.title")}),r.jsx(Vt,{children:a("providerSettings.migrationPack.export.subtitle")})]}),l===null?r.jsxs("div",{className:"space-y-4",children:[r.jsx("p",{className:"text-xs text-amber-500",children:a("providerSettings.migrationPack.export.warning")}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:a("providerSettings.migrationPack.passphrase")}),r.jsx(V,{type:"password",autoComplete:"new-password",value:n,onChange:v=>o(v.target.value),placeholder:a("providerSettings.migrationPack.passphrasePlaceholder")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:a("providerSettings.migrationPack.passphraseHint")}),n.length>0?r.jsx("p",{className:f==="weak"?"text-xs text-destructive":f==="fair"?"text-xs text-amber-500":"text-xs text-emerald-500",children:a(`providerSettings.migrationPack.strength.${f}`)}):null]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:a("providerSettings.migrationPack.confirm")}),r.jsx(V,{type:"password",autoComplete:"new-password",value:i,onChange:v=>s(v.target.value),placeholder:a("providerSettings.migrationPack.confirmPlaceholder")}),P?r.jsx("p",{className:"text-xs text-destructive",children:a("providerSettings.migrationPack.mismatch")}):null]}),p?r.jsx("p",{className:"text-xs text-destructive",children:p}):null]}):r.jsxs("div",{className:"space-y-3",children:[r.jsx("p",{className:"text-xs text-emerald-500",children:a("providerSettings.migrationPack.export.success")}),r.jsx("textarea",{readOnly:!0,value:l,className:"w-full h-40 resize-none rounded-md border border-border bg-surface-1 p-2 font-mono text-xs",onFocus:v=>v.currentTarget.select()}),r.jsxs("div",{className:"flex gap-2",children:[r.jsx(R,{variant:"outline",size:"sm",onClick:k,children:a("common.copy")}),r.jsxs(R,{variant:"outline",size:"sm",onClick:h,children:[r.jsx(Rd,{className:"h-4 w-4"}),a("providerSettings.migrationPack.export.button")]})]})]}),r.jsxs(Bt,{children:[r.jsx(R,{variant:"ghost",onClick:t,children:a("common.close")}),l===null?r.jsx(R,{onClick:()=>void A(),disabled:!y,children:a("providerSettings.migrationPack.export.submit")}):null]})]})})}function BM({open:e,onClose:t}){const a=$(),[n,o]=g.useState(""),[i,s]=g.useState(""),[l,d]=g.useState(!1),[c,u]=g.useState(null),[p,m]=g.useState(null),f=n.length>0&&i.trim().length>0&&!l;g.useEffect(()=>{e||(o(""),s(""),u(null),m(null),d(!1))},[e]);const P=async A=>{const h=A.target.files?.[0];h&&(s((await h.text()).trim()),A.target.value="")},y=async()=>{d(!0),u(null);const A=await K.migration.importPack({blob:i.trim(),passphrase:n});d(!1),A.success&&A.counts?m(A.counts):u(A.message||a("providerSettings.migrationPack.import.error"))};return r.jsx(Ft,{open:e,onOpenChange:A=>!A&&t(),children:r.jsxs(xt,{className:"max-w-lg",children:[r.jsxs(zt,{children:[r.jsx(It,{children:a("providerSettings.migrationPack.import.title")}),r.jsx(Vt,{children:a("providerSettings.migrationPack.import.subtitle")})]}),p===null?r.jsxs("div",{className:"space-y-4",children:[r.jsx("p",{className:"text-xs text-muted-foreground",children:a("providerSettings.migrationPack.import.hint")}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:a("providerSettings.migrationPack.passphrase")}),r.jsx(V,{type:"password",autoComplete:"off",value:n,onChange:A=>o(A.target.value),placeholder:a("providerSettings.migrationPack.passphrasePlaceholder")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("label",{className:"text-sm font-medium",children:a("providerSettings.migrationPack.import.title")}),r.jsxs("label",{className:"inline-flex cursor-pointer items-center gap-1 text-xs text-primary hover:underline",children:[r.jsx(Ig,{className:"h-3.5 w-3.5"}),r.jsx("span",{children:a("providerSettings.migrationPack.import.button")}),r.jsx("input",{type:"file",accept:".txt,.json,text/plain",className:"hidden",onChange:A=>void P(A)})]})]}),r.jsx("textarea",{value:i,onChange:A=>s(A.target.value),className:"w-full h-32 resize-none rounded-md border border-border bg-surface-1 p-2 font-mono text-xs",placeholder:"OMCXPACK1...."})]}),c?r.jsx("p",{className:"text-xs text-destructive",children:c}):null]}):r.jsxs("div",{className:"space-y-2",children:[r.jsx("p",{className:"text-sm font-medium text-emerald-500",children:a("providerSettings.migrationPack.import.successTitle")}),r.jsx("p",{className:"text-sm text-foreground",children:a("providerSettings.migrationPack.import.summary",{providerKeys:p.providerKeys,poolKeys:p.poolKeys,tokenSets:p.tokenSets})}),p.duplicates>0?r.jsx("p",{className:"text-xs text-muted-foreground",children:a("providerSettings.migrationPack.import.duplicates",{count:p.duplicates})}):null,p.skipped.length>0?r.jsx("p",{className:"text-xs text-muted-foreground",children:a("providerSettings.migrationPack.import.skipped",{names:p.skipped.join(", ")})}):null]}),r.jsxs(Bt,{children:[r.jsx(R,{variant:"ghost",onClick:t,children:a("common.close")}),p===null?r.jsx(R,{onClick:()=>void y(),disabled:!f,children:a("providerSettings.migrationPack.import.submit")}):null]})]})})}function VM(){const e=$(),[t,a]=g.useState(!1),[n,o]=g.useState(!1);return r.jsxs("div",{className:"flex items-center gap-3 border-t border-border/50 px-4 py-3",children:[r.jsx("span",{className:"flex-1 min-w-0 text-xs text-muted-foreground",children:e("providerSettings.migrationPack.barHint")}),r.jsxs(R,{variant:"outline",size:"sm",onClick:()=>a(!0),children:[r.jsx(Rd,{className:"h-4 w-4"}),e("providerSettings.migrationPack.export.button")]}),r.jsxs(R,{variant:"outline",size:"sm",onClick:()=>o(!0),children:[r.jsx(Ig,{className:"h-4 w-4"}),e("providerSettings.migrationPack.import.button")]}),r.jsx(FM,{open:t,onClose:()=>a(!1)}),r.jsx(BM,{open:n,onClose:()=>o(!1)})]})}const qd=({children:e,content:t,position:a="top",className:n="",delay:o=500})=>{const[i,s]=g.useState(!1),l=g.useRef(null),d=g.useCallback(()=>{l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{s(!0)},o)},[o]),c=g.useCallback(()=>{l.current&&(clearTimeout(l.current),l.current=null),s(!1)},[]),u=()=>{switch(a){case"top":return"bottom-full left-1/2 transform -translate-x-1/2 mb-2";case"bottom":return"top-full left-1/2 transform -translate-x-1/2 mt-2";case"left":return"right-full top-1/2 transform -translate-y-1/2 mr-2";case"right":return"left-full top-1/2 transform -translate-y-1/2 ml-2";default:return"bottom-full left-1/2 transform -translate-x-1/2 mb-2"}},p=()=>{switch(a){case"top":return"top-full left-1/2 transform -translate-x-1/2";case"bottom":return"bottom-full left-1/2 transform -translate-x-1/2";case"left":return"left-full top-1/2 transform -translate-y-1/2";case"right":return"right-full top-1/2 transform -translate-y-1/2";default:return"top-full left-1/2 transform -translate-x-1/2"}},m=()=>{const f="hsl(var(--popover))";switch(a){case"top":return{borderTopColor:f};case"bottom":return{borderBottomColor:f};case"left":return{borderLeftColor:f};case"right":return{borderRightColor:f};default:return{borderTopColor:f}}};return Mt.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),t?r.jsxs("div",{className:"relative inline-block",onMouseEnter:d,onMouseLeave:c,children:[e,i?r.jsxs("div",{className:G("absolute z-50 px-2 py-1 text-xs font-medium text-popover-foreground bg-popover border border-border/70 rounded shadow-lg whitespace-nowrap pointer-events-none","animate-in fade-in-0 zoom-in-95 duration-200",u(),n),children:[t,r.jsx("div",{className:G("absolute w-0 h-0 border-4 border-transparent",p()),style:m()})]}):null]}):r.jsx(r.Fragment,{children:e})};function $d(){return $()("appLocal.notSupportedByDaemon")}function Ya({children:e,className:t,position:a="top"}){const n=$d();return r.jsx(qd,{content:n,position:a,children:r.jsx("div",{className:G("opacity-60 pointer-events-none select-none",t),"aria-disabled":"true","data-unbacked":"true",children:e})})}const qM=[{value:"",label:"Auto (Load Balanced)"},{value:"price",label:"Price (Lowest)"},{value:"throughput",label:"Throughput (Highest)"},{value:"latency",label:"Latency (Lowest)"}],$M=[{value:"allow",label:"Allow"},{value:"deny",label:"Deny"}],_M=[{value:"fp32",label:"FP32 (Full precision)"},{value:"bf16",label:"BF16 (Brain float 16)"},{value:"fp16",label:"FP16 (Half precision)"},{value:"fp8",label:"FP8 (8-bit float)"},{value:"int8",label:"INT8 (8-bit integer)"},{value:"int4",label:"INT4 (4-bit integer)"}];function GM({content:e,children:t}){const[a,n]=g.useState(!1),[o,i]=g.useState({x:0,y:0}),s=Mt.useRef(null),l=Mt.useRef(null),d=()=>{l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{if(s.current){const u=s.current.getBoundingClientRect();i({x:u.left+u.width/2,y:u.top-8})}n(!0)},300)},c=()=>{l.current&&(clearTimeout(l.current),l.current=null),n(!1)};return Mt.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),r.jsxs(r.Fragment,{children:[r.jsx("span",{ref:s,onMouseEnter:d,onMouseLeave:c,className:"inline-flex",children:t}),a?Ik.createPortal(r.jsx("div",{className:"fixed z-[9999] px-2 py-1.5 text-xs font-medium text-popover-foreground bg-popover border border-border/70 rounded shadow-lg max-w-xs pointer-events-none animate-in fade-in-0 zoom-in-95 duration-200",style:{left:o.x,top:o.y,transform:"translate(-50%, -100%)"},children:e}),document.body):null]})}function vt({label:e,tooltip:t}){return r.jsxs("label",{className:"text-sm font-medium flex items-center gap-1",children:[e,r.jsx(GM,{content:t,children:r.jsx(jk,{className:"h-3.5 w-3.5 text-muted-foreground cursor-help"})})]})}function Is({value:e,onChange:t,placeholder:a}){const[n,o]=Mt.useState(""),i=l=>{l.key==="Enter"&&n.trim()&&(l.preventDefault(),e.includes(n.trim())||t([...e,n.trim()]),o(""))},s=l=>{t(e.filter(d=>d!==l))};return r.jsxs("div",{className:"space-y-2",children:[r.jsx(V,{value:n,onChange:l=>o(l.target.value),onKeyDown:i,placeholder:a,className:"text-sm"}),e.length>0&&r.jsx("div",{className:"flex flex-wrap gap-1",children:e.map(l=>r.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 bg-muted rounded text-xs",children:[l,r.jsx("button",{type:"button",onClick:()=>s(l),className:"hover:text-destructive",children:r.jsx(Da,{className:"h-3 w-3"})})]},l))})]})}function wh({config:e,onChange:t,defaultExpanded:a=!1}){const n=$(),[o,i]=g.useState(a),s=g.useId(),l=g.useId(),d=(u,p)=>{t({...e,[u]:p})},c=Object.values(e).some(u=>u!=null&&(Array.isArray(u)?u.length>0:!0));return r.jsxs("div",{className:"border-t pt-4 mt-4",children:[r.jsxs("button",{type:"button",className:"w-full flex items-center justify-between text-left",onClick:()=>i(!o),children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("h4",{className:"text-sm font-semibold text-foreground",children:n("providerSettings.openRouter.title","OpenRouter Provider Routing")}),c&&!o?r.jsx("span",{className:"text-xs text-primary bg-primary/10 px-1.5 py-0.5 rounded",children:n("providerSettings.openRouter.configured","Configured")}):null]}),o?r.jsx(Ld,{className:"h-4 w-4 text-muted-foreground"}):r.jsx(ga,{className:"h-4 w-4 text-muted-foreground"})]}),!o&&r.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:n("providerSettings.openRouter.description","Configure how requests are routed to different providers on OpenRouter.")}),r.jsxs("div",{className:G("space-y-4 mt-4",!o&&"hidden"),children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.sort","Routing Strategy"),tooltip:n("providerSettings.openRouter.sortTooltip","Choose how to prioritize providers. Auto uses intelligent load balancing.")}),r.jsx(Lt,{value:e.sort||"",onChange:u=>d("sort",u||void 0),options:qM.map(u=>({value:u.value,label:u.label}))})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.order","Provider Priority Order"),tooltip:n("providerSettings.openRouter.orderTooltip","Specify providers to try in order (e.g., anthropic, openai, together). Press Enter to add.")}),r.jsx(Is,{value:e.order||[],onChange:u=>d("order",u.length>0?u:void 0),placeholder:n("providerSettings.openRouter.orderPlaceholder","Type provider slug and press Enter...")})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx(vt,{label:n("providerSettings.openRouter.allowFallbacks","Allow Fallbacks"),tooltip:n("providerSettings.openRouter.allowFallbacksTooltip","When enabled, OpenRouter will try backup providers if the primary is unavailable.")}),r.jsx(me,{checked:e.allow_fallbacks!==!1,onCheckedChange:u=>d("allow_fallbacks",u?void 0:!1)})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx(vt,{label:n("providerSettings.openRouter.requireParameters","Require All Parameters"),tooltip:n("providerSettings.openRouter.requireParametersTooltip","Only route to providers that support all parameters in your request.")}),r.jsx(me,{checked:e.require_parameters===!0,onCheckedChange:u=>d("require_parameters",u||void 0)})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.dataCollection","Data Collection Policy"),tooltip:n("providerSettings.openRouter.dataCollectionTooltip","Control whether to use providers that may store or train on your data.")}),r.jsx(Lt,{value:e.data_collection||"allow",onChange:u=>d("data_collection",u==="allow"?void 0:u),options:$M.map(u=>({value:u.value,label:u.label}))})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx(vt,{label:n("providerSettings.openRouter.zdr","Zero Data Retention"),tooltip:n("providerSettings.openRouter.zdrTooltip","Only route to endpoints with Zero Data Retention policy.")}),r.jsx(me,{checked:e.zdr===!0,onCheckedChange:u=>d("zdr",u||void 0)})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.only","Only Allow Providers"),tooltip:n("providerSettings.openRouter.onlyTooltip","Only use these specific providers. Leave empty to allow all providers.")}),r.jsx(Is,{value:e.only||[],onChange:u=>d("only",u.length>0?u:void 0),placeholder:n("providerSettings.openRouter.onlyPlaceholder","Type provider slug and press Enter...")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.ignore","Ignore Providers"),tooltip:n("providerSettings.openRouter.ignoreTooltip","Skip these providers when routing requests.")}),r.jsx(Is,{value:e.ignore||[],onChange:u=>d("ignore",u.length>0?u:void 0),placeholder:n("providerSettings.openRouter.ignorePlaceholder","Type provider slug and press Enter...")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx(vt,{label:n("providerSettings.openRouter.quantizations","Quantization Filter"),tooltip:n("providerSettings.openRouter.quantizationsTooltip","Only use providers with specific quantization levels. Lower precision may reduce quality but improve speed.")}),r.jsx("div",{className:"flex flex-wrap gap-2",children:_M.map(u=>r.jsxs("label",{className:"flex items-center gap-1.5 text-xs",children:[r.jsx("input",{type:"checkbox",checked:e.quantizations?.includes(u.value)||!1,onChange:p=>{const m=e.quantizations||[];if(p.target.checked)d("quantizations",[...m,u.value]);else{const f=m.filter(P=>P!==u.value);d("quantizations",f.length>0?f:void 0)}},className:"rounded border-border"}),u.label]},u.value))})]}),r.jsxs("div",{className:"space-y-2",children:[r.jsx(vt,{label:n("providerSettings.openRouter.maxPrice","Maximum Price"),tooltip:n("providerSettings.openRouter.maxPriceTooltip","Set maximum price limits per million tokens. Leave empty for no limit.")}),r.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[r.jsxs("div",{className:"space-y-1",children:[r.jsx("label",{htmlFor:s,className:"text-xs text-muted-foreground",children:"Prompt ($/M tokens)"}),r.jsx(V,{id:s,type:"number",step:"0.01",min:"0",value:e.max_price?.prompt??"",onChange:u=>{const p=u.target.value?parseFloat(u.target.value):void 0;d("max_price",{...e.max_price,prompt:p})},placeholder:"No limit",className:"text-sm"})]}),r.jsxs("div",{className:"space-y-1",children:[r.jsx("label",{htmlFor:l,className:"text-xs text-muted-foreground",children:"Completion ($/M tokens)"}),r.jsx(V,{id:l,type:"number",step:"0.01",min:"0",value:e.max_price?.completion??"",onChange:u=>{const p=u.target.value?parseFloat(u.target.value):void 0;d("max_price",{...e.max_price,completion:p})},placeholder:"No limit",className:"text-sm"})]})]})]})]})]})}const WM=[{id:"openai",name:"OpenAI",apiFormat:"openai",apiType:"openai",api_base_url:"https://api.openai.com/v1/chat/completions",models:["gpt-5.5","gpt-5.4","gpt-5.4-mini","gpt-5.2","gpt-5","gpt-4o","gpt-4o-mini"],modelConfigs:[{id:"gpt-5.5",name:"GPT-5.5",enabled:!0},{id:"gpt-5.4",name:"GPT-5.4",enabled:!0},{id:"gpt-5.4-mini",name:"GPT-5.4 Mini",enabled:!0},{id:"gpt-5.2",name:"GPT-5.2",enabled:!0},{id:"gpt-5",name:"GPT-5",enabled:!1},{id:"gpt-4o",name:"GPT-4o",enabled:!0},{id:"gpt-4o-mini",name:"GPT-4o Mini",enabled:!0}],description:"OpenAI official API",icon:"openai",website:"https://openai.com",docsUrl:"https://platform.openai.com/docs",defaultSettings:{temperature:.7,maxTokens:4096},isSystem:!0,maxConcurrency:8},{id:"gemini",name:"Google Gemini",apiFormat:"google",apiType:"google",api_base_url:"https://generativelanguage.googleapis.com/v1beta/models/",modelsEndpoint:"https://generativelanguage.googleapis.com/v1beta/models",models:["gemini-3-flash","gemini-3.1-pro"],modelConfigs:[{id:"gemini-3-flash",name:"Gemini 3 Flash",enabled:!0},{id:"gemini-3.1-pro",name:"Gemini 3.1 Pro",enabled:!0}],transformer:{use:["gemini"]},description:"Google's multimodal AI models",icon:"gemini",website:"https://ai.google.dev",docsUrl:"https://ai.google.dev/docs",defaultSettings:{temperature:.7,topP:.95,maxTokens:65536},isSystem:!0,maxConcurrency:5},{id:"anthropic",name:"Anthropic",apiFormat:"anthropic",apiType:"anthropic",api_base_url:"https://api.anthropic.com/v1/messages",modelsEndpoint:"https://api.anthropic.com/v1/models",models:["claude-opus-4-7","claude-opus-4-7[1m]","claude-sonnet-4-6","claude-sonnet-4-6[1m]","claude-opus-4-6","claude-opus-4-6[1m]","claude-haiku-4-5"],modelConfigs:[{id:"claude-opus-4-7",name:"Claude Opus 4.7",enabled:!0},{id:"claude-opus-4-7[1m]",name:"Claude Opus 4.7 (1M)",enabled:!1},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",enabled:!0},{id:"claude-sonnet-4-6[1m]",name:"Claude Sonnet 4.6 (1M)",enabled:!1},{id:"claude-opus-4-6",name:"Claude Opus 4.6",enabled:!0},{id:"claude-opus-4-6[1m]",name:"Claude Opus 4.6 (1M)",enabled:!1},{id:"claude-haiku-4-5",name:"Claude Haiku 4.5",enabled:!0}],transformer:{use:["anthropic"]},description:"Claude models official API (Anthropic Messages format)",icon:"anthropic",website:"https://anthropic.com",docsUrl:"https://docs.anthropic.com",defaultSettings:{temperature:.7,maxTokens:65536},isSystem:!0,isOfficial:!0,maxConcurrency:10},{id:"azure-openai",name:"Azure OpenAI",apiFormat:"azure-openai",api_base_url:"",apiVersion:"2024-08-01-preview",models:[],description:"Azure OpenAI Service (requires deployment name as model)",icon:"azure-openai",website:"https://azure.microsoft.com/products/ai-services/openai-service",docsUrl:"https://learn.microsoft.com/azure/ai-services/openai/",defaultSettings:{temperature:.7,maxTokens:4096},isSystem:!1},{id:"openai-response",name:"OpenAI (Responses API)",apiFormat:"openai-response",api_base_url:"https://api.openai.com",models:["gpt-5.5","gpt-5.4","gpt-5.4-mini","gpt-5.3-codex","gpt-5.2","o3","o4-mini","gpt-4.1"],modelConfigs:[{id:"gpt-5.5",name:"GPT-5.5",enabled:!0},{id:"gpt-5.4",name:"GPT-5.4",enabled:!0},{id:"gpt-5.4-mini",name:"GPT-5.4 Mini",enabled:!0},{id:"gpt-5.3-codex",name:"GPT-5.3 Codex",enabled:!0},{id:"gpt-5.2",name:"GPT-5.2",enabled:!0},{id:"o3",name:"o3",enabled:!0},{id:"o4-mini",name:"o4 Mini",enabled:!0},{id:"gpt-4.1",name:"GPT-4.1",enabled:!0}],transformer:{use:["openai-response"]},description:"OpenAI Responses API (/v1/responses endpoint)",icon:"openai",website:"https://openai.com",docsUrl:"https://platform.openai.com/docs/api-reference/responses",defaultSettings:{temperature:.7,maxTokens:4096},isSystem:!1},{id:"grok",name:"Grok",apiFormat:"openai",apiType:"openai",api_base_url:"https://api.x.ai/v1/chat/completions",models:["grok-4.3","grok-4.20","grok-4.20-reasoning","grok-4.20-multi-agent"],modelConfigs:[{id:"grok-4.3",name:"Grok 4.3",enabled:!0},{id:"grok-4.20",name:"Grok 4.20",enabled:!0},{id:"grok-4.20-reasoning",name:"Grok 4.20 Reasoning",enabled:!0},{id:"grok-4.20-multi-agent",name:"Grok 4.20 Multi-Agent",enabled:!0}],description:"xAI Grok models with reasoning, vision, and web search capabilities",icon:"grok",website:"https://x.ai",docsUrl:"https://docs.x.ai",defaultSettings:{temperature:.7,maxTokens:4096},isSystem:!0,maxConcurrency:8},{id:"deepseek",name:"DeepSeek",apiFormat:"openai",apiType:"openai",api_base_url:"https://api.deepseek.com/v1/chat/completions",models:["deepseek-v4-flash","deepseek-v4-pro","deepseek-chat","deepseek-reasoner"],modelConfigs:[{id:"deepseek-v4-flash",name:"DeepSeek V4 Flash",enabled:!0},{id:"deepseek-v4-pro",name:"DeepSeek V4 Pro",enabled:!0},{id:"deepseek-chat",name:"DeepSeek Chat (Legacy)",enabled:!1},{id:"deepseek-reasoner",name:"DeepSeek Reasoner (Legacy)",enabled:!1}],transformer:{use:["deepseek"]},description:"DeepSeek official API",icon:"deepseek",website:"https://deepseek.com",docsUrl:"https://api-docs.deepseek.com",defaultSettings:{temperature:.7,maxTokens:8192},isSystem:!0,maxConcurrency:8}],ZM=[{name:"anthropic",description:"Preserve original Anthropic request/response format"},{name:"deepseek",description:"Adapt for DeepSeek API format"},{name:"gemini",description:"Adapt for Google Gemini API format"},{name:"openai-response",description:"Adapt for OpenAI Responses API (/v1/responses) format"},{name:"openrouter",description:"Adapt for OpenRouter API with provider routing support",hasOptions:!0},{name:"groq",description:"Adapt for Groq API format"},{name:"openai",description:"Standard OpenAI chat completions format"},{name:"maxtoken",description:"Set specific max_tokens value",hasOptions:!0,optionSchema:{max_tokens:{type:"number",description:"Maximum tokens for completion",default:4096}}},{name:"tooluse",description:"Optimize tool usage via tool_choice parameter"},{name:"reasoning",description:"Process reasoning_content field for chain-of-thought"},{name:"sampling",description:"Process sampling parameters (temperature, top_p, etc.)"},{name:"enhancetool",description:"Add error tolerance to tool call parameters"},{name:"cleancache",description:"Clear cache_control field from requests"},{name:"vertex-gemini",description:"Handle Gemini API using Vertex authentication"},{name:"vertex-claude",description:"Handle Claude API using Vertex authentication"},{name:"cerebras",description:"Adapt for Cerebras API format"},{name:"vercel",description:"Adapt for Vercel AI SDK format"},{name:"forcereasoning",description:"Force reasoning mode for models that support it"},{name:"maxcompletiontokens",description:"Set max_completion_tokens instead of max_tokens"},{name:"streamoptions",description:"Configure streaming options"},{name:"customparams",description:"Add custom parameters to requests"}],Le="default",Kt="Default",Th=new Set(["openrouter"]),Gu={name:"",apiFormat:"openai",chatApiFormat:"openai",apiType:"openai",api_base_url:"",api_key:"",models:[],modelConfigs:[],modelGroups:[],modelsEndpoint:"",enabled:!0,icon:void 0,apiVersion:void 0},kn=(e,t)=>{if(!t.nameKey)return t.name;const a=e(t.nameKey);return a===t.nameKey?t.name:a},Rl=e=>e?(e.api_base_url||"").toLowerCase().includes("openrouter.ai"):!1,fr=e=>e?e.split(/[-_/]/).map(t=>t&&t[0].toUpperCase()+t.slice(1)).join(" "):Kt,_d=(e,t)=>{if(!e||!Th.has(e))return null;const a=t.trim();if(!a)return null;const n=a.indexOf("/");if(n>0)return a.slice(0,n);const o=a.indexOf(":");return o>0?a.slice(0,o):null},jh=(e,t)=>{if(!e||!Th.has(e.id))return null;const a=new Map;return t.forEach(n=>{const i=_d(e.id,n.id)||Le,s=a.get(i)??[];s.push(n),a.set(i,s)}),a.size?Array.from(a.entries()).map(([n,o])=>({id:n,name:n===Le?Kt:fr(n),models:o})).sort((n,o)=>n.name.localeCompare(o.name)):null},QM=(e,t)=>{if(!e||!t.length)return[];const a=new Map;return t.forEach(n=>{const i=_d(e.id,n.id)||(n.group?n.group:null)||(n.category?n.category.toLowerCase():Le),s=a.get(i)??[];s.push(n),a.set(i,s)}),Array.from(a.entries()).map(([n,o])=>({id:n,name:n===Le?Kt:fr(n),models:o})).sort((n,o)=>n.name.localeCompare(o.name))},Ss=(e,t)=>{const a=new Map(t.map(i=>[i.id,i])),n=e.modelGroups?.length?e.modelGroups:jh(e,t);if(!n?.length)return[{id:Le,name:Kt,models:t}];const o=n.map(i=>({...i,models:(i.models||[]).map(s=>a.get(s.id)||null).filter(s=>!!s)})).filter(i=>i.models.length>0);return o.length?o:[{id:Le,name:Kt,models:t}]},Wu=(e,t,a)=>{if(!e.length)return[{id:t||Le,name:t===Le?Kt:fr(t),models:[a]}];let n=!1;const o=e.map(i=>i.id!==t||(n=!0,i.models.some(s=>s.id===a.id))?i:{...i,models:[...i.models,a]});return n?o:[...o,{id:t||Le,name:t===Le?Kt:fr(t),models:[a]}]},Ai=(e,t)=>e.capabilities?.length?e.capabilities.some(a=>{const n=a.toLowerCase();return t.some(o=>n.includes(o))}):!1,Ci=(e,t)=>{if(!e.category)return!1;const a=e.category.toLowerCase();return t.some(n=>a.includes(n))},Dl=[{key:"all",labelKey:"providerSettings.modelsManager.filters.all",predicate:()=>!0},{key:"vision",labelKey:"providerSettings.modelsManager.filters.vision",predicate:e=>Ai(e,["vision","multimodal","image","video"])||Ci(e,["vision","multimodal"])},{key:"reasoning",labelKey:"providerSettings.modelsManager.filters.reasoning",predicate:e=>Ai(e,["reasoning","thinking","cot","chain-of-thought"])||Ci(e,["reasoning","thinking"])},{key:"free",labelKey:"providerSettings.modelsManager.filters.free",predicate:e=>Ai(e,["free","trial"])||Ci(e,["free"])},{key:"tools",labelKey:"providerSettings.modelsManager.filters.tools",predicate:e=>Ai(e,["tool","function","planner"])||Ci(e,["tool"])}];function YM({selectedProvider:e,showEditModelDialog:t,setShowEditModelDialog:a,editModelEntry:n,setEditModelEntry:o,normalizedModelGroups:i,onApplyEditModelDialog:s,setEditingModel:l}){const d=$(),c=()=>{a(!1),l(null),o({id:"",name:"",groupId:"default",openRouterProvider:void 0,vision:void 0,reasoning:void 0})};if(g.useEffect(()=>{if(!t)return;const p=m=>{m.key==="Escape"&&(m.preventDefault(),c())};return window.addEventListener("keydown",p),()=>window.removeEventListener("keydown",p)},[t]),!e||!t)return null;const u=Rl(e);return r.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:r.jsxs("div",{className:`bg-background border rounded-lg shadow-xl w-full ${u?"max-w-lg max-h-[90vh] flex flex-col":"max-w-md"}`,children:[r.jsxs("div",{className:"p-4 border-b flex-shrink-0",children:[r.jsx("h3",{className:"text-lg font-semibold",children:d("providerSettings.modelsManager.editDialog.title")}),r.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:d("providerSettings.modelsManager.editDialog.subtitle")})]}),r.jsxs("div",{className:`p-4 space-y-4 ${u?"overflow-y-auto flex-1":""}`,children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-sm font-medium flex items-center gap-1",children:[d("providerSettings.modelsManager.editDialog.modelId"),r.jsx("span",{className:"text-red-500",children:"*"})]}),r.jsx(V,{value:n.id,onChange:p=>o(m=>({...m,id:p.target.value})),placeholder:d("providerSettings.modelsManager.editDialog.modelIdPlaceholder")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.modelIdHelper")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.modelName")}),r.jsx(V,{value:n.name,onChange:p=>o(m=>({...m,name:p.target.value})),placeholder:d("providerSettings.modelsManager.editDialog.modelNamePlaceholder")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.modelNameHelper")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.group")}),r.jsx(V,{className:"w-full",value:n.groupId,onChange:p=>o(m=>({...m,groupId:p.target.value})),placeholder:d("providerSettings.modelsManager.editDialog.groupPlaceholder")})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.vision")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.visionHint")})]}),r.jsx(me,{checked:n.vision??!1,onCheckedChange:p=>o(m=>({...m,vision:p}))})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.reasoning")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.reasoningHint")})]}),r.jsx(me,{checked:n.reasoning??!1,onCheckedChange:p=>o(m=>({...m,reasoning:p}))})]}),Rl(e)&&r.jsx(Ya,{children:r.jsx(wh,{config:n.openRouterProvider||{},onChange:()=>{}})})]}),r.jsxs("div",{className:"flex items-center justify-end gap-2 border-t px-4 py-3 bg-muted/30 flex-shrink-0",children:[r.jsx(R,{type:"button",variant:"ghost",onClick:c,children:d("providerSettings.modelsManager.editDialog.cancel")}),r.jsx(R,{type:"button",onClick:()=>void s(),disabled:!n.id.trim(),children:d("providerSettings.modelsManager.editDialog.submit")})]})]})})}const XM={},Zu=e=>{let t;const a=new Set,n=(u,p)=>{const m=typeof u=="function"?u(t):u;if(!Object.is(m,t)){const f=t;t=p??(typeof m!="object"||m===null)?m:Object.assign({},t,m),a.forEach(P=>P(t,f))}},o=()=>t,d={setState:n,getState:o,getInitialState:()=>c,subscribe:u=>(a.add(u),()=>a.delete(u)),destroy:()=>{(XM?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),a.clear()}},c=t=e(n,o,d);return d},JM=e=>e?Zu(e):Zu;var Mh={exports:{}},Nh={},Lh={exports:{}},Rh={};/**
342
- * @license React
343
- * use-sync-external-store-shim.production.js
344
- *
345
- * Copyright (c) Meta Platforms, Inc. and affiliates.
346
- *
347
- * This source code is licensed under the MIT license found in the
348
- * LICENSE file in the root directory of this source tree.
349
- */var Tn=g;function eN(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var tN=typeof Object.is=="function"?Object.is:eN,aN=Tn.useState,nN=Tn.useEffect,oN=Tn.useLayoutEffect,iN=Tn.useDebugValue;function rN(e,t){var a=t(),n=aN({inst:{value:a,getSnapshot:t}}),o=n[0].inst,i=n[1];return oN(function(){o.value=a,o.getSnapshot=t,ws(o)&&i({inst:o})},[e,a,t]),nN(function(){return ws(o)&&i({inst:o}),e(function(){ws(o)&&i({inst:o})})},[e]),iN(a),a}function ws(e){var t=e.getSnapshot;e=e.value;try{var a=t();return!tN(e,a)}catch{return!0}}function sN(e,t){return t()}var lN=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?sN:rN;Rh.useSyncExternalStore=Tn.useSyncExternalStore!==void 0?Tn.useSyncExternalStore:lN;Lh.exports=Rh;var dN=Lh.exports;/**
350
- * @license React
351
- * use-sync-external-store-shim/with-selector.production.js
352
- *
353
- * Copyright (c) Meta Platforms, Inc. and affiliates.
354
- *
355
- * This source code is licensed under the MIT license found in the
356
- * LICENSE file in the root directory of this source tree.
357
- */var Hr=g,cN=dN;function uN(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var pN=typeof Object.is=="function"?Object.is:uN,mN=cN.useSyncExternalStore,gN=Hr.useRef,hN=Hr.useEffect,fN=Hr.useMemo,vN=Hr.useDebugValue;Nh.useSyncExternalStoreWithSelector=function(e,t,a,n,o){var i=gN(null);if(i.current===null){var s={hasValue:!1,value:null};i.current=s}else s=i.current;i=fN(function(){function d(f){if(!c){if(c=!0,u=f,f=n(f),o!==void 0&&s.hasValue){var P=s.value;if(o(P,f))return p=P}return p=f}if(P=p,pN(u,f))return P;var y=n(f);return o!==void 0&&o(P,y)?(u=f,P):(u=f,p=y)}var c=!1,u,p,m=a===void 0?null:a;return[function(){return d(t())},m===null?void 0:function(){return d(m())}]},[t,a,n,o]);var l=mN(e,i[0],i[1]);return hN(function(){s.hasValue=!0,s.value=l},[l]),vN(l),l};Mh.exports=Nh;var kN=Mh.exports;const yN=El(kN),Dh={},{useDebugValue:bN}=Mt,{useSyncExternalStoreWithSelector:PN}=yN;let Qu=!1;const AN=e=>e;function CN(e,t=AN,a){(Dh?"production":void 0)!=="production"&&a&&!Qu&&(console.warn("[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"),Qu=!0);const n=PN(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,a);return bN(n),n}const Yu=e=>{(Dh?"production":void 0)!=="production"&&typeof e!="function"&&console.warn("[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.");const t=typeof e=="function"?JM(e):e,a=(n,o)=>CN(t,n,o);return Object.assign(a,t),a},xN=e=>e?Yu(e):Yu,Qa=xN((e,t)=>({providers:[],loading:!1,error:null,loaded:!1,async refresh(){e({loading:!0,error:null});try{const a=await K.llmConfig.getProviders();e({providers:a,loading:!1,loaded:!0})}catch(a){e({loading:!1,loaded:!0,error:a instanceof Error?a.message:"Failed to load providers"})}},updateProvider(a){e({providers:t().providers.map(n=>n.id===a.id?a:n)})}}));function zN(){const e=Qa(s=>s.providers),t=Qa(s=>s.loading),a=Qa(s=>s.error),n=Qa(s=>s.loaded),o=Qa(s=>s.refresh),i=Qa(s=>s.updateProvider);return g.useEffect(()=>{!n&&!t&&o()},[]),{providers:e,loading:t,error:a,refresh:o,updateProvider:i}}function IN(e,t,a){const[n,o]=g.useState(""),[i,s]=g.useState("all"),[l,d]=g.useState({}),[c,u]=g.useState(a),[p,m]=g.useState(e?.id);(c!==a||p!==e?.id)&&(u(a),m(e?.id),a||(o(""),s("all"),d({})));const f=g.useMemo(()=>Dl.find(h=>h.key===i)??Dl[0],[i]),P=g.useMemo(()=>{const h=n.trim().toLowerCase();return t.length?t.filter(k=>{const v=!h||k.name?.toLowerCase().includes(h)||k.id.toLowerCase().includes(h)||(k.description?.toLowerCase().includes(h)??!1),b=f.predicate(k);return v&&b}):[]},[t,n,f]),y=g.useMemo(()=>!e||!P.length?[]:QM(e,P),[e,P]);return{catalogSearchTerm:n,setCatalogSearchTerm:o,catalogFilter:i,setCatalogFilter:s,catalogCollapsedGroups:l,toggleCatalogGroup:h=>{d(k=>({...k,[h]:!k[h]}))},filteredDiscoveryModels:P,catalogGroups:y}}function SN(e,t){const a=$(),[n,o]=g.useState(""),[i,s]=g.useState({}),[l,d]=g.useState(!1),[c,u]=g.useState(!1),[p,m]=g.useState({}),[f,P]=g.useState(!1),[y,A]=g.useState(null),[h,k]=g.useState({id:"",name:"",groupId:"default",openRouterProvider:void 0,vision:void 0,reasoning:void 0}),[v,b]=g.useState(null),[z,I]=g.useState(null),[C,S]=g.useState(!1),[L,T]=g.useState({id:"",name:"",groupId:"default",openRouterProvider:void 0,vision:void 0,reasoning:void 0}),M=g.useCallback(x=>{t(x)},[t]),D=g.useMemo(()=>e?e.modelConfigs?.length?e.modelConfigs:(e.models||[]).map(x=>({id:x,name:x,enabled:!0})):[],[e]),Q=g.useMemo(()=>{if(!e)return[];if(!e.modelGroups?.length){const Y=jh(e,D);if(Y)return Y}const x=new Map(D.map(Y=>[Y.id,Y])),j=(e.modelGroups||[]).map(Y=>{const he=(Y.models||[]).map(et=>x.get(et.id)||{...et,enabled:et.enabled??!0}).filter(et=>!!et);return{...Y,models:he}}),F=new Set;j.forEach(Y=>{Y.models.forEach(he=>F.add(he.id))});const B=D.filter(Y=>!F.has(Y.id)),ee=[...j];if(B.length>0){const Y=ee.findIndex(he=>he.id===Le);Y>=0?ee[Y]={...ee[Y],models:[...ee[Y].models,...B]}:ee.push({id:Le,name:Kt,models:B})}return ee.length?ee:[{id:Le,name:Kt,models:D}]},[e,D]),W=Q[0]?.id||Le,J=g.useMemo(()=>new Set(D.map(x=>x.id)),[D]),ye=g.useMemo(()=>{if(!n.trim())return Q;const x=n.trim().toLowerCase();return Q.map(j=>({...j,models:j.models.filter(F=>(F.name?.toLowerCase()||"").includes(x)||F.id.toLowerCase().includes(x))})).filter(j=>j.models.length>0)},[Q,n]),ve=e?p[e.id]:null,w=ve?.models??[],E=()=>e?e.modelConfigs?.length?e.modelConfigs:(e.models||[]).map(x=>({id:x,name:x,enabled:!0})):[],U=async(x,j,F)=>{try{const B={id:x.id,models:j.map(Y=>Y.id),modelConfigs:j,modelGroups:F??Ss(x,j)},ee=await K.llmConfig.updateProvider(B);if(ee.provider)return M(ee.provider),ee.provider;ee.message&&b({type:"error",message:ee.message})}catch(B){b({type:"error",message:B instanceof Error?B.message:a("providerSettings.errors.saveFailed")})}return null},Z=(x,j="success")=>{b({type:j,message:a(x)})};g.useEffect(()=>{e&&k(x=>({...x,groupId:W}))},[e?.id,W]),g.useEffect(()=>{b(null),I(null),o("")},[e?.id]),g.useEffect(()=>{if(!v)return;const x=setTimeout(()=>b(null),3e3);return()=>clearTimeout(x)},[v]),g.useEffect(()=>{l&&e&&fa()},[l,e?.id]);const ae=async x=>{if(!e)return;const F=E().filter(ee=>ee.id!==x);await U(e,F)&&Z("providerSettings.modelsManager.messages.removed")},_e=async(x,j,F,B,ee,Y)=>{if(!e)return;const he=x.trim();if(!he)return;const et=E();if(et.some(Vo=>Vo.id===he)){Z("providerSettings.modelsManager.messages.duplicate","error");return}const Ha={id:he,name:j.trim()||he,enabled:!0,openRouterProvider:B&&Object.keys(B).length>0?B:void 0,vision:ee,reasoning:Y},Dn=[...et,Ha],Fa=Ss(e,Dn),Bo=F.trim()||_d(e.id,he)||Fa[0]?.id||Le,Fr=Wu(Fa,Bo,Ha);await U(e,Dn,Fr)&&(Z("providerSettings.modelsManager.messages.added"),u(!1),k({id:"",name:"",groupId:Bo,openRouterProvider:void 0,vision:void 0,reasoning:void 0}))},xe=async x=>{if(!e)return;const j=E();if(j.some(Fa=>Fa.id===x.id)){Z("providerSettings.modelsManager.messages.duplicate","error");return}const F=["chat","reasoning","image","video","embedding","code"],B=x.category&&F.includes(x.category)?x.category:"chat",ee=new Set(x.capabilities??[]),Y={id:x.id,name:x.name||x.id,enabled:!0,contextLength:x.contextLength,maxTokens:x.maxTokens,category:B,...ee.has("vision")?{vision:!0}:{},...ee.has("function_call")?{functionCall:!0}:{},...ee.has("reasoning")?{reasoning:!0}:{},...ee.has("web_search")?{webSearch:!0}:{}},he=[...j,Y],et=Ss(e,he),Ha=Wu(et,W,Y);await U(e,he,Ha)&&Z("providerSettings.modelsManager.messages.added")},ne=async()=>{if(!e||!z)return;const x=z.name.trim();if(!x)return;const j=E().map(B=>B.id===z.id?{...B,name:x}:B);await U(e,j)&&(Z("providerSettings.modelsManager.messages.updated"),I(null))},Pe=async()=>{if(!e||!C)return;const x=L.id.trim(),j=L.name.trim();if(!x)return;const F=E(),B=z?F.find(he=>he.id===z.id):null;if(!B)return;const ee=F.map(he=>he.id===B.id?{...he,id:x,name:j||x,group:L.groupId||"default",openRouterProvider:L.openRouterProvider,vision:L.vision,reasoning:L.reasoning}:he);await U(e,ee)&&(Z("providerSettings.modelsManager.messages.updated"),S(!1),I(null),T({id:"",name:"",groupId:"default",openRouterProvider:void 0,vision:void 0,reasoning:void 0}))},Ge=async(x,j)=>{if(!e)return;const F=E().map(B=>B.id===x?{...B,enabled:j}:B);await U(e,F)},ht=x=>{s(j=>({...j,[x]:!j[x]}))},fa=async(x=!1)=>{if(e){P(!0),A(null);try{const j=await K.llmConfig.discoverModels(e.id,x?{forceRefresh:!0}:void 0);m(F=>({...F,[e.id]:j})),!j.success&&j.error&&A(j.error)}catch(j){A(j instanceof Error?j.message:a("providerSettings.errors.saveFailed"))}finally{P(!1)}}};return{modelSearch:n,setModelSearch:o,collapsedGroups:i,toggleGroupCollapse:ht,showManageModels:l,setShowManageModels:d,showAddModelDialog:c,setShowAddModelDialog:u,modelDiscoveryLoading:f,modelDiscoveryError:y,newModelEntry:h,setNewModelEntry:k,modelStatus:v,editingModel:z,setEditingModel:I,showEditModelDialog:C,setShowEditModelDialog:S,editModelEntry:L,setEditModelEntry:T,visibleModelGroups:ye,normalizedModelGroups:Q,defaultGroupId:W,discoveryResult:ve,discoveryModels:w,existingModelIds:J,handleRemoveModel:ae,handleAddModelEntry:_e,handleAddDiscoveredModel:xe,handleApplyModelEdit:ne,handleApplyEditModelDialog:Pe,handleToggleModelEnabled:Ge,loadModelDiscovery:fa,onShowEditModelDialog:x=>{I({id:x.id,name:x.name||x.id}),T({id:x.id,name:x.name||x.id,groupId:x.group||"default",openRouterProvider:x.openRouterProvider,vision:x.vision,reasoning:x.reasoning}),S(!0)}}}function wN(e,t,a,n,o,i){const s=$(),[l,d]=g.useState(!1),[c,u]=g.useState(!1),[p,m]=g.useState(Gu),[f,P]=g.useState(!1),[y,A]=g.useState(null),[h,k]=g.useState(!1),[v,b]=g.useState(""),[z,I]=g.useState(""),[C,S]=g.useState(""),[L,T]=g.useState(""),[M,D]=g.useState(""),Q=g.useCallback(x=>{i(x)},[i]),[W,J]=g.useState(n?.id);W!==n?.id&&(J(n?.id),n&&(S(n.api_key?.startsWith("$")?n.api_key:""),T(n.api_base_url||""),b(kn(s,n)),I(n.modelsEndpoint||""),D(n.maxConcurrency!=null?String(n.maxConcurrency):"")));const ye=x=>{a(x),d(!1),u(!1),A(null)},ve=()=>{m(Gu),u(!0),d(!1),a(null),P(!1),A(null),k(!1)},w=async(x,j)=>{try{const F=await K.llmConfig.addFromPreset?.({presetId:x.presetId??x.id,apiKey:j.apiKey,enabled:j.enabled});return F&&!F.success?(A(F.message??s("providerSettings.errors.saveFailed")),!1):(a(F?.provider?.id??x.id),A(null),await o(),!0)}catch(F){return console.error("Error materializing preset:",F),A(s("providerSettings.errors.saveFailed")),!1}};return{isEditing:l,isAddingNew:c,formData:p,setFormData:m,formError:y,showTemplates:h,setShowTemplates:k,showApiKey:f,setShowApiKey:P,inlineName:v,setInlineName:b,inlineModelsEndpoint:z,setInlineModelsEndpoint:I,inlineApiKey:C,setInlineApiKey:S,inlineApiUrl:L,setInlineApiUrl:T,inlineMaxConcurrency:M,setInlineMaxConcurrency:D,handleSelectProvider:ye,handleAddProvider:ve,handleUseTemplate:x=>{m({name:x.name,apiFormat:x.apiFormat||"openai",chatApiFormat:x.chatApiFormat||x.apiFormat||"openai",apiType:x.apiType,api_base_url:x.api_base_url,api_key:"",models:[...x.models],modelConfigs:x.modelConfigs?[...x.modelConfigs]:[],modelGroups:x.modelGroups?[...x.modelGroups]:[],modelsEndpoint:x.modelsEndpoint,enabled:!0,icon:x.icon,transformer:x.transformer,apiVersion:x.apiVersion,maxConcurrency:x.maxConcurrency}),k(!1)},handleEditProvider:()=>{n&&(m({name:n.name,apiFormat:n.apiFormat||"openai",chatApiFormat:n.chatApiFormat||n.apiFormat||"openai",apiType:n.apiType||"openai",api_base_url:n.api_base_url||"",api_key:n.api_key?.startsWith("$")?n.api_key:"",models:n.models||[],modelConfigs:n.modelConfigs||[],modelGroups:n.modelGroups||[],modelsEndpoint:n.modelsEndpoint||"",enabled:n.enabled,icon:n.icon,transformer:n.transformer,apiVersion:n.apiVersion,isOfficial:n.isOfficial,maxConcurrency:n.maxConcurrency}),d(!0),u(!1),P(!1),A(null))},handleSaveProvider:async()=>{if(!p.name.trim()){A(s("providerSettings.errors.nameRequired"));return}if(!p.api_base_url.trim()){A(s("providerSettings.errors.urlRequired"));return}try{new URL(p.api_base_url.trim())}catch{A(s("providerSettings.errors.urlInvalid"));return}if(n?.__preset){await w(n,{apiKey:p.api_key.trim()||void 0,enabled:p.enabled})&&(d(!1),u(!1));return}try{if(l&&t){const x=p.api_key.trim().length>0;await K.llmConfig.updateProvider({id:t,name:p.name,apiFormat:p.apiFormat,chatApiFormat:p.chatApiFormat,apiType:p.apiType,api_base_url:p.api_base_url,...x?{api_key:p.api_key}:{},models:p.models,modelConfigs:p.modelConfigs,modelGroups:p.modelGroups,modelsEndpoint:p.modelsEndpoint,enabled:p.enabled,icon:p.icon,transformer:p.transformer,apiVersion:p.apiVersion,isOfficial:p.isOfficial,maxConcurrency:p.maxConcurrency,codingPlan:p.codingPlan,presetId:p.presetId})}else{const x=await K.llmConfig.addProvider({name:p.name,apiFormat:p.apiFormat,chatApiFormat:p.chatApiFormat,apiType:p.apiType,api_base_url:p.api_base_url,api_key:p.api_key,models:p.models,modelConfigs:p.modelConfigs,modelGroups:p.modelGroups,modelsEndpoint:p.modelsEndpoint,enabled:p.enabled,icon:p.icon,transformer:p.transformer,apiVersion:p.apiVersion,isOfficial:p.isOfficial,maxConcurrency:p.maxConcurrency,codingPlan:p.codingPlan,presetId:p.presetId});if(x.provider)a(x.provider.id);else if(x.message){A(x.message);return}}d(!1),u(!1),await o()}catch(x){console.error("Error saving provider:",x),A(s("providerSettings.errors.saveFailed"))}},handleCancelEdit:()=>{d(!1),u(!1),A(null),e.length>0&&!t&&a(e[0].id)},handleInlineUpdate:async(x,j)=>{if(!(!t||!n)){if(n.__preset){x==="api_key"&&j.trim().length>0&&await w(n,{apiKey:j});return}if(!(x==="api_key"&&j.trim().length===0))try{const B=x==="maxConcurrency"?j&&parseInt(j,10)||null:x==="modelsEndpoint"||x==="apiVersion"?j||null:j,ee=await K.llmConfig.updateProvider({id:t,[x]:B});if(!ee.success){console.error("Failed to update provider:",ee.message);return}Q({...n,[x]:B}),await o()}catch(F){console.error("Error updating provider:",F)}}},handleReorderProviders:async x=>{try{const j=await K.llmConfig.reorderProviders?.(x);j&&!j.success&&console.error("Failed to reorder providers:",j.message),await o()}catch(j){console.error("Error reordering providers:",j)}},handleSelectApiMode:async(x,j)=>{if(!t||!n)return!1;const F=n.apiModes;if(!F||F.length===0)return!1;const B=F.find(Y=>Y.id===x);if(!B)return!1;const ee={selectedApiModeId:x,apiFormat:n.apiFormat,api_base_url:j?.keepCustomizations?n.api_base_url:B.baseUrl};try{const Y=await K.llmConfig.updateProvider({id:t,...ee});return Y.success?(j?.keepCustomizations||(T(B.baseUrl),B.apiKey&&S(B.apiKey)),Q({...n,selectedApiModeId:x,...j?.keepCustomizations?{}:{api_base_url:B.baseUrl,...B.apiKey?{api_key:B.apiKey}:{}}}),await o(),!0):(console.error("Failed to switch api mode:",Y.message),!1)}catch(Y){return console.error("Error switching api mode:",Y),!1}},handleToggleProvider:async x=>{if(!t||!n)return;if(n.__preset){await w(n,{enabled:x,apiKey:C.trim()||void 0});return}const j=C.trim(),F=j.length>0&&j!==(n.api_key||"");try{if(F){const B=await K.llmConfig.updateProvider({id:t,enabled:x,api_key:j});if(!B.success){console.error("Failed to enable provider with key:",B.message);return}S("")}else await K.llmConfig.toggleProvider(t,x);await o()}catch(B){console.error("Error toggling provider:",B)}},handleToggleOfficial:async x=>{if(!(!t||!n))try{const j=await K.llmConfig.updateProvider({id:t,isOfficial:x});if(!j.success){console.error("Failed to update isOfficial:",j.message);return}Q({...n,isOfficial:x}),await o()}catch(j){console.error("Error toggling isOfficial:",j)}},handleDeleteProvider:async()=>{if(!(!t||!n)){if(n.isSystem){console.warn("Cannot delete system provider");return}try{const x=await K.llmConfig.deleteProvider(t);x.success?(a(null),await o()):console.error("Failed to delete provider:",x.message)}catch(x){console.error("Error deleting provider:",x)}}},handleResetProvider:async x=>{const j=x??t;if(j)try{const F=await K.llmConfig.resetProvider?.(j);if(F&&!F.success){console.error("Failed to reset provider:",F.message);return}await o()}catch(F){console.error("Error resetting provider:",F)}},revealApiKey:async()=>{if(!(!t||!n))try{const x=await K.llmConfig.revealProviderKey?.(t);x?.success&&typeof x.apiKey=="string"&&x.apiKey.length>0&&(S(x.apiKey),Q({...n,api_key:x.apiKey}))}catch(x){console.error("Error revealing provider key:",x)}}}}function TN(e){return e==="gemini"?"google":e}function jN(e){return{id:e.id,name:e.name,apiFormat:TN(e.apiFormat),api_base_url:e.baseUrl,api_key:"",hasKey:!1,models:e.models??[],enabled:!1,presetId:e.presetId,__preset:!0,isSystem:!0}}function MN(e,t){if(t.length===0)return e;const a=new Set(t.map(s=>s.id)),n=new Map(e.map(s=>[s.id,s])),o=e.filter(s=>!a.has(s.id)),i=t.map(s=>{const l=n.get(s.id);return l?{...l,isSystem:!0,presetId:l.presetId??s.presetId}:jN(s)});return[...o,...i]}function NN(){const{providers:e,loading:t,error:a,refresh:n,updateProvider:o}=zN(),[i,s]=g.useState([]);g.useEffect(()=>{let k=!0;return K.llmConfig.getPresets().then(v=>{k&&s(v??[])}),()=>{k=!1}},[]);const l=g.useMemo(()=>MN(e,i),[e,i]),[d,c]=g.useState(""),[u,p]=g.useState(null),m=u??(l.length>0?l[0].id:null),f=g.useMemo(()=>l.find(k=>k.id===m)||null,[l,m]),P=g.useMemo(()=>l.filter(k=>k.enabled&&k.hasKey===!1).map(k=>k.id),[l]),y=wN(l,m,p,f,n,o),A=SN(f,o),h=IN(f,A.discoveryModels,A.showManageModels);return{providers:l,providersLoading:t,providersError:a,searchTerm:d,setSearchTerm:c,selectedProviderId:m,selectedProvider:f,missingKeyProviderIds:P,missingKeyCount:P.length,...y,...A,...h}}function LN({selectedProvider:e,showManageModels:t,setShowManageModels:a,discoveryResult:n,filteredDiscoveryModels:o,catalogGroups:i,catalogSearchTerm:s,setCatalogSearchTerm:l,catalogFilter:d,setCatalogFilter:c,catalogCollapsedGroups:u,toggleCatalogGroup:p,modelDiscoveryLoading:m,modelDiscoveryError:f,existingModelIds:P,onLoadModelDiscovery:y,onAddDiscoveredModel:A}){const h=$();if(g.useEffect(()=>{if(!t)return;const b=z=>{z.key==="Escape"&&(z.preventDefault(),a(!1))};return window.addEventListener("keydown",b),()=>window.removeEventListener("keydown",b)},[t,a]),!e||!t)return null;const k=n?.source==="network"?h("providerSettings.modelsManager.manageDialog.sourceNetwork"):h("providerSettings.modelsManager.manageDialog.sourceCache"),v=!o.length&&!m;return r.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:r.jsxs("div",{className:"bg-background border rounded-lg shadow-2xl w-full max-w-3xl max-h-[90vh] flex flex-col",children:[r.jsxs("div",{className:"p-4 border-b flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsxs("h3",{className:"text-lg font-semibold",children:[h("providerSettings.modelsManager.manageDialog.title")," · ",e.name]}),r.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:n?.fetchedAt?h("providerSettings.modelsManager.manageDialog.cachedAt",{date:new Date(n.fetchedAt).toLocaleString(),source:k}):h("providerSettings.modelsManager.manageDialog.empty")})]}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsxs(R,{type:"button",variant:"ghost",size:"sm",onClick:()=>void y(!0),disabled:m,children:[r.jsx(Fo,{className:`h-4 w-4 mr-1 ${m?"animate-spin":""}`}),h("providerSettings.modelsManager.manageDialog.refresh")]}),r.jsx(R,{type:"button",variant:"outline",size:"sm",onClick:()=>a(!1),children:h("providerSettings.modelsManager.manageDialog.close")})]})]}),r.jsxs("div",{className:"px-4 py-3 border-b space-y-2",children:[r.jsxs("div",{className:"relative",children:[r.jsx(Tg,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),r.jsx(V,{value:s,onChange:b=>l(b.target.value),placeholder:h("providerSettings.modelsManager.searchPlaceholder"),className:"pl-8 pr-8"}),s?r.jsx("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground",onClick:()=>l(""),children:r.jsx(Da,{className:"h-4 w-4"})}):null]}),r.jsx("div",{className:"flex flex-wrap gap-2 text-xs",children:Dl.map(b=>r.jsx("button",{type:"button",className:G("px-3 py-1 rounded-full border transition-colors",d===b.key?"bg-primary text-primary-foreground border-primary":"border-border text-muted-foreground hover:text-foreground"),onClick:()=>c(b.key),children:h(b.labelKey)},b.key))})]}),r.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-4",children:[f?r.jsx("div",{className:"text-sm text-destructive border border-destructive/30 bg-destructive/10 px-3 py-2 rounded",children:h("providerSettings.modelsManager.manageDialog.error",{message:f})}):null,m?r.jsx("div",{className:"text-center text-sm text-muted-foreground py-10",children:h("providerSettings.loading")}):v?r.jsx("div",{className:"text-sm text-muted-foreground",children:h("providerSettings.modelsManager.manageDialog.empty")}):r.jsx("div",{className:"space-y-3",children:i.map(b=>r.jsxs("div",{className:"border rounded-md overflow-hidden",children:[r.jsxs("button",{type:"button",className:"w-full flex items-center justify-between px-3 py-2 bg-muted/40 hover:bg-muted/60 transition-colors",onClick:()=>p(b.id),children:[r.jsxs("div",{children:[r.jsx("div",{className:"text-sm font-medium",children:b.id===Le?h("providerSettings.modelsManager.defaultGroup"):b.name}),r.jsx("div",{className:"text-xs text-muted-foreground",children:h("providerSettings.listStatus",{count:b.models.length})})]}),u[b.id]?r.jsx(ga,{className:"h-4 w-4"}):r.jsx(Ld,{className:"h-4 w-4"})]}),!u[b.id]&&r.jsx("div",{className:"divide-y",children:b.models.map(z=>{const I=P.has(z.id);return r.jsxs("div",{className:"flex flex-col gap-3 px-3 py-3 md:flex-row md:items-center",children:[r.jsxs("div",{className:"flex-1 min-w-0",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("div",{className:"font-medium text-sm truncate",children:z.name||z.id}),r.jsx("div",{className:"text-xs text-muted-foreground truncate",children:z.id})]}),z.description?r.jsx("p",{className:"text-xs text-muted-foreground mt-1 line-clamp-2",children:z.description}):null,z.contextLength||z.maxTokens?r.jsxs("div",{className:"text-[11px] text-muted-foreground mt-1",children:[z.contextLength?h("providerSettings.modelsManager.manageDialog.contextLength",{value:z.contextLength}):null,z.contextLength&&z.maxTokens?" · ":null,z.maxTokens?h("providerSettings.modelsManager.manageDialog.maxTokens",{value:z.maxTokens}):null]}):null,z.capabilities?.length?r.jsx("div",{className:"flex flex-wrap gap-1 mt-2",children:z.capabilities.slice(0,6).map(C=>r.jsx(Be,{variant:"secondary",className:"text-[10px] uppercase tracking-wide",children:C},`${z.id}-${C}`))}):null]}),r.jsx(R,{type:"button",size:"sm",variant:I?"outline":"default",disabled:I,onClick:()=>void A(z),children:h(I?"providerSettings.modelsManager.messages.duplicate":"providerSettings.modelsManager.manageDialog.addFromCatalog")})]},z.id)})})]},b.id))}),n?.raw?r.jsxs("details",{className:"border rounded-md",children:[r.jsx("summary",{className:"cursor-pointer px-3 py-2 text-sm font-medium",children:h("providerSettings.modelsManager.manageDialog.raw")}),r.jsx("pre",{className:"text-xs bg-muted/40 p-3 max-h-64 overflow-y-auto",children:JSON.stringify(n.raw,null,2)})]}):null]})]})})}function RN({selectedProvider:e,showAddModelDialog:t,setShowAddModelDialog:a,newModelEntry:n,setNewModelEntry:o,normalizedModelGroups:i,defaultGroupId:s,onAddModelEntry:l}){const d=$(),c=$d(),u=()=>{a(!1),o({id:"",name:"",groupId:s,openRouterProvider:void 0,vision:void 0,reasoning:void 0})};if(g.useEffect(()=>{if(!t)return;const m=f=>{f.key==="Escape"&&(f.preventDefault(),u())};return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[t]),!e||!t)return null;const p=Rl(e);return r.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:r.jsxs("div",{className:`bg-background border rounded-lg shadow-xl w-full ${p?"max-w-lg max-h-[90vh] flex flex-col":"max-w-md"}`,children:[r.jsxs("div",{className:"p-4 border-b flex-shrink-0",children:[r.jsx("h3",{className:"text-lg font-semibold",children:d("providerSettings.modelsManager.manualDialog.title")}),r.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:d("providerSettings.modelsManager.manualDialog.subtitle")})]}),r.jsxs("div",{className:`p-4 space-y-4 ${p?"overflow-y-auto flex-1":""}`,children:[r.jsxs("div",{className:"space-y-1.5",children:[r.jsxs("label",{className:"text-sm font-medium flex items-center gap-1",children:[d("providerSettings.modelsManager.manualDialog.modelId"),r.jsx("span",{className:"text-red-500",children:"*"})]}),r.jsx(V,{value:n.id,onChange:m=>o(f=>({...f,id:m.target.value})),placeholder:d("providerSettings.modelsManager.manualDialog.modelIdPlaceholder")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.manualDialog.modelIdHelper")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.manualDialog.modelName")}),r.jsx(Ya,{children:r.jsx(V,{value:n.name,disabled:!0,title:c,placeholder:d("providerSettings.modelsManager.manualDialog.modelNamePlaceholder")})}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.manualDialog.modelNameHelper")})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.manualDialog.group")}),r.jsx(Ya,{children:r.jsx(V,{className:"w-full",value:n.groupId,disabled:!0,title:c,placeholder:d("providerSettings.modelsManager.manualDialog.groupPlaceholder")})})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.vision")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.visionHint")})]}),r.jsx(Ya,{children:r.jsx(me,{checked:n.vision??!1,disabled:!0})})]}),r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:d("providerSettings.modelsManager.editDialog.reasoning")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:d("providerSettings.modelsManager.editDialog.reasoningHint")})]}),r.jsx(Ya,{children:r.jsx(me,{checked:n.reasoning??!1,disabled:!0})})]}),p?r.jsx(Ya,{children:r.jsx(wh,{config:n.openRouterProvider||{},onChange:()=>{}})}):null]}),r.jsxs("div",{className:"flex items-center justify-end gap-2 border-t px-4 py-3 bg-muted/30 flex-shrink-0",children:[r.jsx(R,{type:"button",variant:"ghost",onClick:u,children:d("providerSettings.modelsManager.manualDialog.cancel")}),r.jsx(R,{type:"button",onClick:()=>void l(n.id,n.name,n.groupId,n.openRouterProvider,n.vision,n.reasoning),disabled:!n.id.trim(),children:d("providerSettings.modelsManager.manualDialog.submit")})]})]})})}const Jn=g.forwardRef(({label:e,description:t,error:a,htmlFor:n,labelAction:o,children:i,className:s},l)=>r.jsxs("div",{ref:l,className:G("space-y-2",s),children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("label",{htmlFor:n,className:"text-sm font-medium",children:e}),o?r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"flex-1"}),o]}):null]}),i,a?r.jsx("p",{className:"text-xs text-destructive",children:a}):t?r.jsx("p",{className:"text-xs text-muted-foreground",children:t}):null]}));Jn.displayName="FormField";function DN(e,t,a){return t&&t.until>a?"cooling":!e.enabled&&e.disabledReason==="auth_failure"?"authFailed":e.enabled?"healthy":"disabled"}function EN(e){const t=Math.max(0,Math.ceil(e/1e3)),a=Math.floor(t/60),n=t%60;return`${a}:${n.toString().padStart(2,"0")}`}function ON(e,t){const a=Math.max(0,t-e),n=Math.floor(a/1e3);if(n<60)return{unitKey:"agoSeconds",value:n};const o=Math.floor(n/60);if(o<60)return{unitKey:"agoMinutes",value:o};const i=Math.floor(o/60);return i<24?{unitKey:"agoHours",value:i}:{unitKey:"agoDays",value:Math.floor(i/24)}}function KN({entry:e,health:t,now:a}){const n=$(),o=DN(e,t,a);if(o==="cooling"&&t){const i=EN(t.until-a),s=t.lastStatus??e.lastErrorStatus??null;return r.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-warning/15 text-warning",title:s?String(s):void 0,children:[r.jsx(qk,{className:"h-2.5 w-2.5","aria-hidden":"true"}),n("providerSettings.apiKeyPool.statusCoolingDown",{time:i}),s?r.jsxs("span",{className:"opacity-80",children:["· ",s]}):null]})}if(o==="authFailed"){const i=e.lastErrorStatus??null,s=e.lastErrorAt?ON(e.lastErrorAt,a):null;return r.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-destructive/15 text-destructive",children:[r.jsx(Pg,{className:"h-2.5 w-2.5","aria-hidden":"true"}),n("providerSettings.apiKeyPool.statusAuthFailed"),i?r.jsxs("span",{className:"opacity-80",children:["· ",i]}):null,s?r.jsxs("span",{className:"opacity-70",children:["·"," ",n(`providerSettings.apiKeyPool.${s.unitKey}`,{count:s.value})]}):null]})}return o==="disabled"?r.jsx("span",{className:"text-[10px] px-1 py-0.5 rounded bg-muted text-muted-foreground",children:n("providerSettings.disabled")}):r.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] text-success",title:n("providerSettings.apiKeyPool.statusHealthy"),children:[r.jsx("span",{className:"inline-block h-1.5 w-1.5 rounded-full bg-success","aria-hidden":"true"}),r.jsx("span",{className:"sr-only",children:n("providerSettings.apiKeyPool.statusHealthy")})]})}const xi=!1,UN=3e3,HN=1e3;function FN({providerId:e}){const t=$();$d();const[a,n]=g.useState(!1),[o,i]=g.useState([]),[s,l]=g.useState(!1),[d,c]=g.useState(!1),[u,p]=g.useState({}),[m,f]=g.useState(()=>Date.now()),[P,y]=g.useState(""),[A,h]=g.useState(""),[k,v]=g.useState(1),b=g.useCallback(async()=>{if(e){l(!0);try{const T=await K.llmConfig.getApiKeys(e);i(T)}catch{}finally{l(!1)}}},[e]);g.useEffect(()=>{a&&b()},[a,b]),g.useEffect(()=>{if(!a||!e){p({});return}let T=!1;const M=async()=>{try{const W=await K.llmConfig.getKeyHealth(e);T||p(W)}catch{T||p({})}};M();const D=window.setInterval(()=>void M(),UN),Q=window.setInterval(()=>{T||f(Date.now())},HN);return()=>{T=!0,window.clearInterval(D),window.clearInterval(Q)}},[a,e]);const z=async()=>{if(!A.trim())return;const T={providerId:e,label:P.trim()||`Key #${o.length+1}`,apiKey:A.trim(),weight:k};(await K.llmConfig.addApiKey(T)).success&&(c(!1),y(""),h(""),v(1),b())},I=async T=>{(await K.llmConfig.deleteApiKey(e,T)).success&&b()},C=async(T,M)=>{await K.llmConfig.toggleApiKey(e,T,M),b()},S=async(T,M)=>{const D=Math.max(1,Math.min(100,M));await K.llmConfig.updateApiKey(e,T,{weight:D}),b()},L=T=>T.apiKey&&T.apiKey.startsWith("$")?T.apiKey:T.keyHint?T.keyHint:T.hasKey?"••••••••":t("providerSettings.apiKeyPool.noKey");return r.jsxs("div",{className:"border rounded-lg",children:[r.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-3 hover:bg-muted/50 transition-colors",onClick:()=>n(!a),children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(Sg,{className:"h-4 w-4 text-muted-foreground"}),r.jsx("span",{className:"text-sm font-medium",children:t("providerSettings.apiKeyPool.title")}),o.length>0&&r.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-primary/10 text-primary",children:o.length})]}),a?r.jsx(ga,{className:"h-4 w-4 text-muted-foreground"}):r.jsx(Nd,{className:"h-4 w-4 text-muted-foreground"})]}),a?r.jsxs("div",{className:"border-t p-3 space-y-3",children:[r.jsx("p",{className:"text-xs text-muted-foreground",children:t("providerSettings.apiKeyPool.description")}),s?r.jsx("div",{className:"text-xs text-muted-foreground",children:t("providerSettings.loading")}):r.jsxs(r.Fragment,{children:[o.length>0&&r.jsx("div",{className:"space-y-2",children:o.map(T=>r.jsxs("div",{className:"flex items-center gap-2 p-2 rounded border bg-surface-1/70 wallpaper-blur",children:[r.jsxs("div",{className:"flex-1 min-w-0 space-y-1",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"text-sm font-medium truncate",children:T.label||t("providerSettings.apiKeyPool.defaultLabel")}),r.jsx(KN,{entry:T,health:u[T.id],now:m})]}),r.jsx("div",{className:"flex items-center gap-2",children:r.jsx("code",{className:"text-xs text-muted-foreground",children:L(T)})})]}),r.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[r.jsx("label",{className:"text-[10px] text-muted-foreground",children:t("providerSettings.apiKeyPool.weight")}),r.jsx(V,{type:"number",min:1,max:100,value:T.weight,onChange:M=>{const D=parseInt(M.target.value,10);isNaN(D)||S(T.id,D)},disabled:xi,title:void 0,className:"w-14 h-7 text-xs text-center"})]}),r.jsx(me,{checked:T.enabled,onCheckedChange:M=>void C(T.id,M),disabled:xi,title:void 0}),r.jsx(R,{variant:"ghost",size:"icon",className:"h-7 w-7 text-destructive hover:text-destructive",onClick:()=>void I(T.id),disabled:xi,title:void 0,children:r.jsx(In,{className:"h-3.5 w-3.5"})})]},T.id))}),d?r.jsxs("div",{className:"space-y-2 p-2 rounded border bg-surface-1/30 wallpaper-blur",children:[r.jsx(V,{placeholder:t("providerSettings.apiKeyPool.labelPlaceholder"),value:P,onChange:T=>y(T.target.value)}),r.jsx(Sn,{placeholder:t("providerSettings.form.apiKeyPlaceholder"),value:A,onChange:T=>h(T.target.value)}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("label",{className:"text-xs text-muted-foreground",children:t("providerSettings.apiKeyPool.weight")}),r.jsx(V,{type:"number",min:1,max:100,value:k,onChange:T=>v(parseInt(T.target.value,10)||1),className:"w-20"})]}),r.jsxs("div",{className:"flex gap-2 justify-end",children:[r.jsx(R,{variant:"outline",size:"sm",onClick:()=>{c(!1),y(""),h(""),v(1)},children:t("providerSettings.form.buttons.cancel")}),r.jsx(R,{size:"sm",onClick:()=>void z(),disabled:!A.trim(),children:t("providerSettings.apiKeyPool.add")})]})]}):r.jsxs(R,{variant:"outline",size:"sm",className:"w-full",onClick:()=>c(!0),disabled:xi,title:void 0,children:[r.jsx(Ra,{className:"h-4 w-4 mr-1"}),t("providerSettings.apiKeyPool.addKey")]})]})]}):null]})}function BN({open:e,onOpenChange:t,providerId:a,providerName:n,modelId:o,modelName:i}){const s=$(),[l,d]=g.useState(!1),[c,u]=g.useState(null),p=g.useCallback(async()=>{d(!0),u(null);try{const f=await K.llmConfig.testModel(a,o);f.unsupportedFormat?u({success:!1,message:s("providerSettings.modelsManager.testDialog.unsupportedFormat")}):u({success:f.ok,message:f.message??"",response:f.sample,durationMs:f.latencyMs})}catch(f){u({success:!1,message:f instanceof Error?f.message:"test failed"})}finally{d(!1)}},[a,o,s]);g.useEffect(()=>{e?p():u(null)},[e,p]);const m=c?.durationMs!=null?(c.durationMs/1e3).toFixed(2):null;return r.jsx(Ft,{open:e,onOpenChange:t,children:r.jsxs(xt,{className:"max-w-md",children:[r.jsxs(zt,{children:[r.jsxs(It,{className:"flex items-center gap-2",children:[l?r.jsx(La,{className:"h-5 w-5 animate-spin text-primary"}):c?.success?r.jsx(wo,{className:"h-5 w-5 text-success"}):c?r.jsx(xl,{className:"h-5 w-5 text-destructive"}):null,s("providerSettings.modelsManager.testDialog.title")]}),r.jsx(Vt,{children:o})]}),r.jsxs("div",{className:"space-y-4",children:[r.jsxs("div",{className:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-sm",children:[r.jsx("span",{className:"text-muted-foreground",children:s("providerSettings.modelsManager.testDialog.provider")}),r.jsx("span",{className:"font-medium truncate",children:n}),r.jsx("span",{className:"text-muted-foreground",children:s("providerSettings.modelsManager.testDialog.model")}),r.jsx("span",{className:"font-medium truncate",children:i||o})]}),l?r.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground py-4 justify-center",children:[r.jsx(La,{className:"h-4 w-4 animate-spin"}),s("providerSettings.modelsManager.testDialog.testing")]}):null,c&&!l?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:`flex items-center gap-2 px-3 py-2 rounded-lg text-sm ${c.success?"bg-success/10 text-success":"bg-destructive/10 text-destructive"}`,children:[c.success?r.jsx(wo,{className:"h-4 w-4 shrink-0"}):r.jsx(xl,{className:"h-4 w-4 shrink-0"}),r.jsxs("div",{children:[r.jsx("div",{className:"font-medium",children:c.success?s("providerSettings.modelsManager.testDialog.success"):s("providerSettings.modelsManager.testDialog.failure")}),c.success?r.jsx("div",{className:"text-xs opacity-80",children:s("providerSettings.modelsManager.testDialog.successMessage")}):r.jsx("div",{className:"text-xs opacity-80",children:c.message})]})]}),c.success&&c.response?r.jsxs("div",{className:"space-y-1",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:s("providerSettings.modelsManager.testDialog.aiResponse")}),r.jsx("span",{className:"text-xs text-muted-foreground",children:s("providerSettings.modelsManager.testDialog.charCount",{count:c.response.length})})]}),r.jsx("div",{className:"p-3 rounded-lg bg-surface-1 text-sm max-h-32 overflow-y-auto",children:c.response})]}):null,m?r.jsx("div",{className:"flex items-center gap-1.5 text-xs text-muted-foreground",children:r.jsx("span",{children:s("providerSettings.modelsManager.testDialog.duration",{time:m})})}):null]}):null]}),r.jsxs(Bt,{children:[r.jsx(R,{variant:"outline",onClick:()=>t(!1),children:s("providerSettings.modelsManager.testDialog.close")}),r.jsxs(R,{onClick:()=>void p(),disabled:l,children:[r.jsx(zl,{className:"h-4 w-4 mr-1"}),s("providerSettings.modelsManager.testDialog.retest")]})]})]})})}function VN({modes:e,selectedId:t,onChange:a,disabled:n,className:o}){const i=$();if(!e||e.length<2)return null;const[s,l]=e.length===2?e:[e[0],e[1]];e.length>2;const d=t===l.id,c=u=>G("text-xs font-medium select-none cursor-pointer transition-colors",u?"text-foreground":"text-muted-foreground hover:text-foreground",n&&"cursor-not-allowed opacity-60");return r.jsxs("div",{className:G("inline-flex items-center gap-2",o),"data-testid":"provider-api-mode-switcher",children:[r.jsx("button",{type:"button",onClick:()=>!n&&a(s.id),className:c(!d),"data-mode-id":s.id,"aria-pressed":!d,children:i(s.label)||s.label}),r.jsx(me,{checked:d,onCheckedChange:u=>a((u?l:s).id),disabled:n,"aria-label":i("apiMode.label")}),r.jsx("button",{type:"button",onClick:()=>!n&&a(l.id),className:c(d),"data-mode-id":l.id,"aria-pressed":d,children:i(l.label)||l.label})]})}function qN({selectedProvider:e,visibleModelGroups:t,inlineName:a,setInlineName:n,inlineApiKey:o,setInlineApiKey:i,inlineApiUrl:s,setInlineApiUrl:l,inlineModelsEndpoint:d,setInlineModelsEndpoint:c,showApiKey:u,setShowApiKey:p,modelStatus:m,modelSearch:f,setModelSearch:P,collapsedGroups:y,toggleGroupCollapse:A,editingModel:h,setEditingModel:k,inlineMaxConcurrency:v,setInlineMaxConcurrency:b,onInlineUpdate:z,onRevealApiKey:I,onSelectApiMode:C,onToggleProvider:S,onToggleOfficial:L,onDeleteProvider:T,onResetProvider:M,onShowManageModels:D,onShowAddModelDialog:Q,onApplyModelEdit:W,onToggleModelEnabled:J,onRemoveModel:ye,onShowEditModelDialog:ve}){const w=$(),[E,U]=g.useState(null),[Z,ae]=g.useState(null),[_e,xe]=g.useState(!1),[ne,Pe]=g.useState(!1);if(!e)return r.jsx("div",{className:"flex items-center justify-center h-full text-muted-foreground",children:w("providerSettings.details.noSelection")});const Ge=t.length===0,ht=!!(M&&(e.overriddenFields?.length??0)>0),fa=x=>x.id==="default"?w("providerSettings.modelsManager.defaultGroup"):x.name||x.id,Rn=x=>{switch(x.apiFormat||x.apiType){case"anthropic":return w("providerSettings.tags.anthropic");case"google":return w("providerSettings.tags.gemini");case"claudecode":return w("providerSettings.tags.claudeCode");case"openai":default:return w("providerSettings.tags.openai")}};return r.jsxs("div",{className:"p-4 md:p-6 space-y-6",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsx("div",{className:"flex items-center gap-3",children:r.jsxs("div",{children:[e.isSystem?r.jsx("h2",{className:"h-9 text-lg font-semibold flex items-center px-0",children:kn(w,e)}):r.jsx(V,{value:a,onChange:x=>n(x.target.value),onBlur:()=>{a.trim()&&a!==kn(w,e)&&z("name",a.trim())},onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()},className:"h-9 text-lg font-semibold border-transparent bg-transparent px-0"}),r.jsx(Be,{variant:"outline",children:Rn(e)})]})}),r.jsxs("div",{className:"flex items-center gap-2",children:[ht?r.jsxs(R,{variant:"ghost",size:"sm",onClick:()=>xe(!0),title:w("providerSettings.reset.button"),children:[r.jsx(Kk,{className:"h-4 w-4 mr-1"}),w("providerSettings.reset.button")]}):null,r.jsx(me,{checked:e.enabled,onCheckedChange:S}),!e.isSystem&&r.jsx(R,{variant:"ghost",size:"sm",className:"text-destructive hover:text-destructive",onClick:()=>void T(),title:w("common.delete"),children:r.jsx(In,{className:"h-4 w-4"})})]})]}),r.jsx(Jn,{label:w("providerSettings.credentials.apiKey"),description:e.hasKey?w("providerSettings.form.apiKeyReplaceHelper"):w("providerSettings.form.apiKeyHelper"),children:r.jsx(Sn,{revealed:u,onRevealedChange:x=>{p(x),x&&e.hasKey&&o.trim().length===0&&I?.()},placeholder:e.hasKey?"":w("providerSettings.form.apiKeyPlaceholder"),value:e.hasKey&&!u&&!ne&&o.length===0?"••••••••••••":o,onChange:x=>i(x.target.value),onFocus:()=>Pe(!0),onBlur:()=>{Pe(!1),o.trim().length>0&&o!==(e.api_key||"")&&z("api_key",o)},onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()}})}),r.jsx(FN,{providerId:e.id}),(()=>{const x=e.apiModes;return!x||x.length<2||!C?null:r.jsx(Jn,{label:w("apiMode.label"),children:r.jsxs("div",{className:"flex flex-col gap-1.5",children:[r.jsx(VN,{modes:x,selectedId:e.selectedApiModeId,onChange:j=>{C(j).then(F=>{F||ae(j)})}}),(()=>{const j=x.find(F=>F.id===e.selectedApiModeId);return j?.note?r.jsx("p",{className:"text-[11px] text-muted-foreground",children:w(j.note)||j.note}):null})(),(()=>{const j=x.find(F=>F.id===e.selectedApiModeId);return j?.apiKeyPrefix?r.jsx("p",{className:"text-[11px] text-muted-foreground",children:w("apiMode.apiKeyPrefixHint",{prefix:j.apiKeyPrefix})}):null})()]})})})(),r.jsx(Ft,{open:Z!==null,onOpenChange:x=>{x||ae(null)},children:r.jsxs(xt,{children:[r.jsxs(zt,{children:[r.jsx(It,{children:w("apiMode.confirmOverwriteTitle")}),r.jsx(Vt,{children:w("apiMode.confirmOverwriteBody")})]}),r.jsxs(Bt,{children:[r.jsx(R,{variant:"outline",onClick:()=>ae(null),children:w("common.cancel")||"Cancel"}),r.jsx(R,{variant:"outline",onClick:()=>{Z&&C&&C(Z,{keepCustomizations:!0}),ae(null)},children:w("apiMode.keepCustomizations")}),r.jsx(R,{onClick:()=>{Z&&C&&C(Z),ae(null)},children:w("apiMode.overwriteAndSwitch")})]})]})}),r.jsx(Jn,{label:w("providerSettings.credentials.apiBaseUrl"),labelAction:e.website?r.jsx("a",{href:e.website,target:"_blank",rel:"noreferrer",className:"text-muted-foreground hover:text-foreground transition-colors",title:w("mediaSettings.common.learnMore"),children:r.jsx(Ho,{className:"h-4 w-4"})}):void 0,children:r.jsx(V,{placeholder:e.api_base_url||w("providerSettings.form.apiUrlPlaceholder"),value:s,onChange:x=>l(x.target.value),onBlur:()=>{s!==(e.api_base_url||"")&&z("api_base_url",s)},onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()}})}),(e.apiFormat||e.apiType)==="anthropic"?r.jsx(Jt,{label:w("providerSettings.form.official"),description:w("providerSettings.form.officialHelper"),className:"border-0 bg-transparent px-0",children:r.jsx(me,{checked:e.isOfficial??!1,onCheckedChange:x=>L(x)})}):null,r.jsx(Jn,{label:w("providerSettings.form.maxConcurrency"),description:w("providerSettings.form.maxConcurrencyHelper"),children:r.jsx(V,{type:"number",min:-1,max:100,placeholder:"-1",value:v,onChange:x=>b(x.target.value),onBlur:()=>{v!==(e.maxConcurrency!=null?String(e.maxConcurrency):"")&&z("maxConcurrency",v)},onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()}})}),m?r.jsx("div",{className:`text-xs px-3 py-2 rounded border ${m.type==="success"?"border-success/30 bg-success/10 text-success":"border-destructive/30 bg-destructive/10 text-destructive"}`,children:m.message}):null,r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"flex flex-wrap gap-2",children:[r.jsxs("div",{className:"relative flex-1 min-w-[180px]",children:[r.jsx(V,{placeholder:w("providerSettings.modelsManager.searchPlaceholder"),value:f,onChange:x=>P(x.target.value),className:"pr-8"}),f?r.jsx("button",{type:"button",className:"absolute inset-y-0 right-0 flex items-center pr-3 text-muted-foreground",onClick:()=>P(""),children:r.jsx(Da,{className:"h-4 w-4"})}):null]}),r.jsxs(R,{type:"button",variant:"outline",size:"sm",onClick:D,children:[r.jsx(Il,{className:"h-4 w-4 mr-1"}),w("providerSettings.modelsManager.manage")]}),r.jsxs(R,{type:"button",size:"sm",onClick:Q,children:[r.jsx(Ra,{className:"h-4 w-4 mr-1"}),w("providerSettings.modelsManager.add")]})]}),r.jsxs("div",{className:"space-y-1",children:[r.jsx("label",{className:"text-xs font-medium",children:w("providerSettings.details.modelsEndpoint")}),r.jsx(V,{value:d,placeholder:`${e.api_base_url?.replace(/\/chat\/completions$/,"/models")||""}`,onChange:x=>c(x.target.value),onBlur:()=>{d!==(e.modelsEndpoint||"")&&z("modelsEndpoint",d)},onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()}}),r.jsx("p",{className:"text-[11px] text-muted-foreground",children:w("providerSettings.details.modelsEndpointHelper")})]})]}),r.jsx("div",{className:"space-y-2",children:Ge?r.jsx("div",{className:"text-sm text-muted-foreground italic",children:w("providerSettings.modelsManager.empty")}):t.map(x=>r.jsxs("div",{className:"border rounded-md overflow-hidden",children:[r.jsxs("button",{type:"button",className:"w-full flex items-center justify-between px-3 py-2 bg-muted/40 hover:bg-muted/60 transition-colors",onClick:()=>A(x.id),children:[r.jsxs("div",{children:[r.jsx("div",{className:"text-sm font-medium",children:fa(x)}),r.jsx("div",{className:"text-xs text-muted-foreground",children:w("providerSettings.listStatus",{count:x.models.length})})]}),y[x.id]?r.jsx(ga,{className:"h-4 w-4"}):r.jsx(Ld,{className:"h-4 w-4"})]}),!y[x.id]&&r.jsx("div",{className:"divide-y",children:x.models.map(j=>{const F=h?.id===j.id,B=j.enabled!==!1;return r.jsxs("div",{className:"flex items-center gap-3 px-3 py-2",children:[r.jsx("div",{className:"flex-1 min-w-0",children:F?r.jsxs("div",{className:"flex gap-2",children:[r.jsx(V,{className:"flex-1",value:h?.name||"",onChange:ee=>k(Y=>Y&&{...Y,name:ee.target.value})}),r.jsx(R,{size:"sm",onClick:()=>void W(),children:r.jsx(Ln,{className:"h-4 w-4"})}),r.jsx(R,{size:"sm",variant:"ghost",onClick:()=>k(null),children:r.jsx(Da,{className:"h-4 w-4"})})]}):r.jsxs(r.Fragment,{children:[r.jsx("div",{className:"font-medium text-sm truncate",children:j.name||j.id}),r.jsxs("div",{className:"flex items-center gap-1.5",children:[r.jsx("span",{className:"text-xs text-muted-foreground truncate",children:j.id}),j.vision?r.jsx(Be,{variant:"secondary",className:"text-[10px] px-1.5 py-0 h-4 shrink-0",children:w("providerSettings.modelsManager.filters.vision")}):null,j.reasoning?r.jsx(Be,{variant:"secondary",className:"text-[10px] px-1.5 py-0 h-4 shrink-0",children:w("providerSettings.modelsManager.filters.reasoning")}):null]})]})}),!F&&r.jsxs(r.Fragment,{children:[r.jsx(Be,{variant:B?"outline":"secondary",children:w(B?"providerSettings.modelsManager.enabled":"providerSettings.modelsManager.disabled")}),r.jsx(me,{checked:B,onCheckedChange:ee=>void J(j.id,ee)}),r.jsx(R,{type:"button",variant:"ghost",size:"icon",title:w("providerSettings.modelsManager.testDialog.testButton"),onClick:()=>U({id:j.id,name:j.name||j.id}),children:r.jsx(Vk,{className:"h-4 w-4"})}),r.jsx(R,{type:"button",variant:"ghost",size:"icon",onClick:()=>ve(j),children:r.jsx(Il,{className:"h-4 w-4"})}),r.jsx(R,{type:"button",variant:"ghost",size:"icon",className:"text-destructive hover:text-destructive/80",onClick:()=>void ye(j.id),children:r.jsx(In,{className:"h-4 w-4"})})]})]},j.id)})})]},x.id))}),e&&E?r.jsx(BN,{open:!!E,onOpenChange:x=>{x||U(null)},providerId:e.id,providerName:kn(w,e),modelId:E.id,modelName:E.name}):null,r.jsx(Kr,{open:_e,onOpenChange:xe,title:w("providerSettings.reset.confirmTitle"),description:w("providerSettings.reset.confirmBody"),confirmLabel:w("providerSettings.reset.confirmButton"),variant:"default",onConfirm:()=>{M?.(e.id),xe(!1)}})]})}function Ts(e){return Array.isArray(e)?e[0]:e}const $N=[{value:"openai",label:"OpenAI"},{value:"google",label:"Google Gemini"},{value:"anthropic",label:"Anthropic"},{value:"azure-openai",label:"Azure OpenAI"},{value:"openai-response",label:"OpenAI (Responses API)"}],_N=e=>{const t={openai:"openai",google:"gemini",anthropic:"anthropic","azure-openai":"azure-openai","openai-response":"openai-response"};return WM.find(a=>a.id===t[e])};function Xu({isEditing:e,isAddingNew:t,formData:a,setFormData:n,formError:o,showApiKey:i,setShowApiKey:s,hasKey:l,hasCodingPlanKey:d,onCancel:c,onSave:u}){const p=$(),[m,f]=g.useState(!1),P=a.transformer?.use??[],y=P.length,A=new Set(P.map(Ts)),h=(v,b)=>{n(z=>{const I=z.transformer?.use??[],C=b?I.some(S=>Ts(S)===v)?I:[...I,v]:I.filter(S=>Ts(S)!==v);return{...z,transformer:{...z.transformer,use:C}}})},k=v=>{const b=_N(v);n(b?z=>({...z,apiFormat:b.apiFormat||"openai",chatApiFormat:b.chatApiFormat||b.apiFormat||"openai",apiType:b.apiType,api_base_url:b.api_base_url,models:[...b.models],modelConfigs:b.modelConfigs?[...b.modelConfigs]:[],modelGroups:b.modelGroups?[...b.modelGroups]:[],modelsEndpoint:b.modelsEndpoint,icon:b.icon,transformer:b.transformer,apiVersion:b.apiVersion}):z=>({...z,apiFormat:v,apiVersion:void 0}))};return r.jsxs("div",{className:"space-y-4 p-4",children:[o?r.jsx("div",{className:"p-2 bg-red-500/10 border border-red-500/20 rounded text-red-500 text-sm",children:o}):null,r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.name")}),r.jsx(V,{placeholder:p("providerSettings.form.name"),value:a.name,onChange:v=>n(b=>({...b,name:v.target.value}))})]}),t?r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.providerType")}),r.jsx(Lt,{value:a.apiFormat||"openai",onChange:k,options:$N})]}):null,r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.apiKey")}),r.jsx("div",{className:"flex gap-2",children:r.jsxs("div",{className:"relative flex-1",children:[r.jsx(V,{type:i?"text":"password",placeholder:p(l?"providerSettings.form.apiKeySetPlaceholder":"providerSettings.form.apiKeyPlaceholder"),value:a.api_key,onChange:v=>n(b=>({...b,api_key:v.target.value})),className:"pr-10"}),r.jsx("button",{type:"button",className:"absolute inset-y-0 right-0 flex items-center pr-3 text-muted-foreground",onClick:()=>s(!i),children:i?r.jsx(xg,{className:"h-4 w-4"}):r.jsx(zg,{className:"h-4 w-4"})})]})}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p(l?"providerSettings.form.apiKeyReplaceHelper":"providerSettings.form.apiKeyHelper")})]}),r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.apiUrl")}),r.jsx(V,{placeholder:p("providerSettings.form.apiUrlPlaceholder"),value:a.api_base_url,onChange:v=>n(b=>({...b,api_base_url:v.target.value}))}),a.api_base_url?r.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[p("providerSettings.form.apiUrlPreview")," ",a.api_base_url,r.jsx(Ho,{className:"h-3 w-3"})]}):null]}),r.jsxs("div",{className:"border rounded-lg p-3 space-y-3",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.codingPlan.label")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.codingPlan.description")})]}),r.jsx(me,{checked:a.codingPlan?.enabled??!1,onCheckedChange:v=>n(b=>({...b,codingPlan:{...b.codingPlan??{enabled:!1},enabled:v}}))})]}),a.codingPlan?.enabled?r.jsxs("div",{className:"space-y-3 pt-1",children:[r.jsxs("div",{className:"space-y-1",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:p("providerSettings.form.codingPlan.baseUrl")}),r.jsx(V,{placeholder:p("providerSettings.form.codingPlan.baseUrlPlaceholder"),value:a.codingPlan?.baseUrl||"",onChange:v=>n(b=>({...b,codingPlan:{...b.codingPlan??{enabled:!1},baseUrl:v.target.value}}))})]}),r.jsxs("div",{className:"space-y-1",children:[r.jsx("label",{className:"text-xs font-medium text-muted-foreground",children:p("providerSettings.form.codingPlan.apiKey")}),r.jsx(V,{type:"password",placeholder:p(d?"providerSettings.form.apiKeySetPlaceholder":"providerSettings.form.codingPlan.apiKeyPlaceholder"),value:a.codingPlan?.apiKey||"",onChange:v=>n(b=>({...b,codingPlan:{...b.codingPlan??{enabled:!1},apiKey:v.target.value}}))}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.codingPlan.apiKeyHelper")})]})]}):null]}),a.apiFormat==="azure-openai"?r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.apiVersion")}),r.jsx(V,{placeholder:p("providerSettings.form.apiVersionPlaceholder"),value:a.apiVersion||"",onChange:v=>n(b=>({...b,apiVersion:v.target.value}))}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.apiVersionHelper")})]}):null,a.apiFormat==="anthropic"?r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs("div",{children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.official")}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.officialHelper")})]}),r.jsx(me,{checked:a.isOfficial??!1,onCheckedChange:v=>n(b=>({...b,isOfficial:v}))})]}):null,r.jsxs("div",{className:"space-y-2",children:[r.jsx("label",{className:"text-sm font-medium",children:p("providerSettings.form.maxConcurrency")}),r.jsx(V,{type:"number",min:1,max:100,placeholder:"5",value:a.maxConcurrency??"",onChange:v=>{const b=parseInt(v.target.value,10);n(z=>({...z,maxConcurrency:Number.isFinite(b)?b:void 0}))}}),r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.maxConcurrencyHelper")})]}),!t&&r.jsxs("div",{className:"border rounded-lg",children:[r.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-3 hover:bg-muted/50 transition-colors",onClick:()=>f(!m),children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(Il,{className:"h-4 w-4 text-muted-foreground"}),r.jsx("span",{className:"text-sm font-medium",children:p("providerSettings.form.transformerConfig")}),y>0&&r.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-primary/10 text-primary",children:y})]}),m?r.jsx(ga,{className:"h-4 w-4 text-muted-foreground"}):r.jsx(Nd,{className:"h-4 w-4 text-muted-foreground"})]}),m?r.jsxs("div",{className:"p-3 border-t space-y-3",children:[r.jsx("p",{className:"text-xs text-muted-foreground",children:p("providerSettings.form.transformerConfigDescription")}),r.jsx("div",{className:"space-y-1.5 max-h-64 overflow-y-auto pr-1",children:ZM.map(v=>{const b=A.has(v.name);return r.jsxs("label",{className:"flex items-start gap-2 rounded-md px-2 py-1.5 hover:bg-muted/50 cursor-pointer",children:[r.jsx("input",{type:"checkbox",className:"mt-0.5",checked:b,onChange:z=>h(v.name,z.target.checked)}),r.jsxs("span",{className:"flex-1",children:[r.jsx("span",{className:"text-sm font-medium",children:v.name}),v.description?r.jsx("span",{className:"block text-xs text-muted-foreground",children:v.description}):null]})]},v.name)})}),r.jsx("p",{className:"text-xs text-muted-foreground italic",children:p("providerSettings.form.transformerConfigNote")})]}):null]}),r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(me,{checked:a.enabled,onCheckedChange:v=>n(b=>({...b,enabled:v}))}),r.jsx("label",{className:"text-sm",children:p("providerSettings.form.enabled")})]}),r.jsxs("div",{className:"flex gap-2 justify-end pt-2",children:[r.jsx(R,{variant:"outline",onClick:c,children:p("providerSettings.form.buttons.cancel")}),r.jsx(R,{onClick:u,children:p(e?"providerSettings.form.buttons.submitUpdate":"providerSettings.form.buttons.submitAdd")})]})]})}function GN({providers:e,loading:t=!1,selectedProviderId:a,searchTerm:n,setSearchTerm:o,onSelectProvider:i,onAddProvider:s,onReorderProviders:l,isAddingNew:d}){const c=$(),[u,p]=g.useState(!1),[m,f]=g.useState(-1),[P,y]=g.useState(-1),A=g.useMemo(()=>{let I=e;if(u&&(I=I.filter(C=>C.enabled)),n.trim()){const C=n.trim().toLowerCase();I=I.filter(S=>{const L=`${S.name} ${kn(c,S)} ${S.apiFormat||S.apiType||""} ${S.models?.join(" ")||""}`.toLowerCase(),T=S.id.toLowerCase().includes(C);return L.includes(C)||T})}return I},[e,n,u,c]),h=!!l&&!u&&!n.trim(),k=g.useCallback(I=>C=>{h&&(f(I),C.dataTransfer.effectAllowed="move",C.dataTransfer.setData("text/plain",String(I)))},[h]),v=g.useCallback(I=>C=>{h&&(C.preventDefault(),C.dataTransfer.dropEffect="move",y(I))},[h]),b=g.useCallback(()=>{f(-1),y(-1)},[]),z=g.useCallback(I=>()=>{if(f(-1),y(-1),!h||!l||m===-1||I===-1||m===I)return;const C=[...e],[S]=C.splice(m,1);C.splice(I,0,S),l(C.map(L=>L.id))},[e,l,h,m]);return r.jsxs("div",{className:"w-72 border-r border-border bg-surface-1/60 flex flex-col h-full overflow-hidden",children:[r.jsxs("div",{className:"p-3 border-b border-border/70 flex-shrink-0 flex items-center gap-2",children:[r.jsxs("div",{className:"relative flex-1 min-w-0",children:[r.jsx(Tg,{className:"absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),r.jsx(V,{placeholder:c("providerSettings.searchPlaceholder"),value:n,onChange:I=>o(I.target.value),className:"pl-8 h-9"}),n?r.jsx("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground",onClick:()=>o(""),children:r.jsx(Da,{className:"h-4 w-4"})}):null]}),r.jsx("button",{type:"button",className:G("h-9 w-9 flex items-center justify-center rounded-md border transition-colors flex-shrink-0",u?"border-primary text-primary bg-primary/10":"border-border/40 text-muted-foreground hover:border-border hover:text-foreground"),onClick:()=>p(I=>!I),"aria-pressed":u,"aria-label":c(u?"providerSettings.showAll":"providerSettings.showEnabledOnly"),title:c(u?"providerSettings.showAll":"providerSettings.showEnabledOnly"),children:r.jsx(Cg,{className:"h-4 w-4"})})]}),r.jsx(ha,{className:"flex-1 min-h-0",children:r.jsx("div",{className:"p-2 space-y-1.5",children:t&&e.length===0?r.jsx("div",{className:"flex items-center justify-center py-6",children:r.jsx(La,{className:"h-4 w-4 animate-spin text-muted-foreground"})}):A.length===0?r.jsx("p",{className:"text-xs text-muted-foreground text-center py-6",children:c(n||u?"providerSettings.emptySearch":"providerSettings.emptyList")}):A.map((I,C)=>{const S=a===I.id&&!d,L=h&&P===C&&m!==C;return r.jsxs("div",{draggable:h,onDragStart:k(C),onDragOver:v(C),onDrop:z(C),onDragEnd:b,className:G("group relative rounded-lg border transition-colors",S?"border-primary bg-primary/10":"border-transparent hover:border-primary/40 hover:bg-surface-2",L&&"border-primary/60 bg-primary/5"),children:[r.jsxs("button",{className:G("w-full px-3 py-2 pl-7 text-left",S&&"text-primary"),onClick:()=>i(I.id),children:[r.jsxs("div",{className:"flex items-center justify-between gap-2",children:[r.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[r.jsx("span",{className:G("h-2 w-2 rounded-full flex-shrink-0",I.enabled?"bg-primary":"bg-border")}),r.jsx("span",{className:"font-medium text-sm truncate",children:kn(c,I)})]}),r.jsx(Be,{variant:"secondary",className:"text-[10px] uppercase tracking-wide flex-shrink-0",children:I.enabled?c("providerSettings.enabled"):c("providerSettings.disabled")})]}),r.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:I.models?.length?c("providerSettings.listStatus",{count:I.models.length}):c("providerSettings.noModels")})]}),h?r.jsx("span",{className:"absolute left-1 top-1/2 -translate-y-1/2 flex items-center text-muted-foreground/40 group-hover:text-muted-foreground cursor-grab active:cursor-grabbing","aria-label":c("providerSettings.dragHandle"),title:c("providerSettings.dragHandle"),children:r.jsx(Lk,{className:"h-3.5 w-3.5"})}):null]},I.id)})})}),r.jsx("div",{className:"border-t border-border/70 p-3 flex-shrink-0",children:r.jsxs(R,{className:"w-full",variant:"outline",onClick:s,children:[r.jsx(Ra,{className:"h-4 w-4 mr-1"}),c("providerSettings.form.buttons.submitAdd")]})})]})}function WN(){const e=$(),[t,a]=g.useState(!1),{providers:n,providersLoading:o,searchTerm:i,setSearchTerm:s,selectedProviderId:l,selectedProvider:d,isEditing:c,isAddingNew:u,formData:p,setFormData:m,formError:f,showApiKey:P,setShowApiKey:y,modelSearch:A,setModelSearch:h,collapsedGroups:k,toggleGroupCollapse:v,showManageModels:b,setShowManageModels:z,showAddModelDialog:I,setShowAddModelDialog:C,modelDiscoveryLoading:S,modelDiscoveryError:L,catalogSearchTerm:T,setCatalogSearchTerm:M,catalogFilter:D,setCatalogFilter:Q,catalogCollapsedGroups:W,toggleCatalogGroup:J,newModelEntry:ye,setNewModelEntry:ve,modelStatus:w,editingModel:E,setEditingModel:U,showEditModelDialog:Z,setShowEditModelDialog:ae,editModelEntry:_e,setEditModelEntry:xe,inlineName:ne,setInlineName:Pe,inlineModelsEndpoint:Ge,setInlineModelsEndpoint:ht,inlineApiKey:fa,setInlineApiKey:Rn,inlineApiUrl:x,setInlineApiUrl:j,inlineMaxConcurrency:F,setInlineMaxConcurrency:B,visibleModelGroups:ee,normalizedModelGroups:Y,defaultGroupId:he,discoveryResult:et,filteredDiscoveryModels:Ha,catalogGroups:Dn,existingModelIds:Fa,handleSelectProvider:Wd,handleAddProvider:Bo,handleReorderProviders:Fr,handleSelectApiMode:Zd,handleSaveProvider:Vo,handleCancelEdit:Qd,handleInlineUpdate:Eh,handleToggleProvider:Oh,handleToggleOfficial:Kh,handleDeleteProvider:Uh,handleResetProvider:Hh,revealApiKey:Fh,missingKeyCount:Yd,handleRemoveModel:Bh,handleAddModelEntry:Vh,handleAddDiscoveredModel:qh,handleApplyModelEdit:$h,handleApplyEditModelDialog:_h,handleToggleModelEnabled:Gh,loadModelDiscovery:Wh,onShowEditModelDialog:Zh}=NN(),Qh=Yd>0&&!t;return r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"flex flex-col h-full overflow-hidden",children:[Qh?r.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 border-b border-border/50 bg-surface-2/60 text-sm",role:"status",children:[r.jsx(Dd,{className:"h-4 w-4 shrink-0 text-primary","aria-hidden":"true"}),r.jsx("span",{className:"flex-1 min-w-0 text-foreground",children:e("providerSettings.reentryBanner.message",{count:Yd})}),r.jsx(R,{variant:"ghost",size:"icon",className:"h-7 w-7 shrink-0",onClick:()=>a(!0),title:e("common.dismiss"),"aria-label":e("common.dismiss"),children:r.jsx(Da,{className:"h-4 w-4"})})]}):null,r.jsxs("div",{className:"flex flex-1 min-h-0 overflow-hidden",children:[r.jsx(GN,{providers:n,loading:o,selectedProviderId:l,searchTerm:i,setSearchTerm:s,onSelectProvider:Wd,onAddProvider:Bo,onReorderProviders:Fr,isAddingNew:u}),r.jsx("div",{className:"flex-1 flex flex-col h-full overflow-hidden bg-surface-1/60 wallpaper-blur",children:r.jsx("div",{className:"flex-1 overflow-y-auto min-h-0",children:u?r.jsx(Xu,{isEditing:!1,isAddingNew:!0,formData:p,setFormData:m,formError:f,showApiKey:P,setShowApiKey:y,onCancel:Qd,onSave:Vo}):c?r.jsx(Xu,{isEditing:c,isAddingNew:u,formData:p,setFormData:m,formError:f,showApiKey:P,setShowApiKey:y,hasKey:d?.hasKey,hasCodingPlanKey:!!d?.codingPlan?.hasApiKey,onCancel:Qd,onSave:Vo}):r.jsx(qN,{selectedProvider:d,visibleModelGroups:ee,inlineName:ne,setInlineName:Pe,inlineApiKey:fa,setInlineApiKey:Rn,inlineApiUrl:x,setInlineApiUrl:j,inlineModelsEndpoint:Ge,setInlineModelsEndpoint:ht,inlineMaxConcurrency:F,setInlineMaxConcurrency:B,showApiKey:P,setShowApiKey:y,modelStatus:w,modelSearch:A,setModelSearch:h,collapsedGroups:k,toggleGroupCollapse:v,editingModel:E,setEditingModel:U,onInlineUpdate:Eh,onRevealApiKey:Fh,onSelectApiMode:Zd,onToggleProvider:Oh,onToggleOfficial:Kh,onDeleteProvider:Uh,onResetProvider:Hh,onShowManageModels:()=>z(!0),onShowAddModelDialog:()=>C(!0),onApplyModelEdit:$h,onToggleModelEnabled:Gh,onRemoveModel:Bh,onShowEditModelDialog:Zh})})})]}),r.jsx(VM,{})]}),r.jsx(LN,{selectedProvider:d,showManageModels:b,setShowManageModels:z,discoveryResult:et,filteredDiscoveryModels:Ha,catalogGroups:Dn,catalogSearchTerm:T,setCatalogSearchTerm:M,catalogFilter:D,setCatalogFilter:Q,catalogCollapsedGroups:W,toggleCatalogGroup:J,modelDiscoveryLoading:S,modelDiscoveryError:L,existingModelIds:Fa,onLoadModelDiscovery:Wh,onAddDiscoveredModel:qh}),r.jsx(RN,{selectedProvider:d,showAddModelDialog:I,setShowAddModelDialog:C,newModelEntry:ye,setNewModelEntry:ve,normalizedModelGroups:Y,defaultGroupId:he,onAddModelEntry:Vh}),r.jsx(YM,{selectedProvider:d,showEditModelDialog:Z,setShowEditModelDialog:ae,editModelEntry:_e,setEditModelEntry:xe,normalizedModelGroups:Y,onApplyEditModelDialog:_h,setEditingModel:U})]})}function Gd(){try{return Rr()}catch{return!1}}async function Ju(){if(!Gd())return null;try{return await Qt("get_ui_settings")}catch{return null}}async function ep(e){if(!Gd())return!1;try{return await Qt("set_ui_settings",{patch:e}),!0}catch{return!1}}function tp(){const e=ie.language??"en";if(No(e))return e;const t=e.split("-")[0];return No(t)?t:"en"}function ZN(){const e=$(),t=Gd(),[a,n]=g.useState(tp()),[o,i]=g.useState({closeToTray:!1,startMinimized:!1,autoStart:!1,language:tp()});g.useEffect(()=>{let c=!1;return(async()=>{const u=await Ju();u&&!c&&i(u)})(),()=>{c=!0}},[]);const s=async c=>{i(p=>({...p,...c})),await ep(c);const u=await Ju();u&&i(u)},l=c=>{const u=No(c)?c:"en";Nj(u),n(u),ep({language:u})},d=wj.map(({code:c,nativeName:u})=>({value:c,label:u}));return r.jsx("div",{className:"flex h-full flex-col overflow-hidden",children:r.jsx(ha,{className:"flex-1",children:r.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 px-6 py-6",children:[r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(jg,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{children:[r.jsx("h2",{className:"text-base font-semibold text-foreground",children:e("settings.title")}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("settings.description")})]})]})}),t?null:r.jsx("div",{className:"rounded-md border border-border/60 bg-surface-2/40 px-4 py-3 text-sm text-muted-foreground",children:e("settings.desktopOnly")}),r.jsxs("section",{className:"space-y-3 rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("settings.language.title")}),r.jsx(Jt,{label:e("settings.language.label"),children:r.jsx(Lt,{value:a,options:d,onChange:l,size:"sm",className:"w-32"})})]}),r.jsxs("section",{className:"space-y-3 rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("settings.startup.title")}),r.jsx(Jt,{icon:wg,label:e("settings.startup.autoLaunch"),description:e("settings.startup.autoLaunchHint"),children:r.jsx(me,{checked:o.autoStart,disabled:!t,onCheckedChange:c=>void s({autoStart:c})})}),r.jsx(Jt,{label:e("settings.startup.startMinimized"),description:e("settings.startup.startMinimizedHint"),children:r.jsx(me,{checked:o.startMinimized,disabled:!t,onCheckedChange:c=>void s({startMinimized:c})})}),r.jsx(Jt,{icon:Fk,label:e("settings.tray.minimizeOnClose"),description:e("settings.tray.minimizeOnCloseHint"),children:r.jsx(me,{checked:o.closeToTray,disabled:!t,onCheckedChange:c=>void s({closeToTray:c})})})]})]})})})}function js(e,t=0){const a=new Date(e);return new Date(a.getFullYear(),a.getMonth(),a.getDate()-t).getTime()}function QN(e,t){switch(e){case"today":return{startTs:js(t),endTs:t};case"7d":return{startTs:js(t,6),endTs:t};case"30d":return{startTs:js(t,29),endTs:t}}}function YN(e,t){if(!e||!t)return null;const a=new Date(`${e}T00:00:00`).getTime(),n=new Date(`${t}T00:00:00`);if(!Number.isFinite(a)||!Number.isFinite(n.getTime()))return null;const o=new Date(n.getFullYear(),n.getMonth(),n.getDate()+1).getTime();return o<=a?null:{startTs:a,endTs:o}}async function XN(e){const[t,a,n]=await Promise.all([wM(e),TM(e),jM(e)]);return{totals:t,byModel:a,byApiKey:n}}function JN(e){const t=e.filter(n=>n.apiKeyId!==null),a=e.find(n=>n.apiKeyId===null)??null;return{attributed:t,unattributed:a}}function eL(e){return[...e].sort((t,a)=>a.costUsd-t.costUsd)}function He(e,t){return new Intl.NumberFormat(t,{maximumFractionDigits:0}).format(e)}function Lo(e,t){return new Intl.NumberFormat(t,{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:4}).format(e)}const ap="px-3 py-2 text-left text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground",zi="px-3 py-2 text-right text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground",np="px-3 py-2 text-sm text-foreground",tL="px-3 py-2 text-right text-sm tabular-nums text-foreground",op="px-3 py-2 text-sm text-muted-foreground",aL="px-3 py-2 text-right text-sm tabular-nums text-muted-foreground";function nL({rows:e}){const t=$(),a=ie.language||"en",{attributed:n,unattributed:o}=g.useMemo(()=>JN(e),[e]),i=(s,l)=>{const d=l?aL:tL;return r.jsxs(r.Fragment,{children:[r.jsx("td",{className:d,children:He(s.eventCount,a)}),r.jsx("td",{className:d,children:He(s.inputTokens,a)}),r.jsx("td",{className:d,children:He(s.outputTokens,a)}),r.jsx("td",{className:d,children:Lo(s.costUsd,a)})]})};return r.jsx("div",{className:"overflow-x-auto rounded-lg border border-border/70",children:r.jsxs("table",{className:"w-full border-collapse bg-surface-1/40",children:[r.jsx("thead",{className:"border-b border-border/60",children:r.jsxs("tr",{children:[r.jsx("th",{className:ap,children:t("usageStats.apiKey")}),r.jsx("th",{className:ap,children:t("usageStats.provider")}),r.jsx("th",{className:zi,children:t("usageStats.events")}),r.jsx("th",{className:zi,children:t("usageStats.inputTokens")}),r.jsx("th",{className:zi,children:t("usageStats.outputTokens")}),r.jsx("th",{className:zi,children:t("usageStats.cost")})]})}),r.jsxs("tbody",{children:[n.map(s=>r.jsxs("tr",{className:"border-b border-border/40 last:border-b-0",children:[r.jsx("td",{className:np,children:s.label}),r.jsx("td",{className:np,children:s.providerId??"—"}),i(s,!1)]},s.apiKeyId)),o?r.jsxs("tr",{className:"border-b border-border/40 last:border-b-0",children:[r.jsx("td",{className:op,children:r.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[r.jsx("span",{className:"italic",children:t("usageStats.unattributed")}),r.jsx(qd,{content:t("usageStats.unattributedHint"),children:r.jsx(Dk,{className:"h-3.5 w-3.5 text-muted-foreground/70","aria-label":t("usageStats.unattributedHint")})})]})}),r.jsx("td",{className:op,children:"—"}),i(o,!0)]}):null]})]})})}const ip="px-3 py-2 text-left text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground",rp="px-3 py-2 text-sm text-foreground",va="px-3 py-2 text-right text-sm tabular-nums text-foreground",ka="px-3 py-2 text-right text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground";function oL({rows:e}){const t=$(),a=ie.language||"en",n=g.useMemo(()=>eL(e),[e]);return r.jsx("div",{className:"overflow-x-auto rounded-lg border border-border/70",children:r.jsxs("table",{className:"w-full border-collapse bg-surface-1/40",children:[r.jsx("thead",{className:"border-b border-border/60",children:r.jsxs("tr",{children:[r.jsx("th",{className:ip,children:t("usageStats.provider")}),r.jsx("th",{className:ip,children:t("usageStats.model")}),r.jsx("th",{className:ka,children:t("usageStats.events")}),r.jsx("th",{className:ka,children:t("usageStats.inputTokens")}),r.jsx("th",{className:ka,children:t("usageStats.outputTokens")}),r.jsx("th",{className:ka,children:t("usageStats.cacheReadTokens")}),r.jsx("th",{className:ka,children:t("usageStats.cacheWriteTokens")}),r.jsx("th",{className:ka,children:t("usageStats.cost")}),r.jsx("th",{className:ka,children:t("usageStats.cacheSavings")})]})}),r.jsx("tbody",{children:n.map(o=>r.jsxs("tr",{className:"border-b border-border/40 last:border-b-0",children:[r.jsx("td",{className:rp,children:o.providerId}),r.jsx("td",{className:rp,children:r.jsxs("span",{className:"inline-flex items-center gap-2",children:[r.jsx("span",{className:"break-all",children:o.model}),o.unpriced?r.jsx(qd,{content:t("usageStats.unpricedHint"),children:r.jsx(Be,{variant:"secondary",children:t("usageStats.unpriced")})}):null]})}),r.jsx("td",{className:va,children:He(o.eventCount,a)}),r.jsx("td",{className:va,children:He(o.inputTokens,a)}),r.jsx("td",{className:va,children:He(o.outputTokens,a)}),r.jsx("td",{className:va,children:He(o.cacheReadTokens,a)}),r.jsx("td",{className:va,children:He(o.cacheCreationTokens,a)}),r.jsx("td",{className:o.unpriced?"px-3 py-2 text-right text-sm tabular-nums text-muted-foreground/60":va,children:o.unpriced?"—":Lo(o.costUsd,a)}),r.jsx("td",{className:va,children:Lo(o.costSavedByCacheUsd,a)})]},`${o.providerId}\0${o.model}`))})]})})}const iL=[{id:"today",labelKey:"usageStats.rangeToday"},{id:"7d",labelKey:"usageStats.range7d"},{id:"30d",labelKey:"usageStats.range30d"},{id:"custom",labelKey:"usageStats.rangeCustom"}];function rL({preset:e,customFrom:t,customTo:a,onPresetChange:n,onCustomFromChange:o,onCustomToChange:i}){const s=$();return r.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[r.jsx("div",{className:"flex items-center gap-1",children:iL.map(l=>r.jsx(R,{size:"sm",variant:e===l.id?"default":"secondary",onClick:()=>n(l.id),children:s(l.labelKey)},l.id))}),e==="custom"?r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(V,{type:"date",className:"h-7 w-36 text-xs","aria-label":s("usageStats.from"),value:t,onChange:l=>o(l.target.value)}),r.jsx("span",{className:"text-xs text-muted-foreground",children:"→"}),r.jsx(V,{type:"date",className:"h-7 w-36 text-xs","aria-label":s("usageStats.to"),value:a,onChange:l=>i(l.target.value)})]}):null]})}function sL({totals:e}){const t=$(),a=ie.language||"en",n=[{labelKey:"usageStats.totalCost",value:Lo(e.costUsd,a),highlight:!0},{labelKey:"usageStats.cacheSavings",value:Lo(e.costSavedByCacheUsd,a)},{labelKey:"usageStats.events",value:He(e.eventCount,a)},{labelKey:"usageStats.inputTokens",value:He(e.inputTokens,a)},{labelKey:"usageStats.outputTokens",value:He(e.outputTokens,a)},{labelKey:"usageStats.cacheReadTokens",value:He(e.cacheReadTokens,a)},{labelKey:"usageStats.cacheWriteTokens",value:He(e.cacheCreationTokens,a)},{labelKey:"usageStats.reasoningTokens",value:He(e.reasoningTokens,a)}];return r.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:n.map(o=>r.jsxs("div",{className:"rounded-lg border border-border/70 bg-surface-1/60 px-3 py-2.5",children:[r.jsx("p",{className:"truncate text-[11px] uppercase tracking-[0.06em] text-muted-foreground",children:t(o.labelKey)}),r.jsx("p",{className:o.highlight?"mt-1 text-lg font-semibold text-primary":"mt-1 text-lg font-semibold text-foreground",children:o.value})]},o.labelKey))})}function lL(){const[e,t]=g.useState("7d"),[a,n]=g.useState(""),[o,i]=g.useState(""),[s,l]=g.useState(!0),[d,c]=g.useState(null),[u,p]=g.useState(null),[m,f]=g.useState(0),P=g.useMemo(()=>e==="custom"?YN(a,o):QN(e,Date.now()),[e,a,o,m]);g.useEffect(()=>{if(!P){l(!1),c(null);return}let A=!1;return l(!0),c(null),(async()=>{try{const h=await XN(P);if(A)return;p(h)}catch(h){if(A)return;c(h instanceof Error?h.message:"request failed")}finally{A||l(!1)}})(),()=>{A=!0}},[P]);const y=g.useCallback(()=>f(A=>A+1),[]);return{preset:e,setPreset:t,customFrom:a,customTo:o,setCustomFrom:n,setCustomTo:i,range:P,loading:s,error:d,data:u,reload:y}}function dL(){const e=$(),t=lL(),{loading:a,error:n,data:o,range:i}=t,s=(o?.totals.eventCount??0)>0;return r.jsx("div",{className:"flex h-full flex-col overflow-hidden",children:r.jsx(ha,{className:"flex-1",children:r.jsxs("div",{className:"mx-auto max-w-5xl space-y-6 px-6 py-6",children:[r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-4 md:p-5",children:r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-surface-2",children:r.jsx(bg,{className:"h-5 w-5 text-muted-foreground"})}),r.jsxs("div",{className:"min-w-0 flex-1",children:[r.jsx("h2",{className:"text-base font-semibold text-foreground",children:e("usageStats.title")}),r.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:e("usageStats.description")}),r.jsx("div",{className:"mt-3",children:r.jsx(rL,{preset:t.preset,customFrom:t.customFrom,customTo:t.customTo,onPresetChange:t.setPreset,onCustomFromChange:t.setCustomFrom,onCustomToChange:t.setCustomTo})})]})]})}),n?r.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-lg border border-destructive/60 bg-destructive/10 px-4 py-3",children:[r.jsx("p",{className:"text-sm text-destructive",children:n}),r.jsx(R,{size:"sm",variant:"outline",onClick:t.reload,children:e("common.retry")})]}):null,!n&&a?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("common.loading")}):null,!n&&!a&&i===null?r.jsx("p",{className:"text-sm text-muted-foreground",children:e("usageStats.invalidRange")}):null,!n&&!a&&i!==null&&o&&!s?r.jsx("section",{className:"rounded-xl border border-border/70 bg-surface-1/60 p-8 text-center",children:r.jsx("p",{className:"text-sm text-muted-foreground",children:e("usageStats.empty")})}):null,!n&&!a&&o&&s?r.jsxs(r.Fragment,{children:[r.jsx(sL,{totals:o.totals}),r.jsxs("section",{className:"space-y-2",children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("usageStats.byModel")}),r.jsx(oL,{rows:o.byModel})]}),r.jsxs("section",{className:"space-y-2",children:[r.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("usageStats.byApiKey")}),r.jsx(nL,{rows:o.byApiKey})]})]}):null]})})})}function cL(e){switch(e){case"api-service":return r.jsx(pM,{});case"accounts":return r.jsx(eM,{});case"code-cli":return r.jsx(hM,{});case"usage-stats":return r.jsx(dL,{});case"pricing":return r.jsx(KM,{});case"settings":return r.jsx(ZN,{});case"providers":default:return r.jsx(WN,{})}}function uL(){const[e,t]=g.useState("providers");return r.jsxs("div",{className:"flex h-screen w-screen overflow-hidden bg-background text-foreground",children:[r.jsx(yy,{activePage:e,onNavigate:t}),r.jsxs("div",{className:"flex min-w-0 flex-1 flex-col overflow-hidden",children:[r.jsx(vy,{}),r.jsx("main",{className:"min-w-0 flex-1 overflow-hidden",children:cL(e)})]})]})}Mj();Ms.createRoot(document.getElementById("root")).render(r.jsx(Mt.StrictMode,{children:r.jsx(uL,{})}));