@frumu/tandem-panel 0.4.41 → 0.4.42

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.
@@ -7369,7 +7369,7 @@ Return:
7369
7369
 
7370
7370
  Do not guarantee ranking outcomes or propose manipulative tactics unless explicitly requested by the parent agent.`,tags:[`seo`,`specialist`,`specialized`,`domains`,`read-only`],requires:[],role:`worker`}]},Ov=`tandem.studio.agentCatalogHandoff`,kv=[`worker`,`reviewer`,`tester`,`watcher`,`delegator`,`committer`,`orchestrator`],Av={worker:`Executes hands-on work and reports concrete progress.`,reviewer:`Critiques output, spots risks, and improves quality.`,tester:`Validates behavior and looks for regressions or gaps.`,watcher:`Monitors activity, incidents, and changes over time.`,delegator:`Breaks work down and routes tasks across participants.`,committer:`Finalizes work and drives it toward completion.`,orchestrator:`Coordinates multi-agent flow and synthesizes updates.`},jv=[`You are the frontend lead. Focus on shipped UI changes, active branches, visual regressions, and blockers from design or review.`,`You are the backend lead. Focus on APIs, database work, deploys, incidents, and blockers from reliability or dependencies.`,`You are the product and ops agent. Focus on launches, customer feedback, analytics, triage, and operational blockers.`],Mv={templateId:``,displayName:``,avatarUrl:``,role:`worker`,systemPrompt:``,modelProvider:``,modelId:``};function Nv(e,t){return Array.isArray(e)?e:Array.isArray(e?.[t])?e[t]:[]}function Pv(e){let t=e?.default_model||e?.defaultModel||{};return{templateId:String(e?.template_id||e?.templateID||e?.id||``).trim(),displayName:String(e?.display_name||e?.displayName||e?.name||``).trim(),avatarUrl:String(e?.avatar_url||e?.avatarUrl||``).trim(),role:String(e?.role||`worker`).trim()||`worker`,systemPrompt:String(e?.system_prompt||e?.systemPrompt||``).trim(),modelProvider:String(t?.provider_id||t?.providerId||``).trim(),modelId:String(t?.model_id||t?.modelId||``).trim()}}function Fv(e){let t={templateID:e.templateId.trim(),display_name:e.displayName.trim()||void 0,avatar_url:e.avatarUrl.trim()||void 0,role:e.role,system_prompt:e.systemPrompt.trim()||void 0,skills:[],default_budget:{},capabilities:{}};return e.modelProvider.trim()&&e.modelId.trim()&&(t.default_model={provider_id:e.modelProvider.trim(),model_id:e.modelId.trim()}),t}function Iv(e){return String(e||``).trim().toLowerCase()}function Lv(e){return String(e.instructions||``).trim().split(/\n\s*\n/).find(Boolean)?.trim()||e.summary}function Rv({client:e,toast:t,navigate:n}){let i=_(),s=e?.agentTeams,l=c(null),[u,d]=r(Mv),[f,p]=r(null),[h,g]=r(``),[v,b]=r(`all`),[S,C]=r(``),[w,T]=r(``),[E,D]=r(()=>Iu()),O=c(null),k=c(null),A=dc().data?.agent_teams===!0,j=y({queryKey:[`teams`,`health`],queryFn:()=>e?.health?.().catch(()=>({}))??Promise.resolve({}),refetchInterval:3e4}),M=String(j.data?.workspaceRoot||j.data?.workspace_root||``).trim(),N=String(w||M||``).trim();m(()=>{M&&T(e=>e||M)},[M]);let P=y({queryKey:[`teams`,`templates`],queryFn:()=>s?.listTemplates?.().catch(()=>({templates:[]}))??Promise.resolve({templates:[]}),refetchInterval:8e3}),F=y({queryKey:[`teams`,`instances`],queryFn:()=>s?.listInstances?.().catch(()=>({instances:[]}))??Promise.resolve({instances:[]}),refetchInterval:8e3}),I=y({queryKey:[`teams`,`approvals`],queryFn:()=>s?.listApprovals?.().catch(()=>({spawnApprovals:[]}))??Promise.resolve({spawnApprovals:[]}),refetchInterval:6e3}),L=x({mutationFn:async()=>{if(!u.templateId.trim())throw Error(`Template ID is required.`);return f?s?.updateTemplate?.(f,{display_name:u.displayName.trim()||void 0,avatar_url:u.avatarUrl.trim()||void 0,role:u.role,system_prompt:u.systemPrompt.trim()||void 0,default_model:u.modelProvider.trim()&&u.modelId.trim()?{provider_id:u.modelProvider.trim(),model_id:u.modelId.trim()}:void 0}):s?.createTemplate?.({template:Fv(u)})},onSuccess:async()=>{t(`ok`,f?`Template updated.`:`Template created.`),d(Mv),p(null),await i.invalidateQueries({queryKey:[`teams`]})},onError:e=>t(`err`,e instanceof Error?e.message:String(e))}),R=x({mutationFn:e=>s?.deleteTemplate?.(e),onSuccess:async()=>{t(`ok`,`Template deleted.`),f&&(p(null),d(Mv)),await i.invalidateQueries({queryKey:[`teams`]})},onError:e=>t(`err`,e instanceof Error?e.message:String(e))}),z=x({mutationFn:({requestId:e,decision:t})=>t===`approve`?s?.approveSpawn?.(e):s?.denySpawn?.(e),onSuccess:async()=>{t(`ok`,`Approval updated.`),await i.invalidateQueries({queryKey:[`teams`]})},onError:e=>t(`err`,e instanceof Error?e.message:String(e))}),ee=o(()=>Nv(P.data,`templates`).map(Pv).filter(e=>e.templateId),[P.data]),B=Nv(F.data,`instances`),V=Nv(I.data,`spawnApprovals`),H=!!(f||u.templateId||u.displayName||u.systemPrompt),te=u.displayName.trim()||u.templateId.trim()||`New Agent`,U=te.slice(0,1).toUpperCase()||`A`,ne=Av[u.role],re=u.avatarUrl.trim(),ie=o(()=>{let e=Iv(h);return Dv.agents.filter(t=>v!==`all`&&t.category_id!==v?!1:e?[t.name,t.summary,t.category_title,t.category_id,t.source_path,t.source_file,t.sandbox_mode,t.role,...t.tags||[],...t.requires||[]].join(` `).toLowerCase().includes(e):!0)},[v,h]),ae=o(()=>{let e=new Map;for(let t of ie){let n=e.get(t.category_id)||[];n.push(t),e.set(t.category_id,n)}return Dv.categories.map(t=>({...t,agents:e.get(t.id)||[]})).filter(e=>e.agents.length>0)},[ie]);m(()=>{let e=l.current;e&&Mr(e)},[ee.length,B.length,V.length,u.role,u.templateId,u.displayName,u.avatarUrl,u.modelProvider,u.modelId,u.systemPrompt,f,L.isPending,R.isPending,z.isPending]);let[oe,se]=r(``),ce=async e=>{try{await navigator.clipboard.writeText(e),se(e),C(`Copied: ${e}`),setTimeout(()=>se(t=>t===e?``:t),2e3)}catch(e){C(e instanceof Error?e.message:String(e))}},le=e=>{try{sessionStorage.setItem(Ov,JSON.stringify({agentId:e.id,displayName:e.name,categoryId:e.category_id,categoryTitle:e.category_title,summary:e.summary,sourcePath:e.source_path,sandboxMode:e.sandbox_mode,role:e.role,tags:e.tags,requires:e.requires,instructions:e.instructions}));let t=window.location.href.replace(/#.*$/,``);window.open(`${t}#studio`,`_blank`,`noopener`)}catch(e){t(`err`,e instanceof Error?e.message:String(e))}},ue=e=>{let t=e.name.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``),n={worker:`worker`,reviewer:`reviewer`,delegator:`delegator`,orchestrator:`orchestrator`,watcher:`watcher`,committer:`committer`,tester:`tester`}[e.role]??`worker`;p(null),d({templateId:t,displayName:e.name,avatarUrl:``,role:n,systemPrompt:[e.summary,Lv(e)===e.summary?``:Lv(e)].filter(Boolean).join(`
7371
7371
 
7372
- `).trim(),modelProvider:``,modelId:``}),C(`Imported "${e.name}" into the agent form — review and save below.`),setTimeout(()=>{k.current?.scrollIntoView({behavior:`smooth`,block:`start`})},80)},de=e=>{if(!e)return;if(e.size>10*1024*1024){t(`err`,`Avatar image is too large (max 10 MB).`);return}let n=new FileReader;n.onload=()=>{let e=typeof n.result==`string`?n.result:``;if(!e){t(`err`,`Failed to read avatar image.`);return}d(t=>({...t,avatarUrl:e}))},n.onerror=()=>t(`err`,`Failed to read avatar image.`),n.readAsDataURL(e)};return a(`div`,{ref:l,className:`grid gap-4`,children:[A&&a(yr,{title:`Agent Standup`,subtitle:`Compose scheduled standups from the same saved agents you manage here`,children:a(Ev,{client:e,toast:t,workspaceRoot:N,onWorkspaceRootChange:T,defaultWorkspaceRoot:M,timezone:E,onTimezoneChange:D,templates:ee.map(e=>({templateId:e.templateId,displayName:e.displayName||e.templateId,role:e.role,modelLabel:e.modelProvider&&e.modelId?`${e.modelProvider}/${e.modelId}`:``}))})}),a(yr,{title:`Agent Catalog`,subtitle:`Browse and import from the canonical Codex subagent set. Use any entry to pre-fill the agent form below.`,children:a(`div`,{className:`grid gap-3`,children:[a(`div`,{className:`grid gap-2 md:grid-cols-[1fr_auto]`,children:[a(`input`,{className:`tcp-input`,placeholder:`Search agent name, category, tag, or path`,value:h,onInput:e=>g(e.target.value)}),a(`button`,{className:`tcp-btn`,onClick:()=>{g(``),b(`all`)},disabled:!h&&v===`all`,children:`Clear`})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${v===`all`?`border-amber-400/60 bg-amber-400/10`:``}`,onClick:()=>b(`all`),children:`All`}),Dv.categories.map(e=>a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${v===e.id?`border-amber-400/60 bg-amber-400/10`:``}`,onClick:()=>b(e.id),children:[e.title,` (`,e.count,`)`]},e.id))]}),S?a(`div`,{className:`text-xs text-slate-400`,children:S}):null,ae.length?ae.map(e=>a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`flex items-start justify-between gap-2`,children:[a(`div`,{children:[a(`div`,{className:`font-medium text-slate-100`,children:e.title}),a(`div`,{className:`text-xs text-slate-400`,children:e.summary})]}),a(`div`,{className:`tcp-badge-info`,children:[e.agents.length,` agents`]})]}),a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:e.agents.map(e=>a(`div`,{className:`tcp-list-item grid gap-2`,children:[a(`div`,{className:`flex items-start justify-between gap-2`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`truncate font-semibold text-slate-100`,children:e.name}),a(`div`,{className:`text-xs text-slate-400`,children:e.summary})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`span`,{className:`tcp-badge-info`,children:e.role}),a(`span`,{className:e.sandbox_mode===`read-only`?`tcp-badge-warn`:`tcp-badge-ok`,children:e.sandbox_mode})]})]}),a(`div`,{className:`font-mono text-xs text-slate-400`,children:e.source_path}),a(`div`,{className:`line-clamp-3 text-xs text-slate-200`,children:Lv(e)}),a(`div`,{className:`flex flex-wrap gap-1`,children:[e.tags.slice(0,4).map(t=>a(`span`,{className:`tcp-badge-muted`,children:t},`${e.id}-${t}`)),e.requires.slice(0,3).map(t=>a(`span`,{className:`tcp-badge-info`,children:t},`${e.id}-${t}`))]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn h-8 px-3 text-xs`,title:`Pre-fill the agent creation form from this catalog entry`,onClick:()=>ue(e),children:[a(`i`,{"data-lucide":`download`}),`Import as Agent`]}),a(`button`,{className:`tcp-btn h-8 px-3 text-xs`,title:`Open this agent in Studio (new tab)`,onClick:()=>le(e),children:[a(`i`,{"data-lucide":`external-link`}),`Studio ↗`]}),a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${oe===e.source_path?`border-emerald-400/60 bg-emerald-400/10 text-emerald-300`:``}`,title:`Copy source path to clipboard`,onClick:()=>void ce(e.source_path),children:[a(`i`,{"data-lucide":oe===e.source_path?`check`:`copy`}),oe===e.source_path?`Copied`:`Copy path`]})]})]},e.source_path))})]},e.id)):a(br,{text:`No agents match your search.`})]})}),a(`div`,{className:`grid gap-4 xl:grid-cols-2`,children:[a(`div`,{ref:k,children:a(yr,{title:`Agents`,subtitle:`Create reusable agent personalities, prompts, and default models for automation workflows`,children:a(`div`,{className:`grid gap-3`,children:[a(`div`,{className:`rounded-2xl border border-cyan-500/20 bg-cyan-500/5 p-4`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-cyan-300`,children:`Reusable Personalities`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:`Each saved agent defines a persistent personality for automation workflows. Define who the agent is, what kind of work it owns, and which default model it should use. These personalities can be reused in standups and other workflow responses.`})]}),a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:[a(`input`,{className:`tcp-input`,placeholder:`template-id`,value:u.templateId,disabled:!!f,onInput:e=>d(t=>({...t,templateId:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Display name`,value:u.displayName,onInput:e=>d(t=>({...t,displayName:e.target.value}))}),a(`select`,{className:`tcp-input`,value:u.role,onInput:e=>d(t=>({...t,role:e.target.value})),children:kv.map(e=>a(`option`,{value:e,children:e},e))}),a(`input`,{className:`tcp-input`,placeholder:`Avatar URL or upload (optional)`,value:u.avatarUrl,onInput:e=>d(t=>({...t,avatarUrl:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Model provider (optional)`,value:u.modelProvider,onInput:e=>d(t=>({...t,modelProvider:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Model ID (optional)`,value:u.modelId,onInput:e=>d(t=>({...t,modelId:e.target.value}))})]}),a(`div`,{className:`grid gap-3 lg:grid-cols-[1.15fr_0.85fr]`,children:[a(`div`,{className:`rounded-2xl border border-slate-800/80 bg-slate-950/40 px-4 py-3`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Prompt Guidance`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:`Write the lasting perspective for this agent, not a one-off task. Good prompts describe ownership and judgment: frontend lead, backend lead, product ops, incident watcher.`}),a(`div`,{className:`mt-3 flex flex-wrap gap-2`,children:jv.map(e=>a(`button`,{type:`button`,className:`tcp-btn h-auto min-h-8 px-3 py-2 text-left text-xs`,onClick:()=>d(t=>({...t,systemPrompt:e})),children:`Use Example`},e))})]}),a(`div`,{className:`rounded-[28px] border border-slate-800/80 bg-[radial-gradient(circle_at_top,_rgba(34,211,238,0.18),_transparent_45%),linear-gradient(180deg,rgba(15,23,42,0.9),rgba(2,6,23,0.96))] p-5`,children:[a(`div`,{className:`flex items-start justify-between gap-4`,children:[a(`div`,{className:`flex items-start gap-4`,children:[a(`div`,{className:`flex h-14 w-14 items-center justify-center overflow-hidden rounded-2xl border border-cyan-400/30 bg-cyan-400/10 text-lg font-semibold text-cyan-100`,children:re?a(`img`,{src:re,alt:te,className:`h-full w-full object-cover`}):U}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`flex flex-wrap items-center gap-2`,children:[a(`strong`,{className:`text-white`,children:te}),a(`span`,{className:`tcp-badge-info`,children:u.role})]}),a(`div`,{className:`mt-1 text-xs text-slate-400`,children:u.templateId.trim()||`template-id`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:ne})]})]}),a(`div`,{className:`flex items-center gap-2`,children:[a(`button`,{type:`button`,className:`tcp-icon-btn`,title:`Upload avatar`,"aria-label":`Upload avatar`,onClick:()=>O.current?.click(),children:a(`i`,{"data-lucide":`pencil`})}),a(`button`,{type:`button`,className:`tcp-icon-btn`,title:`Clear avatar`,"aria-label":`Clear avatar`,onClick:()=>d(e=>({...e,avatarUrl:``})),children:a(`i`,{"data-lucide":`trash-2`})})]})]}),a(`div`,{className:`mt-3 text-xs text-slate-400`,children:`Upload an image like Settings Identity preview, or paste a direct avatar URL.`}),a(`input`,{ref:O,type:`file`,accept:`image/*`,className:`hidden`,onChange:e=>{de(e.target.files?.[0]||null),e.target.value=``}}),a(`div`,{className:`mt-4 rounded-2xl border border-slate-800/70 bg-black/20 p-4`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Personality Preview`}),a(`div`,{className:`mt-2 whitespace-pre-wrap text-sm leading-6 text-slate-200`,children:u.systemPrompt.trim()||`This agent will respond from the persistent personality you define here across workflows and standups.`})]}),(u.modelProvider.trim()||u.modelId.trim())&&a(`div`,{className:`mt-3 text-xs text-cyan-200`,children:[`Default model: `,u.modelProvider.trim()||`provider`,`/`,u.modelId.trim()||`model`]})]})]}),a(`textarea`,{className:`tcp-input min-h-[140px]`,placeholder:`Persistent system prompt`,value:u.systemPrompt,onInput:e=>d(t=>({...t,systemPrompt:e.target.value}))}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn`,disabled:L.isPending,onClick:()=>L.mutate(),children:[a(`i`,{"data-lucide":`save`}),f?`Update Agent`:`Create Agent`]}),H&&a(`button`,{type:`button`,className:`tcp-btn`,onClick:()=>{p(null),d(Mv)},children:[a(`i`,{"data-lucide":`rotate-ccw`}),`Reset`]})]}),a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`flex items-center justify-between gap-2`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Saved Agents`}),a(`div`,{className:`tcp-subtle text-xs`,children:[ee.length,` saved`]})]}),ee.length?ee.map(e=>a(`div`,{className:`tcp-list-item`,children:a(`div`,{className:`flex items-start justify-between gap-3`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`flex items-center gap-2`,children:[a(`strong`,{children:e.displayName||e.templateId}),a(`span`,{className:`tcp-badge-info`,children:e.role}),e.modelProvider&&e.modelId?a(`span`,{className:`tcp-badge-ok`,children:[e.modelProvider,`/`,e.modelId]}):null]}),a(`div`,{className:`tcp-subtle text-xs`,children:e.templateId}),e.systemPrompt?a(`div`,{className:`mt-2 line-clamp-4 text-xs text-slate-300`,children:e.systemPrompt}):a(`div`,{className:`mt-2 text-xs text-slate-500`,children:`No persistent prompt set yet.`})]}),a(`div`,{className:`flex gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn h-7 px-2 text-xs`,onClick:()=>{p(e.templateId),d({templateId:e.templateId,displayName:e.displayName,avatarUrl:e.avatarUrl,role:kv.includes(e.role)?e.role:`worker`,systemPrompt:e.systemPrompt,modelProvider:e.modelProvider,modelId:e.modelId})},children:[a(`i`,{"data-lucide":`pencil`}),`Edit`]}),a(`button`,{type:`button`,className:`tcp-btn-danger h-7 px-2 text-xs`,onClick:()=>R.mutate(e.templateId),children:[a(`i`,{"data-lucide":`trash-2`}),`Delete`]})]})]})},e.templateId)):a(br,{title:`No agents yet`,text:`Create your first saved personality here, then reuse it across automation workflows and standups.`})]})]})})}),a(yr,{title:`Team Instances`,subtitle:`Running collaborative agent instances`,children:a(`div`,{className:`grid gap-2`,children:B.length?B.map((e,t)=>a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[a(`strong`,{children:String(e?.template_id||e?.templateID||e?.instance_id||`Instance`)}),a(`span`,{className:`tcp-badge-info`,children:String(e?.status||`active`)})]}),a(`div`,{className:`tcp-subtle text-xs`,children:[`mission: `,String(e?.mission_id||e?.missionID||`n/a`)]})]},String(e?.instance_id||e?.id||t))):a(br,{text:`No team instances found.`})})}),a(yr,{title:`Spawn Approvals`,subtitle:`Pending team approval requests`,children:a(`div`,{className:`grid gap-2`,children:V.length?V.map((e,t)=>{let n=String(e?.approval_id||e?.request_id||e?.id||`request-${t}`);return a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`mb-1 font-medium`,children:String(e?.reason||e?.title||n)}),a(`div`,{className:`tcp-subtle text-xs`,children:n}),a(`div`,{className:`mt-2 flex gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn h-7 px-2 text-xs`,onClick:()=>z.mutate({requestId:n,decision:`approve`}),children:[a(`i`,{"data-lucide":`badge-check`}),`Approve`]}),a(`button`,{type:`button`,className:`tcp-btn-danger h-7 px-2 text-xs`,onClick:()=>z.mutate({requestId:n,decision:`deny`}),children:[a(`i`,{"data-lucide":`x`}),`Deny`]})]})]},n)}):a(br,{text:`No pending approvals.`})})})]})]})}function zv({theme:e}){let t=e?.cssVars?.[`--color-background`]||`#000000`,n=e?.cssVars?.[`--color-surface`]||`#111111`,r=e?.cssVars?.[`--color-primary`]||`#ffffff`,i=e?.cssVars?.[`--color-secondary`]||`#ffffff`;return a(`div`,{className:`flex items-center gap-2`,children:[a(`span`,{className:`tcp-theme-swatch`,style:{background:t},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:n},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:r},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:i},"aria-hidden":`true`})]})}function Bv({themes:e,themeId:t,onChange:n}){return a(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.map(e=>{let r=e.id===t;return a(s.button,{type:`button`,layout:!0,onClick:()=>n(e.id),className:`tcp-theme-tile ${r?`active`:``}`,whileHover:{y:-2},whileTap:{scale:.985},transition:Nn.spring.gentle,children:[a(`div`,{className:`tcp-theme-tile-top`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`tcp-theme-tile-title`,children:e.name}),a(`p`,{className:`tcp-subtle mt-1 text-xs`,children:e.description})]}),a(zv,{theme:e})]}),a(`div`,{className:`tcp-theme-preview`,children:a(`div`,{className:`tcp-theme-preview-bg`,style:{background:e.cssVars[`--color-background`]||`#000`},children:a(`div`,{className:`tcp-theme-preview-card`,style:{background:e.cssVars[`--color-surface`]||`#111`,borderColor:e.cssVars[`--color-border`]||`rgba(255,255,255,0.1)`},children:[a(`div`,{className:`tcp-theme-preview-line short`,style:{background:e.cssVars[`--color-text`]||`#fff`}}),a(`div`,{className:`tcp-theme-preview-line`,style:{background:e.cssVars[`--color-text-muted`]||`#aaa`}}),a(`div`,{className:`tcp-theme-preview-pill`,style:{background:e.cssVars[`--color-primary`]||`#fff`}})]})})}),a(l,{initial:!1,children:r?a(s.span,{className:`tcp-theme-active`,initial:{opacity:0,scale:.86},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.86},transition:Nn.spring.snappy,children:[a(`i`,{"data-lucide":`badge-check`}),`Active`]}):null})]},e.id)})})}var Vv=`tcp.nav.visibility.v1`,Hv=new Set([`dashboard`,`chat`,`workflows`,`automations`,`coding`,`settings`]);function Uv(e){let t=new Set([`planner`,`studio`,`coding`,`memory`,`files`,`marketplace`,`orchestrator`,`experiments`,`teams`]);return Object.fromEntries(lr.map(([n])=>[n,e?Hv.has(n):!t.has(n)]))}function Wv(e,t){let n=Uv(t);if(!e||typeof e!=`object`)return n;let r=e,i={...n};for(let[e]of lr)typeof r[e]==`boolean`&&(i[e]=r[e]);if(t)for(let e of Hv)i[e]=!0;return i}function Gv(e){try{let t=localStorage.getItem(Vv);return t?Wv(JSON.parse(t),e):Uv(e)}catch{return Uv(e)}}function Kv(e){try{localStorage.setItem(Vv,JSON.stringify(e))}catch{}}function qv(e){return lr.filter(([t])=>e[t]!==!1)}var Jv=`tandem_control_panel_pending_provider_oauth`;function Yv(){if(typeof window>`u`)return{};try{let e=window.sessionStorage.getItem(Jv)||``;if(!e)return{};let t=JSON.parse(e);return!t||typeof t!=`object`?{}:Object.fromEntries(Object.entries(t).map(([e,t])=>[String(e||``).trim().toLowerCase(),String(t||``).trim()]).filter(([e,t])=>!!e&&!!t))}catch{return{}}}function Xv(e){if(!(typeof window>`u`))try{let t=Object.fromEntries(Object.entries(e||{}).map(([e,t])=>[String(e||``).trim().toLowerCase(),String(t||``).trim()]).filter(([e,t])=>!!e&&!!t));if(!Object.keys(t).length){window.sessionStorage.removeItem(Jv);return}window.sessionStorage.setItem(Jv,JSON.stringify(t))}catch{}}var Zv=new Set([`openai`,`openai-codex`,`openrouter`,`anthropic`,`ollama`,`groq`,`mistral`,`together`,`azure`,`bedrock`,`vertex`,`copilot`,`cohere`]),Qv=`openai-codex`,$v=[`telegram`,`discord`,`slack`];function ey(e){let t=String(e||``).trim().toLowerCase();return t.startsWith(`mcp_header::`)||t.startsWith(`channel::`)}var ty=[{label:`File`,tools:[`read`,`glob`,`ls`,`list`,`grep`,`codesearch`,`search`]},{label:`Web`,tools:[`websearch`,`webfetch`,`webfetch_html`]},{label:`Terminal`,tools:[`bash`,`write`,`edit`,`apply_patch`]},{label:`Memory`,tools:[`memory_search`,`memory_store`,`memory_list`]},{label:`Other`,tools:[`skill`,`task`,`question`,`pack_builder`]}],ny=`tandem.workflow_planner`,ry=[`websearch`,`webfetch`,`webfetch_html`,`memory_search`,`memory_store`,`memory_list`];function iy(e){try{return new URL(e)}catch{return null}}function ay(e){return String(e||``).trim().toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^-+|-+$/g,``)||`mcp-server`}function oy(e){let t=iy(e);if(!t)return``;let n=String(t.hostname||``).toLowerCase();if(!n)return``;if(n.endsWith(`composio.dev`))return`composio`;let r=n.split(`.`).filter(Boolean);return r.length?ay([`backend`,`api`,`mcp`,`www`].includes(r[0])&&r[1]||r[0]):``}function sy(e){let t=iy(e);return t?String(t.hostname||``).toLowerCase().endsWith(`composio.dev`):!1}function cy(e){let t=iy(e);if(!t)return!1;let n=String(t.hostname||``).toLowerCase();return n===`api.githubcopilot.com`||n.endsWith(`.githubcopilot.com`)}function ly(e){let t=iy(e);if(!t)return!1;let n=String(t.hostname||``).toLowerCase();return n===`mcp.notion.com`||n.endsWith(`.notion.com`)}function uy(e,t){return String(e||``).trim().toLowerCase()===`notion`||ly(t)?`Notion uses browser OAuth. Save the server, finish the Notion sign-in in your browser, then come back and click Mark sign-in complete. Token paste is not the right flow for this MCP.`:`This MCP server uses browser OAuth. Save it, complete the authorization page that opens in your browser, then come back and finish the connection in Tandem.`}function dy(e){return e.map(e=>({key:String(e?.key||``).trim(),value:String(e?.value||``).trim()}))}function fy(e,t){let n={...e};for(let e of dy(t))!e.key||!e.value||(n[e.key]=e.value);return n}function py({authMode:e,token:t,customHeader:n,transport:r}){let i=String(t||``).trim();if(e===`oauth`||!i||e===`none`)return{};if(e===`custom`){let e=String(n||``).trim();if(!e)throw Error(`Custom header name is required.`);return{[e]:i}}return e===`x-api-key`?{"x-api-key":i}:e===`bearer`?{Authorization:`Bearer ${i.replace(/^bearer\s+/i,``).trim()}`}:sy(r)?{"x-api-key":i}:{Authorization:`Bearer ${i.replace(/^bearer\s+/i,``).trim()}`}}function my(e,t,n,r){return e===`oauth`?`OAuth handoff: Tandem will open the server authorization flow on connect.`:!String(t||``).trim()||e===`none`?`No auth header will be sent.`:e===`custom`?n?`Header preview: ${n}: <token>`:`Set a custom header name.`:e===`x-api-key`?`Header preview: x-api-key: <token>`:e===`bearer`?`Header preview: Authorization: Bearer <token>`:sy(r)?`Auto mode: selected x-api-key for this endpoint`:`Auto mode: using Authorization Bearer token`}function hy(e,t=``){if(!e||typeof e!=`object`)return null;let n=e,r=String(n.name||t||``).trim();if(!r)return null;let i=n.last_auth_challenge||n.lastAuthChallenge||null;return{name:r,transport:String(n.transport||``).trim(),authKind:String(n.auth_kind||n.authKind||``).trim().toLowerCase(),connected:!!n.connected,enabled:n.enabled!==!1,lastError:String(n.last_error||n.lastError||``).trim(),lastAuthChallenge:i&&typeof i==`object`?i:null,authorizationUrl:String(n.authorization_url||n.authorizationUrl||``).trim(),headers:n.headers&&typeof n.headers==`object`?n.headers:{},toolCache:Array.isArray(n.tool_cache||n.toolCache)?n.tool_cache||n.toolCache:[],allowedTools:Array.isArray(n.allowed_tools||n.allowedTools)?(n.allowed_tools||n.allowedTools).map(e=>String(e||``).trim()).filter(Boolean):null}}function gy(e,t,n){let r=String(t||``).trim().toLowerCase(),i=String(n||``).trim().replace(/\/+$/,``).toLowerCase(),a=e.servers.find(e=>{let t=String(e.transportUrl||``).trim().replace(/\/+$/,``).toLowerCase(),n=String(e.slug||``).trim().toLowerCase(),a=String(e.serverConfigName||``).trim().toLowerCase();return i&&t&&t===i||i&&t&&t.includes(i)||i&&t&&i.includes(t)||!!r&&(n===r||a===r)});return String(a?.authKind||``).trim().toLowerCase()}function _y(e){return Array.isArray(e)?e.map(e=>hy(e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name)):!e||typeof e!=`object`?[]:Array.isArray(e.servers)?e.servers.map(e=>hy(e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name)):Object.entries(e).map(([e,t])=>hy(t&&typeof t==`object`?t:{transport:String(t||``)},e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name))}function vy(e){return(Array.isArray(e)?e:Array.isArray(e?.tools)?e.tools:[]).map(e=>typeof e==`string`?e:!e||typeof e!=`object`?``:String(e.namespaced_name||e.namespacedName||e.id||e.tool_name||e.toolName||``).trim()).filter(Boolean)}function yy(e){let t=e&&typeof e==`object`?e:{},n=Array.isArray(t.servers)?t.servers:[];return{generatedAt:String(t.generated_at||``).trim(),count:Number.isFinite(Number(t.count))?Number(t.count):n.length,servers:n.map(e=>!e||typeof e!=`object`?null:{slug:String(e.slug||``).trim(),name:String(e.name||e.slug||``).trim(),description:String(e.description||``).trim(),transportUrl:String(e.transport_url||``).trim(),serverConfigName:String(e.server_config_name||e.slug||``).trim(),documentationUrl:String(e.documentation_url||``).trim(),directoryUrl:String(e.directory_url||``).trim(),toolCount:Number.isFinite(Number(e.tool_count))?Number(e.tool_count):0,requiresAuth:e.requires_auth!==!1,requiresSetup:!!e.requires_setup,authKind:String(e.auth_kind||e.authKind||``).trim().toLowerCase()}).filter(e=>!!e&&!!e.slug&&!!e.transportUrl).sort((e,t)=>e.name.localeCompare(t.name))}}function by(e,t){let n=t&&typeof t==`object`?t:{};return{botToken:``,allowedUsers:Array.isArray(n.allowed_users)?n.allowed_users.join(`, `):``,mentionOnly:n.mention_only!==!1&&e===`discord`?!0:!!n.mention_only,guildId:String(n.guild_id||``).trim(),channelId:String(n.channel_id||``).trim(),modelProviderId:String(n.model_provider_id||``).trim(),modelId:String(n.model_id||``).trim(),styleProfile:String(n.style_profile||`default`).trim()||`default`,securityProfile:String(n.security_profile||`operator`).trim()||`operator`}}function xy(){return{enabled_tools:[],disabled_tools:[],enabled_mcp_servers:[],enabled_mcp_tools:[]}}function Sy(e){return Array.from(new Set(e.map(e=>e.trim()).filter(Boolean)))}function Cy(e){let t=e&&typeof e==`object`?e:{};return{enabled_tools:Array.isArray(t.enabled_tools)?Sy(t.enabled_tools.map(e=>String(e))):[],disabled_tools:Array.isArray(t.disabled_tools)?Sy(t.disabled_tools.map(e=>String(e))):[],enabled_mcp_servers:Array.isArray(t.enabled_mcp_servers)?Sy(t.enabled_mcp_servers.map(e=>String(e))):[],enabled_mcp_tools:Array.isArray(t.enabled_mcp_tools)?Sy(t.enabled_mcp_tools.map(e=>String(e))):[]}}function wy(e){let t=e&&typeof e==`object`?e:{};return(Array.isArray(t.scopes)?t.scopes:[]).map(e=>{if(!e||typeof e!=`object`)return null;let t=String(e.scope_id||e.scopeId||``).trim();return t?{scope_id:t,scope_kind:String(e.scope_kind||e.scopeKind||``).trim(),session_count:Number.isFinite(Number(e.session_count))?Number(e.session_count):Number.isFinite(Number(e.sessionCount))?Number(e.sessionCount):0,sender_count:Number.isFinite(Number(e.sender_count))?Number(e.sender_count):Number.isFinite(Number(e.senderCount))?Number(e.senderCount):0,last_seen_at_ms:Number.isFinite(Number(e.last_seen_at_ms))?Number(e.last_seen_at_ms):Number.isFinite(Number(e.lastSeenAtMs))?Number(e.lastSeenAtMs):0}:null}).filter(e=>!!e).sort((e,t)=>e.last_seen_at_ms===t.last_seen_at_ms?e.scope_id.localeCompare(t.scope_id):t.last_seen_at_ms-e.last_seen_at_ms)}function Ty(e){let t=[];return e.scope_kind&&t.push(e.scope_kind),t.push(e.scope_id),e.session_count>1?t.push(`${e.session_count} sessions`):e.session_count===1&&t.push(`1 session`),t.join(` · `)}function Ey(e,t){let n=e.enabled_tools.filter(e=>e!==ny);return t===ny?e.disabled_tools.includes(t)?!1:e.enabled_tools.includes(t):e.disabled_tools.includes(t)?!1:n.length===0||n.includes(t)}function Dy(e,t,n){let r=e.disabled_tools.filter(e=>e!==t),i=e.enabled_tools.filter(e=>e!==ny);return t===ny?n?{...e,disabled_tools:r,enabled_tools:Sy([...e.enabled_tools,t])}:{...e,disabled_tools:Sy([...r,t]),enabled_tools:e.enabled_tools.filter(e=>e!==t)}:n?{...e,disabled_tools:r,enabled_tools:i.length>0?Sy([...e.enabled_tools,t]):e.enabled_tools}:{...e,disabled_tools:Sy([...r,t]),enabled_tools:i.length>0?e.enabled_tools.filter(e=>e!==t):e.enabled_tools}}function Oy(e,t,n){let r=e.enabled_mcp_servers.filter(e=>e!==t);return{...e,enabled_mcp_servers:n?Sy([...r,t]):r}}function ky(e,t,n){let r=`mcp.${yc(t)}.`,i=e.enabled_mcp_tools.filter(e=>e.startsWith(r));return i.length?n.some(e=>e.startsWith(r))?i:i.map(e=>e.slice(r.length)).filter(Boolean):null}function Ay(e,t,n,r){let i=`mcp.${yc(t)}.`,a=e=>{let t=String(e||``).trim();return t?t.startsWith(`mcp.`)?t:`${i}${t}`:``},o=Sy(n.map(a).filter(Boolean)),s=e.enabled_mcp_tools.filter(e=>!e.startsWith(i)),c=r===null?o:Sy(r.map(a).filter(Boolean));return{...e,enabled_mcp_tools:Sy([...s,...c])}}function jy(e,t){return e===`public_demo`?ry.includes(t):!0}function My(e,t,n){return jy(n,t)&&Ey(e,t)}function Ny(e){let t=String(e||``).split(`,`).map(e=>e.trim()).filter(Boolean);return t.length?t:[`*`]}function Py(e){let t=(Array.isArray(e)?e:String(e||``).split(`,`)).map(e=>String(e||``).trim()).filter(Boolean);return t.length?Array.from(new Set(t)):[`*`]}function Fy(e,t){let n=Py(e).slice().sort(),r=Py(t).slice().sort();return n.length===r.length?n.every((e,t)=>e===r[t]):!1}function Iy(e,t){let n=t&&typeof t==`object`?t:{},r=Py(n.allowed_users);return!!n.has_token||r.some(e=>e!==`*`)||!!n.mention_only||!!String(n.guild_id||``).trim()||!!String(n.channel_id||``).trim()||!!String(n.model_provider_id||``).trim()||!!String(n.model_id||``).trim()||String(n.style_profile||`default`).trim()!==`default`||String(n.security_profile||`operator`).trim()!==`operator`}function Ly(e,t,n){let r=by(e,n);return!String(t.botToken||``).trim()&&Fy(t.allowedUsers,r.allowedUsers)&&!!t.mentionOnly==!!r.mentionOnly&&String(t.guildId||``).trim()===String(r.guildId||``).trim()&&String(t.channelId||``).trim()===String(r.channelId||``).trim()&&String(t.modelProviderId||``).trim()===String(r.modelProviderId||``).trim()&&String(t.modelId||``).trim()===String(r.modelId||``).trim()&&String(t.styleProfile||`default`).trim()===String(r.styleProfile||`default`).trim()&&String(t.securityProfile||`operator`).trim()===String(r.securityProfile||`operator`).trim()}function Ry(e,t){let n=String(e?.catalog_source||``).trim().toLowerCase();return n===`remote`&&t>0?{tone:`ok`,text:`${t} models`}:n===`config`&&t>0?{tone:`info`,text:`configured models`}:{tone:`warn`,text:`manual entry`}}function zy(e,t){return String(e?.catalog_message||``).trim()||`Default model: ${t||`none`}`}var By={dashboard:`Command status, activity, and fast paths.`,chat:`Session-driven conversation, uploads, and live responses.`,planner:`Advanced long-horizon planning and governed handoff.`,studio:`Advanced template-first workflow builder.`,automations:`Reusable routines, approvals, and execution history.`,experiments:`Opt-in automation experiments, optimization campaigns, and team approvals.`,coding:`ACA intake, task launchers, and coding runs.`,agents:`Reusable agent roles and workflow drafts.`,orchestrator:`Task board planning, approvals, and execution.`,memory:`Searchable memory records and operational context.`,files:`Managed files plus the hosted knowledgebase upload surface.`,runs:`Live operations overview with queue state and per-run inspection.`,settings:`Provider defaults, themes, and runtime diagnostics.`};function Vy({client:e,api:t,toast:n,navigate:i,currentRoute:u,providerStatus:d,identity:f,themes:g,setTheme:v,themeId:b,refreshProviderStatus:S,refreshIdentityStatus:C,navigation:w}){let T=_(),E=c(null),[D,O]=r({}),[k,A]=r(String(f?.botName||`Tandem`)),[j,M]=r(String(f?.botAvatarUrl||``)),[N,P]=r(`Control Center`),[F,I]=r(d?.needsOnboarding?`providers`:w?.acaMode?`navigation`:`install`),[L,R]=r(``),[z,ee]=r(``),[B,V]=r(`auto`),[H,te]=r(``),[U,ne]=r(``),[re,ie]=r(`10000`),[ae,oe]=r(``),[se,ce]=r(``),[le,ue]=r(`autonomous AI agentic workflows`),[de,fe]=r(null),[pe,W]=r(`multi`),[G,K]=r(``),[me,he]=r(!1),[ge,_e]=r(!1),[ve,ye]=r(!1),[be,xe]=r(!1),[Se,Ce]=r(()=>Yv()),[we,Te]=r(`custom`),[Ee,De]=r(``),[Oe,ke]=r(``),[Ae,je]=r(``),[Me,Ne]=r(!0),[Pe,Fe]=r(``),[q,Ie]=r({}),Le=c({telegram:!1,discord:!1,slack:!1}),[Re,ze]=r({telegram:``,discord:``,slack:``}),[Be,Ve]=r({telegram:!1,discord:!1,slack:!1}),[He,Ue]=r({}),[We,Ge]=r(!1),[Ke,qe]=r(``),[Je,Ye]=r(``),[Xe,Ze]=r(`none`),[Qe,$e]=r(``),[et,tt]=r(``),[nt,rt]=r(``),[it,at]=r([]),[ot,st]=r(!0),[ct,lt]=r(``),[ut,dt]=r(`manual`),[ft,pt]=r(``),[mt,ht]=r(!1),[J,gt]=r(!1),[_t,vt]=r(``),[yt,bt]=r(``),[xt,St]=r(``),[Ct,wt]=r(`auto`),[Tt,Et]=r(``),[Dt,Ot]=r(``),[kt,At]=r(!0),[jt,Mt]=r(!1),[Nt,Pt]=r(!0),[Ft,It]=r(!1),[Lt,Rt]=r(``),[zt,Bt]=r(``),Vt=c(null),Ht=c(null),[Ut,Wt]=r(``);m(()=>{Xv(Se)},[Se]);let Gt=async()=>{let n=e?.identity;return n?.get?n.get():t(`/api/engine/config/identity`,{method:`GET`})},Kt=async n=>{let r=e?.identity;return r?.patch?r.patch(n):t(`/api/engine/config/identity`,{method:`PATCH`,body:JSON.stringify(n)})},qt=y({queryKey:[`settings`,`identity`,`config`],queryFn:()=>Gt().catch(()=>({identity:{}}))});m(()=>{let e=qt.data?.identity?.bot||{},t=e?.aliases||{},n=String(e?.canonicalName||e?.canonical_name||f?.botName||`Tandem`).trim(),r=String(e?.avatarUrl||e?.avatar_url||f?.botAvatarUrl||``).trim(),i=String(t?.controlPanel||t?.control_panel||``).trim();A(n||`Tandem`),M(r),P(i||`Control Center`)},[f?.botAvatarUrl,f?.botName,qt.data]),m(()=>{u===`mcp`&&I(`mcp`),u===`channels`&&I(`channels`),u===`bug-monitor`&&I(`bug_monitor`)},[u]);let Jt=y({queryKey:[`settings`,`install`,`profile`],queryFn:()=>t(`/api/install/profile`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),Yt=y({queryKey:[`settings`,`install`,`config`],queryFn:()=>t(`/api/control-panel/config`,{method:`GET`}).catch(()=>null)});m(()=>{let e=Yt.data?.config||null;if(e)try{R(JSON.stringify(e,null,2)),ee(``)}catch{ee(`Loaded config could not be rendered as JSON.`)}},[Yt.data]),m(()=>{if(u===`settings`){if(d?.needsOnboarding){I(`providers`),ye(!0);return}if(!w?.acaMode){I(`install`);return}I(Jt.data?.aca_integration!==!0||Jt.data?.control_panel_config_ready!==!0?`install`:`navigation`)}},[u,w?.acaMode,d?.needsOnboarding,Jt.data?.aca_integration,Jt.data?.control_panel_config_ready]);let Xt=y({queryKey:[`settings`,`providers`,`catalog`],queryFn:()=>e.providers.catalog().catch(()=>({all:[],connected:[]}))}),Zt=y({queryKey:[`settings`,`providers`,`config`],queryFn:()=>e.providers.config().catch(()=>({default:``,providers:{}}))}),Qt=y({queryKey:[`settings`,`providers`,`auth`],queryFn:()=>e.providers.authStatus().catch(()=>({providers:{}})),refetchInterval:15e3}),$t=y({queryKey:[`settings`,`system`,`health`],queryFn:()=>t(`/api/system/health`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),en=o(()=>fa({providerCatalog:Xt.data,providerConfig:Zt.data,defaultProvider:String(Zt.data?.default||``).trim(),defaultModel:String(Zt.data?.providers?.[String(Zt.data?.default||``).trim()]?.default_model||Zt.data?.providers?.[String(Zt.data?.default||``).trim()]?.defaultModel||``).trim(),includeUnconfiguredProviders:!0}),[Xt.data,Zt.data]),tn=o(()=>{let e=Qt.data?.providers;return e&&typeof e==`object`?e:Qt.data&&typeof Qt.data==`object`?Qt.data:{}},[Qt.data]),nn=$t.data?.localEngine===!0,rn=Jt.data?.hosted_managed===!0,an=o(()=>{let e=String(Zt.data?.default||``).trim();return{provider:e,model:String(Zt.data?.providers?.[e]?.default_model||Zt.data?.providers?.[e]?.defaultModel||``).trim()}},[Zt.data]),on=o(()=>Zt.data?.providers||{},[Zt.data?.providers]),sn=o(()=>Object.entries(on).filter(([e])=>{let t=e.trim().toLowerCase();return t&&!Zv.has(t)&&!ey(t)}).map(([e,t])=>({id:e,url:String(t?.url||``).trim(),model:String(t?.default_model||t?.defaultModel||``).trim(),isDefault:String(Zt.data?.default||``).trim().toLowerCase()===e.trim().toLowerCase()})),[on,Zt.data?.default]),cn=y({queryKey:[`settings`,`search`,`config`],queryFn:()=>t(`/api/system/search-settings`,{method:`GET`}).catch(()=>null)}),ln=y({queryKey:[`settings`,`scheduler`,`config`],queryFn:()=>t(`/api/system/scheduler-settings`,{method:`GET`}).catch(()=>null)});m(()=>{let e=cn.data?.settings||null;e&&(V(String(e.backend||`auto`).trim()||`auto`),te(String(e.tandem_url||``).trim()),ne(String(e.searxng_url||``).trim()),ie(String(e.timeout_ms||1e4)))},[cn.data]),m(()=>{let e=ln.data?.settings||null;e&&(W(String(e.mode||`multi`).trim()||`multi`),K(e.max_concurrent_runs==null?``:String(e.max_concurrent_runs)))},[ln.data]);let un=y({queryKey:[`settings`,`browser`,`status`],queryFn:()=>t(`/api/engine/browser/status`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),[dn,fn]=r(null),pn=x({mutationFn:()=>t(`/api/engine/browser/install`,{method:`POST`}),onSuccess:async()=>{n(`ok`,`Browser sidecar installed on the engine host.`),await un.refetch()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),mn=x({mutationFn:()=>t(`/api/engine/browser/smoke-test`,{method:`POST`,body:JSON.stringify({url:`https://example.com`})}),onSuccess:async e=>{fn(e),n(`ok`,`Browser smoke test passed.`),await un.refetch()},onError:e=>{fn(null),n(`err`,e instanceof Error?e.message:String(e))}}),hn=y({queryKey:[`settings`,`mcp`,`servers`],queryFn:()=>e.mcp.list().catch(()=>({})),refetchInterval:1e4}),gn=y({queryKey:[`settings`,`mcp`,`tools`],queryFn:()=>e.mcp.listTools().catch(()=>[]),refetchInterval:15e3}),_n=y({queryKey:[`settings`,`mcp`,`catalog`],queryFn:()=>t(`/api/engine/mcp/catalog`,{method:`GET`}).catch(()=>null),refetchInterval:6e4}),vn=y({queryKey:[`settings`,`bug-monitor`,`config`],queryFn:()=>t(`/api/engine/config/bug-monitor`,{method:`GET`}).catch(()=>({bug_monitor:{}}))}),yn=y({queryKey:[`settings`,`bug-monitor`,`status`],queryFn:()=>t(`/api/engine/bug-monitor/status`,{method:`GET`}).catch(()=>({status:{}})),refetchInterval:1e4}),bn=y({queryKey:[`settings`,`bug-monitor`,`drafts`],queryFn:()=>t(`/api/engine/bug-monitor/drafts?limit=10`,{method:`GET`}).catch(()=>({drafts:[]})),refetchInterval:15e3}),xn=y({queryKey:[`settings`,`bug-monitor`,`incidents`],queryFn:()=>t(`/api/engine/bug-monitor/incidents?limit=10`,{method:`GET`}).catch(()=>({incidents:[]})),refetchInterval:1e4}),Sn=y({queryKey:[`settings`,`bug-monitor`,`posts`],queryFn:()=>t(`/api/engine/bug-monitor/posts?limit=10`,{method:`GET`}).catch(()=>({posts:[]})),refetchInterval:15e3}),Cn=y({queryKey:[`settings`,`bug-monitor`,`workspace-browser`,Lt],enabled:Ft&&!!Lt,queryFn:()=>t(`/api/orchestrator/workspaces/list?dir=${encodeURIComponent(Lt)}`,{method:`GET`})}),wn=y({queryKey:[`settings`,`channels`,`config`],queryFn:()=>e.channels.config().catch(()=>({})),refetchInterval:15e3}),Tn=y({queryKey:[`settings`,`channels`,`status`],queryFn:()=>e.channels.status().catch(()=>({})),refetchInterval:6e3}),En=y({queryKey:[`settings`,`channels`,`scopes`],queryFn:async()=>{let e=await Promise.all($v.map(async e=>[e,wy(await t(`/api/engine/channels/${e}/scopes`,{method:`GET`}).catch(()=>({scopes:[]})))]));return Object.fromEntries(e)},refetchInterval:15e3}),Dn=y({queryKey:[`settings`,`channels`,`tool-preferences`,Re],queryFn:async()=>{let e=await Promise.all($v.map(async e=>{let n=String(Re[e]||``).trim();return[e,Cy(await t(`/api/engine/channels/${e}/tool-preferences${n?`?scope_id=${encodeURIComponent(n)}`:``}`,{method:`GET`}).catch(()=>xy()))]}));return Object.fromEntries(e)},refetchInterval:15e3}),On=x({mutationFn:async({providerId:t,modelId:n})=>e.providers.setDefaults(t,n),onSuccess:async()=>{n(`ok`,`Updated provider defaults.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),kn=()=>String(Zt.data?.providers?.[Qv]?.default_model||Zt.data?.providers?.[Qv]?.defaultModel||`gpt-5.4`).trim()||`gpt-5.4`,An=async()=>{await e.providers.setDefaults(Qv,kn())},jn=x({mutationFn:async({providerId:n,url:r,modelId:i,apiKey:a,makeDefault:o})=>{let s=n.trim().toLowerCase(),c=r.trim(),l=i.trim();if(!s)throw Error(`Custom provider ID is required.`);if(!c)throw Error(`Custom provider URL is required.`);await t(`/api/engine/config`,{method:`PATCH`,body:JSON.stringify({...o?{default_provider:s}:{},providers:{[s]:{url:c,...l?{default_model:l}:{}}}})}),a.trim()&&await e.providers.setApiKey(s,a.trim())},onSuccess:async()=>{n(`ok`,`Custom provider saved.`),je(``),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Mn=x({mutationFn:async()=>t(`/api/engine/config/bug-monitor`,{method:`PATCH`,body:JSON.stringify({bug_monitor:{enabled:mt,paused:J,workspace_root:String(_t||``).trim()||null,repo:String(yt||``).trim()||null,mcp_server:String(xt||``).trim()||null,provider_preference:String(Ct||`auto`).trim(),model_policy:Tt&&Dt?{default_model:{provider_id:Tt,model_id:Dt}}:null,auto_create_new_issues:kt,require_approval_for_new_issues:jt,auto_comment_on_matched_open_issues:Nt,label_mode:`reporter_only`}})}),onSuccess:async()=>{n(`ok`,`Bug Monitor settings saved.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})])},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Nn=x({mutationFn:async()=>t(`/api/engine/capabilities/bindings/refresh-builtins`,{method:`POST`}),onSuccess:async()=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]}),T.invalidateQueries({queryKey:[`settings`,`mcp`]})]),n(`ok`,`Capability bindings refreshed from built-ins.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Pn=x({mutationFn:async({draftId:e,decision:n})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/${n}`,{method:`POST`,body:JSON.stringify({reason:`${n}d from control panel settings`})}),onSuccess:async(e,t)=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`Bug Monitor draft ${t.decision===`approve`?`approved`:`denied`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Fn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/triage-run`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.deduped?`Bug Monitor triage run already exists: ${e?.run?.run_id||`unknown`}`:`Bug Monitor triage run created: ${e?.run?.run_id||`unknown`}`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),In=x({mutationFn:async({action:e})=>t(`/api/engine/bug-monitor/${e}`,{method:`POST`}),onSuccess:async(e,t)=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`Bug Monitor ${t.action===`pause`?`paused`:`resumed`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Ln=x({mutationFn:async({incidentId:e})=>t(`/api/engine/bug-monitor/incidents/${encodeURIComponent(e)}/replay`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.deduped?`Bug Monitor triage run already exists: ${e?.run?.run_id||`unknown`}`:`Bug Monitor replay queued triage: ${e?.run?.run_id||`unknown`}`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Rn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/publish`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.action===`comment_issue`?`Bug Monitor commented on issue #${e?.draft?.issue_number||`unknown`}.`:`Bug Monitor published issue #${e?.draft?.issue_number||`unknown`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),zn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/recheck-match`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`GitHub match result: ${String(e?.action||`rechecked`).replaceAll(`_`,` `)}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Bn=x({mutationFn:({providerId:t,apiKey:n})=>e.providers.setApiKey(t,n),onSuccess:async()=>{n(`ok`,`API key updated.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Vn=x({mutationFn:({providerId:t})=>e.providers.oauthAuthorize(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim(),o=String(e?.session_id||e?.sessionId||``).trim(),s=String(e?.authorization_url||e?.authorizationUrl||e?.url||``).trim();if(!i||!r||!o||!s){n(`err`,a||`OAuth authorize response was incomplete.`);return}Ce(e=>({...e,[r]:o})),window.open(s,`_blank`,`noopener,noreferrer`),n(`info`,r===Qv?`Browser sign-in opened for Codex. Finish the flow there, then return to Tandem.`:`Browser sign-in opened for ${r}.`),await T.invalidateQueries({queryKey:[`settings`,`providers`,`auth`]})},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Hn=x({mutationFn:({providerId:t})=>e.providers.oauthDisconnect(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase();Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t}),n(`ok`,r===Qv?`Codex account disconnected.`:`${r} disconnected.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Un=x({mutationFn:({providerId:t})=>e.providers.oauthUseLocalSession(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim();if(!i){n(`err`,a||`Unable to import the local Codex session. Make sure Codex CLI is signed in on this machine.`);return}Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t});let o=String(e?.email||``).trim();if(n(`ok`,r===Qv?o?`Local Codex session imported: ${o}`:`Local Codex session imported.`:`${r} local session imported.`),r===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex session imported, but Tandem could not switch the default provider.`)}await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Wn=x({mutationFn:({providerId:e,authJson:n})=>t(`/api/engine/provider/${encodeURIComponent(e)}/oauth/session/import`,{method:`POST`,body:JSON.stringify({auth_json:n})}),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim();if(!i){n(`err`,a||`Unable to import the Codex auth.json file. Make sure it was copied from a signed-in Codex CLI session.`);return}Fe(``),Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t});let o=String(e?.email||``).trim();if(n(`ok`,r===Qv?o?`Codex auth.json imported: ${o}`:`Codex auth.json imported.`:`${r} auth.json imported.`),r===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex auth.json imported, but Tandem could not switch the default provider.`)}await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),qn=h(async(e,t)=>{if(t)try{let r=await t.text();if(Wt(t.name||`auth.json`),Fe(r),!r.trim()){n(`warn`,`Selected auth.json file was empty.`);return}Wn.mutate({providerId:e,authJson:r})}catch(e){n(`err`,e instanceof Error?e.message:String(e))}finally{Ht.current&&(Ht.current.value=``)}},[Wn,n]);m(()=>{let t=Object.entries(Se).filter(([e,t])=>!!e&&!!t);if(!t.length)return;let r=!1,i=new Set,a=async()=>{let a=await Promise.all(t.map(async([t,n])=>{try{return{providerId:t,sessionId:n,payload:await e.providers.oauthStatus(t,n),error:null}}catch(e){return{providerId:t,sessionId:n,payload:null,error:e instanceof Error?e:Error(String(e))}}}));for(let e of a){if(r||i.has(e.providerId))continue;if(e.error){i.add(e.providerId),Ce(t=>{if(t[e.providerId]!==e.sessionId)return t;let n={...t};return delete n[e.providerId],n}),n(`err`,e.error.message);continue}let t=e.payload,a=String(t?.status||``).trim().toLowerCase();if(!(!a||a===`pending`)){if(i.add(e.providerId),Ce(t=>{if(t[e.providerId]!==e.sessionId)return t;let n={...t};return delete n[e.providerId],n}),a===`connected`){let r=String(t?.email||``).trim();if(n(`ok`,r?`Codex account connected: ${r}`:`Codex account connected.`),e.providerId===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex connected, but Tandem could not switch the default provider.`)}}else a===`expired`?n(`warn`,`Codex sign-in expired. Start the connection again.`):n(`err`,String(t?.error||t?.message||``).trim()||`Codex sign-in did not complete. Please try again.`);await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])}}};a();let o=window.setInterval(()=>{a()},2e3);return()=>{r=!0,window.clearInterval(o)}},[e,Se,T,S,n]);let Jn=x({mutationFn:async e=>t(`/api/system/search-settings`,{method:`PATCH`,body:JSON.stringify(e)}),onSuccess:async e=>{oe(``),ce(``),await T.invalidateQueries({queryKey:[`settings`,`search`]}),n(`ok`,e?.restart_required?`Search settings saved. Restart tandem-engine to apply them.`:`Search settings saved.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Yn=x({mutationFn:async e=>t(`/api/system/scheduler-settings`,{method:`PATCH`,body:JSON.stringify(e)}),onSuccess:async e=>{await T.invalidateQueries({queryKey:[`settings`,`scheduler`]}),n(`ok`,e?.restart_required?`Scheduler settings saved. Restart tandem-engine to apply them.`:`Scheduler settings saved.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Zn=x({mutationFn:async({query:e})=>t(`/api/system/search-settings/test`,{method:`POST`,body:JSON.stringify({query:e,limit:5})}),onSuccess:e=>{fe(e),n(`ok`,`Websearch test completed.`)},onError:e=>{fe(null),n(`err`,e instanceof Error?e.message:String(e))}}),Qn=x({mutationFn:async()=>{let e;try{e=JSON.parse(L)}catch(e){throw Error(e instanceof Error?`Config JSON is invalid: ${e.message}`:`Config JSON is invalid.`)}return t(`/api/control-panel/config`,{method:`PATCH`,body:JSON.stringify({config:e})})},onSuccess:async()=>{ee(``),n(`ok`,`Control panel config saved.`),await T.invalidateQueries({queryKey:[`settings`,`install`]}),await T.invalidateQueries({queryKey:[`system`,`capabilities`]})},onError:e=>{let t=e instanceof Error?e.message:String(e);ee(t),n(`err`,t)}}),$n=x({mutationFn:async()=>{let e=(qt.data?.identity?.bot||{})?.aliases||{},t=String(k||``).trim();if(!t)throw Error(`Bot name is required.`);let n=String(j||``).trim(),r=String(N||``).trim();return Kt({identity:{bot:{canonical_name:t,avatar_url:n||null,aliases:{...e,control_panel:r||void 0}}}})},onSuccess:async()=>{n(`ok`,`Identity updated.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`identity`]}),C()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),nr=h(async()=>Promise.all([T.invalidateQueries({queryKey:[`settings`,`channels`]}),T.invalidateQueries({queryKey:[`settings`,`channels`,`scopes`]}),T.invalidateQueries({queryKey:[`settings`,`channels`,`tool-preferences`]})]),[T]),rr=x({mutationFn:async({channel:e,scopeId:n,payload:r})=>{let i=String(n||``).trim()?`?scope_id=${encodeURIComponent(String(n||``).trim())}`:``;return`reset`in r?t(`/api/engine/channels/${e}/tool-preferences${i}`,{method:`PUT`,body:JSON.stringify({reset:!0})}):t(`/api/engine/channels/${e}/tool-preferences${i}`,{method:`PUT`,body:JSON.stringify(r)})},onSuccess:async(e,t)=>{await T.invalidateQueries({queryKey:[`settings`,`channels`,`tool-preferences`]}),await T.invalidateQueries({queryKey:[`settings`,`channels`,`scopes`]});let r=String(t.scopeId||``).trim();n(`ok`,r?`Saved ${t.channel} scope ${r}.`:`Saved ${t.channel} channel tool scope.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),ir=x({mutationFn:async t=>{let n=q[t];if(!n)throw Error(`No draft found for ${t}.`);let r=String(n.modelProviderId||``).trim(),i=String(n.modelId||``).trim(),a={allowed_users:Ny(n.allowedUsers),mention_only:!!n.mentionOnly,security_profile:String(n.securityProfile||`operator`).trim()||`operator`,model_provider_id:r||null,model_id:i||null},o=String(n.botToken||``).trim();if(o&&(a.bot_token=o),t===`telegram`&&(a.style_profile=String(n.styleProfile||`default`).trim()||`default`),t===`discord`&&(a.guild_id=String(n.guildId||``).trim()),t===`slack`){let e=String(n.channelId||``).trim();if(!e&&!wn.data?.slack?.channel_id)throw Error(`Slack channel ID is required.`);e&&(a.channel_id=e)}return e.channels.put(t,a)},onSuccess:async(e,t)=>{n(`ok`,`Saved ${t} channel settings.`),Ue(e=>({...e,[t]:null})),Ie(e=>({...e,[t]:{...e[t],botToken:``}})),await nr()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),ar=x({mutationFn:async t=>e.channels.delete(t),onSuccess:async(e,t)=>{n(`ok`,`Removed ${t} channel settings.`),Ue(e=>({...e,[t]:null})),ze(e=>({...e,[t]:``})),Le.current[t]=!1,Ie(e=>({...e,[t]:by(t,null)})),await nr()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),or=x({mutationFn:async t=>{let n=q[t],r=String(n?.botToken||``).trim(),i={};return r&&(i.bot_token=r),e.channels.verify(t,i)},onSuccess:(e,t)=>{Ue(n=>({...n,[t]:e})),n(`ok`,`${t} verification complete.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),cr=h(async()=>T.invalidateQueries({queryKey:[`settings`,`mcp`]}),[T]),ur=x({mutationFn:async({serverName:t,allowedTools:n})=>e.mcp.patch(t,{allowed_tools:n??void 0,clear_allowed_tools:n===null}),onSuccess:async()=>{await cr(),n(`ok`,`MCP tool access updated.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),dr=x({mutationFn:async({action:n,server:r})=>{if(!r)throw Error(`No MCP server selected.`);if(n===`connect`)return e.mcp.connect(r.name);if(n===`disconnect`)return e.mcp.disconnect(r.name);if(n===`refresh`)return e.mcp.refresh(r.name);if(n===`authenticate`)return t(`/api/engine/mcp/${encodeURIComponent(r.name)}/auth/authenticate`,{method:`POST`});if(n===`toggle-enabled`)return e.mcp.setEnabled(r.name,!r.enabled);if(n===`delete`)return t(`/api/engine/mcp/${encodeURIComponent(r.name)}`,{method:`DELETE`});throw Error(`Unknown action: ${n}`)},onSuccess:async(e,t)=>{await cr();let r=!!e?.pendingAuth||!!e?.lastAuthChallenge||!!e?.authorizationUrl,i=e?.ok!==!1,a=String(t.server?.authKind||``).trim().toLowerCase();if(t.action===`connect`)if(r||!i&&a===`oauth`){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization required for ${t.server?.name}: ${i}`:`OAuth authorization required for ${t.server?.name}.`)}else if(i)n(`ok`,`Connected ${t.server?.name}.`);else{let r=String(e?.error?.message||e?.error||``).trim();n(`err`,r?`Failed to connect ${t.server?.name}: ${r}`:`Failed to connect ${t.server?.name}.`)}if(t.action===`disconnect`&&n(`ok`,`Disconnected ${t.server?.name}.`),t.action===`refresh`)if(r||!i&&a===`oauth`){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization required for ${t.server?.name}: ${i}`:`OAuth authorization required for ${t.server?.name}.`)}else if(i)n(`ok`,`Refreshed ${t.server?.name}.`);else{let r=String(e?.error?.message||e?.error||``).trim();n(`err`,r?`Failed to refresh ${t.server?.name}: ${r}`:`Failed to refresh ${t.server?.name}.`)}if(t.action===`authenticate`){let i=e?.ok!==!1,a=String(e?.error?.message||e?.error||``).trim();if(!i&&!r)n(`err`,a?`OAuth authorization check failed for ${t.server?.name}: ${a}`:`OAuth authorization check failed for ${t.server?.name}.`);else if(r){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization still pending for ${t.server?.name}: ${i}`:`OAuth authorization still pending for ${t.server?.name}.`)}else n(`ok`,`Marked ${t.server?.name} as signed in.`)}t.action===`toggle-enabled`&&n(`ok`,`${t.server?.enabled?`Disabled`:`Enabled`} ${t.server?.name}.`),t.action===`delete`&&n(`ok`,`Deleted ${t.server?.name}.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),fr=x({mutationFn:async()=>{let n=String(Je||``).trim(),r=oy(n),i=ay(Ke||r);if(!n)throw Error(`Transport URL is required.`);if(!iy(n)&&!n.startsWith(`stdio:`))throw Error(`Transport must be a valid URL or stdio:* transport.`);let a=fy(py({authMode:Xe,token:Qe,customHeader:et,transport:n}),it),o=String(nt||``).trim();cy(n)&&o&&(a[`X-MCP-Toolsets`]=o);let s={name:i,transport:n,enabled:!0,auth_kind:Xe===`oauth`?`oauth`:``};Object.keys(a).length&&(s.headers=a);let c=String(ct||``).trim();if(c&&c!==i&&await t(`/api/engine/mcp/${encodeURIComponent(c)}`,{method:`DELETE`}).catch(()=>null),await e.mcp.add(s),ot){let t=await e.mcp.connect(s.name),n=t?.pendingAuth===!0||!!t?.lastAuthChallenge||!!t?.authorizationUrl;if(!t?.ok&&!n&&Xe!==`oauth`)throw Error(`Added "${s.name}" but connect failed.`);return{name:s.name,connectResult:t,connectAfterAdd:!0,authKind:Xe===`oauth`?`oauth`:``}}return{name:s.name,connectAfterAdd:!1,authKind:Xe===`oauth`?`oauth`:``}},onSuccess:async e=>{await cr(),Ge(!1),qe(``),Ye(``),Ze(`none`),$e(``),tt(``),rt(``),at([]),st(!0),lt(``);let t=String(e?.name||``).trim(),r=e?.connectResult,i=String(e?.authKind||``).trim().toLowerCase(),a=!!r?.pendingAuth||!!r?.lastAuthChallenge||!!r?.authorizationUrl;if(e?.connectAfterAdd&&a){let e=r?.lastAuthChallenge||{},i=String(e?.message||``).trim();n(`warn`,i?`Saved MCP "${t}" and OAuth authorization is still required: ${i}`:`Saved MCP "${t}" and OAuth authorization is still required.`)}else e?.connectAfterAdd?i===`oauth`&&r&&r.ok!==!0?n(`warn`,`Saved MCP "${t}" as OAuth-backed. If it still needs authorization, open the auth link from the server row and refresh after signing in.`):n(`ok`,`Saved MCP "${t}" and connected it.`):n(`ok`,`Saved MCP "${t}".`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),pr=e=>{if(!e)return;if(e.size>10*1024*1024){n(`err`,`Avatar image is too large (max 10 MB).`);return}let t=new FileReader;t.onload=()=>{let e=typeof t.result==`string`?t.result:``;if(!e){n(`err`,`Failed to read avatar image.`);return}M(e)},t.onerror=()=>n(`err`,`Failed to read avatar image.`),t.readAsDataURL(e)},mr=Array.isArray(Xt.data?.all)?Xt.data.all:[];m(()=>{let e=sn.find(e=>e.isDefault)||sn[0];e&&(Te(t=>t.trim()&&t.trim().toLowerCase()!==`custom`?t:e.id),De(t=>t.trim()?t:e.url),ke(t=>t.trim()?t:e.model),Ne(String(Zt.data?.default||``).trim().toLowerCase()===e.id.trim().toLowerCase()))},[sn,Zt.data?.default]);let hr=o(()=>_y(hn.data),[hn.data]),gr=o(()=>vy(gn.data),[gn.data]),_r=o(()=>yy(_n.data?.catalog||_n.data||null),[_n.data]),vr=o(()=>new Set(hr.map(e=>e.name.toLowerCase())),[hr]);m(()=>{let e=hr.filter(e=>{let t=String(e.authKind||``).trim().toLowerCase(),n=String(e.lastAuthChallenge?.authorization_url||e.lastAuthChallenge?.authorizationUrl||e.authorizationUrl||``).trim();return t===`oauth`&&(!!e.lastAuthChallenge||!!n)});if(!e.length)return;let n=!1,r=!1,i=async()=>{if(!(n||r)){r=!0;try{let r=await Promise.all(e.map(async e=>{try{return{payload:await t(`/api/engine/mcp/${encodeURIComponent(e.name)}/auth/authenticate`,{method:`POST`}),error:null}}catch(e){return{payload:null,error:e instanceof Error?e:Error(String(e))}}}));if(n)return;r.some(({payload:e,error:t})=>t?!1:!(e?.pendingAuth===!0||e?.lastAuthChallenge||e?.authorizationUrl))&&await T.invalidateQueries({queryKey:[`settings`,`mcp`]})}finally{r=!1}}};i();let a=window.setInterval(()=>{i()},3e3);return()=>{n=!0,window.clearInterval(a)}},[t,hr,T]);let yr=o(()=>{let e=String(ft||``).trim().toLowerCase();return _r.servers.filter(t=>e?t.name.toLowerCase().includes(e)||t.slug.toLowerCase().includes(e)||t.transportUrl.toLowerCase().includes(e):!0).slice(0,36)},[_r.servers,ft]),xr=hr.filter(e=>e.connected).length,Sr=o(()=>yn.data?.status||{},[yn.data]),Cr=o(()=>Array.isArray(bn.data?.drafts)&&bn.data.drafts||[],[bn.data]),wr=o(()=>Array.isArray(xn.data?.incidents)&&xn.data.incidents||[],[xn.data]),Tr=o(()=>Array.isArray(Sn.data?.posts)&&Sn.data.posts||[],[Sn.data]),Er=o(()=>hr.find(e=>e.name.toLowerCase()===String(xt||``).trim().toLowerCase())||null,[xt,hr]),Dr=o(()=>mr.find(e=>String(e?.id||``).toLowerCase()===String(Tt||``).trim().toLowerCase())||null,[Tt,mr]),Or=o(()=>{let e=Dr&&typeof Dr==`object`&&Dr.models||{};return Object.keys(e).sort((e,t)=>e.localeCompare(t))},[Dr]),kr=Array.isArray(un.data?.blocking_issues)&&un.data?.blocking_issues||[],Ar=Array.isArray(un.data?.recommendations)&&un.data?.recommendations||[],jr=Array.isArray(un.data?.install_hints)&&un.data?.install_hints||[],Pr=$v.filter(e=>!!Tn.data?.[e]?.connected).length,Fr=Array.isArray(Cn.data?.directories)?Cn.data.directories:[],Ir=String(zt||``).trim().toLowerCase(),Lr=o(()=>Ir?Fr.filter(e=>String(e?.name||e?.path||``).trim().toLowerCase().includes(Ir)):Fr,[Fr,Ir]),Rr=String(Cn.data?.parent||``).trim(),zr=String(Cn.data?.dir||Lt||``).trim();m(()=>{let e=vn.data?.bug_monitor&&typeof vn.data?.bug_monitor==`object`?vn.data.bug_monitor:{};ht(!!e.enabled),gt(!!e.paused),vt(String(e.workspace_root||``).trim()),bt(String(e.repo||``).trim()),St(String(e.mcp_server||``).trim()),wt(String(e.provider_preference||`auto`).trim()||`auto`),Et(String(e.model_policy?.default_model?.provider_id||``).trim()),Ot(String(e.model_policy?.default_model?.model_id||``).trim()),At(e.auto_create_new_issues!==!1),Mt(!!e.require_approval_for_new_issues),Pt(e.auto_comment_on_matched_open_issues!==!1)},[vn.data]),m(()=>{let e=wn.data&&typeof wn.data==`object`?wn.data:{};!wn.data||typeof wn.data!=`object`||Ie(t=>{let n={...t};for(let t of $v)n[t]||(n[t]=by(t,e[t]),Le.current[t]=!0);return n})},[wn.data]);let Br=(e,t)=>{let n=String(t||``).trim();n&&On.mutate({providerId:e,modelId:n})},Vr=e=>{if(e){dt(`manual`);let t=e.headers&&typeof e.headers==`object`?e.headers:{},n=Object.keys(t),r=n.find(e=>String(e).toLowerCase()===`authorization`),i=n.find(e=>String(e).toLowerCase()===`x-api-key`),a=n.find(e=>String(e).toLowerCase()===`x-mcp-toolsets`),o=String(e.lastAuthChallenge?.authorization_url||e.lastAuthChallenge?.authorizationUrl||e.authorizationUrl||``).trim(),s=n.filter(e=>![r,i,a].filter(Boolean).map(e=>String(e).toLowerCase()).includes(String(e).toLowerCase())),c=String(e.authKind||``).trim().toLowerCase()||gy(_r,e.name,e.transport),l=o||c===`oauth`?`oauth`:`none`,u=``,d=``;o?d=``:i?(l=`x-api-key`,d=String(t[i]||``).trim()):r?(l=`bearer`,d=String(t[r]||``).replace(/^bearer\s+/i,``).trim()):s.length===1&&(l=`custom`,u=s[0],d=String(t[s[0]]||``).trim()),lt(e.name),qe(e.name),Ye(e.transport||``),st(e.connected||!1),rt(a?String(t[a]||``).trim():cy(e.transport||``)?`default`:``),Ze(l),tt(u),$e(d);let f=new Set([r,i,a,l===`custom`?u:``].filter(Boolean).map(e=>String(e).toLowerCase()));at(n.filter(e=>!f.has(String(e).toLowerCase())).map(e=>({key:e,value:String(t[e]||``).trim()})))}else dt(`catalog`),lt(``),qe(``),Ye(``),Ze(`none`),tt(``),$e(``),rt(``),at([]),st(!0);Ge(!0)},Hr=async()=>{let e=await t(`/api/engine/bug-monitor/debug`,{method:`GET`});await navigator.clipboard.writeText(JSON.stringify(e,null,2)),n(`ok`,`Bug Monitor debug payload copied.`)},Ur=[{id:`install`,label:`Install`,icon:`clipboard-list`},{id:`navigation`,label:`Navigation`,icon:`panel-left`},{id:`providers`,label:`Providers`,icon:`cpu`},{id:`search`,label:`Web Search`,icon:`globe`},{id:`scheduler`,label:`Scheduler`,icon:`layers`},{id:`identity`,label:`Identity`,icon:`badge-check`},{id:`theme`,label:`Themes`,icon:`paint-bucket`},{id:`channels`,label:`Channels`,icon:`message-circle`},{id:`mcp`,label:`MCP`,icon:`plug-zap`},{id:`bug_monitor`,label:`Bug Monitor`,icon:`bug-play`},{id:`browser`,label:`Browser`,icon:`monitor-cog`}],Wr=o(()=>my(Xe,Qe,et,Je),[Xe,et,Qe,Je]),Gr=o(()=>uy(Ke,Je),[Ke,Je]),Kr=Xe===`oauth`&&ot,qr=o(()=>cy(Je),[Je]),Jr=w?.routeVisibility||{},Yr=Uv(!!w?.acaMode),Xr=lr.map(([e,t,n])=>{let r=e;return{routeId:e,label:t,icon:n,enabled:Jr[r]!==!1,pinned:!!w?.acaMode&&Hv.has(r),defaultVisible:Yr[r]!==!1,description:By[e]||`Open the ${String(t||e).toLowerCase()} section.`}}),Zr=Xr.filter(e=>e.enabled).length,Qr=Xr.filter(e=>e.defaultVisible),$r=Xr.filter(e=>!e.defaultVisible),ei=$r.filter(e=>!e.enabled).length;return m(()=>{let e=E.current;e?Mr(e):Mr()},[F,mt,J,_t,xt,Sr.readiness?.runtime_ready,Sr.runtime?.monitoring_active,Sr.runtime?.paused,Sr.runtime?.pending_incidents,Sr.pending_drafts,Cr.length,wr.length,Nn.isPending,In.isPending,Pn.isPending,Ln.isPending,Fn.isPending,Mn.isPending,dr.isPending,Jn.isPending]),a(Gn,{className:`grid gap-4`,children:a(`div`,{ref:E,className:`grid gap-4`,children:[a(`div`,{className:`tcp-settings-tabs`,children:Ur.map(e=>a(`button`,{type:`button`,className:`tcp-settings-tab tcp-settings-tab-underline ${F===e.id?`active`:``}`,onClick:()=>I(e.id),children:[a(`i`,{"data-lucide":e.icon}),e.label]},e.id))}),a(er,{main:a(Kn,{className:`grid gap-4`,children:[F===`navigation`?a(X,{title:`Sidebar navigation`,subtitle:w?.acaMode?`ACA mode keeps Dashboard, Chat, Coding, and Settings visible by default.`:`Choose which sections appear in the sidebar. Advanced and experimental surfaces stay hidden until you turn them on.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:w?.acaMode?`ok`:`info`,children:w?.acaMode?`ACA compact default`:`Core-first default`}),a(Y,{tone:`ghost`,children:[Zr,`/`,Xr.length,` visible`]}),a(`button`,{className:`tcp-btn`,type:`button`,onClick:()=>w?.showAllSections(),children:`Show all sections`}),a(`button`,{className:`tcp-btn-primary`,type:`button`,onClick:()=>w?.resetNavigation(),children:[`Reset `,w?.acaMode?`ACA compact`:`default`]})]}),children:a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Default sections`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`These sections are part of the standard control panel and start on by default.`})]}),a(Y,{tone:`ok`,children:[Qr.filter(e=>e.enabled).length,`/`,Qr.length,` shown`]})]}),a(`div`,{className:`mt-3 grid gap-2`,children:Qr.map(e=>a(`button`,{type:`button`,className:`flex items-center justify-between rounded-xl border px-3 py-3 text-left transition ${e.enabled?`border-lime-500/40 bg-lime-500/10 hover:border-lime-400/70`:`border-slate-700/60 bg-slate-900/20 hover:border-slate-500/70`}`,onClick:()=>w?.setRouteVisibility(e.routeId,!e.enabled),children:[a(`div`,{className:`flex min-w-0 items-center gap-3`,children:[a(`span`,{className:`flex h-9 w-9 items-center justify-center rounded-lg border ${e.enabled?`border-lime-500/30 bg-lime-500/10 text-lime-200`:`border-slate-700/70 bg-slate-950/30 text-slate-300`}`,children:a(`i`,{"data-lucide":e.icon})}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.label}),a(`div`,{className:`tcp-subtle truncate text-xs`,children:e.description})]})]}),a(`div`,{className:`flex items-center gap-2`,children:[e.pinned?a(Y,{tone:`ok`,children:`Pinned`}):null,a(Y,{tone:e.enabled?`ok`:`ghost`,children:e.enabled?`Shown`:`Hidden`})]})]},e.routeId))})]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Advanced / experimental sections`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Only routes that ship hidden by default live here.`})]}),a(Y,{tone:ei>0?`warn`:`ok`,children:[ei,` hidden`]})]}),a(`div`,{className:`mt-3 grid gap-2`,children:$r.map(e=>a(`button`,{type:`button`,className:`flex items-center justify-between rounded-xl border px-3 py-3 text-left transition ${e.enabled?`border-lime-500/40 bg-lime-500/10 hover:border-lime-400/70`:`border-slate-700/60 bg-slate-900/20 hover:border-slate-500/70`}`,onClick:()=>w?.setRouteVisibility(e.routeId,!e.enabled),children:[a(`div`,{className:`flex min-w-0 items-center gap-3`,children:[a(`span`,{className:`flex h-9 w-9 items-center justify-center rounded-lg border ${e.enabled?`border-lime-500/30 bg-lime-500/10 text-lime-200`:`border-slate-700/70 bg-slate-950/30 text-slate-300`}`,children:a(`i`,{"data-lucide":e.icon})}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.label}),a(`div`,{className:`tcp-subtle truncate text-xs`,children:e.description})]})]}),a(Y,{tone:e.enabled?`ok`:`ghost`,children:e.enabled?`Shown`:`Hidden`})]},e.routeId))})]}),a(`div`,{className:`tcp-subtle text-xs`,children:`These preferences are stored in this browser only.`})]})}):null,F===`install`?a(X,{title:`Install config`,subtitle:`Durable non-secret install preferences stored in tandem-data for Tandem startup and navigation defaults.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:String(Jt.data?.control_panel_mode||``).trim().toLowerCase()===`aca`?`ok`:`info`,children:Jt.data?.control_panel_mode||`auto`}),a(Y,{tone:Jt.data?.control_panel_config_ready?`ok`:`warn`,children:Jt.data?.control_panel_config_ready?`Ready`:`Needs setup`}),a(`button`,{type:`button`,className:`tcp-btn`,onClick:()=>Yt.refetch().then(()=>n(`ok`,`Install config refreshed.`)),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh`]}),a(`button`,{type:`button`,className:`tcp-btn-primary`,onClick:()=>Qn.mutate(),disabled:Qn.isPending,children:[a(`i`,{"data-lucide":`save`}),`Save config`]})]}),children:a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Startup profile`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:Jt.data?.control_panel_mode_reason||`The control panel auto-detects its startup mode and can be overridden with TANDEM_CONTROL_PANEL_MODE.`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Mode source`}),a(`span`,{children:Jt.data?.control_panel_mode_source||`detected`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Integration detected`}),a(`span`,{children:Jt.data?.aca_integration?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Compact nav`}),a(`span`,{children:Jt.data?.control_panel_compact_nav?`on`:`off`})]})]})]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Hosted management`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Detect whether this panel is running on a Tandem-managed hosted deployment so hosted-only update and notification UX can stay gated.`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Managed hosted server`}),a(`span`,{children:Jt.data?.hosted_managed?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Provider`}),a(`span`,{children:Jt.data?.hosted_provider||`—`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Deployment slug`}),a(`span`,{children:Jt.data?.hosted_deployment_slug||`—`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Release`}),a(`span`,{children:[Jt.data?.hosted_release_version||`—`,Jt.data?.hosted_release_channel?` · ${Jt.data.hosted_release_channel}`:``]})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Update policy`}),a(`span`,{children:Jt.data?.hosted_update_policy||`—`})]})]}),Jt.data?.hosted_managed?a(`div`,{className:`mt-3 rounded-xl border border-lime-500/20 bg-lime-500/10 px-3 py-2 text-xs text-lime-200`,children:`Hosted-managed features can safely key off this signal instead of guessing from hostname or environment.`}):null]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Config file`}),a(`div`,{className:`tcp-subtle mt-1 break-all text-xs`,children:Jt.data?.control_panel_config_path||Yt.data?.path||`control-panel-config.json`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Ready`}),a(`span`,{children:Jt.data?.control_panel_config_ready?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Missing`}),a(`span`,{children:Array.isArray(Jt.data?.control_panel_config_missing)?Jt.data?.control_panel_config_missing.join(`, `)||`none`:`unknown`})]})]})]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-sm font-medium`,children:`Control panel config JSON`}),a(`textarea`,{className:`tcp-input min-h-[28rem] font-mono text-xs leading-5`,value:L,onInput:e=>R(e.target.value),spellCheck:!1})]}),z?a(`div`,{className:`rounded-xl border border-rose-500/30 bg-rose-500/10 px-3 py-2 text-sm text-rose-200`,children:z}):null,a(`div`,{className:`tcp-subtle text-xs`,children:"This file holds non-secret install state: repo binding, provider defaults, task source, swarm policy, GitHub MCP preferences, and navigation defaults. Secrets should stay in `.env` or token files."})]})}):null,F===`providers`?a(X,{title:`Provider defaults`,subtitle:`Provider catalog, model selection, and API key entry.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:String(Zt.data?.default||``).trim()?`ok`:`warn`,children:[`Default: `,String(Zt.data?.default||`none`)]}),a(Y,{tone:`info`,children:[String(Xt.data?.connected?.length||0),` connected`]}),a(`button`,{className:`tcp-btn`,onClick:()=>S().then(()=>n(`ok`,`Provider status refreshed.`)),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh provider`]})]}),children:a(`div`,{className:`grid gap-3`,children:[a(`button`,{type:`button`,className:`tcp-list-item text-left`,onClick:()=>ye(e=>!e),"aria-expanded":ve,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium inline-flex items-center gap-2`,children:[a(`i`,{"data-lucide":ve?`chevron-down`:`chevron-right`}),a(`span`,{children:ve?`Hide provider catalog`:`Show provider catalog`})]}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:[mr.length,` providers available for configuration. Expand to change models and API keys.`]})]}),a(Y,{tone:`info`,children:[String(Xt.data?.connected?.length||0),` connected`]})]})}),a(l,{initial:!1,children:ve?a(s.div,{className:`grid gap-3`,initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},children:[a(`div`,{className:`tcp-list-item grid gap-3`,children:[a(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Custom OpenAI-compatible provider`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Add providers like MiniMax by ID, base URL, default model, and API key.`})]}),a(Y,{tone:sn.length?`ok`:`info`,children:[sn.length,` configured`]})]}),a(`button`,{type:`button`,className:`tcp-list-item text-left`,onClick:()=>xe(e=>!e),"aria-expanded":be,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium inline-flex items-center gap-2`,children:[a(`i`,{"data-lucide":be?`chevron-down`:`chevron-right`}),a(`span`,{children:be?`Hide custom provider form`:`Show custom provider form`})]}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Use this for OpenAI-compatible endpoints. Anthropic is handled by the built-in provider row below.`})]}),a(Y,{tone:`info`,children:`OpenAI-compatible only`})]})}),a(l,{initial:!1,children:be?a(s.div,{className:`grid gap-3`,initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},children:a(`form`,{className:`grid gap-3`,onSubmit:e=>{e.preventDefault(),jn.mutate({providerId:we,url:Ee,modelId:Oe,apiKey:Ae,makeDefault:Me})},children:[a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Provider ID`}),a(`input`,{className:`tcp-input`,value:we,onInput:e=>Te(e.target.value),placeholder:`custom`})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Default model`}),a(`input`,{className:`tcp-input`,value:Oe,onInput:e=>ke(e.target.value),placeholder:`MiniMax-M2`})]})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Base URL`}),a(`input`,{className:`tcp-input`,value:Ee,onInput:e=>De(e.target.value),placeholder:`https://api.minimax.io/v1`})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`API key`}),a(`input`,{className:`tcp-input`,type:`password`,value:Ae,onInput:e=>je(e.target.value),placeholder:`Optional. Leave blank to keep the existing key.`})]}),a(`label`,{className:`inline-flex items-center gap-2 text-sm text-slate-200`,children:[a(`input`,{type:`checkbox`,className:`accent-slate-400`,checked:Me,onChange:e=>Ne(e.target.checked)}),`Make this the default provider`]}),a(`div`,{className:`flex flex-wrap justify-end gap-2`,children:a(`button`,{className:`tcp-btn-primary`,type:`submit`,disabled:jn.isPending,children:[a(`i`,{"data-lucide":`plus`}),`Save custom provider`]})})]})}):null}),sn.length?a(`div`,{className:`grid gap-2`,children:sn.map(e=>a(`div`,{className:`flex flex-wrap items-start justify-between gap-2 rounded-xl border border-slate-700/60 bg-slate-900/20 px-3 py-2`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.id}),a(`div`,{className:`tcp-subtle break-all text-xs`,children:e.url||`No URL configured`}),a(`div`,{className:`tcp-subtle text-xs`,children:[`Model: `,e.model||`not set`]})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[e.isDefault?a(Y,{tone:`ok`,children:`default`}):null,a(`button`,{type:`button`,className:`tcp-btn h-8 px-3 text-xs`,onClick:()=>{Te(e.id),De(e.url),ke(e.model),Ne(e.isDefault),xe(!0),ye(!0)},children:[a(`i`,{"data-lucide":`square-pen`}),`Edit`]})]})]},e.id))}):null]}),mr.length?mr.map(e=>{let t=String(e?.id||``),n=Object.keys(e?.models||{}),r=String(Zt.data?.providers?.[t]?.default_model||n[0]||``),i=String(D[t]??r).trim(),o=i.toLowerCase(),c=n.filter(e=>o?e.toLowerCase().includes(o):!0).slice(0,80),l=Ry(e,n.length),u=zy(e,r),d=sr[t]||null,f=String(d?.keyUrl||``).trim(),p=tn[t]||{},m=String(Zt.data?.default||``).trim().toLowerCase(),h=t===Qv&&m===Qv,g=String(p?.auth_kind||p?.authKind||``).trim().toLowerCase(),_=String(p?.status||``).trim().toLowerCase(),v=String(p?.email||``).trim(),y=String(p?.display_name||p?.displayName||``).trim(),b=String(p?.managed_by||p?.managedBy||``).trim(),x=Number(p?.expires_at_ms||p?.expiresAtMs||0),S=p?.local_session_available===!0||p?.localSessionAvailable===!0,C=!!String(Se[t]||``).trim()||Vn.isPending&&String(Vn.variables?.providerId||``).trim().toLowerCase()===t,w=g===`oauth`&&p?.connected===!0&&_!==`reauth_required`,T=t===Qv,E=!T||nn||rn,k=C?{tone:`info`,text:`sign-in pending`}:w?{tone:`ok`,text:`account connected`}:_===`reauth_required`?{tone:`warn`,text:`reauth required`}:{tone:`warn`,text:`not connected`},A=rn&&t===Qv;return a(s.details,{layout:!0,className:`tcp-list-item`,children:[a(`summary`,{className:`cursor-pointer list-none`,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:t}),a(`div`,{className:`tcp-subtle text-xs`,children:u})]}),a(Y,{tone:l.tone,children:l.text})]})}),a(`div`,{className:`mt-3 grid gap-3`,children:[f&&!T?a(`div`,{className:`flex justify-end`,children:a(`a`,{className:`tcp-btn h-8 px-3 text-xs`,href:f,target:`_blank`,rel:`noreferrer`,children:[a(`i`,{"data-lucide":`external-link`}),`Get API key`]})}):null,a(`form`,{className:`grid gap-2`,onSubmit:e=>{e.preventDefault(),Br(t,i)},children:[a(`div`,{className:`flex gap-2`,children:[a(`input`,{className:`tcp-input`,value:i,placeholder:`Type model id for ${t}`,onInput:e=>O(n=>({...n,[t]:e.target.value}))}),a(`button`,{className:`tcp-btn`,type:`submit`,children:[a(`i`,{"data-lucide":`badge-check`}),`Apply`]})]}),a(`div`,{className:`max-h-48 overflow-auto rounded-xl border border-slate-700/60 bg-slate-900/20 p-1`,children:c.length?c.map(e=>a(`button`,{type:`button`,className:`block w-full rounded-lg px-2 py-1.5 text-left text-sm hover:bg-slate-700/30 ${e===r?`bg-slate-700/40`:``}`,onClick:()=>{O(n=>({...n,[t]:e})),Br(t,e)},children:e},e)):a(`div`,{className:`tcp-subtle px-2 py-1 text-xs`,children:n.length?`No matching models.`:`No live catalog available. Type a model ID manually.`})})]}),T?a(`div`,{className:`grid gap-3 rounded-xl border border-slate-700/60 bg-slate-900/20 p-3`,children:[a(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:String(d?.label||`Codex Account`)}),a(`div`,{className:`tcp-subtle text-xs`,children:String(d?.description||`Use your ChatGPT/Codex subscription instead of a separate API key.`)})]}),a(Y,{tone:k.tone,children:k.text})]}),a(`div`,{className:`grid gap-1 text-xs tcp-subtle`,children:[A?a(`div`,{className:`rounded-xl border border-sky-700/50 bg-sky-950/20 px-3 py-2 text-sky-100`,children:[a(`div`,{className:`font-medium`,children:`Recommended for hosted servers`}),a(`div`,{className:`mt-1`,children:[`Import a Codex `,a(`code`,{children:`auth.json`}),` from a signed-in machine. Browser OAuth on provisioned servers can stall after the consent screen, so the import path is the reliable v1 flow.`]})]}):null,C?a(`div`,{children:`Pending browser sign-in is saved in this browser session, so you can refresh this page and Tandem will keep checking when you come back.`}):null,w?a(`div`,{children:y||v?`Connected as ${y||v}.`:`Connected to a Codex account.`}):null,b?a(`div`,{children:[`Managed by`,` `,b===`codex-cli`?`the local Codex CLI session`:b===`codex-upload`?`an uploaded Codex auth.json`:`Tandem`,`.`]}):null,A&&w&&b===`codex-upload`?a(`div`,{children:[`This hosted server is currently using an imported Codex session stored on the VM. Import another`,` `,a(`code`,{children:`auth.json`}),` any time to replace it.`]}):null,x>0?a(`div`,{children:[`Session status refreshes through`,` `,new Date(x).toLocaleString(),`.`]}):null,t===Qv&&w&&!h?a(`div`,{children:`Tandem is connected to Codex, but new runs are still using a different default provider.`}):null,E?a(`div`,{children:A?`This Tandem-hosted server can import a Codex auth.json from a signed-in machine and keep the session on the VM.`:S?`Local Codex CLI session detected on this machine.`:`If the Codex CLI is already signed in on this machine, you can mirror that session here instead of starting a fresh browser login.`}):null,E?null:a(`div`,{children:`Codex account sign-in is only enabled when this control panel is connected to a local engine or a Tandem-hosted managed server.`})]}),A?a(`div`,{className:`grid gap-3`,children:[a(`input`,{ref:Ht,type:`file`,accept:`.json,application/json`,className:`hidden`,onChange:e=>{qn(t,e.target.files?.[0]||null)}}),a(`textarea`,{className:`tcp-input min-h-40 resize-y rounded-xl p-3 font-mono text-xs leading-5`,value:Pe,onChange:e=>Fe(e.target.value),placeholder:`Paste the contents of ~/.codex/auth.json here.
7372
+ `).trim(),modelProvider:``,modelId:``}),C(`Imported "${e.name}" into the agent form — review and save below.`),setTimeout(()=>{k.current?.scrollIntoView({behavior:`smooth`,block:`start`})},80)},de=e=>{if(!e)return;if(e.size>10*1024*1024){t(`err`,`Avatar image is too large (max 10 MB).`);return}let n=new FileReader;n.onload=()=>{let e=typeof n.result==`string`?n.result:``;if(!e){t(`err`,`Failed to read avatar image.`);return}d(t=>({...t,avatarUrl:e}))},n.onerror=()=>t(`err`,`Failed to read avatar image.`),n.readAsDataURL(e)};return a(`div`,{ref:l,className:`grid gap-4`,children:[A&&a(yr,{title:`Agent Standup`,subtitle:`Compose scheduled standups from the same saved agents you manage here`,children:a(Ev,{client:e,toast:t,workspaceRoot:N,onWorkspaceRootChange:T,defaultWorkspaceRoot:M,timezone:E,onTimezoneChange:D,templates:ee.map(e=>({templateId:e.templateId,displayName:e.displayName||e.templateId,role:e.role,modelLabel:e.modelProvider&&e.modelId?`${e.modelProvider}/${e.modelId}`:``}))})}),a(yr,{title:`Agent Catalog`,subtitle:`Browse and import from the canonical Codex subagent set. Use any entry to pre-fill the agent form below.`,children:a(`div`,{className:`grid gap-3`,children:[a(`div`,{className:`grid gap-2 md:grid-cols-[1fr_auto]`,children:[a(`input`,{className:`tcp-input`,placeholder:`Search agent name, category, tag, or path`,value:h,onInput:e=>g(e.target.value)}),a(`button`,{className:`tcp-btn`,onClick:()=>{g(``),b(`all`)},disabled:!h&&v===`all`,children:`Clear`})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${v===`all`?`border-amber-400/60 bg-amber-400/10`:``}`,onClick:()=>b(`all`),children:`All`}),Dv.categories.map(e=>a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${v===e.id?`border-amber-400/60 bg-amber-400/10`:``}`,onClick:()=>b(e.id),children:[e.title,` (`,e.count,`)`]},e.id))]}),S?a(`div`,{className:`text-xs text-slate-400`,children:S}):null,ae.length?ae.map(e=>a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`flex items-start justify-between gap-2`,children:[a(`div`,{children:[a(`div`,{className:`font-medium text-slate-100`,children:e.title}),a(`div`,{className:`text-xs text-slate-400`,children:e.summary})]}),a(`div`,{className:`tcp-badge-info`,children:[e.agents.length,` agents`]})]}),a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:e.agents.map(e=>a(`div`,{className:`tcp-list-item grid gap-2`,children:[a(`div`,{className:`flex items-start justify-between gap-2`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`truncate font-semibold text-slate-100`,children:e.name}),a(`div`,{className:`text-xs text-slate-400`,children:e.summary})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`span`,{className:`tcp-badge-info`,children:e.role}),a(`span`,{className:e.sandbox_mode===`read-only`?`tcp-badge-warn`:`tcp-badge-ok`,children:e.sandbox_mode})]})]}),a(`div`,{className:`font-mono text-xs text-slate-400`,children:e.source_path}),a(`div`,{className:`line-clamp-3 text-xs text-slate-200`,children:Lv(e)}),a(`div`,{className:`flex flex-wrap gap-1`,children:[e.tags.slice(0,4).map(t=>a(`span`,{className:`tcp-badge-muted`,children:t},`${e.id}-${t}`)),e.requires.slice(0,3).map(t=>a(`span`,{className:`tcp-badge-info`,children:t},`${e.id}-${t}`))]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn h-8 px-3 text-xs`,title:`Pre-fill the agent creation form from this catalog entry`,onClick:()=>ue(e),children:[a(`i`,{"data-lucide":`download`}),`Import as Agent`]}),a(`button`,{className:`tcp-btn h-8 px-3 text-xs`,title:`Open this agent in Studio (new tab)`,onClick:()=>le(e),children:[a(`i`,{"data-lucide":`external-link`}),`Studio ↗`]}),a(`button`,{className:`tcp-btn h-8 px-3 text-xs ${oe===e.source_path?`border-emerald-400/60 bg-emerald-400/10 text-emerald-300`:``}`,title:`Copy source path to clipboard`,onClick:()=>void ce(e.source_path),children:[a(`i`,{"data-lucide":oe===e.source_path?`check`:`copy`}),oe===e.source_path?`Copied`:`Copy path`]})]})]},e.source_path))})]},e.id)):a(br,{text:`No agents match your search.`})]})}),a(`div`,{className:`grid gap-4 xl:grid-cols-2`,children:[a(`div`,{ref:k,children:a(yr,{title:`Agents`,subtitle:`Create reusable agent personalities, prompts, and default models for automation workflows`,children:a(`div`,{className:`grid gap-3`,children:[a(`div`,{className:`rounded-2xl border border-cyan-500/20 bg-cyan-500/5 p-4`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-cyan-300`,children:`Reusable Personalities`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:`Each saved agent defines a persistent personality for automation workflows. Define who the agent is, what kind of work it owns, and which default model it should use. These personalities can be reused in standups and other workflow responses.`})]}),a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:[a(`input`,{className:`tcp-input`,placeholder:`template-id`,value:u.templateId,disabled:!!f,onInput:e=>d(t=>({...t,templateId:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Display name`,value:u.displayName,onInput:e=>d(t=>({...t,displayName:e.target.value}))}),a(`select`,{className:`tcp-input`,value:u.role,onInput:e=>d(t=>({...t,role:e.target.value})),children:kv.map(e=>a(`option`,{value:e,children:e},e))}),a(`input`,{className:`tcp-input`,placeholder:`Avatar URL or upload (optional)`,value:u.avatarUrl,onInput:e=>d(t=>({...t,avatarUrl:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Model provider (optional)`,value:u.modelProvider,onInput:e=>d(t=>({...t,modelProvider:e.target.value}))}),a(`input`,{className:`tcp-input`,placeholder:`Model ID (optional)`,value:u.modelId,onInput:e=>d(t=>({...t,modelId:e.target.value}))})]}),a(`div`,{className:`grid gap-3 lg:grid-cols-[1.15fr_0.85fr]`,children:[a(`div`,{className:`rounded-2xl border border-slate-800/80 bg-slate-950/40 px-4 py-3`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Prompt Guidance`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:`Write the lasting perspective for this agent, not a one-off task. Good prompts describe ownership and judgment: frontend lead, backend lead, product ops, incident watcher.`}),a(`div`,{className:`mt-3 flex flex-wrap gap-2`,children:jv.map(e=>a(`button`,{type:`button`,className:`tcp-btn h-auto min-h-8 px-3 py-2 text-left text-xs`,onClick:()=>d(t=>({...t,systemPrompt:e})),children:`Use Example`},e))})]}),a(`div`,{className:`rounded-[28px] border border-slate-800/80 bg-[radial-gradient(circle_at_top,_rgba(34,211,238,0.18),_transparent_45%),linear-gradient(180deg,rgba(15,23,42,0.9),rgba(2,6,23,0.96))] p-5`,children:[a(`div`,{className:`flex items-start justify-between gap-4`,children:[a(`div`,{className:`flex items-start gap-4`,children:[a(`div`,{className:`flex h-14 w-14 items-center justify-center overflow-hidden rounded-2xl border border-cyan-400/30 bg-cyan-400/10 text-lg font-semibold text-cyan-100`,children:re?a(`img`,{src:re,alt:te,className:`h-full w-full object-cover`}):U}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`flex flex-wrap items-center gap-2`,children:[a(`strong`,{className:`text-white`,children:te}),a(`span`,{className:`tcp-badge-info`,children:u.role})]}),a(`div`,{className:`mt-1 text-xs text-slate-400`,children:u.templateId.trim()||`template-id`}),a(`div`,{className:`mt-2 text-sm text-slate-300`,children:ne})]})]}),a(`div`,{className:`flex items-center gap-2`,children:[a(`button`,{type:`button`,className:`tcp-icon-btn`,title:`Upload avatar`,"aria-label":`Upload avatar`,onClick:()=>O.current?.click(),children:a(`i`,{"data-lucide":`pencil`})}),a(`button`,{type:`button`,className:`tcp-icon-btn`,title:`Clear avatar`,"aria-label":`Clear avatar`,onClick:()=>d(e=>({...e,avatarUrl:``})),children:a(`i`,{"data-lucide":`trash-2`})})]})]}),a(`div`,{className:`mt-3 text-xs text-slate-400`,children:`Upload an image like Settings Identity preview, or paste a direct avatar URL.`}),a(`input`,{ref:O,type:`file`,accept:`image/*`,className:`hidden`,onChange:e=>{de(e.target.files?.[0]||null),e.target.value=``}}),a(`div`,{className:`mt-4 rounded-2xl border border-slate-800/70 bg-black/20 p-4`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Personality Preview`}),a(`div`,{className:`mt-2 whitespace-pre-wrap text-sm leading-6 text-slate-200`,children:u.systemPrompt.trim()||`This agent will respond from the persistent personality you define here across workflows and standups.`})]}),(u.modelProvider.trim()||u.modelId.trim())&&a(`div`,{className:`mt-3 text-xs text-cyan-200`,children:[`Default model: `,u.modelProvider.trim()||`provider`,`/`,u.modelId.trim()||`model`]})]})]}),a(`textarea`,{className:`tcp-input min-h-[140px]`,placeholder:`Persistent system prompt`,value:u.systemPrompt,onInput:e=>d(t=>({...t,systemPrompt:e.target.value}))}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn`,disabled:L.isPending,onClick:()=>L.mutate(),children:[a(`i`,{"data-lucide":`save`}),f?`Update Agent`:`Create Agent`]}),H&&a(`button`,{type:`button`,className:`tcp-btn`,onClick:()=>{p(null),d(Mv)},children:[a(`i`,{"data-lucide":`rotate-ccw`}),`Reset`]})]}),a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`flex items-center justify-between gap-2`,children:[a(`div`,{className:`text-xs font-medium uppercase tracking-[0.24em] text-slate-500`,children:`Saved Agents`}),a(`div`,{className:`tcp-subtle text-xs`,children:[ee.length,` saved`]})]}),ee.length?ee.map(e=>a(`div`,{className:`tcp-list-item`,children:a(`div`,{className:`flex items-start justify-between gap-3`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`flex items-center gap-2`,children:[a(`strong`,{children:e.displayName||e.templateId}),a(`span`,{className:`tcp-badge-info`,children:e.role}),e.modelProvider&&e.modelId?a(`span`,{className:`tcp-badge-ok`,children:[e.modelProvider,`/`,e.modelId]}):null]}),a(`div`,{className:`tcp-subtle text-xs`,children:e.templateId}),e.systemPrompt?a(`div`,{className:`mt-2 line-clamp-4 text-xs text-slate-300`,children:e.systemPrompt}):a(`div`,{className:`mt-2 text-xs text-slate-500`,children:`No persistent prompt set yet.`})]}),a(`div`,{className:`flex gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn h-7 px-2 text-xs`,onClick:()=>{p(e.templateId),d({templateId:e.templateId,displayName:e.displayName,avatarUrl:e.avatarUrl,role:kv.includes(e.role)?e.role:`worker`,systemPrompt:e.systemPrompt,modelProvider:e.modelProvider,modelId:e.modelId})},children:[a(`i`,{"data-lucide":`pencil`}),`Edit`]}),a(`button`,{type:`button`,className:`tcp-btn-danger h-7 px-2 text-xs`,onClick:()=>R.mutate(e.templateId),children:[a(`i`,{"data-lucide":`trash-2`}),`Delete`]})]})]})},e.templateId)):a(br,{title:`No agents yet`,text:`Create your first saved personality here, then reuse it across automation workflows and standups.`})]})]})})}),a(yr,{title:`Team Instances`,subtitle:`Running collaborative agent instances`,children:a(`div`,{className:`grid gap-2`,children:B.length?B.map((e,t)=>a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[a(`strong`,{children:String(e?.template_id||e?.templateID||e?.instance_id||`Instance`)}),a(`span`,{className:`tcp-badge-info`,children:String(e?.status||`active`)})]}),a(`div`,{className:`tcp-subtle text-xs`,children:[`mission: `,String(e?.mission_id||e?.missionID||`n/a`)]})]},String(e?.instance_id||e?.id||t))):a(br,{text:`No team instances found.`})})}),a(yr,{title:`Spawn Approvals`,subtitle:`Pending team approval requests`,children:a(`div`,{className:`grid gap-2`,children:V.length?V.map((e,t)=>{let n=String(e?.approval_id||e?.request_id||e?.id||`request-${t}`);return a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`mb-1 font-medium`,children:String(e?.reason||e?.title||n)}),a(`div`,{className:`tcp-subtle text-xs`,children:n}),a(`div`,{className:`mt-2 flex gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn h-7 px-2 text-xs`,onClick:()=>z.mutate({requestId:n,decision:`approve`}),children:[a(`i`,{"data-lucide":`badge-check`}),`Approve`]}),a(`button`,{type:`button`,className:`tcp-btn-danger h-7 px-2 text-xs`,onClick:()=>z.mutate({requestId:n,decision:`deny`}),children:[a(`i`,{"data-lucide":`x`}),`Deny`]})]})]},n)}):a(br,{text:`No pending approvals.`})})})]})]})}function zv({theme:e}){let t=e?.cssVars?.[`--color-background`]||`#000000`,n=e?.cssVars?.[`--color-surface`]||`#111111`,r=e?.cssVars?.[`--color-primary`]||`#ffffff`,i=e?.cssVars?.[`--color-secondary`]||`#ffffff`;return a(`div`,{className:`flex items-center gap-2`,children:[a(`span`,{className:`tcp-theme-swatch`,style:{background:t},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:n},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:r},"aria-hidden":`true`}),a(`span`,{className:`tcp-theme-swatch`,style:{background:i},"aria-hidden":`true`})]})}function Bv({themes:e,themeId:t,onChange:n}){return a(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.map(e=>{let r=e.id===t;return a(s.button,{type:`button`,layout:!0,onClick:()=>n(e.id),className:`tcp-theme-tile ${r?`active`:``}`,whileHover:{y:-2},whileTap:{scale:.985},transition:Nn.spring.gentle,children:[a(`div`,{className:`tcp-theme-tile-top`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`tcp-theme-tile-title`,children:e.name}),a(`p`,{className:`tcp-subtle mt-1 text-xs`,children:e.description})]}),a(zv,{theme:e})]}),a(`div`,{className:`tcp-theme-preview`,children:a(`div`,{className:`tcp-theme-preview-bg`,style:{background:e.cssVars[`--color-background`]||`#000`},children:a(`div`,{className:`tcp-theme-preview-card`,style:{background:e.cssVars[`--color-surface`]||`#111`,borderColor:e.cssVars[`--color-border`]||`rgba(255,255,255,0.1)`},children:[a(`div`,{className:`tcp-theme-preview-line short`,style:{background:e.cssVars[`--color-text`]||`#fff`}}),a(`div`,{className:`tcp-theme-preview-line`,style:{background:e.cssVars[`--color-text-muted`]||`#aaa`}}),a(`div`,{className:`tcp-theme-preview-pill`,style:{background:e.cssVars[`--color-primary`]||`#fff`}})]})})}),a(l,{initial:!1,children:r?a(s.span,{className:`tcp-theme-active`,initial:{opacity:0,scale:.86},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.86},transition:Nn.spring.snappy,children:[a(`i`,{"data-lucide":`badge-check`}),`Active`]}):null})]},e.id)})})}var Vv=`tcp.nav.visibility.v1`,Hv=new Set([`dashboard`,`chat`,`workflows`,`automations`,`coding`,`files`,`settings`]);function Uv(e){let t=new Set([`planner`,`studio`,`coding`,`memory`,`files`,`marketplace`,`orchestrator`,`experiments`,`teams`]);return Object.fromEntries(lr.map(([n])=>[n,e?Hv.has(n):!t.has(n)]))}function Wv(e,t){let n=Uv(t);if(!e||typeof e!=`object`)return n;let r=e,i={...n};for(let[e]of lr)typeof r[e]==`boolean`&&(i[e]=r[e]);if(t)for(let e of Hv)i[e]=!0;return i}function Gv(e){try{let t=localStorage.getItem(Vv);return t?Wv(JSON.parse(t),e):Uv(e)}catch{return Uv(e)}}function Kv(e){try{localStorage.setItem(Vv,JSON.stringify(e))}catch{}}function qv(e){return lr.filter(([t])=>e[t]!==!1)}var Jv=`tandem_control_panel_pending_provider_oauth`;function Yv(){if(typeof window>`u`)return{};try{let e=window.sessionStorage.getItem(Jv)||``;if(!e)return{};let t=JSON.parse(e);return!t||typeof t!=`object`?{}:Object.fromEntries(Object.entries(t).map(([e,t])=>[String(e||``).trim().toLowerCase(),String(t||``).trim()]).filter(([e,t])=>!!e&&!!t))}catch{return{}}}function Xv(e){if(!(typeof window>`u`))try{let t=Object.fromEntries(Object.entries(e||{}).map(([e,t])=>[String(e||``).trim().toLowerCase(),String(t||``).trim()]).filter(([e,t])=>!!e&&!!t));if(!Object.keys(t).length){window.sessionStorage.removeItem(Jv);return}window.sessionStorage.setItem(Jv,JSON.stringify(t))}catch{}}var Zv=new Set([`openai`,`openai-codex`,`openrouter`,`anthropic`,`ollama`,`groq`,`mistral`,`together`,`azure`,`bedrock`,`vertex`,`copilot`,`cohere`]),Qv=`openai-codex`,$v=[`telegram`,`discord`,`slack`];function ey(e){let t=String(e||``).trim().toLowerCase();return t.startsWith(`mcp_header::`)||t.startsWith(`channel::`)}var ty=[{label:`File`,tools:[`read`,`glob`,`ls`,`list`,`grep`,`codesearch`,`search`]},{label:`Web`,tools:[`websearch`,`webfetch`,`webfetch_html`]},{label:`Terminal`,tools:[`bash`,`write`,`edit`,`apply_patch`]},{label:`Memory`,tools:[`memory_search`,`memory_store`,`memory_list`]},{label:`Other`,tools:[`skill`,`task`,`question`,`pack_builder`]}],ny=`tandem.workflow_planner`,ry=[`websearch`,`webfetch`,`webfetch_html`,`memory_search`,`memory_store`,`memory_list`];function iy(e){try{return new URL(e)}catch{return null}}function ay(e){return String(e||``).trim().toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^-+|-+$/g,``)||`mcp-server`}function oy(e){let t=iy(e);if(!t)return``;let n=String(t.hostname||``).toLowerCase();if(!n)return``;if(n.endsWith(`composio.dev`))return`composio`;let r=n.split(`.`).filter(Boolean);return r.length?ay([`backend`,`api`,`mcp`,`www`].includes(r[0])&&r[1]||r[0]):``}function sy(e){let t=iy(e);return t?String(t.hostname||``).toLowerCase().endsWith(`composio.dev`):!1}function cy(e){let t=iy(e);if(!t)return!1;let n=String(t.hostname||``).toLowerCase();return n===`api.githubcopilot.com`||n.endsWith(`.githubcopilot.com`)}function ly(e){let t=iy(e);if(!t)return!1;let n=String(t.hostname||``).toLowerCase();return n===`mcp.notion.com`||n.endsWith(`.notion.com`)}function uy(e,t){return String(e||``).trim().toLowerCase()===`notion`||ly(t)?`Notion uses browser OAuth. Save the server, finish the Notion sign-in in your browser, then come back and click Mark sign-in complete. Token paste is not the right flow for this MCP.`:`This MCP server uses browser OAuth. Save it, complete the authorization page that opens in your browser, then come back and finish the connection in Tandem.`}function dy(e){return e.map(e=>({key:String(e?.key||``).trim(),value:String(e?.value||``).trim()}))}function fy(e,t){let n={...e};for(let e of dy(t))!e.key||!e.value||(n[e.key]=e.value);return n}function py({authMode:e,token:t,customHeader:n,transport:r}){let i=String(t||``).trim();if(e===`oauth`||!i||e===`none`)return{};if(e===`custom`){let e=String(n||``).trim();if(!e)throw Error(`Custom header name is required.`);return{[e]:i}}return e===`x-api-key`?{"x-api-key":i}:e===`bearer`?{Authorization:`Bearer ${i.replace(/^bearer\s+/i,``).trim()}`}:sy(r)?{"x-api-key":i}:{Authorization:`Bearer ${i.replace(/^bearer\s+/i,``).trim()}`}}function my(e,t,n,r){return e===`oauth`?`OAuth handoff: Tandem will open the server authorization flow on connect.`:!String(t||``).trim()||e===`none`?`No auth header will be sent.`:e===`custom`?n?`Header preview: ${n}: <token>`:`Set a custom header name.`:e===`x-api-key`?`Header preview: x-api-key: <token>`:e===`bearer`?`Header preview: Authorization: Bearer <token>`:sy(r)?`Auto mode: selected x-api-key for this endpoint`:`Auto mode: using Authorization Bearer token`}function hy(e,t=``){if(!e||typeof e!=`object`)return null;let n=e,r=String(n.name||t||``).trim();if(!r)return null;let i=n.last_auth_challenge||n.lastAuthChallenge||null;return{name:r,transport:String(n.transport||``).trim(),authKind:String(n.auth_kind||n.authKind||``).trim().toLowerCase(),connected:!!n.connected,enabled:n.enabled!==!1,lastError:String(n.last_error||n.lastError||``).trim(),lastAuthChallenge:i&&typeof i==`object`?i:null,authorizationUrl:String(n.authorization_url||n.authorizationUrl||``).trim(),headers:n.headers&&typeof n.headers==`object`?n.headers:{},toolCache:Array.isArray(n.tool_cache||n.toolCache)?n.tool_cache||n.toolCache:[],allowedTools:Array.isArray(n.allowed_tools||n.allowedTools)?(n.allowed_tools||n.allowedTools).map(e=>String(e||``).trim()).filter(Boolean):null}}function gy(e,t,n){let r=String(t||``).trim().toLowerCase(),i=String(n||``).trim().replace(/\/+$/,``).toLowerCase(),a=e.servers.find(e=>{let t=String(e.transportUrl||``).trim().replace(/\/+$/,``).toLowerCase(),n=String(e.slug||``).trim().toLowerCase(),a=String(e.serverConfigName||``).trim().toLowerCase();return i&&t&&t===i||i&&t&&t.includes(i)||i&&t&&i.includes(t)||!!r&&(n===r||a===r)});return String(a?.authKind||``).trim().toLowerCase()}function _y(e){return Array.isArray(e)?e.map(e=>hy(e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name)):!e||typeof e!=`object`?[]:Array.isArray(e.servers)?e.servers.map(e=>hy(e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name)):Object.entries(e).map(([e,t])=>hy(t&&typeof t==`object`?t:{transport:String(t||``)},e)).filter(e=>!!e).sort((e,t)=>e.name.localeCompare(t.name))}function vy(e){return(Array.isArray(e)?e:Array.isArray(e?.tools)?e.tools:[]).map(e=>typeof e==`string`?e:!e||typeof e!=`object`?``:String(e.namespaced_name||e.namespacedName||e.id||e.tool_name||e.toolName||``).trim()).filter(Boolean)}function yy(e){let t=e&&typeof e==`object`?e:{},n=Array.isArray(t.servers)?t.servers:[];return{generatedAt:String(t.generated_at||``).trim(),count:Number.isFinite(Number(t.count))?Number(t.count):n.length,servers:n.map(e=>!e||typeof e!=`object`?null:{slug:String(e.slug||``).trim(),name:String(e.name||e.slug||``).trim(),description:String(e.description||``).trim(),transportUrl:String(e.transport_url||``).trim(),serverConfigName:String(e.server_config_name||e.slug||``).trim(),documentationUrl:String(e.documentation_url||``).trim(),directoryUrl:String(e.directory_url||``).trim(),toolCount:Number.isFinite(Number(e.tool_count))?Number(e.tool_count):0,requiresAuth:e.requires_auth!==!1,requiresSetup:!!e.requires_setup,authKind:String(e.auth_kind||e.authKind||``).trim().toLowerCase()}).filter(e=>!!e&&!!e.slug&&!!e.transportUrl).sort((e,t)=>e.name.localeCompare(t.name))}}function by(e,t){let n=t&&typeof t==`object`?t:{};return{botToken:``,allowedUsers:Array.isArray(n.allowed_users)?n.allowed_users.join(`, `):``,mentionOnly:n.mention_only!==!1&&e===`discord`?!0:!!n.mention_only,guildId:String(n.guild_id||``).trim(),channelId:String(n.channel_id||``).trim(),modelProviderId:String(n.model_provider_id||``).trim(),modelId:String(n.model_id||``).trim(),styleProfile:String(n.style_profile||`default`).trim()||`default`,securityProfile:String(n.security_profile||`operator`).trim()||`operator`}}function xy(){return{enabled_tools:[],disabled_tools:[],enabled_mcp_servers:[],enabled_mcp_tools:[]}}function Sy(e){return Array.from(new Set(e.map(e=>e.trim()).filter(Boolean)))}function Cy(e){let t=e&&typeof e==`object`?e:{};return{enabled_tools:Array.isArray(t.enabled_tools)?Sy(t.enabled_tools.map(e=>String(e))):[],disabled_tools:Array.isArray(t.disabled_tools)?Sy(t.disabled_tools.map(e=>String(e))):[],enabled_mcp_servers:Array.isArray(t.enabled_mcp_servers)?Sy(t.enabled_mcp_servers.map(e=>String(e))):[],enabled_mcp_tools:Array.isArray(t.enabled_mcp_tools)?Sy(t.enabled_mcp_tools.map(e=>String(e))):[]}}function wy(e){let t=e&&typeof e==`object`?e:{};return(Array.isArray(t.scopes)?t.scopes:[]).map(e=>{if(!e||typeof e!=`object`)return null;let t=String(e.scope_id||e.scopeId||``).trim();return t?{scope_id:t,scope_kind:String(e.scope_kind||e.scopeKind||``).trim(),session_count:Number.isFinite(Number(e.session_count))?Number(e.session_count):Number.isFinite(Number(e.sessionCount))?Number(e.sessionCount):0,sender_count:Number.isFinite(Number(e.sender_count))?Number(e.sender_count):Number.isFinite(Number(e.senderCount))?Number(e.senderCount):0,last_seen_at_ms:Number.isFinite(Number(e.last_seen_at_ms))?Number(e.last_seen_at_ms):Number.isFinite(Number(e.lastSeenAtMs))?Number(e.lastSeenAtMs):0}:null}).filter(e=>!!e).sort((e,t)=>e.last_seen_at_ms===t.last_seen_at_ms?e.scope_id.localeCompare(t.scope_id):t.last_seen_at_ms-e.last_seen_at_ms)}function Ty(e){let t=[];return e.scope_kind&&t.push(e.scope_kind),t.push(e.scope_id),e.session_count>1?t.push(`${e.session_count} sessions`):e.session_count===1&&t.push(`1 session`),t.join(` · `)}function Ey(e,t){let n=e.enabled_tools.filter(e=>e!==ny);return t===ny?e.disabled_tools.includes(t)?!1:e.enabled_tools.includes(t):e.disabled_tools.includes(t)?!1:n.length===0||n.includes(t)}function Dy(e,t,n){let r=e.disabled_tools.filter(e=>e!==t),i=e.enabled_tools.filter(e=>e!==ny);return t===ny?n?{...e,disabled_tools:r,enabled_tools:Sy([...e.enabled_tools,t])}:{...e,disabled_tools:Sy([...r,t]),enabled_tools:e.enabled_tools.filter(e=>e!==t)}:n?{...e,disabled_tools:r,enabled_tools:i.length>0?Sy([...e.enabled_tools,t]):e.enabled_tools}:{...e,disabled_tools:Sy([...r,t]),enabled_tools:i.length>0?e.enabled_tools.filter(e=>e!==t):e.enabled_tools}}function Oy(e,t,n){let r=e.enabled_mcp_servers.filter(e=>e!==t);return{...e,enabled_mcp_servers:n?Sy([...r,t]):r}}function ky(e,t,n){let r=`mcp.${yc(t)}.`,i=e.enabled_mcp_tools.filter(e=>e.startsWith(r));return i.length?n.some(e=>e.startsWith(r))?i:i.map(e=>e.slice(r.length)).filter(Boolean):null}function Ay(e,t,n,r){let i=`mcp.${yc(t)}.`,a=e=>{let t=String(e||``).trim();return t?t.startsWith(`mcp.`)?t:`${i}${t}`:``},o=Sy(n.map(a).filter(Boolean)),s=e.enabled_mcp_tools.filter(e=>!e.startsWith(i)),c=r===null?o:Sy(r.map(a).filter(Boolean));return{...e,enabled_mcp_tools:Sy([...s,...c])}}function jy(e,t){return e===`public_demo`?ry.includes(t):!0}function My(e,t,n){return jy(n,t)&&Ey(e,t)}function Ny(e){let t=String(e||``).split(`,`).map(e=>e.trim()).filter(Boolean);return t.length?t:[`*`]}function Py(e){let t=(Array.isArray(e)?e:String(e||``).split(`,`)).map(e=>String(e||``).trim()).filter(Boolean);return t.length?Array.from(new Set(t)):[`*`]}function Fy(e,t){let n=Py(e).slice().sort(),r=Py(t).slice().sort();return n.length===r.length?n.every((e,t)=>e===r[t]):!1}function Iy(e,t){let n=t&&typeof t==`object`?t:{},r=Py(n.allowed_users);return!!n.has_token||r.some(e=>e!==`*`)||!!n.mention_only||!!String(n.guild_id||``).trim()||!!String(n.channel_id||``).trim()||!!String(n.model_provider_id||``).trim()||!!String(n.model_id||``).trim()||String(n.style_profile||`default`).trim()!==`default`||String(n.security_profile||`operator`).trim()!==`operator`}function Ly(e,t,n){let r=by(e,n);return!String(t.botToken||``).trim()&&Fy(t.allowedUsers,r.allowedUsers)&&!!t.mentionOnly==!!r.mentionOnly&&String(t.guildId||``).trim()===String(r.guildId||``).trim()&&String(t.channelId||``).trim()===String(r.channelId||``).trim()&&String(t.modelProviderId||``).trim()===String(r.modelProviderId||``).trim()&&String(t.modelId||``).trim()===String(r.modelId||``).trim()&&String(t.styleProfile||`default`).trim()===String(r.styleProfile||`default`).trim()&&String(t.securityProfile||`operator`).trim()===String(r.securityProfile||`operator`).trim()}function Ry(e,t){let n=String(e?.catalog_source||``).trim().toLowerCase();return n===`remote`&&t>0?{tone:`ok`,text:`${t} models`}:n===`config`&&t>0?{tone:`info`,text:`configured models`}:{tone:`warn`,text:`manual entry`}}function zy(e,t){return String(e?.catalog_message||``).trim()||`Default model: ${t||`none`}`}var By={dashboard:`Command status, activity, and fast paths.`,chat:`Session-driven conversation, uploads, and live responses.`,planner:`Advanced long-horizon planning and governed handoff.`,studio:`Advanced template-first workflow builder.`,automations:`Reusable routines, approvals, and execution history.`,experiments:`Opt-in automation experiments, optimization campaigns, and team approvals.`,coding:`ACA intake, task launchers, and coding runs.`,agents:`Reusable agent roles and workflow drafts.`,orchestrator:`Task board planning, approvals, and execution.`,memory:`Searchable memory records and operational context.`,files:`Managed files plus the hosted knowledgebase upload surface.`,runs:`Live operations overview with queue state and per-run inspection.`,settings:`Provider defaults, themes, and runtime diagnostics.`};function Vy({client:e,api:t,toast:n,navigate:i,currentRoute:u,providerStatus:d,identity:f,themes:g,setTheme:v,themeId:b,refreshProviderStatus:S,refreshIdentityStatus:C,navigation:w}){let T=_(),E=c(null),[D,O]=r({}),[k,A]=r(String(f?.botName||`Tandem`)),[j,M]=r(String(f?.botAvatarUrl||``)),[N,P]=r(`Control Center`),[F,I]=r(d?.needsOnboarding?`providers`:w?.acaMode?`navigation`:`install`),[L,R]=r(``),[z,ee]=r(``),[B,V]=r(`auto`),[H,te]=r(``),[U,ne]=r(``),[re,ie]=r(`10000`),[ae,oe]=r(``),[se,ce]=r(``),[le,ue]=r(`autonomous AI agentic workflows`),[de,fe]=r(null),[pe,W]=r(`multi`),[G,K]=r(``),[me,he]=r(!1),[ge,_e]=r(!1),[ve,ye]=r(!1),[be,xe]=r(!1),[Se,Ce]=r(()=>Yv()),[we,Te]=r(`custom`),[Ee,De]=r(``),[Oe,ke]=r(``),[Ae,je]=r(``),[Me,Ne]=r(!0),[Pe,Fe]=r(``),[q,Ie]=r({}),Le=c({telegram:!1,discord:!1,slack:!1}),[Re,ze]=r({telegram:``,discord:``,slack:``}),[Be,Ve]=r({telegram:!1,discord:!1,slack:!1}),[He,Ue]=r({}),[We,Ge]=r(!1),[Ke,qe]=r(``),[Je,Ye]=r(``),[Xe,Ze]=r(`none`),[Qe,$e]=r(``),[et,tt]=r(``),[nt,rt]=r(``),[it,at]=r([]),[ot,st]=r(!0),[ct,lt]=r(``),[ut,dt]=r(`manual`),[ft,pt]=r(``),[mt,ht]=r(!1),[J,gt]=r(!1),[_t,vt]=r(``),[yt,bt]=r(``),[xt,St]=r(``),[Ct,wt]=r(`auto`),[Tt,Et]=r(``),[Dt,Ot]=r(``),[kt,At]=r(!0),[jt,Mt]=r(!1),[Nt,Pt]=r(!0),[Ft,It]=r(!1),[Lt,Rt]=r(``),[zt,Bt]=r(``),Vt=c(null),Ht=c(null),[Ut,Wt]=r(``);m(()=>{Xv(Se)},[Se]);let Gt=async()=>{let n=e?.identity;return n?.get?n.get():t(`/api/engine/config/identity`,{method:`GET`})},Kt=async n=>{let r=e?.identity;return r?.patch?r.patch(n):t(`/api/engine/config/identity`,{method:`PATCH`,body:JSON.stringify(n)})},qt=y({queryKey:[`settings`,`identity`,`config`],queryFn:()=>Gt().catch(()=>({identity:{}}))});m(()=>{let e=qt.data?.identity?.bot||{},t=e?.aliases||{},n=String(e?.canonicalName||e?.canonical_name||f?.botName||`Tandem`).trim(),r=String(e?.avatarUrl||e?.avatar_url||f?.botAvatarUrl||``).trim(),i=String(t?.controlPanel||t?.control_panel||``).trim();A(n||`Tandem`),M(r),P(i||`Control Center`)},[f?.botAvatarUrl,f?.botName,qt.data]),m(()=>{u===`mcp`&&I(`mcp`),u===`channels`&&I(`channels`),u===`bug-monitor`&&I(`bug_monitor`)},[u]);let Jt=y({queryKey:[`settings`,`install`,`profile`],queryFn:()=>t(`/api/install/profile`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),Yt=y({queryKey:[`settings`,`install`,`config`],queryFn:()=>t(`/api/control-panel/config`,{method:`GET`}).catch(()=>null)});m(()=>{let e=Yt.data?.config||null;if(e)try{R(JSON.stringify(e,null,2)),ee(``)}catch{ee(`Loaded config could not be rendered as JSON.`)}},[Yt.data]),m(()=>{if(u===`settings`){if(d?.needsOnboarding){I(`providers`),ye(!0);return}if(!w?.acaMode){I(`install`);return}I(Jt.data?.aca_integration!==!0||Jt.data?.control_panel_config_ready!==!0?`install`:`navigation`)}},[u,w?.acaMode,d?.needsOnboarding,Jt.data?.aca_integration,Jt.data?.control_panel_config_ready]);let Xt=y({queryKey:[`settings`,`providers`,`catalog`],queryFn:()=>e.providers.catalog().catch(()=>({all:[],connected:[]}))}),Zt=y({queryKey:[`settings`,`providers`,`config`],queryFn:()=>e.providers.config().catch(()=>({default:``,providers:{}}))}),Qt=y({queryKey:[`settings`,`providers`,`auth`],queryFn:()=>e.providers.authStatus().catch(()=>({providers:{}})),refetchInterval:15e3}),$t=y({queryKey:[`settings`,`system`,`health`],queryFn:()=>t(`/api/system/health`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),en=o(()=>fa({providerCatalog:Xt.data,providerConfig:Zt.data,defaultProvider:String(Zt.data?.default||``).trim(),defaultModel:String(Zt.data?.providers?.[String(Zt.data?.default||``).trim()]?.default_model||Zt.data?.providers?.[String(Zt.data?.default||``).trim()]?.defaultModel||``).trim(),includeUnconfiguredProviders:!0}),[Xt.data,Zt.data]),tn=o(()=>{let e=Qt.data?.providers;return e&&typeof e==`object`?e:Qt.data&&typeof Qt.data==`object`?Qt.data:{}},[Qt.data]),nn=$t.data?.localEngine===!0,rn=Jt.data?.hosted_managed===!0,an=o(()=>{let e=String(Zt.data?.default||``).trim();return{provider:e,model:String(Zt.data?.providers?.[e]?.default_model||Zt.data?.providers?.[e]?.defaultModel||``).trim()}},[Zt.data]),on=o(()=>Zt.data?.providers||{},[Zt.data?.providers]),sn=o(()=>Object.entries(on).filter(([e])=>{let t=e.trim().toLowerCase();return t&&!Zv.has(t)&&!ey(t)}).map(([e,t])=>({id:e,url:String(t?.url||``).trim(),model:String(t?.default_model||t?.defaultModel||``).trim(),isDefault:String(Zt.data?.default||``).trim().toLowerCase()===e.trim().toLowerCase()})),[on,Zt.data?.default]),cn=y({queryKey:[`settings`,`search`,`config`],queryFn:()=>t(`/api/system/search-settings`,{method:`GET`}).catch(()=>null)}),ln=y({queryKey:[`settings`,`scheduler`,`config`],queryFn:()=>t(`/api/system/scheduler-settings`,{method:`GET`}).catch(()=>null)});m(()=>{let e=cn.data?.settings||null;e&&(V(String(e.backend||`auto`).trim()||`auto`),te(String(e.tandem_url||``).trim()),ne(String(e.searxng_url||``).trim()),ie(String(e.timeout_ms||1e4)))},[cn.data]),m(()=>{let e=ln.data?.settings||null;e&&(W(String(e.mode||`multi`).trim()||`multi`),K(e.max_concurrent_runs==null?``:String(e.max_concurrent_runs)))},[ln.data]);let un=y({queryKey:[`settings`,`browser`,`status`],queryFn:()=>t(`/api/engine/browser/status`,{method:`GET`}).catch(()=>null),refetchInterval:3e4}),[dn,fn]=r(null),pn=x({mutationFn:()=>t(`/api/engine/browser/install`,{method:`POST`}),onSuccess:async()=>{n(`ok`,`Browser sidecar installed on the engine host.`),await un.refetch()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),mn=x({mutationFn:()=>t(`/api/engine/browser/smoke-test`,{method:`POST`,body:JSON.stringify({url:`https://example.com`})}),onSuccess:async e=>{fn(e),n(`ok`,`Browser smoke test passed.`),await un.refetch()},onError:e=>{fn(null),n(`err`,e instanceof Error?e.message:String(e))}}),hn=y({queryKey:[`settings`,`mcp`,`servers`],queryFn:()=>e.mcp.list().catch(()=>({})),refetchInterval:1e4}),gn=y({queryKey:[`settings`,`mcp`,`tools`],queryFn:()=>e.mcp.listTools().catch(()=>[]),refetchInterval:15e3}),_n=y({queryKey:[`settings`,`mcp`,`catalog`],queryFn:()=>t(`/api/engine/mcp/catalog`,{method:`GET`}).catch(()=>null),refetchInterval:6e4}),vn=y({queryKey:[`settings`,`bug-monitor`,`config`],queryFn:()=>t(`/api/engine/config/bug-monitor`,{method:`GET`}).catch(()=>({bug_monitor:{}}))}),yn=y({queryKey:[`settings`,`bug-monitor`,`status`],queryFn:()=>t(`/api/engine/bug-monitor/status`,{method:`GET`}).catch(()=>({status:{}})),refetchInterval:1e4}),bn=y({queryKey:[`settings`,`bug-monitor`,`drafts`],queryFn:()=>t(`/api/engine/bug-monitor/drafts?limit=10`,{method:`GET`}).catch(()=>({drafts:[]})),refetchInterval:15e3}),xn=y({queryKey:[`settings`,`bug-monitor`,`incidents`],queryFn:()=>t(`/api/engine/bug-monitor/incidents?limit=10`,{method:`GET`}).catch(()=>({incidents:[]})),refetchInterval:1e4}),Sn=y({queryKey:[`settings`,`bug-monitor`,`posts`],queryFn:()=>t(`/api/engine/bug-monitor/posts?limit=10`,{method:`GET`}).catch(()=>({posts:[]})),refetchInterval:15e3}),Cn=y({queryKey:[`settings`,`bug-monitor`,`workspace-browser`,Lt],enabled:Ft&&!!Lt,queryFn:()=>t(`/api/orchestrator/workspaces/list?dir=${encodeURIComponent(Lt)}`,{method:`GET`})}),wn=y({queryKey:[`settings`,`channels`,`config`],queryFn:()=>e.channels.config().catch(()=>({})),refetchInterval:15e3}),Tn=y({queryKey:[`settings`,`channels`,`status`],queryFn:()=>e.channels.status().catch(()=>({})),refetchInterval:6e3}),En=y({queryKey:[`settings`,`channels`,`scopes`],queryFn:async()=>{let e=await Promise.all($v.map(async e=>[e,wy(await t(`/api/engine/channels/${e}/scopes`,{method:`GET`}).catch(()=>({scopes:[]})))]));return Object.fromEntries(e)},refetchInterval:15e3}),Dn=y({queryKey:[`settings`,`channels`,`tool-preferences`,Re],queryFn:async()=>{let e=await Promise.all($v.map(async e=>{let n=String(Re[e]||``).trim();return[e,Cy(await t(`/api/engine/channels/${e}/tool-preferences${n?`?scope_id=${encodeURIComponent(n)}`:``}`,{method:`GET`}).catch(()=>xy()))]}));return Object.fromEntries(e)},refetchInterval:15e3}),On=x({mutationFn:async({providerId:t,modelId:n})=>e.providers.setDefaults(t,n),onSuccess:async()=>{n(`ok`,`Updated provider defaults.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),kn=()=>String(Zt.data?.providers?.[Qv]?.default_model||Zt.data?.providers?.[Qv]?.defaultModel||`gpt-5.4`).trim()||`gpt-5.4`,An=async()=>{await e.providers.setDefaults(Qv,kn())},jn=x({mutationFn:async({providerId:n,url:r,modelId:i,apiKey:a,makeDefault:o})=>{let s=n.trim().toLowerCase(),c=r.trim(),l=i.trim();if(!s)throw Error(`Custom provider ID is required.`);if(!c)throw Error(`Custom provider URL is required.`);await t(`/api/engine/config`,{method:`PATCH`,body:JSON.stringify({...o?{default_provider:s}:{},providers:{[s]:{url:c,...l?{default_model:l}:{}}}})}),a.trim()&&await e.providers.setApiKey(s,a.trim())},onSuccess:async()=>{n(`ok`,`Custom provider saved.`),je(``),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Mn=x({mutationFn:async()=>t(`/api/engine/config/bug-monitor`,{method:`PATCH`,body:JSON.stringify({bug_monitor:{enabled:mt,paused:J,workspace_root:String(_t||``).trim()||null,repo:String(yt||``).trim()||null,mcp_server:String(xt||``).trim()||null,provider_preference:String(Ct||`auto`).trim(),model_policy:Tt&&Dt?{default_model:{provider_id:Tt,model_id:Dt}}:null,auto_create_new_issues:kt,require_approval_for_new_issues:jt,auto_comment_on_matched_open_issues:Nt,label_mode:`reporter_only`}})}),onSuccess:async()=>{n(`ok`,`Bug Monitor settings saved.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})])},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Nn=x({mutationFn:async()=>t(`/api/engine/capabilities/bindings/refresh-builtins`,{method:`POST`}),onSuccess:async()=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]}),T.invalidateQueries({queryKey:[`settings`,`mcp`]})]),n(`ok`,`Capability bindings refreshed from built-ins.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Pn=x({mutationFn:async({draftId:e,decision:n})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/${n}`,{method:`POST`,body:JSON.stringify({reason:`${n}d from control panel settings`})}),onSuccess:async(e,t)=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`Bug Monitor draft ${t.decision===`approve`?`approved`:`denied`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Fn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/triage-run`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.deduped?`Bug Monitor triage run already exists: ${e?.run?.run_id||`unknown`}`:`Bug Monitor triage run created: ${e?.run?.run_id||`unknown`}`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),In=x({mutationFn:async({action:e})=>t(`/api/engine/bug-monitor/${e}`,{method:`POST`}),onSuccess:async(e,t)=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`Bug Monitor ${t.action===`pause`?`paused`:`resumed`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Ln=x({mutationFn:async({incidentId:e})=>t(`/api/engine/bug-monitor/incidents/${encodeURIComponent(e)}/replay`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.deduped?`Bug Monitor triage run already exists: ${e?.run?.run_id||`unknown`}`:`Bug Monitor replay queued triage: ${e?.run?.run_id||`unknown`}`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Rn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/publish`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,e?.action===`comment_issue`?`Bug Monitor commented on issue #${e?.draft?.issue_number||`unknown`}.`:`Bug Monitor published issue #${e?.draft?.issue_number||`unknown`}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),zn=x({mutationFn:async({draftId:e})=>t(`/api/engine/bug-monitor/drafts/${encodeURIComponent(e)}/recheck-match`,{method:`POST`}),onSuccess:async e=>{await Promise.all([T.invalidateQueries({queryKey:[`settings`,`bug-monitor`]})]),n(`ok`,`GitHub match result: ${String(e?.action||`rechecked`).replaceAll(`_`,` `)}.`)},onError:e=>{n(`err`,e instanceof Error?e.message:String(e?.detail||e?.error||e))}}),Bn=x({mutationFn:({providerId:t,apiKey:n})=>e.providers.setApiKey(t,n),onSuccess:async()=>{n(`ok`,`API key updated.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Vn=x({mutationFn:({providerId:t})=>e.providers.oauthAuthorize(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim(),o=String(e?.session_id||e?.sessionId||``).trim(),s=String(e?.authorization_url||e?.authorizationUrl||e?.url||``).trim();if(!i||!r||!o||!s){n(`err`,a||`OAuth authorize response was incomplete.`);return}Ce(e=>({...e,[r]:o})),window.open(s,`_blank`,`noopener,noreferrer`),n(`info`,r===Qv?`Browser sign-in opened for Codex. Finish the flow there, then return to Tandem.`:`Browser sign-in opened for ${r}.`),await T.invalidateQueries({queryKey:[`settings`,`providers`,`auth`]})},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Hn=x({mutationFn:({providerId:t})=>e.providers.oauthDisconnect(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase();Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t}),n(`ok`,r===Qv?`Codex account disconnected.`:`${r} disconnected.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Un=x({mutationFn:({providerId:t})=>e.providers.oauthUseLocalSession(t),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim();if(!i){n(`err`,a||`Unable to import the local Codex session. Make sure Codex CLI is signed in on this machine.`);return}Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t});let o=String(e?.email||``).trim();if(n(`ok`,r===Qv?o?`Local Codex session imported: ${o}`:`Local Codex session imported.`:`${r} local session imported.`),r===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex session imported, but Tandem could not switch the default provider.`)}await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Wn=x({mutationFn:({providerId:e,authJson:n})=>t(`/api/engine/provider/${encodeURIComponent(e)}/oauth/session/import`,{method:`POST`,body:JSON.stringify({auth_json:n})}),onSuccess:async(e,t)=>{let r=String(t.providerId||``).trim().toLowerCase(),i=e?.ok!==!1,a=String(e?.error||e?.message||``).trim();if(!i){n(`err`,a||`Unable to import the Codex auth.json file. Make sure it was copied from a signed-in Codex CLI session.`);return}Fe(``),Ce(e=>{if(!e[r])return e;let t={...e};return delete t[r],t});let o=String(e?.email||``).trim();if(n(`ok`,r===Qv?o?`Codex auth.json imported: ${o}`:`Codex auth.json imported.`:`${r} auth.json imported.`),r===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex auth.json imported, but Tandem could not switch the default provider.`)}await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),qn=h(async(e,t)=>{if(t)try{let r=await t.text();if(Wt(t.name||`auth.json`),Fe(r),!r.trim()){n(`warn`,`Selected auth.json file was empty.`);return}Wn.mutate({providerId:e,authJson:r})}catch(e){n(`err`,e instanceof Error?e.message:String(e))}finally{Ht.current&&(Ht.current.value=``)}},[Wn,n]);m(()=>{let t=Object.entries(Se).filter(([e,t])=>!!e&&!!t);if(!t.length)return;let r=!1,i=new Set,a=async()=>{let a=await Promise.all(t.map(async([t,n])=>{try{return{providerId:t,sessionId:n,payload:await e.providers.oauthStatus(t,n),error:null}}catch(e){return{providerId:t,sessionId:n,payload:null,error:e instanceof Error?e:Error(String(e))}}}));for(let e of a){if(r||i.has(e.providerId))continue;if(e.error){i.add(e.providerId),Ce(t=>{if(t[e.providerId]!==e.sessionId)return t;let n={...t};return delete n[e.providerId],n}),n(`err`,e.error.message);continue}let t=e.payload,a=String(t?.status||``).trim().toLowerCase();if(!(!a||a===`pending`)){if(i.add(e.providerId),Ce(t=>{if(t[e.providerId]!==e.sessionId)return t;let n={...t};return delete n[e.providerId],n}),a===`connected`){let r=String(t?.email||``).trim();if(n(`ok`,r?`Codex account connected: ${r}`:`Codex account connected.`),e.providerId===Qv)try{await An(),n(`ok`,`Codex is now the default provider for Tandem runs.`)}catch(e){n(`warn`,e instanceof Error?e.message:`Codex connected, but Tandem could not switch the default provider.`)}}else a===`expired`?n(`warn`,`Codex sign-in expired. Start the connection again.`):n(`err`,String(t?.error||t?.message||``).trim()||`Codex sign-in did not complete. Please try again.`);await Promise.all([T.invalidateQueries({queryKey:[`settings`,`providers`]}),S()])}}};a();let o=window.setInterval(()=>{a()},2e3);return()=>{r=!0,window.clearInterval(o)}},[e,Se,T,S,n]);let Jn=x({mutationFn:async e=>t(`/api/system/search-settings`,{method:`PATCH`,body:JSON.stringify(e)}),onSuccess:async e=>{oe(``),ce(``),await T.invalidateQueries({queryKey:[`settings`,`search`]}),n(`ok`,e?.restart_required?`Search settings saved. Restart tandem-engine to apply them.`:`Search settings saved.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Yn=x({mutationFn:async e=>t(`/api/system/scheduler-settings`,{method:`PATCH`,body:JSON.stringify(e)}),onSuccess:async e=>{await T.invalidateQueries({queryKey:[`settings`,`scheduler`]}),n(`ok`,e?.restart_required?`Scheduler settings saved. Restart tandem-engine to apply them.`:`Scheduler settings saved.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),Zn=x({mutationFn:async({query:e})=>t(`/api/system/search-settings/test`,{method:`POST`,body:JSON.stringify({query:e,limit:5})}),onSuccess:e=>{fe(e),n(`ok`,`Websearch test completed.`)},onError:e=>{fe(null),n(`err`,e instanceof Error?e.message:String(e))}}),Qn=x({mutationFn:async()=>{let e;try{e=JSON.parse(L)}catch(e){throw Error(e instanceof Error?`Config JSON is invalid: ${e.message}`:`Config JSON is invalid.`)}return t(`/api/control-panel/config`,{method:`PATCH`,body:JSON.stringify({config:e})})},onSuccess:async()=>{ee(``),n(`ok`,`Control panel config saved.`),await T.invalidateQueries({queryKey:[`settings`,`install`]}),await T.invalidateQueries({queryKey:[`system`,`capabilities`]})},onError:e=>{let t=e instanceof Error?e.message:String(e);ee(t),n(`err`,t)}}),$n=x({mutationFn:async()=>{let e=(qt.data?.identity?.bot||{})?.aliases||{},t=String(k||``).trim();if(!t)throw Error(`Bot name is required.`);let n=String(j||``).trim(),r=String(N||``).trim();return Kt({identity:{bot:{canonical_name:t,avatar_url:n||null,aliases:{...e,control_panel:r||void 0}}}})},onSuccess:async()=>{n(`ok`,`Identity updated.`),await Promise.all([T.invalidateQueries({queryKey:[`settings`,`identity`]}),C()])},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),nr=h(async()=>Promise.all([T.invalidateQueries({queryKey:[`settings`,`channels`]}),T.invalidateQueries({queryKey:[`settings`,`channels`,`scopes`]}),T.invalidateQueries({queryKey:[`settings`,`channels`,`tool-preferences`]})]),[T]),rr=x({mutationFn:async({channel:e,scopeId:n,payload:r})=>{let i=String(n||``).trim()?`?scope_id=${encodeURIComponent(String(n||``).trim())}`:``;return`reset`in r?t(`/api/engine/channels/${e}/tool-preferences${i}`,{method:`PUT`,body:JSON.stringify({reset:!0})}):t(`/api/engine/channels/${e}/tool-preferences${i}`,{method:`PUT`,body:JSON.stringify(r)})},onSuccess:async(e,t)=>{await T.invalidateQueries({queryKey:[`settings`,`channels`,`tool-preferences`]}),await T.invalidateQueries({queryKey:[`settings`,`channels`,`scopes`]});let r=String(t.scopeId||``).trim();n(`ok`,r?`Saved ${t.channel} scope ${r}.`:`Saved ${t.channel} channel tool scope.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),ir=x({mutationFn:async t=>{let n=q[t];if(!n)throw Error(`No draft found for ${t}.`);let r=String(n.modelProviderId||``).trim(),i=String(n.modelId||``).trim(),a={allowed_users:Ny(n.allowedUsers),mention_only:!!n.mentionOnly,security_profile:String(n.securityProfile||`operator`).trim()||`operator`,model_provider_id:r||null,model_id:i||null},o=String(n.botToken||``).trim();if(o&&(a.bot_token=o),t===`telegram`&&(a.style_profile=String(n.styleProfile||`default`).trim()||`default`),t===`discord`&&(a.guild_id=String(n.guildId||``).trim()),t===`slack`){let e=String(n.channelId||``).trim();if(!e&&!wn.data?.slack?.channel_id)throw Error(`Slack channel ID is required.`);e&&(a.channel_id=e)}return e.channels.put(t,a)},onSuccess:async(e,t)=>{n(`ok`,`Saved ${t} channel settings.`),Ue(e=>({...e,[t]:null})),Ie(e=>({...e,[t]:{...e[t],botToken:``}})),await nr()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),ar=x({mutationFn:async t=>e.channels.delete(t),onSuccess:async(e,t)=>{n(`ok`,`Removed ${t} channel settings.`),Ue(e=>({...e,[t]:null})),ze(e=>({...e,[t]:``})),Le.current[t]=!1,Ie(e=>({...e,[t]:by(t,null)})),await nr()},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),or=x({mutationFn:async t=>{let n=q[t],r=String(n?.botToken||``).trim(),i={};return r&&(i.bot_token=r),e.channels.verify(t,i)},onSuccess:(e,t)=>{Ue(n=>({...n,[t]:e})),n(`ok`,`${t} verification complete.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),cr=h(async()=>T.invalidateQueries({queryKey:[`settings`,`mcp`]}),[T]),ur=x({mutationFn:async({serverName:t,allowedTools:n})=>e.mcp.patch(t,{allowed_tools:n??void 0,clear_allowed_tools:n===null}),onSuccess:async()=>{await cr(),n(`ok`,`MCP tool access updated.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),dr=x({mutationFn:async({action:n,server:r})=>{if(!r)throw Error(`No MCP server selected.`);if(n===`connect`)return e.mcp.connect(r.name);if(n===`disconnect`)return e.mcp.disconnect(r.name);if(n===`refresh`)return e.mcp.refresh(r.name);if(n===`authenticate`)return t(`/api/engine/mcp/${encodeURIComponent(r.name)}/auth/authenticate`,{method:`POST`});if(n===`toggle-enabled`)return e.mcp.setEnabled(r.name,!r.enabled);if(n===`delete`)return t(`/api/engine/mcp/${encodeURIComponent(r.name)}`,{method:`DELETE`});throw Error(`Unknown action: ${n}`)},onSuccess:async(e,t)=>{await cr();let r=!!e?.pendingAuth||!!e?.lastAuthChallenge||!!e?.authorizationUrl,i=e?.ok!==!1,a=String(t.server?.authKind||``).trim().toLowerCase();if(t.action===`connect`)if(r||!i&&a===`oauth`){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization required for ${t.server?.name}: ${i}`:`OAuth authorization required for ${t.server?.name}.`)}else if(i)n(`ok`,`Connected ${t.server?.name}.`);else{let r=String(e?.error?.message||e?.error||``).trim();n(`err`,r?`Failed to connect ${t.server?.name}: ${r}`:`Failed to connect ${t.server?.name}.`)}if(t.action===`disconnect`&&n(`ok`,`Disconnected ${t.server?.name}.`),t.action===`refresh`)if(r||!i&&a===`oauth`){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization required for ${t.server?.name}: ${i}`:`OAuth authorization required for ${t.server?.name}.`)}else if(i)n(`ok`,`Refreshed ${t.server?.name}.`);else{let r=String(e?.error?.message||e?.error||``).trim();n(`err`,r?`Failed to refresh ${t.server?.name}: ${r}`:`Failed to refresh ${t.server?.name}.`)}if(t.action===`authenticate`){let i=e?.ok!==!1,a=String(e?.error?.message||e?.error||``).trim();if(!i&&!r)n(`err`,a?`OAuth authorization check failed for ${t.server?.name}: ${a}`:`OAuth authorization check failed for ${t.server?.name}.`);else if(r){let r=e?.lastAuthChallenge||{},i=String(r?.message||``).trim();n(`warn`,i?`OAuth authorization still pending for ${t.server?.name}: ${i}`:`OAuth authorization still pending for ${t.server?.name}.`)}else n(`ok`,`Marked ${t.server?.name} as signed in.`)}t.action===`toggle-enabled`&&n(`ok`,`${t.server?.enabled?`Disabled`:`Enabled`} ${t.server?.name}.`),t.action===`delete`&&n(`ok`,`Deleted ${t.server?.name}.`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),fr=x({mutationFn:async()=>{let n=String(Je||``).trim(),r=oy(n),i=ay(Ke||r);if(!n)throw Error(`Transport URL is required.`);if(!iy(n)&&!n.startsWith(`stdio:`))throw Error(`Transport must be a valid URL or stdio:* transport.`);let a=fy(py({authMode:Xe,token:Qe,customHeader:et,transport:n}),it),o=String(nt||``).trim();cy(n)&&o&&(a[`X-MCP-Toolsets`]=o);let s={name:i,transport:n,enabled:!0,auth_kind:Xe===`oauth`?`oauth`:``};Object.keys(a).length&&(s.headers=a);let c=String(ct||``).trim();if(c&&c!==i&&await t(`/api/engine/mcp/${encodeURIComponent(c)}`,{method:`DELETE`}).catch(()=>null),await e.mcp.add(s),ot){let t=await e.mcp.connect(s.name),n=t?.pendingAuth===!0||!!t?.lastAuthChallenge||!!t?.authorizationUrl;if(!t?.ok&&!n&&Xe!==`oauth`)throw Error(`Added "${s.name}" but connect failed.`);return{name:s.name,connectResult:t,connectAfterAdd:!0,authKind:Xe===`oauth`?`oauth`:``}}return{name:s.name,connectAfterAdd:!1,authKind:Xe===`oauth`?`oauth`:``}},onSuccess:async e=>{await cr(),Ge(!1),qe(``),Ye(``),Ze(`none`),$e(``),tt(``),rt(``),at([]),st(!0),lt(``);let t=String(e?.name||``).trim(),r=e?.connectResult,i=String(e?.authKind||``).trim().toLowerCase(),a=!!r?.pendingAuth||!!r?.lastAuthChallenge||!!r?.authorizationUrl;if(e?.connectAfterAdd&&a){let e=r?.lastAuthChallenge||{},i=String(e?.message||``).trim();n(`warn`,i?`Saved MCP "${t}" and OAuth authorization is still required: ${i}`:`Saved MCP "${t}" and OAuth authorization is still required.`)}else e?.connectAfterAdd?i===`oauth`&&r&&r.ok!==!0?n(`warn`,`Saved MCP "${t}" as OAuth-backed. If it still needs authorization, open the auth link from the server row and refresh after signing in.`):n(`ok`,`Saved MCP "${t}" and connected it.`):n(`ok`,`Saved MCP "${t}".`)},onError:e=>n(`err`,e instanceof Error?e.message:String(e))}),pr=e=>{if(!e)return;if(e.size>10*1024*1024){n(`err`,`Avatar image is too large (max 10 MB).`);return}let t=new FileReader;t.onload=()=>{let e=typeof t.result==`string`?t.result:``;if(!e){n(`err`,`Failed to read avatar image.`);return}M(e)},t.onerror=()=>n(`err`,`Failed to read avatar image.`),t.readAsDataURL(e)},mr=Array.isArray(Xt.data?.all)?Xt.data.all:[];m(()=>{let e=sn.find(e=>e.isDefault)||sn[0];e&&(Te(t=>t.trim()&&t.trim().toLowerCase()!==`custom`?t:e.id),De(t=>t.trim()?t:e.url),ke(t=>t.trim()?t:e.model),Ne(String(Zt.data?.default||``).trim().toLowerCase()===e.id.trim().toLowerCase()))},[sn,Zt.data?.default]);let hr=o(()=>_y(hn.data),[hn.data]),gr=o(()=>vy(gn.data),[gn.data]),_r=o(()=>yy(_n.data?.catalog||_n.data||null),[_n.data]),vr=o(()=>new Set(hr.map(e=>e.name.toLowerCase())),[hr]);m(()=>{let e=hr.filter(e=>{let t=String(e.authKind||``).trim().toLowerCase(),n=String(e.lastAuthChallenge?.authorization_url||e.lastAuthChallenge?.authorizationUrl||e.authorizationUrl||``).trim();return t===`oauth`&&(!!e.lastAuthChallenge||!!n)});if(!e.length)return;let n=!1,r=!1,i=async()=>{if(!(n||r)){r=!0;try{let r=await Promise.all(e.map(async e=>{try{return{payload:await t(`/api/engine/mcp/${encodeURIComponent(e.name)}/auth/authenticate`,{method:`POST`}),error:null}}catch(e){return{payload:null,error:e instanceof Error?e:Error(String(e))}}}));if(n)return;r.some(({payload:e,error:t})=>t?!1:!(e?.pendingAuth===!0||e?.lastAuthChallenge||e?.authorizationUrl))&&await T.invalidateQueries({queryKey:[`settings`,`mcp`]})}finally{r=!1}}};i();let a=window.setInterval(()=>{i()},3e3);return()=>{n=!0,window.clearInterval(a)}},[t,hr,T]);let yr=o(()=>{let e=String(ft||``).trim().toLowerCase();return _r.servers.filter(t=>e?t.name.toLowerCase().includes(e)||t.slug.toLowerCase().includes(e)||t.transportUrl.toLowerCase().includes(e):!0).slice(0,36)},[_r.servers,ft]),xr=hr.filter(e=>e.connected).length,Sr=o(()=>yn.data?.status||{},[yn.data]),Cr=o(()=>Array.isArray(bn.data?.drafts)&&bn.data.drafts||[],[bn.data]),wr=o(()=>Array.isArray(xn.data?.incidents)&&xn.data.incidents||[],[xn.data]),Tr=o(()=>Array.isArray(Sn.data?.posts)&&Sn.data.posts||[],[Sn.data]),Er=o(()=>hr.find(e=>e.name.toLowerCase()===String(xt||``).trim().toLowerCase())||null,[xt,hr]),Dr=o(()=>mr.find(e=>String(e?.id||``).toLowerCase()===String(Tt||``).trim().toLowerCase())||null,[Tt,mr]),Or=o(()=>{let e=Dr&&typeof Dr==`object`&&Dr.models||{};return Object.keys(e).sort((e,t)=>e.localeCompare(t))},[Dr]),kr=Array.isArray(un.data?.blocking_issues)&&un.data?.blocking_issues||[],Ar=Array.isArray(un.data?.recommendations)&&un.data?.recommendations||[],jr=Array.isArray(un.data?.install_hints)&&un.data?.install_hints||[],Pr=$v.filter(e=>!!Tn.data?.[e]?.connected).length,Fr=Array.isArray(Cn.data?.directories)?Cn.data.directories:[],Ir=String(zt||``).trim().toLowerCase(),Lr=o(()=>Ir?Fr.filter(e=>String(e?.name||e?.path||``).trim().toLowerCase().includes(Ir)):Fr,[Fr,Ir]),Rr=String(Cn.data?.parent||``).trim(),zr=String(Cn.data?.dir||Lt||``).trim();m(()=>{let e=vn.data?.bug_monitor&&typeof vn.data?.bug_monitor==`object`?vn.data.bug_monitor:{};ht(!!e.enabled),gt(!!e.paused),vt(String(e.workspace_root||``).trim()),bt(String(e.repo||``).trim()),St(String(e.mcp_server||``).trim()),wt(String(e.provider_preference||`auto`).trim()||`auto`),Et(String(e.model_policy?.default_model?.provider_id||``).trim()),Ot(String(e.model_policy?.default_model?.model_id||``).trim()),At(e.auto_create_new_issues!==!1),Mt(!!e.require_approval_for_new_issues),Pt(e.auto_comment_on_matched_open_issues!==!1)},[vn.data]),m(()=>{let e=wn.data&&typeof wn.data==`object`?wn.data:{};!wn.data||typeof wn.data!=`object`||Ie(t=>{let n={...t};for(let t of $v)n[t]||(n[t]=by(t,e[t]),Le.current[t]=!0);return n})},[wn.data]);let Br=(e,t)=>{let n=String(t||``).trim();n&&On.mutate({providerId:e,modelId:n})},Vr=e=>{if(e){dt(`manual`);let t=e.headers&&typeof e.headers==`object`?e.headers:{},n=Object.keys(t),r=n.find(e=>String(e).toLowerCase()===`authorization`),i=n.find(e=>String(e).toLowerCase()===`x-api-key`),a=n.find(e=>String(e).toLowerCase()===`x-mcp-toolsets`),o=String(e.lastAuthChallenge?.authorization_url||e.lastAuthChallenge?.authorizationUrl||e.authorizationUrl||``).trim(),s=n.filter(e=>![r,i,a].filter(Boolean).map(e=>String(e).toLowerCase()).includes(String(e).toLowerCase())),c=String(e.authKind||``).trim().toLowerCase()||gy(_r,e.name,e.transport),l=o||c===`oauth`?`oauth`:`none`,u=``,d=``;o?d=``:i?(l=`x-api-key`,d=String(t[i]||``).trim()):r?(l=`bearer`,d=String(t[r]||``).replace(/^bearer\s+/i,``).trim()):s.length===1&&(l=`custom`,u=s[0],d=String(t[s[0]]||``).trim()),lt(e.name),qe(e.name),Ye(e.transport||``),st(e.connected||!1),rt(a?String(t[a]||``).trim():cy(e.transport||``)?`default`:``),Ze(l),tt(u),$e(d);let f=new Set([r,i,a,l===`custom`?u:``].filter(Boolean).map(e=>String(e).toLowerCase()));at(n.filter(e=>!f.has(String(e).toLowerCase())).map(e=>({key:e,value:String(t[e]||``).trim()})))}else dt(`catalog`),lt(``),qe(``),Ye(``),Ze(`none`),tt(``),$e(``),rt(``),at([]),st(!0);Ge(!0)},Hr=async()=>{let e=await t(`/api/engine/bug-monitor/debug`,{method:`GET`});await navigator.clipboard.writeText(JSON.stringify(e,null,2)),n(`ok`,`Bug Monitor debug payload copied.`)},Ur=[{id:`install`,label:`Install`,icon:`clipboard-list`},{id:`navigation`,label:`Navigation`,icon:`panel-left`},{id:`providers`,label:`Providers`,icon:`cpu`},{id:`search`,label:`Web Search`,icon:`globe`},{id:`scheduler`,label:`Scheduler`,icon:`layers`},{id:`identity`,label:`Identity`,icon:`badge-check`},{id:`theme`,label:`Themes`,icon:`paint-bucket`},{id:`channels`,label:`Channels`,icon:`message-circle`},{id:`mcp`,label:`MCP`,icon:`plug-zap`},{id:`bug_monitor`,label:`Bug Monitor`,icon:`bug-play`},{id:`browser`,label:`Browser`,icon:`monitor-cog`}],Wr=o(()=>my(Xe,Qe,et,Je),[Xe,et,Qe,Je]),Gr=o(()=>uy(Ke,Je),[Ke,Je]),Kr=Xe===`oauth`&&ot,qr=o(()=>cy(Je),[Je]),Jr=w?.routeVisibility||{},Yr=Uv(!!w?.acaMode),Xr=lr.map(([e,t,n])=>{let r=e;return{routeId:e,label:t,icon:n,enabled:Jr[r]!==!1,pinned:!!w?.acaMode&&Hv.has(r),defaultVisible:Yr[r]!==!1,description:By[e]||`Open the ${String(t||e).toLowerCase()} section.`}}),Zr=Xr.filter(e=>e.enabled).length,Qr=Xr.filter(e=>e.defaultVisible),$r=Xr.filter(e=>!e.defaultVisible),ei=$r.filter(e=>!e.enabled).length;return m(()=>{let e=E.current;e?Mr(e):Mr()},[F,mt,J,_t,xt,Sr.readiness?.runtime_ready,Sr.runtime?.monitoring_active,Sr.runtime?.paused,Sr.runtime?.pending_incidents,Sr.pending_drafts,Cr.length,wr.length,Nn.isPending,In.isPending,Pn.isPending,Ln.isPending,Fn.isPending,Mn.isPending,dr.isPending,Jn.isPending]),a(Gn,{className:`grid gap-4`,children:a(`div`,{ref:E,className:`grid gap-4`,children:[a(`div`,{className:`tcp-settings-tabs`,children:Ur.map(e=>a(`button`,{type:`button`,className:`tcp-settings-tab tcp-settings-tab-underline ${F===e.id?`active`:``}`,onClick:()=>I(e.id),children:[a(`i`,{"data-lucide":e.icon}),e.label]},e.id))}),a(er,{main:a(Kn,{className:`grid gap-4`,children:[F===`navigation`?a(X,{title:`Sidebar navigation`,subtitle:w?.acaMode?`ACA mode keeps Dashboard, Chat, Coding, and Settings visible by default.`:`Choose which sections appear in the sidebar. Advanced and experimental surfaces stay hidden until you turn them on.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:w?.acaMode?`ok`:`info`,children:w?.acaMode?`ACA compact default`:`Core-first default`}),a(Y,{tone:`ghost`,children:[Zr,`/`,Xr.length,` visible`]}),a(`button`,{className:`tcp-btn`,type:`button`,onClick:()=>w?.showAllSections(),children:`Show all sections`}),a(`button`,{className:`tcp-btn-primary`,type:`button`,onClick:()=>w?.resetNavigation(),children:[`Reset `,w?.acaMode?`ACA compact`:`default`]})]}),children:a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Default sections`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`These sections are part of the standard control panel and start on by default.`})]}),a(Y,{tone:`ok`,children:[Qr.filter(e=>e.enabled).length,`/`,Qr.length,` shown`]})]}),a(`div`,{className:`mt-3 grid gap-2`,children:Qr.map(e=>a(`button`,{type:`button`,className:`flex items-center justify-between rounded-xl border px-3 py-3 text-left transition ${e.enabled?`border-lime-500/40 bg-lime-500/10 hover:border-lime-400/70`:`border-slate-700/60 bg-slate-900/20 hover:border-slate-500/70`}`,onClick:()=>w?.setRouteVisibility(e.routeId,!e.enabled),children:[a(`div`,{className:`flex min-w-0 items-center gap-3`,children:[a(`span`,{className:`flex h-9 w-9 items-center justify-center rounded-lg border ${e.enabled?`border-lime-500/30 bg-lime-500/10 text-lime-200`:`border-slate-700/70 bg-slate-950/30 text-slate-300`}`,children:a(`i`,{"data-lucide":e.icon})}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.label}),a(`div`,{className:`tcp-subtle truncate text-xs`,children:e.description})]})]}),a(`div`,{className:`flex items-center gap-2`,children:[e.pinned?a(Y,{tone:`ok`,children:`Pinned`}):null,a(Y,{tone:e.enabled?`ok`:`ghost`,children:e.enabled?`Shown`:`Hidden`})]})]},e.routeId))})]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Advanced / experimental sections`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Only routes that ship hidden by default live here.`})]}),a(Y,{tone:ei>0?`warn`:`ok`,children:[ei,` hidden`]})]}),a(`div`,{className:`mt-3 grid gap-2`,children:$r.map(e=>a(`button`,{type:`button`,className:`flex items-center justify-between rounded-xl border px-3 py-3 text-left transition ${e.enabled?`border-lime-500/40 bg-lime-500/10 hover:border-lime-400/70`:`border-slate-700/60 bg-slate-900/20 hover:border-slate-500/70`}`,onClick:()=>w?.setRouteVisibility(e.routeId,!e.enabled),children:[a(`div`,{className:`flex min-w-0 items-center gap-3`,children:[a(`span`,{className:`flex h-9 w-9 items-center justify-center rounded-lg border ${e.enabled?`border-lime-500/30 bg-lime-500/10 text-lime-200`:`border-slate-700/70 bg-slate-950/30 text-slate-300`}`,children:a(`i`,{"data-lucide":e.icon})}),a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.label}),a(`div`,{className:`tcp-subtle truncate text-xs`,children:e.description})]})]}),a(Y,{tone:e.enabled?`ok`:`ghost`,children:e.enabled?`Shown`:`Hidden`})]},e.routeId))})]}),a(`div`,{className:`tcp-subtle text-xs`,children:`These preferences are stored in this browser only.`})]})}):null,F===`install`?a(X,{title:`Install config`,subtitle:`Durable non-secret install preferences stored in tandem-data for Tandem startup and navigation defaults.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:String(Jt.data?.control_panel_mode||``).trim().toLowerCase()===`aca`?`ok`:`info`,children:Jt.data?.control_panel_mode||`auto`}),a(Y,{tone:Jt.data?.control_panel_config_ready?`ok`:`warn`,children:Jt.data?.control_panel_config_ready?`Ready`:`Needs setup`}),a(`button`,{type:`button`,className:`tcp-btn`,onClick:()=>Yt.refetch().then(()=>n(`ok`,`Install config refreshed.`)),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh`]}),a(`button`,{type:`button`,className:`tcp-btn-primary`,onClick:()=>Qn.mutate(),disabled:Qn.isPending,children:[a(`i`,{"data-lucide":`save`}),`Save config`]})]}),children:a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Startup profile`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:Jt.data?.control_panel_mode_reason||`The control panel auto-detects its startup mode and can be overridden with TANDEM_CONTROL_PANEL_MODE.`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Mode source`}),a(`span`,{children:Jt.data?.control_panel_mode_source||`detected`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Integration detected`}),a(`span`,{children:Jt.data?.aca_integration?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Compact nav`}),a(`span`,{children:Jt.data?.control_panel_compact_nav?`on`:`off`})]})]})]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Hosted management`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Detect whether this panel is running on a Tandem-managed hosted deployment so hosted-only update and notification UX can stay gated.`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Managed hosted server`}),a(`span`,{children:Jt.data?.hosted_managed?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Provider`}),a(`span`,{children:Jt.data?.hosted_provider||`—`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Deployment slug`}),a(`span`,{children:Jt.data?.hosted_deployment_slug||`—`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Release`}),a(`span`,{children:[Jt.data?.hosted_release_version||`—`,Jt.data?.hosted_release_channel?` · ${Jt.data.hosted_release_channel}`:``]})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Update policy`}),a(`span`,{children:Jt.data?.hosted_update_policy||`—`})]})]}),Jt.data?.hosted_managed?a(`div`,{className:`mt-3 rounded-xl border border-lime-500/20 bg-lime-500/10 px-3 py-2 text-xs text-lime-200`,children:`Hosted-managed features can safely key off this signal instead of guessing from hostname or environment.`}):null]}),a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`font-medium`,children:`Config file`}),a(`div`,{className:`tcp-subtle mt-1 break-all text-xs`,children:Jt.data?.control_panel_config_path||Yt.data?.path||`control-panel-config.json`}),a(`div`,{className:`mt-3 grid gap-2 text-xs`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Ready`}),a(`span`,{children:Jt.data?.control_panel_config_ready?`yes`:`no`})]}),a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`span`,{className:`tcp-subtle`,children:`Missing`}),a(`span`,{children:Array.isArray(Jt.data?.control_panel_config_missing)?Jt.data?.control_panel_config_missing.join(`, `)||`none`:`unknown`})]})]})]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-sm font-medium`,children:`Control panel config JSON`}),a(`textarea`,{className:`tcp-input min-h-[28rem] font-mono text-xs leading-5`,value:L,onInput:e=>R(e.target.value),spellCheck:!1})]}),z?a(`div`,{className:`rounded-xl border border-rose-500/30 bg-rose-500/10 px-3 py-2 text-sm text-rose-200`,children:z}):null,a(`div`,{className:`tcp-subtle text-xs`,children:"This file holds non-secret install state: repo binding, provider defaults, task source, swarm policy, GitHub MCP preferences, and navigation defaults. Secrets should stay in `.env` or token files."})]})}):null,F===`providers`?a(X,{title:`Provider defaults`,subtitle:`Provider catalog, model selection, and API key entry.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:String(Zt.data?.default||``).trim()?`ok`:`warn`,children:[`Default: `,String(Zt.data?.default||`none`)]}),a(Y,{tone:`info`,children:[String(Xt.data?.connected?.length||0),` connected`]}),a(`button`,{className:`tcp-btn`,onClick:()=>S().then(()=>n(`ok`,`Provider status refreshed.`)),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh provider`]})]}),children:a(`div`,{className:`grid gap-3`,children:[a(`button`,{type:`button`,className:`tcp-list-item text-left`,onClick:()=>ye(e=>!e),"aria-expanded":ve,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium inline-flex items-center gap-2`,children:[a(`i`,{"data-lucide":ve?`chevron-down`:`chevron-right`}),a(`span`,{children:ve?`Hide provider catalog`:`Show provider catalog`})]}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:[mr.length,` providers available for configuration. Expand to change models and API keys.`]})]}),a(Y,{tone:`info`,children:[String(Xt.data?.connected?.length||0),` connected`]})]})}),a(l,{initial:!1,children:ve?a(s.div,{className:`grid gap-3`,initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},children:[a(`div`,{className:`tcp-list-item grid gap-3`,children:[a(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Custom OpenAI-compatible provider`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Add providers like MiniMax by ID, base URL, default model, and API key.`})]}),a(Y,{tone:sn.length?`ok`:`info`,children:[sn.length,` configured`]})]}),a(`button`,{type:`button`,className:`tcp-list-item text-left`,onClick:()=>xe(e=>!e),"aria-expanded":be,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium inline-flex items-center gap-2`,children:[a(`i`,{"data-lucide":be?`chevron-down`:`chevron-right`}),a(`span`,{children:be?`Hide custom provider form`:`Show custom provider form`})]}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:`Use this for OpenAI-compatible endpoints. Anthropic is handled by the built-in provider row below.`})]}),a(Y,{tone:`info`,children:`OpenAI-compatible only`})]})}),a(l,{initial:!1,children:be?a(s.div,{className:`grid gap-3`,initial:{opacity:0,y:-8},animate:{opacity:1,y:0},exit:{opacity:0,y:-8},children:a(`form`,{className:`grid gap-3`,onSubmit:e=>{e.preventDefault(),jn.mutate({providerId:we,url:Ee,modelId:Oe,apiKey:Ae,makeDefault:Me})},children:[a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Provider ID`}),a(`input`,{className:`tcp-input`,value:we,onInput:e=>Te(e.target.value),placeholder:`custom`})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Default model`}),a(`input`,{className:`tcp-input`,value:Oe,onInput:e=>ke(e.target.value),placeholder:`MiniMax-M2`})]})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`Base URL`}),a(`input`,{className:`tcp-input`,value:Ee,onInput:e=>De(e.target.value),placeholder:`https://api.minimax.io/v1`})]}),a(`div`,{className:`grid gap-2`,children:[a(`label`,{className:`text-sm font-medium`,children:`API key`}),a(`input`,{className:`tcp-input`,type:`password`,value:Ae,onInput:e=>je(e.target.value),placeholder:`Optional. Leave blank to keep the existing key.`})]}),a(`label`,{className:`inline-flex items-center gap-2 text-sm text-slate-200`,children:[a(`input`,{type:`checkbox`,className:`accent-slate-400`,checked:Me,onChange:e=>Ne(e.target.checked)}),`Make this the default provider`]}),a(`div`,{className:`flex flex-wrap justify-end gap-2`,children:a(`button`,{className:`tcp-btn-primary`,type:`submit`,disabled:jn.isPending,children:[a(`i`,{"data-lucide":`plus`}),`Save custom provider`]})})]})}):null}),sn.length?a(`div`,{className:`grid gap-2`,children:sn.map(e=>a(`div`,{className:`flex flex-wrap items-start justify-between gap-2 rounded-xl border border-slate-700/60 bg-slate-900/20 px-3 py-2`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:e.id}),a(`div`,{className:`tcp-subtle break-all text-xs`,children:e.url||`No URL configured`}),a(`div`,{className:`tcp-subtle text-xs`,children:[`Model: `,e.model||`not set`]})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[e.isDefault?a(Y,{tone:`ok`,children:`default`}):null,a(`button`,{type:`button`,className:`tcp-btn h-8 px-3 text-xs`,onClick:()=>{Te(e.id),De(e.url),ke(e.model),Ne(e.isDefault),xe(!0),ye(!0)},children:[a(`i`,{"data-lucide":`square-pen`}),`Edit`]})]})]},e.id))}):null]}),mr.length?mr.map(e=>{let t=String(e?.id||``),n=Object.keys(e?.models||{}),r=String(Zt.data?.providers?.[t]?.default_model||n[0]||``),i=String(D[t]??r).trim(),o=i.toLowerCase(),c=n.filter(e=>o?e.toLowerCase().includes(o):!0).slice(0,80),l=Ry(e,n.length),u=zy(e,r),d=sr[t]||null,f=String(d?.keyUrl||``).trim(),p=tn[t]||{},m=String(Zt.data?.default||``).trim().toLowerCase(),h=t===Qv&&m===Qv,g=String(p?.auth_kind||p?.authKind||``).trim().toLowerCase(),_=String(p?.status||``).trim().toLowerCase(),v=String(p?.email||``).trim(),y=String(p?.display_name||p?.displayName||``).trim(),b=String(p?.managed_by||p?.managedBy||``).trim(),x=Number(p?.expires_at_ms||p?.expiresAtMs||0),S=p?.local_session_available===!0||p?.localSessionAvailable===!0,C=!!String(Se[t]||``).trim()||Vn.isPending&&String(Vn.variables?.providerId||``).trim().toLowerCase()===t,w=g===`oauth`&&p?.connected===!0&&_!==`reauth_required`,T=t===Qv,E=!T||nn||rn,k=C?{tone:`info`,text:`sign-in pending`}:w?{tone:`ok`,text:`account connected`}:_===`reauth_required`?{tone:`warn`,text:`reauth required`}:{tone:`warn`,text:`not connected`},A=rn&&t===Qv;return a(s.details,{layout:!0,className:`tcp-list-item`,children:[a(`summary`,{className:`cursor-pointer list-none`,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:t}),a(`div`,{className:`tcp-subtle text-xs`,children:u})]}),a(Y,{tone:l.tone,children:l.text})]})}),a(`div`,{className:`mt-3 grid gap-3`,children:[f&&!T?a(`div`,{className:`flex justify-end`,children:a(`a`,{className:`tcp-btn h-8 px-3 text-xs`,href:f,target:`_blank`,rel:`noreferrer`,children:[a(`i`,{"data-lucide":`external-link`}),`Get API key`]})}):null,a(`form`,{className:`grid gap-2`,onSubmit:e=>{e.preventDefault(),Br(t,i)},children:[a(`div`,{className:`flex gap-2`,children:[a(`input`,{className:`tcp-input`,value:i,placeholder:`Type model id for ${t}`,onInput:e=>O(n=>({...n,[t]:e.target.value}))}),a(`button`,{className:`tcp-btn`,type:`submit`,children:[a(`i`,{"data-lucide":`badge-check`}),`Apply`]})]}),a(`div`,{className:`max-h-48 overflow-auto rounded-xl border border-slate-700/60 bg-slate-900/20 p-1`,children:c.length?c.map(e=>a(`button`,{type:`button`,className:`block w-full rounded-lg px-2 py-1.5 text-left text-sm hover:bg-slate-700/30 ${e===r?`bg-slate-700/40`:``}`,onClick:()=>{O(n=>({...n,[t]:e})),Br(t,e)},children:e},e)):a(`div`,{className:`tcp-subtle px-2 py-1 text-xs`,children:n.length?`No matching models.`:`No live catalog available. Type a model ID manually.`})})]}),T?a(`div`,{className:`grid gap-3 rounded-xl border border-slate-700/60 bg-slate-900/20 p-3`,children:[a(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{className:`min-w-0`,children:[a(`div`,{className:`font-medium`,children:String(d?.label||`Codex Account`)}),a(`div`,{className:`tcp-subtle text-xs`,children:String(d?.description||`Use your ChatGPT/Codex subscription instead of a separate API key.`)})]}),a(Y,{tone:k.tone,children:k.text})]}),a(`div`,{className:`grid gap-1 text-xs tcp-subtle`,children:[A?a(`div`,{className:`rounded-xl border border-sky-700/50 bg-sky-950/20 px-3 py-2 text-sky-100`,children:[a(`div`,{className:`font-medium`,children:`Recommended for hosted servers`}),a(`div`,{className:`mt-1`,children:[`Import a Codex `,a(`code`,{children:`auth.json`}),` from a signed-in machine. Browser OAuth on provisioned servers can stall after the consent screen, so the import path is the reliable v1 flow.`]})]}):null,C?a(`div`,{children:`Pending browser sign-in is saved in this browser session, so you can refresh this page and Tandem will keep checking when you come back.`}):null,w?a(`div`,{children:y||v?`Connected as ${y||v}.`:`Connected to a Codex account.`}):null,b?a(`div`,{children:[`Managed by`,` `,b===`codex-cli`?`the local Codex CLI session`:b===`codex-upload`?`an uploaded Codex auth.json`:`Tandem`,`.`]}):null,A&&w&&b===`codex-upload`?a(`div`,{children:[`This hosted server is currently using an imported Codex session stored on the VM. Import another`,` `,a(`code`,{children:`auth.json`}),` any time to replace it.`]}):null,x>0?a(`div`,{children:[`Session status refreshes through`,` `,new Date(x).toLocaleString(),`.`]}):null,t===Qv&&w&&!h?a(`div`,{children:`Tandem is connected to Codex, but new runs are still using a different default provider.`}):null,E?a(`div`,{children:A?`This Tandem-hosted server can import a Codex auth.json from a signed-in machine and keep the session on the VM.`:S?`Local Codex CLI session detected on this machine.`:`If the Codex CLI is already signed in on this machine, you can mirror that session here instead of starting a fresh browser login.`}):null,E?null:a(`div`,{children:`Codex account sign-in is only enabled when this control panel is connected to a local engine or a Tandem-hosted managed server.`})]}),A?a(`div`,{className:`grid gap-3`,children:[a(`input`,{ref:Ht,type:`file`,accept:`.json,application/json`,className:`hidden`,onChange:e=>{qn(t,e.target.files?.[0]||null)}}),a(`textarea`,{className:`tcp-input min-h-40 resize-y rounded-xl p-3 font-mono text-xs leading-5`,value:Pe,onChange:e=>Fe(e.target.value),placeholder:`Paste the contents of ~/.codex/auth.json here.
7373
7373
 
7374
7374
  Tandem will store it on this server and reuse it for Codex sessions.`}),a(`div`,{className:`grid gap-1 text-xs tcp-subtle`,children:[a(`div`,{children:`You can paste the JSON directly, or choose the file from a signed-in machine.`}),Ut?a(`div`,{children:[`Loaded file: `,Ut]}):null]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn`,disabled:!E||!Pe.trim()||Wn.isPending||Hn.isPending,onClick:()=>Wn.mutate({providerId:t,authJson:Pe}),children:[a(`i`,{"data-lucide":`upload`}),w?`Replace hosted Codex session`:`Import pasted auth.json`]}),a(`button`,{type:`button`,className:`tcp-btn`,disabled:Wn.isPending||Hn.isPending,onClick:()=>Ht.current?.click(),children:[a(`i`,{"data-lucide":`file-up`}),`Choose auth.json file`]}),S?a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:!E||Vn.isPending||Un.isPending,onClick:()=>{Ce(e=>{if(!e[t])return e;let n={...e};return delete n[t],n}),Un.mutate({providerId:t})},children:[a(`i`,{"data-lucide":`link-2`}),`Use Local Codex Session`]}):null,t===Qv&&w&&!h?a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:On.isPending,onClick:()=>On.mutate({providerId:t,modelId:r||`gpt-5.4`}),children:[a(`i`,{"data-lucide":`sparkles`}),`Use for Tandem Runs`]}):null,a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:!w||Hn.isPending||Wn.isPending||C,onClick:()=>Hn.mutate({providerId:t}),children:[a(`i`,{"data-lucide":`unlink`}),`Disconnect`]})]})]}):a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{type:`button`,className:`tcp-btn`,disabled:!E||C||Hn.isPending,onClick:()=>Vn.mutate({providerId:t}),children:[a(`i`,{"data-lucide":`log-in`}),w?`Reconnect Codex Account`:`Connect Codex Account`]}),nn&&t===Qv&&S?a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:!E||Vn.isPending||Un.isPending,onClick:()=>{Ce(e=>{if(!e[t])return e;let n={...e};return delete n[t],n}),Un.mutate({providerId:t})},children:[a(`i`,{"data-lucide":`link-2`}),`Use Local Codex Session`]}):null,t===Qv&&w&&!h?a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:On.isPending,onClick:()=>On.mutate({providerId:t,modelId:r||`gpt-5.4`}),children:[a(`i`,{"data-lucide":`sparkles`}),`Use for Tandem Runs`]}):null,a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,disabled:!w||Hn.isPending||C,onClick:()=>Hn.mutate({providerId:t}),children:[a(`i`,{"data-lucide":`unlink`}),`Disconnect`]}),C?a(`button`,{type:`button`,className:`tcp-btn h-10 px-4 text-sm`,onClick:()=>window.open(`https://chatgpt.com/codex`,`_blank`,`noopener,noreferrer`),children:[a(`i`,{"data-lucide":`external-link`}),`Open Codex`]}):null]})]}):a(`form`,{onSubmit:e=>{e.preventDefault();let n=e.currentTarget.elements.namedItem(`apiKey`),r=String(n?.value||``).trim();r&&(Bn.mutate({providerId:t,apiKey:r}),n.value=``)},className:`flex gap-2`,children:[a(`input`,{name:`apiKey`,className:`tcp-input`,placeholder:String(d?.placeholder||`Set ${t} API key`)}),a(`button`,{className:`tcp-btn`,type:`submit`,children:[a(`i`,{"data-lucide":`save`}),`Save`]})]})]})]},t)}):a(br,{text:`No providers were detected from the engine catalog.`})]}):null})]})}):null,F===`search`?a(X,{title:`Web Search`,subtitle:"Configure the engine's `websearch` backend and provider keys.",actions:a(Xn,{children:[a(Y,{tone:cn.data?.settings?.has_brave_key?`ok`:`warn`,children:[`Brave`,` `,cn.data?.settings?.has_brave_key?`configured`:`missing`]}),a(Y,{tone:cn.data?.settings?.has_exa_key?`ok`:`warn`,children:[`Exa`,` `,cn.data?.settings?.has_exa_key?`configured`:`missing`]}),a(`button`,{className:`tcp-btn`,onClick:()=>Zn.mutate({query:le.trim()}),disabled:!cn.data?.available||!le.trim()||Zn.isPending,children:[a(`i`,{"data-lucide":Zn.isPending?`loader-circle`:`search`}),Zn.isPending?`Testing...`:`Test search`]}),a(`button`,{className:`tcp-btn-primary`,onClick:()=>Jn.mutate({backend:B,tandem_url:H,searxng_url:U,timeout_ms:Number.parseInt(re||`10000`,10),brave_api_key:ae.trim()||void 0,exa_api_key:se.trim()||void 0}),disabled:!cn.data?.available||Jn.isPending,children:[a(`i`,{"data-lucide":`save`}),`Save`]})]}),children:cn.data?.available?a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4 text-sm`,children:[a(`div`,{className:`font-medium`,children:`Engine env file`}),a(`div`,{className:`tcp-subtle mt-1 break-all`,children:cn.data?.managed_env_path||`/etc/tandem/engine.env`}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:cn.data?.restart_hint||`Changes apply immediately.`})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`Backend`}),a(`select`,{className:`tcp-select`,value:B,onChange:e=>V(e.target.value),children:[a(`option`,{value:`auto`,children:`Auto failover`}),a(`option`,{value:`brave`,children:`Brave Search`}),a(`option`,{value:`exa`,children:`Exa`}),a(`option`,{value:`searxng`,children:`SearxNG`}),a(`option`,{value:`tandem`,children:`Tandem hosted search`}),a(`option`,{value:`none`,children:`Disable websearch`})]})]}),a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`Timeout (ms)`}),a(`input`,{className:`tcp-input`,type:`number`,min:1e3,max:12e4,value:re,onInput:e=>ie(e.target.value)})]})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`Tandem search URL`}),a(`input`,{className:`tcp-input`,placeholder:`https://search.tandem.ac`,value:H,onInput:e=>te(e.target.value)}),a(`span`,{className:`tcp-subtle text-xs`,children:"Only used when backend is set to `tandem` or `auto`. This is the hosted Tandem search router, not the SearXNG endpoint."})]}),a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`SearxNG URL`}),a(`input`,{className:`tcp-input`,placeholder:`http://127.0.0.1:8080`,value:U,onInput:e=>ne(e.target.value)}),a(`span`,{className:`tcp-subtle text-xs`,children:"Only used when backend is `searxng` or `auto`."})]})]}),a(`div`,{className:`grid gap-3 rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Search test`}),a(`div`,{className:`tcp-subtle mt-1 text-xs`,children:"Runs `websearch` against the currently running engine config and renders the result as markdown below."})]}),a(Y,{tone:`warn`,children:`Tests live engine config`})]}),a(`div`,{className:`grid gap-3 md:grid-cols-[minmax(0,1fr)_auto]`,children:[a(`input`,{className:`tcp-input`,placeholder:`Try a test query like autonomous AI agentic workflows`,value:le,onInput:e=>ue(e.target.value)}),a(`button`,{className:`tcp-btn`,onClick:()=>Zn.mutate({query:le.trim()}),disabled:!cn.data?.available||!le.trim()||Zn.isPending,children:[a(`i`,{"data-lucide":Zn.isPending?`loader-circle`:`play`}),Zn.isPending?`Running...`:`Run test`]})]}),de?.markdown?a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`flex flex-wrap items-center gap-2 text-xs`,children:[a(Y,{tone:`ok`,children:[`Backend`,` `,String(de.parsed_output?.backend||de.metadata?.backend||`unknown`)]}),de.parsed_output?.configured_backend?a(Y,{tone:`info`,children:[`Configured`,` `,String(de.parsed_output.configured_backend)]}):null,de.metadata?.error?a(Y,{tone:`warn`,children:String(de.metadata.error).replaceAll(`_`,` `)}):null]}),a(`div`,{className:`tcp-markdown tcp-markdown-ai max-h-[320px] overflow-auto rounded-xl border border-slate-700/60 bg-black/20 p-3 text-sm`,dangerouslySetInnerHTML:{__html:Nr(de.markdown||``)}})]}):null]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`grid gap-2 rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-2`,children:[a(`div`,{className:`font-medium`,children:`Brave Search key`}),a(Y,{tone:cn.data?.settings?.has_brave_key?`ok`:`warn`,children:cn.data?.settings?.has_brave_key?`Saved`:`Missing`})]}),a(`input`,{className:`tcp-input`,type:`password`,placeholder:`Paste Brave Search key`,value:ae,onInput:e=>oe(e.target.value)}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn`,onClick:()=>Jn.mutate({backend:B,tandem_url:H,searxng_url:U,timeout_ms:Number.parseInt(re||`10000`,10),brave_api_key:ae.trim()||void 0}),disabled:!ae.trim()||Jn.isPending,children:`Save Brave Key`}),cn.data?.settings?.has_brave_key?a(`button`,{className:`tcp-btn`,onClick:()=>Jn.mutate({backend:B,tandem_url:H,searxng_url:U,timeout_ms:Number.parseInt(re||`10000`,10),clear_brave_key:!0}),disabled:Jn.isPending,children:`Remove`}):null]})]}),a(`div`,{className:`grid gap-2 rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:[a(`div`,{className:`flex items-center justify-between gap-2`,children:[a(`div`,{className:`font-medium`,children:`Exa key`}),a(Y,{tone:cn.data?.settings?.has_exa_key?`ok`:`warn`,children:cn.data?.settings?.has_exa_key?`Saved`:`Missing`})]}),a(`input`,{className:`tcp-input`,type:`password`,placeholder:`Paste Exa API key`,value:se,onInput:e=>ce(e.target.value)}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn`,onClick:()=>Jn.mutate({backend:B,tandem_url:H,searxng_url:U,timeout_ms:Number.parseInt(re||`10000`,10),exa_api_key:se.trim()||void 0}),disabled:!se.trim()||Jn.isPending,children:`Save Exa Key`}),cn.data?.settings?.has_exa_key?a(`button`,{className:`tcp-btn`,onClick:()=>Jn.mutate({backend:B,tandem_url:H,searxng_url:U,timeout_ms:Number.parseInt(re||`10000`,10),clear_exa_key:!0}),disabled:Jn.isPending,children:`Remove`}):null]})]})]}),a(`div`,{className:`tcp-subtle text-xs`,children:"`auto` tries the configured backends with failover. If Brave is rate-limited and Exa is configured, the engine can continue with Exa instead of returning a generic unavailable message."})]}):a(br,{text:cn.data?.reason||`Search settings are only editable here when the panel points at a local engine host or a Tandem-hosted managed server.`})}):null,F===`scheduler`?a(X,{title:`Automation Scheduler`,subtitle:`Controls parallel execution of automation runs. Restart tandem-engine after changing.`,actions:a(Xn,{children:a(`button`,{className:`tcp-btn-primary`,onClick:()=>Yn.mutate({mode:pe,max_concurrent_runs:G?Number.parseInt(G,10):null}),disabled:!ln.data?.available||Yn.isPending,children:[a(`i`,{"data-lucide":`save`}),`Save`]})}),children:ln.data?.available?a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4 text-sm`,children:[a(`div`,{className:`font-medium`,children:`Engine env file`}),a(`div`,{className:`tcp-subtle mt-1 break-all`,children:ln.data?.managed_env_path||`/etc/tandem/engine.env`}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:ln.data?.restart_hint||`Restart tandem-engine after changing scheduler mode.`})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`Mode`}),a(`select`,{className:`tcp-select`,value:pe,onChange:e=>W(e.target.value),children:[a(`option`,{value:`multi`,children:`Multi — parallel runs (recommended)`}),a(`option`,{value:`single`,children:`Single — one run at a time`})]})]}),a(`label`,{className:`grid gap-1 text-sm`,children:[a(`span`,{className:`tcp-subtle text-xs uppercase tracking-[0.18em]`,children:`Max concurrent runs`}),a(`input`,{className:`tcp-input`,type:`number`,min:1,max:32,placeholder:`8 (default)`,value:G,onInput:e=>K(e.target.value)})]})]}),a(`div`,{className:`tcp-subtle text-xs`,children:`Multi mode allows several automation runs to execute concurrently. Max concurrent runs caps parallelism. Changes require a tandem-engine restart to take effect.`})]}):a(br,{text:ln.data?.reason||`Scheduler settings are only editable here when the panel points at a local engine host or a Tandem-hosted managed server.`})}):null,F===`identity`?a(X,{title:`Identity preview`,subtitle:`Live preview of how the assistant appears across the panel.`,actions:a(Xn,{children:[a(`button`,{className:`tcp-btn`,onClick:()=>C().then(()=>n(`ok`,`Identity refreshed.`)),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh identity`]}),a(`button`,{className:`tcp-btn-primary`,onClick:()=>$n.mutate(),disabled:$n.isPending,children:[a(`i`,{"data-lucide":`save`}),`Save`]})]}),children:a(`div`,{className:`grid gap-3`,children:[a(`div`,{className:`rounded-2xl border border-slate-700/60 bg-slate-950/25 p-4`,children:a(`div`,{className:`flex items-center justify-between gap-3`,children:[a(`div`,{className:`inline-flex items-center gap-3`,children:[a(`span`,{className:`tcp-brand-avatar inline-grid h-12 w-12 rounded-xl`,children:a(`img`,{src:j||`/icon.png`,alt:k||`Tandem`,className:`block h-full w-full object-contain p-1`})}),a(`div`,{children:[a(`div`,{className:`font-semibold`,children:k||`Tandem`}),a(`div`,{className:`tcp-subtle text-xs`,children:N||`Control Center`})]})]}),a(Xn,{children:[a(`button`,{className:`tcp-icon-btn`,title:`Upload avatar`,"aria-label":`Upload avatar`,onClick:()=>Vt.current?.click(),children:a(`i`,{"data-lucide":`pencil`})}),a(`button`,{className:`tcp-icon-btn`,title:`Clear avatar`,"aria-label":`Clear avatar`,onClick:()=>M(``),children:a(`i`,{"data-lucide":`trash-2`})})]})]})}),a(`input`,{className:`tcp-input`,value:k,onInput:e=>A(e.target.value),placeholder:`Bot name`}),a(`input`,{className:`tcp-input`,value:N,onInput:e=>P(e.target.value),placeholder:`Control panel alias`}),a(`input`,{className:`tcp-input`,value:j,onInput:e=>M(e.target.value),placeholder:`Avatar URL or data URL`}),a(`input`,{ref:Vt,type:`file`,accept:`image/*`,className:`hidden`,onChange:e=>pr(e.target.files?.[0]||null)})]})}):null,F===`theme`?a(X,{title:`Theme studio`,subtitle:`Preview tiles with richer feedback and immediate switching.`,children:a(Bv,{themes:g,themeId:b,onChange:v})}):null,F===`channels`?a(X,{title:`Channel connections`,subtitle:`Telegram, Discord, and Slack delivery setup and live listener status.`,actions:a(Xn,{children:[a(Y,{tone:Pr?`ok`:`warn`,children:[Pr,`/`,$v.length,` connected`]}),a(`button`,{className:`tcp-btn`,onClick:()=>void nr(),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Refresh channels`]})]}),children:a(`div`,{className:`grid gap-3`,children:$v.map(e=>{let t=wn.data?.[e]||{},n=Tn.data?.[e]||{},r=q[e]||by(e,t),i=He[e],o=(En.data||{})[e]?.slice()||[],c=String(Re[e]||``).trim(),u=o.find(e=>e.scope_id===c)||null,d=u?Ty(u):c||`Channel default`,f=c?`scope`:`channel`,p=Cy(Dn.data?.[e]||xy()),m=hr.map(e=>`mcp.${yc(e.name)}.`),h=new Set(p.enabled_mcp_tools.filter(e=>m.some(t=>e.startsWith(t)))),g=r.securityProfile===`public_demo`,_=Iy(e,t),v=!Ly(e,r,t);return a(`div`,{className:`tcp-list-item grid gap-3`,children:[a(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-semibold capitalize`,children:e}),a(`div`,{className:`tcp-subtle text-xs`,children:e===`telegram`?`Bot token, allowed users, style profile, and optional model override.`:e===`discord`?`Bot token, allowed users, mention policy, guild targeting, and optional model override.`:`Bot token, allowed users, mention policy, default channel, and optional model override.`})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(Y,{tone:n.connected?`ok`:`warn`,children:n.connected?`Connected`:n.enabled?`Configured`:`Disconnected`}),a(Y,{tone:t.has_token?`info`:`warn`,children:t.has_token?`Token saved`:`No token`})]})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`input`,{className:`tcp-input`,type:`password`,placeholder:t.has_token?String(t.token_masked||`****`):`Paste ${e} bot token`,value:r.botToken,onInput:t=>Ie(n=>({...n,[e]:{...r,botToken:t.target.value}}))}),t.has_token&&!r.botToken?a(`div`,{className:`tcp-subtle text-xs`,children:`Token is already stored. Enter a new token only if you want to replace it.`}):null,a(`input`,{className:`tcp-input`,placeholder:`Allowed users (comma separated)`,value:r.allowedUsers,onInput:t=>Ie(n=>({...n,[e]:{...r,allowedUsers:t.target.value}}))})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`select`,{className:`tcp-input`,value:r.securityProfile,onInput:t=>Ie(n=>({...n,[e]:{...r,securityProfile:t.target.value}})),children:[a(`option`,{value:`operator`,children:`Operator`}),a(`option`,{value:`trusted_team`,children:`Trusted team`}),a(`option`,{value:`public_demo`,children:`Public demo`})]}),e===`telegram`?a(`input`,{className:`tcp-input`,placeholder:`Style profile`,value:r.styleProfile,onInput:t=>Ie(n=>({...n,[e]:{...r,styleProfile:t.target.value}}))}):null,e===`discord`?a(`input`,{className:`tcp-input`,placeholder:`Guild ID (optional)`,value:r.guildId,onInput:t=>Ie(n=>({...n,[e]:{...r,guildId:t.target.value}}))}):null,e===`slack`?a(`input`,{className:`tcp-input`,placeholder:`Default channel ID`,value:r.channelId,onInput:t=>Ie(n=>({...n,[e]:{...r,channelId:t.target.value}}))}):null,a(`label`,{className:`inline-flex items-center gap-2 rounded-xl border border-slate-700/60 bg-slate-900/20 px-3 py-2 text-sm`,children:[a(`input`,{type:`checkbox`,checked:r.mentionOnly,onChange:t=>Ie(n=>({...n,[e]:{...r,mentionOnly:t.target.checked}}))}),`Mention only`]})]}),a(`div`,{className:`rounded-xl border border-slate-700/60 bg-slate-900/20 p-3`,children:[a(`div`,{className:`mb-3 flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Channel model override`}),a(`div`,{className:`tcp-subtle text-xs`,children:`Pick the provider and model this channel should use. Leave both blank to inherit Tandem's global default.`})]}),a(Y,{tone:r.modelProviderId&&r.modelId?`ok`:`info`,children:r.modelProviderId&&r.modelId?`Custom model`:`Global default`})]}),a(Zi,{providerLabel:`Provider`,modelLabel:`Model`,draft:{provider:r.modelProviderId,model:r.modelId},providers:en,onChange:({provider:t,model:n})=>Ie(i=>({...i,[e]:{...r,modelProviderId:t,modelId:n}})),inheritLabel:`Use global default`}),a(`div`,{className:`mt-2 tcp-subtle text-xs`,children:r.modelProviderId&&r.modelId?a(`span`,{children:[`Selected model: `,a(`strong`,{children:r.modelProviderId}),` /`,` `,a(`strong`,{children:r.modelId})]}):an.provider&&an.model?a(`span`,{children:[`Inheriting Tandem default:`,` `,a(`strong`,{children:an.provider}),` /`,` `,a(`strong`,{children:an.model})]}):a(`span`,{children:`No global default model is configured yet.`})})]}),r.securityProfile===`public_demo`?a(`div`,{className:`tcp-subtle text-xs`,children:"Public demo mode blocks operator commands, file/workspace access, MCP access, shell access, and tool-scope widening. Memory stays confined to this channel's quarantined public namespace, and `/help` still advertises restricted capabilities for security."}):null,a(`div`,{className:`tcp-subtle text-xs`,children:[`Active sessions: `,Number(n.active_sessions||0),n.last_error?` · Last error: ${n.last_error}`:``]}),i?.hints?.length?a(`div`,{className:`rounded-xl border border-slate-700/60 bg-slate-900/20 p-3 text-xs`,children:[a(`div`,{className:`mb-1 font-medium`,children:`Verification hints`}),a(`div`,{className:`grid gap-1`,children:i.hints.map((t,n)=>a(`div`,{className:`tcp-subtle`,children:t},`${e}-hint-${n}`))})]}):null,a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn-primary`,disabled:ir.isPending||!v,onClick:()=>ir.mutate(e),children:[a(`i`,{"data-lucide":`save`}),`Save`]}),e===`discord`?a(`button`,{className:`tcp-btn`,disabled:or.isPending,onClick:()=>or.mutate(`discord`),children:[a(`i`,{"data-lucide":`shield-check`}),`Verify`]}):null,a(`button`,{className:`tcp-btn-danger`,disabled:ar.isPending||!_,onClick:()=>ar.mutate(e),children:[a(`i`,{"data-lucide":`trash-2`}),`Remove`]})]}),a(s.div,{layout:!0,className:`rounded-xl border border-slate-700/60 bg-slate-900/20 p-3`,children:[a(`div`,{className:`mb-3 flex flex-wrap items-start justify-between gap-3`,children:[a(`div`,{children:[a(`div`,{className:`font-medium`,children:`Channel tool scope`}),a(`div`,{className:`tcp-subtle text-xs`,children:[`Built-in tools and MCP servers available to `,e,` sessions.`]}),p.enabled_tools.some(e=>e!==ny)?a(`div`,{className:`mt-1 text-xs text-amber-300`,children:[`Explicit built-in allowlist is active for this`,` `,f,`.`]}):null,g?a(`div`,{className:`mt-1 text-xs text-slate-400`,children:`Public demo profile can only expose web and quarantined public-memory tools here. File, shell, MCP, and operator-facing tools stay disabled even if saved in channel preferences.`}):null]}),a(`div`,{className:`flex flex-wrap items-center gap-2`,children:[a(`button`,{className:`tcp-btn`,disabled:rr.isPending,onClick:()=>rr.mutate({channel:e,scopeId:c||null,payload:{reset:!0}}),children:`Reset scope`}),a(`button`,{className:`tcp-btn`,"aria-expanded":!!Be[e],onClick:()=>Ve(t=>({...t,[e]:!t[e]})),children:[a(`span`,{children:Be[e]?`Hide`:`Show`}),a(`i`,{"data-lucide":`chevron-down`,className:`h-4 w-4 transition-transform duration-200 ${Be[e]?`rotate-180`:``}`})]})]})]}),a(`div`,{className:`mb-3 grid gap-3 md:grid-cols-[minmax(0,1fr)_320px] md:items-end`,children:[a(`div`,{className:`grid gap-1`,children:[a(`div`,{className:`tcp-subtle text-xs`,children:c?`Editing ${d}. Saving here stores a scope-specific override on top of the ${e} default.`:`Editing the ${e} default. Pick a conversation scope to override one specific ${e} thread, room, or chat.`}),a(`div`,{className:`tcp-subtle text-[11px]`,children:o.length?`${o.length} known scope${o.length===1?``:`s`} discovered from channel sessions.`:`No scoped conversations discovered yet.`})]}),a(`label`,{className:`grid gap-1`,children:[a(`span`,{className:`tcp-subtle text-[11px] uppercase tracking-[0.24em]`,children:`Conversation scope`}),a(`select`,{className:`tcp-input`,value:c,onChange:t=>ze(n=>({...n,[e]:t.target.value})),children:[a(`option`,{value:``,children:`Channel default`}),c&&!o.some(e=>e.scope_id===c)?a(`option`,{value:c,children:d}):null,o.map(e=>a(`option`,{value:e.scope_id,children:Ty(e)},e.scope_id))]})]})]}),a(`div`,{className:`tcp-subtle text-xs`,children:[p.enabled_mcp_servers.length?`${p.enabled_mcp_servers.length} MCP server${p.enabled_mcp_servers.length===1?``:`s`} enabled for this ${f}.`:g?`MCP servers stay disabled in public demo mode.`:`No MCP servers enabled for this ${f}.`,p.enabled_mcp_tools.length?` ${p.enabled_mcp_tools.length} exact MCP tool${p.enabled_mcp_tools.length===1?``:`s`} also selected.`:``,` ${jy(r.securityProfile,ny)?Ey(p,ny)?`Workflow drafts from chat are enabled.`:`Workflow drafts from chat are disabled.`:`Workflow drafts stay disabled in public demo mode.`}`]}),a(l,{initial:!1,children:Be[e]?a(s.div,{initial:{opacity:0,height:0,y:-6},animate:{opacity:1,height:`auto`,y:0},exit:{opacity:0,height:0,y:-6},transition:{duration:.22,ease:[.22,1,.36,1]},className:`overflow-hidden`,children:a(`div`,{className:`grid gap-3 pt-3`,children:[a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`tcp-subtle text-[11px] uppercase tracking-[0.24em]`,children:`Workflow planning`}),a(`label`,{className:`flex items-center justify-between rounded-xl border border-slate-700/60 bg-slate-950/30 px-3 py-2 text-sm`,children:[a(`div`,{className:`flex flex-col`,children:[a(`span`,{className:`font-mono text-xs`,children:`Allow workflow drafts from chat`}),a(`span`,{className:`tcp-subtle text-[11px]`,children:"Stores the `tandem.workflow_planner` pseudo-tool in this channel scope without changing the normal tool allowlist."})]}),a(`input`,{type:`checkbox`,checked:Ey(p,ny),disabled:rr.isPending||!jy(r.securityProfile,ny),onChange:t=>rr.mutate({channel:e,scopeId:c||null,payload:Dy(p,ny,t.currentTarget.checked)})})]})]}),ty.map(t=>a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`tcp-subtle text-[11px] uppercase tracking-[0.24em]`,children:t.label}),a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:t.tools.map(t=>{let n=jy(r.securityProfile,t),i=My(p,t,r.securityProfile);return a(`label`,{className:`flex items-center justify-between rounded-xl border border-slate-700/60 bg-slate-950/30 px-3 py-2 text-sm`,children:[a(`div`,{className:`flex flex-col`,children:[a(`span`,{className:`font-mono text-xs`,children:t}),n?null:a(`span`,{className:`tcp-subtle text-[11px]`,children:`Disabled by security profile`})]}),a(`input`,{type:`checkbox`,checked:i,disabled:rr.isPending||!n,onChange:n=>rr.mutate({channel:e,scopeId:c||null,payload:Dy(p,t,n.currentTarget.checked)})})]},`${e}-tool-${t}`)})})]},`${e}-${t.label}`)),a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`tcp-subtle text-[11px] uppercase tracking-[0.24em]`,children:`MCP servers`}),hr.length?a(`div`,{className:`grid gap-2 md:grid-cols-2`,children:hr.map(t=>{let n=!g&&p.enabled_mcp_servers.includes(t.name);return a(`label`,{className:`flex items-center justify-between rounded-xl border border-slate-700/60 bg-slate-950/30 px-3 py-2 text-sm`,children:[a(`div`,{className:`flex flex-col`,children:[a(`span`,{className:`font-mono text-xs`,children:t.name}),g?a(`span`,{className:`tcp-subtle text-[11px]`,children:`Disabled by security profile`}):null]}),a(`input`,{type:`checkbox`,checked:n,disabled:rr.isPending||g,onChange:n=>rr.mutate({channel:e,scopeId:c||null,payload:Oy(p,t.name,n.currentTarget.checked)})})]},`${e}-mcp-${t.name}`)})}):a(`div`,{className:`tcp-subtle text-xs`,children:g?`MCP servers stay disabled in public demo mode.`:`No MCP servers configured yet.`})]}),a(`div`,{className:`grid gap-2`,children:[a(`div`,{className:`tcp-subtle text-[11px] uppercase tracking-[0.24em]`,children:`Exact MCP tools`}),a(`div`,{className:`tcp-subtle text-xs`,children:[`Choose exact tool names for this `,f,`. This narrows access without changing the whole-server toggles above.`]}),hr.length?a(`div`,{className:`grid gap-3`,children:[hr.map(t=>{let n=vy(Array.isArray(t.toolCache)?t.toolCache:[]),r=ky(p,t.name,n);return a(Tc,{title:t.name,subtitle:t.connected?t.enabled?`Connected and enabled globally. Pick the exact tools this scope can use.`:`Connected, but disabled globally. Exact selections are saved here and will apply if the server is enabled.`:`This server is disconnected. Exact selections are saved here and will apply when it reconnects.`,discoveredTools:n,value:r,disabled:rr.isPending||g,collapsible:!0,defaultCollapsed:!0,emptyText:`No MCP tools have been discovered for this server yet.`,onChange:r=>rr.mutate({channel:e,scopeId:c||null,payload:Ay(p,t.name,n,r)})},`${e}-exact-mcp-${t.name}`)}),p.enabled_mcp_tools.filter(e=>!h.has(e)).length?a(Tc,{title:`Saved exact tools not currently matched`,subtitle:`These exact MCP tools are still stored for this scope, but no discovered server is currently exposing them.`,discoveredTools:[],value:p.enabled_mcp_tools.filter(e=>!h.has(e)),disabled:rr.isPending||g,emptyText:`All saved exact MCP tools currently match a discovered server.`,onChange:t=>rr.mutate({channel:e,scopeId:c||null,payload:{...p,enabled_mcp_tools:Sy([...p.enabled_mcp_tools.filter(e=>h.has(e)),...t===null?[]:t])}})}):null]}):a(`div`,{className:`tcp-subtle text-xs`,children:g?`Exact MCP tools stay disabled in public demo mode.`:`No MCP servers configured yet.`})]})]})},`${e}-tool-scope-body`):null})]})]},e)})})}):null,F===`mcp`?a(X,{title:`MCP connections`,subtitle:`Configured MCP servers, connection state, and discovered tool coverage. Per-channel exact tool scopes live under Channels.`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:xr?`ok`:`warn`,children:[xr,`/`,hr.length,` connected`]}),a(Y,{tone:`info`,children:[gr.length,` tools`]}),a(`button`,{className:`tcp-btn`,onClick:()=>I(`channels`),children:`Channel scopes`}),a(`button`,{className:`tcp-btn-primary`,onClick:()=>Vr(),children:[a(`i`,{"data-lucide":`plus`}),`Add MCP server`]}),a(`button`,{className:`tcp-btn`,onClick:()=>void cr(),children:[a(`i`,{"data-lucide":`refresh-cw`}),`Reload`]})]}),children:a(`div`,{className:`grid gap-3`,children:[hr.length?hr.map(e=>{let t=Object.keys(e.headers||{}).filter(Boolean),n=Array.isArray(e.toolCache)?e.toolCache.length:0;return a(`div`,{className:`tcp-list-item grid gap-2`,children:[a(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[a(`div`,{children:[a(`div`,{className:`font-semibold`,children:e.name}),a(`div`,{className:`tcp-subtle text-sm`,children:e.transport||`No transport set`})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(Y,{tone:e.connected?`ok`:`warn`,children:e.connected?`Connected`:`Disconnected`}),a(Y,{tone:e.enabled?`info`:`warn`,children:e.enabled?`Enabled`:`Disabled`}),String(e.authKind||``).trim().toLowerCase()===`oauth`?a(Y,{tone:`info`,children:`OAuth`}):null,a(Y,{tone:`info`,children:[n,` tools`]})]})]}),e.lastError?a(`div`,{className:`rounded-xl border border-rose-700/60 bg-rose-950/20 px-2 py-1 text-xs text-rose-300`,children:e.lastError}):null,e.lastAuthChallenge?a(`div`,{className:`rounded-xl border border-amber-700/60 bg-amber-950/20 px-3 py-2 text-xs text-amber-100`,children:[a(`div`,{className:`font-medium`,children:`OAuth authorization pending`}),a(`div`,{className:`tcp-subtle mt-1`,children:String(e.lastAuthChallenge.message||``).trim()||`Open the authorization URL to finish connecting this MCP server.`}),a(`div`,{className:`tcp-subtle mt-1`,children:`Tandem will keep checking for completion automatically while this page is open.`}),String(e.lastAuthChallenge.authorization_url||e.lastAuthChallenge.authorizationUrl||e.authorizationUrl||``).trim()?a(`div`,{className:`mt-2 flex flex-wrap gap-2`,children:[a(`a`,{className:`tcp-btn inline-flex h-8 px-3 text-xs`,href:String(e.lastAuthChallenge.authorization_url||e.lastAuthChallenge.authorizationUrl||e.authorizationUrl||``).trim(),target:`_blank`,rel:`noreferrer`,children:`Open auth URL`}),a(`button`,{type:`button`,className:`tcp-btn inline-flex h-8 px-3 text-xs`,disabled:dr.isPending,onClick:()=>dr.mutate({action:`authenticate`,server:e}),children:`Mark sign-in complete`})]}):null]}):null,a(`div`,{className:`tcp-subtle text-xs`,children:t.length?`Auth headers: ${t.join(`, `)}`:`No stored auth headers.`}),a(Tc,{title:`Tool access`,subtitle:`Leave all discovered tools selected to expose the full MCP server, or uncheck tools to hide them from agents and workflows.`,discoveredTools:Array.isArray(e.toolCache)?e.toolCache:[],value:e.allowedTools,disabled:ur.isPending,onChange:t=>ur.mutate({serverName:e.name,allowedTools:t})}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn`,onClick:()=>Vr(e),children:`Edit`}),a(`button`,{className:`tcp-btn`,disabled:dr.isPending,onClick:()=>dr.mutate({action:e.connected?`disconnect`:`connect`,server:e}),children:e.connected?`Disconnect`:`Connect`}),a(`button`,{className:`tcp-btn`,disabled:dr.isPending,onClick:()=>dr.mutate({action:`refresh`,server:e}),children:`Refresh`}),a(`button`,{className:`tcp-btn`,disabled:dr.isPending,onClick:()=>dr.mutate({action:`toggle-enabled`,server:e}),children:e.enabled?`Disable`:`Enable`}),a(`button`,{className:`tcp-btn-danger`,disabled:dr.isPending,onClick:()=>dr.mutate({action:`delete`,server:e}),children:`Delete`})]})]},e.name)}):a(`div`,{className:`grid gap-3`,children:[a(br,{text:`No MCP servers configured.`}),a(`div`,{className:`flex justify-start`,children:a(`button`,{className:`tcp-btn-primary`,onClick:()=>Vr(),children:[a(`i`,{"data-lucide":`plus`}),`Add MCP server`]})})]}),a(`div`,{className:`rounded-xl border border-slate-700/60 bg-slate-900/20 p-3`,children:[a(`div`,{className:`mb-2 font-medium`,children:`Discovered tools`}),a(`pre`,{className:`tcp-code max-h-56 overflow-auto whitespace-pre-wrap break-words`,children:gr.length?gr.slice(0,250).join(`
7375
7375
  `):`No MCP tools discovered yet. Connect a server first.`})]})]})}):null,F===`bug_monitor`?a(X,{title:`Bug monitor`,actions:a(`div`,{className:`flex flex-wrap items-center justify-end gap-2`,children:[a(Y,{tone:Sr.runtime?.monitoring_active?Sr.readiness?.publish_ready?`ok`:`info`:Sr.readiness?.ingest_ready?`info`:`warn`,children:Sr.runtime?.monitoring_active?Sr.readiness?.publish_ready?`Monitoring`:`Watching locally`:Sr.readiness?.ingest_ready?`Ready`:`Not ready`}),J||Sr.runtime?.paused?a(Y,{tone:`warn`,children:`Paused`}):null,a(Y,{tone:`info`,children:[Number(Sr.runtime?.pending_incidents||0),` incidents`]}),a(Y,{tone:`info`,children:[Number(Sr.pending_drafts||0),` pending drafts`]}),a(Y,{tone:`info`,children:[Number(Sr.pending_posts||0),` post attempts`]}),a(`button`,{className:`tcp-icon-btn`,title:`Reload status`,"aria-label":`Reload status`,onClick:()=>Promise.all([yn.refetch(),bn.refetch(),xn.refetch(),Sn.refetch()]).then(()=>n(`ok`,`Bug Monitor status refreshed.`)),children:a(`i`,{"data-lucide":`refresh-cw`})}),a(`button`,{className:`tcp-icon-btn`,title:J||Sr.runtime?.paused?`Resume monitoring`:`Pause monitoring`,"aria-label":J||Sr.runtime?.paused?`Resume monitoring`:`Pause monitoring`,disabled:In.isPending,onClick:()=>In.mutate({action:J||Sr.runtime?.paused?`resume`:`pause`}),children:a(`i`,{"data-lucide":J||Sr.runtime?.paused?`play`:`pause`})}),a(`button`,{className:`tcp-icon-btn`,title:`Refresh capability bindings`,"aria-label":`Refresh capability bindings`,disabled:Nn.isPending,onClick:()=>Nn.mutate(),children:a(`i`,{"data-lucide":`rotate-cw`})}),a(`button`,{className:`tcp-icon-btn`,title:`Copy debug payload`,"aria-label":`Copy debug payload`,onClick:()=>void Hr(),children:a(`i`,{"data-lucide":`copy`})}),a(`button`,{className:`tcp-icon-btn`,title:`Open GitHub MCP guide`,"aria-label":`Open GitHub MCP guide`,onClick:()=>_e(!0),children:a(`i`,{"data-lucide":`book-open`})})]}),children:a(`div`,{className:`grid gap-4`,children:[a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Reporter state`}),a(`button`,{type:`button`,className:`tcp-list-item text-left ${mt?`ring-1 ring-emerald-400/40`:``}`,onClick:()=>ht(e=>!e),children:[a(`div`,{className:`font-medium`,children:mt?J?`Paused`:`Enabled`:`Disabled`}),a(`div`,{className:`tcp-subtle text-xs`,children:mt?J?`Monitoring is paused. Resume to process new failures.`:`Failure events can be analyzed once readiness is green.`:`No reporter work will execute.`})]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Local directory`}),a(`div`,{className:`grid gap-2 md:grid-cols-[auto_1fr_auto]`,children:[a(`button`,{className:`tcp-btn`,type:`button`,onClick:()=>{Rt(String(_t||`/`).trim()||`/`),Bt(``),It(!0)},children:[a(`i`,{"data-lucide":`folder-open`}),`Browse`]}),a(`input`,{className:`tcp-input`,readOnly:!0,value:_t,placeholder:`No local directory selected. Use Browse.`}),a(`button`,{className:`tcp-btn`,type:`button`,onClick:()=>vt(``),disabled:!_t,children:[a(`i`,{"data-lucide":`x`}),`Clear`]})]}),a(`div`,{className:`tcp-subtle text-xs`,children:_t?`Reporter analysis root: ${_t}`:`Defaults to the engine workspace root if not set.`})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Target repo`}),a(`input`,{className:`tcp-input`,value:yt,onChange:e=>bt(e.target.value),placeholder:`owner/repo`})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`MCP server`}),a(`select`,{className:`tcp-input`,value:xt,onChange:e=>St(e.target.value),children:[a(`option`,{value:``,children:`Select an MCP server`}),hr.map(e=>a(`option`,{value:e.name,children:e.name},e.name))]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Provider preference`}),a(`select`,{className:`tcp-input`,value:Ct,onChange:e=>wt(e.target.value),children:[a(`option`,{value:`auto`,children:`Auto`}),a(`option`,{value:`official_github`,children:`Official GitHub`}),a(`option`,{value:`composio`,children:`Composio`}),a(`option`,{value:`arcade`,children:`Arcade`})]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Provider`}),a(`select`,{className:`tcp-input`,value:Tt,onChange:e=>{let t=e.target.value;Et(t),Ot(``)},children:[a(`option`,{value:``,children:`Select a provider`}),mr.map(e=>a(`option`,{value:String(e?.id||``),children:String(e?.id||``)},String(e?.id||``)))]})]}),a(`label`,{className:`grid gap-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`Model`}),a(`input`,{className:`tcp-input`,value:Dt,onChange:e=>Ot(e.target.value),list:`bug-monitor-models`,disabled:!Tt,placeholder:Tt?`Type or paste a model id`:`Choose a provider first`,spellCheck:!1}),a(`datalist`,{id:`bug-monitor-models`,children:Or.map(e=>a(`option`,{value:e},e))}),a(`div`,{className:`tcp-subtle text-xs`,children:Tt?Or.length?`${Or.length} suggested models from provider catalog`:`No provider catalog models available. Manual model ids are allowed.`:`Select a provider to load model suggestions.`})]}),a(`div`,{className:`grid gap-2 md:col-span-2`,children:[a(`span`,{className:`text-xs uppercase tracking-[0.24em] tcp-subtle`,children:`GitHub posting`}),a(`div`,{className:`grid gap-2 md:grid-cols-3`,children:[a(`button`,{type:`button`,className:`tcp-list-item text-left ${kt&&!jt?`ring-1 ring-emerald-400/40`:``}`,onClick:()=>{At(e=>!e),jt&&kt&&Mt(!1)},children:[a(`div`,{className:`font-medium`,children:`Auto-create new issues`}),a(`div`,{className:`tcp-subtle text-xs`,children:kt?`New drafts post to GitHub automatically.`:`New drafts stay internal until published manually.`})]}),a(`button`,{type:`button`,className:`tcp-list-item text-left ${jt?`ring-1 ring-amber-400/40`:``}`,onClick:()=>{Mt(e=>{let t=!e;return t&&At(!1),t})},children:[a(`div`,{className:`font-medium`,children:`Require approval`}),a(`div`,{className:`tcp-subtle text-xs`,children:jt?`New drafts wait for a manual publish click.`:`Approval gate disabled.`})]}),a(`button`,{type:`button`,className:`tcp-list-item text-left ${Nt?`ring-1 ring-sky-400/40`:``}`,onClick:()=>Pt(e=>!e),children:[a(`div`,{className:`font-medium`,children:`Auto-comment matches`}),a(`div`,{className:`tcp-subtle text-xs`,children:Nt?`Open matching GitHub issues receive new evidence comments.`:`Matching issues are detected but not updated automatically.`})]})]})]})]}),a(`div`,{className:`flex flex-wrap gap-2`,children:[a(`button`,{className:`tcp-btn-primary`,disabled:Mn.isPending,title:`Save Bug Monitor settings`,"aria-label":`Save Bug Monitor settings`,onClick:()=>Mn.mutate(),children:[a(`i`,{"data-lucide":`save`}),Mn.isPending?`Saving...`:null]}),a(`button`,{className:`tcp-icon-btn`,title:`Add MCP server`,"aria-label":`Add MCP server`,onClick:()=>Vr(),children:a(`i`,{"data-lucide":`plus`})}),a(`button`,{className:`tcp-icon-btn`,title:`Open setup guide`,"aria-label":`Open setup guide`,onClick:()=>_e(!0),children:a(`i`,{"data-lucide":`external-link`})}),a(`button`,{className:`tcp-icon-btn`,title:`Refresh capability bindings`,"aria-label":`Refresh capability bindings`,disabled:Nn.isPending,onClick:()=>Nn.mutate(),children:a(`i`,{"data-lucide":`rotate-cw`})}),a(`button`,{className:`tcp-icon-btn`,title:`Copy debug payload`,"aria-label":`Copy debug payload`,onClick:()=>void Hr(),children:a(`i`,{"data-lucide":`copy`})}),Er?a(`button`,{className:`tcp-icon-btn`,title:Er.connected?`Refresh selected MCP`:`Connect selected MCP`,"aria-label":Er.connected?`Refresh selected MCP`:`Connect selected MCP`,disabled:dr.isPending,onClick:()=>dr.mutate({action:Er.connected?`refresh`:`connect`,server:Er}),children:a(`i`,{"data-lucide":Er.connected?`refresh-cw`:`plug-zap`})}):null]}),a(`div`,{className:`grid gap-3 md:grid-cols-3`,children:[a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`text-sm font-medium`,children:`Readiness`}),a(`div`,{className:`mt-1 text-sm`,children:Sr.runtime?.monitoring_active?Sr.readiness?.publish_ready?`Monitoring`:`Watching locally`:Sr.runtime?.paused||J?`Paused`:Sr.readiness?.ingest_ready?`Ready`:`Blocked`}),a(`div`,{className:`tcp-subtle text-xs`,children:Sr.runtime?.last_runtime_error||Sr.last_error||`No blocking issue reported.`}),!Sr.readiness?.publish_ready&&Array.isArray(Sr.missing_required_capabilities)&&Sr.missing_required_capabilities.length?a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:[`Missing: `,Sr.missing_required_capabilities.join(`, `)]}):null]}),a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`text-sm font-medium`,children:`Selected MCP`}),a(`div`,{className:`mt-1 text-sm`,children:Er?.name||`None selected`}),a(`div`,{className:`tcp-subtle text-xs`,children:Er?Er.connected?`Connected`:`Disconnected`:`No server selected`}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:[`Bindings: `,Sr.binding_source_version||`unknown version`,Sr.bindings_last_merged_at_ms?` · merged ${new Date(Sr.bindings_last_merged_at_ms).toLocaleString()}`:``]}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:[`Local directory:`,` `,_t||String(Sr.config?.workspace_root||``).trim()||`engine workspace root`]}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:[`Last event:`,` `,String(Sr.runtime?.last_incident_event_type||``).trim()||`No incidents processed yet`]})]}),a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`text-sm font-medium`,children:`Model route`}),a(`div`,{className:`mt-1 break-all text-sm`,children:Sr.selected_model?.provider_id&&Sr.selected_model?.model_id?`${Sr.selected_model.provider_id} / ${Sr.selected_model.model_id}`:`No dedicated model selected`}),a(`div`,{className:`tcp-subtle text-xs`,children:Sr.readiness?.selected_model_ready?`Available`:`Fail-closed when unavailable`}),a(`div`,{className:`tcp-subtle mt-2 text-xs`,children:[`Last processed:`,` `,Sr.runtime?.last_processed_at_ms?new Date(Number(Sr.runtime.last_processed_at_ms)).toLocaleString():`Not processed yet`]})]})]}),a(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[a(`div`,{className:`tcp-list-item`,children:[a(`div`,{className:`font-medium`,children:`Capability readiness`}),a(`div`,{className:`tcp-subtle mt-2 grid gap-1 text-xs`,children:[a(`div`,{children:[`github.list_issues:`,` `,Sr.required_capabilities?.github_list_issues?`ready`:`missing`]}),a(`div`,{children:[`github.get_issue:`,` `,Sr.required_capabilities?.github_get_issue?`ready`:`missing`]}),a(`div`,{children:[`github.create_issue:`,` `,Sr.required_capabilities?.github_create_issue?`ready`:`missing`]}),a(`div`,{children:[`github.comment_on_issue:`,` `,Sr.required_capabilities?.github_comment_on_issue?`ready`:`missing`]})]}),Array.isArray(Sr.resolved_capabilities)&&Sr.resolved_capabilities.length?a(`div`,{className:`tcp-subtle mt-3 grid gap-1 text-xs`,children:Sr.resolved_capabilities.map((e,t)=>a(`div`,{children:[String(e.capability_id||`unknown`),`:`,` `,String(e.tool_name||`unresolved`)]},`${e.capability_id||`cap`}-${t}`))}):null,Array.isArray(Sr.selected_server_binding_candidates)&&Sr.selected_server_binding_candidates.length?a(`div`,{className:`tcp-subtle mt-3 grid gap-1 text-xs`,children:Sr.selected_server_binding_candidates.map((e,t)=>a(`div`,{children:[String(e.capability_id||`unknown`),`:`,` `,String(e.binding_tool_name||`unknown`),e.matched?` · matched`:` · candidate`]},`${e.capability_id||`candidate`}-${t}`))}):null,Array.isArray(Sr.discovered_mcp_tools)&&Sr.discovered_mcp_tools.length?a(`div`,{className:`mt-3`,children:[a(`div`,{className:`tcp-subtle text-xs font-medium`,children:`Discovered MCP tools`}),a(`pre`,{className:`tcp-code mt-1 max-h-40 overflow-auto whitespace-pre-wrap break-words text-xs`,children:Sr.discovered_mcp_tools.join(`
package/dist/index.html CHANGED
@@ -11,7 +11,7 @@
11
11
  href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Rubik:wght@500;700;800&family=Manrope:wght@400;500;600;700&display=swap"
12
12
  rel="stylesheet"
13
13
  />
14
- <script type="module" crossorigin src="/assets/index-BKPSvrcQ.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-CGXrSEHn.js"></script>
15
15
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Dgq8h090.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/motion-CBnf8hfk.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/react-query-_hsOQSt5.js">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frumu/tandem-panel",
3
- "version": "0.4.41",
3
+ "version": "0.4.42",
4
4
  "description": "Full web control center for Tandem Engine (chat, routines, swarm, memory, channels, and ops)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -46,8 +46,8 @@
46
46
  "@fullcalendar/interaction": "6.1.20",
47
47
  "@fullcalendar/react": "6.1.20",
48
48
  "@fullcalendar/timegrid": "6.1.20",
49
- "@frumu/tandem": "^0.4.41",
50
- "@frumu/tandem-client": "^0.4.41",
49
+ "@frumu/tandem": "^0.4.42",
50
+ "@frumu/tandem-client": "^0.4.42",
51
51
  "@tanstack/react-query": "^5.90.21",
52
52
  "dompurify": "^3.3.1",
53
53
  "lucide": "^0.575.0",