@mmmbuto/nexuscrew 0.8.52-rc.1 → 0.8.52-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -90,4 +90,4 @@ Minimum version required to store current data is: `+I+`.
90
90
  `).filter(o=>o!==""),promptMode:e.promptMode};return e.modelFlag&&(s.model={flag:e.modelFlag,value:e.modelValue||""}),e.promptMode==="flag"&&(s.promptFlag=e.promptFlag),t&&(s.env=Object.fromEntries(e.envRows.filter(o=>!o.remove&&o.key).map(o=>[o.key,o.value]))),s}function zs({children:e,onClose:t,label:n,error:s=""}){const o=N.useRef(null),a=N.useRef(null),u=N.useRef(t);return u.current=t,N.useEffect(()=>{const h=document.activeElement,f=o.current,p=()=>Array.from((f==null?void 0:f.querySelectorAll('button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [href], [tabindex]:not([tabindex="-1"])'))||[]).filter(y=>y.offsetParent!==null),v=requestAnimationFrame(()=>{var y;return(y=p()[0]||f)==null?void 0:y.focus({preventScroll:!0})}),S=y=>{var C;if(y.key==="Escape"){y.preventDefault(),(C=u.current)==null||C.call(u);return}if(y.key!=="Tab")return;const w=p();if(!w.length){y.preventDefault(),f==null||f.focus();return}const b=w[0],k=w[w.length-1];y.shiftKey&&document.activeElement===b?(y.preventDefault(),k.focus()):!y.shiftKey&&document.activeElement===k&&(y.preventDefault(),b.focus())};return document.addEventListener("keydown",S),()=>{cancelAnimationFrame(v),document.removeEventListener("keydown",S),h&&h.isConnected&&typeof h.focus=="function"&&h.focus({preventScroll:!0})}},[]),N.useEffect(()=>{s&&requestAnimationFrame(()=>{var h;return(h=a.current)==null?void 0:h.scrollIntoView({block:"nearest"})})},[s]),c.jsx("div",{className:"nc-fleet-modal",role:"presentation",onMouseDown:h=>{h.target===h.currentTarget&&t()},children:c.jsxs("div",{ref:o,className:"nc-fleet-modal-dialog",role:"dialog","aria-modal":"true","aria-label":n||m("settings"),tabIndex:-1,children:[e,s&&c.jsx("div",{ref:a,className:"nc-err nc-fleet-modal-error",role:"alert","aria-live":"assertive",children:s})]})})}function Od({token:e,targets:t=[],readonly:n=!1,onPower:s,onImport:o}){const[a,u]=N.useState([]),[h,f]=N.useState(0);N.useEffect(()=>{let C=!0;async function j(){const F=[{route:[],label:m("local")}].concat((t||[]).map(Y=>({route:Array.isArray(Y.route)?Y.route:[],label:Y.label||(Y.route||[]).join(" › ")}))),B=await Promise.all(F.map(async Y=>{const V={...Y,available:!1,readonly:!1,capabilities:[],provider:null,cells:[],unmanaged:[],err:""};try{const z=await ys(e,Y.route);V.available=!!z.available,V.capabilities=z.capabilities||[],V.provider=z.provider||null,V.cells=(z.cells||[]).map(Z=>({...Z,route:Y.route}));try{V.readonly=!!(await Qh(e,Y.route)).readonlyDefault}catch{}try{const Z=await Xh(e,Y.route),q=new Set(V.cells.map(G=>G.tmuxSession).filter(Boolean));V.unmanaged=(Z.sessions||[]).filter(G=>G&&!q.has(G.name))}catch{}}catch(z){V.err=String(z&&z.message||z)}return V}));C&&u(B)}j();const x=setInterval(j,6e3);return()=>{C=!1,clearInterval(x)}},[e,t,h]);const p=(C,j)=>Array.isArray(C.capabilities)&&C.capabilities.includes(j)&&!n&&!C.readonly,v=()=>f(C=>C+1),S=(C,j)=>{s&&s({...C,route:j})},y=(C,j)=>{s&&s({...C,route:j})},w=async(C,j)=>{try{await zo(e,C.cell,j)}catch{}v()},b=async(C,j)=>{if(window.confirm(m("fleet-remove-cell").replace("{id}",C.cell))){try{await G_(e,C.cell,!0,j)}catch{}v()}},k=async(C,j)=>{if(window.confirm(m("terminate-confirm").replace("{name}",C.name))){try{await Yh(e,C.name,j)}catch{}v()}};return c.jsxs("div",{className:"nc-fleet-inventory",children:[c.jsxs("div",{className:"nc-fleet-section-head",children:[c.jsx("b",{children:m("fleet-inventory")}),c.jsx("small",{children:m("fleet-inventory-help")})]}),a.map(C=>{const j=C.route.length?C.route.join("/"):"local";return c.jsxs("div",{className:"nc-fleet-pos",children:[c.jsxs("div",{className:"nc-fleet-pos-title",children:[c.jsx("span",{className:`dot ${C.available?"on":"warn"}`}),c.jsx("b",{children:C.label}),c.jsx("small",{children:C.available?`${C.cells.length} ${m("fleet-cells")} · ${C.unmanaged.length} ${m("fleet-tmux")}`:C.err||m("fleet-not-available")})]}),C.cells.map(x=>c.jsxs("div",{className:"nc-fleet-item nc-fleet-cell",children:[c.jsxs("span",{children:[c.jsx("b",{children:x.cell}),c.jsx("small",{children:`${x.engine||""}${x.key?`·${x.key}`:""}${x.active?"":` · ${m("cell-off")}`}`})]}),c.jsxs("span",{className:"nc-fleet-cell-actions",children:[x.active&&p(C,"down")&&c.jsx("button",{className:"nc-btn ghost",title:m("power-off"),onClick:()=>y(x,C.route),children:m("stop")}),!x.active&&p(C,"up")&&c.jsx("button",{className:"nc-btn ghost",title:m("power-on"),onClick:()=>S(x,C.route),children:m("start")}),p(C,"restart")&&x.active&&c.jsx("button",{className:"nc-btn ghost",title:m("restart"),onClick:()=>w(x,C.route),children:m("restart")}),p(C,"remove")&&c.jsx("button",{className:"nc-btn danger",title:m("delete"),onClick:()=>b(x,C.route),children:"×"})]})]},`${j}:${x.cell}`)),C.unmanaged.map(x=>c.jsxs("div",{className:"nc-fleet-item nc-fleet-unmanaged",children:[c.jsxs("span",{children:[c.jsx("b",{children:x.name}),c.jsx("small",{children:m("fleet-tmux")})]}),c.jsxs("span",{className:"nc-fleet-cell-actions",children:[p(C,"import")&&o&&c.jsx("button",{className:"nc-btn ghost",title:m("import-as-cell"),onClick:()=>o(x,C.route),children:m("import-as-cell")}),c.jsx("button",{className:"nc-btn danger",title:m("terminate"),onClick:()=>k(x,C.route),children:"×"})]})]},`${j}:u:${x.name}`)),C.available&&C.cells.length===0&&C.unmanaged.length===0&&c.jsx("div",{className:"nc-empty",children:m("fleet-inventory-empty")})]},j)})]})}function H2({cells:e=[],engines:t=[],busy:n,canRestore:s=!1,onRestore:o,onClose:a}){const[u,h]=N.useState("export"),[f,p]=N.useState(()=>new Set(e.map(E=>E.id))),[v,S]=N.useState(()=>new Set(t.map(E=>E.id))),[y,w]=N.useState([]),[b,k]=N.useState([]),[C,j]=N.useState(""),x=new Set(t.map(E=>E.id)),F=new Set(e.map(E=>E.id)),B=(E,D)=>E(T=>{const $=new Set(T);return $.has(D)?$.delete(D):$.add(D),$}),Y=()=>{const E=M2(e,f,t,v);if(E.ok===!1){j(m(`fleet-backup-${E.error}`));return}const D=e.filter(K=>f.has(K.id)).length,T=t.filter(K=>v.has(K.id)).length;if(E.cells.length!==D){j(m("fleet-backup-invalid-cell"));return}if(E.engines.length!==T){j(m("fleet-backup-invalid-engine"));return}if(!E.cells.length&&!E.engines.length){j(m("fleet-backup-select-one"));return}const $=new Blob([`${JSON.stringify(E,null,2)}
91
91
  `],{type:"application/json"}),W=URL.createObjectURL($),R=document.createElement("a");R.href=W,R.download=`nexuscrew-fleet-${new Date().toISOString().slice(0,10)}.json`,document.body.appendChild(R),R.click(),R.remove(),setTimeout(()=>URL.revokeObjectURL(W),0),j("")},V=async E=>{if(j(""),w([]),k([]),!!E){if(E.size>1024*1024){j(m("fleet-backup-too-large"));return}try{const D=I2(await E.text());if(!D.ok){j(m(`fleet-backup-${D.error}`));return}const T=new Set(D.engines.map($=>$.id));k(D.engines.map($=>({engine:$,exists:x.has($.id),selected:!x.has($.id)}))),w(D.cells.map($=>{const W=x.has($.engine)||T.has($.engine),R=F.has($.id);return{cell:$,engine:W?$.engine:"",selected:W&&!R,exists:R}}))}catch(D){j(String(D.message||D))}}},z=(E,D)=>w(T=>T.map(($,W)=>W===E?{...$,...D}:$)),Z=(E,D)=>k(T=>T.map(($,W)=>W===E?{...$,...D}:$)),q=new Set([...x,...b.filter(E=>E.selected).map(E=>E.engine.id)]),G=y.filter(E=>E.selected&&E.engine&&q.has(E.engine)),I=b.filter(E=>E.selected),M=[...new Map([...t.map(E=>[E.id,E.label||E.id]),...b.filter(E=>E.selected).map(E=>[E.engine.id,E.engine.label||E.engine.id])]).entries()];return c.jsxs("div",{className:"nc-set-form nc-fleet-form nc-backup-dialog",children:[c.jsx("b",{children:m("fleet-backup")}),c.jsx("small",{children:m("fleet-backup-help")}),c.jsxs("div",{className:"nc-set-tabs nc-backup-tabs",children:[c.jsx("button",{type:"button",className:`nc-set-tabbtn${u==="export"?" on":""}`,onClick:()=>{h("export"),j("")},children:m("fleet-backup-export")}),c.jsx("button",{type:"button",className:`nc-set-tabbtn${u==="import"?" on":""}`,disabled:!s,title:s?"":m("fleet-backup-restore-unavailable"),onClick:()=>{h("import"),j("")},children:m("fleet-backup-import")})]}),u==="export"?c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:()=>{p(new Set(e.map(E=>E.id))),S(new Set(t.map(E=>E.id)))},children:m("select-all")}),c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:()=>{p(new Set),S(new Set)},children:m("select-none")})]}),c.jsxs("div",{className:"nc-backup-list",children:[c.jsx("b",{children:m("fleet-engines")}),t.map(E=>{var D;return c.jsxs("label",{className:"nc-check nc-backup-row",children:[c.jsx("input",{type:"checkbox",checked:v.has(E.id),onChange:()=>B(S,E.id)}),c.jsxs("span",{children:[c.jsx("b",{children:E.label||E.id}),c.jsxs("small",{children:[E.id,(D=E.envKeys)!=null&&D.length?` · ${E.envKeys.length} ${m("fleet-backup-env-names")}`:""]})]})]},E.id)}),c.jsx("b",{children:m("fleet-cells")}),e.map(E=>c.jsxs("label",{className:"nc-check nc-backup-row",children:[c.jsx("input",{type:"checkbox",checked:f.has(E.id),onChange:()=>B(p,E.id)}),c.jsxs("span",{children:[c.jsx("b",{children:E.id}),c.jsxs("small",{children:[E.engine," · ",m("fleet-system-prompt")," ",(E.prompt||"").length," ",m("characters")]})]})]},E.id)),!e.length&&!t.length&&c.jsx("div",{className:"nc-empty",children:m("fleet-backup-empty")})]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:a,children:m("cancel")}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:!f.size&&!v.size,onClick:Y,children:m("fleet-backup-download")})]})]}):c.jsxs(c.Fragment,{children:[c.jsx("input",{type:"file",accept:"application/json,.json",disabled:n,onChange:E=>V(E.target.files&&E.target.files[0])}),c.jsx("small",{children:m("fleet-backup-import-help")}),!!(y.length||b.length)&&c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:()=>{k(E=>E.map(D=>({...D,selected:!0}))),w(E=>E.map(D=>({...D,selected:!!D.engine})))},children:m("select-all")}),c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:()=>{k(E=>E.map(D=>({...D,selected:!1}))),w(E=>E.map(D=>({...D,selected:!1})))},children:m("select-none")})]}),c.jsxs("div",{className:"nc-backup-list",children:[!!b.length&&c.jsx("b",{children:m("fleet-engines")}),b.map((E,D)=>{var T;return c.jsx("div",{className:"nc-backup-import-row",children:c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:E.selected,onChange:$=>Z(D,{selected:$.target.checked})}),c.jsxs("span",{children:[c.jsx("b",{children:E.engine.label||E.engine.id}),c.jsxs("small",{children:[E.engine.id," · ",E.exists?m("fleet-backup-overwrite"):m("fleet-backup-new"),(T=E.engine.envKeys)!=null&&T.length?` · ${m("fleet-backup-env-values-required")}`:""]})]})]})},E.engine.id)}),!!y.length&&c.jsx("b",{children:m("fleet-cells")}),y.map((E,D)=>c.jsxs("div",{className:"nc-backup-import-row",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:E.selected,disabled:!E.engine||!q.has(E.engine),onChange:T=>z(D,{selected:T.target.checked})}),c.jsxs("span",{children:[c.jsx("b",{children:E.cell.id}),c.jsxs("small",{children:[E.exists?m("fleet-backup-overwrite"):m("fleet-backup-new")," · ",m("fleet-system-prompt")," ",E.cell.systemPrompt.length," ",m("characters")]})]})]}),c.jsxs("select",{value:E.engine,onChange:T=>z(D,{engine:T.target.value,selected:!!T.target.value}),children:[c.jsx("option",{value:"",children:m("fleet-backup-engine-missing")}),M.map(([T,$])=>c.jsx("option",{value:T,children:$},T))]})]},E.cell.id))]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:a,children:m("cancel")}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:n||!G.length&&!I.length,onClick:()=>o({engineRows:b,cellRows:y}),children:m("fleet-backup-restore")})]})]}),C&&c.jsx("div",{className:"nc-err",children:C})]})}function W2({state:e,setState:t,busy:n,onSave:s,catalog:o}){var j;const a=e.form,u=x=>t({...e,form:{...a,...x}}),h=a.envRows||[],f=[...new Map(o.map(x=>[x.client,x.clientLabel||x.client])).entries()],p=o.filter(x=>x.client===a.client),v=Qo(o,a),S=typeof(v==null?void 0:v.credentialEnv)=="string"?v.credentialEnv:"",y=Array.isArray(v==null?void 0:v.credentialUsedBy)?v.credentialUsedBy:[],w=(v==null?void 0:v.credentialSource)||"missing",b=!!(v!=null&&v.credentialEnv)||a.credentialProfile==="a"||a.credentialProfile==="p",k=!!S&&e.mode==="new"&&(v==null?void 0:v.authConfigured)!==!0&&!a.credentialValue&&!a.allowMissingCredential,C=x=>{x&&u({client:x.client,provider:x.provider,credentialProfile:x.credentialProfile||"",managedModel:x.model||"",protocol:x.protocol||"",permissionPolicy:x.permissionPolicyDefault||"standard",credentialSourcePolicy:"auto",rc:!!x.rc,displayName:x.custom?m("fleet-custom-provider-default"):"",baseUrl:x.custom?"":x.endpoint||"",envKey:x.defaultEnvKey||"",providerId:"nexuscrew-custom",credentialValue:"",credentialReveal:!1,allowMissingCredential:!1,...e.mode==="new"?{id:x.id,label:""}:{}})};return c.jsxs("div",{className:"nc-set-form nc-fleet-form",children:[c.jsx("b",{children:e.mode==="new"?m("fleet-new-engine"):`${m("edit")} ${a.id}`}),c.jsx("input",{value:a.id,disabled:e.mode!=="new",placeholder:"id",onChange:x=>u({id:x.target.value})}),c.jsx("input",{value:a.label,placeholder:m("label"),onChange:x=>u({label:x.target.value})}),c.jsxs("select",{value:a.kind,disabled:e.mode!=="new",onChange:x=>u({kind:x.target.value}),children:[c.jsx("option",{value:"managed",children:m("fleet-managed")}),c.jsx("option",{value:"custom",children:m("fleet-custom")})]}),a.kind==="managed"?c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"nc-fleet-pair",children:[c.jsx("select",{value:a.client,disabled:e.mode!=="new",onChange:x=>C(o.find(F=>F.client===x.target.value&&F.default)||o.find(F=>F.client===x.target.value)),children:f.map(([x,F])=>c.jsx("option",{value:x,children:F},x))}),c.jsx("select",{value:((j=Qo(o,a))==null?void 0:j.id)||"",disabled:e.mode!=="new",onChange:x=>C(o.find(F=>F.id===x.target.value)),children:p.map(x=>c.jsx("option",{value:x.id,children:x.label},x.id))})]}),a.client!=="shell"&&c.jsxs(c.Fragment,{children:[c.jsx("input",{value:a.managedModel,list:"nc-managed-models",placeholder:m(v!=null&&v.requiresModel?"fleet-model-required":"fleet-model-default"),onChange:x=>u({managedModel:x.target.value})}),c.jsx("datalist",{id:"nc-managed-models",children:[...(v==null?void 0:v.models)||[],...a.modelOptions||[]].filter((x,F,B)=>x&&B.indexOf(x)===F).map(x=>c.jsx("option",{value:x},x))})]}),v!=null&&v.supportsUnsafe?c.jsxs("select",{value:a.permissionPolicy,onChange:x=>u({permissionPolicy:x.target.value}),children:[c.jsx("option",{value:"standard",children:m("fleet-standard-permissions")}),c.jsx("option",{value:"unsafe",children:m("fleet-unsafe-permissions")})]}):c.jsx("small",{children:m("fleet-standard-permissions")}),(v==null?void 0:v.supportsUnsafe)&&a.permissionPolicy==="unsafe"&&c.jsx("small",{className:"nc-err",children:m("fleet-unsafe-warning")}),b&&c.jsxs("select",{"aria-label":m("fleet-credential-source-policy"),value:a.credentialSourcePolicy||"auto",onChange:x=>u({credentialSourcePolicy:x.target.value}),children:[c.jsx("option",{value:"auto",children:m("fleet-credential-source-policy-auto")}),c.jsx("option",{value:"nexuscrew-store",children:m("fleet-credential-source-policy-nexuscrew-store")}),c.jsx("option",{value:"environment",children:m("fleet-credential-source-policy-environment")})]}),(v==null?void 0:v.credentialEnv)===!0&&c.jsxs(c.Fragment,{children:[c.jsx("input",{value:a.envKey,placeholder:m("fleet-api-key-env"),onChange:x=>u({envKey:x.target.value})}),c.jsx("small",{children:m("fleet-custom-secret-help")})]}),S&&c.jsxs("section",{className:"nc-fleet-key","aria-label":m("fleet-key-section"),children:[c.jsxs("div",{className:"nc-fleet-key-head",children:[c.jsx("b",{children:m("fleet-key-section")}),c.jsx("span",{children:m(`fleet-credential-source-${w}`)})]}),c.jsxs("label",{className:"nc-field",children:[m("fleet-key-variable"),c.jsx("input",{value:S,readOnly:!0,"aria-label":m("fleet-key-variable")})]}),c.jsx("small",{children:y.length?m("fleet-key-used-by").replace("{engines}",y.join(", ")):m("fleet-key-used-by-none")}),y.length>0&&c.jsx("small",{children:m("fleet-key-shared-impact").replace("{key}",S).replace("{engines}",y.join(", "))}),c.jsxs("div",{className:"nc-fleet-key-input",children:[c.jsx("input",{type:a.credentialReveal?"text":"password",value:a.credentialValue||"","aria-label":m("fleet-key-value").replace("{key}",S),autoComplete:"new-password",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",placeholder:v!=null&&v.authConfigured||e.mode==="edit"?m("fleet-key-blank-keeps"):m("fleet-key-enter"),onChange:x=>u({credentialValue:x.target.value,allowMissingCredential:x.target.value?!1:a.allowMissingCredential})}),c.jsx("button",{type:"button",className:"nc-btn ghost","aria-label":m(a.credentialReveal?"fleet-key-hide":"fleet-key-reveal"),onClick:()=>u({credentialReveal:!a.credentialReveal}),children:m(a.credentialReveal?"fleet-key-hide":"fleet-key-reveal")})]}),c.jsx("small",{children:m("fleet-key-local-help")}),e.mode==="new"&&(v==null?void 0:v.authConfigured)!==!0&&!a.credentialValue&&c.jsxs("label",{className:"nc-check nc-fleet-key-missing",children:[c.jsx("input",{type:"checkbox",checked:!!a.allowMissingCredential,onChange:x=>u({allowMissingCredential:x.target.checked})}),m("fleet-key-create-missing")]}),(v==null?void 0:v.notice)&&c.jsx("small",{className:"nc-fleet-provider-notice",children:m(`fleet-provider-notice-${v.notice}`)})]}),(v==null?void 0:v.notice)&&!S&&c.jsx("small",{className:"nc-fleet-provider-notice",children:m(`fleet-provider-notice-${v.notice}`)}),a.provider==="custom"&&c.jsxs(c.Fragment,{children:[c.jsx("input",{value:a.displayName,placeholder:m("fleet-provider-display"),onChange:x=>u({displayName:x.target.value})}),c.jsx("input",{value:a.baseUrl,placeholder:"https://api.example.com/v1",onChange:x=>u({baseUrl:x.target.value})}),((v==null?void 0:v.protocols)||[]).length>1&&c.jsx("select",{value:a.protocol,onChange:x=>u({protocol:x.target.value}),children:v.protocols.map(x=>c.jsx("option",{value:x,children:x},x))}),c.jsxs("div",{className:"nc-fleet-pair",children:[c.jsx("input",{value:a.envKey,placeholder:m("fleet-api-key-env"),onChange:x=>u({envKey:x.target.value})}),c.jsx("input",{value:a.providerId,placeholder:m("fleet-provider-id"),onChange:x=>u({providerId:x.target.value})})]}),c.jsxs("small",{children:[a.protocol," · ",m("fleet-custom-secret-help")]})]}),c.jsx("small",{children:m(a.client==="shell"?"fleet-shell-engine-help":"fleet-managed-help")})]}):c.jsxs(c.Fragment,{children:[c.jsx("input",{value:a.command,placeholder:m("command-path"),onChange:x=>u({command:x.target.value})}),c.jsx("textarea",{value:a.argsText,placeholder:m("args-lines"),onChange:x=>u({argsText:x.target.value})}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:a.rc,onChange:x=>u({rc:x.target.checked})})," remote control"]}),c.jsxs("select",{value:a.promptMode,onChange:x=>u({promptMode:x.target.value}),children:[c.jsx("option",{value:"send-keys",children:"send-keys"}),c.jsx("option",{value:"flag",children:"flag"})]}),a.promptMode==="flag"&&c.jsx("input",{value:a.promptFlag,placeholder:"prompt flag",onChange:x=>u({promptFlag:x.target.value})}),c.jsxs("div",{className:"nc-fleet-pair",children:[c.jsx("input",{value:a.modelFlag,placeholder:"model flag",onChange:x=>u({modelFlag:x.target.value})}),c.jsx("input",{value:a.modelValue,placeholder:"model default",onChange:x=>u({modelValue:x.target.value})})]}),c.jsx("small",{children:m("env-write-only")}),h.map((x,F)=>c.jsxs("div",{className:"nc-fleet-env",children:[c.jsx("input",{value:x.key,disabled:x.configured,placeholder:"ENV_KEY",onChange:B=>{const Y=h.slice();Y[F]={...x,key:B.target.value},u({envRows:Y})}}),c.jsx("input",{type:"password",value:x.value,placeholder:x.configured?"•••••• (unchanged)":"value",onChange:B=>{const Y=h.slice();Y[F]={...x,value:B.target.value},u({envRows:Y})}}),c.jsx("button",{className:"nc-btn danger",onClick:()=>u({envRows:h.filter((B,Y)=>Y!==F)}),children:"×"})]},`${x.key}-${F}`)),c.jsx("button",{className:"nc-btn ghost",onClick:()=>u({envRows:[...h,{key:"",value:"",configured:!1}]}),children:"+ env"})]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",onClick:()=>t(null),children:m("cancel")}),c.jsx("button",{className:"nc-btn primary",disabled:n||!a.id||k||a.kind==="custom"&&!a.command||a.kind==="managed"&&(v==null?void 0:v.requiresModel)&&!a.managedModel||a.kind==="managed"&&(v==null?void 0:v.credentialEnv)===!0&&!a.envKey||a.kind==="managed"&&a.provider==="custom"&&(!a.displayName||!a.baseUrl||!a.envKey||!a.providerId),onClick:s,children:m("save")})]})]})}function U2({token:e,route:t,targets:n=[],location:s,setLocation:o,state:a,setState:u,engines:h,busy:f,onSave:p}){var V;const[v,S]=N.useState(null),[y,w]=N.useState(""),b=a.form,k=z=>u({...a,form:{...b,...z}}),C=h.find(z=>z.id===b.engine),j=((V=C==null?void 0:C.managed)==null?void 0:V.client)==="shell",x=z=>{var G,I,M,E;const Z=h.find(D=>D.id===z),q={...b.commands||{}};((G=C==null?void 0:C.managed)==null?void 0:G.client)==="shell"&&(b.command?q[b.engine]=b.command:delete q[b.engine]),k({engine:z,model:((I=b.models)==null?void 0:I[z])||((M=Z==null?void 0:Z.managed)==null?void 0:M.model)||((E=Z==null?void 0:Z.model)==null?void 0:E.value)||"",commands:q,command:q[z]||""})},F=z=>{const Z={...b.commands||{}};z?Z[b.engine]=z:delete Z[b.engine],k({command:z,commands:Z})},B=j&&/[|&;<>()`$*?{}\[\]~]/.test(b.command||""),Y=async z=>{try{const Z=await Gh(e,z,t);S(Z),k({cwd:Z.path}),w("")}catch(Z){w(String(Z.message||Z))}};return c.jsxs("div",{className:"nc-set-form nc-fleet-form",children:[c.jsx("b",{children:a.mode==="new"?m("fleet-new-cell"):`${m("edit")} ${b.id}`}),a.mode==="new"&&c.jsxs("label",{className:"nc-field",children:[m("location"),c.jsx("span",{className:"nc-req",children:" *"}),c.jsxs("select",{value:s,onChange:z=>{o(z.target.value),k({engine:""})},children:[c.jsx("option",{value:"",children:m("local")}),n.map(z=>c.jsxs("option",{value:z.route.join("/"),disabled:z.status&&z.status!=="up",children:[z.label,z.status&&z.status!=="up"?` · ${m("node-offline")}`:""]},z.route.join("/")))]})]}),c.jsx("input",{value:b.id,disabled:a.mode!=="new",placeholder:"id",onChange:z=>k({id:z.target.value})}),c.jsx("input",{value:b.label||"",maxLength:64,placeholder:m("fleet-cell-label"),onChange:z=>k({label:z.target.value})}),c.jsxs("div",{className:"nc-fleet-pair",children:[c.jsx("input",{value:b.cwd,placeholder:m("cwd"),onChange:z=>k({cwd:z.target.value})}),c.jsx("button",{className:"nc-btn ghost",onClick:()=>v?S(null):Y(b.cwd),children:m("browse")})]}),v&&c.jsxs("div",{className:"nc-fs",children:[c.jsx("div",{className:"nc-fs-path",children:v.path}),c.jsxs("div",{className:"nc-fs-list",children:[v.parent&&c.jsxs("button",{className:"nc-fs-item nc-fs-nav",onClick:()=>Y(v.parent),children:["↑ ",m("fs-parent")]}),(v.dirs||[]).map(z=>c.jsxs("button",{className:"nc-fs-item",onClick:()=>Y(`${v.path.replace(/\/$/,"")}/${z}`),children:["📁 ",z]},z))]})]}),y&&c.jsx("div",{className:"nc-err",children:y}),c.jsx("select",{value:b.engine,onChange:z=>x(z.target.value),children:h.map(z=>c.jsx("option",{value:z.id,children:z.label},z.id))}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:!!b.boot,onChange:z=>k({boot:z.target.checked})})," boot"]}),j?c.jsxs(c.Fragment,{children:[c.jsx("input",{value:b.command||"",maxLength:4096,placeholder:m("fleet-shell-command-placeholder"),onChange:z=>F(z.target.value)}),c.jsx("small",{children:b.command?m("fleet-shell-command-help"):m("fleet-shell-interactive")}),B&&c.jsx("small",{className:"nc-note",children:m("fleet-shell-command-metachar")})]}):c.jsxs(c.Fragment,{children:[c.jsx("input",{value:b.model||"",list:"nc-cell-models",placeholder:m("fleet-model-override"),onChange:z=>k({model:z.target.value})}),c.jsx("datalist",{id:"nc-cell-models",children:((C==null?void 0:C.availableModels)||[]).map(z=>c.jsx("option",{value:z},z))}),c.jsx("textarea",{value:b.prompt||"",placeholder:"prompt",onChange:z=>k({prompt:z.target.value})})]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",onClick:()=>u(null),children:m("cancel")}),c.jsx("button",{className:"nc-btn primary",disabled:f||!b.id||!b.cwd||!b.engine,onClick:p,children:m("save")})]})]})}function D_({token:e,route:t=[],state:n,setState:s,busy:o,onSave:a}){const[u,h]=N.useState(null),[f,p]=N.useState([]),[v,S]=N.useState(""),y=Array.isArray(t)?t.join("/"):"";N.useEffect(()=>{let j=!0;return Vh(e,y?y.split("/"):[]).then(x=>{j&&(p(x.engines||[]),S(""))}).catch(x=>{j&&(p([]),S(String(x.message||x)))}),()=>{j=!1}},[e,y]);const w=n.form,b=j=>s({...n,form:{...w,...j}}),k=async j=>{try{const x=await Gh(e,j,t);h(x),b({cwd:x.path})}catch{}},C=!w.id&&w.tmuxSession?w.tmuxSession.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32):w.id;return c.jsxs("div",{className:"nc-set-form nc-fleet-form",children:[c.jsxs("b",{children:[m("import-as-cell")," · ",w.tmuxSession]}),c.jsx("small",{children:m("import-help")}),c.jsx("input",{value:w.tmuxSession,disabled:!0,placeholder:"tmux session",readOnly:!0}),c.jsx("input",{value:w.id,placeholder:m("name"),onChange:j=>b({id:j.target.value})}),c.jsxs("div",{className:"nc-fleet-pair",children:[c.jsx("input",{value:w.cwd,placeholder:m("cwd"),onChange:j=>b({cwd:j.target.value})}),c.jsx("button",{className:"nc-btn ghost",type:"button",onClick:()=>u?h(null):k(w.cwd),children:m("browse")})]}),u&&c.jsxs("div",{className:"nc-fs",children:[c.jsx("div",{className:"nc-fs-path",children:u.path}),c.jsxs("div",{className:"nc-fs-list",children:[u.parent&&c.jsxs("button",{className:"nc-fs-item nc-fs-nav",onClick:()=>k(u.parent),children:["↑ ",m("fs-parent")]}),(u.dirs||[]).map(j=>c.jsxs("button",{className:"nc-fs-item",onClick:()=>k(`${u.path.replace(/\/$/,"")}/${j}`),children:["📁 ",j]},j))]})]}),c.jsxs("select",{value:w.engine,onChange:j=>b({engine:j.target.value}),children:[c.jsx("option",{value:"",children:m("import-engine-required")}),f.map(j=>c.jsx("option",{value:j.id,children:j.label},j.id))]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:!!w.boot,onChange:j=>b({boot:j.target.checked})})," boot"]}),(n.err||v)&&c.jsx("div",{className:"nc-err",children:n.err||v}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",onClick:()=>s(null),children:m("cancel")}),c.jsx("button",{className:"nc-btn primary",disabled:o||!w.tmuxSession||!w.engine||!f.length,onClick:a,children:m(C?"import-as-cell":"save")})]})]})}function Cl(e){const t=Ws(e);return t===null?`~/${e}`:t?`~/${t}`:"~"}function K2(e){if(!e||typeof e.path!="string"||typeof e.home!="string")return"";const{path:t,home:n}=e;return!n||t===n||!t.startsWith(n+"/")?"":t.slice(n.length+1).replace(/\/+$/,"")}function q2({token:e,route:t,cell:n,busy:s=!1,onSaved:o,onClose:a}){const[u,h]=N.useState(""),[f,p]=N.useState(null),[v,S]=N.useState(!1),[y,w]=N.useState(""),b=typeof(n==null?void 0:n.cwdSuggestion)=="string"&&Ws(n.cwdSuggestion)!==null?Ws(n.cwdSuggestion):null,[k,C]=N.useState(b),j=n==null?void 0:n.id,x=s||v,F=async q=>{const G=Ws(q);if(G===null){p({rel:"",dirs:[],loading:!1,err:m("fleet-cwd-repair-invalid")});return}p({rel:G,dirs:[],loading:!0,err:""});try{const I=await Gh(e,G,t),M=K2(I);p({rel:M,dirs:Array.isArray(I.dirs)?I.dirs:[],loading:!1,err:""})}catch(I){p({rel:G,dirs:[],loading:!1,err:String(I&&I.message||I)})}},B=q=>{if(!f)return;const G=f.rel?`${f.rel}/${q}`:q;F(G)},Y=()=>{f!=null&&f.rel&&F(f.rel.split("/").slice(0,-1).join("/"))},V=()=>{f&&(h(f.rel||""),p(null),w(""),C(null))},z=()=>{k!==null&&(h(k),C(null),w(""))},Z=async()=>{if(x)return;const q=Ws(u);if(q===null){w(m("fleet-cwd-repair-invalid"));return}const G=Cl(q);let I=!0;try{I=window.confirm(m("fleet-cwd-repair-confirm").replace("{id}",String(j||"")).replace("{path}",G))}catch{I=!1}if(I){S(!0),w(""),C(null);try{const M=await Y_(e,j,{cwdRel:q},t);o==null||o(M)}catch(M){const E=M&&M.data||{};if(E.code==="unportable-cwd"){w(m("fleet-cwd-repair-unportable"));const D=Array.isArray(E.cells)?E.cells.find($=>$&&$.id===j):null,T=D&&typeof D.suggestion=="string"?D.suggestion:null;T!==null&&Ws(T)!==null&&C(T)}else w(String(M&&M.message||M))}finally{S(!1)}}};return c.jsxs("div",{className:"nc-set-form nc-fleet-form nc-cwd-repair",children:[c.jsx("b",{children:m("fleet-cwd-repair-title").replace("{id}",String(j||""))}),c.jsx("small",{className:"nc-set-info",children:m("fleet-cwd-repair-help")}),c.jsx("small",{className:"nc-cwd-no-source",children:m("fleet-cwd-repair-no-source-path")}),c.jsxs("label",{className:"nc-field",children:[m("cwd"),c.jsxs("div",{className:"nc-cwd-rel-row",children:[c.jsx("span",{className:"nc-cwd-rel-prefix",children:"~/"}),c.jsx("input",{value:u,placeholder:m("fleet-cwd-repair-placeholder"),autoComplete:"off",spellCheck:"false",autoCapitalize:"none",onChange:q=>h(q.target.value)}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:x,onClick:()=>f?p(null):F(""),children:m(f?"close":"fleet-cwd-repair-browse")})]})]}),c.jsx("div",{className:"nc-cwd-preview",children:m("fleet-cwd-repair-preview").replace("{path}",Cl(u))}),f&&c.jsxs("div",{className:"nc-fs",children:[c.jsx("div",{className:"nc-fs-path",children:Cl(f.rel)}),c.jsxs("div",{className:"nc-fs-list",children:[f.rel&&c.jsxs("button",{type:"button",className:"nc-fs-item nc-fs-nav",onClick:Y,children:["↑ ",m("fs-parent")]}),f.loading&&c.jsx("div",{className:"nc-fs-empty",children:"…"}),!f.loading&&f.dirs.length===0&&c.jsx("div",{className:"nc-fs-empty",children:m("fleet-cwd-repair-fs-empty")}),!f.loading&&f.dirs.map(q=>c.jsxs("button",{type:"button",className:"nc-fs-item",onClick:()=>B(q),children:["📁 ",q]},q))]}),f.err&&c.jsx("div",{className:"nc-err",children:f.err}),c.jsx("div",{className:"nc-sheet-actions",children:c.jsx("button",{type:"button",className:"nc-btn primary",disabled:x||f.loading||!!f.err,onClick:V,children:m("fleet-cwd-repair-use-current")})})]}),y&&c.jsx("div",{className:"nc-err",role:"alert",children:y}),k!==null&&c.jsxs("div",{className:"nc-cwd-suggestion",role:"status",children:[c.jsx("span",{children:m("fleet-cwd-repair-suggestion")}),c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:z,children:m("fleet-cwd-repair-use-suggestion").replace("{path}",Cl(k))})]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:v,onClick:a,children:m("cancel")}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:x,onClick:Z,children:v?"…":m("save")})]})]})}function V2({token:e,readonly:t,targets:n=[],startNewCell:s=!1,initialLocation:o=""}){const[a,u]=N.useState({engines:[],cells:[],managedCatalog:[]}),[h,f]=N.useState({available:!1,capabilities:[]}),[p,v]=N.useState(!1),[S,y]=N.useState(null),[w,b]=N.useState(null),[k,C]=N.useState(!1),[j,x]=N.useState(""),[F,B]=N.useState(""),[Y,V]=N.useState(o),[z,Z]=N.useState(!1),[q,G]=N.useState(null),[I,M]=N.useState(null),[E,D]=N.useState(null),[T,$]=N.useState(!1),[W,R]=N.useState([]),[K,A]=N.useState(null),[L,O]=N.useState("manage"),X=N.useRef(!1),ne=Y?Y.split("/"):[],ce=N.useCallback(async()=>{try{const oe=await ys(e,ne);f(oe);try{const xe=await Qh(e,ne);Z(!!xe.readonlyDefault)}catch{Z(!1)}if(oe.provider==="builtin"&&(oe.capabilities||[]).includes("definitions")){const xe=await Vh(e,ne),De=new Map((oe.engines||[]).map($e=>[$e.id,$e]));if(xe.engines=(xe.engines||[]).map($e=>{var ue;return{...$e,availableModels:((ue=De.get($e.id))==null?void 0:ue.models)||[]}}),u(xe),(oe.capabilities||[]).includes("credentials"))try{R((await o0(e,ne)).credentials||[])}catch{R([])}else R([])}x("")}catch(oe){x(String(oe.message||oe))}finally{v(!0)}},[e,Y]);N.useEffect(()=>{ce();const oe=setInterval(ce,5e3);return()=>clearInterval(oe)},[ce]);const fe=new Set((h.cells||[]).filter(oe=>oe.active).map(oe=>oe.cell)),pe=h.provider==="builtin"&&(h.capabilities||[]).includes("edit"),me=(h.capabilities||[]).includes("restore");N.useEffect(()=>{!s||X.current||!pe||!a.engines.length||(X.current=!0,b({mode:"new",form:T_(a.engines[0].id)}))},[s,pe,a.engines]);const le=async oe=>{C(!0),x(""),B("");try{await oe(),await ce()}catch(xe){x(String(xe.message||xe))}C(!1)},Ie=()=>le(async()=>{var Ee;const oe=S.mode==="new",xe=S.form,De=a.managedCatalog||[],$e=xe.kind==="managed"?Qo(De,xe):null,ue=typeof($e==null?void 0:$e.credentialEnv)=="string"?$e.credentialEnv:"",Q=ue&&xe.credentialValue||"",te=$2(xe,oe,De);!oe&&S.form.kind==="custom"&&!S.form.modelFlag&&(te.model=null),!oe&&S.form.kind==="custom"&&S.form.promptMode!=="flag"&&(te.promptFlag=null);let H;if(oe)H=await l0(e,te,ne);else{const ye=S.original,Ne=new Set(S.form.envRows.filter(ze=>!ze.remove).map(ze=>ze.key)),Je=(ye.envKeys||[]).filter(ze=>!Ne.has(ze)),Ct=Object.fromEntries(S.form.envRows.filter(ze=>!ze.remove&&ze.key&&(!ze.configured||ze.value!=="")).map(ze=>[ze.key,ze.value]));H=await c0(e,ye.id,te,S.form.kind==="custom"?{set:Ct,remove:Je}:void 0,ne)}let ie=null;if(ue&&Q)try{ie=await vg(e,ue,Q,ne),R(ie.credentials||[])}catch{throw await ce(),oe&&y({mode:"edit",original:{...te,id:xe.id},form:{...xe,credentialReveal:!1}}),new Error(m(oe?"fleet-key-partial-create":"fleet-key-partial-edit"))}await ce(),y(null),B(m("fleet-saved"));const ve=((Ee=((ie==null?void 0:ie.credentials)||[]).find(ye=>ye.envKey===ue))==null?void 0:Ee.activeCells)||[],_e=[...new Set([...(H==null?void 0:H.activeCells)||[],...ve])];if(_e.length&&window.confirm(m("fleet-restart-confirm").replace("{cells}",_e.join(", "))))for(const ye of _e)await zo(e,ye,ne)}),st=()=>le(async()=>{var ie,ve,_e,Ee,ye,Ne;const oe=w.mode==="new",xe=w.form,De={...oe?{id:xe.id}:{},cwd:xe.cwd,engine:xe.engine,boot:!!xe.boot},$e={...xe.commands||{}},ue=a.engines.find(Je=>Je.id===xe.engine);((ie=ue==null?void 0:ue.managed)==null?void 0:ie.client)==="shell"&&typeof xe.command=="string"&&xe.command.length?$e[xe.engine]=xe.command:((ve=ue==null?void 0:ue.managed)==null?void 0:ve.client)==="shell"&&delete $e[xe.engine],(Object.keys($e).length||!oe)&&(De.commands=$e);const Q=(xe.label||"").trim();oe?Q&&(De.label=Q):De.label=Q||null,oe?(((_e=ue==null?void 0:ue.managed)==null?void 0:_e.client)!=="shell"&&xe.model&&(De.model=xe.model),((Ee=ue==null?void 0:ue.managed)==null?void 0:Ee.client)!=="shell"&&xe.prompt&&(De.prompt=xe.prompt)):(De.model=((ye=ue==null?void 0:ue.managed)==null?void 0:ye.client)==="shell"?null:xe.model||null,((Ne=ue==null?void 0:ue.managed)==null?void 0:Ne.client)!=="shell"&&(De.prompt=xe.prompt||null));const te=oe?await d0(e,De,ne):await Y_(e,w.original.id,De,ne),H=oe?xe.id:w.original.id;b(null),B(m("fleet-saved")),!oe&&(te!=null&&te.active)&&window.confirm(m("fleet-restart-confirm").replace("{cells}",H))&&await zo(e,H,ne)}),We=t||z,Fe=oe=>W.find(xe=>{var De;return(De=xe.engines)==null?void 0:De.includes(oe.id)})||null,Wt=()=>le(async()=>{var De;const oe=await vg(e,K.envKey,K.value,ne);R(oe.credentials||[]),A(null),B(m("fleet-credential-saved"));const xe=((De=(oe.credentials||[]).find($e=>$e.envKey===K.envKey))==null?void 0:De.activeCells)||[];if(xe.length&&window.confirm(m("fleet-restart-confirm").replace("{cells}",xe.join(", "))))for(const $e of xe)await zo(e,$e,ne)}),Xt=oe=>le(async()=>{if(!window.confirm(m("fleet-credential-remove-confirm").replace("{key}",oe.envKey)))return;const xe=await a0(e,oe.envKey,ne);R(xe.credentials||[]),B(m("fleet-credential-removed"))}),Be=oe=>G({...oe,route:Array.isArray(oe==null?void 0:oe.route)?oe.route:ne}),Lt=async oe=>{if(!q)return;const xe=q.cell||q.id,De=Array.isArray(q.route)?q.route:ne;if(oe.action==="up"){const $e=await qh(e,{cell:xe,boot:!!oe.boot,...oe.engine?{engine:oe.engine}:{},...oe.model!==void 0?{model:oe.model}:{},...oe.permissionPolicy?{permissionPolicy:oe.permissionPolicy}:{}},De),ue=lf($e);ue&&B(ue.text)}else await Ml(e,{cell:xe,boot:!!oe.boot},De)},gt=(oe,xe)=>{x(""),M({mode:"new",route:Array.isArray(xe)?xe:ne,form:{tmuxSession:oe.name,id:"",engine:"",cwd:"",boot:!1},err:""})},Bt=()=>le(async()=>{const oe=I.form;if(!oe.engine){M({...I,err:m("import-engine-required")});return}await h0(e,{tmuxSession:oe.tmuxSession,id:oe.id||void 0,engine:oe.engine,cwd:oe.cwd||void 0,boot:!!oe.boot},oe.route||ne),M(null),B(m("fleet-saved"))}),rt=({engineRows:oe=[],cellRows:xe=[]})=>le(async()=>{const De=oe.filter(Ee=>Ee.selected),$e=De.map(Ee=>Xw(Ee.engine));if($e.some(Ee=>!Ee))throw new Error(m("fleet-backup-invalid-engine"));const ue=De.filter(Ee=>Ee.exists).map(Ee=>Ee.engine.id);if(ue.length&&!window.confirm(m("fleet-backup-confirm-engine-overwrite").replace("{engines}",ue.join(", "))))return;const Q=[...new Set([...a.engines.map(Ee=>Ee.id),...$e.map(Ee=>Ee.id)])],te=[];for(const Ee of xe.filter(ye=>ye.selected)){const ye=O2(Ee.cell,Ee.engine,Q);if(!ye)throw new Error(`${Ee.cell.id}: ${m("fleet-backup-engine-missing")}`);te.push(ye)}const H=xe.filter(Ee=>Ee.selected&&Ee.exists).map(Ee=>Ee.cell.id);if(H.length&&!window.confirm(m("fleet-backup-confirm-overwrite").replace("{cells}",H.join(", "))))return;const ie=$e.length?await p0(e,$e,ue.length>0,ne):{needsRestart:[]},ve=te.length?await f0(e,te,ne):{needsRestart:[]},_e=[...new Set([...ie.needsRestart||[],...ve.needsRestart||[]])];$(!1),B(`${m("fleet-backup-restored").replace("{n}",String(te.length))}${$e.length?` · ${$e.length} ${m("fleet-engines").toLowerCase()}`:""}${_e.length?` · ${m("fleet-backup-needs-restart").replace("{cells}",_e.join(", "))}`:""}`)}),lt=c.jsxs("label",{className:"nc-field",children:[m("location"),c.jsxs("select",{value:Y,onChange:oe=>{V(oe.target.value),y(null),b(null),x(""),B(""),Z(!1),v(!1),f({available:!1,capabilities:[]}),u({engines:[],cells:[],managedCatalog:[]}),R([]),A(null)},children:[c.jsx("option",{value:"",children:m("local")}),n.map(oe=>c.jsxs("option",{value:oe.route.join("/"),disabled:oe.status&&oe.status!=="up",children:[oe.label,oe.status&&oe.status!=="up"?` · ${m("node-offline")}`:""]},oe.route.join("/")))]})]}),vt=c.jsxs("div",{className:"nc-fleet-view-tabs",role:"tablist","aria-label":m("tab-fleet"),children:[c.jsx("button",{type:"button",role:"tab","aria-selected":L==="manage",className:`nc-set-tabbtn${L==="manage"?" on":""}`,onClick:()=>O("manage"),children:m("fleet-manage-location")}),c.jsx("button",{type:"button",role:"tab","aria-selected":L==="overview",className:`nc-set-tabbtn${L==="overview"?" on":""}`,onClick:()=>O("overview"),children:m("fleet-network-overview")})]});return p?pe?c.jsxs("div",{className:"nc-set-tab nc-fleet-editor",children:[vt,L==="overview"?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"nc-set-info",children:m("fleet-overview-help")}),c.jsx(Od,{token:e,targets:n,readonly:t,onPower:Be,onImport:gt})]}):c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"nc-set-info",children:m("fleet-manage-help")}),lt,c.jsxs("div",{className:"nc-set-row nc-fleet-backup-actions",children:[c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>{x(""),$(!0)},children:m("fleet-backup")}),c.jsx("small",{children:m("fleet-backup-help")})]}),c.jsxs("div",{className:"nc-fleet-section-head",children:[c.jsx("b",{children:m("fleet-cells")}),c.jsx("span",{className:"nc-fleet-head-actions",children:c.jsxs("button",{className:"nc-btn primary",disabled:We||k||!a.engines.length,onClick:()=>{var oe;x(""),b({mode:"new",form:T_((oe=a.engines[0])==null?void 0:oe.id)})},children:["+ ",m("add")]})})]}),a.cells.map(oe=>{const xe=fe.has(oe.id),De=h.capabilities||[],$e=oe.needsRepair===!0;return c.jsxs("div",{className:"nc-fleet-item",children:[c.jsxs("span",{children:[c.jsx("b",{children:oe.id}),oe.label?c.jsxs("small",{className:"nc-fleet-label",children:[" ",oe.label]}):null,c.jsxs("small",{children:[oe.engine," · ",$e?c.jsx("span",{className:"nc-fleet-tag nc-fleet-tag-warn",children:m("fleet-cwd-needs-repair")}):oe.cwd,xe?` · ${m("service-active")}`:` · ${m("cell-off")}`]})]}),c.jsxs("span",{children:[xe&&De.includes("down")&&c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>le(()=>Ml(e,{cell:oe.id},ne)),children:m("stop")}),!xe&&De.includes("up")&&c.jsx("button",{className:"nc-btn primary",disabled:We||k,onClick:()=>Be({cell:oe.id,id:oe.id,engine:oe.engine,model:oe.model,models:oe.models,permissionPolicies:oe.permissionPolicies,active:!1,boot:oe.boot}),children:m("start")}),xe&&De.includes("restart")&&c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>le(()=>zo(e,oe.id,ne)),children:m("restart")}),$e?c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>{x(""),D(oe)},children:m("fleet-cwd-repair")}):c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>{var ue;x(""),b({mode:"edit",original:oe,form:{...oe,commands:{...oe.commands||{}},command:((ue=oe.commands)==null?void 0:ue[oe.engine])||""}})},children:m("edit")}),c.jsx("button",{className:"nc-btn danger",disabled:We||k,onClick:()=>le(async()=>{window.confirm(m("fleet-remove-cell").replace("{id}",oe.id))&&await G_(e,oe.id,!0,ne)}),children:"×"})]})]},oe.id)}),c.jsxs("div",{className:"nc-fleet-section-head",children:[c.jsx("b",{children:m("fleet-engines")}),c.jsxs("button",{className:"nc-btn primary",disabled:We||k,onClick:()=>{x(""),y({mode:"new",form:B2()})},children:["+ ",m("add")]})]}),a.engines.map(oe=>{var De,$e;const xe=Fe(oe);return c.jsxs("div",{className:"nc-fleet-item",children:[c.jsxs("span",{children:[c.jsx("b",{children:oe.label}),c.jsx("small",{children:oe.managed?`${oe.id} · ${oe.managed.client} / ${oe.managed.provider} · ${(De=oe.managedInfo)!=null&&De.configured?m("fleet-ready"):(($e=oe.managedInfo)==null?void 0:$e.reason)||m("fleet-not-ready")}`:`${oe.id} · ${oe.command}`}),xe&&c.jsxs("small",{children:[xe.envKey," · ",m(`fleet-credential-source-${xe.source||"missing"}`)]})]}),c.jsxs("span",{children:[xe&&c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>{x(""),A({envKey:xe.envKey,value:""})},children:xe.configured?m("fleet-credential-change"):m("fleet-credential-set")}),(xe==null?void 0:xe.source)==="local"&&c.jsx("button",{className:"nc-btn danger",disabled:We||k,onClick:()=>Xt(xe),children:m("fleet-credential-forget")}),c.jsx("button",{className:"nc-btn ghost",disabled:We||k,onClick:()=>{x(""),y({mode:"edit",original:oe,form:F2(oe)})},children:m("edit")}),c.jsx("button",{className:"nc-btn danger",disabled:We||k,onClick:()=>le(async()=>{window.confirm(m("fleet-remove-engine").replace("{id}",oe.id))&&await u0(e,oe.id,ne)}),children:"×"})]})]},oe.id)})]}),S&&c.jsx(zs,{onClose:()=>y(null),label:m("fleet-new-engine"),error:j,children:c.jsx(W2,{state:S,setState:y,busy:k,onSave:Ie,catalog:a.managedCatalog||[]})}),w&&c.jsx(zs,{onClose:()=>b(null),label:m("fleet-new-cell"),error:j,children:c.jsx(U2,{token:e,route:ne,targets:n,location:Y,setLocation:V,state:w,setState:b,engines:a.engines,busy:k,onSave:st})}),E&&c.jsx(zs,{onClose:()=>D(null),label:m("fleet-cwd-repair-title").replace("{id}",E.id),error:"",children:c.jsx(q2,{token:e,route:ne,cell:E,busy:k,onSaved:async()=>{D(null),B(m("fleet-cwd-repaired")),await ce()},onClose:()=>D(null)})}),F&&c.jsx("div",{className:"nc-set-note",children:F}),j&&c.jsx("div",{className:"nc-err",children:j}),T&&c.jsx(zs,{onClose:()=>$(!1),label:m("fleet-backup"),error:j,children:c.jsx(H2,{cells:a.cells,engines:a.engines,busy:k,canRestore:me,onRestore:rt,onClose:()=>$(!1)})}),K&&c.jsx(zs,{onClose:()=>A(null),label:m("fleet-credential-title"),error:j,children:c.jsxs("div",{className:"nc-fleet-form nc-credential-form",children:[c.jsx("b",{children:m("fleet-credential-title")}),c.jsx("small",{children:m("fleet-credential-help")}),c.jsxs("label",{className:"nc-field",children:[K.envKey,c.jsx("input",{type:"password",autoComplete:"off",spellCheck:"false",autoCapitalize:"none",value:K.value,onChange:oe=>A({...K,value:oe.target.value})})]}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",onClick:()=>A(null),children:m("cancel")}),c.jsx("button",{className:"nc-btn primary",disabled:k||!K.value,onClick:Wt,children:m("save")})]})]})}),I&&c.jsx(zs,{onClose:()=>M(null),label:m("import-as-cell"),error:j,children:c.jsx(D_,{token:e,route:I.route||ne,state:I,setState:M,busy:k,onSave:Bt})}),q&&c.jsx(Ol,{cell:q,token:e,route:Array.isArray(q.route)?q.route:ne,onConfirm:async oe=>{try{await Lt(oe)}finally{await ce()}},onClose:()=>G(null)})]}):c.jsxs("div",{className:"nc-set-tab",children:[vt,L==="overview"?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"nc-set-info",children:m("fleet-overview-help")}),c.jsx(Od,{token:e,targets:n,readonly:t,onPower:Be,onImport:gt})]}):c.jsxs(c.Fragment,{children:[lt,c.jsxs("div",{className:"nc-set-info",children:[m(j?"fleet-editor-load-error":"fleet-editor-unavailable"),!j&&h.reason?` ${h.reason}`:""]})]}),j&&c.jsx("div",{className:"nc-err",children:j}),I&&c.jsx(zs,{onClose:()=>M(null),label:m("import-as-cell"),error:j,children:c.jsx(D_,{token:e,route:I.route||ne,state:I,setState:M,busy:k,onSave:Bt})}),q&&c.jsx(Ol,{cell:q,token:e,route:Array.isArray(q.route)?q.route:ne,onConfirm:async oe=>{try{await Lt(oe)}finally{await ce()}},onClose:()=>G(null)})]}):c.jsxs("div",{className:"nc-set-tab",children:[vt,L==="overview"?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"nc-set-info",children:m("fleet-overview-help")}),c.jsx(Od,{token:e,targets:n,readonly:t,onPower:Be,onImport:gt})]}):c.jsxs(c.Fragment,{children:[lt,c.jsx("div",{className:"nc-set-info",children:m("fleet-editor-loading")})]})]})}const Mf="nc_notification_speech_v1",El="nc-notification-speech",Bh="nc-notification-speech-preview",Y2=320,G2=2,X2=3e4,Q2=1e4,J2=6e4,Z2=64,M_=Object.freeze({enabled:!1}),ej=Object.freeze({it:"it-IT",en:"en-US",es:"es-ES"}),tj=Object.freeze({it:new Set(["che","con","correzione","della","delle","difetto","il","lavoro","nessun","non","per","pronto","pubblicata","pubblicato","rilascio","sono","stato","tutti","verificata","verificato","versione","completata","completato","riepilogo"]),en:new Set(["all","and","completed","fix","for","issue","no","published","ready","release","summary","the","verified","version","with","work"]),es:new Set(["con","correccion","defecto","el","esta","para","publicada","publicado","resumen","sin","todos","trabajo","verificada","verificado","version","y"])}),If=new WeakSet;function Of(e){return{enabled:(e&&typeof e=="object"&&!Array.isArray(e)?e:{}).enabled===!0}}function Jw(){try{return typeof localStorage<"u"?localStorage:null}catch{return null}}function I_(e=Jw()){if(!e)return{...M_};try{return Of(JSON.parse(e.getItem(Mf)||"null"))}catch{return{...M_}}}function nj(e,t=Jw()){const n=Of(e);if(t)try{t.setItem(Mf,JSON.stringify(n))}catch{}return n}function Hr(){try{return typeof window<"u"?window:null}catch{return null}}function Jo(e=Hr()){try{return!!(e&&e.speechSynthesis&&typeof e.speechSynthesis.speak=="function"&&typeof e.SpeechSynthesisUtterance=="function")}catch{return!1}}function Zw(e=Hr()){return!!(e&&(typeof e=="object"||typeof e=="function")&&If.has(e))}function zh(e=Hr()){e&&(typeof e=="object"||typeof e=="function")&&If.delete(e)}function Lr(e){const t=String(e||"").trim().toLowerCase().split("-")[0];return ej[t]||""}function cc(e){return String(e||"").normalize("NFC").replace(/[\p{Cc}\p{Cf}]+/gu," ").replace(/\s+/g," ").trim()}function ij(e){const t=cc(e).normalize("NFD").replace(new RegExp("\\p{M}+","gu"),"").toLowerCase(),n=new Set(t.match(new RegExp("\\p{L}+","gu"))||[]);if(n.size<4)return"";const s=Object.entries(tj).map(([o,a])=>({lang:o,score:[...n].reduce((u,h)=>u+(a.has(h)?1:0),0)})).sort((o,a)=>a.score-o.score);return s[0].score>=3&&s[0].score-s[1].score>=2?s[0].lang:""}function sj(e,t){const n=Lr(e&&e.lang);return n||Lr(ij(e&&e.body))||Lr(t)}function eb(e){try{const t=e&&e.speechSynthesis&&e.speechSynthesis.getVoices;return typeof t=="function"?Array.from(t.call(e.speechSynthesis)||[]).filter(Boolean):[]}catch{return[]}}function tb(e,t){const n=Lr(t);if(!n)return null;const s=Array.from(e||[]).filter(h=>h&&typeof h.lang=="string"&&h.lang.trim()),o=s.filter(h=>h.lang.trim().toLowerCase()===n.toLowerCase()),a=n.slice(0,2).toLowerCase(),u=s.filter(h=>h.lang.trim().toLowerCase().split("-")[0]===a);return o.find(h=>h.default===!0)||o[0]||u.find(h=>h.default===!0)||u[0]||null}function O_(e){return cc(e).replace(/\bBearer\s+\S+/gi,"Bearer [redacted]").replace(/\b(?:sk|hf|zai|xox[baprs]|gh[pousr]|npm)[_-][A-Za-z0-9._-]{8,}\b/gi,"[redacted]").replace(/\b(?:token|password|secret|credential|api[_-]?key)\s*[=:]\s*(?:"[^"]*"|'[^']*'|\S+)/gi,"[redacted]").replace(/\b[A-Z][A-Z0-9_]{2,}\s*=\s*(?:"[^"]*"|'[^']*'|\S+)/g,"[redacted]").replace(/(?:\/home\/[^/\s]+|\/Users\/[^/\s]+|\/data\/(?:data|user\/\d+)\/[^/\s]+)(?:\/[^\s]*)?/g,"[private path]").replace(/\b[A-Za-z]:\\Users\\[^\\\s]+(?:\\[^\s]*)?/g,"[private path]")}function rj(e,t=Y2){const n=O_(e&&e.title),s=O_(e&&e.body),o=[n,s&&s!==n?s:""].filter(Boolean).join(". "),a=Array.from(o);return a.length<=t?o:`${a.slice(0,Math.max(0,t-1)).join("").trimEnd()}…`}function oj(e){try{return!!(e&&e.visibilityState==="visible"&&typeof e.hasFocus=="function"&&e.hasFocus())}catch{return!1}}function nb(e=Hr()){if(!Jo(e))return!1;try{return e.speechSynthesis.cancel(),!0}catch{return!1}}function aj(e){try{e&&typeof e.dispatchEvent=="function"&&typeof e.Event=="function"&&e.dispatchEvent(new e.Event(Bh))}catch{}}function lj(e,t,n=Hr(),s={}){var p;if(zh(n),!Jo(n))return Promise.resolve(!1);const o=cc(e);if(!o||(p=s.signal)!=null&&p.aborted)return Promise.resolve(!1);const a=Number.isFinite(s.timeoutMs)&&s.timeoutMs>0?s.timeoutMs:Q2,u=s.setTimer||((v,S)=>setTimeout(v,S)),h=s.clearTimer||(v=>clearTimeout(v)),f=s.signal;return aj(n),new Promise(v=>{let S=!1,y=!1,w=null,b=null;const k=C=>{if(!S){if(S=!0,f&&b&&f.removeEventListener("abort",b),w!==null&&h(w),C)If.add(n);else try{n.speechSynthesis.cancel()}catch{}v(C)}};b=()=>k(!1),f&&f.addEventListener("abort",b,{once:!0});try{n.speechSynthesis.cancel();const C=new n.SpeechSynthesisUtterance(o);C.lang=Lr(t);const j=tb(eb(n),C.lang);j&&(C.voice=j),C.onstart=()=>{y=!0},C.onend=()=>k(y),C.onerror=()=>k(!1),w=u(()=>k(!1),a),n.speechSynthesis.speak(C)}catch{k(!1)}})}function cj(e={}){const t=e.scope||Hr(),n=e.document||t&&t.document,s=Number.isInteger(e.maxPending)&&e.maxPending>=0?e.maxPending:G2,o=Number.isFinite(e.watchdogMs)&&e.watchdogMs>0?e.watchdogMs:X2,a=Number.isFinite(e.dedupWindowMs)&&e.dedupWindowMs>0?e.dedupWindowMs:J2,u=Number.isInteger(e.maxDedup)&&e.maxDedup>0?e.maxDedup:Z2,h=e.now||Date.now,f=e.setTimer||((I,M)=>setTimeout(I,M)),p=e.clearTimer||(I=>clearTimeout(I)),v=e.isPrimed||(()=>Zw(t)),S=t&&t.speechSynthesis;let y=null,w=null,b=[],k=[],C=()=>{};const j=new Map,x=()=>{k=eb(t)};if(x(),S&&typeof S.addEventListener=="function")S.addEventListener("voiceschanged",x),C=()=>S.removeEventListener("voiceschanged",x);else if(S&&"onvoiceschanged"in S){const I=S.onvoiceschanged,M=(...E)=>{x(),typeof I=="function"&&I.apply(S,E)};S.onvoiceschanged=M,C=()=>{S.onvoiceschanged===M&&(S.onvoiceschanged=I)}}const F=I=>{if(I&&typeof I.id=="string"&&I.id)return`id:${I.id}`;const M=Number(I&&I.ts),E=cc(I&&I.title);return Number.isFinite(M)&&E?`frame:${M}:${E}`:""},B=I=>{if(!I)return!0;const M=h();for(const[E,D]of j)M-D>=a&&j.delete(E);if(j.has(I))return!1;for(j.set(I,M);j.size>u;)j.delete(j.keys().next().value);return!0},Y=()=>{w!==null&&p(w),w=null},V=()=>{Y(),y&&(y.onend=null,y.onerror=null,y=null),nb(t)},z=I=>{if(!Jo(t))return b=[],"unsupported";let M;try{M=new t.SpeechSynthesisUtterance(I.text),M.lang=Lr(I.lang);const D=tb(k,M.lang);D&&(M.voice=D)}catch{return b=[],"error"}y=M;const E=()=>{if(y!==M)return;Y(),y=null,M.onend=null,M.onerror=null;const D=b.shift();D&&z(D)};M.onend=E,M.onerror=E;try{return w=f(()=>{if(y!==M)return;y=null,M.onend=null,M.onerror=null;try{t.speechSynthesis.cancel()}catch{}Y();const D=b.shift();D&&z(D)},o),t.speechSynthesis.speak(M),"speaking"}catch{return E(),"error"}},Z=(I,M)=>{if(!Jo(t))return"unsupported";const E=rj(I);if(!E)return"empty";if(!B(F(I)))return"duplicate";if(!oj(n))return"inactive";if(!v())return"unprimed";const D={text:E,lang:M};return I&&I.urgency==="high"?(b=[],V(),z(D)):y?s===0?"dropped":(b.length>=s&&b.shift(),b.push(D),"queued"):z(D)},q=()=>{b=[],V()};return{enqueue:Z,stop:q,dispose:()=>{q(),C(),C=()=>{}}}}function ib(){const[e,t]=N.useState(I_);N.useEffect(()=>{const s=o=>{if((o==null?void 0:o.type)==="storage"&&o.key!==Mf&&o.key!==null)return;const a=(o==null?void 0:o.type)===El?Of(o.detail):I_();t(a)};return window.addEventListener(El,s),window.addEventListener("storage",s),()=>{window.removeEventListener(El,s),window.removeEventListener("storage",s)}},[]);const n=N.useCallback(s=>{const o=nj({enabled:s===!0});return t(o),window.dispatchEvent(new CustomEvent(El,{detail:o})),o.enabled},[]);return[e.enabled,n]}function uj({text:e}){const[t,n]=N.useState(!1),s=async()=>{try{await navigator.clipboard.writeText(e),n(!0),setTimeout(()=>n(!1),1500)}catch{}};return c.jsxs("div",{className:"nc-set-copyline",children:[c.jsx("code",{children:e}),c.jsxs("button",{type:"button",className:"nc-btn ghost",onClick:s,children:[c.jsx(et,{name:"copy",size:14})," ",m(t?"copied":"copy")]})]})}function dj({value:e}){const[t,n]=N.useState("");return N.useEffect(()=>{let s=!0;return qN.toDataURL(e,{margin:1,width:220}).then(o=>{s&&n(o)}).catch(()=>{}),()=>{s=!1}},[e]),t?c.jsx("img",{src:t,width:"220",height:"220",alt:"NexusCrew pairing QR"}):null}function hj({token:e,nodes:t,roster:n,settings:s,readonly:o,refresh:a,refreshAliases:u}){const[h,f]=N.useState(null),[p,v]=N.useState(null),[S,y]=N.useState(null),[w,b]=N.useState({ssh:"",sshPort:"",name:""}),[k,C]=N.useState(""),[j,x]=N.useState(""),[F,B]=N.useState(""),[Y,V]=N.useState(!1),[z,Z]=N.useState(null),q=Date.now(),G=s&&s.deviceName||"",I=(t||[]).filter(A=>A&&A.direction==="outbound"&&A.name&&A.ssh),M=I.find(A=>A.name===k)||I[0]||null,E=I.find(A=>A.name===j)||I[0]||null,D=E?qd(E.tunnel,q):null,T=E!=null&&E.shared?D!=null&&D.up?"share-local-active":"share-local-pending":D!=null&&D.up?"share-local-private":"share-local-private-down",$=[{key:"peer-group-hubs",rows:(t||[]).filter(A=>A.kind!=="transitive"&&A.kind!=="vl"&&A.relation!=="client")},{key:"peer-group-clients",rows:(t||[]).filter(A=>A.kind!=="transitive"&&A.kind!=="vl"&&A.relation==="client")},{key:"peer-group-routed",rows:(t||[]).filter(A=>A.kind==="transitive")},{key:"peer-group-vl",rows:(t||[]).filter(A=>A.kind==="vl")}],W=z&&(t||[]).find(A=>`${A.kind||"direct"}:${A.nodeId||A.name}`===z)||null,R=async A=>{if(E){f(null),v(`${E.name}:share`);try{const L=await E0(e,E.name,A);await a(),L&&L.reversePoolPending===!0&&f(`${E.name}: ${m("share-reverse-pool-pending")}`)}catch(L){const O=L!=null&&L.data&&L.data.shared===!1?L.data:null;if(O)try{await a()}catch{}const X=L!=null&&L.data&&typeof L.data.hint=="string"?L.data.hint:"",ne=(O==null?void 0:O.revoked)===!0&&(O==null?void 0:O.localReconcilePending)===!0?m("share-off-local-reconcile-pending"):(O==null?void 0:O.revoked)===!1&&(O==null?void 0:O.reconcilePending)===!0?m("share-off-hub-reconcile-pending"):"",ce=L!=null&&L.data&&L.data.reversePoolPending===!0?m("share-reverse-pool-pending"):"",fe=L!=null&&L.data&&typeof L.data.code=="string"?L.data.code:"",pe=L!=null&&L.data&&typeof L.data.detail=="string"?L.data.detail.trim():"",me=pe&&pe!==String(L.message||"")?pe:"";f(`${E.name}: ${String(L.message||L)}${fe?` [${fe}]`:""}${me?` — ${me}`:""}${X?` — ${X}`:""}${ne?` — ${ne}`:""}${ce?` — ${ce}`:""}`)}v(null)}},K=async()=>{if(f(null),M){const O=Dg({name:M.name,ssh:M.ssh,sshPort:M.sshPort||""});if(!O.ok){f(m(O.error));return}v("invite");try{y(await yg(e,{ssh:O.value.ssh,...O.value.sshPort?{sshPort:O.value.sshPort}:{}},[M.name]))}catch(X){f(X&&X.status===404?m("invite-hub-only"):String(X.message||X))}v(null);return}const A=gs(w.name||F||G||"NexusCrew"),L=Dg({name:A,ssh:w.ssh,sshPort:w.sshPort});if(!L.ok){f(m(L.error));return}v("invite");try{y(await yg(e,{...F||G?{label:F||G}:{},name:A,ssh:L.value.ssh,...L.value.sshPort?{sshPort:L.value.sshPort}:{}}))}catch(O){f(String(O.message||O))}v(null)};return c.jsxs("div",{className:"nc-set-tab",children:[c.jsx("div",{className:"nc-sheet-label",children:m("peer-inventory-title")}),(t||[]).length===0&&c.jsx("div",{className:"nc-empty",children:m("no-nodes")}),$.map(A=>A.rows.length>0&&c.jsxs("div",{className:"nc-peer-group",children:[c.jsxs("div",{className:"nc-peer-group-title",children:[m(A.key)," ",c.jsx("span",{children:A.rows.length})]}),A.rows.map(L=>{const O=s2(L);if(!O)return null;const X=`${L.kind||"direct"}:${L.nodeId||L.name}`,ne=O.routed?{up:O.reach.up,since:null}:qd(L.tunnel,q);return c.jsxs("button",{type:"button",className:`nc-set-node nc-node-row${O.routed?" routed":""}`,"aria-label":`${O.title} — ${m("node-detail-open")}`,onClick:()=>Z(X),children:[c.jsx("span",{className:`nc-dot ${O.reach.up?"on":""}`}),c.jsxs("span",{className:"nc-node-row-text",children:[c.jsx("b",{children:O.title}),c.jsxs("small",{children:[O.routed?O.routeLabel:`${O.subtitle} · ${m(O.exposure.shortKey)}`,!O.routed&&O.exposure.shortKey==="visibility-selected"?` (${O.exposure.count})`:""]})]}),c.jsxs("span",{className:`nc-set-tunnel${O.reach.up?" up":""}`,children:[m(O.reach.key),ne.since?` · ${ne.since}`:""]}),c.jsx("span",{className:"nc-node-row-more",children:c.jsx(et,{name:"chevronDown",size:14})})]},X)})]},A.key)),W&&c.jsx(m2,{node:W,nodes:t||[],token:e,readonly:o,refresh:a,onClose:()=>Z(null)}),(n||[]).some(A=>!A.direct&&A.instanceId)&&c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("routed-node-aliases")}),c.jsx("small",{className:"nc-set-hint",children:m("routed-node-aliases-help")}),(n||[]).filter(A=>!A.direct&&A.instanceId).map(A=>c.jsxs("div",{className:"nc-set-node",children:[c.jsxs("div",{className:"nc-set-node-head",children:[c.jsx("span",{className:`nc-dot ${A.status==="up"?"on":""}`}),c.jsx("b",{children:A.label||A.name}),c.jsx("small",{children:(A.route||[]).join(" › ")})]}),c.jsxs("div",{className:"nc-set-node-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:o||!!p,onClick:async()=>{const L=window.prompt(m("node-local-alias"),A.alias||"");if(L!=null){if(L.trim()&&!Dr(L.normalize("NFC"))){f(m("err-label"));return}v(`${A.instanceId}:alias`),f(null);try{L.trim()?await k0(e,A.instanceId,L):await wg(e,A.instanceId),u()}catch(O){f(String(O.message||O))}v(null)}},children:m("alias-on-device")}),A.alias&&c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:o||!!p,onClick:async()=>{v(`${A.instanceId}:alias-reset`),f(null);try{await wg(e,A.instanceId),u()}catch(L){f(String(L.message||L))}v(null)},children:m("reset-alias")})]})]},A.instanceId))]}),E&&c.jsxs("div",{className:"nc-set-form nc-local-share",children:[c.jsx("div",{className:"nc-sheet-label",children:m("share-local-heading")}),I.length>1&&c.jsxs("label",{className:"nc-field",children:[m("share-local-hub"),c.jsx("select",{value:E.name,disabled:o||!!p,onChange:A=>x(A.target.value),children:I.map(A=>c.jsx("option",{value:A.name,children:A.label||A.name},A.name))})]}),c.jsxs("label",{className:"nc-check nc-node-share",children:[c.jsx("input",{type:"checkbox",checked:E.shared===!0,disabled:o||!!p,onChange:A=>R(A.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("share-local-through").replace("{device}",G||m("local")).replace("{hub}",E.label||E.name)}),c.jsx("small",{children:m(E.shared?"share-node-on-desc":"share-node-off-desc")})]})]}),c.jsx("div",{className:`nc-set-test${E.shared&&(D!=null&&D.up)?" ok":D!=null&&D.up?"":" ko"}`,children:m(T)}),!(D!=null&&D.up)&&c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:o||!!p,onClick:()=>R(E.shared===!0),children:m("share-local-reconnect")})]}),c.jsx($w,{token:e,deviceDefault:G,localNodeId:s&&s.nodeId||"",localNameDefault:s&&s.localName||"",readonly:o,onSuccess:a}),c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("invite-node")}),c.jsx("small",{className:"nc-set-hint",children:m(M?"invite-network-hint":"invite-v2-hint")}),M?c.jsxs(c.Fragment,{children:[I.length>1&&c.jsxs("label",{className:"nc-field",children:[m("invite-network-label"),c.jsx("select",{value:M.name,disabled:o||!!p,onChange:A=>{C(A.target.value),y(null)},children:I.map(A=>c.jsx("option",{value:A.name,children:A.label||A.name},A.name))})]}),c.jsxs("div",{className:"nc-set-info nc-invite-endpoint",children:[m("invite-network-via"),": ",c.jsx("b",{children:M.label||M.name})," · ",M.ssh,M.sshPort?`:${M.sshPort}`:""]}),c.jsx("small",{className:"nc-set-hint",children:m("invite-network-route")})]}):c.jsxs("label",{className:"nc-field",children:[m("invite-endpoint-label"),c.jsx("input",{placeholder:"user@host",value:w.ssh,disabled:o,onChange:A=>b({...w,ssh:A.target.value})}),c.jsx("small",{className:"nc-set-hint",children:m("invite-endpoint-needed")})]}),!M&&Y&&c.jsxs("div",{className:"nc-invite-advanced",children:[c.jsxs("label",{className:"nc-field",children:[m("node-ssh-port-label"),c.jsx("input",{inputMode:"numeric",placeholder:"22",value:w.sshPort,disabled:o,onChange:A=>b({...w,sshPort:A.target.value.replace(/[^0-9]/g,"").slice(0,5)})})]}),c.jsxs("label",{className:"nc-field",children:[m("device-name-label"),c.jsx("input",{placeholder:G||"NexusCrew",value:F,disabled:o,onChange:A=>B(A.target.value)}),c.jsx("small",{className:"nc-set-hint",children:m("device-name-hint")})]}),c.jsxs("label",{className:"nc-field",children:[m("node-name-label"),c.jsx("input",{placeholder:gs(F||G||m("node-name-ph")),value:w.name,disabled:o,onChange:A=>b({...w,name:A.target.value?gs(A.target.value):""})})]})]}),c.jsxs("div",{className:"nc-set-row nc-invite-actions",children:[c.jsx("button",{type:"button",className:"nc-btn primary",disabled:o||!!p||!M&&!w.ssh.trim(),onClick:K,children:m("create-pairing-link")}),!M&&c.jsxs("button",{type:"button",className:"nc-btn ghost",disabled:!!p,onClick:()=>V(A=>!A),children:[Y?"▾":"▸"," ",m("pair-advanced")]})]}),S&&c.jsxs(c.Fragment,{children:[c.jsx(dj,{value:S.pairingUrl}),c.jsx(uj,{text:S.pairingUrl}),c.jsx("div",{className:"nc-set-info",children:m("invite-next-steps")})]})]}),h&&c.jsx("div",{className:"nc-err",children:h})]})}function fj({token:e,readonly:t}){const[n,s]=N.useState("idle"),[o,a]=N.useState(!1),[u,h]=N.useState(null);N.useEffect(()=>{let p=!1;return _2().then(v=>{p||s(v)}),()=>{p=!0}},[]);const f=async()=>{h(null),a(!0);try{n==="subscribed"?(await w2(e),s("idle")):(await y2(e),s("subscribed"))}catch(p){const v=String(p.message||p);v==="push-denied"?(s("denied"),h(m("push-denied"))):v==="push-unsupported"?(s("unsupported"),h(m("push-unsupported"))):h(v)}a(!1)};return n==="unsupported"?c.jsx("div",{className:"nc-set-info",children:m("push-unsupported")}):c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:t||o||n==="denied",title:t?m("settings-readonly"):"",onClick:f,children:m(n==="subscribed"?"push-disable":"push-enable")}),c.jsx("span",{className:"nc-set-info",children:m(n==="subscribed"?"push-on":n==="denied"?"push-denied":"push-off")})]}),u&&c.jsx("div",{className:"nc-err",children:u})]})}function pj(){const[e,t]=ib(),[n,s]=N.useState(""),[o,a]=N.useState(""),[u,h]=N.useState(!1),[f,p]=N.useState(Zw),v=N.useRef(0),S=N.useRef(!1),y=N.useRef(null),w=Jo();N.useEffect(()=>()=>{var C;v.current+=1,S.current&&((C=y.current)==null||C.abort(),y.current=null,S.current=!1,zh())},[]);const b=async()=>{const C=v.current+=1,j=typeof AbortController=="function"?new AbortController:null;s(""),a(""),h(!0),p(!1),S.current=!0,y.current=j;const x=await lj(m("notification-speech-preview"),Il(),void 0,j?{signal:j.signal}:{});return C!==v.current||(y.current=null,S.current=!1,h(!1),p(x),x?a(m("notification-speech-preview-ok")):s(m("notification-speech-preview-failed"))),x},k=C=>{var j;if(t(C),s(""),a(""),C)b();else{v.current+=1;const x=S.current;(j=y.current)==null||j.abort(),y.current=null,S.current=!1,h(!1),p(!1),zh(),x||nb()}};return c.jsxs("div",{className:"nc-set-form",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox","aria-label":m("notification-speech-enable"),checked:e,disabled:!w,onChange:C=>k(C.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("notification-speech-enable")}),c.jsx("small",{children:m("notification-speech-help")})]})]}),w?c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:!e||u,onClick:()=>{b()},children:m(u?"notification-speech-testing":"notification-speech-test")})}):c.jsx("div",{className:"nc-set-info",children:m("notification-speech-unsupported")}),e&&!f&&!u&&!n&&c.jsx("div",{className:"nc-set-info",children:m("notification-speech-needs-test")}),o&&c.jsx("div",{className:"nc-set-info",role:"status",children:o}),n&&c.jsx("div",{className:"nc-err",children:n})]})}function mj({token:e,readonly:t,nodes:n=[],settings:s=null}){const[o,a]=N.useState(null),[u,h]=N.useState([]),[f,p]=N.useState({name:"",mode:"primary-failover",targets:[]}),[v,S]=N.useState(null),[y,w]=N.useState(!1),[b,k]=N.useState(null),[C,j]=N.useState(""),x=N.useCallback(async()=>{try{const[W,R]=await Promise.all([j0(e),A0(e)]);a(W),h(Array.isArray(R==null?void 0:R.groups)?R.groups:[]),j("")}catch(W){j(String(W.message||W))}},[e]);N.useEffect(()=>{x()},[x]);const F=async W=>{w(!0),k(null),j("");try{a(await R0(e,W))}catch(R){j(String(R.message||R))}w(!1)},B=async()=>{w(!0),k(null),j("");try{k({kind:"test",...await P0(e)})}catch(W){j(String(W.message||W))}w(!1)},Y=async()=>{w(!0),k(null),j("");try{k({kind:"stop",...await L0(e)})}catch(W){j(String(W.message||W))}w(!1)},V=[],z=new Set,Z=(W,R)=>{const K=typeof W=="string"?W.toLowerCase():"";!/^[a-f0-9]{32}$/.test(K)||z.has(K)||(z.add(K),V.push({id:K,label:R||K}))};Z(s==null?void 0:s.nodeId,m("audio-group-local"));for(const W of n||[])Z((W==null?void 0:W.nodeId)||(W==null?void 0:W.instanceId),(W==null?void 0:W.label)||(W==null?void 0:W.name)||(W==null?void 0:W.nodeId));for(const W of f.targets)Z(W,`${W} (${m("audio-group-unavailable-target")})`);const q=(W=null)=>{j(""),W?(S(W.name),p({name:W.name,mode:W.mode,targets:[...W.targets||[]]})):(S(null),p({name:"",mode:"primary-failover",targets:[]}))},G=(W,R)=>p(K=>({...K,targets:R?[...new Set([...K.targets,W])]:K.targets.filter(A=>A!==W)})),I=async()=>{const W=f.name.trim().toLowerCase();if(!/^[a-z0-9][a-z0-9-]{0,31}$/.test(W)||f.targets.length<1){j(m("audio-group-invalid"));return}w(!0),j("");try{const R=await T0(e,W,{targets:f.targets,mode:f.mode}),K=R==null?void 0:R.group;if(!K||!K.name)throw new Error(m("audio-group-save-failed"));h(A=>[...A.filter(L=>L.name!==K.name),K].sort((L,O)=>L.name.localeCompare(O.name))),q(null)}catch(R){j(String(R.message||R))}w(!1)},M=async W=>{w(!0),j("");try{await D0(e,W),h(R=>R.filter(K=>K.name!==W)),v===W&&q(null)}catch(R){j(String(R.message||R))}w(!1)},E=(o==null?void 0:o.installed)===!0,D=(o==null?void 0:o.liveness)==="ready",T=(o==null?void 0:o.consent)===!0&&E&&D,$=b?b.kind==="stop"?m(b.stopped?"audio-stop-stopped":"audio-stop-idle"):b.status==="accepted"||b.status==="spoken"?m("audio-test-accepted"):b.status==="unknown"?m("audio-test-unknown"):`${m("audio-test-refused")}${b.reason?` (${b.reason})`:""}`:"";return c.jsxs("div",{className:"nc-set-tab nc-audio-settings",children:[c.jsxs("div",{className:"nc-set-info",children:[c.jsx("b",{children:m("audio-title")}),c.jsx("br",{}),m("audio-help")]}),o?c.jsxs(c.Fragment,{children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox","aria-label":m("audio-consent"),checked:o.consent===!0,disabled:t||y,onChange:W=>{F(W.target.checked)}}),c.jsxs("span",{children:[c.jsx("b",{children:m("audio-consent")}),c.jsx("small",{children:m("audio-consent-help")})]})]}),c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("audio-capability")}),c.jsxs("div",{className:"nc-set-info",children:[m("audio-adapter"),": ",o.adapter||m("audio-adapter-none"),c.jsx("br",{}),m("audio-installed"),": ",m(E?"audio-installed-yes":"audio-installed-no"),c.jsx("br",{}),m("audio-liveness"),": ",m(D?"audio-liveness-ready":"audio-liveness-unavailable"),Array.isArray(o.languages)&&o.languages.length>0&&c.jsxs(c.Fragment,{children:[c.jsx("br",{}),m("audio-languages"),": ",o.languages.join(", ")]})]}),o.limits&&c.jsxs("small",{className:"nc-set-hint",children:[m("audio-limits"),": ",o.limits]})]}),!o.consent&&c.jsx("div",{className:"nc-set-info",children:m("audio-test-needs-consent")}),!E&&c.jsx("div",{className:"nc-set-info",children:m("audio-unavailable")}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn primary",disabled:t||y||!T,title:t?m("settings-readonly"):"",onClick:()=>{B()},children:m(y?"audio-testing":"audio-test")}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:y,onClick:()=>{Y()},children:m(y?"audio-stopping":"audio-stop")}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:y,onClick:()=>{x()},children:m("refresh")})]}),c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("audio-groups-title")}),c.jsx("small",{className:"nc-set-hint",children:m("audio-groups-help")}),u.length===0&&c.jsx("div",{className:"nc-set-info",children:m("audio-groups-empty")}),u.map(W=>{var R;return c.jsxs("div",{className:"nc-set-row",children:[c.jsxs("span",{children:[c.jsx("b",{children:W.name})," ",c.jsxs("small",{children:["· ",W.mode==="fanout"?m("audio-group-fanout"):m("audio-group-primary")," · ",((R=W.targets)==null?void 0:R.length)||0]})]}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:t||y,onClick:()=>q(W),children:m("audio-group-edit")}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:t||y,onClick:()=>{M(W.name)},children:m("audio-group-delete")})]},W.name)}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:t||y,onClick:()=>q(null),children:m("audio-group-new")})}),c.jsxs("label",{className:"nc-field",children:[m("audio-group-name"),c.jsx("input",{"aria-label":m("audio-group-name"),value:f.name,maxLength:"32",disabled:t||y,onChange:W=>p(R=>({...R,name:W.target.value}))})]}),c.jsxs("label",{className:"nc-field",children:[m("audio-group-mode"),c.jsxs("select",{"aria-label":m("audio-group-mode"),value:f.mode,disabled:t||y,onChange:W=>p(R=>({...R,mode:W.target.value})),children:[c.jsx("option",{value:"primary-failover",children:m("audio-group-primary")}),c.jsx("option",{value:"fanout",children:m("audio-group-fanout")})]})]}),c.jsx("div",{className:"nc-set-info",children:m("audio-group-targets")}),V.length===0?c.jsx("small",{className:"nc-set-hint",children:m("audio-group-no-targets")}):V.map(W=>c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:f.targets.includes(W.id),disabled:t||y,onChange:R=>G(W.id,R.target.checked)}),c.jsxs("span",{children:[W.label,c.jsx("small",{children:W.id})]})]},W.id)),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn primary",disabled:t||y,onClick:()=>{I()},children:m("audio-group-save")}),v&&c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:y,onClick:()=>q(null),children:m("audio-group-cancel")})]})]})]}):c.jsx("div",{className:"nc-set-info",children:m("audio-loading")}),$&&c.jsx("div",{className:"nc-set-note",role:"status",children:$}),C&&c.jsx("div",{className:"nc-err",children:C})]})}function gj(){const[e,t]=Sf();return c.jsxs("div",{className:"nc-set-tab nc-input-settings",children:[c.jsx("div",{className:"nc-set-info",children:m("input-settings-local")}),c.jsxs("div",{className:"nc-set-form",children:[c.jsxs("label",{className:"nc-field",children:[m("terminal-keyboard-gesture"),c.jsx("select",{"aria-label":m("terminal-keyboard-gesture"),value:e.terminalKeyboardGesture,onChange:n=>t({terminalKeyboardGesture:n.target.value}),children:yw.map(n=>c.jsx("option",{value:n,children:m(`terminal-keyboard-${n}`)},n))}),c.jsx("small",{children:m("terminal-keyboard-gesture-help")})]}),c.jsxs("label",{className:"nc-field",children:[m("keybar-layout"),c.jsx("select",{"aria-label":m("keybar-layout"),value:e.keybarLayout,onChange:n=>t({keybarLayout:n.target.value}),children:ww.map(n=>c.jsx("option",{value:n,children:m(`keybar-layout-${n}`)},n))}),c.jsx("small",{children:m("keybar-layout-help")})]})]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:e.keybarKeepsKeyboardClosed,onChange:n=>t({keybarKeepsKeyboardClosed:n.target.checked})}),c.jsxs("span",{children:[c.jsx("b",{children:m("keybar-ime-lock")}),c.jsx("small",{children:m("keybar-ime-lock-help")})]})]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:e.voiceKeepsKeyboardClosed,onChange:n=>t({voiceKeepsKeyboardClosed:n.target.checked})}),c.jsxs("span",{children:[c.jsx("b",{children:m("voice-ime-lock")}),c.jsx("small",{children:m("voice-ime-lock-help")})]})]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:e.showKeybarEnter,onChange:n=>t({showKeybarEnter:n.target.checked})}),c.jsxs("span",{children:[c.jsx("b",{children:m("keybar-enter-show")}),c.jsx("small",{children:m("keybar-enter-show-help")})]})]}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:()=>t(fs),children:m("input-settings-reset")})})]})}function vj({token:e,roster:t=[],readonly:n}){const s=[{key:"local",route:[],label:m("diagnostics-local"),status:"up"},...t.filter(T=>Array.isArray(T.route)&&T.route.length).map(T=>({key:T.route.join("/"),route:T.route,label:T.label||T.name,status:T.status}))],[o,a]=N.useState("local"),u=s.find(T=>T.key===o)||s[0],[h,f]=N.useState(null),[p,v]=N.useState([]),[S,y]=N.useState(""),[w,b]=N.useState(!1),[k,C]=N.useState(!0),[j,x]=N.useState(900),[F,B]=N.useState("all"),[Y,V]=N.useState(""),z=N.useRef(0),Z=N.useRef(null),q=N.useCallback(async()=>{try{const T=await B0(e,u.route);if(f(T),y(""),!w){const $=await z0(e,{after:z.current,limit:200},u.route);Array.isArray($.records)&&$.records.length&&(z.current=$.cursor,v(W=>[...W,...$.records].slice(-500)))}}catch(T){y(T&&T.status===404?m("diagnostics-unsupported"):String(T.message||T))}},[e,u.key,w]);N.useEffect(()=>{z.current=0,v([]),f(null),y("")},[u.key]),N.useEffect(()=>{let T=null,$=!0;const W=()=>{!$||document.visibilityState==="hidden"||q()},R=()=>{T&&clearInterval(T),T=document.visibilityState==="hidden"?null:setInterval(W,2e3),document.visibilityState!=="hidden"&&W()};return document.addEventListener("visibilitychange",R),R(),()=>{$=!1,T&&clearInterval(T),document.removeEventListener("visibilitychange",R)}},[q]),N.useEffect(()=>{k&&Z.current&&(Z.current.scrollTop=Z.current.scrollHeight)},[p,k]);const G=p.filter(T=>(F==="all"||T.level===F)&&(!Y||String(T.component||"").toLowerCase().includes(Y.toLowerCase()))),I=G.map(T=>`${T.ts} ${T.level.toUpperCase()} ${T.component} ${T.code} ${T.message}${Object.keys(T.meta||{}).length?` ${JSON.stringify(T.meta)}`:""}`).join(`
92
92
  `),M=async T=>{y("");try{const $=await T();f($),await q()}catch($){y(String($.message||$))}},E=async()=>{try{await navigator.clipboard.writeText(I)}catch{y(m("copy-manual"))}},D=()=>{try{const T=new Blob([`${JSON.stringify(G,null,2)}
93
- `],{type:"application/json"}),$=URL.createObjectURL(T),W=document.createElement("a");W.href=$,W.download="nexuscrew-diagnostics.json",W.click(),URL.revokeObjectURL($)}catch{y(m("diagnostics-export-failed"))}};return c.jsxs("div",{className:"nc-set-tab nc-diagnostics",children:[c.jsxs("label",{className:"nc-field",children:[m("diagnostics-target"),c.jsx("select",{value:u.key,onChange:T=>a(T.target.value),children:s.map(T=>c.jsxs("option",{value:T.key,children:[T.label,T.status!=="up"?` · ${T.status}`:""]},T.key))})]}),c.jsxs("div",{className:"nc-set-form nc-diag-controls",children:[c.jsx("div",{className:"nc-sheet-label",children:m("diagnostics-verbose")}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("select",{"aria-label":m("diagnostics-duration"),value:j,onChange:T=>x(Number(T.target.value)),disabled:n,children:[300,900,1800,3600].map(T=>c.jsxs("option",{value:T,children:[T/60," min"]},T))}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:n||(h==null?void 0:h.verbose)===!0,onClick:()=>M(()=>bg(e,!0,j,u.route)),children:m("enable")}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||(h==null?void 0:h.verbose)!==!0,onClick:()=>M(()=>bg(e,!1,j,u.route)),children:m("stop")})]}),c.jsx("small",{className:"nc-set-hint",children:h!=null&&h.verbose?m("diagnostics-expires").replace("{time}",new Date(h.expiresAt).toLocaleTimeString()):m("diagnostics-off")})]}),c.jsxs("div",{className:"nc-diag-filters",children:[c.jsxs("select",{"aria-label":m("diagnostics-level"),value:F,onChange:T=>B(T.target.value),children:[c.jsx("option",{value:"all",children:m("diagnostics-all-levels")}),["debug","info","warn","error"].map(T=>c.jsx("option",{value:T,children:T},T))]}),c.jsx("input",{"aria-label":m("diagnostics-component"),placeholder:m("diagnostics-component"),value:Y,onChange:T=>V(T.target.value)})]}),c.jsxs("div",{className:"nc-set-row",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:w,onChange:T=>b(T.target.checked)})," ",m("diagnostics-pause")]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:k,onChange:T=>C(T.target.checked)})," ",m("diagnostics-autoscroll")]})]}),c.jsx("pre",{ref:Z,className:"nc-diag-log","aria-label":m("diagnostics-log"),children:I||m("diagnostics-empty")}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:E,children:m("copy")}),c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:D,children:m("diagnostics-export")}),c.jsx("button",{type:"button",className:"nc-btn danger",disabled:n,onClick:()=>{window.confirm(m("diagnostics-clear-confirm"))&&M(async()=>{const T=await F0(e,u.route);return z.current=0,v([]),T})},children:m("diagnostics-clear")})]}),S&&c.jsx("div",{className:"nc-err",children:S})]})}function _j({token:e,settings:t,readonly:n,refresh:s,roster:o,section:a,setSection:u}){const[h,f]=N.useState(null),[p,v]=N.useState(null),[S,y]=N.useState(!1),[w,b]=N.useState(!1),[k,C]=N.useState(null),[j,x]=N.useState(!0),[F,B]=N.useState(!1);N.useEffect(()=>{C(t&&t.update||null),x(!t||t.autoUpdate!==!1),B(!!(t&&t.alternateScreen))},[t]);const Y=async()=>{f(null),v(null),b(!0);try{const E=await w0(e);v(E.note||"ok"),y(!1)}catch(E){f(String(E.message||E))}b(!1)},V=async()=>{f(null),v(null),b(!0);try{const E=await M0(e);v(`${E.note||"ok"}${E.target?` (${E.target})`:""}`)}catch(E){f(String(E.message||E))}b(!1)},z=async E=>{f(null),v(null),b(!0);try{await $d(e,{autoUpdate:E}),x(E),s&&await s()}catch(D){f(String(D.message||D))}b(!1)},Z=async E=>{f(null),v(null),b(!0);try{await $d(e,{alternateScreen:E}),B(E),s&&await s()}catch(D){f(String(D.message||D))}b(!1)},q=async()=>{f(null),v(null),b(!0);try{C(await I0(e))}catch(E){f(String(E.message||E))}b(!1)},G=async()=>{f(null),v(null),b(!0);try{const E=await O0(e);C(E),v(m("npm-update-restarting"))}catch(E){f(String(E.message||E))}b(!1)},I=()=>{window.confirm(m("composer-clear-confirm"))&&(f(null),ME()?(window.dispatchEvent(new Event(Ah)),v(m("composer-clear-done"))):f(m("composer-clear-failed")))},M=t&&t.service;return c.jsxs("div",{className:"nc-set-tab",children:[c.jsx("div",{className:"nc-system-tabs",role:"tablist","aria-label":m("tab-system"),children:["general","diagnostics"].map(E=>c.jsx("button",{type:"button",role:"tab","aria-selected":a===E,className:`nc-set-tabbtn${a===E?" on":""}`,onClick:()=>u(E),children:m(`system-${E}`)},E))}),a==="general"&&c.jsxs(c.Fragment,{children:[c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-this-node")}),t&&c.jsxs("div",{className:"nc-set-info",children:["v",t.version," · ",t.platform," · :",t.port,c.jsx("br",{}),M&&M.installed?m("service-installed"):m("service-missing"),M&&M.installed?` · ${M.active?m("service-active"):m("service-inactive")}`:"",M?` · boot ${M.boot?"on":"off"}`:""]}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w,title:n?m("settings-readonly"):"",onClick:V,children:m("service-regenerate")})}),c.jsx(fj,{token:e,readonly:n}),c.jsx(pj,{})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-updates")}),c.jsxs("div",{className:"nc-set-form nc-update-settings",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:j,disabled:n||w||k&&!k.supported,onChange:E=>z(E.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("npm-auto-update")}),c.jsx("small",{children:m("npm-auto-update-help")})]})]}),k&&c.jsxs("div",{className:"nc-set-info",children:[m("npm-update-current")," v",k.current,k.latest?` · ${m("npm-update-latest")} v${k.latest}`:""," · ",m(`npm-update-${k.supported?k.phase:"unsupported"}`)]}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w||!k||!k.supported,onClick:q,children:m("npm-update-check")}),k&&k.available&&c.jsx("button",{type:"button",className:"nc-btn primary",disabled:n||w||k.phase==="installing",onClick:G,children:m("npm-update-install")})]}),k&&k.lastError&&c.jsx("div",{className:"nc-err",children:k.lastError})]})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-security")}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w,title:n?m("settings-readonly"):"",onClick:()=>{f(null),v(null),y(!0)},children:m("token-rotate")})})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-local-data")}),c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("composer-clear-data")}),c.jsx("small",{className:"nc-set-hint",children:m("composer-clear-data-help")}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:I,children:m("composer-clear-data")})})]})]})]}),a==="diagnostics"&&c.jsxs("section",{className:"nc-system-group nc-system-diagnostics",children:[c.jsx("h3",{children:m("system-diagnostics")}),c.jsxs("div",{className:"nc-set-form nc-alternate-screen-settings",children:[c.jsx("div",{className:"nc-sheet-label",children:m("system-terminal")}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox","aria-label":m("alternate-screen"),checked:F,disabled:n||w,onChange:E=>Z(E.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("alternate-screen")}),c.jsx("small",{children:m("alternate-screen-help")})]})]})]}),c.jsx(vj,{token:e,roster:o,readonly:n})]}),S&&c.jsxs("div",{className:"nc-set-confirm",children:[c.jsx("div",{children:m("token-rotate-explain")}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:w,onClick:()=>y(!1),children:m("cancel")}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:w,onClick:Y,children:m("confirm")})]})]}),p&&c.jsx("div",{className:"nc-set-note",children:p}),h&&c.jsx("div",{className:"nc-err",children:h})]})}function yj({token:e,onClose:t,initialTab:n="nodes",initialLocation:s="",startNewCell:o=!1}){Tn();const a=n==="diagnostics"?"diagnostics":"general",[u,h]=N.useState(n==="diagnostics"?"system":n),f=N.useRef(null),p=N.useRef(null),[v,S]=N.useState({start:!1,end:!1}),[y,w]=N.useState(a),[b,k]=N.useState(null),[C,j]=N.useState([]),[x,F]=N.useState(!1),[B,Y]=N.useState(null),[V,z]=N.useState(0),Z=ef(e,!0,V),q=N.useCallback(()=>{const I=f.current;if(!I)return;const M=I.scrollWidth>I.clientWidth+1,E={start:M&&I.scrollLeft>1,end:M&&I.scrollLeft+I.clientWidth<I.scrollWidth-1};S(D=>D.start===E.start&&D.end===E.end?D:E)},[]);N.useEffect(()=>{const I=f.current;if(!I)return;const M=typeof ResizeObserver=="function"?new ResizeObserver(q):null;return M==null||M.observe(I),window.addEventListener("resize",q),q(),()=>{M==null||M.disconnect(),window.removeEventListener("resize",q)}},[q]),N.useEffect(()=>{var M,E;(E=(M=p.current)==null?void 0:M.scrollIntoView)==null||E.call(M,{behavior:"smooth",block:"nearest",inline:"nearest"});const I=window.requestAnimationFrame?window.requestAnimationFrame(q):setTimeout(q,0);return()=>{window.cancelAnimationFrame?window.cancelAnimationFrame(I):clearTimeout(I)}},[u,q]);const G=N.useCallback(async()=>{try{const I=await Q_(e);k(I),Y(null)}catch(I){Y(String(I.message||I))}try{const M=(await g0(e)).peers||[];let E=[];try{E=((await v0(e)).nodes||[]).map(g2).filter(Boolean)}catch{}j([...M,...E])}catch(I){Y(String(I.message||I))}},[e]);return N.useEffect(()=>{G();const I=setInterval(G,5e3);return()=>clearInterval(I)},[G]),N.useEffect(()=>{let I=!1;return Yt("/api/config",e).then(M=>M.json()).then(M=>{I||F(!!M.readonlyDefault)}).catch(()=>{}),()=>{I=!0}},[e]),c.jsx("div",{className:"nc-set-overlay",onClick:t,children:c.jsxs("div",{className:"nc-set-panel",onClick:I=>I.stopPropagation(),children:[c.jsxs("div",{className:"nc-set-head",children:[c.jsx(et,{name:"gear",size:18}),c.jsx("b",{children:m("settings")}),c.jsx("button",{type:"button",className:"nc-set-close",onClick:t,title:m("close"),children:c.jsx(et,{name:"x",size:18})})]}),x&&c.jsx("div",{className:"nc-set-readonly",children:m("settings-readonly")}),B&&c.jsx("div",{className:"nc-err",children:B}),c.jsx("div",{className:`nc-set-tabs-wrap${v.start?" has-start-overflow":""}${v.end?" has-end-overflow":""}`,children:c.jsx("div",{className:"nc-set-tabs",ref:f,onScroll:q,children:["nodes","fleet","audio","input","system"].map(I=>c.jsx("button",{ref:u===I?p:null,type:"button",className:`nc-set-tabbtn${u===I?" on":""}`,onClick:()=>h(I),children:m(`tab-${I}`)},I))})}),c.jsxs("div",{className:"nc-set-body",children:[u==="nodes"&&c.jsx(hj,{token:e,nodes:C,roster:Z,settings:b,readonly:x,refresh:G,refreshAliases:()=>z(I=>I+1)}),u==="fleet"&&c.jsx(V2,{token:e,readonly:x,startNewCell:o,initialLocation:s,targets:Z.map(I=>({route:I.route,label:I.label||I.name,status:I.status}))}),u==="audio"&&c.jsx(mj,{token:e,readonly:x,nodes:C,settings:b}),u==="input"&&c.jsx(gj,{}),u==="system"&&c.jsx(_j,{token:e,settings:b,readonly:x,refresh:G,roster:Z,section:y,setSection:w})]})]})})}function wj({token:e,initialPair:t,deviceDefault:n="",localNodeId:s="",localNameDefault:o="",onPairDone:a,onDone:u}){Tn();const[h,f]=N.useState(t?"pair":"welcome"),[p,v]=N.useState(!1),[S,y]=N.useState(null),w=async()=>{v(!0),y(null);try{await $d(e,{wizardDone:!0}),a&&a(),u()}catch(b){y(String(b.message||b)),v(!1)}};return c.jsx("div",{className:"nc-wiz-overlay",children:c.jsxs("div",{className:"nc-wiz",children:[c.jsxs("div",{className:"nc-wiz-head",children:[c.jsx("b",{children:m("wizard-title")}),c.jsx("small",{children:m("hydra-simple")})]}),h==="welcome"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx("div",{className:"nc-wiz-done",children:m("local-ready")}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",disabled:p,onClick:w,children:m("local-only")}),c.jsx("button",{className:"nc-btn primary",disabled:p,onClick:()=>f("pair"),children:m("add-node")})]})]}),h==="pair"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx($w,{token:e,initial:t||"",autoStart:!!t,deviceDefault:n,localNodeId:s,localNameDefault:o,onBusyChange:v,onSuccess:async()=>{a&&a(),f("done")}}),c.jsx("div",{className:"nc-sheet-actions",children:c.jsx("button",{className:"nc-btn ghost",disabled:p,onClick:()=>{a&&a(),f("welcome")},children:m("back")})})]}),h==="done"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx("div",{className:"nc-wiz-done",children:m("node-connected")}),c.jsx("div",{className:"nc-sheet-actions",children:c.jsx("button",{className:"nc-btn primary",disabled:p,onClick:w,children:m("finish")})})]}),S&&c.jsx("div",{className:"nc-err",children:S})]})})}function bj(e,t){if(typeof EventSource>"u"||!e)return()=>{};const n=new EventSource(`/api/events?token=${encodeURIComponent(e)}`);return n.onmessage=s=>{try{const o=JSON.parse(s.data);o&&typeof o=="object"&&typeof o.type=="string"&&t(o)}catch{}},()=>{try{n.close()}catch{}}}const Sj=6e3,kj=12e3;function xj({n:e,onClose:t}){return c.jsxs("div",{className:`nc-ntf-toast${e.urgency==="high"?" high":""}`,role:"status","aria-live":"polite",children:[c.jsxs("div",{className:"nc-ntf-toast-txt",children:[c.jsx("b",{children:e.title}),e.body&&c.jsx("small",{children:e.body}),e.session&&c.jsx("span",{className:"nc-ntf-from",children:e.session})]}),c.jsx("button",{type:"button",className:"nc-ntf-x",onClick:t,title:m("close"),children:c.jsx(et,{name:"x",size:14})})]})}function Cj({ask:e,token:t,onAnswered:n}){const[s,o]=N.useState(""),[a,u]=N.useState(!1),[h,f]=N.useState(null),p=async v=>{const S=String(v||"").trim();if(!(!S||a)){f(null),u(!0);try{await H0(t,e.id,S),n(e.id)}catch(y){f(String(y.message||y))}u(!1)}};return c.jsxs("div",{className:"nc-ask-card",children:[c.jsxs("div",{className:"nc-ask-head",children:[c.jsx("span",{className:"nc-ntf-from",children:e.session}),c.jsxs("code",{className:"nc-ask-id",children:["#",e.id]})]}),c.jsx("div",{className:"nc-ask-q",children:e.question}),Array.isArray(e.options)&&e.options.length>0&&c.jsx("div",{className:"nc-ask-opts",children:e.options.map(v=>c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:a,onClick:()=>p(v),children:v},v))}),c.jsxs("div",{className:"nc-ask-reply",children:[c.jsx("textarea",{rows:2,placeholder:m("ask-reply-ph"),value:s,disabled:a,onChange:v=>o(v.target.value)}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:a||!s.trim(),onClick:()=>p(s),children:m("send")})]}),h&&c.jsx("div",{className:"nc-err",children:h})]})}function Ej({token:e}){const[t]=Tn(),[n]=ib(),[s,o]=N.useState([]),[a,u]=N.useState([]),[h,f]=N.useState(()=>{try{return/(?:^|[#&])ask=/.test(location.hash)}catch{return!1}}),p=N.useRef(0),v=N.useRef(null);v.current||(v.current=cj());const S=N.useRef({enabled:n,lang:t});S.current={enabled:n,lang:t};const y=N.useCallback(k=>{o(C=>C.filter(j=>j.key!==k))},[]),w=N.useCallback(k=>{const C=`t${p.current+=1}`;o(x=>[...x.slice(-3),{...k,key:C}]),setTimeout(()=>y(C),k.urgency==="high"?kj:Sj);const j=S.current;if(j.enabled)try{v.current.enqueue(k,sj(k,j.lang))}catch{}},[y]);N.useEffect(()=>{n||v.current.stop()},[n]),N.useEffect(()=>{const k=()=>{(document.visibilityState!=="visible"||!document.hasFocus())&&v.current.stop()},C=()=>v.current.stop();return document.addEventListener("visibilitychange",k),window.addEventListener("blur",k),window.addEventListener(Bh,C),()=>{document.removeEventListener("visibilitychange",k),window.removeEventListener("blur",k),window.removeEventListener(Bh,C),typeof v.current.dispose=="function"?v.current.dispose():v.current.stop()}},[]),N.useEffect(()=>{if(!e)return;let k=!1;$0(e).then(j=>{k||u(j.asks||[])}).catch(()=>{});const C=bj(e,j=>{j.type==="notify"?w(j):j.type==="ask"&&j.ask&&j.ask.id?u(x=>x.some(F=>F.id===j.ask.id)?x:[...x,j.ask]):j.type==="ask-answered"&&j.id&&u(x=>x.filter(F=>F.id!==j.id))});return()=>{k=!0,C()}},[e,w]);const b=k=>u(C=>C.filter(j=>j.id!==k));return c.jsxs(c.Fragment,{children:[s.length>0&&c.jsx("div",{className:"nc-ntf-toasts",children:s.map(k=>c.jsx(xj,{n:k,onClose:()=>y(k.key)},k.key))}),a.length>0&&!h&&c.jsxs("button",{type:"button",className:"nc-ask-badge",onClick:()=>f(!0),title:m("asks-title"),children:["? ",c.jsx("span",{className:"nc-ask-count",children:a.length})]}),a.length>0&&h&&c.jsxs("div",{className:"nc-ask-panel",children:[c.jsxs("div",{className:"nc-ask-panel-head",children:[c.jsx("b",{children:m("asks-title")}),c.jsx("span",{className:"nc-ask-count",children:a.length}),c.jsx("button",{type:"button",className:"nc-ntf-x",onClick:()=>f(!1),title:m("close"),children:c.jsx(et,{name:"x",size:16})})]}),c.jsx("div",{className:"nc-ask-panel-body",children:a.map(k=>c.jsx(Cj,{ask:k,token:e,onAnswered:b},k.id))})]})]})}const Nj=4e3;async function jj(e){const t=await Yt("/api/sessions",e);if((t==null?void 0:t.ok)===!1)throw new Error(`HTTP ${t.status}`);const n=await t.json();if(!Array.isArray(n==null?void 0:n.sessions))throw new Error("invalid sessions payload");return n.sessions}async function Bd(e,t=[]){var h;const[n,s]=await Promise.allSettled([t.length?Xh(e,t):jj(e),ys(e,t)]),o=n.status==="fulfilled"&&Array.isArray((h=n.value)==null?void 0:h.sessions)?n.value.sessions:Array.isArray(n.value)?n.value:null,a=s.status==="fulfilled"?s.value:null,u=(a==null?void 0:a.available)===!0&&Array.isArray(a.cells)?a.cells:null;return{sessions:o,cells:u,fresh:Array.isArray(o)&&Array.isArray(u)}}function sb(e,t,n){return n===!0&&(e==null?void 0:e.degraded)!==!0&&(e==null?void 0:e.active)===!0&&e.tmux!==!1&&!!e.tmuxSession&&(t||[]).some(s=>(s==null?void 0:s.name)===e.tmuxSession)}function Rj(e){const t=new Map((e.sessions||[]).map(o=>[o.name,o])),n=[],s=(o,a,u,h=[],f="")=>{const p=new Map((a||[]).map(v=>[v.name,v]));for(const v of o||[]){const S=p.get(v.tmuxSession)||{},y=sf(v,S),w=sb(v,a,u);n.push({key:Vo(h,v.tmuxSession||v.cell),session:v.tmuxSession,route:h,cellName:v.cell,label:v.cell,node:h.length?h.join("/"):"",nodeLabel:f,live:w,selectable:w,verified:u===!0,working:y.working,degraded:!!v.degraded,activity:S.activity||v.activity||0,subtitle:y.subtitle})}};s(e.cells,[...t.values()],e.localFresh===!0);for(const o of e.nodeGroups||[])s(o.cells,o.sessions,o.switcherFresh===!0,Array.isArray(o.route)?o.route:[],o.label||o.name||"");return n}function Pj(e){const t=new Map,n=Array.isArray(e.sessions)?e.sessions:[],s=Array.isArray(e.cells)?e.cells:[],o=new Map(n.map(u=>[u.name,u])),a=new Set(s.map(u=>u.tmuxSession).filter(Boolean));t.set("local",rf(s,n.filter(u=>!a.has(u.name)),o));for(const u of e.nodeGroups||[]){const h=Array.isArray(u.route)?u.route:[];if(!h.length)continue;const f=Array.isArray(u.cells)?u.cells:[],p=Array.isArray(u.sessions)?u.sessions:[],v=new Set(f.map(S=>S.tmuxSession).filter(Boolean));t.set(h.join("/"),Fl({...u,route:h,cells:f,sessions:p,unmanaged:p.filter(S=>!v.has(S.name))}).rawItems)}return t}function Lj(e,t,n,s){return[...new Set(e.map(a=>a.node||"local"))].flatMap(a=>{const u=e.filter(v=>(v.node||"local")===a),h=new Map((t.get(a)||[]).map(v=>[v.key,v])),f=new Map(u.map(v=>[v.key,v])),p=u.map(v=>{const S=h.get(v.key);return{...v,label:(S==null?void 0:S.label)||v.label,live:(S==null?void 0:S.live)??v.live,fresh:(S==null?void 0:S.fresh)===!0,activity:(S==null?void 0:S.activity)??v.activity}});return ms(p,n,"all",zi(s,a)).map(v=>f.get(v.key))})}function Aj({token:e,current:t,onPick:n,onClose:s}){const[o,a]=N.useState(Mg),[u,h]=N.useState(!1),[f,p]=N.useState(!1),[v,S]=N.useState(""),[y,w]=N.useState(""),[b,k]=N.useState(""),C=N.useRef(null),j=N.useRef(null),x=N.useMemo(()=>Rj(o),[o]),F=N.useMemo(()=>Pj(o),[o]),{pins:B,orders:Y,canMoveRoster:V,moveRoster:z,stepRoster:Z}=nf(),q=N.useMemo(()=>Lj(x,F,B,Y),[x,F,B,Y]),G=N.useMemo(()=>u?q:q.filter(T=>T.selectable||T.degraded),[q,u]),I=N.useMemo(()=>x.find(T=>T.key===y&&T.selectable),[x,y]);N.useEffect(()=>{var W;const T=document.activeElement;(W=j.current)==null||W.focus();const $=R=>{R.key==="Escape"&&s()};return document.addEventListener("keydown",$),()=>{var R;document.removeEventListener("keydown",$),(R=T==null?void 0:T.focus)==null||R.call(T)}},[s]),N.useEffect(()=>{let T=!0,$=!1;const W=async()=>{if($)return;$=!0;const K=Mg(),A=Array.isArray(K.nodeGroups)?K.nodeGroups:[],L=Bd(e),O=await Promise.all(A.map(async pe=>{const me=Array.isArray(pe.route)?pe.route:[];return me.length?{group:pe,result:await Bd(e,me)}:{group:pe,result:{fresh:!1,sessions:null,cells:null}}})),X=await L;if(!T)return;const ne=new Map(O.map(({group:pe,result:me})=>[JSON.stringify(pe.route||[]),me])),ce=A.map(pe=>{const me=ne.get(JSON.stringify(pe.route||[]));return me?{...pe,sessions:me.sessions||pe.sessions||[],cells:me.cells||pe.cells||[],switcherFresh:me.fresh}:{...pe,switcherFresh:!1}}),fe=py({...K,sessions:X.sessions||K.sessions||[],cells:X.cells||K.cells||[],localFresh:X.fresh,nodeGroups:ce,refreshedAt:Date.now()});a(fe),p(!0),$=!1};W();const R=setInterval(W,Nj);return()=>{T=!1,clearInterval(R)}},[e]);const M=T=>T.degraded?m("cell-degraded"):T.verified?T.selectable?T.working?m("cell-working"):m("cell-idle"):m("cell-off"):m("cell-switcher-not-confirmed"),E=T=>{if(S(""),!T.selectable){S(m("cell-switcher-not-active"));return}w(T.key)},D=async()=>{const T=I;if(!T){S(m("cell-switcher-select"));return}S(""),k(T.key);try{const $=await Bd(e,T.route),W=($.cells||[]).find(R=>(R==null?void 0:R.cell)===T.cellName&&(R==null?void 0:R.tmuxSession)===T.session);if(!sb(W,$.sessions,$.fresh)){S(m("cell-switcher-not-active"));return}n({session:T.session,...T.node?{node:T.node}:{},cellName:T.cellName}),s()}catch{S(m("cell-switcher-not-active"))}finally{k("")}};return c.jsx("div",{className:"nc-cell-switcher-backdrop",onClick:s,children:c.jsxs("aside",{ref:C,className:"nc-cell-switcher",role:"dialog","aria-label":m("fleet-cells"),tabIndex:-1,onClick:T=>T.stopPropagation(),children:[c.jsxs("div",{className:"nc-cell-switcher-list",children:[!f&&c.jsx("div",{className:"nc-empty",role:"status",children:m("cell-switcher-refreshing")}),f&&G.length===0&&c.jsx("div",{className:"nc-empty",role:"status",children:m("cell-switcher-empty-active")}),G.map(T=>{const $=(t==null?void 0:t.session)===T.session&&((t==null?void 0:t.node)||"")===T.node,W=y===T.key,R=M(T),K=T.node||"local",A=F.get(K)||x.filter(L=>(L.node||"local")===K);return c.jsxs("div",{className:`nc-cell-switcher-row${$?" current":""}${W?" selected":""}${T.selectable?"":" off"}`,"data-roster-key":T.key,"data-position":K,children:[c.jsx(Oi,{position:K,itemKey:T.key,label:T.cellName,canMove:V,onMove:(L,O)=>z(K,L,O,A),onStep:L=>Z(K,T.key,L,A)}),c.jsxs("button",{type:"button",className:"nc-cell-switcher-row-select","aria-current":$?"true":void 0,"aria-pressed":W,"aria-disabled":!T.selectable,disabled:b===T.key,onClick:()=>E(T),children:[c.jsx("span",{className:`nc-cell-switcher-dot${T.degraded?" warn":T.live?` on${T.working?" working":""}`:""}`}),c.jsxs("span",{className:"nc-cell-switcher-copy",children:[c.jsx("b",{children:T.cellName}),c.jsx("small",{className:"nc-cell-switcher-state",children:R}),c.jsx("small",{children:[T.nodeLabel,T.subtitle].filter(Boolean).join(" · ")})]})]})]},T.key)})]}),v&&c.jsx("div",{className:"nc-cell-switcher-notice",role:"status",children:v}),c.jsx("div",{className:"nc-cell-switcher-actions",children:c.jsx("button",{type:"button",className:"nc-cell-switcher-open",disabled:!I||!!b,onClick:D,children:I?`${m("cell-switcher-open")}: ${I.cellName}`:m("cell-switcher-select")})}),c.jsxs("div",{className:"nc-cell-switcher-controls",children:[c.jsx("b",{children:m("fleet-cells")}),c.jsx("button",{type:"button",className:"nc-cell-switcher-filter","aria-pressed":u,onClick:()=>{S(""),h(T=>!T)},children:m(u?"cell-switcher-show-active":"cell-switcher-show-all")}),c.jsx("button",{ref:j,type:"button",className:"nc-cell-switcher-close","aria-label":m("cell-switcher-close"),title:m("cell-switcher-close"),onClick:s,children:"×"})]})]})})}const zd=e=>ki(qs(e)).length===0,Fd=e=>Array.isArray(e)?e.join("/"):"";function Tj(e){const t=new Set,n=[];for(const s of Array.isArray(e)?e:[])!s||!Hn.test(String(s.instanceId||""))||!Array.isArray(s.route)||!s.route.length||t.has(s.instanceId)||(t.add(s.instanceId),n.push({instanceId:s.instanceId,route:[...s.route],label:String(s.label||s.name||s.route.join(" › ")),status:s.status||"offline"}));return n.sort((s,o)=>s.label.localeCompare(o.label))}function Bo(e){return{instanceId:e.ownerId,route:e.ownerRoute||[],label:e.ownerLabel,status:e.available===!1?"offline":"up"}}function Fs(e,t,n,s=!1,o=!0){const a=t.instanceId;return{...e,id:Pr(s?null:a,e.name),ownerId:a,ownerRoute:s?[]:[...t.route],ownerLabel:s?"Local":t.label,local:s,available:o,ownerTopology:Array.isArray(n)?n:[],layout:Dh(e.layout,a,n)}}function Dj(e,t,n,s,o=[]){const[a,u]=N.useState([]),[h,f]=N.useState(!1),[p,v]=N.useState("idle"),[S,y]=N.useState(""),[w,b]=N.useState(""),k=N.useRef([]),C=N.useRef([]),j=N.useRef(""),x=N.useRef(t),F=N.useRef(n),B=N.useRef(!1),Y=N.useRef(!0),V=N.useRef(""),z=N.useMemo(()=>Tj(o),[o]),Z=z.map(A=>`${A.instanceId}:${Fd(A.route)}:${A.status}:${A.label}`).join("|");C.current=z,F.current=n,x.current=t,k.current=a;const q=N.useCallback(A=>Mh(A.layout,j.current,C.current),[]),G=N.useCallback((A,L=!0,O=x.current)=>{const X=Vv(A,Sl()),ne=k.current.some(fe=>fe.id===O);k.current=X,u(X);const ce=X.find(fe=>fe.id===O);if(L&&ce){Y.current=!0;const fe=q(ce);s(fe),ce.local&&rN(ce.name,fe)}else ne&&!ce&&(Y.current=!0,s(Rr()),y("deck non più condiviso dal nodo owner"));tN(X.filter(fe=>fe.local).map(fe=>fe.name))},[s,q]),I=N.useCallback(async A=>{let L=await fl(e);const O=L.decks.find(X=>X.name==="main");if(L.decks.length===1&&O&&O.revision===0&&zd(O.layout)){const X=eN(),ne=qs(Ih("main")||Rr());if(!zd(ne)){const ce=Dh(ne,A,[]);L.decks[0]=await pl(e,"main",ce,0,[])}for(const ce of X.filter(fe=>fe!=="main"))try{let fe=await Sg(e,ce,[]);const pe=qs(Ih(ce)||Rr());zd(pe)||(fe=await pl(e,ce,Dh(pe,A,[]),fe.revision,[]))}catch{}L=await fl(e)}return L},[e]),M=N.useCallback(async({migrate:A=!1}={})=>{const L=await Qh(e,[]),O=Hn.test(String(L.instanceId||""))?L.instanceId:"";if(!O)throw new Error("instanceId locale non disponibile");j.current=O,b(O);const[X,ne]=await Promise.all([A?I(O):fl(e),_g(e,[]).catch(()=>({nodes:[]}))]),ce={instanceId:O,route:[],label:"Local"},fe=X.decks.map(me=>Fs(me,ce,ne.nodes,!0,!0)),pe=k.current;return await Promise.all(C.current.map(async me=>{if(me.status!=="up"){fe.push(...pe.filter(le=>!le.local&&le.ownerId===me.instanceId).map(le=>({...le,ownerRoute:[...me.route],ownerLabel:me.label,available:!1})));return}try{const[le,Ie]=await Promise.all([fl(e,me.route),_g(e,me.route).catch(()=>({nodes:[]}))]);fe.push(...le.decks.map(st=>Fs(st,me,Ie.nodes,!1,!0)))}catch{fe.push(...pe.filter(Ie=>!Ie.local&&Ie.ownerId===me.instanceId).map(Ie=>({...Ie,ownerRoute:[...me.route],ownerLabel:me.label,available:!1})))}})),fe.sort((me,le)=>me.local===le.local?me.ownerLabel.localeCompare(le.ownerLabel)||(me.name==="main"?-1:le.name==="main"?1:me.name.localeCompare(le.name)):me.local?-1:1),fe},[e,I,Z]);N.useEffect(()=>{if(!e)return;let A=!1;const L=V.current!==e;return V.current=e,M({migrate:L}).then(O=>{if(A)return;const X=k.current.find(fe=>fe.id===x.current),ne=O.find(fe=>fe.id===x.current),ce=ne&&(!X||ne.revision>X.revision||X.available!==ne.available||Fd(X.ownerRoute)!==Fd(ne.ownerRoute));G(O,L||!!ce&&!B.current),f(!0),ne&&y("")}).catch(O=>{A||(f(!0),y(String(O.message||O)))}),()=>{A=!0}},[G,M,Z,e]);const E=N.useCallback(async(A=x.current)=>{if(!h||!B.current)return!0;const L=k.current.find(O=>O.id===A);if(!L)return y(`deck inesistente: ${A}`),!1;if(L.available===!1)return y(`nodo owner offline: ${L.ownerLabel}`),!1;v("saving");try{const O=Kv(qs(F.current),L.ownerId,L.ownerTopology),X=await pl(e,L.name,O,L.revision,L.ownerRoute),ne=Fs(X,Bo(L),L.ownerTopology,L.local,!0);return G(k.current.map(ce=>ce.id===A?ne:ce),!1),B.current=!1,v("saved"),y(""),setTimeout(()=>v("idle"),1500),!0}catch(O){if(v("error"),y(String(O.message||O)),O.status===409&&O.data&&O.data.current){const X=k.current.find(ce=>ce.id===A),ne=Fs(O.data.current,Bo(X),X.ownerTopology,X.local,!0);G(k.current.map(ce=>ce.id===A?ne:ce),!1)}return!1}},[h,e,G]);return N.useEffect(()=>{if(!h)return;if(Y.current){Y.current=!1;return}B.current=!0,v("saving");const A=setTimeout(E,650);return()=>clearTimeout(A)},[n,h,E]),N.useEffect(()=>{if(!h)return;const A=setInterval(async()=>{try{const L=await M(),O=k.current.find(ce=>ce.id===x.current),X=L.find(ce=>ce.id===x.current),ne=X&&(!O||X.revision>O.revision||O.available!==X.available);G(L,ne&&!B.current)}catch{}},5e3);return()=>clearInterval(A)},[h,M,G]),{decks:a,records:a,localNodeId:w,ready:h,saveState:p,error:S,setError:y,saveNow:E,select:async A=>{if(B.current&&!await E(x.current))throw new Error("salvataggio del deck corrente fallito: cambio annullato");const L=k.current.find(O=>O.id===A);if(!L)throw new Error(`deck inesistente: ${A}`);return B.current=!1,Y.current=!0,q(L)},add:async(A,L=null)=>{const O=L===bi?k.current.find(ce=>ce.local):L?k.current.find(ce=>ce.ownerId===L):null;if(!O||O.available===!1)throw new Error("nodo owner non disponibile");const X=await Sg(e,A,O.ownerRoute),ne=Fs(X,Bo(O),O.ownerTopology,O.local,!0);return G([...k.current,ne],!1),ne},rename:async(A,L)=>{const O=k.current.find(pe=>pe.id===A);if(!O)throw new Error("deck inesistente");if(A===x.current&&B.current&&!await E(A))throw new Error(`salvataggio di "${O.name}" fallito: rinomina annullata`);const X=k.current.find(pe=>pe.id===A);if(!X)throw new Error("deck inesistente");const ne=await W0(e,X.name,L,X.revision,X.ownerRoute),ce=Fs(ne,Bo(X),X.ownerTopology,X.local,!0),fe=X.local?bi:X.ownerId;return hd(iN(Sl(),fe,A,ce.id)),G(k.current.map(pe=>pe.id===A?ce:pe),!1),ce},remove:async A=>{const L=k.current.find(X=>X.id===A);if(!L)throw new Error("deck inesistente");A===x.current&&(B.current=!1),await U0(e,L.name,L.revision,L.ownerRoute);const O=L.local?bi:L.ownerId;hd(sN(Sl(),O,A)),G(k.current.filter(X=>X.id!==A),!1)},reorder:(A,L)=>{const O=k.current.find(me=>me.id===A),X=k.current.find(me=>me.id===L);if(!O||!X)return!1;const ne=O.local?bi:O.ownerId,ce=X.local?bi:X.ownerId;if(ne!==ce)return!1;const fe=k.current.filter(me=>(me.local?bi:me.ownerId)===ne).map(me=>me.id),pe=hd(nN(Sl(),ne,A,L,fe));return G(Vv(k.current,pe),!1),!0},addTileTo:async(A,L)=>{const O=k.current.find(me=>me.id===A);if(!O)throw new Error("deck inesistente");if(O.available===!1)throw new Error(`nodo owner offline: ${O.ownerLabel}`);const X=kw(L,j.current,C.current);if(!X)throw new Error("riferimento sessione non valido");const ne=q(O),ce=Kv(dy(ne,X),O.ownerId,O.ownerTopology),fe=await pl(e,O.name,ce,O.revision,O.ownerRoute),pe=Fs(fe,Bo(O),O.ownerTopology,O.local,!0);return G(k.current.map(me=>me.id===A?pe:me),!1),pe},localMainId:Pr(null,"main"),parseDeckId:sc}}const Mj="/sw.js",Fh="nc-sw-update";let $h=null,Hh=!1,Wh=null,rb=Object.freeze({needed:!1,kind:null,version:""}),ob=!1;function ab(){typeof window<"u"&&window.dispatchEvent(new Event(Fh))}function lb(){const e=Wh||(Hh?{kind:"reload",version:""}:null);rb=Object.freeze({needed:!!e,kind:(e==null?void 0:e.kind)||null,version:(e==null?void 0:e.version)||""})}function B_(){return rb}function Ij(e){return typeof window>"u"?()=>{}:(window.addEventListener(Fh,e),()=>window.removeEventListener(Fh,e))}function Bf(e){Hh!==e&&(Hh=e,lb(),ab())}function Oj(e,t,n){let s=null;e&&t&&e!==t?s={kind:"install",version:e}:t&&n&&t!==n&&(s={kind:"reload",version:t});const o=JSON.stringify(s)===JSON.stringify(Wh);Wh=s,lb(),o||ab()}function Bj(e){e.addEventListener("statechange",()=>{e.state==="installed"&&navigator.serviceWorker.controller&&Bf(!0)})}function zj(){typeof navigator>"u"||!("serviceWorker"in navigator)||(navigator.serviceWorker.addEventListener("controllerchange",()=>{ob&&location.reload()}),navigator.serviceWorker.register(Mj).then(e=>{$h=e,e.waiting&&Bf(!0),e.addEventListener("updatefound",()=>{const t=e.installing;t&&Bj(t)}),setInterval(()=>{e.update().catch(()=>{})},3600*1e3)}).catch(()=>{}))}function Fj(){ob=!0,Bf(!1);const e=$h&&$h.waiting;e?(e.postMessage({type:"SKIP_WAITING"}),setTimeout(()=>location.reload(),4e3)):location.reload()}function $j({hash:e="",origin:t="",pathname:n="",search:s=""}={}){const o=String(e||"").replace(/^#/,""),a=`${n||""}${s||""}`;if(!o)return{token:"",pair:"",nextUrl:a};const u=new URLSearchParams(o),h=u.get("token")||"",f=u.get("pair")||"",p=f?`${t||""}${n||""}#pair=${f}`:"";return{token:h,pair:p,nextUrl:a}}const cb=9,ub=24,db="nc_side_w",z_="nc_side_min",Hj=240,F_="(min-width:1024px) and (pointer:fine)";function Wj(){const e=Number(localStorage.getItem(db));return e>=180&&e<=480?e:Hj}function Uj(){const e=Number(localStorage.getItem("nc_fontsize"));return e>=cb&&e<=ub?e:13}function Kj(){const e={token:"",pair:""};try{const{token:t,pair:n,nextUrl:s}=$j({hash:location.hash,origin:location.origin,pathname:location.pathname,search:location.search});if(t){e.token=t;try{localStorage.setItem("nc_token",t)}catch{}}if(n){e.pair=n;try{sessionStorage.setItem("nc_pair",n)}catch{}}if(location.hash)try{history.replaceState(null,"",s)}catch{}}catch{}if(e.token||(e.token=sessionStorage.getItem("nc_token")||localStorage.getItem("nc_token")||""),!e.pair){const t=sessionStorage.getItem("nc_pair");t&&(e.pair=t)}return e}function qj(e){try{return qs(Ih(e))}catch{return Rr()}}function $_(e){if(!e)return"";const t=Math.floor(Date.now()/1e3)-e;return t<0||t<60?"ora":t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}g`}function Vj(){const[e,t]=N.useState(()=>window.matchMedia(F_).matches);return N.useEffect(()=>{const n=window.matchMedia(F_),s=o=>t(o.matches);return n.addEventListener("change",s),()=>n.removeEventListener("change",s)},[]),e}function H_({session:e,node:t,ownerId:n,cellName:s,token:o,readonly:a=!1,onBack:u,onCellSwitcher:h,cellSwitcherOpen:f=!1}){Tn();const[p]=Sf(),[v,S]=N.useState(!1),[y,w]=N.useState(()=>window.matchMedia("(pointer: coarse)").matches),[b,k]=N.useState(null),[C,j]=N.useState(Uj),[x,F]=N.useState(s||e),[B,Y]=N.useState(""),V=$=>j(W=>{const R=Math.max(cb,Math.min(ub,W+$));return localStorage.setItem("nc_fontsize",String(R)),R}),z=N.useRef(()=>{}),Z=N.useRef(()=>!1),q=N.useRef(()=>{}),G=N.useRef(!1),[I,M]=N.useState(!1),[E,D]=N.useState(!1),T=()=>{G.current=!G.current,M(G.current)};return N.useEffect(()=>{F(s||e)},[s,e]),N.useEffect(()=>{let $=!0;const W=t?t.split("/"):[],R=t?`/api/route/${t.split("/").map(encodeURIComponent).join("/")}/_`:"/api";async function K(){let L=null,O=null;try{const ce=await(await Yt(`${R}/sessions`,o)).json();Array.isArray(ce.sessions)&&(L=ce.sessions.find(fe=>fe.name===e))}catch{}try{const ne=await ys(o,W);ne.available&&Array.isArray(ne.cells)&&(O=ne.cells.find(ce=>ce.tmuxSession===e))}catch{}if(!$)return;F(kf({session:e,cell:O||(s?{cell:s}:null)}));let X="";O?X=`${O.engine}${O.key?`·${O.key}`:""}`:L&&(X=L.attached?`attached · ${$_(L.activity)}`:L.activity?$_(L.activity):""),Y(X)}K();const A=setInterval(K,4e3);return()=>{$=!1,clearInterval(A)}},[e,t,o]),c.jsxs("div",{className:"nc-app",children:[c.jsxs("header",{className:"nc-bar nc-bar-single",children:[c.jsxs("button",{onClick:u,title:m("sessions"),children:[c.jsx(et,{name:"chevronLeft",size:18}),c.jsx("span",{className:"nc-bar-label",children:m("sessions")})]}),c.jsxs("span",{className:"nc-bar-center",children:[c.jsx("b",{title:t?`${x} · ${t}`:x,children:x}),B&&c.jsx("small",{className:"nc-bar-sub",children:B})]}),c.jsxs("span",{className:"nc-bar-right",children:[c.jsx("button",{onClick:()=>V(-1),title:m("zoom-out"),children:c.jsx(et,{name:"zoomOut",size:18})}),c.jsx("button",{onClick:()=>V(1),title:m("zoom-in"),children:c.jsx(et,{name:"zoomIn",size:18})}),c.jsx("button",{onClick:()=>w($=>!$),title:m("composer"),children:c.jsx(et,{name:"keyboard",size:20})}),c.jsx("button",{onClick:()=>S($=>!$),title:m("files"),children:c.jsx(et,{name:"folder",size:20})})]})]}),c.jsx("div",{className:"nc-termwrap",children:c.jsx(lw,{session:e,node:t,token:o,readonly:a,takeSize:!0,sendRef:z,composerRef:Z,actionRef:q,ctrlRef:G,setCtrlArmed:M,onFiles:k,fontSize:C,selectionMode:E,onSelectionModeChange:D,keyboardGesture:p.terminalKeyboardGesture})}),c.jsx(xE,{onKeyboard:()=>w($=>!$),onCellSwitcher:h,cellSwitcherOpen:f,send:$=>z.current($),action:$=>q.current($),ctrlArmed:I,onCtrl:T,selectionMode:E,onSelectionMode:D,keepKeyboardClosed:p.keybarKeepsKeyboardClosed,showEnter:p.showKeybarEnter,keybarLayout:p.keybarLayout}),y&&c.jsx(_w,{submitText:$=>Z.current($),token:o,session:e,node:t,ownerId:n,keepKeyboardClosedOnVoice:p.voiceKeepsKeyboardClosed}),v&&c.jsx(cw,{session:e,node:t,token:o,filesEvent:b,onClose:()=>S(!1)})]})}function Yj(){Tn();const[e]=N.useState(Kj),[t,n]=N.useState(e.token),[s,o]=N.useState(e.pair||""),a=N.useCallback(()=>{o("");try{sessionStorage.removeItem("nc_pair")}catch{}},[]),[u,h]=N.useState(!1),f=Vj(),[p]=N.useState(()=>ZE(typeof location<"u"?location.pathname:"/")),[v,S]=N.useState(p.id),y=v===Pr(null,Wn),[w,b]=N.useState(null),k=de=>{const je=_s(de);b(je?{...je,...typeof(de==null?void 0:de.cellName)=="string"&&de.cellName?{cellName:de.cellName}:{}}:null)},[C,j]=N.useState([]),[x,F]=N.useState([]),[B,Y]=N.useState([]),[V,z]=N.useState(()=>p.ownerId?Rr():qj(p.name)),[Z,q]=N.useState(null),[G,I]=N.useState(null),M=de=>I(_s(de)),E=ef(t,f),D=N.useMemo(()=>(E||[]).filter(de=>de.instanceId).map(de=>({instanceId:de.instanceId,route:de.route,label:de.label,status:de.status})),[E]),T=Dj(t,v,V,z,D),$=T.decks;N.useEffect(()=>{const de=new Map;for(const je of E||[]){const Ye=(je.route||[je.name]).join("/"),Et=new Set((je.sessions||[]).map(ut=>ut.name));for(const ut of je.cells||[])!ut.cell||!ut.tmuxSession||ut.cell===ut.tmuxSession||Et.has(ut.cell)||de.set(`${Ye}:${ut.cell}`,`${Ye}:${ut.tmuxSession}`)}z(je=>_1(je,de))},[E]),N.useEffect(()=>{T.localNodeId&&z(de=>{const je=Mh(de,T.localNodeId,D);return JSON.stringify(je)===JSON.stringify(de)?de:je})},[D,T.localNodeId]);const[W,R]=N.useState(null),[K,A]=N.useState(null),L=N.useRef(0),[O,X]=N.useState(!1),[ne,ce]=N.useState(Wj),[fe,pe]=N.useState(!y),[me,le]=N.useState(()=>y?localStorage.getItem(z_)==="1":!0),[Ie,st]=N.useState(!1),[We,Fe]=N.useState("nodes"),[Wt,Xt]=N.useState(!1),[Be,Lt]=N.useState(""),[gt,Bt]=N.useState(!1),rt=(de="nodes",je=!1,Ye="")=>{Fe(de),Xt(je),Lt(Ye),st(!0)},[lt,vt]=N.useState(!1),[oe,xe]=N.useState({deviceDefault:"",localNodeId:"",localNameDefault:""}),[De,$e]=N.useState(!1);N.useEffect(()=>{try{localStorage.setItem(db,String(ne))}catch{}},[ne]),N.useEffect(()=>{try{localStorage.setItem(z_,me?"1":"")}catch{}},[me]),N.useEffect(()=>{if(!t)return;let de=!1;return Promise.all([Q_(t),Yt("/api/config",t).then(je=>je.json())]).then(([je,Ye])=>{de||(xe({deviceDefault:je.deviceName||"",localNodeId:je.nodeId||"",localNameDefault:je.localName||""}),$e(!!Ye.readonlyDefault),(je.firstRun===!0&&!Ye.readonlyDefault||s)&&vt(!0))}).catch(()=>{}),()=>{de=!0}},[t,s]);const ue=N.useCallback(async()=>{try{const je=await(await Yt("/api/sessions",t)).json();je.error||j(je.sessions||[])}catch{}try{const de=await ys(t);F(de.available?de.cells||[]:[]),Y(de.available?de.capabilities||[]:[])}catch{F([]),Y([])}},[t]);N.useEffect(()=>{if(!f)return;ue();const de=setInterval(ue,4e3);return()=>clearInterval(de)},[f,ue]),N.useEffect(()=>{let de=!1;return Yt("/api/config",t).then(je=>je.json()).then(je=>{de||Oj(je.version,je.uiVersion,"0.8.52-rc.1")}).catch(()=>{}),()=>{de=!0}},[t]);const Q=new Set([...C.map(de=>de.name),...E.flatMap(de=>de.sessions.map(je=>je.key))]),te=ki(V),H=de=>z(je=>{const Ye=kw(de,T.localNodeId,D)||de,Et=dy(je,Ye);return Et===je&&ki(je).length>=9&&T.setError(m("grid-full")),Et}),ie=async(de,je=[])=>{try{await Yh(t,de,je)}catch{return}const Ye=je.length?`${je.join("/")}:${de}`:de;z(Et=>Hl(Et,Ye)),ue()},ve=async(de,je,Ye=[])=>{try{await X_(t,de,je,Ye)}catch{return}ue()},_e=async(de,je,Ye=[])=>{await V_(t,{cell:de,enabled:!!je},Ye),ue()},Ee=async de=>{if(!W)return;const{cell:je}=W,Ye=Array.isArray(W.route)?W.route:[];if(de.action==="up"){const ut=await qh(t,{cell:je,boot:!!de.boot,...de.engine?{engine:de.engine}:{},...de.model!==void 0?{model:de.model}:{},...de.permissionPolicy?{permissionPolicy:de.permissionPolicy}:{}},Ye),ii=lf(ut);ii&&T.setError(ii.text)}else await Ml(t,{cell:je,boot:!!de.boot},Ye);const Et=de.action==="up"?!!de.boot:de.boot?!1:!!W.boot;A({id:++L.current,cell:je,route:Ye,enabled:Et}),ue()},ye=N.useCallback(de=>{A(je=>(je==null?void 0:je.id)===de?null:je)},[]),Ne=async de=>{if(!(!(de!=null&&de.direct)||O)){X(!0);try{await Jh(t,de.name,de.tunnelStatus==="up"?"down":"up")}finally{X(!1)}}},Je=async(de,je)=>{const Ye=String(je||"").trim();return!(de!=null&&de.direct)||!Dr(Ye)?!1:(await J_(t,de.name,Ye),!0)},Ct=de=>{const je=$.find(Ye=>Ye.id===de);if(!je)return!1;try{const Ye=window.open(dd(je,t),"_blank");return Ye&&(Ye.opener=null),!!Ye}catch{return!1}},ze=async de=>{if(!de||de===v)return;const je=await T.select(de),Ye=T.records.find(Et=>Et.id===de);S(de),z(je),q(null),I(null);try{history.replaceState(null,"",dd(Ye||de,null))}catch{}},_n=async(de,je)=>{const Ye=await T.add(de,je);await ze(Ye.id)},ft=async(de,je)=>{const Ye=await T.rename(de,je);if(de===v){S(Ye.id),z(Mh(Ye.layout,T.localNodeId,D)),q(null),I(null);try{history.replaceState(null,"",dd(Ye,null))}catch{}}},Ge=async de=>{await T.remove(de),de===v&&await ze(T.localMainId)},Qt=async(de,je)=>{!je||je===v||(await T.addTileTo(je,de),z(Ye=>Hl(Ye,de)))};if(!t)return c.jsxs("div",{className:"nc-auth",children:[c.jsx("p",{children:m("auth-prompt")}),c.jsx("input",{onChange:de=>n(de.target.value.trim()),placeholder:"token"}),c.jsxs("label",{children:[c.jsx("input",{type:"checkbox",checked:u,onChange:de=>h(de.target.checked)})," ",m("remember-device")]}),c.jsx("button",{onClick:()=>{(u?localStorage:sessionStorage).setItem("nc_token",t)},children:"ok"})]});const Un=c.jsxs(c.Fragment,{children:[Ie&&c.jsx(yj,{token:t,initialTab:We,initialLocation:Be,startNewCell:Wt,onClose:()=>{st(!1),Xt(!1),Lt("")}}),lt&&c.jsx(wj,{token:t,initialPair:s,...oe,onPairDone:a,onDone:()=>vt(!1)}),c.jsx(Ej,{token:t})]});if(!f)return w?c.jsxs(c.Fragment,{children:[c.jsx(H_,{session:w.session,node:w.node,ownerId:w.ownerId,cellName:w.cellName,token:t,readonly:De,onBack:()=>b(null),onCellSwitcher:()=>Bt(!0),cellSwitcherOpen:gt}),gt&&c.jsx(Aj,{token:t,current:w,onPick:de=>{k(de),Bt(!1)},onClose:()=>Bt(!1)}),Un]}):c.jsxs(c.Fragment,{children:[c.jsx(M1,{onPick:k,token:t,onSettings:rt}),Un]});const ni=y||!fe;return c.jsxs("div",{className:"nc-workspace",children:[ni&&c.jsx($E,{sessions:C,cells:x,activeSessions:te,nodeGroups:E,fleetCapabilities:B,bootSettlement:K,onBootSettlementApplied:ye,localNodeId:T.localNodeId,onPick:M,onAddTile:H,onPower:R,onBoot:_e,onBootError:de=>T.setError(String((de==null?void 0:de.message)||de)),onNodePower:Ne,onNodeRename:Je,onKill:ie,onVisibility:ve,onNew:()=>rt("fleet",!0),onSettings:rt,width:ne,collapsed:me,onResize:ce,onToggleCollapse:()=>le(de=>!de)}),c.jsxs("div",{className:"nc-workspace-main",children:[c.jsx(SN,{decks:$,currentDeck:v,onCreate:_n,onRename:ft,onDelete:Ge,onReorder:T.reorder,onOpenWindow:Ct,onNavigate:ze,saveState:T.saveState,error:T.error,sidebarVisible:ni,onToggleSidebar:y?null:()=>pe(de=>!de)}),c.jsx(YE,{layout:V,onLayoutChange:z,token:t,readonly:De,sessionsAlive:Q,focusSession:Z,onFocus:q,onOpenSingle:M,decks:$,currentDeck:v,onSendToDeck:Qt,cells:x,nodeGroups:E})]}),G&&c.jsx("div",{className:"nc-single-overlay",children:c.jsx(H_,{session:G.session,node:G.node,ownerId:G.ownerId,cellName:kf({session:G.session,node:G.node,ownerId:G.ownerId,cells:x,nodeGroups:E}),token:t,readonly:De,onBack:()=>I(null)})}),W&&c.jsx(Ol,{cell:W,token:t,route:Array.isArray(W.route)?W.route:[],onConfirm:Ee,onClose:()=>R(null)}),Un]})}function Gj(){Tn();const e=N.useSyncExternalStore(Ij,B_,B_);if(!e.needed)return null;const t=e.kind==="install"?m("install-version-mismatch").replace("{v}",e.version):m("update-available").replace("{v}",e.version).replace(" "," ").trim();return c.jsxs("div",{className:"nc-update",role:"status","aria-live":"polite",children:[c.jsx("span",{className:"nc-update-msg",children:t}),e.kind==="reload"&&c.jsx("button",{className:"nc-update-btn",onClick:Fj,children:m("reload")})]})}zj();r0.createRoot(document.getElementById("root")).render(c.jsxs(JS.StrictMode,{children:[c.jsx(Yj,{}),c.jsx(Gj,{})]}));
93
+ `],{type:"application/json"}),$=URL.createObjectURL(T),W=document.createElement("a");W.href=$,W.download="nexuscrew-diagnostics.json",W.click(),URL.revokeObjectURL($)}catch{y(m("diagnostics-export-failed"))}};return c.jsxs("div",{className:"nc-set-tab nc-diagnostics",children:[c.jsxs("label",{className:"nc-field",children:[m("diagnostics-target"),c.jsx("select",{value:u.key,onChange:T=>a(T.target.value),children:s.map(T=>c.jsxs("option",{value:T.key,children:[T.label,T.status!=="up"?` · ${T.status}`:""]},T.key))})]}),c.jsxs("div",{className:"nc-set-form nc-diag-controls",children:[c.jsx("div",{className:"nc-sheet-label",children:m("diagnostics-verbose")}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("select",{"aria-label":m("diagnostics-duration"),value:j,onChange:T=>x(Number(T.target.value)),disabled:n,children:[300,900,1800,3600].map(T=>c.jsxs("option",{value:T,children:[T/60," min"]},T))}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:n||(h==null?void 0:h.verbose)===!0,onClick:()=>M(()=>bg(e,!0,j,u.route)),children:m("enable")}),c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||(h==null?void 0:h.verbose)!==!0,onClick:()=>M(()=>bg(e,!1,j,u.route)),children:m("stop")})]}),c.jsx("small",{className:"nc-set-hint",children:h!=null&&h.verbose?m("diagnostics-expires").replace("{time}",new Date(h.expiresAt).toLocaleTimeString()):m("diagnostics-off")})]}),c.jsxs("div",{className:"nc-diag-filters",children:[c.jsxs("select",{"aria-label":m("diagnostics-level"),value:F,onChange:T=>B(T.target.value),children:[c.jsx("option",{value:"all",children:m("diagnostics-all-levels")}),["debug","info","warn","error"].map(T=>c.jsx("option",{value:T,children:T},T))]}),c.jsx("input",{"aria-label":m("diagnostics-component"),placeholder:m("diagnostics-component"),value:Y,onChange:T=>V(T.target.value)})]}),c.jsxs("div",{className:"nc-set-row",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:w,onChange:T=>b(T.target.checked)})," ",m("diagnostics-pause")]}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:k,onChange:T=>C(T.target.checked)})," ",m("diagnostics-autoscroll")]})]}),c.jsx("pre",{ref:Z,className:"nc-diag-log","aria-label":m("diagnostics-log"),children:I||m("diagnostics-empty")}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:E,children:m("copy")}),c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:D,children:m("diagnostics-export")}),c.jsx("button",{type:"button",className:"nc-btn danger",disabled:n,onClick:()=>{window.confirm(m("diagnostics-clear-confirm"))&&M(async()=>{const T=await F0(e,u.route);return z.current=0,v([]),T})},children:m("diagnostics-clear")})]}),S&&c.jsx("div",{className:"nc-err",children:S})]})}function _j({token:e,settings:t,readonly:n,refresh:s,roster:o,section:a,setSection:u}){const[h,f]=N.useState(null),[p,v]=N.useState(null),[S,y]=N.useState(!1),[w,b]=N.useState(!1),[k,C]=N.useState(null),[j,x]=N.useState(!0),[F,B]=N.useState(!1);N.useEffect(()=>{C(t&&t.update||null),x(!t||t.autoUpdate!==!1),B(!!(t&&t.alternateScreen))},[t]);const Y=async()=>{f(null),v(null),b(!0);try{const E=await w0(e);v(E.note||"ok"),y(!1)}catch(E){f(String(E.message||E))}b(!1)},V=async()=>{f(null),v(null),b(!0);try{const E=await M0(e);v(`${E.note||"ok"}${E.target?` (${E.target})`:""}`)}catch(E){f(String(E.message||E))}b(!1)},z=async E=>{f(null),v(null),b(!0);try{await $d(e,{autoUpdate:E}),x(E),s&&await s()}catch(D){f(String(D.message||D))}b(!1)},Z=async E=>{f(null),v(null),b(!0);try{await $d(e,{alternateScreen:E}),B(E),s&&await s()}catch(D){f(String(D.message||D))}b(!1)},q=async()=>{f(null),v(null),b(!0);try{C(await I0(e))}catch(E){f(String(E.message||E))}b(!1)},G=async()=>{f(null),v(null),b(!0);try{const E=await O0(e);C(E),v(m("npm-update-restarting"))}catch(E){f(String(E.message||E))}b(!1)},I=()=>{window.confirm(m("composer-clear-confirm"))&&(f(null),ME()?(window.dispatchEvent(new Event(Ah)),v(m("composer-clear-done"))):f(m("composer-clear-failed")))},M=t&&t.service;return c.jsxs("div",{className:"nc-set-tab",children:[c.jsx("div",{className:"nc-system-tabs",role:"tablist","aria-label":m("tab-system"),children:["general","diagnostics"].map(E=>c.jsx("button",{type:"button",role:"tab","aria-selected":a===E,className:`nc-set-tabbtn${a===E?" on":""}`,onClick:()=>u(E),children:m(`system-${E}`)},E))}),a==="general"&&c.jsxs(c.Fragment,{children:[c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-this-node")}),t&&c.jsxs("div",{className:"nc-set-info",children:["v",t.version," · ",t.platform," · :",t.port,c.jsx("br",{}),M&&M.installed?m("service-installed"):m("service-missing"),M&&M.installed?` · ${M.active?m("service-active"):m("service-inactive")}`:"",M?` · boot ${M.boot?"on":"off"}`:""]}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w,title:n?m("settings-readonly"):"",onClick:V,children:m("service-regenerate")})}),c.jsx(fj,{token:e,readonly:n}),c.jsx(pj,{})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-updates")}),c.jsxs("div",{className:"nc-set-form nc-update-settings",children:[c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox",checked:j,disabled:n||w||k&&!k.supported,onChange:E=>z(E.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("npm-auto-update")}),c.jsx("small",{children:m("npm-auto-update-help")})]})]}),k&&c.jsxs("div",{className:"nc-set-info",children:[m("npm-update-current")," v",k.current,k.latest?` · ${m("npm-update-latest")} v${k.latest}`:""," · ",m(`npm-update-${k.supported?k.phase:"unsupported"}`)]}),c.jsxs("div",{className:"nc-set-row",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w||!k||!k.supported,onClick:q,children:m("npm-update-check")}),k&&k.available&&c.jsx("button",{type:"button",className:"nc-btn primary",disabled:n||w||k.phase==="installing",onClick:G,children:m("npm-update-install")})]}),k&&k.lastError&&c.jsx("div",{className:"nc-err",children:k.lastError})]})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-security")}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:n||w,title:n?m("settings-readonly"):"",onClick:()=>{f(null),v(null),y(!0)},children:m("token-rotate")})})]}),c.jsxs("section",{className:"nc-system-group",children:[c.jsx("h3",{children:m("system-local-data")}),c.jsxs("div",{className:"nc-set-form",children:[c.jsx("div",{className:"nc-sheet-label",children:m("composer-clear-data")}),c.jsx("small",{className:"nc-set-hint",children:m("composer-clear-data-help")}),c.jsx("div",{className:"nc-set-row",children:c.jsx("button",{type:"button",className:"nc-btn ghost",onClick:I,children:m("composer-clear-data")})})]})]})]}),a==="diagnostics"&&c.jsxs("section",{className:"nc-system-group nc-system-diagnostics",children:[c.jsx("h3",{children:m("system-diagnostics")}),c.jsxs("div",{className:"nc-set-form nc-alternate-screen-settings",children:[c.jsx("div",{className:"nc-sheet-label",children:m("system-terminal")}),c.jsxs("label",{className:"nc-check",children:[c.jsx("input",{type:"checkbox","aria-label":m("alternate-screen"),checked:F,disabled:n||w,onChange:E=>Z(E.target.checked)}),c.jsxs("span",{children:[c.jsx("b",{children:m("alternate-screen")}),c.jsx("small",{children:m("alternate-screen-help")})]})]})]}),c.jsx(vj,{token:e,roster:o,readonly:n})]}),S&&c.jsxs("div",{className:"nc-set-confirm",children:[c.jsx("div",{children:m("token-rotate-explain")}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:w,onClick:()=>y(!1),children:m("cancel")}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:w,onClick:Y,children:m("confirm")})]})]}),p&&c.jsx("div",{className:"nc-set-note",children:p}),h&&c.jsx("div",{className:"nc-err",children:h})]})}function yj({token:e,onClose:t,initialTab:n="nodes",initialLocation:s="",startNewCell:o=!1}){Tn();const a=n==="diagnostics"?"diagnostics":"general",[u,h]=N.useState(n==="diagnostics"?"system":n),f=N.useRef(null),p=N.useRef(null),[v,S]=N.useState({start:!1,end:!1}),[y,w]=N.useState(a),[b,k]=N.useState(null),[C,j]=N.useState([]),[x,F]=N.useState(!1),[B,Y]=N.useState(null),[V,z]=N.useState(0),Z=ef(e,!0,V),q=N.useCallback(()=>{const I=f.current;if(!I)return;const M=I.scrollWidth>I.clientWidth+1,E={start:M&&I.scrollLeft>1,end:M&&I.scrollLeft+I.clientWidth<I.scrollWidth-1};S(D=>D.start===E.start&&D.end===E.end?D:E)},[]);N.useEffect(()=>{const I=f.current;if(!I)return;const M=typeof ResizeObserver=="function"?new ResizeObserver(q):null;return M==null||M.observe(I),window.addEventListener("resize",q),q(),()=>{M==null||M.disconnect(),window.removeEventListener("resize",q)}},[q]),N.useEffect(()=>{var M,E;(E=(M=p.current)==null?void 0:M.scrollIntoView)==null||E.call(M,{behavior:"smooth",block:"nearest",inline:"nearest"});const I=window.requestAnimationFrame?window.requestAnimationFrame(q):setTimeout(q,0);return()=>{window.cancelAnimationFrame?window.cancelAnimationFrame(I):clearTimeout(I)}},[u,q]);const G=N.useCallback(async()=>{try{const I=await Q_(e);k(I),Y(null)}catch(I){Y(String(I.message||I))}try{const M=(await g0(e)).peers||[];let E=[];try{E=((await v0(e)).nodes||[]).map(g2).filter(Boolean)}catch{}j([...M,...E])}catch(I){Y(String(I.message||I))}},[e]);return N.useEffect(()=>{G();const I=setInterval(G,5e3);return()=>clearInterval(I)},[G]),N.useEffect(()=>{let I=!1;return Yt("/api/config",e).then(M=>M.json()).then(M=>{I||F(!!M.readonlyDefault)}).catch(()=>{}),()=>{I=!0}},[e]),c.jsx("div",{className:"nc-set-overlay",onClick:t,children:c.jsxs("div",{className:"nc-set-panel",onClick:I=>I.stopPropagation(),children:[c.jsxs("div",{className:"nc-set-head",children:[c.jsx(et,{name:"gear",size:18}),c.jsx("b",{children:m("settings")}),c.jsx("button",{type:"button",className:"nc-set-close",onClick:t,title:m("close"),children:c.jsx(et,{name:"x",size:18})})]}),x&&c.jsx("div",{className:"nc-set-readonly",children:m("settings-readonly")}),B&&c.jsx("div",{className:"nc-err",children:B}),c.jsx("div",{className:`nc-set-tabs-wrap${v.start?" has-start-overflow":""}${v.end?" has-end-overflow":""}`,children:c.jsx("div",{className:"nc-set-tabs",ref:f,onScroll:q,children:["nodes","fleet","audio","input","system"].map(I=>c.jsx("button",{ref:u===I?p:null,type:"button",className:`nc-set-tabbtn${u===I?" on":""}`,onClick:()=>h(I),children:m(`tab-${I}`)},I))})}),c.jsxs("div",{className:"nc-set-body",children:[u==="nodes"&&c.jsx(hj,{token:e,nodes:C,roster:Z,settings:b,readonly:x,refresh:G,refreshAliases:()=>z(I=>I+1)}),u==="fleet"&&c.jsx(V2,{token:e,readonly:x,startNewCell:o,initialLocation:s,targets:Z.map(I=>({route:I.route,label:I.label||I.name,status:I.status}))}),u==="audio"&&c.jsx(mj,{token:e,readonly:x,nodes:C,settings:b}),u==="input"&&c.jsx(gj,{}),u==="system"&&c.jsx(_j,{token:e,settings:b,readonly:x,refresh:G,roster:Z,section:y,setSection:w})]})]})})}function wj({token:e,initialPair:t,deviceDefault:n="",localNodeId:s="",localNameDefault:o="",onPairDone:a,onDone:u}){Tn();const[h,f]=N.useState(t?"pair":"welcome"),[p,v]=N.useState(!1),[S,y]=N.useState(null),w=async()=>{v(!0),y(null);try{await $d(e,{wizardDone:!0}),a&&a(),u()}catch(b){y(String(b.message||b)),v(!1)}};return c.jsx("div",{className:"nc-wiz-overlay",children:c.jsxs("div",{className:"nc-wiz",children:[c.jsxs("div",{className:"nc-wiz-head",children:[c.jsx("b",{children:m("wizard-title")}),c.jsx("small",{children:m("hydra-simple")})]}),h==="welcome"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx("div",{className:"nc-wiz-done",children:m("local-ready")}),c.jsxs("div",{className:"nc-sheet-actions",children:[c.jsx("button",{className:"nc-btn ghost",disabled:p,onClick:w,children:m("local-only")}),c.jsx("button",{className:"nc-btn primary",disabled:p,onClick:()=>f("pair"),children:m("add-node")})]})]}),h==="pair"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx($w,{token:e,initial:t||"",autoStart:!!t,deviceDefault:n,localNodeId:s,localNameDefault:o,onBusyChange:v,onSuccess:async()=>{a&&a(),f("done")}}),c.jsx("div",{className:"nc-sheet-actions",children:c.jsx("button",{className:"nc-btn ghost",disabled:p,onClick:()=>{a&&a(),f("welcome")},children:m("back")})})]}),h==="done"&&c.jsxs("div",{className:"nc-wiz-body",children:[c.jsx("div",{className:"nc-wiz-done",children:m("node-connected")}),c.jsx("div",{className:"nc-sheet-actions",children:c.jsx("button",{className:"nc-btn primary",disabled:p,onClick:w,children:m("finish")})})]}),S&&c.jsx("div",{className:"nc-err",children:S})]})})}function bj(e,t){if(typeof EventSource>"u"||!e)return()=>{};const n=new EventSource(`/api/events?token=${encodeURIComponent(e)}`);return n.onmessage=s=>{try{const o=JSON.parse(s.data);o&&typeof o=="object"&&typeof o.type=="string"&&t(o)}catch{}},()=>{try{n.close()}catch{}}}const Sj=6e3,kj=12e3;function xj({n:e,onClose:t}){return c.jsxs("div",{className:`nc-ntf-toast${e.urgency==="high"?" high":""}`,role:"status","aria-live":"polite",children:[c.jsxs("div",{className:"nc-ntf-toast-txt",children:[c.jsx("b",{children:e.title}),e.body&&c.jsx("small",{children:e.body}),e.session&&c.jsx("span",{className:"nc-ntf-from",children:e.session})]}),c.jsx("button",{type:"button",className:"nc-ntf-x",onClick:t,title:m("close"),children:c.jsx(et,{name:"x",size:14})})]})}function Cj({ask:e,token:t,onAnswered:n}){const[s,o]=N.useState(""),[a,u]=N.useState(!1),[h,f]=N.useState(null),p=async v=>{const S=String(v||"").trim();if(!(!S||a)){f(null),u(!0);try{await H0(t,e.id,S),n(e.id)}catch(y){f(String(y.message||y))}u(!1)}};return c.jsxs("div",{className:"nc-ask-card",children:[c.jsxs("div",{className:"nc-ask-head",children:[c.jsx("span",{className:"nc-ntf-from",children:e.session}),c.jsxs("code",{className:"nc-ask-id",children:["#",e.id]})]}),c.jsx("div",{className:"nc-ask-q",children:e.question}),Array.isArray(e.options)&&e.options.length>0&&c.jsx("div",{className:"nc-ask-opts",children:e.options.map(v=>c.jsx("button",{type:"button",className:"nc-btn ghost",disabled:a,onClick:()=>p(v),children:v},v))}),c.jsxs("div",{className:"nc-ask-reply",children:[c.jsx("textarea",{rows:2,placeholder:m("ask-reply-ph"),value:s,disabled:a,onChange:v=>o(v.target.value)}),c.jsx("button",{type:"button",className:"nc-btn primary",disabled:a||!s.trim(),onClick:()=>p(s),children:m("send")})]}),h&&c.jsx("div",{className:"nc-err",children:h})]})}function Ej({token:e}){const[t]=Tn(),[n]=ib(),[s,o]=N.useState([]),[a,u]=N.useState([]),[h,f]=N.useState(()=>{try{return/(?:^|[#&])ask=/.test(location.hash)}catch{return!1}}),p=N.useRef(0),v=N.useRef(null);v.current||(v.current=cj());const S=N.useRef({enabled:n,lang:t});S.current={enabled:n,lang:t};const y=N.useCallback(k=>{o(C=>C.filter(j=>j.key!==k))},[]),w=N.useCallback(k=>{const C=`t${p.current+=1}`;o(x=>[...x.slice(-3),{...k,key:C}]),setTimeout(()=>y(C),k.urgency==="high"?kj:Sj);const j=S.current;if(j.enabled)try{v.current.enqueue(k,sj(k,j.lang))}catch{}},[y]);N.useEffect(()=>{n||v.current.stop()},[n]),N.useEffect(()=>{const k=()=>{(document.visibilityState!=="visible"||!document.hasFocus())&&v.current.stop()},C=()=>v.current.stop();return document.addEventListener("visibilitychange",k),window.addEventListener("blur",k),window.addEventListener(Bh,C),()=>{document.removeEventListener("visibilitychange",k),window.removeEventListener("blur",k),window.removeEventListener(Bh,C),typeof v.current.dispose=="function"?v.current.dispose():v.current.stop()}},[]),N.useEffect(()=>{if(!e)return;let k=!1;$0(e).then(j=>{k||u(j.asks||[])}).catch(()=>{});const C=bj(e,j=>{j.type==="notify"?w(j):j.type==="ask"&&j.ask&&j.ask.id?u(x=>x.some(F=>F.id===j.ask.id)?x:[...x,j.ask]):j.type==="ask-answered"&&j.id&&u(x=>x.filter(F=>F.id!==j.id))});return()=>{k=!0,C()}},[e,w]);const b=k=>u(C=>C.filter(j=>j.id!==k));return c.jsxs(c.Fragment,{children:[s.length>0&&c.jsx("div",{className:"nc-ntf-toasts",children:s.map(k=>c.jsx(xj,{n:k,onClose:()=>y(k.key)},k.key))}),a.length>0&&!h&&c.jsxs("button",{type:"button",className:"nc-ask-badge",onClick:()=>f(!0),title:m("asks-title"),children:["? ",c.jsx("span",{className:"nc-ask-count",children:a.length})]}),a.length>0&&h&&c.jsxs("div",{className:"nc-ask-panel",children:[c.jsxs("div",{className:"nc-ask-panel-head",children:[c.jsx("b",{children:m("asks-title")}),c.jsx("span",{className:"nc-ask-count",children:a.length}),c.jsx("button",{type:"button",className:"nc-ntf-x",onClick:()=>f(!1),title:m("close"),children:c.jsx(et,{name:"x",size:16})})]}),c.jsx("div",{className:"nc-ask-panel-body",children:a.map(k=>c.jsx(Cj,{ask:k,token:e,onAnswered:b},k.id))})]})]})}const Nj=4e3;async function jj(e){const t=await Yt("/api/sessions",e);if((t==null?void 0:t.ok)===!1)throw new Error(`HTTP ${t.status}`);const n=await t.json();if(!Array.isArray(n==null?void 0:n.sessions))throw new Error("invalid sessions payload");return n.sessions}async function Bd(e,t=[]){var h;const[n,s]=await Promise.allSettled([t.length?Xh(e,t):jj(e),ys(e,t)]),o=n.status==="fulfilled"&&Array.isArray((h=n.value)==null?void 0:h.sessions)?n.value.sessions:Array.isArray(n.value)?n.value:null,a=s.status==="fulfilled"?s.value:null,u=(a==null?void 0:a.available)===!0&&Array.isArray(a.cells)?a.cells:null;return{sessions:o,cells:u,fresh:Array.isArray(o)&&Array.isArray(u)}}function sb(e,t,n){return n===!0&&(e==null?void 0:e.degraded)!==!0&&(e==null?void 0:e.active)===!0&&e.tmux!==!1&&!!e.tmuxSession&&(t||[]).some(s=>(s==null?void 0:s.name)===e.tmuxSession)}function Rj(e){const t=new Map((e.sessions||[]).map(o=>[o.name,o])),n=[],s=(o,a,u,h=[],f="")=>{const p=new Map((a||[]).map(v=>[v.name,v]));for(const v of o||[]){const S=p.get(v.tmuxSession)||{},y=sf(v,S),w=sb(v,a,u);n.push({key:Vo(h,v.tmuxSession||v.cell),session:v.tmuxSession,route:h,cellName:v.cell,label:v.cell,node:h.length?h.join("/"):"",nodeLabel:f,live:w,selectable:w,verified:u===!0,working:y.working,degraded:!!v.degraded,activity:S.activity||v.activity||0,subtitle:y.subtitle})}};s(e.cells,[...t.values()],e.localFresh===!0);for(const o of e.nodeGroups||[])s(o.cells,o.sessions,o.switcherFresh===!0,Array.isArray(o.route)?o.route:[],o.label||o.name||"");return n}function Pj(e){const t=new Map,n=Array.isArray(e.sessions)?e.sessions:[],s=Array.isArray(e.cells)?e.cells:[],o=new Map(n.map(u=>[u.name,u])),a=new Set(s.map(u=>u.tmuxSession).filter(Boolean));t.set("local",rf(s,n.filter(u=>!a.has(u.name)),o));for(const u of e.nodeGroups||[]){const h=Array.isArray(u.route)?u.route:[];if(!h.length)continue;const f=Array.isArray(u.cells)?u.cells:[],p=Array.isArray(u.sessions)?u.sessions:[],v=new Set(f.map(S=>S.tmuxSession).filter(Boolean));t.set(h.join("/"),Fl({...u,route:h,cells:f,sessions:p,unmanaged:p.filter(S=>!v.has(S.name))}).rawItems)}return t}function Lj(e,t,n,s){return[...new Set(e.map(a=>a.node||"local"))].flatMap(a=>{const u=e.filter(v=>(v.node||"local")===a),h=new Map((t.get(a)||[]).map(v=>[v.key,v])),f=new Map(u.map(v=>[v.key,v])),p=u.map(v=>{const S=h.get(v.key);return{...v,label:(S==null?void 0:S.label)||v.label,live:(S==null?void 0:S.live)??v.live,fresh:(S==null?void 0:S.fresh)===!0,activity:(S==null?void 0:S.activity)??v.activity}});return ms(p,n,"all",zi(s,a)).map(v=>f.get(v.key))})}function Aj({token:e,current:t,onPick:n,onClose:s}){const[o,a]=N.useState(Mg),[u,h]=N.useState(!1),[f,p]=N.useState(!1),[v,S]=N.useState(""),[y,w]=N.useState(""),[b,k]=N.useState(""),C=N.useRef(null),j=N.useRef(null),x=N.useMemo(()=>Rj(o),[o]),F=N.useMemo(()=>Pj(o),[o]),{pins:B,orders:Y,canMoveRoster:V,moveRoster:z,stepRoster:Z}=nf(),q=N.useMemo(()=>Lj(x,F,B,Y),[x,F,B,Y]),G=N.useMemo(()=>u?q:q.filter(T=>T.selectable||T.degraded),[q,u]),I=N.useMemo(()=>x.find(T=>T.key===y&&T.selectable),[x,y]);N.useEffect(()=>{var W;const T=document.activeElement;(W=j.current)==null||W.focus();const $=R=>{R.key==="Escape"&&s()};return document.addEventListener("keydown",$),()=>{var R;document.removeEventListener("keydown",$),(R=T==null?void 0:T.focus)==null||R.call(T)}},[s]),N.useEffect(()=>{let T=!0,$=!1;const W=async()=>{if($)return;$=!0;const K=Mg(),A=Array.isArray(K.nodeGroups)?K.nodeGroups:[],L=Bd(e),O=await Promise.all(A.map(async pe=>{const me=Array.isArray(pe.route)?pe.route:[];return me.length?{group:pe,result:await Bd(e,me)}:{group:pe,result:{fresh:!1,sessions:null,cells:null}}})),X=await L;if(!T)return;const ne=new Map(O.map(({group:pe,result:me})=>[JSON.stringify(pe.route||[]),me])),ce=A.map(pe=>{const me=ne.get(JSON.stringify(pe.route||[]));return me?{...pe,sessions:me.sessions||pe.sessions||[],cells:me.cells||pe.cells||[],switcherFresh:me.fresh}:{...pe,switcherFresh:!1}}),fe=py({...K,sessions:X.sessions||K.sessions||[],cells:X.cells||K.cells||[],localFresh:X.fresh,nodeGroups:ce,refreshedAt:Date.now()});a(fe),p(!0),$=!1};W();const R=setInterval(W,Nj);return()=>{T=!1,clearInterval(R)}},[e]);const M=T=>T.degraded?m("cell-degraded"):T.verified?T.selectable?T.working?m("cell-working"):m("cell-idle"):m("cell-off"):m("cell-switcher-not-confirmed"),E=T=>{if(S(""),!T.selectable){S(m("cell-switcher-not-active"));return}w(T.key)},D=async()=>{const T=I;if(!T){S(m("cell-switcher-select"));return}S(""),k(T.key);try{const $=await Bd(e,T.route),W=($.cells||[]).find(R=>(R==null?void 0:R.cell)===T.cellName&&(R==null?void 0:R.tmuxSession)===T.session);if(!sb(W,$.sessions,$.fresh)){S(m("cell-switcher-not-active"));return}n({session:T.session,...T.node?{node:T.node}:{},cellName:T.cellName}),s()}catch{S(m("cell-switcher-not-active"))}finally{k("")}};return c.jsx("div",{className:"nc-cell-switcher-backdrop",onClick:s,children:c.jsxs("aside",{ref:C,className:"nc-cell-switcher",role:"dialog","aria-label":m("fleet-cells"),tabIndex:-1,onClick:T=>T.stopPropagation(),children:[c.jsxs("div",{className:"nc-cell-switcher-list",children:[!f&&c.jsx("div",{className:"nc-empty",role:"status",children:m("cell-switcher-refreshing")}),f&&G.length===0&&c.jsx("div",{className:"nc-empty",role:"status",children:m("cell-switcher-empty-active")}),G.map(T=>{const $=(t==null?void 0:t.session)===T.session&&((t==null?void 0:t.node)||"")===T.node,W=y===T.key,R=M(T),K=T.node||"local",A=F.get(K)||x.filter(L=>(L.node||"local")===K);return c.jsxs("div",{className:`nc-cell-switcher-row${$?" current":""}${W?" selected":""}${T.selectable?"":" off"}`,"data-roster-key":T.key,"data-position":K,children:[c.jsx(Oi,{position:K,itemKey:T.key,label:T.cellName,canMove:V,onMove:(L,O)=>z(K,L,O,A),onStep:L=>Z(K,T.key,L,A)}),c.jsxs("button",{type:"button",className:"nc-cell-switcher-row-select","aria-current":$?"true":void 0,"aria-pressed":W,"aria-disabled":!T.selectable,disabled:b===T.key,onClick:()=>E(T),children:[c.jsx("span",{className:`nc-cell-switcher-dot${T.degraded?" warn":T.live?` on${T.working?" working":""}`:""}`}),c.jsxs("span",{className:"nc-cell-switcher-copy",children:[c.jsx("b",{children:T.cellName}),c.jsx("small",{className:"nc-cell-switcher-state",children:R}),c.jsx("small",{children:[T.nodeLabel,T.subtitle].filter(Boolean).join(" · ")})]})]})]},T.key)})]}),v&&c.jsx("div",{className:"nc-cell-switcher-notice",role:"status",children:v}),c.jsx("div",{className:"nc-cell-switcher-actions",children:c.jsx("button",{type:"button",className:"nc-cell-switcher-open",disabled:!I||!!b,onClick:D,children:I?`${m("cell-switcher-open")}: ${I.cellName}`:m("cell-switcher-select")})}),c.jsxs("div",{className:"nc-cell-switcher-controls",children:[c.jsx("b",{children:m("fleet-cells")}),c.jsx("button",{type:"button",className:"nc-cell-switcher-filter","aria-pressed":u,onClick:()=>{S(""),h(T=>!T)},children:m(u?"cell-switcher-show-active":"cell-switcher-show-all")}),c.jsx("button",{ref:j,type:"button",className:"nc-cell-switcher-close","aria-label":m("cell-switcher-close"),title:m("cell-switcher-close"),onClick:s,children:"×"})]})]})})}const zd=e=>ki(qs(e)).length===0,Fd=e=>Array.isArray(e)?e.join("/"):"";function Tj(e){const t=new Set,n=[];for(const s of Array.isArray(e)?e:[])!s||!Hn.test(String(s.instanceId||""))||!Array.isArray(s.route)||!s.route.length||t.has(s.instanceId)||(t.add(s.instanceId),n.push({instanceId:s.instanceId,route:[...s.route],label:String(s.label||s.name||s.route.join(" › ")),status:s.status||"offline"}));return n.sort((s,o)=>s.label.localeCompare(o.label))}function Bo(e){return{instanceId:e.ownerId,route:e.ownerRoute||[],label:e.ownerLabel,status:e.available===!1?"offline":"up"}}function Fs(e,t,n,s=!1,o=!0){const a=t.instanceId;return{...e,id:Pr(s?null:a,e.name),ownerId:a,ownerRoute:s?[]:[...t.route],ownerLabel:s?"Local":t.label,local:s,available:o,ownerTopology:Array.isArray(n)?n:[],layout:Dh(e.layout,a,n)}}function Dj(e,t,n,s,o=[]){const[a,u]=N.useState([]),[h,f]=N.useState(!1),[p,v]=N.useState("idle"),[S,y]=N.useState(""),[w,b]=N.useState(""),k=N.useRef([]),C=N.useRef([]),j=N.useRef(""),x=N.useRef(t),F=N.useRef(n),B=N.useRef(!1),Y=N.useRef(!0),V=N.useRef(""),z=N.useMemo(()=>Tj(o),[o]),Z=z.map(A=>`${A.instanceId}:${Fd(A.route)}:${A.status}:${A.label}`).join("|");C.current=z,F.current=n,x.current=t,k.current=a;const q=N.useCallback(A=>Mh(A.layout,j.current,C.current),[]),G=N.useCallback((A,L=!0,O=x.current)=>{const X=Vv(A,Sl()),ne=k.current.some(fe=>fe.id===O);k.current=X,u(X);const ce=X.find(fe=>fe.id===O);if(L&&ce){Y.current=!0;const fe=q(ce);s(fe),ce.local&&rN(ce.name,fe)}else ne&&!ce&&(Y.current=!0,s(Rr()),y("deck non più condiviso dal nodo owner"));tN(X.filter(fe=>fe.local).map(fe=>fe.name))},[s,q]),I=N.useCallback(async A=>{let L=await fl(e);const O=L.decks.find(X=>X.name==="main");if(L.decks.length===1&&O&&O.revision===0&&zd(O.layout)){const X=eN(),ne=qs(Ih("main")||Rr());if(!zd(ne)){const ce=Dh(ne,A,[]);L.decks[0]=await pl(e,"main",ce,0,[])}for(const ce of X.filter(fe=>fe!=="main"))try{let fe=await Sg(e,ce,[]);const pe=qs(Ih(ce)||Rr());zd(pe)||(fe=await pl(e,ce,Dh(pe,A,[]),fe.revision,[]))}catch{}L=await fl(e)}return L},[e]),M=N.useCallback(async({migrate:A=!1}={})=>{const L=await Qh(e,[]),O=Hn.test(String(L.instanceId||""))?L.instanceId:"";if(!O)throw new Error("instanceId locale non disponibile");j.current=O,b(O);const[X,ne]=await Promise.all([A?I(O):fl(e),_g(e,[]).catch(()=>({nodes:[]}))]),ce={instanceId:O,route:[],label:"Local"},fe=X.decks.map(me=>Fs(me,ce,ne.nodes,!0,!0)),pe=k.current;return await Promise.all(C.current.map(async me=>{if(me.status!=="up"){fe.push(...pe.filter(le=>!le.local&&le.ownerId===me.instanceId).map(le=>({...le,ownerRoute:[...me.route],ownerLabel:me.label,available:!1})));return}try{const[le,Ie]=await Promise.all([fl(e,me.route),_g(e,me.route).catch(()=>({nodes:[]}))]);fe.push(...le.decks.map(st=>Fs(st,me,Ie.nodes,!1,!0)))}catch{fe.push(...pe.filter(Ie=>!Ie.local&&Ie.ownerId===me.instanceId).map(Ie=>({...Ie,ownerRoute:[...me.route],ownerLabel:me.label,available:!1})))}})),fe.sort((me,le)=>me.local===le.local?me.ownerLabel.localeCompare(le.ownerLabel)||(me.name==="main"?-1:le.name==="main"?1:me.name.localeCompare(le.name)):me.local?-1:1),fe},[e,I,Z]);N.useEffect(()=>{if(!e)return;let A=!1;const L=V.current!==e;return V.current=e,M({migrate:L}).then(O=>{if(A)return;const X=k.current.find(fe=>fe.id===x.current),ne=O.find(fe=>fe.id===x.current),ce=ne&&(!X||ne.revision>X.revision||X.available!==ne.available||Fd(X.ownerRoute)!==Fd(ne.ownerRoute));G(O,L||!!ce&&!B.current),f(!0),ne&&y("")}).catch(O=>{A||(f(!0),y(String(O.message||O)))}),()=>{A=!0}},[G,M,Z,e]);const E=N.useCallback(async(A=x.current)=>{if(!h||!B.current)return!0;const L=k.current.find(O=>O.id===A);if(!L)return y(`deck inesistente: ${A}`),!1;if(L.available===!1)return y(`nodo owner offline: ${L.ownerLabel}`),!1;v("saving");try{const O=Kv(qs(F.current),L.ownerId,L.ownerTopology),X=await pl(e,L.name,O,L.revision,L.ownerRoute),ne=Fs(X,Bo(L),L.ownerTopology,L.local,!0);return G(k.current.map(ce=>ce.id===A?ne:ce),!1),B.current=!1,v("saved"),y(""),setTimeout(()=>v("idle"),1500),!0}catch(O){if(v("error"),y(String(O.message||O)),O.status===409&&O.data&&O.data.current){const X=k.current.find(ce=>ce.id===A),ne=Fs(O.data.current,Bo(X),X.ownerTopology,X.local,!0);G(k.current.map(ce=>ce.id===A?ne:ce),!1)}return!1}},[h,e,G]);return N.useEffect(()=>{if(!h)return;if(Y.current){Y.current=!1;return}B.current=!0,v("saving");const A=setTimeout(E,650);return()=>clearTimeout(A)},[n,h,E]),N.useEffect(()=>{if(!h)return;const A=setInterval(async()=>{try{const L=await M(),O=k.current.find(ce=>ce.id===x.current),X=L.find(ce=>ce.id===x.current),ne=X&&(!O||X.revision>O.revision||O.available!==X.available);G(L,ne&&!B.current)}catch{}},5e3);return()=>clearInterval(A)},[h,M,G]),{decks:a,records:a,localNodeId:w,ready:h,saveState:p,error:S,setError:y,saveNow:E,select:async A=>{if(B.current&&!await E(x.current))throw new Error("salvataggio del deck corrente fallito: cambio annullato");const L=k.current.find(O=>O.id===A);if(!L)throw new Error(`deck inesistente: ${A}`);return B.current=!1,Y.current=!0,q(L)},add:async(A,L=null)=>{const O=L===bi?k.current.find(ce=>ce.local):L?k.current.find(ce=>ce.ownerId===L):null;if(!O||O.available===!1)throw new Error("nodo owner non disponibile");const X=await Sg(e,A,O.ownerRoute),ne=Fs(X,Bo(O),O.ownerTopology,O.local,!0);return G([...k.current,ne],!1),ne},rename:async(A,L)=>{const O=k.current.find(pe=>pe.id===A);if(!O)throw new Error("deck inesistente");if(A===x.current&&B.current&&!await E(A))throw new Error(`salvataggio di "${O.name}" fallito: rinomina annullata`);const X=k.current.find(pe=>pe.id===A);if(!X)throw new Error("deck inesistente");const ne=await W0(e,X.name,L,X.revision,X.ownerRoute),ce=Fs(ne,Bo(X),X.ownerTopology,X.local,!0),fe=X.local?bi:X.ownerId;return hd(iN(Sl(),fe,A,ce.id)),G(k.current.map(pe=>pe.id===A?ce:pe),!1),ce},remove:async A=>{const L=k.current.find(X=>X.id===A);if(!L)throw new Error("deck inesistente");A===x.current&&(B.current=!1),await U0(e,L.name,L.revision,L.ownerRoute);const O=L.local?bi:L.ownerId;hd(sN(Sl(),O,A)),G(k.current.filter(X=>X.id!==A),!1)},reorder:(A,L)=>{const O=k.current.find(me=>me.id===A),X=k.current.find(me=>me.id===L);if(!O||!X)return!1;const ne=O.local?bi:O.ownerId,ce=X.local?bi:X.ownerId;if(ne!==ce)return!1;const fe=k.current.filter(me=>(me.local?bi:me.ownerId)===ne).map(me=>me.id),pe=hd(nN(Sl(),ne,A,L,fe));return G(Vv(k.current,pe),!1),!0},addTileTo:async(A,L)=>{const O=k.current.find(me=>me.id===A);if(!O)throw new Error("deck inesistente");if(O.available===!1)throw new Error(`nodo owner offline: ${O.ownerLabel}`);const X=kw(L,j.current,C.current);if(!X)throw new Error("riferimento sessione non valido");const ne=q(O),ce=Kv(dy(ne,X),O.ownerId,O.ownerTopology),fe=await pl(e,O.name,ce,O.revision,O.ownerRoute),pe=Fs(fe,Bo(O),O.ownerTopology,O.local,!0);return G(k.current.map(me=>me.id===A?pe:me),!1),pe},localMainId:Pr(null,"main"),parseDeckId:sc}}const Mj="/sw.js",Fh="nc-sw-update";let $h=null,Hh=!1,Wh=null,rb=Object.freeze({needed:!1,kind:null,version:""}),ob=!1;function ab(){typeof window<"u"&&window.dispatchEvent(new Event(Fh))}function lb(){const e=Wh||(Hh?{kind:"reload",version:""}:null);rb=Object.freeze({needed:!!e,kind:(e==null?void 0:e.kind)||null,version:(e==null?void 0:e.version)||""})}function B_(){return rb}function Ij(e){return typeof window>"u"?()=>{}:(window.addEventListener(Fh,e),()=>window.removeEventListener(Fh,e))}function Bf(e){Hh!==e&&(Hh=e,lb(),ab())}function Oj(e,t,n){let s=null;e&&t&&e!==t?s={kind:"install",version:e}:t&&n&&t!==n&&(s={kind:"reload",version:t});const o=JSON.stringify(s)===JSON.stringify(Wh);Wh=s,lb(),o||ab()}function Bj(e){e.addEventListener("statechange",()=>{e.state==="installed"&&navigator.serviceWorker.controller&&Bf(!0)})}function zj(){typeof navigator>"u"||!("serviceWorker"in navigator)||(navigator.serviceWorker.addEventListener("controllerchange",()=>{ob&&location.reload()}),navigator.serviceWorker.register(Mj).then(e=>{$h=e,e.waiting&&Bf(!0),e.addEventListener("updatefound",()=>{const t=e.installing;t&&Bj(t)}),setInterval(()=>{e.update().catch(()=>{})},3600*1e3)}).catch(()=>{}))}function Fj(){ob=!0,Bf(!1);const e=$h&&$h.waiting;e?(e.postMessage({type:"SKIP_WAITING"}),setTimeout(()=>location.reload(),4e3)):location.reload()}function $j({hash:e="",origin:t="",pathname:n="",search:s=""}={}){const o=String(e||"").replace(/^#/,""),a=`${n||""}${s||""}`;if(!o)return{token:"",pair:"",nextUrl:a};const u=new URLSearchParams(o),h=u.get("token")||"",f=u.get("pair")||"",p=f?`${t||""}${n||""}#pair=${f}`:"";return{token:h,pair:p,nextUrl:a}}const cb=9,ub=24,db="nc_side_w",z_="nc_side_min",Hj=240,F_="(min-width:1024px) and (pointer:fine)";function Wj(){const e=Number(localStorage.getItem(db));return e>=180&&e<=480?e:Hj}function Uj(){const e=Number(localStorage.getItem("nc_fontsize"));return e>=cb&&e<=ub?e:13}function Kj(){const e={token:"",pair:""};try{const{token:t,pair:n,nextUrl:s}=$j({hash:location.hash,origin:location.origin,pathname:location.pathname,search:location.search});if(t){e.token=t;try{localStorage.setItem("nc_token",t)}catch{}}if(n){e.pair=n;try{sessionStorage.setItem("nc_pair",n)}catch{}}if(location.hash)try{history.replaceState(null,"",s)}catch{}}catch{}if(e.token||(e.token=sessionStorage.getItem("nc_token")||localStorage.getItem("nc_token")||""),!e.pair){const t=sessionStorage.getItem("nc_pair");t&&(e.pair=t)}return e}function qj(e){try{return qs(Ih(e))}catch{return Rr()}}function $_(e){if(!e)return"";const t=Math.floor(Date.now()/1e3)-e;return t<0||t<60?"ora":t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}g`}function Vj(){const[e,t]=N.useState(()=>window.matchMedia(F_).matches);return N.useEffect(()=>{const n=window.matchMedia(F_),s=o=>t(o.matches);return n.addEventListener("change",s),()=>n.removeEventListener("change",s)},[]),e}function H_({session:e,node:t,ownerId:n,cellName:s,token:o,readonly:a=!1,onBack:u,onCellSwitcher:h,cellSwitcherOpen:f=!1}){Tn();const[p]=Sf(),[v,S]=N.useState(!1),[y,w]=N.useState(()=>window.matchMedia("(pointer: coarse)").matches),[b,k]=N.useState(null),[C,j]=N.useState(Uj),[x,F]=N.useState(s||e),[B,Y]=N.useState(""),V=$=>j(W=>{const R=Math.max(cb,Math.min(ub,W+$));return localStorage.setItem("nc_fontsize",String(R)),R}),z=N.useRef(()=>{}),Z=N.useRef(()=>!1),q=N.useRef(()=>{}),G=N.useRef(!1),[I,M]=N.useState(!1),[E,D]=N.useState(!1),T=()=>{G.current=!G.current,M(G.current)};return N.useEffect(()=>{F(s||e)},[s,e]),N.useEffect(()=>{let $=!0;const W=t?t.split("/"):[],R=t?`/api/route/${t.split("/").map(encodeURIComponent).join("/")}/_`:"/api";async function K(){let L=null,O=null;try{const ce=await(await Yt(`${R}/sessions`,o)).json();Array.isArray(ce.sessions)&&(L=ce.sessions.find(fe=>fe.name===e))}catch{}try{const ne=await ys(o,W);ne.available&&Array.isArray(ne.cells)&&(O=ne.cells.find(ce=>ce.tmuxSession===e))}catch{}if(!$)return;F(kf({session:e,cell:O||(s?{cell:s}:null)}));let X="";O?X=`${O.engine}${O.key?`·${O.key}`:""}`:L&&(X=L.attached?`attached · ${$_(L.activity)}`:L.activity?$_(L.activity):""),Y(X)}K();const A=setInterval(K,4e3);return()=>{$=!1,clearInterval(A)}},[e,t,o]),c.jsxs("div",{className:"nc-app",children:[c.jsxs("header",{className:"nc-bar nc-bar-single",children:[c.jsxs("button",{onClick:u,title:m("sessions"),children:[c.jsx(et,{name:"chevronLeft",size:18}),c.jsx("span",{className:"nc-bar-label",children:m("sessions")})]}),c.jsxs("span",{className:"nc-bar-center",children:[c.jsx("b",{title:t?`${x} · ${t}`:x,children:x}),B&&c.jsx("small",{className:"nc-bar-sub",children:B})]}),c.jsxs("span",{className:"nc-bar-right",children:[c.jsx("button",{onClick:()=>V(-1),title:m("zoom-out"),children:c.jsx(et,{name:"zoomOut",size:18})}),c.jsx("button",{onClick:()=>V(1),title:m("zoom-in"),children:c.jsx(et,{name:"zoomIn",size:18})}),c.jsx("button",{onClick:()=>w($=>!$),title:m("composer"),children:c.jsx(et,{name:"keyboard",size:20})}),c.jsx("button",{onClick:()=>S($=>!$),title:m("files"),children:c.jsx(et,{name:"folder",size:20})})]})]}),c.jsx("div",{className:"nc-termwrap",children:c.jsx(lw,{session:e,node:t,token:o,readonly:a,takeSize:!0,sendRef:z,composerRef:Z,actionRef:q,ctrlRef:G,setCtrlArmed:M,onFiles:k,fontSize:C,selectionMode:E,onSelectionModeChange:D,keyboardGesture:p.terminalKeyboardGesture})}),c.jsx(xE,{onKeyboard:()=>w($=>!$),onCellSwitcher:h,cellSwitcherOpen:f,send:$=>z.current($),action:$=>q.current($),ctrlArmed:I,onCtrl:T,selectionMode:E,onSelectionMode:D,keepKeyboardClosed:p.keybarKeepsKeyboardClosed,showEnter:p.showKeybarEnter,keybarLayout:p.keybarLayout}),y&&c.jsx(_w,{submitText:$=>Z.current($),token:o,session:e,node:t,ownerId:n,keepKeyboardClosedOnVoice:p.voiceKeepsKeyboardClosed}),v&&c.jsx(cw,{session:e,node:t,token:o,filesEvent:b,onClose:()=>S(!1)})]})}function Yj(){Tn();const[e]=N.useState(Kj),[t,n]=N.useState(e.token),[s,o]=N.useState(e.pair||""),a=N.useCallback(()=>{o("");try{sessionStorage.removeItem("nc_pair")}catch{}},[]),[u,h]=N.useState(!1),f=Vj(),[p]=N.useState(()=>ZE(typeof location<"u"?location.pathname:"/")),[v,S]=N.useState(p.id),y=v===Pr(null,Wn),[w,b]=N.useState(null),k=de=>{const je=_s(de);b(je?{...je,...typeof(de==null?void 0:de.cellName)=="string"&&de.cellName?{cellName:de.cellName}:{}}:null)},[C,j]=N.useState([]),[x,F]=N.useState([]),[B,Y]=N.useState([]),[V,z]=N.useState(()=>p.ownerId?Rr():qj(p.name)),[Z,q]=N.useState(null),[G,I]=N.useState(null),M=de=>I(_s(de)),E=ef(t,f),D=N.useMemo(()=>(E||[]).filter(de=>de.instanceId).map(de=>({instanceId:de.instanceId,route:de.route,label:de.label,status:de.status})),[E]),T=Dj(t,v,V,z,D),$=T.decks;N.useEffect(()=>{const de=new Map;for(const je of E||[]){const Ye=(je.route||[je.name]).join("/"),Et=new Set((je.sessions||[]).map(ut=>ut.name));for(const ut of je.cells||[])!ut.cell||!ut.tmuxSession||ut.cell===ut.tmuxSession||Et.has(ut.cell)||de.set(`${Ye}:${ut.cell}`,`${Ye}:${ut.tmuxSession}`)}z(je=>_1(je,de))},[E]),N.useEffect(()=>{T.localNodeId&&z(de=>{const je=Mh(de,T.localNodeId,D);return JSON.stringify(je)===JSON.stringify(de)?de:je})},[D,T.localNodeId]);const[W,R]=N.useState(null),[K,A]=N.useState(null),L=N.useRef(0),[O,X]=N.useState(!1),[ne,ce]=N.useState(Wj),[fe,pe]=N.useState(!y),[me,le]=N.useState(()=>y?localStorage.getItem(z_)==="1":!0),[Ie,st]=N.useState(!1),[We,Fe]=N.useState("nodes"),[Wt,Xt]=N.useState(!1),[Be,Lt]=N.useState(""),[gt,Bt]=N.useState(!1),rt=(de="nodes",je=!1,Ye="")=>{Fe(de),Xt(je),Lt(Ye),st(!0)},[lt,vt]=N.useState(!1),[oe,xe]=N.useState({deviceDefault:"",localNodeId:"",localNameDefault:""}),[De,$e]=N.useState(!1);N.useEffect(()=>{try{localStorage.setItem(db,String(ne))}catch{}},[ne]),N.useEffect(()=>{try{localStorage.setItem(z_,me?"1":"")}catch{}},[me]),N.useEffect(()=>{if(!t)return;let de=!1;return Promise.all([Q_(t),Yt("/api/config",t).then(je=>je.json())]).then(([je,Ye])=>{de||(xe({deviceDefault:je.deviceName||"",localNodeId:je.nodeId||"",localNameDefault:je.localName||""}),$e(!!Ye.readonlyDefault),(je.firstRun===!0&&!Ye.readonlyDefault||s)&&vt(!0))}).catch(()=>{}),()=>{de=!0}},[t,s]);const ue=N.useCallback(async()=>{try{const je=await(await Yt("/api/sessions",t)).json();je.error||j(je.sessions||[])}catch{}try{const de=await ys(t);F(de.available?de.cells||[]:[]),Y(de.available?de.capabilities||[]:[])}catch{F([]),Y([])}},[t]);N.useEffect(()=>{if(!f)return;ue();const de=setInterval(ue,4e3);return()=>clearInterval(de)},[f,ue]),N.useEffect(()=>{let de=!1;return Yt("/api/config",t).then(je=>je.json()).then(je=>{de||Oj(je.version,je.uiVersion,"0.8.52-rc.2")}).catch(()=>{}),()=>{de=!0}},[t]);const Q=new Set([...C.map(de=>de.name),...E.flatMap(de=>de.sessions.map(je=>je.key))]),te=ki(V),H=de=>z(je=>{const Ye=kw(de,T.localNodeId,D)||de,Et=dy(je,Ye);return Et===je&&ki(je).length>=9&&T.setError(m("grid-full")),Et}),ie=async(de,je=[])=>{try{await Yh(t,de,je)}catch{return}const Ye=je.length?`${je.join("/")}:${de}`:de;z(Et=>Hl(Et,Ye)),ue()},ve=async(de,je,Ye=[])=>{try{await X_(t,de,je,Ye)}catch{return}ue()},_e=async(de,je,Ye=[])=>{await V_(t,{cell:de,enabled:!!je},Ye),ue()},Ee=async de=>{if(!W)return;const{cell:je}=W,Ye=Array.isArray(W.route)?W.route:[];if(de.action==="up"){const ut=await qh(t,{cell:je,boot:!!de.boot,...de.engine?{engine:de.engine}:{},...de.model!==void 0?{model:de.model}:{},...de.permissionPolicy?{permissionPolicy:de.permissionPolicy}:{}},Ye),ii=lf(ut);ii&&T.setError(ii.text)}else await Ml(t,{cell:je,boot:!!de.boot},Ye);const Et=de.action==="up"?!!de.boot:de.boot?!1:!!W.boot;A({id:++L.current,cell:je,route:Ye,enabled:Et}),ue()},ye=N.useCallback(de=>{A(je=>(je==null?void 0:je.id)===de?null:je)},[]),Ne=async de=>{if(!(!(de!=null&&de.direct)||O)){X(!0);try{await Jh(t,de.name,de.tunnelStatus==="up"?"down":"up")}finally{X(!1)}}},Je=async(de,je)=>{const Ye=String(je||"").trim();return!(de!=null&&de.direct)||!Dr(Ye)?!1:(await J_(t,de.name,Ye),!0)},Ct=de=>{const je=$.find(Ye=>Ye.id===de);if(!je)return!1;try{const Ye=window.open(dd(je,t),"_blank");return Ye&&(Ye.opener=null),!!Ye}catch{return!1}},ze=async de=>{if(!de||de===v)return;const je=await T.select(de),Ye=T.records.find(Et=>Et.id===de);S(de),z(je),q(null),I(null);try{history.replaceState(null,"",dd(Ye||de,null))}catch{}},_n=async(de,je)=>{const Ye=await T.add(de,je);await ze(Ye.id)},ft=async(de,je)=>{const Ye=await T.rename(de,je);if(de===v){S(Ye.id),z(Mh(Ye.layout,T.localNodeId,D)),q(null),I(null);try{history.replaceState(null,"",dd(Ye,null))}catch{}}},Ge=async de=>{await T.remove(de),de===v&&await ze(T.localMainId)},Qt=async(de,je)=>{!je||je===v||(await T.addTileTo(je,de),z(Ye=>Hl(Ye,de)))};if(!t)return c.jsxs("div",{className:"nc-auth",children:[c.jsx("p",{children:m("auth-prompt")}),c.jsx("input",{onChange:de=>n(de.target.value.trim()),placeholder:"token"}),c.jsxs("label",{children:[c.jsx("input",{type:"checkbox",checked:u,onChange:de=>h(de.target.checked)})," ",m("remember-device")]}),c.jsx("button",{onClick:()=>{(u?localStorage:sessionStorage).setItem("nc_token",t)},children:"ok"})]});const Un=c.jsxs(c.Fragment,{children:[Ie&&c.jsx(yj,{token:t,initialTab:We,initialLocation:Be,startNewCell:Wt,onClose:()=>{st(!1),Xt(!1),Lt("")}}),lt&&c.jsx(wj,{token:t,initialPair:s,...oe,onPairDone:a,onDone:()=>vt(!1)}),c.jsx(Ej,{token:t})]});if(!f)return w?c.jsxs(c.Fragment,{children:[c.jsx(H_,{session:w.session,node:w.node,ownerId:w.ownerId,cellName:w.cellName,token:t,readonly:De,onBack:()=>b(null),onCellSwitcher:()=>Bt(!0),cellSwitcherOpen:gt}),gt&&c.jsx(Aj,{token:t,current:w,onPick:de=>{k(de),Bt(!1)},onClose:()=>Bt(!1)}),Un]}):c.jsxs(c.Fragment,{children:[c.jsx(M1,{onPick:k,token:t,onSettings:rt}),Un]});const ni=y||!fe;return c.jsxs("div",{className:"nc-workspace",children:[ni&&c.jsx($E,{sessions:C,cells:x,activeSessions:te,nodeGroups:E,fleetCapabilities:B,bootSettlement:K,onBootSettlementApplied:ye,localNodeId:T.localNodeId,onPick:M,onAddTile:H,onPower:R,onBoot:_e,onBootError:de=>T.setError(String((de==null?void 0:de.message)||de)),onNodePower:Ne,onNodeRename:Je,onKill:ie,onVisibility:ve,onNew:()=>rt("fleet",!0),onSettings:rt,width:ne,collapsed:me,onResize:ce,onToggleCollapse:()=>le(de=>!de)}),c.jsxs("div",{className:"nc-workspace-main",children:[c.jsx(SN,{decks:$,currentDeck:v,onCreate:_n,onRename:ft,onDelete:Ge,onReorder:T.reorder,onOpenWindow:Ct,onNavigate:ze,saveState:T.saveState,error:T.error,sidebarVisible:ni,onToggleSidebar:y?null:()=>pe(de=>!de)}),c.jsx(YE,{layout:V,onLayoutChange:z,token:t,readonly:De,sessionsAlive:Q,focusSession:Z,onFocus:q,onOpenSingle:M,decks:$,currentDeck:v,onSendToDeck:Qt,cells:x,nodeGroups:E})]}),G&&c.jsx("div",{className:"nc-single-overlay",children:c.jsx(H_,{session:G.session,node:G.node,ownerId:G.ownerId,cellName:kf({session:G.session,node:G.node,ownerId:G.ownerId,cells:x,nodeGroups:E}),token:t,readonly:De,onBack:()=>I(null)})}),W&&c.jsx(Ol,{cell:W,token:t,route:Array.isArray(W.route)?W.route:[],onConfirm:Ee,onClose:()=>R(null)}),Un]})}function Gj(){Tn();const e=N.useSyncExternalStore(Ij,B_,B_);if(!e.needed)return null;const t=e.kind==="install"?m("install-version-mismatch").replace("{v}",e.version):m("update-available").replace("{v}",e.version).replace(" "," ").trim();return c.jsxs("div",{className:"nc-update",role:"status","aria-live":"polite",children:[c.jsx("span",{className:"nc-update-msg",children:t}),e.kind==="reload"&&c.jsx("button",{className:"nc-update-btn",onClick:Fj,children:m("reload")})]})}zj();r0.createRoot(document.getElementById("root")).render(c.jsxs(JS.StrictMode,{children:[c.jsx(Yj,{}),c.jsx(Gj,{})]}));
@@ -11,7 +11,7 @@
11
11
  <meta name="apple-mobile-web-app-title" content="NexusCrew" />
12
12
  <link rel="manifest" href="/manifest.json" />
13
13
  <title>NexusCrew</title>
14
- <script type="module" crossorigin src="/assets/index-fWilj5EH.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-TqepO9Zm.js"></script>
15
15
  <link rel="stylesheet" crossorigin href="/assets/index-DNQLAGoa.css">
16
16
  </head>
17
17
  <body>
@@ -1 +1 @@
1
- {"version":"0.8.52-rc.1"}
1
+ {"version":"0.8.52-rc.2"}
package/lib/mcp/tools.js CHANGED
@@ -176,20 +176,8 @@ async function readVlDirectory(ctx) {
176
176
  const availableOwners = [];
177
177
  const unavailable = [];
178
178
  await Promise.all(owners.map(async (owner) => {
179
- // Le route /vl-nodes/* non sono federabili (NOTE in lib/proxy/federation.js).
180
- // Un owner remoto non e' irraggiungibile: e' chiuso per decisione. Chiamarlo
181
- // per raccogliere il 404 e riportarlo come 'unreachable' descriverebbe un
182
- // confine sano come un guasto, e manderebbe chi diagnostica a cercare un
183
- // tunnel che sta benissimo — proprio quando quel campo serve a distinguere
184
- // un nodo davvero muto.
185
- if (owner.route.length) {
186
- unavailable.push({
187
- instanceId: owner.instanceId, owner: owner.label,
188
- route: owner.route.join('/'), failure: 'policy-denied',
189
- });
190
- return;
191
- }
192
- const apiPath = '/api/vl-nodes';
179
+ const apiPath = owner.route.length ? routePath(owner.route, 'vl-nodes') : '/api/vl-nodes';
180
+ if (!apiPath) return;
193
181
  try {
194
182
  const payload = await ctx.api('GET', apiPath);
195
183
  if (String(payload && payload.instanceId || '') !== owner.instanceId
@@ -105,20 +105,25 @@ function knownResource(resource) {
105
105
  || resource === '/files/upload'
106
106
  || resource === '/cells'
107
107
  || resource === '/cells/send'
108
- // NOTE: `/vl-nodes`, `/vl-nodes/invite`, `/vl-nodes/:id` and
109
- // `/vl-nodes/:id/commands` were federated when the VL bridge was written.
110
- // They were removed before the bridge ever shipped. `commands` accepts
111
- // `update_candidate`, which names the URL the device downloads its own
112
- // update from — and accepts `http:` — while the `sha256` guarantees
113
- // nothing, because the sender supplies both the URL and the hash. Federated,
114
- // that lets a paired peer install an arbitrary binary on someone else's
115
- // device.
108
+ // VL nodes are federated like every other resource: where you connect, you
109
+ // see everything. That is how NexusCrew works today, and VL nodes are its
110
+ // arms an unfederated island would break the alignment on purpose.
116
111
  //
117
- // Same class as `/settings/peering/invite` below: a capability that extends
118
- // trust past the boundary the owner chose. Denied by default; it can be
119
- // federated the day the update channel is bound to something the receiving
120
- // owner controls, not before. Local `/vl-nodes/*` calls are unaffected
121
- // this is the federation allowlist only.
112
+ // These four were briefly removed on 2026-08-05 over `update_candidate`,
113
+ // which names the URL a device fetches its own update from and accepts
114
+ // `http:`. The removal was wrong on both counts. It was incoherent: a paired
115
+ // peer is trusted as its owner (docs/SECURITY.md). And it was ineffective:
116
+ // `/fleet/define-engine` + `/fleet/up` are federated, so a peer can already
117
+ // define an arbitrary command and run it on the host — including one that
118
+ // calls the local `/api/vl-nodes` endpoints. The door was shut next to an
119
+ // open window.
120
+ //
121
+ // `update_candidate` is still a real defect. It belongs to the command, not
122
+ // to this allowlist: bind the update channel to something the receiving
123
+ // owner controls. Fixing it here only hid it.
124
+ || resource === '/vl-nodes'
125
+ || resource === '/vl-nodes/invite'
126
+ || /^\/vl-nodes\/[a-f0-9]{32}(?:\/commands)?$/.test(resource)
122
127
  || resource === '/decks'
123
128
  || /^\/decks\/[a-z0-9-]{1,32}$/.test(resource)
124
129
  || resource === '/topology'
@@ -155,7 +160,10 @@ function allowedResource(resource, method = 'GET') {
155
160
  if (resource === '/files/upload') return method === 'POST';
156
161
  if (resource === '/cells') return method === 'GET';
157
162
  if (resource === '/cells/send') return method === 'POST';
158
- // `/vl-nodes/*` is deliberately absent — see the NOTE in `knownResource`.
163
+ if (resource === '/vl-nodes') return method === 'GET';
164
+ if (resource === '/vl-nodes/invite') return method === 'POST';
165
+ if (/^\/vl-nodes\/[a-f0-9]{32}\/commands$/.test(resource)) return method === 'POST';
166
+ if (/^\/vl-nodes\/[a-f0-9]{32}$/.test(resource)) return method === 'DELETE';
159
167
  if (resource === '/decks') return method === 'GET' || method === 'POST';
160
168
  if (/^\/decks\/[a-z0-9-]{1,32}$/.test(resource)) {
161
169
  return method === 'PUT' || method === 'PATCH' || method === 'DELETE';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/nexuscrew",
3
- "version": "0.8.52-rc.1",
3
+ "version": "0.8.52-rc.2",
4
4
  "description": "Faithful browser tmux client — attach to live sessions over a real PTY, localhost-only, mobile-easy",
5
5
  "main": "lib/server.js",
6
6
  "bin": {