diff --git a/cli/src/wizard/assets/index.html b/cli/src/wizard/assets/index.html index 7bee2959..5a2ab979 100644 --- a/cli/src/wizard/assets/index.html +++ b/cli/src/wizard/assets/index.html @@ -92,7 +92,7 @@ `},qT=function(){var e=parseInt(document.body.getAttribute(`data-scroll-locked`)||`0`,10);return isFinite(e)?e:0},JT=function(){F.useEffect(function(){return document.body.setAttribute(GT,(qT()+1).toString()),function(){var e=qT()-1;e<=0?document.body.removeAttribute(GT):document.body.setAttribute(GT,e.toString())}},[])},YT=function(e){var t=e.noRelative,n=e.noImportant,r=e.gapMode,i=r===void 0?`margin`:r;JT();var a=F.useMemo(function(){return UT(i)},[i]);return F.createElement(WT,{styles:KT(a,!t,i,n?``:`!important`)})},XT=!1;if(typeof window<`u`)try{var ZT=Object.defineProperty({},`passive`,{get:function(){return XT=!0,!0}});window.addEventListener(`test`,ZT,ZT),window.removeEventListener(`test`,ZT,ZT)}catch{XT=!1}var QT=XT?{passive:!1}:!1,$T=function(e){return e.tagName===`TEXTAREA`},eE=function(e,t){if(!(e instanceof Element))return!1;var n=window.getComputedStyle(e);return n[t]!==`hidden`&&!(n.overflowY===n.overflowX&&!$T(e)&&n[t]===`visible`)},tE=function(e){return eE(e,`overflowY`)},nE=function(e){return eE(e,`overflowX`)},rE=function(e,t){var n=t.ownerDocument,r=t;do{if(typeof ShadowRoot<`u`&&r instanceof ShadowRoot&&(r=r.host),oE(e,r)){var i=sE(e,r);if(i[1]>i[2])return!0}r=r.parentNode}while(r&&r!==n.body);return!1},iE=function(e){return[e.scrollTop,e.scrollHeight,e.clientHeight]},aE=function(e){return[e.scrollLeft,e.scrollWidth,e.clientWidth]},oE=function(e,t){return e===`v`?tE(t):nE(t)},sE=function(e,t){return e===`v`?iE(t):aE(t)},cE=function(e,t){return e===`h`&&t===`rtl`?-1:1},lE=function(e,t,n,r,i){var a=cE(e,window.getComputedStyle(t).direction),o=a*r,s=n.target,c=t.contains(s),l=!1,u=o>0,d=0,f=0;do{if(!s)break;var p=sE(e,s),m=p[0],h=p[1]-p[2]-a*m;(m||h)&&oE(e,s)&&(d+=h,f+=m);var g=s.parentNode;s=g&&g.nodeType===Node.DOCUMENT_FRAGMENT_NODE?g.host:g}while(!c&&s!==document.body||c&&(t.contains(s)||t===s));return(u&&(i&&Math.abs(d)<1||!i&&o>d)||!u&&(i&&Math.abs(f)<1||!i&&-o>f))&&(l=!0),l},uE=function(e){return`changedTouches`in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},dE=function(e){return[e.deltaX,e.deltaY]},fE=function(e){return e&&`current`in e?e.current:e},pE=function(e,t){return e[0]===t[0]&&e[1]===t[1]},mE=function(e){return` .block-interactivity-${e} {pointer-events: none;} .allow-interactivity-${e} {pointer-events: all;} -`},hE=0,gE=[];function _E(e){var t=F.useRef([]),n=F.useRef([0,0]),r=F.useRef(),i=F.useState(hE++)[0],a=F.useState(zT)[0],o=F.useRef(e);F.useEffect(function(){o.current=e},[e]),F.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=mT([e.lockRef.current],(e.shards||[]).map(fE),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=F.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=uE(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=rE(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=rE(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return lE(h,t,e,h===`h`?s:c,!0)},[]),c=F.useCallback(function(e){var n=e;if(!(!gE.length||gE[gE.length-1]!==a)){var r=`deltaY`in n?dE(n):uE(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&pE(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(fE).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=F.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:vE(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=F.useCallback(function(e){n.current=uE(e),r.current=void 0},[]),d=F.useCallback(function(t){l(t.type,dE(t),t.target,s(t,e.lockRef.current))},[]),f=F.useCallback(function(t){l(t.type,uE(t),t.target,s(t,e.lockRef.current))},[]);F.useEffect(function(){return gE.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,QT),document.addEventListener(`touchmove`,c,QT),document.addEventListener(`touchstart`,u,QT),function(){gE=gE.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,QT),document.removeEventListener(`touchmove`,c,QT),document.removeEventListener(`touchstart`,u,QT)}},[]);var p=e.removeScrollBar,m=e.inert;return F.createElement(F.Fragment,null,m?F.createElement(a,{styles:mE(i)}):null,p?F.createElement(YT,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function vE(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var yE=OT(kT,_E),bE=F.forwardRef(function(e,t){return F.createElement(jT,fT({},e,{ref:t,sideCar:yE}))});bE.classNames=jT.classNames;var xE=[` `,`Enter`,`ArrowUp`,`ArrowDown`],SE=[` `,`Enter`],CE=`Select`,[wE,TE,EE]=yw(CE),[DE,OE]=bw(CE,[EE,qo]),kE=qo(),[AE,jE]=DE(CE),[ME,NE]=DE(CE),PE=e=>{let{__scopeSelect:t,children:n,open:r,defaultOpen:i,onOpenChange:a,value:o,defaultValue:s,onValueChange:c,dir:l,name:u,autoComplete:d,disabled:f,required:p,form:m}=e,h=kE(t),[g,_]=F.useState(null),[v,y]=F.useState(null),[b,x]=F.useState(!1),S=Cw(l),[C,w]=Is({prop:r,defaultProp:i??!1,onChange:a,caller:CE}),[T,E]=Is({prop:o,defaultProp:s,onChange:c,caller:CE}),ee=F.useRef(null),D=g?m||!!g.closest(`form`):!0,[O,k]=F.useState(new Set),te=Array.from(O).map(e=>e.props.value).join(`;`);return(0,I.jsx)(ls,{...h,children:(0,I.jsxs)(AE,{required:p,scope:t,trigger:g,onTriggerChange:_,valueNode:v,onValueNodeChange:y,valueNodeHasChildren:b,onValueNodeHasChildrenChange:x,contentId:fi(),value:T,onValueChange:E,open:C,onOpenChange:w,dir:S,triggerPointerDownPosRef:ee,disabled:f,children:[(0,I.jsx)(wE.Provider,{scope:t,children:(0,I.jsx)(ME,{scope:e.__scopeSelect,onNativeOptionAdd:F.useCallback(e=>{k(t=>new Set(t).add(e))},[]),onNativeOptionRemove:F.useCallback(e=>{k(t=>{let n=new Set(t);return n.delete(e),n})},[]),children:n})}),D?(0,I.jsxs)(kD,{"aria-hidden":!0,required:p,tabIndex:-1,name:u,autoComplete:d,value:T,onChange:e=>E(e.target.value),disabled:f,form:m,children:[T===void 0?(0,I.jsx)(`option`,{value:``}):null,Array.from(O)]},te):null]})})};PE.displayName=CE;var FE=`SelectTrigger`,IE=F.forwardRef((e,t)=>{let{__scopeSelect:n,disabled:r=!1,...i}=e,a=kE(n),o=jE(FE,n),s=o.disabled||r,c=yt(t,o.onTriggerChange),l=TE(n),u=F.useRef(`touch`),[d,f,p]=jD(e=>{let t=l().filter(e=>!e.disabled),n=MD(t,e,t.find(e=>e.value===o.value));n!==void 0&&o.onValueChange(n.value)}),m=e=>{s||(o.onOpenChange(!0),p()),e&&(o.triggerPointerDownPosRef.current={x:Math.round(e.pageX),y:Math.round(e.pageY)})};return(0,I.jsx)(us,{asChild:!0,...a,children:(0,I.jsx)(nT.button,{type:`button`,role:`combobox`,"aria-controls":o.contentId,"aria-expanded":o.open,"aria-required":o.required,"aria-autocomplete":`none`,dir:o.dir,"data-state":o.open?`open`:`closed`,disabled:s,"data-disabled":s?``:void 0,"data-placeholder":AD(o.value)?``:void 0,...i,ref:c,onClick:Lr(i.onClick,e=>{e.currentTarget.focus(),u.current!==`mouse`&&m(e)}),onPointerDown:Lr(i.onPointerDown,e=>{u.current=e.pointerType;let t=e.target;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),e.button===0&&e.ctrlKey===!1&&e.pointerType===`mouse`&&(m(e),e.preventDefault())}),onKeyDown:Lr(i.onKeyDown,e=>{let t=d.current!==``;!(e.ctrlKey||e.altKey||e.metaKey)&&e.key.length===1&&f(e.key),!(t&&e.key===` `)&&xE.includes(e.key)&&(m(),e.preventDefault())})})})});IE.displayName=FE;var LE=`SelectValue`,RE=F.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,children:a,placeholder:o=``,...s}=e,c=jE(LE,n),{onValueNodeHasChildrenChange:l}=c,u=a!==void 0,d=yt(t,c.onValueNodeChange);return li(()=>{l(u)},[l,u]),(0,I.jsx)(nT.span,{...s,ref:d,style:{pointerEvents:`none`},children:AD(c.value)?(0,I.jsx)(I.Fragment,{children:o}):a})});RE.displayName=LE;var zE=`SelectIcon`,BE=F.forwardRef((e,t)=>{let{__scopeSelect:n,children:r,...i}=e;return(0,I.jsx)(nT.span,{"aria-hidden":!0,...i,ref:t,children:r||`▼`})});BE.displayName=zE;var VE=`SelectPortal`,HE=e=>(0,I.jsx)(xs,{asChild:!0,...e});HE.displayName=VE;var UE=`SelectContent`,WE=F.forwardRef((e,t)=>{let n=jE(UE,e.__scopeSelect),[r,i]=F.useState();if(li(()=>{i(new DocumentFragment)},[]),!n.open){let t=r;return t?Ar.createPortal((0,I.jsx)(KE,{scope:e.__scopeSelect,children:(0,I.jsx)(wE.Slot,{scope:e.__scopeSelect,children:(0,I.jsx)(`div`,{children:e.children})})}),t):null}return(0,I.jsx)(XE,{...e,ref:t})});WE.displayName=UE;var GE=10,[KE,qE]=DE(UE),JE=`SelectContentImpl`,YE=Xw(`SelectContent.RemoveScroll`),XE=F.forwardRef((e,t)=>{let{__scopeSelect:n,position:r=`item-aligned`,onCloseAutoFocus:i,onEscapeKeyDown:a,onPointerDownOutside:o,side:s,sideOffset:c,align:l,alignOffset:u,arrowPadding:d,collisionBoundary:f,collisionPadding:p,sticky:m,hideWhenDetached:h,avoidCollisions:g,..._}=e,v=jE(UE,n),[y,b]=F.useState(null),[x,S]=F.useState(null),C=yt(t,e=>b(e)),[w,T]=F.useState(null),[E,ee]=F.useState(null),D=TE(n),[O,k]=F.useState(!1),te=F.useRef(!1);F.useEffect(()=>{if(y)return dT(y)},[y]),Tw();let A=F.useCallback(e=>{let[t,...n]=D().map(e=>e.ref.current),[r]=n.slice(-1),i=document.activeElement;for(let n of e)if(n===i||(n?.scrollIntoView({block:`nearest`}),n===t&&x&&(x.scrollTop=0),n===r&&x&&(x.scrollTop=x.scrollHeight),n?.focus(),document.activeElement!==i))return},[D,x]),j=F.useCallback(()=>A([w,y]),[A,w,y]);F.useEffect(()=>{O&&j()},[O,j]);let{onOpenChange:ne,triggerPointerDownPosRef:re}=v;F.useEffect(()=>{if(y){let e={x:0,y:0},t=t=>{e={x:Math.abs(Math.round(t.pageX)-(re.current?.x??0)),y:Math.abs(Math.round(t.pageY)-(re.current?.y??0))}},n=n=>{e.x<=10&&e.y<=10?n.preventDefault():y.contains(n.target)||ne(!1),document.removeEventListener(`pointermove`,t),re.current=null};return re.current!==null&&(document.addEventListener(`pointermove`,t),document.addEventListener(`pointerup`,n,{capture:!0,once:!0})),()=>{document.removeEventListener(`pointermove`,t),document.removeEventListener(`pointerup`,n,{capture:!0})}}},[y,ne,re]),F.useEffect(()=>{let e=()=>ne(!1);return window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e)}},[ne]);let[M,N]=jD(e=>{let t=D().filter(e=>!e.disabled),n=MD(t,e,t.find(e=>e.ref.current===document.activeElement));n&&setTimeout(()=>n.ref.current.focus())}),ie=F.useCallback((e,t,n)=>{let r=!te.current&&!n;(v.value!==void 0&&v.value===t||r)&&(T(e),r&&(te.current=!0))},[v.value]),ae=F.useCallback(()=>y?.focus(),[y]),oe=F.useCallback((e,t,n)=>{let r=!te.current&&!n;(v.value!==void 0&&v.value===t||r)&&ee(e)},[v.value]),P=r===`popper`?eD:QE,se=P===eD?{side:s,sideOffset:c,align:l,alignOffset:u,arrowPadding:d,collisionBoundary:f,collisionPadding:p,sticky:m,hideWhenDetached:h,avoidCollisions:g}:{};return(0,I.jsx)(KE,{scope:n,content:y,viewport:x,onViewportChange:S,itemRefCallback:ie,selectedItem:w,onItemLeave:ae,itemTextRefCallback:oe,focusSelectedItem:j,selectedItemText:E,position:r,isPositioned:O,searchRef:M,children:(0,I.jsx)(bE,{as:YE,allowPinchZoom:!0,children:(0,I.jsx)(Rw,{asChild:!0,trapped:v.open,onMountAutoFocus:e=>{e.preventDefault()},onUnmountAutoFocus:Lr(i,e=>{v.trigger?.focus({preventScroll:!0}),e.preventDefault()}),children:(0,I.jsx)(ni,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:a,onPointerDownOutside:o,onFocusOutside:e=>e.preventDefault(),onDismiss:()=>v.onOpenChange(!1),children:(0,I.jsx)(P,{role:`listbox`,id:v.contentId,"data-state":v.open?`open`:`closed`,dir:v.dir,onContextMenu:e=>e.preventDefault(),..._,...se,onPlaced:()=>k(!0),ref:C,style:{display:`flex`,flexDirection:`column`,outline:`none`,..._.style},onKeyDown:Lr(_.onKeyDown,e=>{let t=e.ctrlKey||e.altKey||e.metaKey;if(e.key===`Tab`&&e.preventDefault(),!t&&e.key.length===1&&N(e.key),[`ArrowUp`,`ArrowDown`,`Home`,`End`].includes(e.key)){let t=D().filter(e=>!e.disabled).map(e=>e.ref.current);if([`ArrowUp`,`End`].includes(e.key)&&(t=t.slice().reverse()),[`ArrowUp`,`ArrowDown`].includes(e.key)){let n=e.target,r=t.indexOf(n);t=t.slice(r+1)}setTimeout(()=>A(t)),e.preventDefault()}})})})})})})});XE.displayName=JE;var ZE=`SelectItemAlignedPosition`,QE=F.forwardRef((e,t)=>{let{__scopeSelect:n,onPlaced:r,...i}=e,a=jE(UE,n),o=qE(UE,n),[s,c]=F.useState(null),[l,u]=F.useState(null),d=yt(t,e=>u(e)),f=TE(n),p=F.useRef(!1),m=F.useRef(!0),{viewport:h,selectedItem:g,selectedItemText:_,focusSelectedItem:v}=o,y=F.useCallback(()=>{if(a.trigger&&a.valueNode&&s&&l&&h&&g&&_){let e=a.trigger.getBoundingClientRect(),t=l.getBoundingClientRect(),n=a.valueNode.getBoundingClientRect(),i=_.getBoundingClientRect();if(a.dir!==`rtl`){let r=i.left-t.left,a=n.left-r,o=e.left-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-GE,d=uw(a,[GE,Math.max(GE,u-l)]);s.style.minWidth=c+`px`,s.style.left=d+`px`}else{let r=t.right-i.right,a=window.innerWidth-n.right-r,o=window.innerWidth-e.right-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-GE,d=uw(a,[GE,Math.max(GE,u-l)]);s.style.minWidth=c+`px`,s.style.right=d+`px`}let o=f(),c=window.innerHeight-GE*2,u=h.scrollHeight,d=window.getComputedStyle(l),m=parseInt(d.borderTopWidth,10),v=parseInt(d.paddingTop,10),y=parseInt(d.borderBottomWidth,10),b=parseInt(d.paddingBottom,10),x=m+v+u+b+y,S=Math.min(g.offsetHeight*5,x),C=window.getComputedStyle(h),w=parseInt(C.paddingTop,10),T=parseInt(C.paddingBottom,10),E=e.top+e.height/2-GE,ee=c-E,D=g.offsetHeight/2,O=g.offsetTop+D,k=m+v+O,te=x-k;if(k<=E){let e=o.length>0&&g===o[o.length-1].ref.current;s.style.bottom=`0px`;let t=l.clientHeight-h.offsetTop-h.offsetHeight,n=k+Math.max(ee,D+(e?T:0)+t+y);s.style.height=n+`px`}else{let e=o.length>0&&g===o[0].ref.current;s.style.top=`0px`;let t=Math.max(E,m+h.offsetTop+(e?w:0)+D)+te;s.style.height=t+`px`,h.scrollTop=k-E+h.offsetTop}s.style.margin=`${GE}px 0`,s.style.minHeight=S+`px`,s.style.maxHeight=c+`px`,r?.(),requestAnimationFrame(()=>p.current=!0)}},[f,a.trigger,a.valueNode,s,l,h,g,_,a.dir,r]);li(()=>y(),[y]);let[b,x]=F.useState();return li(()=>{l&&x(window.getComputedStyle(l).zIndex)},[l]),(0,I.jsx)(tD,{scope:n,contentWrapper:s,shouldExpandOnScrollRef:p,onScrollButtonChange:F.useCallback(e=>{e&&m.current===!0&&(y(),v?.(),m.current=!1)},[y,v]),children:(0,I.jsx)(`div`,{ref:c,style:{display:`flex`,flexDirection:`column`,position:`fixed`,zIndex:b},children:(0,I.jsx)(nT.div,{...i,ref:d,style:{boxSizing:`border-box`,maxHeight:`100%`,...i.style}})})})});QE.displayName=ZE;var $E=`SelectPopperPosition`,eD=F.forwardRef((e,t)=>{let{__scopeSelect:n,align:r=`start`,collisionPadding:i=GE,...a}=e,o=kE(n);return(0,I.jsx)(ds,{...o,...a,ref:t,align:r,collisionPadding:i,style:{boxSizing:`border-box`,...a.style,"--radix-select-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-select-content-available-width":`var(--radix-popper-available-width)`,"--radix-select-content-available-height":`var(--radix-popper-available-height)`,"--radix-select-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-select-trigger-height":`var(--radix-popper-anchor-height)`}})});eD.displayName=$E;var[tD,nD]=DE(UE,{}),rD=`SelectViewport`,iD=F.forwardRef((e,t)=>{let{__scopeSelect:n,nonce:r,...i}=e,a=qE(rD,n),o=nD(rD,n),s=yt(t,a.onViewportChange),c=F.useRef(0);return(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(`style`,{dangerouslySetInnerHTML:{__html:`[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`},nonce:r}),(0,I.jsx)(wE.Slot,{scope:n,children:(0,I.jsx)(nT.div,{"data-radix-select-viewport":``,role:`presentation`,...i,ref:s,style:{position:`relative`,flex:1,overflow:`hidden auto`,...i.style},onScroll:Lr(i.onScroll,e=>{let t=e.currentTarget,{contentWrapper:n,shouldExpandOnScrollRef:r}=o;if(r?.current&&n){let e=Math.abs(c.current-t.scrollTop);if(e>0){let r=window.innerHeight-GE*2,i=parseFloat(n.style.minHeight),a=parseFloat(n.style.height),o=Math.max(i,a);if(o0?s:0,n.style.justifyContent=`flex-end`)}}}c.current=t.scrollTop})})})]})});iD.displayName=rD;var aD=`SelectGroup`,[oD,sD]=DE(aD),cD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=fi();return(0,I.jsx)(oD,{scope:n,id:i,children:(0,I.jsx)(nT.div,{role:`group`,"aria-labelledby":i,...r,ref:t})})});cD.displayName=aD;var lD=`SelectLabel`,uD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=sD(lD,n);return(0,I.jsx)(nT.div,{id:i.id,...r,ref:t})});uD.displayName=lD;var dD=`SelectItem`,[fD,pD]=DE(dD),mD=F.forwardRef((e,t)=>{let{__scopeSelect:n,value:r,disabled:i=!1,textValue:a,...o}=e,s=jE(dD,n),c=qE(dD,n),l=s.value===r,[u,d]=F.useState(a??``),[f,p]=F.useState(!1),m=yt(t,e=>c.itemRefCallback?.(e,r,i)),h=fi(),g=F.useRef(`touch`),_=()=>{i||(s.onValueChange(r),s.onOpenChange(!1))};if(r===``)throw Error(`A must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.`);return(0,I.jsx)(fD,{scope:n,value:r,disabled:i,textId:h,isSelected:l,onItemTextChange:F.useCallback(e=>{d(t=>t||(e?.textContent??``).trim())},[]),children:(0,I.jsx)(wE.ItemSlot,{scope:n,value:r,disabled:i,textValue:u,children:(0,I.jsx)(nT.div,{role:`option`,"aria-labelledby":h,"data-highlighted":f?``:void 0,"aria-selected":l&&f,"data-state":l?`checked`:`unchecked`,"aria-disabled":i||void 0,"data-disabled":i?``:void 0,tabIndex:i?void 0:-1,...o,ref:m,onFocus:Lr(o.onFocus,()=>p(!0)),onBlur:Lr(o.onBlur,()=>p(!1)),onClick:Lr(o.onClick,()=>{g.current!==`mouse`&&_()}),onPointerUp:Lr(o.onPointerUp,()=>{g.current===`mouse`&&_()}),onPointerDown:Lr(o.onPointerDown,e=>{g.current=e.pointerType}),onPointerMove:Lr(o.onPointerMove,e=>{g.current=e.pointerType,i?c.onItemLeave?.():g.current===`mouse`&&e.currentTarget.focus({preventScroll:!0})}),onPointerLeave:Lr(o.onPointerLeave,e=>{e.currentTarget===document.activeElement&&c.onItemLeave?.()}),onKeyDown:Lr(o.onKeyDown,e=>{c.searchRef?.current!==``&&e.key===` `||(SE.includes(e.key)&&_(),e.key===` `&&e.preventDefault())})})})})});mD.displayName=dD;var hD=`SelectItemText`,gD=F.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,...a}=e,o=jE(hD,n),s=qE(hD,n),c=pD(hD,n),l=NE(hD,n),[u,d]=F.useState(null),f=yt(t,e=>d(e),c.onItemTextChange,e=>s.itemTextRefCallback?.(e,c.value,c.disabled)),p=u?.textContent,m=F.useMemo(()=>(0,I.jsx)(`option`,{value:c.value,disabled:c.disabled,children:p},c.value),[c.disabled,c.value,p]),{onNativeOptionAdd:h,onNativeOptionRemove:g}=l;return li(()=>(h(m),()=>g(m)),[h,g,m]),(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(nT.span,{id:c.textId,...a,ref:f}),c.isSelected&&o.valueNode&&!o.valueNodeHasChildren?Ar.createPortal(a.children,o.valueNode):null]})});gD.displayName=hD;var _D=`SelectItemIndicator`,vD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return pD(_D,n).isSelected?(0,I.jsx)(nT.span,{"aria-hidden":!0,...r,ref:t}):null});vD.displayName=_D;var yD=`SelectScrollUpButton`,bD=F.forwardRef((e,t)=>{let n=qE(yD,e.__scopeSelect),r=nD(yD,e.__scopeSelect),[i,a]=F.useState(!1),o=yt(t,r.onScrollButtonChange);return li(()=>{if(n.viewport&&n.isPositioned){let e=function(){a(t.scrollTop>0)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,I.jsx)(CD,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop-=t.offsetHeight)}}):null});bD.displayName=yD;var xD=`SelectScrollDownButton`,SD=F.forwardRef((e,t)=>{let n=qE(xD,e.__scopeSelect),r=nD(xD,e.__scopeSelect),[i,a]=F.useState(!1),o=yt(t,r.onScrollButtonChange);return li(()=>{if(n.viewport&&n.isPositioned){let e=function(){let e=t.scrollHeight-t.clientHeight;a(Math.ceil(t.scrollTop)t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,I.jsx)(CD,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop+=t.offsetHeight)}}):null});SD.displayName=xD;var CD=F.forwardRef((e,t)=>{let{__scopeSelect:n,onAutoScroll:r,...i}=e,a=qE(`SelectScrollButton`,n),o=F.useRef(null),s=TE(n),c=F.useCallback(()=>{o.current!==null&&(window.clearInterval(o.current),o.current=null)},[]);return F.useEffect(()=>()=>c(),[c]),li(()=>{s().find(e=>e.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:`nearest`})},[s]),(0,I.jsx)(nT.div,{"aria-hidden":!0,...i,ref:t,style:{flexShrink:0,...i.style},onPointerDown:Lr(i.onPointerDown,()=>{o.current===null&&(o.current=window.setInterval(r,50))}),onPointerMove:Lr(i.onPointerMove,()=>{a.onItemLeave?.(),o.current===null&&(o.current=window.setInterval(r,50))}),onPointerLeave:Lr(i.onPointerLeave,()=>{c()})})}),wD=`SelectSeparator`,TD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return(0,I.jsx)(nT.div,{"aria-hidden":!0,...r,ref:t})});TD.displayName=wD;var ED=`SelectArrow`,DD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=kE(n),a=jE(ED,n),o=qE(ED,n);return a.open&&o.position===`popper`?(0,I.jsx)(fs,{...i,...r,ref:t}):null});DD.displayName=ED;var OD=`SelectBubbleInput`,kD=F.forwardRef(({__scopeSelect:e,value:t,...n},r)=>{let i=F.useRef(null),a=yt(r,i),o=AC(t);return F.useEffect(()=>{let e=i.current;if(!e)return;let n=window.HTMLSelectElement.prototype,r=Object.getOwnPropertyDescriptor(n,`value`).set;if(o!==t&&r){let n=new Event(`change`,{bubbles:!0});r.call(e,t),e.dispatchEvent(n)}},[o,t]),(0,I.jsx)(nT.select,{...n,style:{...Ks,...n.style},ref:a,defaultValue:t})});kD.displayName=OD;function AD(e){return e===``||e===void 0}function jD(e){let t=Jr(e),n=F.useRef(``),r=F.useRef(0),i=F.useCallback(e=>{let i=n.current+e;t(i),(function e(t){n.current=t,window.clearTimeout(r.current),t!==``&&(r.current=window.setTimeout(()=>e(``),1e3))})(i)},[t]),a=F.useCallback(()=>{n.current=``,window.clearTimeout(r.current)},[]);return F.useEffect(()=>()=>window.clearTimeout(r.current),[]),[n,i,a]}function MD(e,t,n){let r=t.length>1&&Array.from(t).every(e=>e===t[0])?t[0]:t,i=n?e.indexOf(n):-1,a=ND(e,Math.max(i,0));r.length===1&&(a=a.filter(e=>e!==n));let o=a.find(e=>e.textValue.toLowerCase().startsWith(r.toLowerCase()));return o===n?void 0:o}function ND(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var PD=PE,FD=IE,ID=RE,LD=BE,RD=HE,zD=WE,BD=iD,VD=uD,HD=mD,UD=gD,WD=vD,GD=bD,KD=SD,qD=TD,JD=PD,YD=ID,XD=F.forwardRef(({className:e,children:t,...n},r)=>(0,I.jsxs)(FD,{ref:r,className:or(`flex h-10 w-full items-center justify-between rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground ring-offset-background placeholder:text-text-tertiary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1`,e),...n,children:[t,(0,I.jsx)(LD,{asChild:!0,children:(0,I.jsx)(gr,{className:`h-3.5 w-3.5 text-text-tertiary`})})]}));XD.displayName=FD.displayName;var ZD=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(GD,{ref:n,className:or(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(_r,{className:`h-3.5 w-3.5 text-text-tertiary`})}));ZD.displayName=GD.displayName;var QD=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(KD,{ref:n,className:or(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(gr,{className:`h-3.5 w-3.5 text-text-tertiary`})}));QD.displayName=KD.displayName;var $D=F.forwardRef(({className:e,children:t,position:n=`popper`,...r},i)=>(0,I.jsx)(RD,{children:(0,I.jsxs)(zD,{ref:i,className:or(`relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-[10px] border border-border bg-popover py-1.5 text-popover-foreground shadow-lg shadow-primary/5 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2`,n===`popper`&&`data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1`,e),position:n,...r,children:[(0,I.jsx)(ZD,{}),(0,I.jsx)(BD,{className:or(`p-0`,n===`popper`&&`h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]`),children:t}),(0,I.jsx)(QD,{})]})}));$D.displayName=zD.displayName;var eO=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(VD,{ref:n,className:or(`px-3.5 py-2 text-[13px] font-medium text-muted-foreground`,e),...t}));eO.displayName=VD.displayName;var tO=F.forwardRef(({className:e,children:t,...n},r)=>(0,I.jsxs)(HD,{ref:r,className:or(`relative flex w-full cursor-pointer select-none items-center py-2 pl-3.5 pr-8 text-[13px] outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50`,e),...n,children:[(0,I.jsx)(`span`,{className:`absolute right-3 flex h-3.5 w-3.5 items-center justify-center`,children:(0,I.jsx)(WD,{children:(0,I.jsx)(hr,{className:`h-3.5 w-3.5 text-primary`})})}),(0,I.jsx)(UD,{children:t})]}));tO.displayName=HD.displayName;var nO=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(qD,{ref:n,className:or(`-mx-1 my-1 h-px bg-border`,e),...t}));nO.displayName=qD.displayName;function rO(e){let t=(e??`read write`).split(/\s+/).map(e=>e.trim()).filter(Boolean),n=new Set(TC);return new Set(t.filter(e=>n.has(e)))}function iO(e){let t=e.allowed_services_csv,n=e.allowed_nodes_csv,r=new Set((t??``).split(`,`).map(e=>e.trim()).filter(Boolean)),i=new Set((n??``).split(`,`).map(e=>e.trim()).filter(Boolean));return{allowAllServices:!t,allowAllNodes:!n,selectedServiceIds:r,selectedNodeIds:i}}function aO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(e.name??``),[a,o]=(0,F.useState)(e.platform??``),[s,c]=(0,F.useState)(!1),[l,u]=(0,F.useState)(()=>rO(e.scopes)),[d,f]=(0,F.useState)(()=>iO(e)),[p,m]=(0,F.useState)(e.org_id??``),h=lw(),[g,_]=(0,F.useState)(!1),[v,y]=(0,F.useState)(null);async function b(){_(!0),y(null);try{let i={name:r,scopes:Array.from(l).join(` `),allow_all_services:d.allowAllServices,allow_all_nodes:d.allowAllNodes};if(a&&(i.platform=a),e.callback_url&&(i.callback_url=e.callback_url),p&&(i.target_org_id=p),d.allowAllServices||(i.allowed_service_ids=Array.from(d.selectedServiceIds)),d.allowAllNodes||(i.allowed_node_ids=Array.from(d.selectedNodeIds)),e.expires_in_days!=null&&e.expires_in_days>0){let t=new Date;t.setDate(t.getDate()+e.expires_in_days),i.expires_at=t.toISOString()}await d_(t);let o=await p_(t,()=>u_.post(`/api-keys`,i));n({kind:`api-key-create`,api_key_id:o.id,full_key:o.full_key})}catch(e){y(fO(e))}finally{_(!1)}}let x=g||!s||l.size===0;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Create an API key`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Review the details your CLI sent and confirm to mint the key.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(wC,{id:`pair-api-key-name`,label:`Name`,schema:xC,value:r,onChange:i,onValidityChange:c,placeholder:`e.g. coding-agent`,hint:"A short label so you can find this key in `nyxid api-key list`.",autoFocus:!0}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-api-key-platform`,children:`Platform`}),(0,I.jsx)(Pc,{delayDuration:150,children:(0,I.jsxs)(Fc,{children:[(0,I.jsx)(Ic,{asChild:!0,children:(0,I.jsx)(`button`,{type:`button`,"aria-label":`About platform tags`,className:`text-muted-foreground transition-colors hover:text-foreground`,children:(0,I.jsx)(Sr,{className:`h-3.5 w-3.5`})})}),(0,I.jsx)(Lc,{side:`right`,align:`start`,sideOffset:8,className:`max-w-[340px] whitespace-normal px-5 py-4 text-[13px] leading-[1.55]`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`p`,{children:[(0,I.jsx)(`span`,{className:`font-medium text-foreground`,children:`Platform`}),` `,`tags the key with the AI agent that will use it.`]}),(0,I.jsx)(`p`,{className:`text-muted-foreground`,children:`It controls three things: audit attribution (logs show which agent made each proxy request), per- agent rate-limit buckets, and dashboard filtering on the API Keys page.`}),(0,I.jsxs)(`p`,{className:`text-muted-foreground`,children:[`Values are a fixed allowlist —`,` `,(0,I.jsx)(`code`,{children:`claude-code`}),`, `,(0,I.jsx)(`code`,{children:`cursor`}),`,`,` `,(0,I.jsx)(`code`,{children:`codex`}),`, `,(0,I.jsx)(`code`,{children:`openclaw`}),`,`,` `,(0,I.jsx)(`code`,{children:`generic`}),`. Custom strings are rejected by the backend.`]}),(0,I.jsxs)(`p`,{className:`text-muted-foreground`,children:[`Leave as `,(0,I.jsx)(`code`,{children:`— none —`}),` if you don't want the tag.`]})]})})]})})]}),(0,I.jsxs)(JD,{value:a===``?`__none__`:a,onValueChange:e=>{o(e===`__none__`?``:e)},children:[(0,I.jsx)(XD,{id:`pair-api-key-platform`,children:(0,I.jsx)(YD,{placeholder:`— none —`})}),(0,I.jsxs)($D,{children:[(0,I.jsx)(tO,{value:`__none__`,children:`— none —`}),SC.map(e=>(0,I.jsx)(tO,{value:e,children:e},e))]})]}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Tags the key for audit attribution + per-agent rate limits.`})]}),(h.data?.length??0)>0?(0,I.jsxs)(uO,{label:`Owner`,htmlFor:`pair-api-key-owner`,children:[(0,I.jsxs)(`select`,{id:`pair-api-key-owner`,value:p,onChange:e=>{m(e.target.value)},className:`flex h-10 w-full rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,children:[(0,I.jsx)(`option`,{value:``,children:`Personal (your account)`}),h.data?.map(e=>(0,I.jsxs)(`option`,{value:e.id,children:[`Org · `,e.display_name??e.id]},e.id))]}),(0,I.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Org-owned keys authenticate as the org; every admin of the selected org can rotate or delete them.`})]}):null,(0,I.jsx)(EC,{value:l,onChange:u}),(0,I.jsx)(rw,{value:d,onChange:f})]}),v?(0,I.jsx)(dO,{message:v}):null,(0,I.jsx)(Dr,{onClick:()=>void b(),disabled:x,children:g?`Creating...`:`Create key`})]})}function oO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(!1),[a,o]=(0,F.useState)(null);async function s(){i(!0),o(null);try{await d_(t);let r=await p_(t,()=>u_.post(`/api-keys/${encodeURIComponent(e.resource_id)}/rotate`));n({kind:`api-key-rotate`,resource_id:r.id,full_key:r.full_key})}catch(e){o(fO(e))}finally{i(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Rotate API key`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Rotating `,(0,I.jsx)(`strong`,{children:e.display_name}),` will issue a new key and immediately revoke the previous one.`]})]}),a?(0,I.jsx)(dO,{message:a}):null,(0,I.jsx)(Dr,{onClick:()=>void s(),disabled:r,children:r?`Rotating...`:`Rotate key`})]})}var sO=`my-node`;function cO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(e.name??``),[a,o]=(0,F.useState)(!0),[s,c]=(0,F.useState)(!1),[l,u]=(0,F.useState)(null);async function d(){c(!0),u(null);try{let e=r.trim(),i=e.length>0?e:sO;await d_(t);let a=await p_(t,()=>u_.post(`/nodes/register-token`,{name:i}));n({kind:`node-register-token`,token_id:a.token_id,token:a.token})}catch(e){u(fO(e))}finally{c(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Generate node registration token`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Use this token with `,(0,I.jsx)(`code`,{children:`nyxid node register`}),` to connect a new node.`]})]}),(0,I.jsx)(wC,{id:`pair-node-name`,label:`Node name (optional)`,schema:bC,value:r,onChange:i,onValidityChange:o,placeholder:sO,hint:`Lowercase letters, digits, hyphens only (max 64). Leave blank for \`${sO}\`.`,optional:!0,autoFocus:!0}),l?(0,I.jsx)(dO,{message:l}):null,(0,I.jsx)(Dr,{onClick:()=>void d(),disabled:s||!a,children:s?`Generating...`:`Generate token`})]})}function lO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(!1),[a,o]=(0,F.useState)(null);async function s(){i(!0),o(null);try{await d_(t);let r=await p_(t,()=>u_.post(`/nodes/${encodeURIComponent(e.resource_id)}/rotate-token`));n({kind:`node-rotate-token`,resource_id:e.resource_id,auth_token:r.auth_token,signing_secret:r.signing_secret})}catch(e){o(fO(e))}finally{i(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Rotate node token`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Rotating `,(0,I.jsx)(`strong`,{children:e.display_name}),` issues a new auth token + signing secret and revokes the previous pair.`]})]}),a?(0,I.jsx)(dO,{message:a}):null,(0,I.jsx)(Dr,{onClick:()=>void s(),disabled:r,children:r?`Rotating...`:`Rotate token`})]})}function uO({label:e,htmlFor:t,children:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:t,children:e}),n]})}function dO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}function fO(e){return e instanceof Error?e.message:`Something went wrong. Please try again.`}function pO({className:e,...t}){return(0,I.jsx)(`div`,{className:or(`animate-pulse rounded-md bg-muted`,e),...t})}function mO(e){let t=(e??`system`).toLowerCase();return t===`user`||t===`both`}async function hO(e,t,n,r,i){let a={service_slug:e,label:t};r&&(a.node_id=r);let o=i?.trim();o&&(a.endpoint_url=o);try{return await u_.post(`/keys`,a)}catch(e){throw e instanceof i_&&e.status>=400&&e.status<500&&(n.current=!1),e}}function gO(e){if(!(typeof window>`u`))try{fetch(`/api/v1/keys/${encodeURIComponent(e)}?only_if_pending=true`,{method:`DELETE`,credentials:`include`,keepalive:!0})}catch{}}function _O(e){if(!(typeof window>`u`))try{fetch(`/api/v1/cli-pairings/${encodeURIComponent(e)}/cancel`,{method:`POST`,credentials:`include`,keepalive:!0,headers:{"Content-Type":`application/json`},body:`{}`})}catch{}}function vO(e,t,n,r){if(!(typeof window>`u`))try{fetch(`/api/v1/cli-pairings/${encodeURIComponent(e)}/complete`,{method:`POST`,credentials:`include`,keepalive:!0,headers:{"Content-Type":`application/json`},body:JSON.stringify({ack:{acknowledged:!0,service_id:t,slug:n,label:r}})})}catch{}}async function yO(e){if(!e)return{kind:`unknown`};try{if((await u_.delete(`/keys/${encodeURIComponent(e)}?only_if_pending=true`)).deleted===!0)return{kind:`deleted`};try{let t=await u_.get(`/keys/${encodeURIComponent(e)}`);return t.status===`active`?{kind:`active`,key:t}:{kind:`unknown`}}catch{return{kind:`unknown`}}}catch{return{kind:`unknown`}}}async function bO(e,t,n,r,i){let a=i.current;if(a)try{await a}catch{}let o=t.current,s=n.current,c=r.current;t.current=null,n.current=!1;let l=s&&!c;if(o)try{let t=await u_.delete(`/keys/${encodeURIComponent(o)}?only_if_pending=true`);if(t.deleted===!0&&s)l=!0;else if(t.deleted===!1){try{let t=await u_.get(`/keys/${encodeURIComponent(o)}`);await u_.post(`/cli-pairings/${encodeURIComponent(e)}/complete`,{ack:{acknowledged:!0,service_id:t.id,slug:t.slug,label:t.label}})}catch{}return}else l=!1}catch{}if(l)try{await f_(e)}catch{}}function xO({providerId:e,slug:t,label:n,nodeId:r,endpointUrl:i,pairingId:a,credentialMode:o,documentationUrl:s,onSuccess:c,onCancel:l}){let[u,d]=(0,F.useState)(mO(o)?`checking-credentials`:`starting`),[f,p]=(0,F.useState)(null),[m,h]=(0,F.useState)(null),[g,_]=(0,F.useState)(``),[v,y]=(0,F.useState)(``),b=(0,F.useRef)(null),x=(0,F.useRef)(!1),S=(0,F.useRef)(!1),C=(0,F.useRef)(!1),w=(0,F.useRef)(null),T=(0,F.useRef)(!1);(0,F.useEffect)(()=>{function e(){if(T.current)return;let e=b.current;if(e){gO(e),vO(a,e,t,n);return}C.current&&_O(a)}return window.addEventListener(`beforeunload`,e),()=>{window.removeEventListener(`beforeunload`,e),!T.current&&bO(a,b,S,C,w)}},[a,t,n]);async function E(){let e=w.current;if(e)try{await e}catch{}let t=b.current;b.current=null;let n=await yO(t);if(n.kind===`active`)return S.current=!1,T.current=!0,d(`done`),c({kind:`ai-key`,service_id:n.key.id,slug:n.key.slug,label:n.key.label}),`active`;let r=!C.current,i=n.kind===`deleted`;return S.current&&(i||r)?(S.current=!1,await f_(a),`released`):(S.current=!1,`uncertain`)}async function ee(){x.current=!0,await E()!==`active`&&l()}(0,F.useEffect)(()=>{if(!mO(o))return;let t=!1;return(async()=>{try{let n=await u_.get(`/providers/${encodeURIComponent(e)}/credentials`);if(t)return;n.has_credentials?d(`starting`):d(`needs-credentials`)}catch(e){if(t)return;d(`error`),p(wO(e))}})(),()=>{t=!0}},[]);async function D(){if(!(!g.trim()||!v.trim())){d(`saving-credentials`),p(null);try{await u_.put(`/providers/${encodeURIComponent(e)}/credentials`,{client_id:g.trim(),client_secret:v.trim(),label:n}),d(`starting`)}catch(e){d(`needs-credentials`),p(wO(e))}}}(0,F.useEffect)(()=>{if(u!==`starting`)return;let o=!1;return x.current=!1,(async()=>{try{b.current||(await d_(a),S.current=!0);let s;if(b.current)s={id:b.current,status:`pending_auth`};else{C.current=!0;let e=hO(t,n,C,r,i);w.current=e;try{s=await e}finally{w.current===e&&(w.current=null)}b.current=s.id}if(o)return;if(s.status===`active`){await k(s.id);return}let c=await u_.get(`/providers/${encodeURIComponent(e)}/connect/oauth?redirect_path=${encodeURIComponent(`/keys/${s.id}`)}`);if(o)return;if(!c.authorization_url)throw Error(`provider did not return an authorization_url`);if(h(c.authorization_url),!window.open(c.authorization_url,`_blank`,`noopener,noreferrer`)){d(`waiting`),p(`Browser blocked the popup. Use the button below to open the provider sign-in.`),await O(s.id);return}d(`waiting`),await O(s.id)}catch(e){if(o)return;d(`error`),p(wO(e)),E()}})(),()=>{o=!0,x.current=!0}},[u]);async function O(e){let t=Date.now()+300*1e3;for(;Date.now(){_(e.target.value)},autoFocus:!0,autoComplete:`off`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-aikey-oauth-client-secret`,children:`Client Secret`}),(0,I.jsx)(m_,{id:`pair-aikey-oauth-client-secret`,type:`password`,value:v,onChange:e=>{y(e.target.value)},autoComplete:`off`})]})]}),f?(0,I.jsx)(CO,{message:f}):null,(0,I.jsx)(Dr,{onClick:()=>void D(),disabled:e||!g.trim()||!v.trim(),children:e?`Saving...`:`Save and continue`}),(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void ee(),disabled:e,children:`Cancel`})]})}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:`Complete sign-in on the provider`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`We opened a new tab where you'll authorize NyxID. When it completes, come back — this page will finish automatically.`})]}),u===`checking-credentials`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Checking provider credentials...`]}):u===`starting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Creating placeholder service...`]}):u===`waiting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Waiting for provider authorization...`]}):null,m&&u===`waiting`?(0,I.jsxs)(`a`,{href:m,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center justify-center gap-2 rounded-md border bg-muted/40 px-3 py-2 text-sm hover:bg-muted`,children:[`Reopen provider sign-in`,(0,I.jsx)(yr,{className:`h-4 w-4`})]}):null,f?(0,I.jsx)(CO,{message:f}):null,u===`done`?null:(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void ee(),children:`Cancel`})]})}function SO({providerId:e,slug:t,label:n,nodeId:r,endpointUrl:i,pairingId:a,onSuccess:o,onCancel:s}){let[c,l]=(0,F.useState)(null),[u,d]=(0,F.useState)(null),[f,p]=(0,F.useState)(`starting`),[m,h]=(0,F.useState)(null),[g,_]=(0,F.useState)(!1),v=(0,F.useRef)(0),y=(0,F.useRef)(null),b=(0,F.useRef)(!1),x=(0,F.useRef)(!1),S=(0,F.useRef)(!1),C=(0,F.useRef)(null),w=(0,F.useRef)(!1);async function T(){let e=C.current;if(e)try{await e}catch{}let t=y.current;y.current=null;let n=await yO(t);if(n.kind===`active`)return x.current=!1,w.current=!0,p(`done`),o({kind:`ai-key`,service_id:n.key.id,slug:n.key.slug,label:n.key.label}),`active`;let r=!S.current,i=n.kind===`deleted`;return x.current&&(i||r)?(x.current=!1,await f_(a),`released`):(x.current=!1,`uncertain`)}async function E(){b.current=!0,v.current+=1,await T()!==`active`&&s()}(0,F.useEffect)(()=>{function e(){if(w.current)return;let e=y.current;if(e){gO(e),vO(a,e,t,n);return}S.current&&_O(a)}return window.addEventListener(`beforeunload`,e),()=>{window.removeEventListener(`beforeunload`,e),!w.current&&bO(a,y,x,S,C)}},[a,t,n]),(0,F.useEffect)(()=>(b.current=!1,ee(),()=>{b.current=!0,v.current+=1}),[]);async function ee(){let s=++v.current;p(`starting`),h(null);try{let c=y.current;if(!c){await d_(a),x.current=!0,S.current=!0;let e=hO(t,n,S,r,i);C.current=e;let l;try{l=await e}finally{C.current===e&&(C.current=null)}if(c=l.id,y.current=c,s!==v.current)return;if(l.status===`active`){let e=await u_.get(`/keys/${encodeURIComponent(c)}`);if(s!==v.current)return;w.current=!0,p(`done`),o({kind:`ai-key`,service_id:e.id,slug:e.slug,label:e.label});return}}let u=await u_.post(`/providers/${encodeURIComponent(e)}/connect/device-code/initiate`,{});if(s!==v.current)return;l(u.user_code),d(u.verification_uri),p(`waiting`);let f=Number(u.interval)||5,m=`/providers/${encodeURIComponent(e)}/connect/device-code/poll`,g=Date.now()+600*1e3;for(;Date.now(){_(!1)},2e3)}catch{}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:`Authorize via device code`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Open the verification URL, enter the code, and complete sign-in on the provider. This page will finish automatically.`})]}),f===`starting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Requesting device code...`]}):f===`waiting`&&c&&u?(0,I.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-md border bg-muted/30 p-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`span`,{className:`text-xs uppercase tracking-wide text-muted-foreground`,children:`Code`}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(`code`,{className:`rounded bg-background px-3 py-1.5 font-mono text-lg`,children:c}),(0,I.jsxs)(Dr,{variant:`outline`,size:`sm`,onClick:()=>void D(),children:[(0,I.jsx)(vr,{className:`mr-1.5 h-3.5 w-3.5`}),g?`Copied`:`Copy`]})]})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`span`,{className:`text-xs uppercase tracking-wide text-muted-foreground`,children:`Visit`}),(0,I.jsxs)(`a`,{href:u,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1.5 text-sm underline-offset-2 hover:underline`,children:[u,(0,I.jsx)(yr,{className:`h-3.5 w-3.5`})]})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-3 w-3 animate-spin`}),`Waiting for authorization...`]})]}):f===`expired`?(0,I.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,I.jsx)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:`The device code expired before authorization completed.`}),(0,I.jsx)(Dr,{onClick:()=>void ee(),children:`Request a new code`})]}):null,m?(0,I.jsx)(CO,{message:m}):null,f===`done`?null:(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void E(),children:`Cancel`})]})}function CO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}function wO(e){return e instanceof i_||e instanceof Error?e.message:`Something went wrong. Please try again.`}function TO(e){return new Promise(t=>{window.setTimeout(t,e)})}function EO(e){let t=(e.provider_type??``).toLowerCase();return(e.service_type??`http`)===`ssh`?`ssh`:t===`oauth2`?`oauth`:t===`device_code`?`device-code`:e.requires_credential===!1?`no-auth`:Array.isArray(e.token_exchange_credential_fields)&&e.token_exchange_credential_fields.length>0?`token-exchange`:e.requires_gateway_url?`gateway-url`:`paste-key`}function DO(e,t){switch(e){case`no-auth`:return`1-click connect`;case`gateway-url`:return`URL + API key`;case`token-exchange`:return`${(t.token_exchange_credential_fields??[]).length} fields`;case`oauth`:return`OAuth sign-in`;case`device-code`:return`device code`;case`ssh`:return`SSH cert`;case`paste-key`:return`paste API key`}}var OO={oauth:`OAuth`,"device-code":`Device code`,ssh:`SSH`};function kO(e,t){if(!t)return 0;let n=e.toLowerCase(),r=t.toLowerCase(),i=n.indexOf(r);if(i>=0)return i;let a=0,o=0,s=100,c=0;for(;a{let e=await u_.get(`/catalog?include_all=true`);return e.entries??e.services??[]}}),o=r??[],s=t.trim(),c=s?o.map(e=>{let t=kO(e.slug,s),n=kO(e.name??``,s),r=t===null?n:n===null?t:Math.min(t,n);return r===null?null:{entry:e,score:r}}).filter(e=>e!==null).sort((e,t)=>e.score-t.score).map(e=>e.entry):o;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(`label`,{htmlFor:`catalog-search`,className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:`Search`}),(0,I.jsx)(m_,{id:`catalog-search`,type:`search`,placeholder:`search services…`,autoComplete:`off`,spellCheck:!1,value:t,onChange:e=>{n(e.target.value)}})]}),(0,I.jsx)(jO,{children:`Simple setup`}),i?(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Loading catalog…`}):a?(0,I.jsx)(`p`,{className:`text-sm text-destructive`,children:a instanceof i_?`Couldn't load the catalog: ${a.message} (${String(a.status)})`:`Couldn't load the catalog. Check the CLI logs for details.`}):c.length===0?(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:s?`No services match your search.`:`Catalog is empty.`}):(0,I.jsx)(`div`,{className:`max-h-[420px] overflow-y-auto overscroll-contain pr-1`,role:`list`,children:(0,I.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:c.map(t=>(0,I.jsx)(MO,{entry:t,onClick:()=>{e(t.slug)}},t.slug))})}),(0,I.jsx)(jO,{children:`Advanced`}),(0,I.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:(0,I.jsx)(NO,{onClick:()=>{e(`__custom__`)}})})]})}function jO({children:e}){return(0,I.jsx)(`div`,{className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:e})}function MO({entry:e,onClick:t}){let n=EO(e),r=OO[n];return(0,I.jsxs)(`button`,{type:`button`,onClick:t,role:`listitem`,className:`group relative flex min-h-[132px] flex-col items-start gap-1 rounded-[10px] border border-border bg-card/60 p-4 text-left transition-colors hover:border-primary/60 hover:bg-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,children:[r?(0,I.jsx)(`span`,{className:`absolute right-3 top-3 rounded-full border border-border bg-muted/60 px-2 py-0.5 text-[10px] uppercase tracking-wide text-muted-foreground`,children:r}):null,(0,I.jsx)(`span`,{className:`font-display text-sm font-semibold text-foreground`,children:e.name||e.slug}),e.description?(0,I.jsx)(`span`,{className:`line-clamp-2 text-xs text-muted-foreground`,children:e.description}):null,(0,I.jsx)(`span`,{className:`mt-auto text-[11px] font-mono text-text-tertiary`,children:DO(n,e)})]})}function NO({onClick:e}){return(0,I.jsxs)(`button`,{type:`button`,onClick:e,className:`flex min-h-[132px] flex-col items-start gap-1 rounded-[10px] border border-dashed border-border bg-transparent p-4 text-left transition-colors hover:border-primary/60 hover:bg-card/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,children:[(0,I.jsx)(`span`,{className:`font-display text-sm font-semibold text-foreground`,children:`Custom / self-hosted…`}),(0,I.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`For anything that isn't in the catalog above — paste your own endpoint URL + credential.`})]})}function PO(e){let t=(e.provider_type??``).toLowerCase();return t===`oauth2`?`oauth`:t===`device_code`?`device-code`:e.requires_credential===!1?`no-auth`:Array.isArray(e.token_exchange_credential_fields)&&e.token_exchange_credential_fields.length>0?`token-exchange`:e.requires_credential?`api-key`:`other`}function FO({prefill:e,pairingId:t,onSuccess:n,onSlugPicked:r}){let[i,a]=(0,F.useState)(e.custom?`__custom__`:e.slug??``),o=i.trim(),s=(0,F.useRef)(o?null:``);(0,F.useEffect)(()=>{s.current!==o&&(s.current=o,r?.(o))},[o,r]);let{data:c,isLoading:l,error:u}=ut({queryKey:[`cli-pair`,`catalog`,o],queryFn:async()=>u_.get(`/catalog/${encodeURIComponent(o)}`),enabled:!!o&&o!==`__custom__`}),d=u?u instanceof i_?u.message:`Couldn't load catalog entry "${o}".`:null,f=!o&&!d,p=o===`__custom__`,m=f?`Add an AI service`:p?`Custom / self-hosted service`:`Connect service`,h=f?`Pick a service to connect. Simple-bearer APIs (OpenAI, Anthropic, Gemini) land in the guided form. Anything else — self-hosted, OAuth, device code, custom endpoint — goes to the power-user form.`:p?`For services not in the catalog — paste your own endpoint URL and credential.`:`Your CLI wants to add ${o||`a service`} to NyxID. Confirm the details here.`;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:m}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:h})]}),f?(0,I.jsx)(AO,{onSelect:a}):p?(0,I.jsx)(BO,{prefill:e,pairingId:t,onSuccess:n,onBack:()=>{a(``)}}):l?(0,I.jsx)(pO,{className:`h-24 w-full`}):d?(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsx)(UO,{message:d}),(0,I.jsx)(AO,{onSelect:a})]}):c?(0,I.jsx)(VO,{entry:c,prefill:e,pairingId:t,onSuccess:n}):null]})}function IO(e){switch(e){case`header`:return`X-API-Key`;case`query`:return`key`;case`path`:return`bot`;case`body`:return`app_secret`;default:return`Authorization`}}function LO(e){switch(e){case`bearer`:case`header`:case`query`:case`path`:case`basic`:case`body`:case`bot_bearer`:case`none`:return e;default:return`bearer`}}function RO(e){return e===`header`||e===`query`||e===`path`||e===`body`}function zO(){return(0,I.jsx)(`span`,{"aria-hidden":`true`,className:`text-destructive ml-0.5`,children:`*`})}function BO({prefill:e,pairingId:t,onSuccess:n,onBack:r}){let[i,a]=(0,F.useState)(e.label??``),[o,s]=(0,F.useState)(e.endpoint_url??``),[c,l]=(0,F.useState)(``),[u,d]=(0,F.useState)(LO(e.auth_method)),[f,p]=(0,F.useState)(e.auth_key_name??IO(LO(e.auth_method))),[m,h]=(0,F.useState)(e.custom_slug??``),[g,_]=(0,F.useState)(!1),[v,y]=(0,F.useState)(null),b=e.via_node?.trim()??``,x=i.trim(),S=o.trim(),C=c.trim(),w=u!==`none`,T=RO(u),E=g||!x||!S||w&&!C,ee=u===`bot_bearer`?`Bot token`:u===`basic`?`user:pass`:u===`body`?`${f.trim()||IO(u)} value`:`API key / credential`;async function D(){_(!0),y(null);try{let e={label:x,endpoint_url:S,auth_method:u};w&&(e.credential=C),T&&(e.auth_key_name=f.trim()||IO(u));let r=m.trim();r&&(e.slug=r),b&&(e.node_id=b),await d_(t);let i=await p_(t,()=>u_.post(`/keys`,e));n({kind:`ai-key`,service_id:i.id,slug:i.slug,label:i.label})}catch(e){y(e instanceof i_?e.message:e.message??`Failed.`)}finally{_(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-label`,children:`Label`}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-label`,value:i,onChange:e=>{a(e.target.value)},placeholder:`e.g. My Self-hosted OpenAI Proxy`,autoFocus:!0,"aria-required":`true`}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Shown everywhere in the CLI and web UI.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-endpoint`,children:`Endpoint URL`}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-endpoint`,value:o,onChange:e=>{s(e.target.value)},placeholder:`https://api.example.com`,"aria-required":`true`}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The base URL NyxID proxies requests to.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-auth-method`,children:`Auth method`}),(0,I.jsx)(zO,{})]}),(0,I.jsxs)(`select`,{id:`pair-custom-auth-method`,value:u,onChange:e=>{let t=e.target.value;d(t),(!f.trim()||[`Authorization`,`X-API-Key`,`key`,`bot`,`app_secret`].includes(f.trim()))&&p(IO(t))},className:`flex h-10 w-full rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,"aria-required":`true`,children:[(0,I.jsx)(`option`,{value:`bearer`,children:`bearer (Authorization: Bearer …)`}),(0,I.jsx)(`option`,{value:`bot_bearer`,children:`bot_bearer (Authorization: Bot …)`}),(0,I.jsx)(`option`,{value:`header`,children:`header (custom header)`}),(0,I.jsx)(`option`,{value:`query`,children:`query (?key=…)`}),(0,I.jsx)(`option`,{value:`path`,children:`path (path-prefix injection)`}),(0,I.jsx)(`option`,{value:`basic`,children:`basic (Authorization: Basic …)`}),(0,I.jsx)(`option`,{value:`body`,children:`body (JSON-body field injection)`}),(0,I.jsx)(`option`,{value:`none`,children:`none (no auth injection)`})]}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`How NyxID attaches the credential to outgoing requests.`})]}),w?(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-credential`,children:ee}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-credential`,type:`password`,value:c,onChange:e=>{l(e.target.value)},placeholder:u===`basic`?`user:pass`:`sk-...`,autoFocus:!!e.custom,"aria-required":`true`}),(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Pasted once, encrypted at rest.`,u===`basic`?` Format: user:pass.`:``]})]}):null,T?(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-auth-key-name`,children:u===`header`?`Header name`:u===`query`?`Query parameter name`:u===`path`?`Path prefix segment`:`Body field name`}),(0,I.jsx)(m_,{id:`pair-custom-auth-key-name`,value:f,onChange:e=>{p(e.target.value)},placeholder:IO(u)})]}):null,b?(0,I.jsxs)(`div`,{className:`rounded-[10px] border border-border bg-muted/40 px-3 py-2`,children:[(0,I.jsx)(`p`,{className:`text-xs font-medium text-foreground`,children:`Routed via node`}),(0,I.jsx)(`code`,{className:`font-mono text-[11px] text-muted-foreground`,children:b}),(0,I.jsx)(`p`,{className:`text-[11px] text-muted-foreground mt-1`,children:`Credential will be encrypted and pushed to this node over the existing WebSocket channel. NyxID never logs it.`})]}):null,(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-slug`,children:`Custom slug (optional)`}),(0,I.jsx)(m_,{id:`pair-custom-slug`,value:m,onChange:e=>{h(e.target.value)},placeholder:`auto-generated from label`}),(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`URL segment at `,(0,I.jsx)(`code`,{children:`/proxy/s//…`}),`. Leave blank to let NyxID derive it from the label.`]})]})]}),v?(0,I.jsx)(UO,{message:v}):null,(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,I.jsx)(Dr,{variant:`outline`,onClick:r,disabled:g,children:`← Back`}),(0,I.jsx)(Dr,{onClick:()=>void D(),disabled:E,children:g?`Connecting…`:`Connect service`})]})]})}function VO({entry:e,prefill:t,pairingId:n,onSuccess:r}){let i=PO(e),[a,o]=(0,F.useState)(t.label??e.name),[s,c]=(0,F.useState)(``),[l,u]=(0,F.useState)(t.endpoint_url??``),[d,f]=(0,F.useState)({}),[p,m]=(0,F.useState)(!1),[h,g]=(0,F.useState)(null),[_,v]=(0,F.useState)(!1);async function y(){m(!0),g(null);try{let o={service_slug:e.slug,label:a};if(i===`token-exchange`){let t=e.token_exchange_credential_fields??[],n={};for(let e of t){let t=d[e.name]?.trim();if(!t){g(`${e.label||e.name} is required.`),m(!1);return}n[e.name]=t}o.credential=JSON.stringify(n)}else i===`api-key`&&e.requires_credential&&(o.credential=s);(e.requires_gateway_url||l)&&(o.endpoint_url=l),t.via_node&&(o.node_id=t.via_node),await d_(n);let c=await p_(n,()=>u_.post(`/keys`,o));r({kind:`ai-key`,service_id:c.id,slug:c.slug,label:c.label})}catch(e){g(e instanceof i_?e.message:`Failed to create service.`)}finally{m(!1)}}async function b(e){try{await u_.post(`/cli-pairings/${encodeURIComponent(n)}/cancel`,{})}catch{}if(e){if(window.__WIZARD_BOOTSTRAP__?.context===`local`){alert(`This auth shape isn't supported in the CLI wizard. Open your NyxID dashboard and complete setup on the Keys page (tab: External Services). You can close this tab now.`);return}window.location.assign(e)}else window.history.back()}if(e.service_type===`ssh`)return(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:[e.name,` is an SSH service. Use`,` `,(0,I.jsx)(`code`,{children:`nyxid service add-ssh`}),` from your CLI instead (certificate-based auth, not a credential binding).`]}),(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void b(null),children:`Go back`})]});if(i===`other`||(i===`oauth`||i===`device-code`)&&!e.provider_config_id){let t=`/keys?tab=services&slug=${encodeURIComponent(e.slug)}`;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:[e.name,` uses `,(0,I.jsx)(`code`,{children:e.auth_method}),` auth, which isn't supported via remote pairing. Complete setup on the main Keys page. Your CLI will receive a cancel and print a "finish in browser" hint.`]}),(0,I.jsxs)(Dr,{onClick:()=>void b(t),className:`justify-center gap-2`,children:[`Open Keys page`,(0,I.jsx)(yr,{className:`h-4 w-4`})]})]})}let x=l.trim()||t.endpoint_url;if(_&&i===`oauth`&&e.provider_config_id)return(0,I.jsx)(xO,{providerId:e.provider_config_id,slug:e.slug,label:a,nodeId:t.via_node,endpointUrl:x,pairingId:n,credentialMode:e.credential_mode,documentationUrl:e.documentation_url,onSuccess:r,onCancel:()=>{v(!1)}});if(_&&i===`device-code`&&e.provider_config_id)return(0,I.jsx)(SO,{providerId:e.provider_config_id,slug:e.slug,label:a,nodeId:t.via_node,endpointUrl:x,pairingId:n,onSuccess:r,onCancel:()=>{v(!1)}});let S=i===`api-key`&&e.requires_credential,C=p?`Creating...`:i===`oauth`?`Continue with provider sign-in`:i===`device-code`?`Get device code`:i===`no-auth`?`Connect`:`Create service`,w=i===`token-exchange`?(e.token_exchange_credential_fields??[]).every(e=>(d[e.name]??``).trim().length>0):!0,T=p||!a.trim()||S&&!s.trim()||e.requires_gateway_url&&!l.trim()||!w;function E(){i===`oauth`||i===`device-code`?v(!0):y()}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border bg-muted/30 p-3`,children:[e.icon_url?(0,I.jsx)(`img`,{src:e.icon_url,alt:``,className:`h-8 w-8 rounded`,loading:`lazy`}):null,(0,I.jsxs)(`div`,{className:`flex flex-col gap-0.5`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:e.name}),e.description?(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:e.description}):null,(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Auth: `,(0,I.jsx)(`code`,{children:e.auth_method})]})]})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsx)(HO,{label:`Label`,htmlFor:`pair-aikey-label`,children:(0,I.jsx)(m_,{id:`pair-aikey-label`,value:a,onChange:e=>{o(e.target.value)},autoFocus:!0})}),e.requires_gateway_url?(0,I.jsx)(HO,{label:`Instance URL`,htmlFor:`pair-aikey-url`,children:(0,I.jsx)(m_,{id:`pair-aikey-url`,value:l,onChange:e=>{u(e.target.value)},placeholder:`https://your-instance.example.com`})}):null,S?(0,I.jsxs)(HO,{label:`API key`,htmlFor:`pair-aikey-credential`,children:[(0,I.jsx)(m_,{id:`pair-aikey-credential`,type:`password`,autoComplete:`off`,value:s,onChange:e=>{c(e.target.value)},placeholder:`sk-...`}),e.api_key_url?(0,I.jsxs)(`a`,{href:e.api_key_url,target:`_blank`,rel:`noopener noreferrer`,className:`mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground underline-offset-2 hover:underline`,children:[`Get an API key`,(0,I.jsx)(yr,{className:`h-3 w-3`})]}):null]}):null,i===`token-exchange`?(e.token_exchange_credential_fields??[]).map(e=>(0,I.jsx)(HO,{label:e.label||e.name,htmlFor:`pair-aikey-tx-${e.name}`,children:(0,I.jsx)(m_,{id:`pair-aikey-tx-${e.name}`,type:e.secret?`password`:`text`,autoComplete:`off`,value:d[e.name]??``,onChange:t=>{let n=t.target.value;f(t=>({...t,[e.name]:n}))},placeholder:e.placeholder??``})},e.name)):null,i===`no-auth`?(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`This service doesn't need a credential. Click Connect to add it to your services.`}):null]}),h?(0,I.jsx)(UO,{message:h}):null,(0,I.jsx)(Dr,{onClick:E,disabled:T,children:C})]})}function HO({label:e,htmlFor:t,children:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:t,children:e}),n]})}function UO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}var WO=!1,GO=null;function KO(e){if(GO=e,WO)return;WO=!0;let t=window.fetch.bind(window);window.fetch=async(e,n)=>{let r=QO(e,n),i=new URL(r.url,window.location.origin);if(i.origin!==window.location.origin)return t(r);if(i.pathname.startsWith(`/api/v1/cli-pairings/`))return i.pathname.endsWith(`/cancel`)?t(`/api/proxy/cancel-unload`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`,keepalive:n?.keepalive??!1}):new Response(JSON.stringify({ok:!0}),{status:200,headers:{"content-type":`application/json`}});if(r.method===`DELETE`&&/^\/api\/v1\/keys\/[^/]+$/.test(i.pathname)&&i.searchParams.get(`only_if_pending`)===`true`){let e=i.pathname.split(`/`).pop()??``;return t(`/api/proxy/abandon-placeholder`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:JSON.stringify({key_id:e})})}if(i.pathname.startsWith(`/api/v1/`)){let e=new URL(i.toString());e.pathname=`/api/proxy${i.pathname}`;let a=ek($O(r,n));return t(e.toString(),{method:r.method,headers:a,body:await tk(r),credentials:r.credentials,signal:r.signal})}return t(r)}}async function qO(e){let t=await fetch(`/api/proxy/complete`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:JSON.stringify(e)});if(!t.ok)throw Error(`/api/proxy/complete failed: ${String(t.status)} ${t.statusText}`)}async function JO(){try{await fetch(`/api/proxy/cancel`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`})}catch{}}var YO=1200,XO=3;function ZO(e){let t=0,n=!1,r=window.setInterval(()=>{fetch(`/api/proxy/heartbeat`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`}).then(r=>{if(!r.ok)throw Error(`heartbeat ${String(r.status)}`);t=0,n&&(n=!1,e?.onReconnect?.())}).catch(()=>{t+=1,t>=XO&&!n&&(n=!0,e?.onDisconnect?.())})},YO);return()=>{window.clearInterval(r)}}function QO(e,t){return e instanceof Request?e:new Request(e,t)}function $O(e,t){let n={};return e.headers.forEach((e,t)=>{n[t]=e}),t?.headers&&new Headers(t.headers).forEach((e,t)=>{n[t]=e}),n}function ek(e){return GO?{...e,"x-wizard-csrf":GO.csrf}:e}async function tk(e){if(e.method===`GET`||e.method===`HEAD`)return null;try{let t=await e.clone().text();return t.length>0?t:null}catch{return null}}function nk({state:e,context:t,pairingStatus:n}){return(0,I.jsxs)(`div`,{role:`alert`,"aria-live":`polite`,className:`mb-4 flex items-start gap-3 rounded-[10px] border border-destructive/50 bg-destructive/10 px-4 py-3 text-[13px] text-foreground`,children:[(0,I.jsx)(e===`reconnecting`?Cr:Tr,{className:`mt-0.5 h-4 w-4 shrink-0 text-destructive `+(e===`reconnecting`?`animate-spin`:``),"aria-hidden":!0}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`p`,{className:`font-medium`,children:e===`reconnecting`?`Reconnecting…`:t===`local`?`Connection to CLI interrupted`:n===`cancelled`?`CLI cancelled this pairing`:n===`expired`?`Pairing expired`:`Pairing went stale`}),(0,I.jsx)(`p`,{className:`text-muted-foreground`,children:e===`reconnecting`?`Retrying the last check…`:t===`local`?`The nyxid CLI missed several heartbeat checks. Keep this tab open; the wizard will continue if the connection recovers. If this message persists, re-run the command in your terminal.`:n===`cancelled`?`The CLI sent a cancel — nothing was created on the server. You can close this tab.`:n===`expired`?`This pairing passed its 15-minute TTL. Re-run the command in your terminal to start a new one.`:`The pairing record is no longer reachable. Re-run the CLI command to start a fresh one.`})]})]})}var rk=window.__WIZARD_BOOTSTRAP__;rk&&KO(rk);var ik=new Ge({defaultOptions:{queries:{retry:1,staleTime:3e4}}});function ak(){let[e,t]=(0,F.useState)({phase:`claimed`}),[n,r]=(0,F.useState)(null),[i,a]=(0,F.useState)(!!rk?.prefill?.slug),[o,s]=(0,F.useState)(!1);if((0,F.useEffect)(()=>{if(!rk)return;let e=ZO({onDisconnect:()=>{s(!0)},onReconnect:()=>{s(!1)}});return()=>{e()}},[]),!rk)return(0,I.jsx)(mk,{});let c=mt(sk(e.phase),rk.flow,{slugPicked:i});async function l(e){if(e.kind===`ai-key`){t({phase:`acking`,result:e}),await ok(e,r,t);return}t({phase:`secret`,result:e})}async function u(){e.phase===`secret`&&await ok(e.result,r,t)}return(0,I.jsxs)(gt,{context:`local`,step:c,children:[o?(0,I.jsx)(nk,{state:`disconnected`,context:`local`}):null,e.phase===`claimed`?(0,I.jsx)(ck,{flow:rk.flow,prefill:rk.prefill??{},onSuccess:e=>void l(e),onCancel:()=>{t({phase:`cancelled`}),JO()},onSlugPicked:e=>{a(!!e)}}):e.phase===`secret`?(0,I.jsx)(lk,{result:e.result,completeError:n,onAck:()=>void u()}):e.phase===`acking`?(0,I.jsx)(uk,{result:e.result,completeError:n,onRetry:()=>{l(e.result)}}):e.phase===`cancelled`?(0,I.jsx)(fk,{}):(0,I.jsx)(dk,{})]})}async function ok(e,t,n){try{await qO(e.kind===`ai-key`?{acknowledged:!0,service_id:e.service_id,slug:e.slug,label:e.label}:e.kind===`api-key-create`?{acknowledged:!0,api_key_id:e.api_key_id}:e.kind===`node-register-token`?{acknowledged:!0,token_id:e.token_id}:{acknowledged:!0,resource_id:e.resource_id}),t(null),n({phase:`done`})}catch(e){t(e instanceof Error?e.message:String(e))}}function sk(e){return e===`claimed`?`claimed`:e===`secret`?`secret`:e===`acking`?`acking`:`done`}function ck({flow:e,prefill:t,onSuccess:n,onCancel:r,onSlugPicked:i}){let a=`local`;switch(e){case`api-key-create`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(aO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(pk,{onCancel:r})]});case`api-key-rotate`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(oO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(pk,{onCancel:r})]});case`node-register-token`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(cO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(pk,{onCancel:r})]});case`node-rotate-token`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(lO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(pk,{onCancel:r})]});case`ai-key`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(FO,{prefill:t,pairingId:a,onSuccess:n,onSlugPicked:i}),(0,I.jsx)(pk,{onCancel:r})]})}}function lk({result:e,completeError:t,onAck:n}){let r=t===null;return e.kind===`api-key-create`?(0,I.jsx)(Or,{title:`API key created`,description:`Save this key now — it won't be shown again.`,secret:e.full_key,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:r&&t===null&&!1}):e.kind===`api-key-rotate`?(0,I.jsx)(Or,{title:`API key rotated`,description:`The previous key is revoked. Save this new value now — it won't be shown again.`,secret:e.full_key,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):e.kind===`node-register-token`?(0,I.jsx)(Or,{title:`Registration token generated`,description:"Use this with `nyxid node register`. Save it now — it won't be shown again.",secret:e.token,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):e.kind===`node-rotate-token`?(0,I.jsx)(Or,{title:`Node tokens rotated`,description:"Update the node with `nyxid node rekey`. Save both values now — they won't be shown again.",secret:e.auth_token,secondarySecret:{label:`Signing secret`,value:e.signing_secret},ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):(0,I.jsx)(`p`,{className:`text-sm text-destructive`,children:`Unknown result kind.`})}function uk({result:e,completeError:t,onRetry:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Service added`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[(0,I.jsx)(`code`,{className:`font-mono text-xs`,children:e.slug}),` is now connected. Check your terminal for the final summary.`]}),t?(0,I.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,I.jsxs)(`p`,{className:`text-sm text-destructive`,children:[`Couldn't notify CLI: `,t]}),(0,I.jsx)(Dr,{variant:`outline`,onClick:n,children:`Retry`})]}):null]})}function dk(){return(0,I.jsx)(`div`,{className:`flex flex-col gap-4`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Done`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`You can close this tab and return to your terminal.`})]})})}function fk(){return(0,I.jsx)(`div`,{className:`flex flex-col gap-4`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Cancelled`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Nothing was created. You can close this tab — your CLI should already be back at the prompt.`})]})})}function pk({onCancel:e}){return(0,I.jsx)(`button`,{type:`button`,onClick:e,className:`self-start text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground`,children:`Cancel and return to terminal`})}function mk(){return(0,I.jsx)(`div`,{className:`mx-auto flex min-h-screen max-w-md items-center justify-center p-6`,children:(0,I.jsxs)(`div`,{className:`w-full rounded-xl border border-border bg-card p-8`,children:[(0,I.jsx)(`h1`,{className:`font-serif text-xl`,children:`Wizard bootstrap missing`}),(0,I.jsxs)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:[`This page expects to be served by the `,(0,I.jsx)(`code`,{children:`nyxid`}),` CLI's local wizard server, which injects bootstrap config on request. Open the URL printed by the CLI instead.`]})]})})}var hk=document.getElementById(`wizard-root`);hk&&(0,dt.createRoot)(hk).render((0,I.jsx)(F.StrictMode,{children:(0,I.jsx)(Xe,{client:ik,children:(0,I.jsx)(ak,{})})})); +`},hE=0,gE=[];function _E(e){var t=F.useRef([]),n=F.useRef([0,0]),r=F.useRef(),i=F.useState(hE++)[0],a=F.useState(zT)[0],o=F.useRef(e);F.useEffect(function(){o.current=e},[e]),F.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=mT([e.lockRef.current],(e.shards||[]).map(fE),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=F.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=uE(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=rE(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=rE(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return lE(h,t,e,h===`h`?s:c,!0)},[]),c=F.useCallback(function(e){var n=e;if(!(!gE.length||gE[gE.length-1]!==a)){var r=`deltaY`in n?dE(n):uE(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&pE(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(fE).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=F.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:vE(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=F.useCallback(function(e){n.current=uE(e),r.current=void 0},[]),d=F.useCallback(function(t){l(t.type,dE(t),t.target,s(t,e.lockRef.current))},[]),f=F.useCallback(function(t){l(t.type,uE(t),t.target,s(t,e.lockRef.current))},[]);F.useEffect(function(){return gE.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,QT),document.addEventListener(`touchmove`,c,QT),document.addEventListener(`touchstart`,u,QT),function(){gE=gE.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,QT),document.removeEventListener(`touchmove`,c,QT),document.removeEventListener(`touchstart`,u,QT)}},[]);var p=e.removeScrollBar,m=e.inert;return F.createElement(F.Fragment,null,m?F.createElement(a,{styles:mE(i)}):null,p?F.createElement(YT,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function vE(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var yE=OT(kT,_E),bE=F.forwardRef(function(e,t){return F.createElement(jT,fT({},e,{ref:t,sideCar:yE}))});bE.classNames=jT.classNames;var xE=[` `,`Enter`,`ArrowUp`,`ArrowDown`],SE=[` `,`Enter`],CE=`Select`,[wE,TE,EE]=yw(CE),[DE,OE]=bw(CE,[EE,qo]),kE=qo(),[AE,jE]=DE(CE),[ME,NE]=DE(CE),PE=e=>{let{__scopeSelect:t,children:n,open:r,defaultOpen:i,onOpenChange:a,value:o,defaultValue:s,onValueChange:c,dir:l,name:u,autoComplete:d,disabled:f,required:p,form:m}=e,h=kE(t),[g,_]=F.useState(null),[v,y]=F.useState(null),[b,x]=F.useState(!1),S=Cw(l),[C,w]=Is({prop:r,defaultProp:i??!1,onChange:a,caller:CE}),[T,E]=Is({prop:o,defaultProp:s,onChange:c,caller:CE}),ee=F.useRef(null),D=g?m||!!g.closest(`form`):!0,[O,k]=F.useState(new Set),te=Array.from(O).map(e=>e.props.value).join(`;`);return(0,I.jsx)(ls,{...h,children:(0,I.jsxs)(AE,{required:p,scope:t,trigger:g,onTriggerChange:_,valueNode:v,onValueNodeChange:y,valueNodeHasChildren:b,onValueNodeHasChildrenChange:x,contentId:fi(),value:T,onValueChange:E,open:C,onOpenChange:w,dir:S,triggerPointerDownPosRef:ee,disabled:f,children:[(0,I.jsx)(wE.Provider,{scope:t,children:(0,I.jsx)(ME,{scope:e.__scopeSelect,onNativeOptionAdd:F.useCallback(e=>{k(t=>new Set(t).add(e))},[]),onNativeOptionRemove:F.useCallback(e=>{k(t=>{let n=new Set(t);return n.delete(e),n})},[]),children:n})}),D?(0,I.jsxs)(kD,{"aria-hidden":!0,required:p,tabIndex:-1,name:u,autoComplete:d,value:T,onChange:e=>E(e.target.value),disabled:f,form:m,children:[T===void 0?(0,I.jsx)(`option`,{value:``}):null,Array.from(O)]},te):null]})})};PE.displayName=CE;var FE=`SelectTrigger`,IE=F.forwardRef((e,t)=>{let{__scopeSelect:n,disabled:r=!1,...i}=e,a=kE(n),o=jE(FE,n),s=o.disabled||r,c=yt(t,o.onTriggerChange),l=TE(n),u=F.useRef(`touch`),[d,f,p]=jD(e=>{let t=l().filter(e=>!e.disabled),n=MD(t,e,t.find(e=>e.value===o.value));n!==void 0&&o.onValueChange(n.value)}),m=e=>{s||(o.onOpenChange(!0),p()),e&&(o.triggerPointerDownPosRef.current={x:Math.round(e.pageX),y:Math.round(e.pageY)})};return(0,I.jsx)(us,{asChild:!0,...a,children:(0,I.jsx)(nT.button,{type:`button`,role:`combobox`,"aria-controls":o.contentId,"aria-expanded":o.open,"aria-required":o.required,"aria-autocomplete":`none`,dir:o.dir,"data-state":o.open?`open`:`closed`,disabled:s,"data-disabled":s?``:void 0,"data-placeholder":AD(o.value)?``:void 0,...i,ref:c,onClick:Lr(i.onClick,e=>{e.currentTarget.focus(),u.current!==`mouse`&&m(e)}),onPointerDown:Lr(i.onPointerDown,e=>{u.current=e.pointerType;let t=e.target;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),e.button===0&&e.ctrlKey===!1&&e.pointerType===`mouse`&&(m(e),e.preventDefault())}),onKeyDown:Lr(i.onKeyDown,e=>{let t=d.current!==``;!(e.ctrlKey||e.altKey||e.metaKey)&&e.key.length===1&&f(e.key),!(t&&e.key===` `)&&xE.includes(e.key)&&(m(),e.preventDefault())})})})});IE.displayName=FE;var LE=`SelectValue`,RE=F.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,children:a,placeholder:o=``,...s}=e,c=jE(LE,n),{onValueNodeHasChildrenChange:l}=c,u=a!==void 0,d=yt(t,c.onValueNodeChange);return li(()=>{l(u)},[l,u]),(0,I.jsx)(nT.span,{...s,ref:d,style:{pointerEvents:`none`},children:AD(c.value)?(0,I.jsx)(I.Fragment,{children:o}):a})});RE.displayName=LE;var zE=`SelectIcon`,BE=F.forwardRef((e,t)=>{let{__scopeSelect:n,children:r,...i}=e;return(0,I.jsx)(nT.span,{"aria-hidden":!0,...i,ref:t,children:r||`▼`})});BE.displayName=zE;var VE=`SelectPortal`,HE=e=>(0,I.jsx)(xs,{asChild:!0,...e});HE.displayName=VE;var UE=`SelectContent`,WE=F.forwardRef((e,t)=>{let n=jE(UE,e.__scopeSelect),[r,i]=F.useState();if(li(()=>{i(new DocumentFragment)},[]),!n.open){let t=r;return t?Ar.createPortal((0,I.jsx)(KE,{scope:e.__scopeSelect,children:(0,I.jsx)(wE.Slot,{scope:e.__scopeSelect,children:(0,I.jsx)(`div`,{children:e.children})})}),t):null}return(0,I.jsx)(XE,{...e,ref:t})});WE.displayName=UE;var GE=10,[KE,qE]=DE(UE),JE=`SelectContentImpl`,YE=Xw(`SelectContent.RemoveScroll`),XE=F.forwardRef((e,t)=>{let{__scopeSelect:n,position:r=`item-aligned`,onCloseAutoFocus:i,onEscapeKeyDown:a,onPointerDownOutside:o,side:s,sideOffset:c,align:l,alignOffset:u,arrowPadding:d,collisionBoundary:f,collisionPadding:p,sticky:m,hideWhenDetached:h,avoidCollisions:g,..._}=e,v=jE(UE,n),[y,b]=F.useState(null),[x,S]=F.useState(null),C=yt(t,e=>b(e)),[w,T]=F.useState(null),[E,ee]=F.useState(null),D=TE(n),[O,k]=F.useState(!1),te=F.useRef(!1);F.useEffect(()=>{if(y)return dT(y)},[y]),Tw();let A=F.useCallback(e=>{let[t,...n]=D().map(e=>e.ref.current),[r]=n.slice(-1),i=document.activeElement;for(let n of e)if(n===i||(n?.scrollIntoView({block:`nearest`}),n===t&&x&&(x.scrollTop=0),n===r&&x&&(x.scrollTop=x.scrollHeight),n?.focus(),document.activeElement!==i))return},[D,x]),j=F.useCallback(()=>A([w,y]),[A,w,y]);F.useEffect(()=>{O&&j()},[O,j]);let{onOpenChange:ne,triggerPointerDownPosRef:re}=v;F.useEffect(()=>{if(y){let e={x:0,y:0},t=t=>{e={x:Math.abs(Math.round(t.pageX)-(re.current?.x??0)),y:Math.abs(Math.round(t.pageY)-(re.current?.y??0))}},n=n=>{e.x<=10&&e.y<=10?n.preventDefault():y.contains(n.target)||ne(!1),document.removeEventListener(`pointermove`,t),re.current=null};return re.current!==null&&(document.addEventListener(`pointermove`,t),document.addEventListener(`pointerup`,n,{capture:!0,once:!0})),()=>{document.removeEventListener(`pointermove`,t),document.removeEventListener(`pointerup`,n,{capture:!0})}}},[y,ne,re]),F.useEffect(()=>{let e=()=>ne(!1);return window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e)}},[ne]);let[M,N]=jD(e=>{let t=D().filter(e=>!e.disabled),n=MD(t,e,t.find(e=>e.ref.current===document.activeElement));n&&setTimeout(()=>n.ref.current.focus())}),ie=F.useCallback((e,t,n)=>{let r=!te.current&&!n;(v.value!==void 0&&v.value===t||r)&&(T(e),r&&(te.current=!0))},[v.value]),ae=F.useCallback(()=>y?.focus(),[y]),oe=F.useCallback((e,t,n)=>{let r=!te.current&&!n;(v.value!==void 0&&v.value===t||r)&&ee(e)},[v.value]),P=r===`popper`?eD:QE,se=P===eD?{side:s,sideOffset:c,align:l,alignOffset:u,arrowPadding:d,collisionBoundary:f,collisionPadding:p,sticky:m,hideWhenDetached:h,avoidCollisions:g}:{};return(0,I.jsx)(KE,{scope:n,content:y,viewport:x,onViewportChange:S,itemRefCallback:ie,selectedItem:w,onItemLeave:ae,itemTextRefCallback:oe,focusSelectedItem:j,selectedItemText:E,position:r,isPositioned:O,searchRef:M,children:(0,I.jsx)(bE,{as:YE,allowPinchZoom:!0,children:(0,I.jsx)(Rw,{asChild:!0,trapped:v.open,onMountAutoFocus:e=>{e.preventDefault()},onUnmountAutoFocus:Lr(i,e=>{v.trigger?.focus({preventScroll:!0}),e.preventDefault()}),children:(0,I.jsx)(ni,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:a,onPointerDownOutside:o,onFocusOutside:e=>e.preventDefault(),onDismiss:()=>v.onOpenChange(!1),children:(0,I.jsx)(P,{role:`listbox`,id:v.contentId,"data-state":v.open?`open`:`closed`,dir:v.dir,onContextMenu:e=>e.preventDefault(),..._,...se,onPlaced:()=>k(!0),ref:C,style:{display:`flex`,flexDirection:`column`,outline:`none`,..._.style},onKeyDown:Lr(_.onKeyDown,e=>{let t=e.ctrlKey||e.altKey||e.metaKey;if(e.key===`Tab`&&e.preventDefault(),!t&&e.key.length===1&&N(e.key),[`ArrowUp`,`ArrowDown`,`Home`,`End`].includes(e.key)){let t=D().filter(e=>!e.disabled).map(e=>e.ref.current);if([`ArrowUp`,`End`].includes(e.key)&&(t=t.slice().reverse()),[`ArrowUp`,`ArrowDown`].includes(e.key)){let n=e.target,r=t.indexOf(n);t=t.slice(r+1)}setTimeout(()=>A(t)),e.preventDefault()}})})})})})})});XE.displayName=JE;var ZE=`SelectItemAlignedPosition`,QE=F.forwardRef((e,t)=>{let{__scopeSelect:n,onPlaced:r,...i}=e,a=jE(UE,n),o=qE(UE,n),[s,c]=F.useState(null),[l,u]=F.useState(null),d=yt(t,e=>u(e)),f=TE(n),p=F.useRef(!1),m=F.useRef(!0),{viewport:h,selectedItem:g,selectedItemText:_,focusSelectedItem:v}=o,y=F.useCallback(()=>{if(a.trigger&&a.valueNode&&s&&l&&h&&g&&_){let e=a.trigger.getBoundingClientRect(),t=l.getBoundingClientRect(),n=a.valueNode.getBoundingClientRect(),i=_.getBoundingClientRect();if(a.dir!==`rtl`){let r=i.left-t.left,a=n.left-r,o=e.left-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-GE,d=uw(a,[GE,Math.max(GE,u-l)]);s.style.minWidth=c+`px`,s.style.left=d+`px`}else{let r=t.right-i.right,a=window.innerWidth-n.right-r,o=window.innerWidth-e.right-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-GE,d=uw(a,[GE,Math.max(GE,u-l)]);s.style.minWidth=c+`px`,s.style.right=d+`px`}let o=f(),c=window.innerHeight-GE*2,u=h.scrollHeight,d=window.getComputedStyle(l),m=parseInt(d.borderTopWidth,10),v=parseInt(d.paddingTop,10),y=parseInt(d.borderBottomWidth,10),b=parseInt(d.paddingBottom,10),x=m+v+u+b+y,S=Math.min(g.offsetHeight*5,x),C=window.getComputedStyle(h),w=parseInt(C.paddingTop,10),T=parseInt(C.paddingBottom,10),E=e.top+e.height/2-GE,ee=c-E,D=g.offsetHeight/2,O=g.offsetTop+D,k=m+v+O,te=x-k;if(k<=E){let e=o.length>0&&g===o[o.length-1].ref.current;s.style.bottom=`0px`;let t=l.clientHeight-h.offsetTop-h.offsetHeight,n=k+Math.max(ee,D+(e?T:0)+t+y);s.style.height=n+`px`}else{let e=o.length>0&&g===o[0].ref.current;s.style.top=`0px`;let t=Math.max(E,m+h.offsetTop+(e?w:0)+D)+te;s.style.height=t+`px`,h.scrollTop=k-E+h.offsetTop}s.style.margin=`${GE}px 0`,s.style.minHeight=S+`px`,s.style.maxHeight=c+`px`,r?.(),requestAnimationFrame(()=>p.current=!0)}},[f,a.trigger,a.valueNode,s,l,h,g,_,a.dir,r]);li(()=>y(),[y]);let[b,x]=F.useState();return li(()=>{l&&x(window.getComputedStyle(l).zIndex)},[l]),(0,I.jsx)(tD,{scope:n,contentWrapper:s,shouldExpandOnScrollRef:p,onScrollButtonChange:F.useCallback(e=>{e&&m.current===!0&&(y(),v?.(),m.current=!1)},[y,v]),children:(0,I.jsx)(`div`,{ref:c,style:{display:`flex`,flexDirection:`column`,position:`fixed`,zIndex:b},children:(0,I.jsx)(nT.div,{...i,ref:d,style:{boxSizing:`border-box`,maxHeight:`100%`,...i.style}})})})});QE.displayName=ZE;var $E=`SelectPopperPosition`,eD=F.forwardRef((e,t)=>{let{__scopeSelect:n,align:r=`start`,collisionPadding:i=GE,...a}=e,o=kE(n);return(0,I.jsx)(ds,{...o,...a,ref:t,align:r,collisionPadding:i,style:{boxSizing:`border-box`,...a.style,"--radix-select-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-select-content-available-width":`var(--radix-popper-available-width)`,"--radix-select-content-available-height":`var(--radix-popper-available-height)`,"--radix-select-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-select-trigger-height":`var(--radix-popper-anchor-height)`}})});eD.displayName=$E;var[tD,nD]=DE(UE,{}),rD=`SelectViewport`,iD=F.forwardRef((e,t)=>{let{__scopeSelect:n,nonce:r,...i}=e,a=qE(rD,n),o=nD(rD,n),s=yt(t,a.onViewportChange),c=F.useRef(0);return(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(`style`,{dangerouslySetInnerHTML:{__html:`[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`},nonce:r}),(0,I.jsx)(wE.Slot,{scope:n,children:(0,I.jsx)(nT.div,{"data-radix-select-viewport":``,role:`presentation`,...i,ref:s,style:{position:`relative`,flex:1,overflow:`hidden auto`,...i.style},onScroll:Lr(i.onScroll,e=>{let t=e.currentTarget,{contentWrapper:n,shouldExpandOnScrollRef:r}=o;if(r?.current&&n){let e=Math.abs(c.current-t.scrollTop);if(e>0){let r=window.innerHeight-GE*2,i=parseFloat(n.style.minHeight),a=parseFloat(n.style.height),o=Math.max(i,a);if(o0?s:0,n.style.justifyContent=`flex-end`)}}}c.current=t.scrollTop})})})]})});iD.displayName=rD;var aD=`SelectGroup`,[oD,sD]=DE(aD),cD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=fi();return(0,I.jsx)(oD,{scope:n,id:i,children:(0,I.jsx)(nT.div,{role:`group`,"aria-labelledby":i,...r,ref:t})})});cD.displayName=aD;var lD=`SelectLabel`,uD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=sD(lD,n);return(0,I.jsx)(nT.div,{id:i.id,...r,ref:t})});uD.displayName=lD;var dD=`SelectItem`,[fD,pD]=DE(dD),mD=F.forwardRef((e,t)=>{let{__scopeSelect:n,value:r,disabled:i=!1,textValue:a,...o}=e,s=jE(dD,n),c=qE(dD,n),l=s.value===r,[u,d]=F.useState(a??``),[f,p]=F.useState(!1),m=yt(t,e=>c.itemRefCallback?.(e,r,i)),h=fi(),g=F.useRef(`touch`),_=()=>{i||(s.onValueChange(r),s.onOpenChange(!1))};if(r===``)throw Error(`A must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.`);return(0,I.jsx)(fD,{scope:n,value:r,disabled:i,textId:h,isSelected:l,onItemTextChange:F.useCallback(e=>{d(t=>t||(e?.textContent??``).trim())},[]),children:(0,I.jsx)(wE.ItemSlot,{scope:n,value:r,disabled:i,textValue:u,children:(0,I.jsx)(nT.div,{role:`option`,"aria-labelledby":h,"data-highlighted":f?``:void 0,"aria-selected":l&&f,"data-state":l?`checked`:`unchecked`,"aria-disabled":i||void 0,"data-disabled":i?``:void 0,tabIndex:i?void 0:-1,...o,ref:m,onFocus:Lr(o.onFocus,()=>p(!0)),onBlur:Lr(o.onBlur,()=>p(!1)),onClick:Lr(o.onClick,()=>{g.current!==`mouse`&&_()}),onPointerUp:Lr(o.onPointerUp,()=>{g.current===`mouse`&&_()}),onPointerDown:Lr(o.onPointerDown,e=>{g.current=e.pointerType}),onPointerMove:Lr(o.onPointerMove,e=>{g.current=e.pointerType,i?c.onItemLeave?.():g.current===`mouse`&&e.currentTarget.focus({preventScroll:!0})}),onPointerLeave:Lr(o.onPointerLeave,e=>{e.currentTarget===document.activeElement&&c.onItemLeave?.()}),onKeyDown:Lr(o.onKeyDown,e=>{c.searchRef?.current!==``&&e.key===` `||(SE.includes(e.key)&&_(),e.key===` `&&e.preventDefault())})})})})});mD.displayName=dD;var hD=`SelectItemText`,gD=F.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,...a}=e,o=jE(hD,n),s=qE(hD,n),c=pD(hD,n),l=NE(hD,n),[u,d]=F.useState(null),f=yt(t,e=>d(e),c.onItemTextChange,e=>s.itemTextRefCallback?.(e,c.value,c.disabled)),p=u?.textContent,m=F.useMemo(()=>(0,I.jsx)(`option`,{value:c.value,disabled:c.disabled,children:p},c.value),[c.disabled,c.value,p]),{onNativeOptionAdd:h,onNativeOptionRemove:g}=l;return li(()=>(h(m),()=>g(m)),[h,g,m]),(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(nT.span,{id:c.textId,...a,ref:f}),c.isSelected&&o.valueNode&&!o.valueNodeHasChildren?Ar.createPortal(a.children,o.valueNode):null]})});gD.displayName=hD;var _D=`SelectItemIndicator`,vD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return pD(_D,n).isSelected?(0,I.jsx)(nT.span,{"aria-hidden":!0,...r,ref:t}):null});vD.displayName=_D;var yD=`SelectScrollUpButton`,bD=F.forwardRef((e,t)=>{let n=qE(yD,e.__scopeSelect),r=nD(yD,e.__scopeSelect),[i,a]=F.useState(!1),o=yt(t,r.onScrollButtonChange);return li(()=>{if(n.viewport&&n.isPositioned){let e=function(){a(t.scrollTop>0)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,I.jsx)(CD,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop-=t.offsetHeight)}}):null});bD.displayName=yD;var xD=`SelectScrollDownButton`,SD=F.forwardRef((e,t)=>{let n=qE(xD,e.__scopeSelect),r=nD(xD,e.__scopeSelect),[i,a]=F.useState(!1),o=yt(t,r.onScrollButtonChange);return li(()=>{if(n.viewport&&n.isPositioned){let e=function(){let e=t.scrollHeight-t.clientHeight;a(Math.ceil(t.scrollTop)t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,I.jsx)(CD,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop+=t.offsetHeight)}}):null});SD.displayName=xD;var CD=F.forwardRef((e,t)=>{let{__scopeSelect:n,onAutoScroll:r,...i}=e,a=qE(`SelectScrollButton`,n),o=F.useRef(null),s=TE(n),c=F.useCallback(()=>{o.current!==null&&(window.clearInterval(o.current),o.current=null)},[]);return F.useEffect(()=>()=>c(),[c]),li(()=>{s().find(e=>e.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:`nearest`})},[s]),(0,I.jsx)(nT.div,{"aria-hidden":!0,...i,ref:t,style:{flexShrink:0,...i.style},onPointerDown:Lr(i.onPointerDown,()=>{o.current===null&&(o.current=window.setInterval(r,50))}),onPointerMove:Lr(i.onPointerMove,()=>{a.onItemLeave?.(),o.current===null&&(o.current=window.setInterval(r,50))}),onPointerLeave:Lr(i.onPointerLeave,()=>{c()})})}),wD=`SelectSeparator`,TD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return(0,I.jsx)(nT.div,{"aria-hidden":!0,...r,ref:t})});TD.displayName=wD;var ED=`SelectArrow`,DD=F.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=kE(n),a=jE(ED,n),o=qE(ED,n);return a.open&&o.position===`popper`?(0,I.jsx)(fs,{...i,...r,ref:t}):null});DD.displayName=ED;var OD=`SelectBubbleInput`,kD=F.forwardRef(({__scopeSelect:e,value:t,...n},r)=>{let i=F.useRef(null),a=yt(r,i),o=AC(t);return F.useEffect(()=>{let e=i.current;if(!e)return;let n=window.HTMLSelectElement.prototype,r=Object.getOwnPropertyDescriptor(n,`value`).set;if(o!==t&&r){let n=new Event(`change`,{bubbles:!0});r.call(e,t),e.dispatchEvent(n)}},[o,t]),(0,I.jsx)(nT.select,{...n,style:{...Ks,...n.style},ref:a,defaultValue:t})});kD.displayName=OD;function AD(e){return e===``||e===void 0}function jD(e){let t=Jr(e),n=F.useRef(``),r=F.useRef(0),i=F.useCallback(e=>{let i=n.current+e;t(i),(function e(t){n.current=t,window.clearTimeout(r.current),t!==``&&(r.current=window.setTimeout(()=>e(``),1e3))})(i)},[t]),a=F.useCallback(()=>{n.current=``,window.clearTimeout(r.current)},[]);return F.useEffect(()=>()=>window.clearTimeout(r.current),[]),[n,i,a]}function MD(e,t,n){let r=t.length>1&&Array.from(t).every(e=>e===t[0])?t[0]:t,i=n?e.indexOf(n):-1,a=ND(e,Math.max(i,0));r.length===1&&(a=a.filter(e=>e!==n));let o=a.find(e=>e.textValue.toLowerCase().startsWith(r.toLowerCase()));return o===n?void 0:o}function ND(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var PD=PE,FD=IE,ID=RE,LD=BE,RD=HE,zD=WE,BD=iD,VD=uD,HD=mD,UD=gD,WD=vD,GD=bD,KD=SD,qD=TD,JD=PD,YD=ID,XD=F.forwardRef(({className:e,children:t,...n},r)=>(0,I.jsxs)(FD,{ref:r,className:or(`flex h-10 w-full items-center justify-between rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground ring-offset-background placeholder:text-text-tertiary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1`,e),...n,children:[t,(0,I.jsx)(LD,{asChild:!0,children:(0,I.jsx)(gr,{className:`h-3.5 w-3.5 text-text-tertiary`})})]}));XD.displayName=FD.displayName;var ZD=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(GD,{ref:n,className:or(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(_r,{className:`h-3.5 w-3.5 text-text-tertiary`})}));ZD.displayName=GD.displayName;var QD=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(KD,{ref:n,className:or(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(gr,{className:`h-3.5 w-3.5 text-text-tertiary`})}));QD.displayName=KD.displayName;var $D=F.forwardRef(({className:e,children:t,position:n=`popper`,...r},i)=>(0,I.jsx)(RD,{children:(0,I.jsxs)(zD,{ref:i,className:or(`relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-[10px] border border-border bg-popover py-1.5 text-popover-foreground shadow-lg shadow-primary/5 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2`,n===`popper`&&`data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1`,e),position:n,...r,children:[(0,I.jsx)(ZD,{}),(0,I.jsx)(BD,{className:or(`p-0`,n===`popper`&&`h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]`),children:t}),(0,I.jsx)(QD,{})]})}));$D.displayName=zD.displayName;var eO=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(VD,{ref:n,className:or(`px-3.5 py-2 text-[13px] font-medium text-muted-foreground`,e),...t}));eO.displayName=VD.displayName;var tO=F.forwardRef(({className:e,children:t,...n},r)=>(0,I.jsxs)(HD,{ref:r,className:or(`relative flex w-full cursor-pointer select-none items-center py-2 pl-3.5 pr-8 text-[13px] outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50`,e),...n,children:[(0,I.jsx)(`span`,{className:`absolute right-3 flex h-3.5 w-3.5 items-center justify-center`,children:(0,I.jsx)(WD,{children:(0,I.jsx)(hr,{className:`h-3.5 w-3.5 text-primary`})})}),(0,I.jsx)(UD,{children:t})]}));tO.displayName=HD.displayName;var nO=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(qD,{ref:n,className:or(`-mx-1 my-1 h-px bg-border`,e),...t}));nO.displayName=qD.displayName;function rO(e){let t=(e??`read write`).split(/\s+/).map(e=>e.trim()).filter(Boolean),n=new Set(TC);return new Set(t.filter(e=>n.has(e)))}function iO(e){let t=e.allowed_services_csv,n=e.allowed_nodes_csv,r=new Set((t??``).split(`,`).map(e=>e.trim()).filter(Boolean)),i=new Set((n??``).split(`,`).map(e=>e.trim()).filter(Boolean));return{allowAllServices:!t,allowAllNodes:!n,selectedServiceIds:r,selectedNodeIds:i}}function aO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(e.name??``),[a,o]=(0,F.useState)(e.platform??``),[s,c]=(0,F.useState)(!1),[l,u]=(0,F.useState)(()=>rO(e.scopes)),[d,f]=(0,F.useState)(()=>iO(e)),[p,m]=(0,F.useState)(e.org_id??``),h=lw(),[g,_]=(0,F.useState)(!1),[v,y]=(0,F.useState)(null);async function b(){_(!0),y(null);try{let i={name:r,scopes:Array.from(l).join(` `),allow_all_services:d.allowAllServices,allow_all_nodes:d.allowAllNodes};if(a&&(i.platform=a),e.callback_url&&(i.callback_url=e.callback_url),p&&(i.target_org_id=p),d.allowAllServices||(i.allowed_service_ids=Array.from(d.selectedServiceIds)),d.allowAllNodes||(i.allowed_node_ids=Array.from(d.selectedNodeIds)),e.expires_in_days!=null&&e.expires_in_days>0){let t=new Date;t.setDate(t.getDate()+e.expires_in_days),i.expires_at=t.toISOString()}await d_(t);let o=await p_(t,()=>u_.post(`/api-keys`,i));n({kind:`api-key-create`,api_key_id:o.id,full_key:o.full_key})}catch(e){y(fO(e))}finally{_(!1)}}let x=g||!s||l.size===0;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Create an API key`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Review the details your CLI sent and confirm to mint the key.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(wC,{id:`pair-api-key-name`,label:`Name`,schema:xC,value:r,onChange:i,onValidityChange:c,placeholder:`e.g. coding-agent`,hint:"A short label so you can find this key in `nyxid api-key list`.",autoFocus:!0}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-api-key-platform`,children:`Platform`}),(0,I.jsx)(Pc,{delayDuration:150,children:(0,I.jsxs)(Fc,{children:[(0,I.jsx)(Ic,{asChild:!0,children:(0,I.jsx)(`button`,{type:`button`,"aria-label":`About platform tags`,className:`text-muted-foreground transition-colors hover:text-foreground`,children:(0,I.jsx)(Sr,{className:`h-3.5 w-3.5`})})}),(0,I.jsx)(Lc,{side:`right`,align:`start`,sideOffset:8,className:`max-w-[340px] whitespace-normal px-5 py-4 text-[13px] leading-[1.55]`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`p`,{children:[(0,I.jsx)(`span`,{className:`font-medium text-foreground`,children:`Platform`}),` `,`tags the key with the AI agent that will use it.`]}),(0,I.jsx)(`p`,{className:`text-muted-foreground`,children:`It controls three things: audit attribution (logs show which agent made each proxy request), per- agent rate-limit buckets, and dashboard filtering on the API Keys page.`}),(0,I.jsxs)(`p`,{className:`text-muted-foreground`,children:[`Values are a fixed allowlist —`,` `,(0,I.jsx)(`code`,{children:`claude-code`}),`, `,(0,I.jsx)(`code`,{children:`cursor`}),`,`,` `,(0,I.jsx)(`code`,{children:`codex`}),`, `,(0,I.jsx)(`code`,{children:`openclaw`}),`,`,` `,(0,I.jsx)(`code`,{children:`generic`}),`. Custom strings are rejected by the backend.`]}),(0,I.jsxs)(`p`,{className:`text-muted-foreground`,children:[`Leave as `,(0,I.jsx)(`code`,{children:`— none —`}),` if you don't want the tag.`]})]})})]})})]}),(0,I.jsxs)(JD,{value:a===``?`__none__`:a,onValueChange:e=>{o(e===`__none__`?``:e)},children:[(0,I.jsx)(XD,{id:`pair-api-key-platform`,children:(0,I.jsx)(YD,{placeholder:`— none —`})}),(0,I.jsxs)($D,{children:[(0,I.jsx)(tO,{value:`__none__`,children:`— none —`}),SC.map(e=>(0,I.jsx)(tO,{value:e,children:e},e))]})]}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Tags the key for audit attribution + per-agent rate limits.`})]}),(h.data?.length??0)>0?(0,I.jsxs)(uO,{label:`Owner`,htmlFor:`pair-api-key-owner`,children:[(0,I.jsxs)(`select`,{id:`pair-api-key-owner`,value:p,onChange:e=>{m(e.target.value)},className:`flex h-10 w-full rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,children:[(0,I.jsx)(`option`,{value:``,children:`Personal (your account)`}),h.data?.map(e=>(0,I.jsxs)(`option`,{value:e.id,children:[`Org · `,e.display_name??e.id]},e.id))]}),(0,I.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Org-owned keys authenticate as the org; every admin of the selected org can rotate or delete them.`})]}):null,(0,I.jsx)(EC,{value:l,onChange:u}),(0,I.jsx)(rw,{value:d,onChange:f})]}),v?(0,I.jsx)(dO,{message:v}):null,(0,I.jsx)(Dr,{onClick:()=>void b(),disabled:x,children:g?`Creating...`:`Create key`})]})}function oO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(!1),[a,o]=(0,F.useState)(null);async function s(){i(!0),o(null);try{await d_(t);let r=await p_(t,()=>u_.post(`/api-keys/${encodeURIComponent(e.resource_id)}/rotate`));n({kind:`api-key-rotate`,resource_id:r.id,full_key:r.full_key})}catch(e){o(fO(e))}finally{i(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Rotate API key`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Rotating `,(0,I.jsx)(`strong`,{children:e.display_name}),` will issue a new key and immediately revoke the previous one.`]})]}),a?(0,I.jsx)(dO,{message:a}):null,(0,I.jsx)(Dr,{onClick:()=>void s(),disabled:r,children:r?`Rotating...`:`Rotate key`})]})}var sO=`my-node`;function cO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(e.name??``),[a,o]=(0,F.useState)(!0),[s,c]=(0,F.useState)(!1),[l,u]=(0,F.useState)(null);async function d(){c(!0),u(null);try{let e=r.trim(),i=e.length>0?e:sO;await d_(t);let a=await p_(t,()=>u_.post(`/nodes/register-token`,{name:i}));n({kind:`node-register-token`,token_id:a.token_id,token:a.token})}catch(e){u(fO(e))}finally{c(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Generate node registration token`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Use this token with `,(0,I.jsx)(`code`,{children:`nyxid node register`}),` to connect a new node.`]})]}),(0,I.jsx)(wC,{id:`pair-node-name`,label:`Node name (optional)`,schema:bC,value:r,onChange:i,onValidityChange:o,placeholder:sO,hint:`Lowercase letters, digits, hyphens only (max 64). Leave blank for \`${sO}\`.`,optional:!0,autoFocus:!0}),l?(0,I.jsx)(dO,{message:l}):null,(0,I.jsx)(Dr,{onClick:()=>void d(),disabled:s||!a,children:s?`Generating...`:`Generate token`})]})}function lO({prefill:e,pairingId:t,onSuccess:n}){let[r,i]=(0,F.useState)(!1),[a,o]=(0,F.useState)(null);async function s(){i(!0),o(null);try{await d_(t);let r=await p_(t,()=>u_.post(`/nodes/${encodeURIComponent(e.resource_id)}/rotate-token`));n({kind:`node-rotate-token`,resource_id:e.resource_id,auth_token:r.auth_token,signing_secret:r.signing_secret})}catch(e){o(fO(e))}finally{i(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Rotate node token`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Rotating `,(0,I.jsx)(`strong`,{children:e.display_name}),` issues a new auth token + signing secret and revokes the previous pair.`]})]}),a?(0,I.jsx)(dO,{message:a}):null,(0,I.jsx)(Dr,{onClick:()=>void s(),disabled:r,children:r?`Rotating...`:`Rotate token`})]})}function uO({label:e,htmlFor:t,children:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:t,children:e}),n]})}function dO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}function fO(e){return e instanceof Error?e.message:`Something went wrong. Please try again.`}function pO({className:e,...t}){return(0,I.jsx)(`div`,{className:or(`animate-pulse rounded-md bg-muted`,e),...t})}function mO(e){let t=(e??`system`).toLowerCase();return t===`user`||t===`both`}async function hO(e,t,n,r,i){let a={service_slug:e,label:t};r&&(a.node_id=r);let o=i?.trim();o&&(a.endpoint_url=o);try{return await u_.post(`/keys`,a)}catch(e){throw e instanceof i_&&e.status>=400&&e.status<500&&(n.current=!1),e}}function gO(e){if(!(typeof window>`u`))try{fetch(`/api/v1/keys/${encodeURIComponent(e)}?only_if_pending=true`,{method:`DELETE`,credentials:`include`,keepalive:!0})}catch{}}function _O(e){if(!(typeof window>`u`))try{fetch(`/api/v1/cli-pairings/${encodeURIComponent(e)}/cancel`,{method:`POST`,credentials:`include`,keepalive:!0,headers:{"Content-Type":`application/json`},body:`{}`})}catch{}}function vO(e,t,n,r){if(!(typeof window>`u`))try{fetch(`/api/v1/cli-pairings/${encodeURIComponent(e)}/complete`,{method:`POST`,credentials:`include`,keepalive:!0,headers:{"Content-Type":`application/json`},body:JSON.stringify({ack:{acknowledged:!0,service_id:t,slug:n,label:r}})})}catch{}}async function yO(e){if(!e)return{kind:`unknown`};try{if((await u_.delete(`/keys/${encodeURIComponent(e)}?only_if_pending=true`)).deleted===!0)return{kind:`deleted`};try{let t=await u_.get(`/keys/${encodeURIComponent(e)}`);return t.status===`active`?{kind:`active`,key:t}:{kind:`unknown`}}catch{return{kind:`unknown`}}}catch{return{kind:`unknown`}}}async function bO(e,t,n,r,i){let a=i.current;if(a)try{await a}catch{}let o=t.current,s=n.current,c=r.current;t.current=null,n.current=!1;let l=s&&!c;if(o)try{let t=await u_.delete(`/keys/${encodeURIComponent(o)}?only_if_pending=true`);if(t.deleted===!0&&s)l=!0;else if(t.deleted===!1){try{let t=await u_.get(`/keys/${encodeURIComponent(o)}`);await u_.post(`/cli-pairings/${encodeURIComponent(e)}/complete`,{ack:{acknowledged:!0,service_id:t.id,slug:t.slug,label:t.label}})}catch{}return}else l=!1}catch{}if(l)try{await f_(e)}catch{}}function xO({providerId:e,slug:t,label:n,nodeId:r,endpointUrl:i,pairingId:a,credentialMode:o,documentationUrl:s,onSuccess:c,onCancel:l}){let[u,d]=(0,F.useState)(mO(o)?`checking-credentials`:`starting`),[f,p]=(0,F.useState)(null),[m,h]=(0,F.useState)(null),[g,_]=(0,F.useState)(``),[v,y]=(0,F.useState)(``),b=(0,F.useRef)(null),x=(0,F.useRef)(!1),S=(0,F.useRef)(!1),C=(0,F.useRef)(!1),w=(0,F.useRef)(null),T=(0,F.useRef)(!1);(0,F.useEffect)(()=>{function e(){if(T.current)return;let e=b.current;if(e){gO(e),vO(a,e,t,n);return}C.current&&_O(a)}return window.addEventListener(`beforeunload`,e),()=>{window.removeEventListener(`beforeunload`,e),!T.current&&bO(a,b,S,C,w)}},[a,t,n]);async function E(){let e=w.current;if(e)try{await e}catch{}let t=b.current;b.current=null;let n=await yO(t);if(n.kind===`active`)return S.current=!1,T.current=!0,d(`done`),c({kind:`ai-key`,service_id:n.key.id,slug:n.key.slug,label:n.key.label}),`active`;let r=!C.current,i=n.kind===`deleted`;return S.current&&(i||r)?(S.current=!1,await f_(a),`released`):(S.current=!1,`uncertain`)}async function ee(){x.current=!0,await E()!==`active`&&l()}(0,F.useEffect)(()=>{if(!mO(o))return;let t=!1;return(async()=>{try{let n=await u_.get(`/providers/${encodeURIComponent(e)}/credentials`);if(t)return;n.has_credentials?d(`starting`):d(`needs-credentials`)}catch(e){if(t)return;d(`error`),p(wO(e))}})(),()=>{t=!0}},[]);async function D(){if(!(!g.trim()||!v.trim())){d(`saving-credentials`),p(null);try{await u_.put(`/providers/${encodeURIComponent(e)}/credentials`,{client_id:g.trim(),client_secret:v.trim(),label:n}),d(`starting`)}catch(e){d(`needs-credentials`),p(wO(e))}}}(0,F.useEffect)(()=>{if(u!==`starting`)return;let o=!1;return x.current=!1,(async()=>{try{b.current||(await d_(a),S.current=!0);let s;if(b.current)s={id:b.current,status:`pending_auth`};else{C.current=!0;let e=hO(t,n,C,r,i);w.current=e;try{s=await e}finally{w.current===e&&(w.current=null)}b.current=s.id}if(o)return;if(s.status===`active`){await k(s.id);return}let c=await u_.get(`/providers/${encodeURIComponent(e)}/connect/oauth?redirect_path=${encodeURIComponent(`/keys/${s.id}`)}`);if(o)return;if(!c.authorization_url)throw Error(`provider did not return an authorization_url`);if(h(c.authorization_url),!window.open(c.authorization_url,`_blank`,`noopener,noreferrer`)){d(`waiting`),p(`Browser blocked the popup. Use the button below to open the provider sign-in.`),await O(s.id);return}d(`waiting`),await O(s.id)}catch(e){if(o)return;d(`error`),p(wO(e)),E()}})(),()=>{o=!0,x.current=!0}},[u]);async function O(e){let t=Date.now()+300*1e3;for(;Date.now(){_(e.target.value)},autoFocus:!0,autoComplete:`off`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-aikey-oauth-client-secret`,children:`Client Secret`}),(0,I.jsx)(m_,{id:`pair-aikey-oauth-client-secret`,type:`password`,value:v,onChange:e=>{y(e.target.value)},autoComplete:`off`})]})]}),f?(0,I.jsx)(CO,{message:f}):null,(0,I.jsx)(Dr,{onClick:()=>void D(),disabled:e||!g.trim()||!v.trim(),children:e?`Saving...`:`Save and continue`}),(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void ee(),disabled:e,children:`Cancel`})]})}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:`Complete sign-in on the provider`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`We opened a new tab where you'll authorize NyxID. When it completes, come back — this page will finish automatically.`})]}),u===`checking-credentials`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Checking provider credentials...`]}):u===`starting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Creating placeholder service...`]}):u===`waiting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Waiting for provider authorization...`]}):null,m&&u===`waiting`?(0,I.jsxs)(`a`,{href:m,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center justify-center gap-2 rounded-md border bg-muted/40 px-3 py-2 text-sm hover:bg-muted`,children:[`Reopen provider sign-in`,(0,I.jsx)(yr,{className:`h-4 w-4`})]}):null,f?(0,I.jsx)(CO,{message:f}):null,u===`done`?null:(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void ee(),children:`Cancel`})]})}function SO({providerId:e,slug:t,label:n,nodeId:r,endpointUrl:i,pairingId:a,onSuccess:o,onCancel:s}){let[c,l]=(0,F.useState)(null),[u,d]=(0,F.useState)(null),[f,p]=(0,F.useState)(`starting`),[m,h]=(0,F.useState)(null),[g,_]=(0,F.useState)(!1),v=(0,F.useRef)(0),y=(0,F.useRef)(null),b=(0,F.useRef)(!1),x=(0,F.useRef)(!1),S=(0,F.useRef)(!1),C=(0,F.useRef)(null),w=(0,F.useRef)(!1);async function T(){let e=C.current;if(e)try{await e}catch{}let t=y.current;y.current=null;let n=await yO(t);if(n.kind===`active`)return x.current=!1,w.current=!0,p(`done`),o({kind:`ai-key`,service_id:n.key.id,slug:n.key.slug,label:n.key.label}),`active`;let r=!S.current,i=n.kind===`deleted`;return x.current&&(i||r)?(x.current=!1,await f_(a),`released`):(x.current=!1,`uncertain`)}async function E(){b.current=!0,v.current+=1,await T()!==`active`&&s()}(0,F.useEffect)(()=>{function e(){if(w.current)return;let e=y.current;if(e){gO(e),vO(a,e,t,n);return}S.current&&_O(a)}return window.addEventListener(`beforeunload`,e),()=>{window.removeEventListener(`beforeunload`,e),!w.current&&bO(a,y,x,S,C)}},[a,t,n]),(0,F.useEffect)(()=>(b.current=!1,ee(),()=>{b.current=!0,v.current+=1}),[]);async function ee(){let s=++v.current;p(`starting`),h(null);try{let c=y.current;if(!c){await d_(a),x.current=!0,S.current=!0;let e=hO(t,n,S,r,i);C.current=e;let l;try{l=await e}finally{C.current===e&&(C.current=null)}if(c=l.id,y.current=c,s!==v.current)return;if(l.status===`active`){let e=await u_.get(`/keys/${encodeURIComponent(c)}`);if(s!==v.current)return;w.current=!0,p(`done`),o({kind:`ai-key`,service_id:e.id,slug:e.slug,label:e.label});return}}let u=await u_.post(`/providers/${encodeURIComponent(e)}/connect/device-code/initiate`,{});if(s!==v.current)return;l(u.user_code),d(u.verification_uri),p(`waiting`);let f=Number(u.interval)||5,m=`/providers/${encodeURIComponent(e)}/connect/device-code/poll`,g=Date.now()+600*1e3;for(;Date.now(){_(!1)},2e3)}catch{}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:`Authorize via device code`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Open the verification URL, enter the code, and complete sign-in on the provider. This page will finish automatically.`})]}),f===`starting`?(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-sm text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-4 w-4 animate-spin`}),`Requesting device code...`]}):f===`waiting`&&c&&u?(0,I.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-md border bg-muted/30 p-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`span`,{className:`text-xs uppercase tracking-wide text-muted-foreground`,children:`Code`}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(`code`,{className:`rounded bg-background px-3 py-1.5 font-mono text-lg`,children:c}),(0,I.jsxs)(Dr,{variant:`outline`,size:`sm`,onClick:()=>void D(),children:[(0,I.jsx)(vr,{className:`mr-1.5 h-3.5 w-3.5`}),g?`Copied`:`Copy`]})]})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`span`,{className:`text-xs uppercase tracking-wide text-muted-foreground`,children:`Visit`}),(0,I.jsxs)(`a`,{href:u,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1.5 text-sm underline-offset-2 hover:underline`,children:[u,(0,I.jsx)(yr,{className:`h-3.5 w-3.5`})]})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,I.jsx)(Cr,{className:`h-3 w-3 animate-spin`}),`Waiting for authorization...`]})]}):f===`expired`?(0,I.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,I.jsx)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:`The device code expired before authorization completed.`}),(0,I.jsx)(Dr,{onClick:()=>void ee(),children:`Request a new code`})]}):null,m?(0,I.jsx)(CO,{message:m}):null,f===`done`?null:(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void E(),children:`Cancel`})]})}function CO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}function wO(e){return e instanceof i_||e instanceof Error?e.message:`Something went wrong. Please try again.`}function TO(e){return new Promise(t=>{window.setTimeout(t,e)})}function EO(e){let t=(e.provider_type??``).toLowerCase();return(e.service_type??`http`)===`ssh`?`ssh`:t===`oauth2`?`oauth`:t===`device_code`?`device-code`:e.requires_credential===!1?`no-auth`:Array.isArray(e.token_exchange_credential_fields)&&e.token_exchange_credential_fields.length>0?`token-exchange`:e.requires_gateway_url?`gateway-url`:`paste-key`}function DO(e,t){switch(e){case`no-auth`:return`1-click connect`;case`gateway-url`:return`URL + API key`;case`token-exchange`:return`${(t.token_exchange_credential_fields??[]).length} fields`;case`oauth`:return`OAuth sign-in`;case`device-code`:return`device code`;case`ssh`:return`SSH cert`;case`paste-key`:return`paste API key`}}var OO={oauth:`OAuth`,"device-code":`Device code`,ssh:`SSH`};function kO(e,t){if(!t)return 0;let n=e.toLowerCase(),r=t.toLowerCase(),i=n.indexOf(r);if(i>=0)return i;let a=0,o=0,s=100,c=0;for(;a{let e=await u_.get(`/catalog?include_all=true`);return e.entries??e.services??[]}}),o=r??[],s=t.trim(),c=s?o.map(e=>{let t=kO(e.slug,s),n=kO(e.name??``,s),r=t===null?n:n===null?t:Math.min(t,n);return r===null?null:{entry:e,score:r}}).filter(e=>e!==null).sort((e,t)=>e.score-t.score).map(e=>e.entry):o;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(`label`,{htmlFor:`catalog-search`,className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:`Search`}),(0,I.jsx)(m_,{id:`catalog-search`,type:`search`,placeholder:`search services…`,autoComplete:`off`,spellCheck:!1,value:t,onChange:e=>{n(e.target.value)}})]}),(0,I.jsx)(jO,{children:`Simple setup`}),i?(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Loading catalog…`}):a?(0,I.jsx)(`p`,{className:`text-sm text-destructive`,children:a instanceof i_?`Couldn't load the catalog: ${a.message} (${String(a.status)})`:`Couldn't load the catalog. Check the CLI logs for details.`}):c.length===0?(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:s?`No services match your search.`:`Catalog is empty.`}):(0,I.jsx)(`div`,{className:`max-h-[420px] overflow-y-auto overscroll-contain pr-1`,role:`list`,children:(0,I.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:c.map(t=>(0,I.jsx)(MO,{entry:t,onClick:()=>{e(t.slug)}},t.slug))})}),(0,I.jsx)(jO,{children:`Advanced`}),(0,I.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:(0,I.jsx)(NO,{onClick:()=>{e(`__custom__`)}})})]})}function jO({children:e}){return(0,I.jsx)(`div`,{className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:e})}function MO({entry:e,onClick:t}){let n=EO(e),r=OO[n];return(0,I.jsxs)(`button`,{type:`button`,onClick:t,role:`listitem`,className:`group relative flex min-h-[132px] flex-col items-start gap-1 rounded-[10px] border border-border bg-card/60 p-4 text-left transition-colors hover:border-primary/60 hover:bg-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,children:[r?(0,I.jsx)(`span`,{className:`absolute right-3 top-3 rounded-full border border-border bg-muted/60 px-2 py-0.5 text-[10px] uppercase tracking-wide text-muted-foreground`,children:r}):null,(0,I.jsx)(`span`,{className:`font-display text-sm font-semibold text-foreground`,children:e.name||e.slug}),e.description?(0,I.jsx)(`span`,{className:`line-clamp-2 text-xs text-muted-foreground`,children:e.description}):null,(0,I.jsx)(`span`,{className:`mt-auto text-[11px] font-mono text-text-tertiary`,children:DO(n,e)})]})}function NO({onClick:e}){return(0,I.jsxs)(`button`,{type:`button`,onClick:e,className:`flex min-h-[132px] flex-col items-start gap-1 rounded-[10px] border border-dashed border-border bg-transparent p-4 text-left transition-colors hover:border-primary/60 hover:bg-card/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,children:[(0,I.jsx)(`span`,{className:`font-display text-sm font-semibold text-foreground`,children:`Custom / self-hosted…`}),(0,I.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`For anything that isn't in the catalog above — paste your own endpoint URL + credential.`})]})}function PO(e){let t=(e.provider_type??``).toLowerCase();return t===`oauth2`?`oauth`:t===`device_code`?`device-code`:e.requires_credential===!1?`no-auth`:Array.isArray(e.token_exchange_credential_fields)&&e.token_exchange_credential_fields.length>0?`token-exchange`:e.requires_credential?`api-key`:`other`}function FO({prefill:e,pairingId:t,onSuccess:n,onSlugPicked:r}){let[i,a]=(0,F.useState)(e.custom?`__custom__`:e.slug??``),o=i.trim(),s=(0,F.useRef)(o?null:``);(0,F.useEffect)(()=>{s.current!==o&&(s.current=o,r?.(o))},[o,r]);let{data:c,isLoading:l,error:u}=ut({queryKey:[`cli-pair`,`catalog`,o],queryFn:async()=>u_.get(`/catalog/${encodeURIComponent(o)}`),enabled:!!o&&o!==`__custom__`}),d=u?u instanceof i_?u.message:`Couldn't load catalog entry "${o}".`:null,f=!o&&!d,p=o===`__custom__`,m=f?`Add an AI service`:p?`Custom / self-hosted service`:`Connect service`,h=f?`Pick a service to connect. Simple-bearer APIs (OpenAI, Anthropic, Gemini) land in the guided form. Anything else — self-hosted, OAuth, device code, custom endpoint — goes to the power-user form.`:p?`For services not in the catalog — paste your own endpoint URL and credential.`:`Your CLI wants to add ${o||`a service`} to NyxID. Confirm the details here.`;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:m}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:h})]}),f?(0,I.jsx)(AO,{onSelect:a}):p?(0,I.jsx)(BO,{prefill:e,pairingId:t,onSuccess:n,onBack:()=>{a(``)}}):l?(0,I.jsx)(pO,{className:`h-24 w-full`}):d?(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsx)(UO,{message:d}),(0,I.jsx)(AO,{onSelect:a})]}):c?(0,I.jsx)(VO,{entry:c,prefill:e,pairingId:t,onSuccess:n}):null]})}function IO(e){switch(e){case`header`:return`X-API-Key`;case`query`:return`key`;case`path`:return`bot`;case`body`:return`app_secret`;default:return`Authorization`}}function LO(e){switch(e){case`bearer`:case`header`:case`query`:case`path`:case`basic`:case`body`:case`bot_bearer`:case`none`:return e;default:return`bearer`}}function RO(e){return e===`header`||e===`query`||e===`path`||e===`body`}function zO(){return(0,I.jsx)(`span`,{"aria-hidden":`true`,className:`text-destructive ml-0.5`,children:`*`})}function BO({prefill:e,pairingId:t,onSuccess:n,onBack:r}){let[i,a]=(0,F.useState)(e.label??``),[o,s]=(0,F.useState)(e.endpoint_url??``),[c,l]=(0,F.useState)(``),[u,d]=(0,F.useState)(LO(e.auth_method)),[f,p]=(0,F.useState)(e.auth_key_name??IO(LO(e.auth_method))),[m,h]=(0,F.useState)(e.custom_slug??``),[g,_]=(0,F.useState)(!1),[v,y]=(0,F.useState)(null),b=e.via_node?.trim()??``,x=i.trim(),S=o.trim(),C=c.trim(),w=u!==`none`,T=RO(u),E=g||!x||!S||w&&!C,ee=u===`bot_bearer`?`Bot token`:u===`basic`?`user:pass`:u===`body`?`${f.trim()||IO(u)} value`:`API key / credential`;async function D(){_(!0),y(null);try{let e={label:x,endpoint_url:S,auth_method:u};w&&(e.credential=C),T&&(e.auth_key_name=f.trim()||IO(u));let r=m.trim();r&&(e.slug=r),b&&(e.node_id=b),await d_(t);let i=await p_(t,()=>u_.post(`/keys`,e));n({kind:`ai-key`,service_id:i.id,slug:i.slug,label:i.label})}catch(e){y(e instanceof i_?e.message:e.message??`Failed.`)}finally{_(!1)}}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-label`,children:`Label`}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-label`,value:i,onChange:e=>{a(e.target.value)},placeholder:`e.g. My Self-hosted OpenAI Proxy`,autoFocus:!0,"aria-required":`true`}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Shown everywhere in the CLI and web UI.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-endpoint`,children:`Endpoint URL`}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-endpoint`,value:o,onChange:e=>{s(e.target.value)},placeholder:`https://api.example.com`,"aria-required":`true`}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The base URL NyxID proxies requests to.`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-auth-method`,children:`Auth method`}),(0,I.jsx)(zO,{})]}),(0,I.jsxs)(`select`,{id:`pair-custom-auth-method`,value:u,onChange:e=>{let t=e.target.value;d(t),(!f.trim()||[`Authorization`,`X-API-Key`,`key`,`bot`,`app_secret`].includes(f.trim()))&&p(IO(t))},className:`flex h-10 w-full rounded-[10px] border border-input bg-transparent px-[14px] py-2 text-[13px] text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,"aria-required":`true`,children:[(0,I.jsx)(`option`,{value:`bearer`,children:`bearer (Authorization: Bearer …)`}),(0,I.jsx)(`option`,{value:`bot_bearer`,children:`bot_bearer (Authorization: Bot …)`}),(0,I.jsx)(`option`,{value:`header`,children:`header (custom header)`}),(0,I.jsx)(`option`,{value:`query`,children:`query (?key=…)`}),(0,I.jsx)(`option`,{value:`path`,children:`path (path-prefix injection)`}),(0,I.jsx)(`option`,{value:`basic`,children:`basic (Authorization: Basic …)`}),(0,I.jsx)(`option`,{value:`body`,children:`body (JSON-body field injection)`}),(0,I.jsx)(`option`,{value:`none`,children:`none (no auth injection)`})]}),(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`How NyxID attaches the credential to outgoing requests.`})]}),w?(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-credential`,children:ee}),(0,I.jsx)(zO,{})]}),(0,I.jsx)(m_,{id:`pair-custom-credential`,type:`password`,value:c,onChange:e=>{l(e.target.value)},placeholder:u===`basic`?`user:pass`:`sk-...`,autoFocus:!!e.custom,"aria-required":`true`}),(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Pasted once, encrypted at rest.`,u===`basic`?` Format: user:pass.`:``]})]}):null,T?(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-auth-key-name`,children:u===`header`?`Header name`:u===`query`?`Query parameter name`:u===`path`?`Path prefix segment`:`Body field name`}),(0,I.jsx)(m_,{id:`pair-custom-auth-key-name`,value:f,onChange:e=>{p(e.target.value)},placeholder:IO(u)})]}):null,b?(0,I.jsxs)(`div`,{className:`rounded-[10px] border border-border bg-muted/40 px-3 py-2`,children:[(0,I.jsx)(`p`,{className:`text-xs font-medium text-foreground`,children:`Routed via node`}),(0,I.jsx)(`code`,{className:`font-mono text-[11px] text-muted-foreground`,children:b}),(0,I.jsx)(`p`,{className:`text-[11px] text-muted-foreground mt-1`,children:`Credential will be encrypted and pushed to this node over the existing WebSocket channel. NyxID never logs it.`})]}):null,(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:`pair-custom-slug`,children:`Custom slug (optional)`}),(0,I.jsx)(m_,{id:`pair-custom-slug`,value:m,onChange:e=>{h(e.target.value)},placeholder:`auto-generated from label`}),(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`URL segment at `,(0,I.jsx)(`code`,{children:`/proxy/s//…`}),`. Leave blank to let NyxID derive it from the label.`]})]})]}),v?(0,I.jsx)(UO,{message:v}):null,(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,I.jsx)(Dr,{variant:`outline`,onClick:r,disabled:g,children:`← Back`}),(0,I.jsx)(Dr,{onClick:()=>void D(),disabled:E,children:g?`Connecting…`:`Connect service`})]})]})}function VO({entry:e,prefill:t,pairingId:n,onSuccess:r}){let i=PO(e),[a,o]=(0,F.useState)(t.label??e.name),[s,c]=(0,F.useState)(``),[l,u]=(0,F.useState)(t.endpoint_url??``),[d,f]=(0,F.useState)({}),[p,m]=(0,F.useState)(!1),[h,g]=(0,F.useState)(null),_=t.via_node?.trim()??``,[v,y]=(0,F.useState)(!1);async function b(){m(!0),g(null);try{let t={service_slug:e.slug,label:a};if(i===`token-exchange`&&!_){let n=e.token_exchange_credential_fields??[],r={};for(let e of n){let t=d[e.name]?.trim();if(!t){g(`${e.label||e.name} is required.`),m(!1);return}r[e.name]=t}t.credential=JSON.stringify(r)}else i===`api-key`&&e.requires_credential&&!_&&(t.credential=s);(e.requires_gateway_url||l)&&(t.endpoint_url=l),_&&(t.node_id=_),await d_(n);let o=await p_(n,()=>u_.post(`/keys`,t));r({kind:`ai-key`,service_id:o.id,slug:o.slug,label:o.label})}catch(e){g(e instanceof i_?e.message:`Failed to create service.`)}finally{m(!1)}}async function x(e){try{await u_.post(`/cli-pairings/${encodeURIComponent(n)}/cancel`,{})}catch{}if(e){if(window.__WIZARD_BOOTSTRAP__?.context===`local`){alert(`This auth shape isn't supported in the CLI wizard. Open your NyxID dashboard and complete setup on the Keys page (tab: External Services). You can close this tab now.`);return}window.location.assign(e)}else window.history.back()}if(e.service_type===`ssh`)return(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:[e.name,` is an SSH service. Use`,` `,(0,I.jsx)(`code`,{children:`nyxid service add-ssh`}),` from your CLI instead (certificate-based auth, not a credential binding).`]}),(0,I.jsx)(Dr,{variant:`outline`,onClick:()=>void x(null),children:`Go back`})]});if(i===`other`||(i===`oauth`||i===`device-code`)&&!e.provider_config_id){let t=`/keys?tab=services&slug=${encodeURIComponent(e.slug)}`;return(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsxs)(`p`,{className:`rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm`,children:[e.name,` uses `,(0,I.jsx)(`code`,{children:e.auth_method}),` auth, which isn't supported via remote pairing. Complete setup on the main Keys page. Your CLI will receive a cancel and print a "finish in browser" hint.`]}),(0,I.jsxs)(Dr,{onClick:()=>void x(t),className:`justify-center gap-2`,children:[`Open Keys page`,(0,I.jsx)(yr,{className:`h-4 w-4`})]})]})}let S=l.trim()||t.endpoint_url;if(v&&i===`oauth`&&e.provider_config_id)return(0,I.jsx)(xO,{providerId:e.provider_config_id,slug:e.slug,label:a,nodeId:t.via_node,endpointUrl:S,pairingId:n,credentialMode:e.credential_mode,documentationUrl:e.documentation_url,onSuccess:r,onCancel:()=>{y(!1)}});if(v&&i===`device-code`&&e.provider_config_id)return(0,I.jsx)(SO,{providerId:e.provider_config_id,slug:e.slug,label:a,nodeId:t.via_node,endpointUrl:S,pairingId:n,onSuccess:r,onCancel:()=>{y(!1)}});let C=i===`api-key`&&e.requires_credential,w=p?`Creating...`:_?`Connect via node`:i===`oauth`?`Continue with provider sign-in`:i===`device-code`?`Get device code`:i===`no-auth`?`Connect`:`Create service`,T=i===`token-exchange`?(e.token_exchange_credential_fields??[]).every(e=>(d[e.name]??``).trim().length>0):!0,E=p||!a.trim()||C&&!_&&!s.trim()||e.requires_gateway_url&&!l.trim()||!_&&!T;function ee(){i===`oauth`||i===`device-code`?y(!0):b()}return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border bg-muted/30 p-3`,children:[e.icon_url?(0,I.jsx)(`img`,{src:e.icon_url,alt:``,className:`h-8 w-8 rounded`,loading:`lazy`}):null,(0,I.jsxs)(`div`,{className:`flex flex-col gap-0.5`,children:[(0,I.jsx)(`h3`,{className:`font-medium`,children:e.name}),e.description?(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:e.description}):null,(0,I.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Auth: `,(0,I.jsx)(`code`,{children:e.auth_method})]})]})]}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,I.jsx)(HO,{label:`Label`,htmlFor:`pair-aikey-label`,children:(0,I.jsx)(m_,{id:`pair-aikey-label`,value:a,onChange:e=>{o(e.target.value)},autoFocus:!0})}),e.requires_gateway_url?(0,I.jsx)(HO,{label:`Instance URL`,htmlFor:`pair-aikey-url`,children:(0,I.jsx)(m_,{id:`pair-aikey-url`,value:l,onChange:e=>{u(e.target.value)},placeholder:`https://your-instance.example.com`})}):null,C&&!_?(0,I.jsxs)(HO,{label:`API key`,htmlFor:`pair-aikey-credential`,children:[(0,I.jsx)(m_,{id:`pair-aikey-credential`,type:`password`,autoComplete:`off`,value:s,onChange:e=>{c(e.target.value)},placeholder:`sk-...`}),e.api_key_url?(0,I.jsxs)(`a`,{href:e.api_key_url,target:`_blank`,rel:`noopener noreferrer`,className:`mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground underline-offset-2 hover:underline`,children:[`Get an API key`,(0,I.jsx)(yr,{className:`h-3 w-3`})]}):null]}):null,i===`token-exchange`&&!_?(e.token_exchange_credential_fields??[]).map(e=>(0,I.jsx)(HO,{label:e.label||e.name,htmlFor:`pair-aikey-tx-${e.name}`,children:(0,I.jsx)(m_,{id:`pair-aikey-tx-${e.name}`,type:e.secret?`password`:`text`,autoComplete:`off`,value:d[e.name]??``,onChange:t=>{let n=t.target.value;f(t=>({...t,[e.name]:n}))},placeholder:e.placeholder??``})},e.name)):null,_?(0,I.jsxs)(`div`,{className:`rounded-[10px] border border-border bg-muted/40 px-3 py-2`,children:[(0,I.jsx)(`p`,{className:`text-xs font-medium text-foreground`,children:`Routed via node`}),(0,I.jsx)(`code`,{className:`font-mono text-[11px] text-muted-foreground`,children:_}),(0,I.jsx)(`p`,{className:`text-[11px] text-muted-foreground mt-1`,children:`Credential will be configured on the node agent. NyxID never sees or stores it.`})]}):null,i===`no-auth`?(0,I.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`This service doesn't need a credential. Click Connect to add it to your services.`}):null]}),h?(0,I.jsx)(UO,{message:h}):null,(0,I.jsx)(Dr,{onClick:ee,disabled:E,children:w})]})}function HO({label:e,htmlFor:t,children:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsx)(Ir,{htmlFor:t,children:e}),n]})}function UO({message:e}){return(0,I.jsx)(`p`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:e})}var WO=!1,GO=null;function KO(e){if(GO=e,WO)return;WO=!0;let t=window.fetch.bind(window);window.fetch=async(e,n)=>{let r=QO(e,n),i=new URL(r.url,window.location.origin);if(i.origin!==window.location.origin)return t(r);if(i.pathname.startsWith(`/api/v1/cli-pairings/`))return i.pathname.endsWith(`/cancel`)?t(`/api/proxy/cancel-unload`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`,keepalive:n?.keepalive??!1}):new Response(JSON.stringify({ok:!0}),{status:200,headers:{"content-type":`application/json`}});if(r.method===`DELETE`&&/^\/api\/v1\/keys\/[^/]+$/.test(i.pathname)&&i.searchParams.get(`only_if_pending`)===`true`){let e=i.pathname.split(`/`).pop()??``;return t(`/api/proxy/abandon-placeholder`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:JSON.stringify({key_id:e})})}if(i.pathname.startsWith(`/api/v1/`)){let e=new URL(i.toString());e.pathname=`/api/proxy${i.pathname}`;let a=ek($O(r,n));return t(e.toString(),{method:r.method,headers:a,body:await tk(r),credentials:r.credentials,signal:r.signal})}return t(r)}}async function qO(e){let t=await fetch(`/api/proxy/complete`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:JSON.stringify(e)});if(!t.ok)throw Error(`/api/proxy/complete failed: ${String(t.status)} ${t.statusText}`)}async function JO(){try{await fetch(`/api/proxy/cancel`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`})}catch{}}var YO=1200,XO=3;function ZO(e){let t=0,n=!1,r=window.setInterval(()=>{fetch(`/api/proxy/heartbeat`,{method:`POST`,headers:ek({"content-type":`application/json`}),body:`{}`}).then(r=>{if(!r.ok)throw Error(`heartbeat ${String(r.status)}`);t=0,n&&(n=!1,e?.onReconnect?.())}).catch(()=>{t+=1,t>=XO&&!n&&(n=!0,e?.onDisconnect?.())})},YO);return()=>{window.clearInterval(r)}}function QO(e,t){return e instanceof Request?e:new Request(e,t)}function $O(e,t){let n={};return e.headers.forEach((e,t)=>{n[t]=e}),t?.headers&&new Headers(t.headers).forEach((e,t)=>{n[t]=e}),n}function ek(e){return GO?{...e,"x-wizard-csrf":GO.csrf}:e}async function tk(e){if(e.method===`GET`||e.method===`HEAD`)return null;try{let t=await e.clone().text();return t.length>0?t:null}catch{return null}}function nk({state:e,context:t,pairingStatus:n}){return(0,I.jsxs)(`div`,{role:`alert`,"aria-live":`polite`,className:`mb-4 flex items-start gap-3 rounded-[10px] border border-destructive/50 bg-destructive/10 px-4 py-3 text-[13px] text-foreground`,children:[(0,I.jsx)(e===`reconnecting`?Cr:Tr,{className:`mt-0.5 h-4 w-4 shrink-0 text-destructive `+(e===`reconnecting`?`animate-spin`:``),"aria-hidden":!0}),(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`p`,{className:`font-medium`,children:e===`reconnecting`?`Reconnecting…`:t===`local`?`Connection to CLI interrupted`:n===`cancelled`?`CLI cancelled this pairing`:n===`expired`?`Pairing expired`:`Pairing went stale`}),(0,I.jsx)(`p`,{className:`text-muted-foreground`,children:e===`reconnecting`?`Retrying the last check…`:t===`local`?`The nyxid CLI missed several heartbeat checks. Keep this tab open; the wizard will continue if the connection recovers. If this message persists, re-run the command in your terminal.`:n===`cancelled`?`The CLI sent a cancel — nothing was created on the server. You can close this tab.`:n===`expired`?`This pairing passed its 15-minute TTL. Re-run the command in your terminal to start a new one.`:`The pairing record is no longer reachable. Re-run the CLI command to start a fresh one.`})]})]})}var rk=window.__WIZARD_BOOTSTRAP__;rk&&KO(rk);var ik=new Ge({defaultOptions:{queries:{retry:1,staleTime:3e4}}});function ak(e,t){return t?e!==`done`&&e!==`cancelled`:!1}function ok(){let[e,t]=(0,F.useState)({phase:`claimed`}),[n,r]=(0,F.useState)(null),[i,a]=(0,F.useState)(!!rk?.prefill?.slug),[o,s]=(0,F.useState)(!1);if((0,F.useEffect)(()=>{if(!rk)return;let e=ZO({onDisconnect:()=>{s(!0)},onReconnect:()=>{s(!1)}});return()=>{e()}},[]),!rk)return(0,I.jsx)(hk,{});let c=mt(ck(e.phase),rk.flow,{slugPicked:i});async function l(e){if(e.kind===`ai-key`){t({phase:`acking`,result:e}),await sk(e,r,t);return}t({phase:`secret`,result:e})}async function u(){e.phase===`secret`&&await sk(e.result,r,t)}return(0,I.jsxs)(gt,{context:`local`,step:c,children:[ak(e.phase,o)?(0,I.jsx)(nk,{state:`disconnected`,context:`local`}):null,e.phase===`claimed`?(0,I.jsx)(lk,{flow:rk.flow,prefill:rk.prefill??{},onSuccess:e=>void l(e),onCancel:()=>{t({phase:`cancelled`}),JO()},onSlugPicked:e=>{a(!!e)}}):e.phase===`secret`?(0,I.jsx)(uk,{result:e.result,completeError:n,onAck:()=>void u()}):e.phase===`acking`?(0,I.jsx)(dk,{result:e.result,completeError:n,onRetry:()=>{l(e.result)}}):e.phase===`cancelled`?(0,I.jsx)(pk,{}):(0,I.jsx)(fk,{})]})}async function sk(e,t,n){try{await qO(e.kind===`ai-key`?{acknowledged:!0,service_id:e.service_id,slug:e.slug,label:e.label}:e.kind===`api-key-create`?{acknowledged:!0,api_key_id:e.api_key_id}:e.kind===`node-register-token`?{acknowledged:!0,token_id:e.token_id}:{acknowledged:!0,resource_id:e.resource_id}),t(null),n({phase:`done`})}catch(e){t(e instanceof Error?e.message:String(e))}}function ck(e){return e===`claimed`?`claimed`:e===`secret`?`secret`:e===`acking`?`acking`:`done`}function lk({flow:e,prefill:t,onSuccess:n,onCancel:r,onSlugPicked:i}){let a=`local`;switch(e){case`api-key-create`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(aO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(mk,{onCancel:r})]});case`api-key-rotate`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(oO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(mk,{onCancel:r})]});case`node-register-token`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(cO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(mk,{onCancel:r})]});case`node-rotate-token`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(lO,{prefill:t,pairingId:a,onSuccess:n}),(0,I.jsx)(mk,{onCancel:r})]});case`ai-key`:return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(FO,{prefill:t,pairingId:a,onSuccess:n,onSlugPicked:i}),(0,I.jsx)(mk,{onCancel:r})]})}}function uk({result:e,completeError:t,onAck:n}){let r=t===null;return e.kind===`api-key-create`?(0,I.jsx)(Or,{title:`API key created`,description:`Save this key now — it won't be shown again.`,secret:e.full_key,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:r&&t===null&&!1}):e.kind===`api-key-rotate`?(0,I.jsx)(Or,{title:`API key rotated`,description:`The previous key is revoked. Save this new value now — it won't be shown again.`,secret:e.full_key,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):e.kind===`node-register-token`?(0,I.jsx)(Or,{title:`Registration token generated`,description:"Use this with `nyxid node register`. Save it now — it won't be shown again.",secret:e.token,ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):e.kind===`node-rotate-token`?(0,I.jsx)(Or,{title:`Node tokens rotated`,description:"Update the node with `nyxid node rekey`. Save both values now — they won't be shown again.",secret:e.auth_token,secondarySecret:{label:`Signing secret`,value:e.signing_secret},ackButtonLabel:`I have saved this — close`,onAcknowledge:n,isAcknowledging:!1}):(0,I.jsx)(`p`,{className:`text-sm text-destructive`,children:`Unknown result kind.`})}function dk({result:e,completeError:t,onRetry:n}){return(0,I.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Service added`}),(0,I.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[(0,I.jsx)(`code`,{className:`font-mono text-xs`,children:e.slug}),` is now connected. Check your terminal for the final summary.`]}),t?(0,I.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,I.jsxs)(`p`,{className:`text-sm text-destructive`,children:[`Couldn't notify CLI: `,t]}),(0,I.jsx)(Dr,{variant:`outline`,onClick:n,children:`Retry`})]}):null]})}function fk(){return(0,I.jsx)(`div`,{className:`flex flex-col gap-4`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Done`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`You can close this tab and return to your terminal.`})]})})}function pk(){return(0,I.jsx)(`div`,{className:`flex flex-col gap-4`,children:(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,I.jsx)(`h2`,{className:`font-serif text-[28px] font-normal`,children:`Cancelled`}),(0,I.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Nothing was created. You can close this tab — your CLI should already be back at the prompt.`})]})})}function mk({onCancel:e}){return(0,I.jsx)(`button`,{type:`button`,onClick:e,className:`self-start text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground`,children:`Cancel and return to terminal`})}function hk(){return(0,I.jsx)(`div`,{className:`mx-auto flex min-h-screen max-w-md items-center justify-center p-6`,children:(0,I.jsxs)(`div`,{className:`w-full rounded-xl border border-border bg-card p-8`,children:[(0,I.jsx)(`h1`,{className:`font-serif text-xl`,children:`Wizard bootstrap missing`}),(0,I.jsxs)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:[`This page expects to be served by the `,(0,I.jsx)(`code`,{children:`nyxid`}),` CLI's local wizard server, which injects bootstrap config on request. Open the URL printed by the CLI instead.`]})]})})}var gk=document.getElementById(`wizard-root`);gk&&(0,dt.createRoot)(gk).render((0,I.jsx)(F.StrictMode,{children:(0,I.jsx)(Xe,{client:ik,children:(0,I.jsx)(ok,{})})})); diff --git a/cli/src/wizard/bundle-meta/index.hash b/cli/src/wizard/bundle-meta/index.hash index 8c877d97..1abaa9df 100644 --- a/cli/src/wizard/bundle-meta/index.hash +++ b/cli/src/wizard/bundle-meta/index.hash @@ -1 +1 @@ -62ff938228e4ec18e5fa1a811ec1f9fe4cbe015f89cd26966722a926cc175377 +56f4f63078e728e5700f0c57bd4418ba2f02100ebb08a84591686aca9c402cd5 diff --git a/frontend/src/components/cli-wizard/ai-key-confirm-panel.test.tsx b/frontend/src/components/cli-wizard/ai-key-confirm-panel.test.tsx index 42053f45..c281b3fd 100644 --- a/frontend/src/components/cli-wizard/ai-key-confirm-panel.test.tsx +++ b/frontend/src/components/cli-wizard/ai-key-confirm-panel.test.tsx @@ -16,14 +16,15 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; // point — regression guard for the existing `service add ` // flow. -const { mockPost } = vi.hoisted(() => ({ +const { mockGet, mockPost } = vi.hoisted(() => ({ + mockGet: vi.fn(), mockPost: vi.fn(), })); vi.mock("@/lib/api-client", () => ({ api: { post: mockPost, - get: vi.fn(), + get: mockGet, }, ApiError: class ApiError extends Error { status: number; @@ -421,3 +422,108 @@ describe("AiKeyConfirm — custom-service back reset", () => { expect(onSlugPicked).toHaveBeenCalledTimes(1); }); }); + +describe("AiKeyConfirm — catalog services routed via node", () => { + const catalogEntry = { + slug: "llm-openai", + name: "OpenAI", + base_url: "https://api.openai.com", + auth_method: "bearer", + service_type: "rest", + requires_credential: true, + requires_gateway_url: false, + }; + + beforeEach(() => { + mockGet.mockReset(); + mockPost.mockReset(); + mockGet.mockResolvedValue(catalogEntry); + baseProps.onSuccess = vi.fn(); + baseProps.onSlugPicked = vi.fn(); + }); + + it("hides credential, shows node badge, and omits credential in POST body", async () => { + const user = userEvent.setup(); + mockPost.mockResolvedValue({ + id: "svc-id-abc", + slug: "llm-openai", + label: "Test", + }); + + render( + , + { wrapper: createWrapper() }, + ); + + await screen.findByText(/Routed via node/i); + + expect(screen.queryByLabelText(/API key/i)).not.toBeInTheDocument(); + expect(screen.getByText("node-uuid-12345")).toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: /Connect via node/i })); + + await waitFor(() => { + expect(mockPost).toHaveBeenCalledWith( + "/keys", + expect.objectContaining({ + service_slug: "llm-openai", + label: "Test", + node_id: "node-uuid-12345", + }), + ); + }); + + const [, body] = mockPost.mock.calls.find(([path]) => path === "/keys") ?? []; + expect(body).not.toHaveProperty("credential"); + }); + + it("enables submit without a credential when via_node is set", async () => { + render( + , + { wrapper: createWrapper() }, + ); + + await screen.findByText(/Routed via node/i); + + expect( + screen.getByRole("button", { name: /Connect via node/i }), + ).not.toBeDisabled(); + }); + + it("keeps submit disabled when label is empty", async () => { + const user = userEvent.setup(); + render( + , + { wrapper: createWrapper() }, + ); + + await screen.findByText(/Routed via node/i); + + await user.clear(screen.getByLabelText("Label")); + + expect( + screen.getByRole("button", { name: /Connect via node/i }), + ).toBeDisabled(); + }); +}); diff --git a/frontend/src/components/cli-wizard/ai-key-confirm-panel.tsx b/frontend/src/components/cli-wizard/ai-key-confirm-panel.tsx index 96dfd1e8..d53f4bea 100644 --- a/frontend/src/components/cli-wizard/ai-key-confirm-panel.tsx +++ b/frontend/src/components/cli-wizard/ai-key-confirm-panel.tsx @@ -662,6 +662,7 @@ function CatalogConfirmForm({ const [tokenFields, setTokenFields] = useState>({}); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); + const viaNode = prefill.via_node?.trim() ?? ""; // Set once the user clicks "Continue" for an OAuth / device-code // flow; drops the confirm UI and mounts the sub-flow panel. Reset // to `null` if the sub-flow reports cancel so the user can edit @@ -676,7 +677,7 @@ function CatalogConfirmForm({ service_slug: entry.slug, label, }; - if (shape === "token-exchange") { + if (shape === "token-exchange" && !viaNode) { // Multi-field credential: validate required-ness and JSON- // encode. Mirror wizard.js submit path at wizard.js:723-734. const fields = entry.token_exchange_credential_fields ?? []; @@ -691,7 +692,7 @@ function CatalogConfirmForm({ creds[f.name] = val; } body.credential = JSON.stringify(creds); - } else if (shape === "api-key" && entry.requires_credential) { + } else if (shape === "api-key" && entry.requires_credential && !viaNode) { body.credential = credential; } // `no-auth` / `oauth` / `device-code` skip credential entirely; @@ -700,8 +701,8 @@ function CatalogConfirmForm({ if (entry.requires_gateway_url || endpointUrl) { body.endpoint_url = endpointUrl; } - if (prefill.via_node) { - body.node_id = prefill.via_node; + if (viaNode) { + body.node_id = viaNode; } // Reserve the destructive action server-side before creating @@ -873,6 +874,7 @@ function CatalogConfirmForm({ const needsCredentialInput = shape === "api-key" && entry.requires_credential; const submitLabel = (() => { if (loading) return "Creating..."; + if (viaNode) return "Connect via node"; if (shape === "oauth") return "Continue with provider sign-in"; if (shape === "device-code") return "Get device code"; if (shape === "no-auth") return "Connect"; @@ -889,9 +891,9 @@ function CatalogConfirmForm({ const submitDisabled = loading || !label.trim() || - (needsCredentialInput && !credential.trim()) || + (needsCredentialInput && !viaNode && !credential.trim()) || (entry.requires_gateway_url && !endpointUrl.trim()) || - !tokenExchangeComplete; + (!viaNode && !tokenExchangeComplete); function handleSubmit() { if (shape === "oauth" || shape === "device-code") { @@ -951,7 +953,7 @@ function CatalogConfirmForm({ ) : null} - {needsCredentialInput ? ( + {needsCredentialInput && !viaNode ? ( ) : null} - {shape === "token-exchange" + {shape === "token-exchange" && !viaNode ? (entry.token_exchange_credential_fields ?? []).map((f) => ( +

Routed via node

+ + {viaNode} + +

+ Credential will be configured on the node agent. NyxID + never sees or stores it. +

+ + ) : null} + {shape === "no-auth" ? (

This service doesn't need a credential. Click Connect to diff --git a/frontend/src/wizard-entry.test.tsx b/frontend/src/wizard-entry.test.tsx new file mode 100644 index 00000000..f7cf286a --- /dev/null +++ b/frontend/src/wizard-entry.test.tsx @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; + +import { shouldShowDisconnectBanner } from "./wizard-entry"; + +describe("shouldShowDisconnectBanner", () => { + it("returns false when the CLI is still connected", () => { + expect(shouldShowDisconnectBanner("claimed", false)).toBe(false); + }); + + it.each(["claimed", "secret", "acking"] as const)( + "returns true for disconnected non-terminal phase %s", + (phase) => { + expect(shouldShowDisconnectBanner(phase, true)).toBe(true); + }, + ); + + it.each(["done", "cancelled"] as const)( + "returns false for disconnected terminal phase %s", + (phase) => { + expect(shouldShowDisconnectBanner(phase, true)).toBe(false); + }, + ); +}); diff --git a/frontend/src/wizard-entry.tsx b/frontend/src/wizard-entry.tsx index efa83999..062ca81c 100644 --- a/frontend/src/wizard-entry.tsx +++ b/frontend/src/wizard-entry.tsx @@ -1,3 +1,5 @@ +/* eslint-disable react-refresh/only-export-components -- standalone entry exports a pure helper for focused tests. */ + /** * Standalone entry for the CLI's locally-served wizard (Mode A). * @@ -105,6 +107,14 @@ const queryClient = new QueryClient({ }, }) +export function shouldShowDisconnectBanner( + phase: ModeAPhase["phase"], + disconnected: boolean, +): boolean { + if (!disconnected) return false + return phase !== "done" && phase !== "cancelled" +} + function WizardApp() { const [stage, setStage] = useState({ phase: "claimed" }) const [completeError, setCompleteError] = useState(null) @@ -167,7 +177,7 @@ function WizardApp() { return ( - {disconnected ? ( + {shouldShowDisconnectBanner(stage.phase, disconnected) ? ( ) : null} {stage.phase === "claimed" ? (