crewly 1.20.140 → 1.20.141

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.
@@ -4913,7 +4913,7 @@ Provide detailed instructions for this skill...`,rows:8,className:"font-mono tex
4913
4913
  "access_token": "...",
4914
4914
  "refresh_token": "...",
4915
4915
  ...
4916
- }`,className:"text-xs font-mono",spellCheck:!1}),i.jsxs("p",{className:"text-xs text-text-secondary-dark mt-1",children:["Copy the entire block from the opening ",i.jsx("code",{children:"{"})," to the closing ",i.jsx("code",{children:"}"}),"."]})]}),y&&i.jsx(tt,{variant:"error",children:y}),i.jsxs("div",{className:"flex justify-between items-center pt-2",children:[i.jsx(de,{type:"button",variant:"ghost",size:"xs",onClick:()=>{r("configure"),x(""),m(null),f(null)},children:"← Back (change scope)"}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:T,children:"Save credential"})]})]})]}),s==="saving"&&i.jsx(Ht,{size:"xs",inline:!0,text:"Saving credential…",className:"py-8"})]})},gye=({onClose:t,onImport:e,onClearExtensionFile:n})=>{const[s,r]=w.useState("name"),[a,o]=w.useState(""),[l,c]=w.useState(null),[d]=w.useState(null),[u,h]=w.useState(!1),f=()=>{if(!a.trim()){c('Please provide a name (e.g. "info-steam-fun", "personal-gmail")');return}c(null),r("instructions")},p=async()=>{c(null),r("importing");try{await e(a.trim()),r("done")}catch(m){c(m instanceof Error?m.message:"Import failed"),r("instructions")}},x=async()=>{h(!0);try{await n(),r("name"),o("")}catch(m){c(m instanceof Error?m.message:"Failed to clear extension file")}finally{h(!1)}},y=s==="done"?"Google account added":"Import from Gemini CLI";return i.jsxs(Kr,{isOpen:!0,onClose:t,title:y,size:"lg",children:[s==="name"&&i.jsxs("div",{className:"space-y-4",children:[i.jsxs(tt,{variant:"info",children:["This option is for developers who already run the Gemini CLI workspace extension locally. For the regular flow, close this and click ",i.jsx("strong",{children:"Add Google Account"}),"."]}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Pick a name for this Google account. You'll use this name to tell agents which account to use for a task."}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"cred-gemcli-name",children:"Name"}),i.jsx(Ut,{id:"cred-gemcli-name",type:"text",value:a,onChange:m=>o(m.target.value),placeholder:"e.g. info-steam-fun, personal-gmail",autoFocus:!0})]}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:f,children:"Next"})]})]}),s==="instructions"&&i.jsxs("div",{className:"space-y-4",children:[i.jsx(tt,{variant:"info",children:"You'll sign in via the Gemini CLI Workspace extension. Crewly will then copy the resulting tokens into its own encrypted store."}),i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"1. Open a terminal and run:"}),i.jsx("pre",{className:"bg-surface-dark border border-border-dark rounded p-3 text-xs font-mono overflow-x-auto",children:"GEMINI_CLI_WORKSPACE_FORCE_FILE_STORAGE=true gemini"})]}),i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"2. Inside gemini, type:"}),i.jsx("pre",{className:"bg-surface-dark border border-border-dark rounded p-3 text-xs font-mono overflow-x-auto",children:"list my calendar events for today"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"This triggers the workspace extension to open a browser for Google sign-in."})]}),i.jsxs("div",{children:[i.jsxs("div",{className:"text-sm font-medium mb-1",children:["3. In the browser: sign in as ",i.jsx("span",{className:"font-mono",children:a})]}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"Grant the requested scopes. You can close the browser after the success page appears."})]}),i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"4. Come back here and click Import."}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"Crewly will read the extension's token file and save an encrypted copy."})]})]}),i.jsxs("a",{href:"https://github.com/gemini-cli-extensions/workspace",target:"_blank",rel:"noreferrer",className:"text-xs text-primary inline-flex items-center gap-1 hover:underline",children:["About the workspace extension ",i.jsx(ws,{className:"w-3 h-3"})]}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:p,children:"Import"})]})]}),s==="importing"&&i.jsx(Ht,{size:"xs",inline:!0,centered:!1,text:"Reading the extension's token file…",className:"py-4"}),s==="done"&&i.jsxs("div",{className:"space-y-4",children:[i.jsxs(tt,{variant:"success",children:["Google account ",i.jsx("strong",{children:a})," added.",d&&i.jsxs(i.Fragment,{children:[" (",d,")"]})]}),i.jsx("div",{className:"text-sm text-text-secondary-dark",children:"To add another Google account, Crewly needs to clear the extension's cached token so your next sign-in captures a different account."}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Done"}),i.jsx(de,{variant:"primary",onClick:x,disabled:u,children:u?"Clearing…":"Add another account"})]})]})]})},xye=1e4;function yye(t){const e=[];for(const n of t)for(const s of n.members)e.push({memberId:s.id,name:s.name,sessionName:s.sessionName,role:s.role,teamName:n.name,teamId:n.id,agentStatus:s.agentStatus,workingStatus:s.workingStatus,readyAt:s.readyAt??null,lastActivityCheck:s.lastActivityCheck??null,runtimeType:s.runtimeType});return e}function vye(){const[t,e]=w.useState([]),[n,s]=w.useState(!0),[r,a]=w.useState(null),o=w.useRef(!0),l=w.useCallback(async()=>{try{const d=await yt.getTeams(!0);o.current&&(e(yye(d)),a(null))}catch(d){o.current&&a(d instanceof Error?d.message:"Failed to fetch agent heartbeats")}},[]),c=w.useCallback(async()=>{await l()},[l]);return w.useEffect(()=>{o.current=!0,(async()=>{await l(),o.current&&s(!1)})();const u=setInterval(l,xye);return()=>{o.current=!1,clearInterval(u)}},[l]),{agents:t,isLoading:n,error:r,refresh:c}}const bye={active:{label:"Active",color:"text-green-400",bgColor:"bg-green-500/10"},started:{label:"Started",color:"text-blue-400",bgColor:"bg-blue-500/10"},starting:{label:"Starting",color:"text-yellow-400",bgColor:"bg-yellow-500/10"},activating:{label:"Activating",color:"text-yellow-400",bgColor:"bg-yellow-500/10"},inactive:{label:"Offline",color:"text-text-secondary-dark",bgColor:"bg-text-secondary-dark/10"},suspended:{label:"Suspended",color:"text-red-400",bgColor:"bg-red-500/10"}};function _ye(t){return t?Hx(t):"Never"}const Sye=({agent:t})=>{const e=bye[t.agentStatus],n=t.agentStatus==="active"||t.agentStatus==="started";return i.jsxs(dt,{variant:"outlined",className:"hover:bg-surface-dark/30 transition-colors",children:[i.jsxs("div",{className:"flex items-start justify-between mb-3",children:[i.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[i.jsx("div",{className:`w-2 h-2 rounded-full shrink-0 ${n?"bg-green-400":"bg-text-secondary-dark"}`}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark truncate",children:t.name})]}),i.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium shrink-0 ${e.bgColor} ${e.color}`,children:e.label})]}),i.jsxs("div",{className:"space-y-2 text-xs",children:[i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Role"}),i.jsx("span",{className:"text-text-primary-dark capitalize",children:t.role})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Team"}),i.jsx("span",{className:"text-text-primary-dark truncate ml-2",children:t.teamName})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Working"}),i.jsx("span",{className:t.workingStatus==="in_progress"?"text-yellow-400":"text-text-secondary-dark",children:t.workingStatus==="in_progress"?"In Progress":"Idle"})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Runtime"}),i.jsx("span",{className:"text-text-primary-dark",children:t.runtimeType})]}),i.jsxs("div",{className:"flex justify-between items-center",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Connection"}),n?i.jsx(w2,{className:"w-3.5 h-3.5 text-green-400"}):i.jsx(yY,{className:"w-3.5 h-3.5 text-text-secondary-dark"})]})]}),i.jsxs("div",{className:"mt-3 pt-3 border-t border-border-dark flex justify-between text-xs",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Last active"}),i.jsx("span",{className:"text-text-secondary-dark",children:_ye(t.lastActivityCheck??t.readyAt)})]})]})},wye=()=>{const{agents:t,isLoading:e,error:n,refresh:s}=vye(),r=t.filter(a=>a.agentStatus==="active"||a.agentStatus==="started").length;return e?i.jsx("div",{className:"flex items-center justify-center py-12",children:i.jsx(Ht,{size:"sm",text:"Loading heartbeat status..."})}):n?i.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-red-500/10 border border-red-500/20",children:[i.jsx(Li,{className:"w-5 h-5 text-red-400 shrink-0"}),i.jsx("span",{className:"text-sm text-red-400",children:n})]}):i.jsxs("div",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-4",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(dl,{className:"w-5 h-5 text-text-secondary-dark"}),i.jsx("h3",{className:"text-lg font-semibold text-text-primary-dark",children:"Agent Heartbeat"}),i.jsxs("span",{className:"text-xs text-text-secondary-dark bg-surface-dark px-2 py-0.5 rounded-full",children:[r,"/",t.length," online"]})]}),i.jsx(de,{variant:"ghost",size:"sm",onClick:s,icon:an,children:"Refresh"})]}),t.length===0?i.jsxs("div",{className:"text-center py-12 text-text-secondary-dark",children:[i.jsx(dl,{className:"w-10 h-10 mx-auto mb-3 opacity-40"}),i.jsx("p",{className:"text-sm",children:"No agents found"}),i.jsx("p",{className:"text-xs mt-1 opacity-60",children:"Agent heartbeats will appear when teams have members configured"})]}):i.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:t.map(a=>i.jsx(Sye,{agent:a},`${a.teamId}-${a.memberId}`))})]})},Cye=()=>i.jsx("div",{className:"space-y-8",children:i.jsx(wye,{})});function kye(t,e,n){if(t!=null&&t.success&&n)return t.data??null;if(!t||!t.success||t.data===void 0||t.data===null)throw new Error((t==null?void 0:t.error)||(t==null?void 0:t.message)||e);return t.data}async function Fl(t,e,n=!1){var s;try{const r=await t();return kye(r.data,e,n)}catch(r){if(U1(r)){const a=(s=r.response)==null?void 0:s.data;throw new Error((a==null?void 0:a.error)||(a==null?void 0:a.message)||r.message||e)}throw r instanceof Error?r:new Error(e)}}function JB(t){return t&&typeof t=="object"&&"id"in t&&"state"in t?t:null}class Eye{async getStatus(){return Fl(()=>Ge.get(Nl.STATUS),"Failed to load harness status")}async startInstall(e){return(await Fl(()=>Ge.post(Nl.install(e)),"Failed to start install")).jobId}async getInstallJob(e){return Fl(()=>Ge.get(Nl.installJob(e)),"Failed to read install progress")}async setOrcHarness(e){return(await Fl(()=>Ge.put(Nl.ORC,{harnessId:e}),"Failed to save orchestrator harness")).orcHarness}async startLogin(e,n){return Fl(()=>Ge.post(Nl.login(e),{method:n}),"Failed to start login")}async getLoginSession(e){return Fl(()=>Ge.get(Nl.loginSession(e)),"Failed to read login status")}async sendLoginInput(e,n){const s=await Fl(()=>Ge.post(Nl.loginInput(e),{text:n}),"Failed to send input",!0);return JB(s)}async cancelLogin(e){const n=await Fl(()=>Ge.post(Nl.loginCancel(e)),"Failed to cancel login",!0);return JB(n)}async setApiKey(e,n){return Fl(()=>Ge.post(Nl.apiKey(e),{key:n}),"Failed to save API key")}}const Eo=new Eye;function Aye(t){const e=n=>{const s=A3.indexOf(n);return s===-1?A3.length:s};return[...t].sort((n,s)=>e(n.id)-e(s.id))}function X9(){const[t,e]=w.useState(null),[n,s]=w.useState(!0),[r,a]=w.useState(null),[o,l]=w.useState(!1),c=w.useRef(!0);w.useEffect(()=>(c.current=!0,()=>{c.current=!1}),[]);const d=w.useCallback(async()=>{try{const f=await Eo.getStatus();if(!c.current)return;e({...f,harnesses:Aye(f.harnesses)}),a(null)}catch(f){c.current&&a(f instanceof Error?f.message:String(f))}finally{c.current&&s(!1)}},[]);w.useEffect(()=>{d()},[d]);const u=w.useCallback(async f=>{l(!0);try{const p=await Eo.setOrcHarness(f);return c.current&&(e(x=>x&&{...x,orcHarness:p}),a(null)),!0}catch(p){return c.current&&a(p instanceof Error?p.message:String(p)),!1}finally{c.current&&l(!1)}},[]),h=w.useCallback(f=>{e(p=>p&&{...p,harnesses:p.harnesses.map(x=>x.id===f.id?f:x)})},[]);return{overview:t,loading:n,error:r,refresh:d,setOrcHarness:u,savingOrc:o,replaceHarness:h}}function Tye(t,e){const[n,s]=w.useState(null),[r,a]=w.useState(null),[o,l]=w.useState(null),[c,d]=w.useState(!1),u=w.useRef(e);u.current=e;const h=w.useCallback(async()=>{l(null),d(!0);try{const f=await Eo.startInstall(t);a({state:"running",log:"",usedUserPrefix:!1}),s(f)}catch(f){l(f instanceof Error?f.message:String(f))}finally{d(!1)}},[t]);return w.useEffect(()=>{if(!n||!r||r.state!=="running")return;let f=!1;const p=setTimeout(async()=>{var x;try{const y=await Eo.getInstallJob(n);if(f)return;a(y),y.state!=="running"&&((x=u.current)==null||x.call(u,y))}catch(y){if(f)return;l(y instanceof Error?y.message:String(y)),a(m=>m&&{...m,state:"failed"})}},$2.INSTALL_POLL_MS);return()=>{f=!0,clearTimeout(p)}},[n,r]),{job:r,error:o,running:c||(r==null?void 0:r.state)==="running",start:h}}const Mye=({log:t})=>{const e=w.useRef(null);return w.useEffect(()=>{e.current&&(e.current.scrollTop=e.current.scrollHeight)},[t]),i.jsx("pre",{ref:e,role:"log","aria-live":"polite","aria-label":"安装日志 / Install log","data-testid":"install-log",className:"mt-3 max-h-48 overflow-auto rounded-2xl border border-border-dark bg-background-dark p-3 font-mono text-xs leading-relaxed text-text-secondary-dark whitespace-pre-wrap break-all",children:t||"…"})},Nye=({harness:t,selectName:e,selected:n=!1,onSelect:s,onInstallFinished:r})=>{const{job:a,error:o,running:l,start:c}=Tye(t.id,r),d=V1[t.loginState],u=!t.installed||t.updateAvailable||(a==null?void 0:a.state)==="failed",h=(a==null?void 0:a.state)==="failed"?"重试安装":t.installed?"更新 / Update":"安装 / Install",f=i.jsx("span",{className:"font-semibold text-text-primary-dark",children:t.displayName});return i.jsxs(dt,{padding:"md","data-testid":`harness-card-${t.id}`,className:n?"border-primary":void 0,children:[i.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[i.jsxs("div",{className:"min-w-0",children:[e?i.jsxs("label",{className:"flex items-center gap-3 cursor-pointer",children:[i.jsx("input",{type:"radio",name:e,value:t.id,checked:n,onChange:()=>s==null?void 0:s(t.id),className:"h-4 w-4 accent-[var(--crewly-primary)]"}),f]}):f,i.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[t.installed?i.jsxs(ft,{variant:"success",children:["已安装",t.version?` v${t.version}`:""]}):i.jsx(ft,{variant:"default",children:"未安装 / Not installed"}),t.installed&&t.updateAvailable&&i.jsxs(ft,{variant:"info",children:["可更新",t.latestVersion?` → v${t.latestVersion}`:""]}),t.installed&&i.jsx(ft,{variant:d.variant,children:d.label}),t.installed&&t.loginSource&&i.jsx("span",{className:"text-xs text-text-secondary-dark",children:t.loginSource})]})]}),u&&i.jsx(de,{type:"button",variant:t.installed&&(a==null?void 0:a.state)!=="failed"?"secondary":"primary",size:"sm",icon:t.installed?an:vh,loading:l,onClick:()=>void c(),className:"shrink-0 self-start",children:l?"安装中…":h})]}),o&&i.jsx(tt,{variant:"error",size:"sm",className:"mt-3",children:o}),a&&i.jsx(Mye,{log:a.log}),(a==null?void 0:a.state)==="succeeded"&&i.jsx(tt,{variant:"success",size:"sm",className:"mt-3",title:"安装完成 / Installed",children:a.usedUserPrefix?"已安装到你的用户目录,不需要管理员权限。Installed to your user folder (no admin rights needed).":`${t.displayName} 已就绪。`}),(a==null?void 0:a.state)==="failed"&&!o&&i.jsx(tt,{variant:"error",size:"sm",className:"mt-3",title:"安装失败 / Install failed",children:"请查看上面的日志后重试。Check the log above and try again."})]})},jye="harness-choice",Y9=({harnesses:t,systemTools:e=[],selectedId:n,onSelect:s,onInstallFinished:r})=>{const a=e.filter(o=>!o.installed);return i.jsxs("div",{className:"space-y-3","data-testid":"harness-list",children:[i.jsx("div",{role:s?"radiogroup":void 0,"aria-label":s?"选择编程助手":void 0,className:"space-y-3",children:t.map(o=>i.jsx(Nye,{harness:o,selectName:s?jye:void 0,selected:s?n===o.id:!1,onSelect:s,onInstallFinished:()=>r==null?void 0:r()},o.id))}),a.map(o=>i.jsxs(tt,{variant:"warning",size:"sm",title:`缺少系统工具 ${o.id} / Missing ${o.id}`,children:[i.jsx("span",{children:"部分技能需要它。安装方法:"}),i.jsx("code",{className:"ml-1 rounded bg-background-dark px-1.5 py-0.5 font-mono text-xs",children:o.installHint})]},o.id))]})};function Rye(t,e,n){var r;const s=t.filter(a=>a.installed);for(const a of[e,n,K2])if(a&&s.some(o=>o.id===a))return a;return((r=s[0])==null?void 0:r.id)??null}const J9=({harnesses:t,value:e,onChange:n,disabled:s=!1})=>{const r=t.filter(a=>a.installed);return r.length===0?i.jsx(Cs,{compact:!0,icon:p0,title:"还没有安装任何编程助手",description:"先安装 Claude Code 或 Codex,再回来选择。Install a harness first."}):i.jsx("div",{role:"radiogroup","aria-label":"Orc 使用的编程助手",className:"space-y-2","data-testid":"orc-harness-picker",children:r.map(a=>{const o=e===a.id,l=V1[a.loginState];return i.jsxs("label",{className:`flex items-center justify-between gap-3 rounded-2xl border p-3 cursor-pointer transition-colors ${o?"border-primary bg-primary/10":"border-border-dark bg-surface-dark hover:border-primary/50"} ${s?"opacity-60 cursor-not-allowed":""}`,children:[i.jsxs("span",{className:"flex items-center gap-3 min-w-0",children:[i.jsx("input",{type:"radio",name:"orc-harness",value:a.id,checked:o,disabled:s,onChange:()=>n(a.id),className:"h-4 w-4 accent-[var(--crewly-primary)]"}),i.jsx("span",{className:"font-medium text-text-primary-dark truncate",children:a.displayName}),a.id===K2&&i.jsx("span",{className:"text-xs text-text-secondary-dark",children:"推荐"})]}),i.jsx(ft,{variant:l.variant,children:l.label})]},a.id)})})},Iye=({harnessId:t,label:e,onSaved:n})=>{const[s,r]=w.useState(""),[a,o]=w.useState(!1),[l,c]=w.useState(null),[d,u]=w.useState(!1),h=jte[t],f=async p=>{p.preventDefault();const x=s.trim();if(x){r(""),o(!0),c(null),u(!1);try{const y=await Eo.setApiKey(t,x);u(!0),n==null||n(y)}catch(y){c(y instanceof Error?y.message:"保存失败 / Save failed")}finally{o(!1)}}};return i.jsxs("form",{onSubmit:f,className:"space-y-3","data-testid":"api-key-form",children:[i.jsx(ys,{type:"password",label:e,name:`${t}-api-key`,autoComplete:"off",spellCheck:!1,placeholder:"sk-…",value:s,onChange:p=>r(p.target.value),fullWidth:!0}),i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[h?i.jsxs("a",{href:h.url,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-sm text-primary hover:underline underline-offset-2",children:["在 ",h.label," 获取 Key",i.jsx(ws,{className:"h-3.5 w-3.5"})]}):i.jsx("span",{}),i.jsx(de,{type:"submit",size:"sm",loading:a,disabled:!s.trim()||a,children:"保存 / Save"})]}),d&&i.jsx(tt,{variant:"success",size:"sm",children:"API Key 已保存。Key saved."}),l&&i.jsx(tt,{variant:"error",size:"sm",children:l})]})},Pye=new Set(["succeeded","failed","timed_out","cancelled"]);function $M(t){return Pye.has(t)}function Lye(t){return t.state==="awaiting_user"&&!t.url&&!t.userCode&&!t.needsInput}function Dye(t,e){const[n,s]=w.useState(null),[r,a]=w.useState(null),[o,l]=w.useState(!1),[c,d]=w.useState(0),u=w.useRef(e);u.current=e;const h=w.useRef(null),f=w.useCallback(async m=>{l(!0),a(null);try{s(await Eo.startLogin(t,m))}catch(g){a(g instanceof Error?g.message:String(g))}finally{l(!1)}},[t]),p=w.useCallback(async m=>{if(!n)return!1;l(!0),a(null);try{const g=await Eo.sendLoginInput(n.id,m);return g&&s(g),!0}catch(g){return a(g instanceof Error?g.message:String(g)),!1}finally{l(!1)}},[n]),x=w.useCallback(async()=>{if(n){l(!0);try{const m=await Eo.cancelLogin(n.id);s(m??{...n,state:"cancelled"})}catch(m){a(m instanceof Error?m.message:String(m))}finally{l(!1)}}},[n]),y=w.useCallback(()=>{s(null),a(null)},[]);return w.useEffect(()=>{if(!n||$M(n.state))return;let m=!1;const g=setTimeout(async()=>{try{const v=await Eo.getLoginSession(n.id);if(m)return;s(v),a(null)}catch(v){if(m)return;a(v instanceof Error?v.message:String(v)),d(b=>b+1)}},$2.LOGIN_POLL_MS);return()=>{m=!0,clearTimeout(g)}},[n,c]),w.useEffect(()=>{var m;(n==null?void 0:n.state)==="succeeded"&&h.current!==n.id&&(h.current=n.id,(m=u.current)==null||m.call(u))},[n]),{session:n,error:r,busy:o,start:f,sendInput:p,cancel:x,reset:y}}const Oye=new Set(["https:","http:"]);function Z9(t){if(!t)return!1;try{return Oye.has(new URL(t).protocol)}catch{return!1}}const Bye=({value:t,label:e="复制"})=>{const[n,s]=w.useState(!1),r=w.useRef(null);w.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]);const a=async()=>{try{await navigator.clipboard.writeText(t),s(!0),r.current&&clearTimeout(r.current),r.current=setTimeout(()=>s(!1),$2.COPIED_FEEDBACK_MS)}catch{}};return i.jsx(de,{type:"button",variant:"secondary",size:"sm",icon:n?Kn:w1,onClick:a,"aria-label":e,"data-testid":"copy-button",children:n?"已复制":e})},ZB=({label:t,submitLabel:e,busy:n,onSubmit:s,mono:r,testId:a})=>{const[o,l]=w.useState(""),c=async d=>{d.preventDefault();const u=o.trim();u&&await s(u)&&l("")};return i.jsxs("form",{onSubmit:c,className:"flex flex-col gap-2 sm:flex-row sm:items-end","data-testid":a,children:[i.jsx("div",{className:"flex-1 min-w-0",children:i.jsx(ys,{label:t,value:o,onChange:d=>l(d.target.value),autoComplete:"off",spellCheck:!1,className:r?"font-mono":void 0,fullWidth:!0})}),i.jsx(de,{type:"submit",loading:n,disabled:!o.trim()||n,className:"shrink-0",children:e})]})};function Fye(t){Z9(t)&&window.open(t,"_blank","noopener,noreferrer")}const Uye=({session:t,busy:e,sendInput:n})=>{const s=Z9(t.url)?t.url:null;return Lye(t)?i.jsxs("div",{className:"space-y-3","data-testid":"login-fallback",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"没能自动识别登录画面,请根据下面的终端内容操作。We couldn't read the login screen automatically."}),i.jsxs("details",{className:"rounded-2xl border border-border-dark bg-background-dark",open:!0,children:[i.jsx("summary",{className:"cursor-pointer px-3 py-2 text-sm font-medium text-text-primary-dark",children:"终端内容"}),i.jsx("pre",{className:"max-h-64 overflow-auto border-t border-border-dark p-3 font-mono text-xs text-text-secondary-dark whitespace-pre-wrap break-all","data-testid":"login-screen",children:t.screen||"(空)"})]}),i.jsx(ZB,{label:"发送到终端 / Send to terminal",submitLabel:"发送",busy:e,onSubmit:n,mono:!0,testId:"login-raw-input"})]}):i.jsxs("div",{className:"space-y-4",children:[s&&i.jsxs("div",{className:"space-y-2",children:[i.jsx(de,{type:"button",fullWidth:!0,icon:ws,onClick:()=>Fye(s),"data-testid":"login-open-url",children:"打开授权页面"}),i.jsx("p",{className:"text-xs text-text-secondary-dark break-all",children:s})]}),t.userCode&&i.jsxs("div",{className:"rounded-2xl border border-border-dark bg-background-dark p-4 text-center space-y-3","data-testid":"login-user-code",children:[i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"验证码 / One-time code"}),i.jsx("p",{className:"font-mono text-3xl font-bold tracking-widest text-text-primary-dark select-all break-all",children:t.userCode}),i.jsx(Bye,{value:t.userCode,label:"复制验证码"}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"在打开的页面输入这个验证码,完成后这里会自动继续"})]}),t.needsInput&&i.jsx(ZB,{label:"把页面上给你的代码粘贴到这里",submitLabel:"提交 / Submit",busy:e,onSubmit:n,testId:"login-code-input"})]})},zye=({harnessId:t,method:e,label:n,onSucceeded:s})=>{const{session:r,error:a,busy:o,start:l,sendInput:c,cancel:d}=Dye(t,s),u=w.useRef(null);if(u.current=r&&!$M(r.state)?r:null,w.useEffect(()=>()=>{u.current&&Eo.cancelLogin(u.current.id).catch(()=>{})},[]),!r)return i.jsxs("div",{className:"space-y-3",children:[i.jsx(de,{type:"button",fullWidth:!0,icon:tY,loading:o,onClick:()=>void l(e),"data-testid":"login-start",children:n}),a&&i.jsx(tt,{variant:"error",size:"sm",children:a})]});const h=r.state==="failed"||r.state==="timed_out",f=!$M(r.state);return i.jsxs("div",{className:"space-y-4","data-testid":"login-session","data-state":r.state,children:[(r.state==="starting"||r.state==="verifying")&&i.jsx(Ht,{size:"sm",inline:!0,text:kk[r.state]}),r.state==="awaiting_user"&&i.jsx(Uye,{session:r,busy:o,sendInput:c}),r.state==="awaiting_user"&&r.message&&i.jsx("p",{className:"text-sm text-text-secondary-dark",children:r.message}),r.state==="succeeded"&&i.jsx(tt,{variant:"success",size:"sm",title:"登录成功 / Signed in",children:r.message||"现在可以使用了。"}),h&&i.jsx(tt,{variant:"error",size:"sm",title:kk[r.state],children:r.message||"请重试。Please try again."}),r.state==="cancelled"&&i.jsx("p",{className:"text-sm text-text-secondary-dark",children:kk.cancelled}),a&&i.jsx(tt,{variant:"error",size:"sm",children:a}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[(h||r.state==="cancelled")&&i.jsx(de,{type:"button",icon:_2,loading:o,onClick:()=>void l(e),children:"重试 / Retry"}),f&&i.jsx(de,{type:"button",variant:"ghost",size:"sm",disabled:o,onClick:()=>void d(),children:"取消 / Cancel"})]})]})},Q9=({harness:t,onLoggedIn:e,onHarnessUpdated:n})=>{var f;const s=t.loginMethods,[r,a]=w.useState(((f=s[0])==null?void 0:f.id)??null),[o,l]=w.useState(!1),c=V1[t.loginState],d=s.find(p=>p.id===r)??s[0],u=t.installed&&s.length>0&&(t.loginState!=="logged_in"||o),h=()=>t.installed?s.length===0?i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["暂不支持在网页登录 ",t.displayName,",请在终端里完成登录。Browser login isn't available for this harness yet."]}):u?i.jsxs("div",{className:"space-y-4",children:[s.length>1&&i.jsx(ao,{"aria-label":"登录方式 / Login method",fullWidth:!0,size:"sm",value:d.id,onChange:a,options:s.map(p=>({value:p.id,label:Ck(t.id,p.id,p.label)}))}),d.kind==="api_key"?i.jsx(Iye,{harnessId:t.id,label:Ck(t.id,d.id,d.label),onSaved:p=>{l(!1),n==null||n(p)}},`${t.id}-${d.id}`):i.jsx(zye,{harnessId:t.id,method:d.id==="device"?"device":"subscription",label:Ck(t.id,d.id,d.label),onSucceeded:()=>e==null?void 0:e()},`${t.id}-${d.id}`)]}):i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:[t.loginSource?`已通过 ${t.loginSource} 登录。`:"已登录。","登录过期时可以在这里重新登录。"]}),i.jsx(de,{type:"button",variant:"secondary",size:"sm",onClick:()=>l(!0),children:"重新登录 / Re-login"})]}):i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["请先安装 ",t.displayName,"。Install it first."]});return i.jsxs(dt,{padding:"md","data-testid":`harness-login-card-${t.id}`,children:[i.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-2",children:[i.jsxs("h3",{className:"font-semibold text-text-primary-dark",children:["登录 ",t.displayName]}),t.installed&&i.jsx(ft,{variant:c.variant,children:c.label})]}),h()]})},QE=({title:t,subtitle:e})=>i.jsxs("div",{className:"mb-3",children:[i.jsx("h2",{className:"text-lg font-semibold text-text-primary-dark",children:t}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:e})]}),Hye=()=>{const{overview:t,loading:e,error:n,refresh:s,setOrcHarness:r,savingOrc:a,replaceHarness:o}=X9();if(e)return i.jsx(Ht,{centered:!0,text:"正在检查编程助手…","data-testid":"harness-tab-loading"});if(!t)return i.jsx(tt,{variant:"error",title:"无法读取编程助手状态 / Couldn't load harness status",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:n}),i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:()=>void s(),children:"重试 / Retry"})]})});const l=t.harnesses.filter(c=>c.installed).sort((c,d)=>+(d.id===t.orcHarness)-+(c.id===t.orcHarness));return i.jsxs("div",{className:"space-y-8 max-w-3xl","data-testid":"harness-tab",children:[n&&i.jsx(tt,{variant:"error",size:"sm",children:n}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-start justify-between gap-3",children:[i.jsx(QE,{title:"编程助手",subtitle:"Coding harnesses installed on this machine"}),i.jsx(de,{type:"button",size:"sm",variant:"ghost",icon:an,onClick:()=>void s(),children:"刷新"})]}),i.jsx(Y9,{harnesses:t.harnesses,systemTools:t.systemTools,onInstallFinished:()=>void s()})]}),i.jsxs("section",{children:[i.jsx(QE,{title:"Orc 使用的编程助手",subtitle:"Which harness the orchestrator runs on"}),i.jsx(J9,{harnesses:t.harnesses,value:t.orcHarness,onChange:c=>void r(c),disabled:a})]}),l.length>0&&i.jsxs("section",{children:[i.jsx(QE,{title:"登录",subtitle:"Sign in again here when a login expires"}),i.jsx("div",{className:"space-y-3",children:l.map(c=>i.jsx(Q9,{harness:c,onLoggedIn:()=>void s(),onHarnessUpdated:o},c.id))})]})]})},Gye=new Set(["general","harness","roles","skills","integrations","api-keys","credentials","system"]),Wye=()=>{const[t]=xh(),e=ms(),n=t.get("tab");w.useEffect(()=>{n==="cloud"&&e("/cloud",{replace:!0})},[n,e]);const s=n==="slack"?"integrations":n&&Gye.has(n)?n:"general",r=[{id:"general",label:"General",icon:zz},{id:"harness",label:"Harness",icon:p0},{id:"roles",label:"Roles",icon:Yp},{id:"skills",label:"Skills",icon:qz},{id:"integrations",label:"Integrations",icon:Gl},{id:"api-keys",label:"API Keys",icon:G_},{id:"credentials",label:"Credentials",icon:W_},{id:"system",label:"System",icon:io}],a=o=>{switch(o){case"general":return i.jsx(G0e,{});case"harness":return i.jsx(Hye,{});case"roles":return i.jsx(q0e,{});case"skills":return i.jsx(Z0e,{});case"integrations":return i.jsx(aye,{});case"api-keys":return i.jsx(lye,{});case"credentials":return i.jsx(hye,{});case"system":return i.jsx(Cye,{});default:return null}};return i.jsxs("div",{className:"max-w-7xl mx-auto",children:[i.jsxs("div",{className:"mb-8",children:[i.jsx("h1",{className:"text-3xl font-bold tracking-tight",children:"Settings"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Configure Crewly behavior and manage roles and skills"})]}),i.jsxs(Zp,{defaultValue:s,children:[i.jsx(Qp,{className:"overflow-x-auto",children:r.map(o=>i.jsx(Qa,{value:o.id,icon:i.jsx(o.icon,{className:"w-4 h-4"}),children:i.jsx("span",{children:o.label})},o.id))}),r.map(o=>i.jsx(Cp,{value:o.id,children:a(o.id)},o.id))]})]})};function Pw(t){if(t!=null)return new Date(t).toISOString()}function vR(t){return t==="starting"?"online":t}function Vye(t,e){return t==="system"?"System":e}function $ye(t){if(!t)return;const e=t.clientMessageId;return typeof e=="string"&&e.length>0?e:void 0}function eA(t){return{id:t.id,agentSession:t.agentSession,name:t.name,purpose:t.purpose,createdAt:new Date(t.createdAt).toISOString(),lastMessageAt:Pw(t.lastMessageAt),presence:vR(t.agentPresence.status),type:t.type??"dm",teamId:t.teamId,projectId:t.projectId,targetMemberId:t.targetMemberId}}function Kye(t){return{id:t.id,kind:"image",url:t.url,filename:t.originalName,size:t.sizeBytes,mimeType:t.mimeType}}function KM(t){var e;return{id:t.id,channelId:t.channelId,seq:t.seq,author:{role:t.senderType,id:t.senderId,name:Vye(t.senderType,t.senderId)},content:t.content,attachments:(e=t.attachments)==null?void 0:e.map(Kye),createdAt:new Date(t.createdAt).toISOString(),clientMessageId:$ye(t.metadata),deliveryStatus:"sent",mentions:Array.isArray(t.mentions)?t.mentions:[],threadId:t.threadId,replyCount:typeof t.replyCount=="number"?t.replyCount:void 0,lastReplyAt:Pw(t.lastReplyAt)}}function qye(t){return{agentId:t.agentSession,status:vR(t.status),lastSeen:Pw(t.lastSeenAt)}}function Xye(t){if(!t||typeof t!="object")return null;const e=t;if(e.type==="message"){const n=t.payload;return!n||typeof n.channelId!="string"||!n.message?null:{type:"message",channelId:n.channelId,message:KM(n.message)}}if(e.type==="presence"){const n=t.payload;return!n||typeof n.agentSession!="string"||typeof n.status!="string"?null:{type:"presence",agentSession:n.agentSession,status:vR(n.status),lastSeen:Pw(n.lastSeenAt??null)}}if(e.type==="pong"){const n=t.ts;return{type:"pong",ts:typeof n=="number"?n:0}}if(e.type==="error"){const n=t.code,s=t.message;return{type:"error",code:typeof n=="string"?n:"unknown",message:typeof s=="string"?s:""}}return null}const Yye=["validation_error","not_found","channel_not_found","agent_not_found","forbidden","agent_already_bound","payload_too_large","rate_limited","invalid_cursor","channel_archived","attachment_not_found","internal_error","network_error","unknown_error"];class s0 extends Error{constructor(n){super(n.message);On(this,"code");On(this,"httpStatus");On(this,"details");this.name="ChatApiError",this.code=n.code,this.httpStatus=n.httpStatus,this.details=n.details}static async fromResponse(n){let s;try{s=await n.json()}catch{s=void 0}if(s&&typeof s=="object"&&"error"in s&&s.error&&typeof s.error=="object"){const r=s.error,a=Jye(r.code),o=typeof r.message=="string"?r.message:`Chat API error ${n.status}`,l=r.details&&typeof r.details=="object"?r.details:void 0;return new s0({code:a,httpStatus:n.status,message:o,details:l})}return new s0({code:"unknown_error",httpStatus:n.status,message:`Chat API error ${n.status}`})}}function Jye(t){return typeof t!="string"?"unknown_error":Yye.includes(t)?t:"unknown_error"}const Zye={id:"__me__",name:"You"},Qye=25e3,eve=1e4,tve=1e3;function nve(){const t=globalThis;return t.crypto&&typeof t.crypto.randomUUID=="function"?t.crypto.randomUUID():`cmid-${Math.random().toString(16).slice(2)}-${Date.now().toString(16)}`}class sve{constructor(e){On(this,"backendURL");On(this,"authToken");On(this,"fetchImpl");On(this,"websocketImpl");On(this,"idGenerator");On(this,"currentUser");On(this,"heartbeatIntervalMs");On(this,"pongTimeoutMs");On(this,"reconnectDelayMs");On(this,"now");On(this,"localSubscribers",new Set);this.backendURL=e.backendURL.replace(/\/+$/,""),this.authToken=e.authToken,this.fetchImpl=e.fetchImpl??(typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):void 0),this.websocketImpl=e.websocketImpl??globalThis.WebSocket,this.idGenerator=e.idGenerator??nve,this.currentUser=e.currentUser??Zye,this.heartbeatIntervalMs=e.heartbeatIntervalMs??Qye,this.pongTimeoutMs=e.pongTimeoutMs??eve,this.reconnectDelayMs=e.reconnectDelayMs??tve,this.now=e.now??Date.now}headers(e){const n={"Content-Type":"application/json",...e};return this.authToken&&(n.Authorization=`Bearer ${this.authToken}`),n}async request(e,n){let s;try{s=await this.fetchImpl(`${this.backendURL}${e}`,{...n,headers:this.headers(n==null?void 0:n.headers)})}catch(a){throw new s0({code:"network_error",httpStatus:0,message:a instanceof Error?a.message:String(a)})}if(!s.ok)throw await s0.fromResponse(s);return(await s.json()).data}async listChannels(){return(await this.request("/api/chat/channels")).channels.map(eA)}async createChannel(e){const n=await this.request("/api/chat/channels",{method:"POST",body:JSON.stringify(e)});return eA(n)}async createHuddle(e){const n=await this.request("/api/chat/channels/huddle",{method:"POST",body:JSON.stringify(e)});return eA(n)}async listMessages(e,n={}){const s=new URLSearchParams;n.cursor&&s.set("cursor",n.cursor),n.limit&&s.set("limit",String(n.limit));const r=s.toString()?`?${s.toString()}`:"",a=await this.request(`/api/chat/channels/${encodeURIComponent(e)}/messages${r}`);return{messages:a.messages.map(KM),nextCursor:a.nextCursor}}async sendMessage(e,n){const s=n.clientMessageId??this.idGenerator(),r=this.buildOptimisticMessage(e,n,s);this.emitLocal(e,{type:"message",channelId:e,message:r});const a={content:n.content,contentType:"markdown",clientMessageId:s};n.mentions&&n.mentions.length>0&&(a.mentions=n.mentions),n.threadId&&(a.threadId=n.threadId);let o;try{o=await this.request(`/api/chat/channels/${encodeURIComponent(e)}/messages`,{method:"POST",body:JSON.stringify(a)})}catch(c){throw this.emitLocal(e,{type:"message",channelId:e,message:{...r,deliveryStatus:"failed"}}),c}const l=KM(o);return l.clientMessageId||(l.clientMessageId=s),this.emitLocal(e,{type:"message",channelId:e,message:l}),l}async getAgentPresence(e){const n=await this.request(`/api/chat/presence/${encodeURIComponent(e)}`);return qye(n)}subscribeToChannel(e,n){const s={channelId:e,onEvent:n};this.localSubscribers.add(s);const r=this.openWebsocketConnection(e,n);return{unsubscribe:()=>{this.localSubscribers.delete(s),r.close()}}}buildOptimisticMessage(e,n,s){return{id:s,channelId:e,seq:-1,author:{role:"user",id:this.currentUser.id,name:this.currentUser.name},content:n.content,attachments:n.attachments,createdAt:new Date(this.now()).toISOString(),clientMessageId:s,deliveryStatus:"pending",mentions:n.mentions??[],threadId:n.threadId}}emitLocal(e,n){for(const s of this.localSubscribers)if(s.channelId===e)try{s.onEvent(n)}catch{}}openWebsocketConnection(e,n){let s=null,r=null,a=null,o=null,l=0,c=!1;const d=()=>{r&&(clearInterval(r),r=null),a&&(clearTimeout(a),a=null),o&&(clearTimeout(o),o=null)},u=()=>{if(s)try{(s.readyState===s.OPEN||s.readyState===s.CONNECTING)&&s.close()}catch{}},h=()=>{c||(d(),o=setTimeout(()=>{o=null,p()},this.reconnectDelayMs))},f=()=>{if(!(!s||s.readyState!==s.OPEN)){try{s.send(JSON.stringify({type:"ping",ts:this.now()}))}catch{return}a&&clearTimeout(a),a=setTimeout(()=>{u()},this.pongTimeoutMs)}},p=()=>{if(c)return;const x=this.backendURL.replace(/^http/,"ws"),y=new URLSearchParams({channelId:e});this.authToken&&y.set("token",this.authToken),l>0&&y.set("lastSeenSeq",String(l));try{s=new this.websocketImpl(`${x}/ws/chat?${y.toString()}`)}catch{h();return}const m=b=>{let S;try{S=JSON.parse(typeof b.data=="string"?b.data:"")}catch{return}const k=Xye(S);if(k){if(k.type==="pong"){a&&(clearTimeout(a),a=null),n(k);return}if(k.type==="message"&&k.message.seq>l&&(l=k.message.seq),k.type==="error"){n(k),c=!0,d(),u();return}n(k)}},g=()=>{r&&clearInterval(r),r=setInterval(f,this.heartbeatIntervalMs)},v=()=>{h()};s.addEventListener("message",m),s.addEventListener("open",g),s.addEventListener("close",v)};return p(),{close(){c=!0,d(),u()}}}}const QB="demo-user",e4="Steve",rve=800,ive=()=>{let t=1;return e=>`${e}-${t++}`};class ave{constructor(e={}){On(this,"channels");On(this,"messages");On(this,"subscribers",{});On(this,"replyDelay");On(this,"nextId",ive());this.channels=e.initialChannels??ove(),this.messages=e.initialMessages??lve(this.channels),this.replyDelay=e.agentReplyDelayMs??rve}async listChannels(){return[...this.channels]}async createChannel(e){const n=e.type??"dm",s={id:this.nextId("ch"),agentSession:n==="dm"?e.agentSession??"":"",name:e.name,purpose:e.purpose,createdAt:new Date().toISOString(),presence:"online",type:n,teamId:e.teamId,projectId:e.projectId,targetMemberId:e.targetMemberId};return this.channels=[...this.channels,s],this.messages[s.id]=[],s}async createHuddle(e){const n={id:this.nextId("ch"),agentSession:"",name:e.name,purpose:e.purpose,createdAt:new Date().toISOString(),presence:"online",type:"huddle"};return this.channels=[...this.channels,n],this.messages[n.id]=[],n}async listMessages(e,n={}){const s=this.messages[e]??[],r=n.limit??50;return{messages:s.slice(-r),nextCursor:s.length>r?"mock-older":null}}async sendMessage(e,n){var d,u;const s=this.channels.find(h=>h.id===e);if(!s)throw new Error(`Unknown channel: ${e}`);const r=n.clientMessageId??this.nextId("cmid"),a=n.mentions??[],o=n.threadId,l={id:r,channelId:e,seq:-1,author:{role:"user",id:QB,name:e4},content:n.content,attachments:n.attachments,createdAt:new Date().toISOString(),clientMessageId:r,deliveryStatus:"pending",mentions:a,threadId:o};this.emit(e,{type:"message",channelId:e,message:l});const c={id:this.nextId("m"),channelId:e,seq:(((d=this.messages[e])==null?void 0:d.length)??0)+1,author:{role:"user",id:QB,name:e4},content:n.content,attachments:n.attachments,createdAt:l.createdAt,clientMessageId:r,deliveryStatus:"sent",mentions:a,threadId:o};return((u=this.messages)[e]||(u[e]=[])).push(c),this.emit(e,{type:"message",channelId:e,message:c}),window.setTimeout(()=>{var f,p;const h={id:this.nextId("m"),channelId:e,seq:(((f=this.messages[e])==null?void 0:f.length)??0)+1,author:{role:"agent",id:s.agentSession,name:s.name},content:`(mock reply) you said: "${n.content}"`,createdAt:new Date().toISOString(),deliveryStatus:"sent",mentions:[],threadId:o};((p=this.messages)[e]||(p[e]=[])).push(h),this.emit(e,{type:"message",channelId:e,message:h})},this.replyDelay),c}async getAgentPresence(e){const n=this.channels.find(s=>s.agentSession===e);return{agentId:e,status:(n==null?void 0:n.presence)??"offline",lastSeen:new Date().toISOString()}}subscribeToChannel(e,n){var s;return((s=this.subscribers)[e]||(s[e]=[])).push(n),{unsubscribe:()=>{const r=this.subscribers[e];r&&(this.subscribers[e]=r.filter(a=>a!==n))}}}emit(e,n){const s=this.subscribers[e];if(s)for(const r of s)try{r(n)}catch{}}}function ove(){const t=new Date().toISOString();return[{id:"ch-ella",agentSession:"crewly-marketing-ella",name:"Ella · Marketing",purpose:"Marketing strategy + content planning",createdAt:t,lastMessageAt:t,presence:"online",type:"dm"},{id:"ch-sam",agentSession:"crewly-product-sam",name:"Sam · Engineering",purpose:"Platform architecture + delivery",createdAt:t,lastMessageAt:t,presence:"busy",type:"dm"},{id:"ch-offline",agentSession:"crewly-offline-demo",name:"Dormant Agent",purpose:"Shows the offline state",createdAt:t,presence:"offline",type:"dm"}]}function lve(t){var n;const e={};for(const s of t)e[s.id]=[{id:`${s.id}-welcome`,channelId:s.id,seq:1,author:{role:"agent",id:s.agentSession,name:s.name},content:`Welcome — I'm **${((n=s.name.split("·")[0])==null?void 0:n.trim())??s.name}**. Ask me anything.`,createdAt:s.createdAt,mentions:[]}];return e}const e7=w.createContext(null);function cve({children:t,backendURL:e,authToken:n,mode:s="real",client:r}){const a=w.useMemo(()=>{if(r)return{client:r,mode:s};if(s==="mock")return{client:new ave,mode:s};if(!e)throw new Error('[@crewly/chat-ui] ChatAPIProvider requires `backendURL` when mode="real".');return{client:new sve({backendURL:e,authToken:n}),mode:s}},[e,n,s,r]);return i.jsx(e7.Provider,{value:a,children:t})}function hm(){const t=w.useContext(e7);if(!t)throw new Error("[@crewly/chat-ui] useChatApiClient must be called inside <ChatAPIProvider>.");return t.client}function dve(t,e){const n=hm(),[s,r]=w.useState("offline"),[a,o]=w.useState(void 0),[l,c]=w.useState(!!t),[d,u]=w.useState(null);return w.useEffect(()=>{if(!t){r("offline"),c(!1);return}let h=!1;return c(!0),u(null),n.getAgentPresence(t).then(f=>{h||(r(f.status),o(f.lastSeen))}).catch(f=>{h||u(f instanceof Error?f:new Error(String(f)))}).finally(()=>{h||c(!1)}),()=>{h=!0}},[t,n]),w.useEffect(()=>{if(!t||!e)return;const h=n.subscribeToChannel(e,f=>{f.type==="presence"&&f.agentSession===t&&(r(f.status),o(f.lastSeen))});return()=>h.unsubscribe()},[t,e,n]),{status:s,lastSeen:a,loading:l,error:d}}const uve={online:"online",busy:"busy",idle:"idle",offline:"offline",inactive:"inactive"},t4={online:"Online",busy:"Busy",idle:"Idle",offline:"Offline",inactive:"Inactive"},hve={online:"bg-emerald-400",busy:"bg-amber-400",idle:"bg-amber-400",offline:"bg-text-secondary-dark/50",inactive:"bg-text-secondary-dark/50"},fve={online:"text-emerald-400",busy:"text-amber-400",idle:"text-amber-400",offline:"text-text-secondary-dark",inactive:"text-text-secondary-dark"};function pve({status:t,agentId:e,channelId:n,compact:s=!1,className:r=""}){const a=mve({status:t,agentId:e,channelId:n});return i.jsxs("span",{className:`inline-flex items-center gap-1.5 ${r}`,"data-testid":"agent-status-badge","data-status":a,children:[i.jsx("span",{"aria-hidden":"true",className:`inline-block h-2 w-2 rounded-full ${hve[a]}`}),!s&&i.jsx("span",{className:`text-xs font-medium ${fve[a]}`,children:t4[a]}),i.jsx("span",{className:"sr-only",children:t4[a]})]})}function mve(t){const e=dve(t.status?null:t.agentId??null,t.channelId??null),n=t.status??e.status;return uve[n]}function gve(){const t=hm(),[e,n]=w.useState([]),[s,r]=w.useState(!0),[a,o]=w.useState(null),l=w.useCallback(async()=>{r(!0),o(null);try{const c=await t.listChannels();n(c)}catch(c){o(c instanceof Error?c:new Error(String(c)))}finally{r(!1)}},[t]);return w.useEffect(()=>{l()},[l]),{channels:e,loading:s,error:a,refresh:l}}function t7(t,e){if(e.clientMessageId){const s=t.findIndex(r=>r.clientMessageId&&r.clientMessageId===e.clientMessageId);if(s>=0){const r=t.slice();return r[s]=e,r}}const n=t.findIndex(s=>s.id===e.id);if(n>=0){const s=t.slice();return s[n]=e,s}return[...t,e]}function n4(t){return[...t].sort((e,n)=>e.seq-n.seq)}function xve(t,e){return t.filter(n=>n.threadId===e).sort((n,s)=>n.seq-s.seq)}function qM(t){if(t.length===0)return!1;const e=t[t.length-1];return e.author.role!=="user"?!1:!!e.clientMessageId}function n7(t){const e=hm(),[n,s]=w.useState([]),[r,a]=w.useState(!1),[o,l]=w.useState(null),c=w.useRef(null),[d,u]=w.useState(!1),[h,f]=w.useState(!1);w.useEffect(()=>{if(!t){s([]),u(!1),f(!1);return}let y=!1;return a(!0),l(null),c.current=null,f(!1),e.listMessages(t).then(m=>{y||(s(n4(m.messages)),c.current=m.nextCursor,u(m.nextCursor!==null))}).catch(m=>{y||l(m instanceof Error?m:new Error(String(m)))}).finally(()=>{y||a(!1)}),()=>{y=!0}},[t,e]),w.useEffect(()=>{if(!t)return;const y=e.subscribeToChannel(t,m=>{m.type==="message"&&s(g=>{const v=t7(g,m.message);return f(qM(v)),v})});return()=>y.unsubscribe()},[t,e]);const p=w.useCallback(async()=>{if(!t||!c.current)return;const y=c.current;try{const m=await e.listMessages(t,{cursor:y});s(g=>[...n4(m.messages),...g]),c.current=m.nextCursor,u(m.nextCursor!==null)}catch(m){l(m instanceof Error?m:new Error(String(m)))}},[t,e]),x=w.useCallback(async y=>{if(!t)throw new Error("sendMessage called without an active channel.");return await e.sendMessage(t,y)},[t,e]);return{messages:n,loading:r,error:o,hasMore:d,agentThinking:h,loadMore:p,sendMessage:x}}function s7(t){const e=t.replace(/\r\n/g,`
4916
+ }`,className:"text-xs font-mono",spellCheck:!1}),i.jsxs("p",{className:"text-xs text-text-secondary-dark mt-1",children:["Copy the entire block from the opening ",i.jsx("code",{children:"{"})," to the closing ",i.jsx("code",{children:"}"}),"."]})]}),y&&i.jsx(tt,{variant:"error",children:y}),i.jsxs("div",{className:"flex justify-between items-center pt-2",children:[i.jsx(de,{type:"button",variant:"ghost",size:"xs",onClick:()=>{r("configure"),x(""),m(null),f(null)},children:"← Back (change scope)"}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:T,children:"Save credential"})]})]})]}),s==="saving"&&i.jsx(Ht,{size:"xs",inline:!0,text:"Saving credential…",className:"py-8"})]})},gye=({onClose:t,onImport:e,onClearExtensionFile:n})=>{const[s,r]=w.useState("name"),[a,o]=w.useState(""),[l,c]=w.useState(null),[d]=w.useState(null),[u,h]=w.useState(!1),f=()=>{if(!a.trim()){c('Please provide a name (e.g. "info-steam-fun", "personal-gmail")');return}c(null),r("instructions")},p=async()=>{c(null),r("importing");try{await e(a.trim()),r("done")}catch(m){c(m instanceof Error?m.message:"Import failed"),r("instructions")}},x=async()=>{h(!0);try{await n(),r("name"),o("")}catch(m){c(m instanceof Error?m.message:"Failed to clear extension file")}finally{h(!1)}},y=s==="done"?"Google account added":"Import from Gemini CLI";return i.jsxs(Kr,{isOpen:!0,onClose:t,title:y,size:"lg",children:[s==="name"&&i.jsxs("div",{className:"space-y-4",children:[i.jsxs(tt,{variant:"info",children:["This option is for developers who already run the Gemini CLI workspace extension locally. For the regular flow, close this and click ",i.jsx("strong",{children:"Add Google Account"}),"."]}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Pick a name for this Google account. You'll use this name to tell agents which account to use for a task."}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"cred-gemcli-name",children:"Name"}),i.jsx(Ut,{id:"cred-gemcli-name",type:"text",value:a,onChange:m=>o(m.target.value),placeholder:"e.g. info-steam-fun, personal-gmail",autoFocus:!0})]}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:f,children:"Next"})]})]}),s==="instructions"&&i.jsxs("div",{className:"space-y-4",children:[i.jsx(tt,{variant:"info",children:"You'll sign in via the Gemini CLI Workspace extension. Crewly will then copy the resulting tokens into its own encrypted store."}),i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"1. Open a terminal and run:"}),i.jsx("pre",{className:"bg-surface-dark border border-border-dark rounded p-3 text-xs font-mono overflow-x-auto",children:"GEMINI_CLI_WORKSPACE_FORCE_FILE_STORAGE=true gemini"})]}),i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"2. Inside gemini, type:"}),i.jsx("pre",{className:"bg-surface-dark border border-border-dark rounded p-3 text-xs font-mono overflow-x-auto",children:"list my calendar events for today"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"This triggers the workspace extension to open a browser for Google sign-in."})]}),i.jsxs("div",{children:[i.jsxs("div",{className:"text-sm font-medium mb-1",children:["3. In the browser: sign in as ",i.jsx("span",{className:"font-mono",children:a})]}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"Grant the requested scopes. You can close the browser after the success page appears."})]}),i.jsxs("div",{children:[i.jsx("div",{className:"text-sm font-medium mb-1",children:"4. Come back here and click Import."}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"Crewly will read the extension's token file and save an encrypted copy."})]})]}),i.jsxs("a",{href:"https://github.com/gemini-cli-extensions/workspace",target:"_blank",rel:"noreferrer",className:"text-xs text-primary inline-flex items-center gap-1 hover:underline",children:["About the workspace extension ",i.jsx(ws,{className:"w-3 h-3"})]}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Cancel"}),i.jsx(de,{variant:"primary",onClick:p,children:"Import"})]})]}),s==="importing"&&i.jsx(Ht,{size:"xs",inline:!0,centered:!1,text:"Reading the extension's token file…",className:"py-4"}),s==="done"&&i.jsxs("div",{className:"space-y-4",children:[i.jsxs(tt,{variant:"success",children:["Google account ",i.jsx("strong",{children:a})," added.",d&&i.jsxs(i.Fragment,{children:[" (",d,")"]})]}),i.jsx("div",{className:"text-sm text-text-secondary-dark",children:"To add another Google account, Crewly needs to clear the extension's cached token so your next sign-in captures a different account."}),l&&i.jsx(tt,{variant:"error",children:l}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(de,{variant:"secondary",onClick:t,children:"Done"}),i.jsx(de,{variant:"primary",onClick:x,disabled:u,children:u?"Clearing…":"Add another account"})]})]})]})},xye=1e4;function yye(t){const e=[];for(const n of t)for(const s of n.members)e.push({memberId:s.id,name:s.name,sessionName:s.sessionName,role:s.role,teamName:n.name,teamId:n.id,agentStatus:s.agentStatus,workingStatus:s.workingStatus,readyAt:s.readyAt??null,lastActivityCheck:s.lastActivityCheck??null,runtimeType:s.runtimeType});return e}function vye(){const[t,e]=w.useState([]),[n,s]=w.useState(!0),[r,a]=w.useState(null),o=w.useRef(!0),l=w.useCallback(async()=>{try{const d=await yt.getTeams(!0);o.current&&(e(yye(d)),a(null))}catch(d){o.current&&a(d instanceof Error?d.message:"Failed to fetch agent heartbeats")}},[]),c=w.useCallback(async()=>{await l()},[l]);return w.useEffect(()=>{o.current=!0,(async()=>{await l(),o.current&&s(!1)})();const u=setInterval(l,xye);return()=>{o.current=!1,clearInterval(u)}},[l]),{agents:t,isLoading:n,error:r,refresh:c}}const bye={active:{label:"Active",color:"text-green-400",bgColor:"bg-green-500/10"},started:{label:"Started",color:"text-blue-400",bgColor:"bg-blue-500/10"},starting:{label:"Starting",color:"text-yellow-400",bgColor:"bg-yellow-500/10"},activating:{label:"Activating",color:"text-yellow-400",bgColor:"bg-yellow-500/10"},inactive:{label:"Offline",color:"text-text-secondary-dark",bgColor:"bg-text-secondary-dark/10"},suspended:{label:"Suspended",color:"text-red-400",bgColor:"bg-red-500/10"}};function _ye(t){return t?Hx(t):"Never"}const Sye=({agent:t})=>{const e=bye[t.agentStatus],n=t.agentStatus==="active"||t.agentStatus==="started";return i.jsxs(dt,{variant:"outlined",className:"hover:bg-surface-dark/30 transition-colors",children:[i.jsxs("div",{className:"flex items-start justify-between mb-3",children:[i.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[i.jsx("div",{className:`w-2 h-2 rounded-full shrink-0 ${n?"bg-green-400":"bg-text-secondary-dark"}`}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark truncate",children:t.name})]}),i.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium shrink-0 ${e.bgColor} ${e.color}`,children:e.label})]}),i.jsxs("div",{className:"space-y-2 text-xs",children:[i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Role"}),i.jsx("span",{className:"text-text-primary-dark capitalize",children:t.role})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Team"}),i.jsx("span",{className:"text-text-primary-dark truncate ml-2",children:t.teamName})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Working"}),i.jsx("span",{className:t.workingStatus==="in_progress"?"text-yellow-400":"text-text-secondary-dark",children:t.workingStatus==="in_progress"?"In Progress":"Idle"})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Runtime"}),i.jsx("span",{className:"text-text-primary-dark",children:t.runtimeType})]}),i.jsxs("div",{className:"flex justify-between items-center",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Connection"}),n?i.jsx(w2,{className:"w-3.5 h-3.5 text-green-400"}):i.jsx(yY,{className:"w-3.5 h-3.5 text-text-secondary-dark"})]})]}),i.jsxs("div",{className:"mt-3 pt-3 border-t border-border-dark flex justify-between text-xs",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Last active"}),i.jsx("span",{className:"text-text-secondary-dark",children:_ye(t.lastActivityCheck??t.readyAt)})]})]})},wye=()=>{const{agents:t,isLoading:e,error:n,refresh:s}=vye(),r=t.filter(a=>a.agentStatus==="active"||a.agentStatus==="started").length;return e?i.jsx("div",{className:"flex items-center justify-center py-12",children:i.jsx(Ht,{size:"sm",text:"Loading heartbeat status..."})}):n?i.jsxs("div",{className:"flex items-center gap-2 p-4 rounded-lg bg-red-500/10 border border-red-500/20",children:[i.jsx(Li,{className:"w-5 h-5 text-red-400 shrink-0"}),i.jsx("span",{className:"text-sm text-red-400",children:n})]}):i.jsxs("div",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-4",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(dl,{className:"w-5 h-5 text-text-secondary-dark"}),i.jsx("h3",{className:"text-lg font-semibold text-text-primary-dark",children:"Agent Heartbeat"}),i.jsxs("span",{className:"text-xs text-text-secondary-dark bg-surface-dark px-2 py-0.5 rounded-full",children:[r,"/",t.length," online"]})]}),i.jsx(de,{variant:"ghost",size:"sm",onClick:s,icon:an,children:"Refresh"})]}),t.length===0?i.jsxs("div",{className:"text-center py-12 text-text-secondary-dark",children:[i.jsx(dl,{className:"w-10 h-10 mx-auto mb-3 opacity-40"}),i.jsx("p",{className:"text-sm",children:"No agents found"}),i.jsx("p",{className:"text-xs mt-1 opacity-60",children:"Agent heartbeats will appear when teams have members configured"})]}):i.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:t.map(a=>i.jsx(Sye,{agent:a},`${a.teamId}-${a.memberId}`))})]})},Cye=()=>i.jsx("div",{className:"space-y-8",children:i.jsx(wye,{})});function kye(t,e,n){if(t!=null&&t.success&&n)return t.data??null;if(!t||!t.success||t.data===void 0||t.data===null)throw new Error((t==null?void 0:t.error)||(t==null?void 0:t.message)||e);return t.data}async function Fl(t,e,n=!1){var s;try{const r=await t();return kye(r.data,e,n)}catch(r){if(U1(r)){const a=(s=r.response)==null?void 0:s.data;throw new Error((a==null?void 0:a.error)||(a==null?void 0:a.message)||r.message||e)}throw r instanceof Error?r:new Error(e)}}function JB(t){return t&&typeof t=="object"&&"id"in t&&"state"in t?t:null}class Eye{async getStatus(){return Fl(()=>Ge.get(Nl.STATUS),"Failed to load harness status")}async startInstall(e){return(await Fl(()=>Ge.post(Nl.install(e)),"Failed to start install")).jobId}async getInstallJob(e){return Fl(()=>Ge.get(Nl.installJob(e)),"Failed to read install progress")}async setOrcHarness(e){return(await Fl(()=>Ge.put(Nl.ORC,{harnessId:e}),"Failed to save orchestrator harness")).orcHarness}async startLogin(e,n){return Fl(()=>Ge.post(Nl.login(e),{method:n,force:!0}),"Failed to start login")}async getLoginSession(e){return Fl(()=>Ge.get(Nl.loginSession(e)),"Failed to read login status")}async sendLoginInput(e,n){const s=await Fl(()=>Ge.post(Nl.loginInput(e),{text:n}),"Failed to send input",!0);return JB(s)}async cancelLogin(e){const n=await Fl(()=>Ge.post(Nl.loginCancel(e)),"Failed to cancel login",!0);return JB(n)}async setApiKey(e,n){return Fl(()=>Ge.post(Nl.apiKey(e),{key:n}),"Failed to save API key")}}const Eo=new Eye;function Aye(t){const e=n=>{const s=A3.indexOf(n);return s===-1?A3.length:s};return[...t].sort((n,s)=>e(n.id)-e(s.id))}function X9(){const[t,e]=w.useState(null),[n,s]=w.useState(!0),[r,a]=w.useState(null),[o,l]=w.useState(!1),c=w.useRef(!0);w.useEffect(()=>(c.current=!0,()=>{c.current=!1}),[]);const d=w.useCallback(async()=>{try{const f=await Eo.getStatus();if(!c.current)return;e({...f,harnesses:Aye(f.harnesses)}),a(null)}catch(f){c.current&&a(f instanceof Error?f.message:String(f))}finally{c.current&&s(!1)}},[]);w.useEffect(()=>{d()},[d]);const u=w.useCallback(async f=>{l(!0);try{const p=await Eo.setOrcHarness(f);return c.current&&(e(x=>x&&{...x,orcHarness:p}),a(null)),!0}catch(p){return c.current&&a(p instanceof Error?p.message:String(p)),!1}finally{c.current&&l(!1)}},[]),h=w.useCallback(f=>{e(p=>p&&{...p,harnesses:p.harnesses.map(x=>x.id===f.id?f:x)})},[]);return{overview:t,loading:n,error:r,refresh:d,setOrcHarness:u,savingOrc:o,replaceHarness:h}}function Tye(t,e){const[n,s]=w.useState(null),[r,a]=w.useState(null),[o,l]=w.useState(null),[c,d]=w.useState(!1),u=w.useRef(e);u.current=e;const h=w.useCallback(async()=>{l(null),d(!0);try{const f=await Eo.startInstall(t);a({state:"running",log:"",usedUserPrefix:!1}),s(f)}catch(f){l(f instanceof Error?f.message:String(f))}finally{d(!1)}},[t]);return w.useEffect(()=>{if(!n||!r||r.state!=="running")return;let f=!1;const p=setTimeout(async()=>{var x;try{const y=await Eo.getInstallJob(n);if(f)return;a(y),y.state!=="running"&&((x=u.current)==null||x.call(u,y))}catch(y){if(f)return;l(y instanceof Error?y.message:String(y)),a(m=>m&&{...m,state:"failed"})}},$2.INSTALL_POLL_MS);return()=>{f=!0,clearTimeout(p)}},[n,r]),{job:r,error:o,running:c||(r==null?void 0:r.state)==="running",start:h}}const Mye=({log:t})=>{const e=w.useRef(null);return w.useEffect(()=>{e.current&&(e.current.scrollTop=e.current.scrollHeight)},[t]),i.jsx("pre",{ref:e,role:"log","aria-live":"polite","aria-label":"安装日志 / Install log","data-testid":"install-log",className:"mt-3 max-h-48 overflow-auto rounded-2xl border border-border-dark bg-background-dark p-3 font-mono text-xs leading-relaxed text-text-secondary-dark whitespace-pre-wrap break-all",children:t||"…"})},Nye=({harness:t,selectName:e,selected:n=!1,onSelect:s,onInstallFinished:r})=>{const{job:a,error:o,running:l,start:c}=Tye(t.id,r),d=V1[t.loginState],u=!t.installed||t.updateAvailable||(a==null?void 0:a.state)==="failed",h=(a==null?void 0:a.state)==="failed"?"重试安装":t.installed?"更新 / Update":"安装 / Install",f=i.jsx("span",{className:"font-semibold text-text-primary-dark",children:t.displayName});return i.jsxs(dt,{padding:"md","data-testid":`harness-card-${t.id}`,className:n?"border-primary":void 0,children:[i.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[i.jsxs("div",{className:"min-w-0",children:[e?i.jsxs("label",{className:"flex items-center gap-3 cursor-pointer",children:[i.jsx("input",{type:"radio",name:e,value:t.id,checked:n,onChange:()=>s==null?void 0:s(t.id),className:"h-4 w-4 accent-[var(--crewly-primary)]"}),f]}):f,i.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[t.installed?i.jsxs(ft,{variant:"success",children:["已安装",t.version?` v${t.version}`:""]}):i.jsx(ft,{variant:"default",children:"未安装 / Not installed"}),t.installed&&t.updateAvailable&&i.jsxs(ft,{variant:"info",children:["可更新",t.latestVersion?` → v${t.latestVersion}`:""]}),t.installed&&i.jsx(ft,{variant:d.variant,children:d.label}),t.installed&&t.loginSource&&i.jsx("span",{className:"text-xs text-text-secondary-dark",children:t.loginSource})]})]}),u&&i.jsx(de,{type:"button",variant:t.installed&&(a==null?void 0:a.state)!=="failed"?"secondary":"primary",size:"sm",icon:t.installed?an:vh,loading:l,onClick:()=>void c(),className:"shrink-0 self-start",children:l?"安装中…":h})]}),o&&i.jsx(tt,{variant:"error",size:"sm",className:"mt-3",children:o}),a&&i.jsx(Mye,{log:a.log}),(a==null?void 0:a.state)==="succeeded"&&i.jsx(tt,{variant:"success",size:"sm",className:"mt-3",title:"安装完成 / Installed",children:a.usedUserPrefix?"已安装到你的用户目录,不需要管理员权限。Installed to your user folder (no admin rights needed).":`${t.displayName} 已就绪。`}),(a==null?void 0:a.state)==="failed"&&!o&&i.jsx(tt,{variant:"error",size:"sm",className:"mt-3",title:"安装失败 / Install failed",children:"请查看上面的日志后重试。Check the log above and try again."})]})},jye="harness-choice",Y9=({harnesses:t,systemTools:e=[],selectedId:n,onSelect:s,onInstallFinished:r})=>{const a=e.filter(o=>!o.installed);return i.jsxs("div",{className:"space-y-3","data-testid":"harness-list",children:[i.jsx("div",{role:s?"radiogroup":void 0,"aria-label":s?"选择编程助手":void 0,className:"space-y-3",children:t.map(o=>i.jsx(Nye,{harness:o,selectName:s?jye:void 0,selected:s?n===o.id:!1,onSelect:s,onInstallFinished:()=>r==null?void 0:r()},o.id))}),a.map(o=>i.jsxs(tt,{variant:"warning",size:"sm",title:`缺少系统工具 ${o.id} / Missing ${o.id}`,children:[i.jsx("span",{children:"部分技能需要它。安装方法:"}),i.jsx("code",{className:"ml-1 rounded bg-background-dark px-1.5 py-0.5 font-mono text-xs",children:o.installHint})]},o.id))]})};function Rye(t,e,n){var r;const s=t.filter(a=>a.installed);for(const a of[e,n,K2])if(a&&s.some(o=>o.id===a))return a;return((r=s[0])==null?void 0:r.id)??null}const J9=({harnesses:t,value:e,onChange:n,disabled:s=!1})=>{const r=t.filter(a=>a.installed);return r.length===0?i.jsx(Cs,{compact:!0,icon:p0,title:"还没有安装任何编程助手",description:"先安装 Claude Code 或 Codex,再回来选择。Install a harness first."}):i.jsx("div",{role:"radiogroup","aria-label":"Orc 使用的编程助手",className:"space-y-2","data-testid":"orc-harness-picker",children:r.map(a=>{const o=e===a.id,l=V1[a.loginState];return i.jsxs("label",{className:`flex items-center justify-between gap-3 rounded-2xl border p-3 cursor-pointer transition-colors ${o?"border-primary bg-primary/10":"border-border-dark bg-surface-dark hover:border-primary/50"} ${s?"opacity-60 cursor-not-allowed":""}`,children:[i.jsxs("span",{className:"flex items-center gap-3 min-w-0",children:[i.jsx("input",{type:"radio",name:"orc-harness",value:a.id,checked:o,disabled:s,onChange:()=>n(a.id),className:"h-4 w-4 accent-[var(--crewly-primary)]"}),i.jsx("span",{className:"font-medium text-text-primary-dark truncate",children:a.displayName}),a.id===K2&&i.jsx("span",{className:"text-xs text-text-secondary-dark",children:"推荐"})]}),i.jsx(ft,{variant:l.variant,children:l.label})]},a.id)})})},Iye=({harnessId:t,label:e,onSaved:n})=>{const[s,r]=w.useState(""),[a,o]=w.useState(!1),[l,c]=w.useState(null),[d,u]=w.useState(!1),h=jte[t],f=async p=>{p.preventDefault();const x=s.trim();if(x){r(""),o(!0),c(null),u(!1);try{const y=await Eo.setApiKey(t,x);u(!0),n==null||n(y)}catch(y){c(y instanceof Error?y.message:"保存失败 / Save failed")}finally{o(!1)}}};return i.jsxs("form",{onSubmit:f,className:"space-y-3","data-testid":"api-key-form",children:[i.jsx(ys,{type:"password",label:e,name:`${t}-api-key`,autoComplete:"off",spellCheck:!1,placeholder:"sk-…",value:s,onChange:p=>r(p.target.value),fullWidth:!0}),i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[h?i.jsxs("a",{href:h.url,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-sm text-primary hover:underline underline-offset-2",children:["在 ",h.label," 获取 Key",i.jsx(ws,{className:"h-3.5 w-3.5"})]}):i.jsx("span",{}),i.jsx(de,{type:"submit",size:"sm",loading:a,disabled:!s.trim()||a,children:"保存 / Save"})]}),d&&i.jsx(tt,{variant:"success",size:"sm",children:"API Key 已保存。Key saved."}),l&&i.jsx(tt,{variant:"error",size:"sm",children:l})]})},Pye=new Set(["succeeded","failed","timed_out","cancelled"]);function $M(t){return Pye.has(t)}function Lye(t){return t.state==="awaiting_user"&&!t.url&&!t.userCode&&!t.needsInput}function Dye(t,e){const[n,s]=w.useState(null),[r,a]=w.useState(null),[o,l]=w.useState(!1),[c,d]=w.useState(0),u=w.useRef(e);u.current=e;const h=w.useRef(null),f=w.useCallback(async m=>{l(!0),a(null);try{s(await Eo.startLogin(t,m))}catch(g){a(g instanceof Error?g.message:String(g))}finally{l(!1)}},[t]),p=w.useCallback(async m=>{if(!n)return!1;l(!0),a(null);try{const g=await Eo.sendLoginInput(n.id,m);return g&&s(g),!0}catch(g){return a(g instanceof Error?g.message:String(g)),!1}finally{l(!1)}},[n]),x=w.useCallback(async()=>{if(n){l(!0);try{const m=await Eo.cancelLogin(n.id);s(m??{...n,state:"cancelled"})}catch(m){a(m instanceof Error?m.message:String(m))}finally{l(!1)}}},[n]),y=w.useCallback(()=>{s(null),a(null)},[]);return w.useEffect(()=>{if(!n||$M(n.state))return;let m=!1;const g=setTimeout(async()=>{try{const v=await Eo.getLoginSession(n.id);if(m)return;s(v),a(null)}catch(v){if(m)return;a(v instanceof Error?v.message:String(v)),d(b=>b+1)}},$2.LOGIN_POLL_MS);return()=>{m=!0,clearTimeout(g)}},[n,c]),w.useEffect(()=>{var m;(n==null?void 0:n.state)==="succeeded"&&h.current!==n.id&&(h.current=n.id,(m=u.current)==null||m.call(u))},[n]),{session:n,error:r,busy:o,start:f,sendInput:p,cancel:x,reset:y}}const Oye=new Set(["https:","http:"]);function Z9(t){if(!t)return!1;try{return Oye.has(new URL(t).protocol)}catch{return!1}}const Bye=({value:t,label:e="复制"})=>{const[n,s]=w.useState(!1),r=w.useRef(null);w.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]);const a=async()=>{try{await navigator.clipboard.writeText(t),s(!0),r.current&&clearTimeout(r.current),r.current=setTimeout(()=>s(!1),$2.COPIED_FEEDBACK_MS)}catch{}};return i.jsx(de,{type:"button",variant:"secondary",size:"sm",icon:n?Kn:w1,onClick:a,"aria-label":e,"data-testid":"copy-button",children:n?"已复制":e})},ZB=({label:t,submitLabel:e,busy:n,onSubmit:s,mono:r,testId:a})=>{const[o,l]=w.useState(""),c=async d=>{d.preventDefault();const u=o.trim();u&&await s(u)&&l("")};return i.jsxs("form",{onSubmit:c,className:"flex flex-col gap-2 sm:flex-row sm:items-end","data-testid":a,children:[i.jsx("div",{className:"flex-1 min-w-0",children:i.jsx(ys,{label:t,value:o,onChange:d=>l(d.target.value),autoComplete:"off",spellCheck:!1,className:r?"font-mono":void 0,fullWidth:!0})}),i.jsx(de,{type:"submit",loading:n,disabled:!o.trim()||n,className:"shrink-0",children:e})]})};function Fye(t){Z9(t)&&window.open(t,"_blank","noopener,noreferrer")}const Uye=({session:t,busy:e,sendInput:n})=>{const s=Z9(t.url)?t.url:null;return Lye(t)?i.jsxs("div",{className:"space-y-3","data-testid":"login-fallback",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"没能自动识别登录画面,请根据下面的终端内容操作。We couldn't read the login screen automatically."}),i.jsxs("details",{className:"rounded-2xl border border-border-dark bg-background-dark",open:!0,children:[i.jsx("summary",{className:"cursor-pointer px-3 py-2 text-sm font-medium text-text-primary-dark",children:"终端内容"}),i.jsx("pre",{className:"max-h-64 overflow-auto border-t border-border-dark p-3 font-mono text-xs text-text-secondary-dark whitespace-pre-wrap break-all","data-testid":"login-screen",children:t.screen||"(空)"})]}),i.jsx(ZB,{label:"发送到终端 / Send to terminal",submitLabel:"发送",busy:e,onSubmit:n,mono:!0,testId:"login-raw-input"})]}):i.jsxs("div",{className:"space-y-4",children:[s&&i.jsxs("div",{className:"space-y-2",children:[i.jsx(de,{type:"button",fullWidth:!0,icon:ws,onClick:()=>Fye(s),"data-testid":"login-open-url",children:"打开授权页面"}),i.jsx("p",{className:"text-xs text-text-secondary-dark break-all",children:s})]}),t.userCode&&i.jsxs("div",{className:"rounded-2xl border border-border-dark bg-background-dark p-4 text-center space-y-3","data-testid":"login-user-code",children:[i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"验证码 / One-time code"}),i.jsx("p",{className:"font-mono text-3xl font-bold tracking-widest text-text-primary-dark select-all break-all",children:t.userCode}),i.jsx(Bye,{value:t.userCode,label:"复制验证码"}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"在打开的页面输入这个验证码,完成后这里会自动继续"})]}),t.needsInput&&i.jsx(ZB,{label:"把页面上给你的代码粘贴到这里",submitLabel:"提交 / Submit",busy:e,onSubmit:n,testId:"login-code-input"})]})},zye=({harnessId:t,method:e,label:n,onSucceeded:s})=>{const{session:r,error:a,busy:o,start:l,sendInput:c,cancel:d}=Dye(t,s),u=w.useRef(null);if(u.current=r&&!$M(r.state)?r:null,w.useEffect(()=>()=>{u.current&&Eo.cancelLogin(u.current.id).catch(()=>{})},[]),!r)return i.jsxs("div",{className:"space-y-3",children:[i.jsx(de,{type:"button",fullWidth:!0,icon:tY,loading:o,onClick:()=>void l(e),"data-testid":"login-start",children:n}),a&&i.jsx(tt,{variant:"error",size:"sm",children:a})]});const h=r.state==="failed"||r.state==="timed_out",f=!$M(r.state);return i.jsxs("div",{className:"space-y-4","data-testid":"login-session","data-state":r.state,children:[(r.state==="starting"||r.state==="verifying")&&i.jsx(Ht,{size:"sm",inline:!0,text:kk[r.state]}),r.state==="awaiting_user"&&i.jsx(Uye,{session:r,busy:o,sendInput:c}),r.state==="awaiting_user"&&r.message&&i.jsx("p",{className:"text-sm text-text-secondary-dark",children:r.message}),r.state==="succeeded"&&i.jsx(tt,{variant:"success",size:"sm",title:"登录成功 / Signed in",children:r.message||"现在可以使用了。"}),h&&i.jsx(tt,{variant:"error",size:"sm",title:kk[r.state],children:r.message||"请重试。Please try again."}),r.state==="cancelled"&&i.jsx("p",{className:"text-sm text-text-secondary-dark",children:kk.cancelled}),a&&i.jsx(tt,{variant:"error",size:"sm",children:a}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[(h||r.state==="cancelled")&&i.jsx(de,{type:"button",icon:_2,loading:o,onClick:()=>void l(e),children:"重试 / Retry"}),f&&i.jsx(de,{type:"button",variant:"ghost",size:"sm",disabled:o,onClick:()=>void d(),children:"取消 / Cancel"})]})]})},Q9=({harness:t,onLoggedIn:e,onHarnessUpdated:n})=>{var f;const s=t.loginMethods,[r,a]=w.useState(((f=s[0])==null?void 0:f.id)??null),[o,l]=w.useState(!1),c=V1[t.loginState],d=s.find(p=>p.id===r)??s[0],u=t.installed&&s.length>0&&(t.loginState!=="logged_in"||o),h=()=>t.installed?s.length===0?i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["暂不支持在网页登录 ",t.displayName,",请在终端里完成登录。Browser login isn't available for this harness yet."]}):u?i.jsxs("div",{className:"space-y-4",children:[s.length>1&&i.jsx(ao,{"aria-label":"登录方式 / Login method",fullWidth:!0,size:"sm",value:d.id,onChange:a,options:s.map(p=>({value:p.id,label:Ck(t.id,p.id,p.label)}))}),d.kind==="api_key"?i.jsx(Iye,{harnessId:t.id,label:Ck(t.id,d.id,d.label),onSaved:p=>{l(!1),n==null||n(p)}},`${t.id}-${d.id}`):i.jsx(zye,{harnessId:t.id,method:d.id==="device"?"device":"subscription",label:Ck(t.id,d.id,d.label),onSucceeded:()=>e==null?void 0:e()},`${t.id}-${d.id}`)]}):i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:[t.loginSource?`已通过 ${t.loginSource} 登录。`:"已登录。","登录过期时可以在这里重新登录。"]}),i.jsx(de,{type:"button",variant:"secondary",size:"sm",onClick:()=>l(!0),children:"重新登录 / Re-login"})]}):i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["请先安装 ",t.displayName,"。Install it first."]});return i.jsxs(dt,{padding:"md","data-testid":`harness-login-card-${t.id}`,children:[i.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-2",children:[i.jsxs("h3",{className:"font-semibold text-text-primary-dark",children:["登录 ",t.displayName]}),t.installed&&i.jsx(ft,{variant:c.variant,children:c.label})]}),h()]})},QE=({title:t,subtitle:e})=>i.jsxs("div",{className:"mb-3",children:[i.jsx("h2",{className:"text-lg font-semibold text-text-primary-dark",children:t}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:e})]}),Hye=()=>{const{overview:t,loading:e,error:n,refresh:s,setOrcHarness:r,savingOrc:a,replaceHarness:o}=X9();if(e)return i.jsx(Ht,{centered:!0,text:"正在检查编程助手…","data-testid":"harness-tab-loading"});if(!t)return i.jsx(tt,{variant:"error",title:"无法读取编程助手状态 / Couldn't load harness status",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:n}),i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:()=>void s(),children:"重试 / Retry"})]})});const l=t.harnesses.filter(c=>c.installed).sort((c,d)=>+(d.id===t.orcHarness)-+(c.id===t.orcHarness));return i.jsxs("div",{className:"space-y-8 max-w-3xl","data-testid":"harness-tab",children:[n&&i.jsx(tt,{variant:"error",size:"sm",children:n}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-start justify-between gap-3",children:[i.jsx(QE,{title:"编程助手",subtitle:"Coding harnesses installed on this machine"}),i.jsx(de,{type:"button",size:"sm",variant:"ghost",icon:an,onClick:()=>void s(),children:"刷新"})]}),i.jsx(Y9,{harnesses:t.harnesses,systemTools:t.systemTools,onInstallFinished:()=>void s()})]}),i.jsxs("section",{children:[i.jsx(QE,{title:"Orc 使用的编程助手",subtitle:"Which harness the orchestrator runs on"}),i.jsx(J9,{harnesses:t.harnesses,value:t.orcHarness,onChange:c=>void r(c),disabled:a})]}),l.length>0&&i.jsxs("section",{children:[i.jsx(QE,{title:"登录",subtitle:"Sign in again here when a login expires"}),i.jsx("div",{className:"space-y-3",children:l.map(c=>i.jsx(Q9,{harness:c,onLoggedIn:()=>void s(),onHarnessUpdated:o},c.id))})]})]})},Gye=new Set(["general","harness","roles","skills","integrations","api-keys","credentials","system"]),Wye=()=>{const[t]=xh(),e=ms(),n=t.get("tab");w.useEffect(()=>{n==="cloud"&&e("/cloud",{replace:!0})},[n,e]);const s=n==="slack"?"integrations":n&&Gye.has(n)?n:"general",r=[{id:"general",label:"General",icon:zz},{id:"harness",label:"Harness",icon:p0},{id:"roles",label:"Roles",icon:Yp},{id:"skills",label:"Skills",icon:qz},{id:"integrations",label:"Integrations",icon:Gl},{id:"api-keys",label:"API Keys",icon:G_},{id:"credentials",label:"Credentials",icon:W_},{id:"system",label:"System",icon:io}],a=o=>{switch(o){case"general":return i.jsx(G0e,{});case"harness":return i.jsx(Hye,{});case"roles":return i.jsx(q0e,{});case"skills":return i.jsx(Z0e,{});case"integrations":return i.jsx(aye,{});case"api-keys":return i.jsx(lye,{});case"credentials":return i.jsx(hye,{});case"system":return i.jsx(Cye,{});default:return null}};return i.jsxs("div",{className:"max-w-7xl mx-auto",children:[i.jsxs("div",{className:"mb-8",children:[i.jsx("h1",{className:"text-3xl font-bold tracking-tight",children:"Settings"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Configure Crewly behavior and manage roles and skills"})]}),i.jsxs(Zp,{defaultValue:s,children:[i.jsx(Qp,{className:"overflow-x-auto",children:r.map(o=>i.jsx(Qa,{value:o.id,icon:i.jsx(o.icon,{className:"w-4 h-4"}),children:i.jsx("span",{children:o.label})},o.id))}),r.map(o=>i.jsx(Cp,{value:o.id,children:a(o.id)},o.id))]})]})};function Pw(t){if(t!=null)return new Date(t).toISOString()}function vR(t){return t==="starting"?"online":t}function Vye(t,e){return t==="system"?"System":e}function $ye(t){if(!t)return;const e=t.clientMessageId;return typeof e=="string"&&e.length>0?e:void 0}function eA(t){return{id:t.id,agentSession:t.agentSession,name:t.name,purpose:t.purpose,createdAt:new Date(t.createdAt).toISOString(),lastMessageAt:Pw(t.lastMessageAt),presence:vR(t.agentPresence.status),type:t.type??"dm",teamId:t.teamId,projectId:t.projectId,targetMemberId:t.targetMemberId}}function Kye(t){return{id:t.id,kind:"image",url:t.url,filename:t.originalName,size:t.sizeBytes,mimeType:t.mimeType}}function KM(t){var e;return{id:t.id,channelId:t.channelId,seq:t.seq,author:{role:t.senderType,id:t.senderId,name:Vye(t.senderType,t.senderId)},content:t.content,attachments:(e=t.attachments)==null?void 0:e.map(Kye),createdAt:new Date(t.createdAt).toISOString(),clientMessageId:$ye(t.metadata),deliveryStatus:"sent",mentions:Array.isArray(t.mentions)?t.mentions:[],threadId:t.threadId,replyCount:typeof t.replyCount=="number"?t.replyCount:void 0,lastReplyAt:Pw(t.lastReplyAt)}}function qye(t){return{agentId:t.agentSession,status:vR(t.status),lastSeen:Pw(t.lastSeenAt)}}function Xye(t){if(!t||typeof t!="object")return null;const e=t;if(e.type==="message"){const n=t.payload;return!n||typeof n.channelId!="string"||!n.message?null:{type:"message",channelId:n.channelId,message:KM(n.message)}}if(e.type==="presence"){const n=t.payload;return!n||typeof n.agentSession!="string"||typeof n.status!="string"?null:{type:"presence",agentSession:n.agentSession,status:vR(n.status),lastSeen:Pw(n.lastSeenAt??null)}}if(e.type==="pong"){const n=t.ts;return{type:"pong",ts:typeof n=="number"?n:0}}if(e.type==="error"){const n=t.code,s=t.message;return{type:"error",code:typeof n=="string"?n:"unknown",message:typeof s=="string"?s:""}}return null}const Yye=["validation_error","not_found","channel_not_found","agent_not_found","forbidden","agent_already_bound","payload_too_large","rate_limited","invalid_cursor","channel_archived","attachment_not_found","internal_error","network_error","unknown_error"];class s0 extends Error{constructor(n){super(n.message);On(this,"code");On(this,"httpStatus");On(this,"details");this.name="ChatApiError",this.code=n.code,this.httpStatus=n.httpStatus,this.details=n.details}static async fromResponse(n){let s;try{s=await n.json()}catch{s=void 0}if(s&&typeof s=="object"&&"error"in s&&s.error&&typeof s.error=="object"){const r=s.error,a=Jye(r.code),o=typeof r.message=="string"?r.message:`Chat API error ${n.status}`,l=r.details&&typeof r.details=="object"?r.details:void 0;return new s0({code:a,httpStatus:n.status,message:o,details:l})}return new s0({code:"unknown_error",httpStatus:n.status,message:`Chat API error ${n.status}`})}}function Jye(t){return typeof t!="string"?"unknown_error":Yye.includes(t)?t:"unknown_error"}const Zye={id:"__me__",name:"You"},Qye=25e3,eve=1e4,tve=1e3;function nve(){const t=globalThis;return t.crypto&&typeof t.crypto.randomUUID=="function"?t.crypto.randomUUID():`cmid-${Math.random().toString(16).slice(2)}-${Date.now().toString(16)}`}class sve{constructor(e){On(this,"backendURL");On(this,"authToken");On(this,"fetchImpl");On(this,"websocketImpl");On(this,"idGenerator");On(this,"currentUser");On(this,"heartbeatIntervalMs");On(this,"pongTimeoutMs");On(this,"reconnectDelayMs");On(this,"now");On(this,"localSubscribers",new Set);this.backendURL=e.backendURL.replace(/\/+$/,""),this.authToken=e.authToken,this.fetchImpl=e.fetchImpl??(typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):void 0),this.websocketImpl=e.websocketImpl??globalThis.WebSocket,this.idGenerator=e.idGenerator??nve,this.currentUser=e.currentUser??Zye,this.heartbeatIntervalMs=e.heartbeatIntervalMs??Qye,this.pongTimeoutMs=e.pongTimeoutMs??eve,this.reconnectDelayMs=e.reconnectDelayMs??tve,this.now=e.now??Date.now}headers(e){const n={"Content-Type":"application/json",...e};return this.authToken&&(n.Authorization=`Bearer ${this.authToken}`),n}async request(e,n){let s;try{s=await this.fetchImpl(`${this.backendURL}${e}`,{...n,headers:this.headers(n==null?void 0:n.headers)})}catch(a){throw new s0({code:"network_error",httpStatus:0,message:a instanceof Error?a.message:String(a)})}if(!s.ok)throw await s0.fromResponse(s);return(await s.json()).data}async listChannels(){return(await this.request("/api/chat/channels")).channels.map(eA)}async createChannel(e){const n=await this.request("/api/chat/channels",{method:"POST",body:JSON.stringify(e)});return eA(n)}async createHuddle(e){const n=await this.request("/api/chat/channels/huddle",{method:"POST",body:JSON.stringify(e)});return eA(n)}async listMessages(e,n={}){const s=new URLSearchParams;n.cursor&&s.set("cursor",n.cursor),n.limit&&s.set("limit",String(n.limit));const r=s.toString()?`?${s.toString()}`:"",a=await this.request(`/api/chat/channels/${encodeURIComponent(e)}/messages${r}`);return{messages:a.messages.map(KM),nextCursor:a.nextCursor}}async sendMessage(e,n){const s=n.clientMessageId??this.idGenerator(),r=this.buildOptimisticMessage(e,n,s);this.emitLocal(e,{type:"message",channelId:e,message:r});const a={content:n.content,contentType:"markdown",clientMessageId:s};n.mentions&&n.mentions.length>0&&(a.mentions=n.mentions),n.threadId&&(a.threadId=n.threadId);let o;try{o=await this.request(`/api/chat/channels/${encodeURIComponent(e)}/messages`,{method:"POST",body:JSON.stringify(a)})}catch(c){throw this.emitLocal(e,{type:"message",channelId:e,message:{...r,deliveryStatus:"failed"}}),c}const l=KM(o);return l.clientMessageId||(l.clientMessageId=s),this.emitLocal(e,{type:"message",channelId:e,message:l}),l}async getAgentPresence(e){const n=await this.request(`/api/chat/presence/${encodeURIComponent(e)}`);return qye(n)}subscribeToChannel(e,n){const s={channelId:e,onEvent:n};this.localSubscribers.add(s);const r=this.openWebsocketConnection(e,n);return{unsubscribe:()=>{this.localSubscribers.delete(s),r.close()}}}buildOptimisticMessage(e,n,s){return{id:s,channelId:e,seq:-1,author:{role:"user",id:this.currentUser.id,name:this.currentUser.name},content:n.content,attachments:n.attachments,createdAt:new Date(this.now()).toISOString(),clientMessageId:s,deliveryStatus:"pending",mentions:n.mentions??[],threadId:n.threadId}}emitLocal(e,n){for(const s of this.localSubscribers)if(s.channelId===e)try{s.onEvent(n)}catch{}}openWebsocketConnection(e,n){let s=null,r=null,a=null,o=null,l=0,c=!1;const d=()=>{r&&(clearInterval(r),r=null),a&&(clearTimeout(a),a=null),o&&(clearTimeout(o),o=null)},u=()=>{if(s)try{(s.readyState===s.OPEN||s.readyState===s.CONNECTING)&&s.close()}catch{}},h=()=>{c||(d(),o=setTimeout(()=>{o=null,p()},this.reconnectDelayMs))},f=()=>{if(!(!s||s.readyState!==s.OPEN)){try{s.send(JSON.stringify({type:"ping",ts:this.now()}))}catch{return}a&&clearTimeout(a),a=setTimeout(()=>{u()},this.pongTimeoutMs)}},p=()=>{if(c)return;const x=this.backendURL.replace(/^http/,"ws"),y=new URLSearchParams({channelId:e});this.authToken&&y.set("token",this.authToken),l>0&&y.set("lastSeenSeq",String(l));try{s=new this.websocketImpl(`${x}/ws/chat?${y.toString()}`)}catch{h();return}const m=b=>{let S;try{S=JSON.parse(typeof b.data=="string"?b.data:"")}catch{return}const k=Xye(S);if(k){if(k.type==="pong"){a&&(clearTimeout(a),a=null),n(k);return}if(k.type==="message"&&k.message.seq>l&&(l=k.message.seq),k.type==="error"){n(k),c=!0,d(),u();return}n(k)}},g=()=>{r&&clearInterval(r),r=setInterval(f,this.heartbeatIntervalMs)},v=()=>{h()};s.addEventListener("message",m),s.addEventListener("open",g),s.addEventListener("close",v)};return p(),{close(){c=!0,d(),u()}}}}const QB="demo-user",e4="Steve",rve=800,ive=()=>{let t=1;return e=>`${e}-${t++}`};class ave{constructor(e={}){On(this,"channels");On(this,"messages");On(this,"subscribers",{});On(this,"replyDelay");On(this,"nextId",ive());this.channels=e.initialChannels??ove(),this.messages=e.initialMessages??lve(this.channels),this.replyDelay=e.agentReplyDelayMs??rve}async listChannels(){return[...this.channels]}async createChannel(e){const n=e.type??"dm",s={id:this.nextId("ch"),agentSession:n==="dm"?e.agentSession??"":"",name:e.name,purpose:e.purpose,createdAt:new Date().toISOString(),presence:"online",type:n,teamId:e.teamId,projectId:e.projectId,targetMemberId:e.targetMemberId};return this.channels=[...this.channels,s],this.messages[s.id]=[],s}async createHuddle(e){const n={id:this.nextId("ch"),agentSession:"",name:e.name,purpose:e.purpose,createdAt:new Date().toISOString(),presence:"online",type:"huddle"};return this.channels=[...this.channels,n],this.messages[n.id]=[],n}async listMessages(e,n={}){const s=this.messages[e]??[],r=n.limit??50;return{messages:s.slice(-r),nextCursor:s.length>r?"mock-older":null}}async sendMessage(e,n){var d,u;const s=this.channels.find(h=>h.id===e);if(!s)throw new Error(`Unknown channel: ${e}`);const r=n.clientMessageId??this.nextId("cmid"),a=n.mentions??[],o=n.threadId,l={id:r,channelId:e,seq:-1,author:{role:"user",id:QB,name:e4},content:n.content,attachments:n.attachments,createdAt:new Date().toISOString(),clientMessageId:r,deliveryStatus:"pending",mentions:a,threadId:o};this.emit(e,{type:"message",channelId:e,message:l});const c={id:this.nextId("m"),channelId:e,seq:(((d=this.messages[e])==null?void 0:d.length)??0)+1,author:{role:"user",id:QB,name:e4},content:n.content,attachments:n.attachments,createdAt:l.createdAt,clientMessageId:r,deliveryStatus:"sent",mentions:a,threadId:o};return((u=this.messages)[e]||(u[e]=[])).push(c),this.emit(e,{type:"message",channelId:e,message:c}),window.setTimeout(()=>{var f,p;const h={id:this.nextId("m"),channelId:e,seq:(((f=this.messages[e])==null?void 0:f.length)??0)+1,author:{role:"agent",id:s.agentSession,name:s.name},content:`(mock reply) you said: "${n.content}"`,createdAt:new Date().toISOString(),deliveryStatus:"sent",mentions:[],threadId:o};((p=this.messages)[e]||(p[e]=[])).push(h),this.emit(e,{type:"message",channelId:e,message:h})},this.replyDelay),c}async getAgentPresence(e){const n=this.channels.find(s=>s.agentSession===e);return{agentId:e,status:(n==null?void 0:n.presence)??"offline",lastSeen:new Date().toISOString()}}subscribeToChannel(e,n){var s;return((s=this.subscribers)[e]||(s[e]=[])).push(n),{unsubscribe:()=>{const r=this.subscribers[e];r&&(this.subscribers[e]=r.filter(a=>a!==n))}}}emit(e,n){const s=this.subscribers[e];if(s)for(const r of s)try{r(n)}catch{}}}function ove(){const t=new Date().toISOString();return[{id:"ch-ella",agentSession:"crewly-marketing-ella",name:"Ella · Marketing",purpose:"Marketing strategy + content planning",createdAt:t,lastMessageAt:t,presence:"online",type:"dm"},{id:"ch-sam",agentSession:"crewly-product-sam",name:"Sam · Engineering",purpose:"Platform architecture + delivery",createdAt:t,lastMessageAt:t,presence:"busy",type:"dm"},{id:"ch-offline",agentSession:"crewly-offline-demo",name:"Dormant Agent",purpose:"Shows the offline state",createdAt:t,presence:"offline",type:"dm"}]}function lve(t){var n;const e={};for(const s of t)e[s.id]=[{id:`${s.id}-welcome`,channelId:s.id,seq:1,author:{role:"agent",id:s.agentSession,name:s.name},content:`Welcome — I'm **${((n=s.name.split("·")[0])==null?void 0:n.trim())??s.name}**. Ask me anything.`,createdAt:s.createdAt,mentions:[]}];return e}const e7=w.createContext(null);function cve({children:t,backendURL:e,authToken:n,mode:s="real",client:r}){const a=w.useMemo(()=>{if(r)return{client:r,mode:s};if(s==="mock")return{client:new ave,mode:s};if(!e)throw new Error('[@crewly/chat-ui] ChatAPIProvider requires `backendURL` when mode="real".');return{client:new sve({backendURL:e,authToken:n}),mode:s}},[e,n,s,r]);return i.jsx(e7.Provider,{value:a,children:t})}function hm(){const t=w.useContext(e7);if(!t)throw new Error("[@crewly/chat-ui] useChatApiClient must be called inside <ChatAPIProvider>.");return t.client}function dve(t,e){const n=hm(),[s,r]=w.useState("offline"),[a,o]=w.useState(void 0),[l,c]=w.useState(!!t),[d,u]=w.useState(null);return w.useEffect(()=>{if(!t){r("offline"),c(!1);return}let h=!1;return c(!0),u(null),n.getAgentPresence(t).then(f=>{h||(r(f.status),o(f.lastSeen))}).catch(f=>{h||u(f instanceof Error?f:new Error(String(f)))}).finally(()=>{h||c(!1)}),()=>{h=!0}},[t,n]),w.useEffect(()=>{if(!t||!e)return;const h=n.subscribeToChannel(e,f=>{f.type==="presence"&&f.agentSession===t&&(r(f.status),o(f.lastSeen))});return()=>h.unsubscribe()},[t,e,n]),{status:s,lastSeen:a,loading:l,error:d}}const uve={online:"online",busy:"busy",idle:"idle",offline:"offline",inactive:"inactive"},t4={online:"Online",busy:"Busy",idle:"Idle",offline:"Offline",inactive:"Inactive"},hve={online:"bg-emerald-400",busy:"bg-amber-400",idle:"bg-amber-400",offline:"bg-text-secondary-dark/50",inactive:"bg-text-secondary-dark/50"},fve={online:"text-emerald-400",busy:"text-amber-400",idle:"text-amber-400",offline:"text-text-secondary-dark",inactive:"text-text-secondary-dark"};function pve({status:t,agentId:e,channelId:n,compact:s=!1,className:r=""}){const a=mve({status:t,agentId:e,channelId:n});return i.jsxs("span",{className:`inline-flex items-center gap-1.5 ${r}`,"data-testid":"agent-status-badge","data-status":a,children:[i.jsx("span",{"aria-hidden":"true",className:`inline-block h-2 w-2 rounded-full ${hve[a]}`}),!s&&i.jsx("span",{className:`text-xs font-medium ${fve[a]}`,children:t4[a]}),i.jsx("span",{className:"sr-only",children:t4[a]})]})}function mve(t){const e=dve(t.status?null:t.agentId??null,t.channelId??null),n=t.status??e.status;return uve[n]}function gve(){const t=hm(),[e,n]=w.useState([]),[s,r]=w.useState(!0),[a,o]=w.useState(null),l=w.useCallback(async()=>{r(!0),o(null);try{const c=await t.listChannels();n(c)}catch(c){o(c instanceof Error?c:new Error(String(c)))}finally{r(!1)}},[t]);return w.useEffect(()=>{l()},[l]),{channels:e,loading:s,error:a,refresh:l}}function t7(t,e){if(e.clientMessageId){const s=t.findIndex(r=>r.clientMessageId&&r.clientMessageId===e.clientMessageId);if(s>=0){const r=t.slice();return r[s]=e,r}}const n=t.findIndex(s=>s.id===e.id);if(n>=0){const s=t.slice();return s[n]=e,s}return[...t,e]}function n4(t){return[...t].sort((e,n)=>e.seq-n.seq)}function xve(t,e){return t.filter(n=>n.threadId===e).sort((n,s)=>n.seq-s.seq)}function qM(t){if(t.length===0)return!1;const e=t[t.length-1];return e.author.role!=="user"?!1:!!e.clientMessageId}function n7(t){const e=hm(),[n,s]=w.useState([]),[r,a]=w.useState(!1),[o,l]=w.useState(null),c=w.useRef(null),[d,u]=w.useState(!1),[h,f]=w.useState(!1);w.useEffect(()=>{if(!t){s([]),u(!1),f(!1);return}let y=!1;return a(!0),l(null),c.current=null,f(!1),e.listMessages(t).then(m=>{y||(s(n4(m.messages)),c.current=m.nextCursor,u(m.nextCursor!==null))}).catch(m=>{y||l(m instanceof Error?m:new Error(String(m)))}).finally(()=>{y||a(!1)}),()=>{y=!0}},[t,e]),w.useEffect(()=>{if(!t)return;const y=e.subscribeToChannel(t,m=>{m.type==="message"&&s(g=>{const v=t7(g,m.message);return f(qM(v)),v})});return()=>y.unsubscribe()},[t,e]);const p=w.useCallback(async()=>{if(!t||!c.current)return;const y=c.current;try{const m=await e.listMessages(t,{cursor:y});s(g=>[...n4(m.messages),...g]),c.current=m.nextCursor,u(m.nextCursor!==null)}catch(m){l(m instanceof Error?m:new Error(String(m)))}},[t,e]),x=w.useCallback(async y=>{if(!t)throw new Error("sendMessage called without an active channel.");return await e.sendMessage(t,y)},[t,e]);return{messages:n,loading:r,error:o,hasMore:d,agentThinking:h,loadMore:p,sendMessage:x}}function s7(t){const e=t.replace(/\r\n/g,`
4917
4917
  `).split(/\n\n+/);return i.jsx(i.Fragment,{children:e.map((n,s)=>i.jsx(yve,{block:n},s))})}function yve({block:t}){const e=t.split(`
4918
4918
  `),n=e.every(r=>/^\s*[-*]\s+/.test(r)),s=e.every(r=>/^\s*\d+\.\s+/.test(r));return n&&e.length>0?i.jsx("ul",{className:"my-1 list-disc pl-5",children:e.map((r,a)=>i.jsx("li",{children:tA(r.replace(/^\s*[-*]\s+/,""))},a))}):s&&e.length>0?i.jsx("ol",{className:"my-1 list-decimal pl-5",children:e.map((r,a)=>i.jsx("li",{children:tA(r.replace(/^\s*\d+\.\s+/,""))},a))}):i.jsx("p",{className:"whitespace-pre-wrap",children:tA(t)})}function tA(t){const e=/(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g,n=t.split(e);return i.jsx(i.Fragment,{children:n.map((s,r)=>/^\*\*[^*]+\*\*$/.test(s)?i.jsx("strong",{children:s.slice(2,-2)},r):/^\*[^*]+\*$/.test(s)?i.jsx("em",{children:s.slice(1,-1)},r):/^`[^`]+`$/.test(s)?i.jsx("code",{className:"rounded bg-primary/10 px-1 font-mono text-[0.85em] text-primary",children:s.slice(1,-1)},r):i.jsx(w.Fragment,{children:s},r))})}function vve({channelId:t,agentName:e,className:n="",emptyState:s,unreadAfterSeq:r=null,unreadDividerLabel:a="New",layout:o="bubble",onReplyInThread:l,hideReplies:c=!1,messages:d,agentThinking:u,loading:h,hasMore:f,onLoadMore:p}){const x=d!==void 0,y=n7(x?null:t),m=x?d:y.messages,g=x?h??!1:y.loading,v=x?null:y.error,b=x?f??!1:y.hasMore,S=x?u??!1:y.agentThinking,k=x?p??(()=>{}):y.loadMore,E=c?m.filter(M=>!M.threadId):m,N=w.useRef(null),T=E.length>0?E[E.length-1].id:null;if(w.useEffect(()=>{var M;(M=N.current)==null||M.scrollIntoView({behavior:"smooth",block:"end"})},[T,t,S]),!t)return i.jsx("div",{className:`flex h-full items-center justify-center text-sm text-text-secondary-dark ${n}`,role:"status",children:s??"Select a channel to start chatting."});const A=o==="flat";return i.jsxs("div",{className:`chat-scrollbar flex h-full flex-col overflow-y-auto bg-background-dark ${n}`,"aria-label":"Message thread","data-testid":"message-thread",children:[b&&i.jsx("div",{className:"sticky top-0 z-10 flex justify-center py-2 backdrop-blur bg-background-dark/80",children:i.jsx("button",{type:"button",onClick:()=>void k(),className:A?"rounded-full border border-border-dark px-3 py-1 text-xs text-text-secondary-dark hover:bg-white/5":"rounded-full border border-border-dark px-3 py-1 text-xs text-text-secondary-dark hover:bg-surface-dark",children:"Load older"})}),i.jsxs("ul",{role:"list",className:`flex flex-1 flex-col ${A?"gap-0 px-4 py-4":"gap-3 px-4 py-4"}`,children:[bve({messages:E,unreadAfterSeq:r,unreadDividerLabel:a,layout:o,onReplyInThread:l}),S&&i.jsx(Mve,{agentName:e,layout:o}),g&&i.jsx("li",{className:"text-xs text-text-secondary-dark",role:"status",children:"Loading messages…"}),v&&i.jsxs("li",{className:"text-xs text-red-500",role:"alert",children:["Failed to load messages: ",v.message]})]}),i.jsx("div",{ref:N})]})}function bve(t){const{messages:e,unreadAfterSeq:n,unreadDividerLabel:s,layout:r,onReplyInThread:a}=t,o=[];let l=null,c=null;const d=n!=null&&e.some(h=>h.seq===n);n!=null&&!d&&e.length>0&&o.push(i.jsx(s4,{label:s,layout:r},"unread-divider"));let u=!1;for(const h of e){r==="flat"&&Rve(c,h.createdAt)&&(o.push(i.jsx(kve,{label:jve(h.createdAt)},`day-${h.id}`)),l=null),c=h.createdAt;const f=r!=="flat"||l!==h.author.id;o.push(i.jsx(_ve,{message:h,layout:r,groupStart:f,onReplyInThread:a},h.id)),l=h.author.id,!u&&d&&h.seq===n&&(o.push(i.jsx(s4,{label:s,layout:r},"unread-divider")),u=!0,l=null)}return o}function s4({label:t,layout:e}){return e==="flat"?i.jsxs("li",{className:"flex items-center gap-4 py-1","data-testid":"unread-divider",role:"separator","aria-label":`${t} messages below`,children:[i.jsx("span",{className:"h-[1px] flex-1 bg-border-dark/20","aria-hidden":"true"}),i.jsx("span",{className:"text-[11px] font-bold uppercase tracking-widest text-text-secondary-dark",children:t}),i.jsx("span",{className:"h-[1px] flex-1 bg-border-dark/20","aria-hidden":"true"})]}):i.jsxs("li",{className:"flex items-center gap-2 py-1","data-testid":"unread-divider",role:"separator","aria-label":`${t} messages below`,children:[i.jsx("span",{className:"h-px flex-1 bg-rose-400/70","aria-hidden":"true"}),i.jsx("span",{className:"rounded-full bg-rose-500 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-white",children:t}),i.jsx("span",{className:"h-px flex-1 bg-rose-400/70","aria-hidden":"true"})]})}function _ve({message:t,layout:e="bubble",groupStart:n=!0,onReplyInThread:s}){var d;if(e==="flat")return i.jsx(Sve,{message:t,groupStart:n,onReplyInThread:s});const r=t.author.role==="user",a=r?"items-end":"items-start",o=t.deliveryStatus,l=r?"bg-primary text-white":"bg-surface-dark text-text-primary-dark",c=o==="pending"?`${l} opacity-60`:o==="failed"?`${l} ring-2 ring-red-400`:l;return i.jsxs("li",{className:`flex flex-col ${a}`,"data-author-role":t.author.role,"data-delivery-status":o??"sent",children:[i.jsx("div",{className:"mb-0.5 text-xs text-text-secondary-dark",children:t.author.name??t.author.id}),i.jsxs("div",{className:`max-w-prose rounded-2xl px-3 py-2 text-sm shadow-sm ${c}`,children:[s7(t.content),(d=t.attachments)==null?void 0:d.map(u=>u.kind==="image"?i.jsx("img",{src:u.url,alt:u.filename??"attachment",className:"mt-2 max-h-64 max-w-full rounded-lg"},u.id):null)]}),i.jsx(Tve,{message:t})]})}function Sve({message:t,groupStart:e,onReplyInThread:n}){var p;const s=t.deliveryStatus,r=t.author.name??t.author.id,a=t.author.role!=="user",l=s==="pending"?"opacity-50":"",c=typeof n=="function",d=t.replyCount??0,u=c&&d>0,h=c&&s!=="pending"&&s!=="failed",f=i7(t.content);return i.jsxs("li",{className:`group relative flex gap-3 rounded-md py-0.5 pl-2 pr-2 transition-colors hover:bg-white/[0.03] ${e?"mt-3":"mt-px"}`,"data-author-role":t.author.role,"data-delivery-status":s??"sent",children:[a&&e&&i.jsx("span",{"aria-hidden":"true",className:"absolute left-0 top-1 h-[calc(100%-0.5rem)] w-[2px] rounded-full bg-primary/40"}),i.jsx("div",{className:"w-9 shrink-0 select-none",children:e?i.jsx(Ave,{name:r,isAgent:a}):i.jsx("time",{className:"block w-9 pt-[3px] text-right text-[10px] leading-5 tabular-nums text-transparent group-hover:text-text-secondary-dark",children:XM(t.createdAt)})}),i.jsxs("div",{className:"min-w-0 flex-1",children:[e&&i.jsxs("div",{className:"flex items-baseline gap-2",children:[i.jsx("span",{className:`text-[13px] font-bold leading-5 ${a?"text-primary":"text-text-primary-dark"}`,children:r}),a&&i.jsx("span",{className:"rounded border border-border-dark bg-white/5 px-1.5 py-px text-[9px] font-semibold uppercase tracking-wide text-text-secondary-dark",children:"Agent"}),i.jsx("time",{className:"text-[10px] tabular-nums text-text-secondary-dark",children:XM(t.createdAt)})]}),i.jsxs("div",{className:`mt-0.5 max-w-[760px] text-[13px] leading-[1.45] text-text-primary-dark [&_a]:text-primary [&_a]:underline ${l}`,children:[s7(f),(p=t.attachments)==null?void 0:p.map(x=>x.kind==="image"?i.jsx("img",{src:x.url,alt:x.filename??"attachment",className:"mt-2 max-h-64 max-w-full rounded-lg"},x.id):null)]}),s==="pending"&&i.jsx("span",{className:"mt-0.5 inline-flex items-center gap-1 text-[10px] italic text-text-secondary-dark",children:"Sending…"}),s==="failed"&&i.jsx("span",{className:"mt-0.5 inline-flex items-center gap-1 text-[10px] font-medium text-amber-300",role:"alert",children:"Send failed — tap to retry"}),u&&i.jsx(Cve,{message:t,onOpen:()=>n==null?void 0:n(t)})]}),h&&i.jsx(wve,{message:t,onReplyInThread:n})]})}function db({label:t,children:e,onClick:n,...s}){return i.jsx("button",{type:"button","aria-label":t,title:t,onClick:n,className:"flex h-7 w-7 items-center justify-center rounded-md text-text-secondary-dark transition-colors hover:bg-white/5 hover:text-text-primary-dark",...s,children:e})}function wve({message:t,onReplyInThread:e}){return i.jsxs("div",{"data-testid":`msg-toolbar-${t.id}`,className:"absolute -top-3 right-2 z-10 hidden items-center gap-0.5 rounded-lg border border-border-dark bg-surface-dark p-0.5 shadow-md group-hover:flex",children:[i.jsx(db,{label:"Add reaction",children:i.jsx(pY,{size:15})}),i.jsx(db,{label:"Reply in thread","data-testid":`msg-reply-action-${t.id}`,onClick:()=>e(t),children:i.jsx(Xp,{size:15})}),i.jsx(db,{label:"Copy link",children:i.jsx(BT,{size:15})}),i.jsx(db,{label:"More actions",children:i.jsx(iY,{size:15})})]})}function Cve({message:t,onOpen:e}){const n=t.replyCount??0,r=[t.author.name??t.author.id].slice(0,3);return i.jsxs("button",{type:"button","data-testid":`msg-thread-summary-${t.id}`,onClick:e,className:"group/chip mt-1 flex w-fit items-center gap-2 rounded-md px-1.5 py-1 text-left transition-colors hover:bg-white/5",children:[i.jsx("span",{className:"flex -space-x-1.5",children:r.map(a=>i.jsx("span",{className:`flex h-5 w-5 items-center justify-center rounded-md text-[9px] font-bold text-white ring-2 ring-background-dark ${Eve(a)}`,"aria-hidden":"true",children:r7(a)},a))}),i.jsxs("span",{className:"text-[12px] font-semibold text-primary group-hover/chip:underline",children:[n," ",n===1?"reply":"replies"]}),t.lastReplyAt&&i.jsxs("span",{className:"text-[11px] font-normal text-text-secondary-dark",children:["Last reply ",Nve(t.lastReplyAt)]})]})}function kve({label:t}){return i.jsxs("li",{className:"relative my-3 flex items-center justify-center",role:"separator","aria-label":t,"data-testid":"day-divider",children:[i.jsx("span",{className:"absolute inset-x-2 top-1/2 h-px -translate-y-1/2 bg-border-dark/50","aria-hidden":"true"}),i.jsx("span",{className:"relative rounded-full border border-border-dark bg-background-dark px-3 py-0.5 text-[11px] font-semibold text-text-secondary-dark",children:t})]})}const r4=["bg-rose-500","bg-orange-500","bg-amber-500","bg-emerald-500","bg-teal-500","bg-sky-500","bg-primary","bg-blue-500","bg-fuchsia-500"];function r7(t){const e=t.split(/[\s\-_.]+/).filter(Boolean);return e.length===0?"?":e.length===1?e[0].slice(0,2).toUpperCase():(e[0][0]+e[1][0]).toUpperCase()}function Eve(t){let e=0;for(let n=0;n<t.length;n+=1)e=e*31+t.charCodeAt(n)>>>0;return r4[e%r4.length]}function Ave({name:t,isAgent:e}){return i.jsx("span",{className:`flex h-9 w-9 items-center justify-center rounded-lg text-[12px] font-bold ${e?"bg-primary/20 text-primary":"bg-blue-500/20 text-blue-300"}`,"aria-hidden":"true",children:e?i.jsx(p0,{size:16}):r7(t)})}function Tve({message:t}){return t.deliveryStatus==="pending"?i.jsx("span",{className:"mt-0.5 text-[10px] italic text-text-secondary-dark",children:"Sending…"}):t.deliveryStatus==="failed"?i.jsx("span",{className:"mt-0.5 text-[10px] font-medium text-red-500",role:"alert",children:"Send failed — tap to retry"}):i.jsx("time",{className:"mt-0.5 text-[10px] text-text-secondary-dark",children:XM(t.createdAt)})}function Mve({agentName:t,layout:e="bubble"}){const n=t?`${t} is thinking`:"Agent is thinking";return e==="flat"?i.jsxs("li",{className:"mt-3 flex items-center gap-3 px-2",role:"status","aria-live":"polite","data-testid":"agent-thinking",children:[i.jsx("span",{className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-primary/20 text-primary",children:i.jsx(p0,{size:16})}),i.jsxs("span",{className:"inline-flex items-center gap-2 text-[13px] text-text-secondary-dark",children:[i.jsxs("span",{"aria-hidden":"true",className:"flex gap-0.5",children:[i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark [animation-delay:-0.3s]"}),i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark [animation-delay:-0.15s]"}),i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark"})]}),i.jsxs("span",{children:[n,"…"]})]})]}):i.jsx("li",{className:"flex flex-col items-start",role:"status","aria-live":"polite","data-testid":"agent-thinking",children:i.jsx("div",{className:"rounded-2xl bg-surface-dark px-3 py-2 text-sm text-text-secondary-dark shadow-sm",children:i.jsxs("span",{className:"inline-flex items-center gap-1",children:[i.jsxs("span",{"aria-hidden":"true",className:"flex gap-0.5",children:[i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark [animation-delay:-0.3s]"}),i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark [animation-delay:-0.15s]"}),i.jsx("span",{className:"h-1.5 w-1.5 animate-bounce rounded-full bg-text-secondary-dark"})]}),i.jsxs("span",{children:[n,"…"]})]})})})}function Nve(t){try{const e=new Date(t).getTime();if(Number.isNaN(e))return"";const n=Date.now()-e,s=Math.floor(n/6e4);if(s<1)return"now";if(s<60)return`${s}m`;const r=Math.floor(s/60);if(r<24)return`${r}h`;const a=Math.floor(r/24);return a<7?`${a}d`:new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"})}catch{return""}}function XM(t){try{return new Date(t).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}catch{return t}}function jve(t){try{const e=new Date(t);if(Number.isNaN(e.getTime()))return t;const n=o=>new Date(o.getFullYear(),o.getMonth(),o.getDate()).getTime(),s=n(new Date),r=n(e),a=864e5;return r===s?"Today":r===s-a?"Yesterday":e.toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric"})}catch{return t}}function Rve(t,e){if(!t)return!0;const n=new Date(t),s=new Date(e);return Number.isNaN(n.getTime())||Number.isNaN(s.getTime())?!1:n.getFullYear()!==s.getFullYear()||n.getMonth()!==s.getMonth()||n.getDate()!==s.getDate()}function i7(t){return t.replace(/\s*\[Thread context file:[^\]]*\]/gi,"").replace(/[ \t]+$/gm,"").trim()}function Ive(){const t=hm(),[e,n]=w.useState(!1),[s,r]=w.useState(null),a=w.useCallback(async(l,c)=>{n(!0),r(null);try{return await t.sendMessage(l,c)}catch(d){const u=d instanceof Error?d:new Error(String(d));throw r(u),u}finally{n(!1)}},[t]),o=w.useCallback(()=>{r(null),n(!1)},[]);return{send:a,sending:e,error:s,reset:o}}const a7="crewly-chat-collapsed-groups",i4=["bg-blue-500/20 text-blue-400","bg-emerald-500/20 text-emerald-400","bg-cyan-500/20 text-cyan-400","bg-amber-500/20 text-amber-400"];function Pve(t){let e=0;for(let n=0;n<t.length;n+=1)e=e*31+t.charCodeAt(n)>>>0;return i4[e%i4.length]}function Lve(){try{const t=localStorage.getItem(a7);if(t){const e=JSON.parse(t);if(Array.isArray(e))return new Set(e.filter(n=>typeof n=="string"))}}catch{}return null}function Dve({workspaceName:t,groups:e,activeConversationId:n=null,onSelectConversation:s,emptyState:r,headerAction:a,isPinned:o,onTogglePin:l,defaultCollapsedGroupIds:c,className:d=""}){const[u,h]=w.useState(""),f=w.useMemo(()=>Ove(e,u),[e,u]),p=w.useMemo(()=>f.reduce((g,v)=>g+Lw(v),0),[f]),[x,y]=w.useState(()=>Lve()??new Set(c??[])),m=w.useCallback(g=>{y(v=>{const b=new Set(v);b.has(g)?b.delete(g):b.add(g);try{localStorage.setItem(a7,JSON.stringify([...b]))}catch{}return b})},[]);return i.jsxs("aside",{className:`flex h-full w-[240px] flex-col border-r border-border-dark bg-surface-dark ${d}`,"aria-label":t?`${t} conversations`:"Conversations","data-testid":"conversation-list-panel",children:[(t||a)&&i.jsxs("header",{className:"border-b border-border-dark p-4",children:[i.jsxs("div",{className:"flex items-center justify-between gap-2",children:[i.jsx("h2",{className:"truncate text-base font-bold text-text-primary-dark",children:t??""}),a]}),i.jsx("div",{className:"relative mt-3",children:i.jsx("input",{type:"text",value:u,onChange:g=>h(g.target.value),placeholder:"Find...","aria-label":"Find a conversation","data-testid":"conv-search",className:"w-full rounded-lg border border-border-dark bg-background-dark px-3 py-1.5 text-[13px] text-text-primary-dark outline-none placeholder:text-text-secondary-dark focus:border-primary focus:ring-1 focus:ring-primary"})})]}),i.jsx("div",{className:"chat-scrollbar flex-1 overflow-y-auto p-2",children:p===0?i.jsx("div",{className:"px-2 py-6 text-[13px] text-text-secondary-dark",role:"status",children:u?"No conversations match your search.":r??"No conversations in this workspace yet."}):f.map(g=>o7(g)?i.jsx(l7,{group:g,activeConversationId:n,onSelectConversation:s,collapsed:x,onToggleCollapse:m,isPinned:o,onTogglePin:l},g.id):null)})]})}function Lw(t){var e;return t.rows.length+(((e=t.subGroups)==null?void 0:e.reduce((n,s)=>n+Lw(s),0))??0)}function o7(t){return Lw(t)>0}function Ove(t,e){const n=e.trim().toLowerCase();if(!n)return t;const s=r=>{var a;return{...r,rows:r.rows.filter(o=>o.title.toLowerCase().includes(n)),subGroups:(a=r.subGroups)==null?void 0:a.map(s)}};return t.map(s)}function l7({group:t,activeConversationId:e,onSelectConversation:n,collapsed:s,onToggleCollapse:r,isPinned:a,onTogglePin:o,depth:l=0}){const c=s.has(t.id),d=(t.subGroups??[]).filter(o7);return i.jsxs("section",{className:l===0?"mb-4":"mt-2","aria-labelledby":`conv-group-${t.id}`,"data-testid":`conv-group-${t.id}`,children:[i.jsxs("button",{type:"button",id:`conv-group-${t.id}`,onClick:()=>r(t.id),"aria-expanded":!c,"data-testid":`conv-group-toggle-${t.id}`,className:"mb-2 flex w-full items-center justify-between px-2",style:{paddingLeft:`${.5+l*.75}rem`},children:[i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx($r,{size:16,className:`text-text-secondary-dark transition-transform ${c?"-rotate-90":""}`}),i.jsx("span",{className:"truncate text-[11px] font-bold uppercase tracking-wider text-text-secondary-dark",children:t.label})]}),i.jsx("span",{className:"text-[10px] text-text-secondary-dark",children:Lw(t)})]}),!c&&i.jsxs(i.Fragment,{children:[t.rows.length>0&&i.jsx("ul",{role:"list",className:"flex flex-col gap-0.5",children:t.rows.map(u=>i.jsx("li",{children:i.jsx(Bve,{row:u,isActive:e===u.id,onSelect:n,pinned:(a==null?void 0:a(u))??!1,onTogglePin:o})},u.id))}),d.map(u=>i.jsx(l7,{group:u,activeConversationId:e,onSelectConversation:n,collapsed:s,onToggleCollapse:r,isPinned:a,onTogglePin:o,depth:l+1},u.id))]})]})}function Bve({row:t,isActive:e,onSelect:n,pinned:s,onTogglePin:r}){const a=(t.unreadCount??0)>0,o=(t.mentionCount??0)>0,l=t.kind==="channel",c=l?e?"flex items-center gap-2 rounded-lg border border-primary/20 bg-primary/10 px-3 py-1.5 text-primary":"flex items-center gap-2 rounded-lg px-3 py-1.5 text-text-secondary-dark hover:bg-white/5":e?"group flex items-center gap-3 rounded-lg border border-primary/20 bg-primary/10 px-3 py-2 text-primary":"group flex items-center gap-3 rounded-lg px-3 py-2 text-text-secondary-dark hover:bg-white/5";return i.jsxs("div",{className:"group/row relative flex w-full items-center",children:[i.jsxs("button",{type:"button",onClick:()=>n==null?void 0:n(t),"data-testid":`conv-row-${t.id}`,"data-active":e?"true":"false","data-kind":t.kind,"data-unread":a?"true":"false",className:`min-w-0 flex-1 text-left ${c}`,"aria-current":e?"page":void 0,children:[i.jsx(Uve,{row:t}),l?i.jsx("span",{className:["min-w-0 flex-1 truncate text-[13px]",a?"font-semibold text-text-primary-dark":""].join(" "),children:t.title.replace(/^#+\s*/,"")}):i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:["truncate text-[13px] font-medium",a?"font-semibold text-text-primary-dark":"text-text-primary-dark group-hover:text-primary"].join(" "),children:t.title}),t.badge&&i.jsx("span",{className:"shrink-0 rounded bg-primary/15 px-1.5 py-px text-[10px] font-semibold uppercase tracking-wide text-primary","data-testid":`conv-badge-${t.id}`,children:t.badge}),t.lastMessageAt&&i.jsx("time",{className:"ml-auto shrink-0 text-[10px] text-text-secondary-dark",dateTime:t.lastMessageAt,children:Hve(t.lastMessageAt)})]}),t.lastMessagePreview&&i.jsx("div",{className:"truncate text-[10px] opacity-70",children:t.lastMessagePreview}),t.subtitle&&!t.lastMessagePreview&&i.jsx("div",{className:"truncate text-[10px] opacity-70",children:t.subtitle})]}),o?i.jsxs("span",{className:"inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-rose-500 px-1 text-[10px] font-semibold text-white","data-testid":`conv-mention-pill-${t.id}`,"aria-label":`${t.mentionCount} mentions`,children:["@",t.mentionCount]}):a?i.jsx("span",{className:"inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[10px] font-semibold text-white","data-testid":`conv-unread-pill-${t.id}`,"aria-label":`${t.unreadCount} unread`,children:t.unreadCount}):null]}),r&&i.jsx("button",{type:"button",onClick:d=>{d.stopPropagation(),r(t)},"data-testid":`conv-pin-${t.id}`,"aria-label":s?`Unpin ${t.title}`:`Pin ${t.title}`,"aria-pressed":s,title:s?"Unpin":"Pin",className:["ml-1 shrink-0 rounded p-1 text-text-secondary-dark hover:text-amber-400",s?"text-amber-400":"opacity-0 group-hover/row:opacity-100"].join(" "),children:i.jsx(Fve,{filled:s??!1})})]})}function Fve({filled:t}){return i.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 16 16",className:"h-3.5 w-3.5",children:i.jsx("path",{d:"M9.5 1.5l5 5-2 .5-2.5 2.5L9 13 7 11 3.5 14.5 3 14l3.5-3.5L4.5 8.5 7 6l.5-2.5 2-2z",fill:t?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.2",strokeLinejoin:"round"})})}function Uve({row:t}){return t.kind==="channel"?i.jsx("span",{"aria-hidden":"true",className:"flex shrink-0 items-center justify-center text-base font-medium","data-testid":`conv-icon-${t.id}`,children:"#"}):t.kind==="dm"?i.jsxs("span",{"aria-hidden":"true",className:`relative flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-[10px] font-bold uppercase ${Pve(t.title)}`,"data-testid":`conv-icon-${t.id}`,children:[zve(t.title),t.presence&&i.jsx("span",{className:"absolute -bottom-0.5 -right-0.5 rounded-full bg-surface-dark p-[1px]",children:i.jsx(pve,{status:t.presence,compact:!0})})]}):i.jsx("span",{"aria-hidden":"true",className:"flex h-8 w-8 shrink-0 items-center justify-center text-xs text-text-secondary-dark","data-testid":`conv-icon-${t.id}`,children:"⟳"})}function zve(t){const e=t.trim().split(/\s+/).filter(Boolean);return e.length===0?"?":e.length===1?e[0].slice(0,2).toUpperCase():(e[0][0]+e[1][0]).toUpperCase()}function Hve(t){try{const e=new Date(t).getTime(),s=Date.now()-e,r=Math.floor(s/6e4);if(r<1)return"now";if(r<60)return`${r}m`;const a=Math.floor(r/60);if(a<24)return`${a}h`;const o=Math.floor(a/24);return o<7?`${o}d`:new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"})}catch{return""}}const Gve="Message — try @ to mention a team or agent",Wve={online:"bg-emerald-400",busy:"bg-amber-400",idle:"bg-amber-400",offline:"bg-text-secondary-dark/50",inactive:"bg-text-secondary-dark/50"};function c7({mentionables:t,placeholder:e=Gve,disabled:n=!1,inactiveHelper:s,onSend:r,className:a=""}){const[o,l]=w.useState(""),[c,d]=w.useState([]),[u,h]=w.useState(!1),[f,p]=w.useState(""),x=w.useRef(null),y=w.useRef(!1),m=w.useMemo(()=>Kve(t,f),[t,f]),g=m.teams.length+m.agents.length,v=w.useCallback(I=>{const F=I.target.value;l(F);const G=o4(F,I.target.selectionStart??F.length);G?(h(!0),p(G.partial)):(h(!1),p(""))},[]),b=w.useCallback(I=>{var V,H;d($=>$.find(P=>P.id===I.id)?$:[...$,I]);const F=((V=x.current)==null?void 0:V.selectionStart)??o.length,G=o4(o,F);if(G){const $=o.slice(0,G.start),P=o.slice(F),B=`@${I.label} `;l($+B+P)}else l($=>`${$}@${I.label} `);h(!1),p(""),(H=x.current)==null||H.focus()},[o]),S=w.useCallback(I=>{d(F=>F.filter(G=>G.id!==I))},[]),k=!n&&(o.trim().length>0||c.length>0),E=w.useCallback(()=>{k&&(r==null||r({content:o.trim(),mentions:c}),l(""),d([]),h(!1),p(""))},[k,c,r,o]),N=w.useCallback(I=>{if(I.key==="Escape"&&u){I.preventDefault(),h(!1);return}if(I.key==="Enter"&&!I.shiftKey){if(y.current||I.nativeEvent.isComposing)return;I.preventDefault(),E()}},[E,u]),T=w.useCallback(()=>{y.current=!0},[]),A=w.useCallback(()=>{y.current=!1},[]),M=w.useCallback(()=>{var I;n||(l(F=>{const G=F.length>0&&!/\s$/.test(F);return`${F}${G?" ":""}@`}),p(""),h(!0),(I=x.current)==null||I.focus())},[n]),L=w.useMemo(()=>{if(s)return s;const I=c[c.length-1];return I?I.routingHint?I.routingHint:I.kind==="team"?"Sent to team channel; TL is primary responder":`Directly notifies ${I.label}`:null},[s,c]);return i.jsxs("div",{className:`relative px-4 pb-4 pt-2 ${a}`,"data-testid":"mention-composer",children:[c.length>0&&i.jsx("ul",{className:"mb-2 flex flex-wrap gap-1.5","aria-label":"Pending mentions","data-testid":"mention-chip-strip",children:c.map(I=>i.jsx("li",{children:i.jsx($ve,{target:I,onRemove:()=>S(I.id)})},I.id))}),i.jsxs("div",{className:"glass-panel flex flex-col gap-2 rounded-2xl bg-background-dark/50 p-2 focus-within:ring-1 focus-within:ring-primary/50",children:[i.jsx("textarea",{ref:x,value:o,onChange:v,onKeyDown:N,onCompositionStart:T,onCompositionEnd:A,disabled:n,placeholder:e,rows:1,"data-testid":"mention-textarea",className:"min-h-[44px] w-full resize-none border-none bg-transparent px-4 py-2 text-sm text-text-primary-dark placeholder:text-text-secondary-dark focus:outline-none focus:ring-0 disabled:opacity-50"}),i.jsxs("div",{className:"flex items-center justify-between px-2 pb-1",children:[i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx(ub,{label:"Attach",disabled:!0,children:i.jsx(ts,{size:16})}),i.jsx(ub,{label:"Mention",onClick:M,disabled:n,children:i.jsx(UX,{size:16})}),i.jsx(ub,{label:"Emoji",disabled:!0,children:i.jsx(mY,{size:16})}),i.jsx(ub,{label:"Code",disabled:!0,children:i.jsx(KX,{size:16})})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx("span",{className:"text-[11px] text-text-secondary-dark",children:"Markdown supported"}),i.jsxs("button",{type:"button",onClick:E,disabled:!k,"data-testid":"mention-send",className:"flex h-8 items-center gap-2 rounded-lg bg-primary px-4 text-[13px] font-bold text-white transition hover:bg-primary/90 active:scale-95 disabled:cursor-not-allowed disabled:opacity-50",children:[i.jsx(g0,{size:14}),"Send"]})]})]})]}),L&&i.jsx("p",{className:"mt-1 text-[11px] text-text-secondary-dark","data-testid":"mention-helper",children:L}),u&&g>0&&i.jsx(Vve,{teams:m.teams,agents:m.agents,onSelect:b})]})}function ub({label:t,onClick:e,disabled:n,children:s}){return i.jsx("button",{type:"button",onClick:e,disabled:n,"aria-label":t,title:t,className:"flex h-8 w-8 items-center justify-center rounded-lg text-text-secondary-dark transition hover:bg-white/5 disabled:opacity-40",children:s})}function Vve({teams:t,agents:e,onSelect:n}){return i.jsxs("div",{role:"listbox","data-testid":"mention-suggestions",className:"absolute bottom-[110%] left-4 right-4 z-10 max-h-72 overflow-y-auto rounded-xl border border-border-dark bg-surface-dark shadow-lg",children:[t.length>0&&i.jsx(a4,{label:"Teams",items:t,onSelect:n,testid:"teams"}),e.length>0&&i.jsx(a4,{label:"Agents",items:e,onSelect:n,testid:"agents"})]})}function a4({label:t,items:e,onSelect:n,testid:s}){return i.jsxs("div",{"data-testid":`mention-group-${s}`,children:[i.jsx("div",{className:"border-b border-border-dark bg-background-dark px-3 py-1 text-[10px] font-semibold uppercase tracking-wide text-text-secondary-dark",children:t}),i.jsx("ul",{role:"list",children:e.map(r=>i.jsx("li",{children:i.jsxs("button",{type:"button",onClick:()=>n(r),"data-testid":`mention-suggestion-${r.id}`,className:"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-white/5",children:[i.jsx(d7,{target:r}),i.jsx("span",{className:"min-w-0 flex-1 truncate text-text-primary-dark",children:r.label}),r.routingHint&&i.jsx("span",{className:"shrink-0 text-[11px] text-text-secondary-dark",children:r.routingHint})]})},r.id))})]})}function $ve({target:t,onRemove:e}){const n=t.kind==="team";return i.jsxs("span",{"data-testid":`mention-chip-${t.id}`,"data-kind":t.kind,className:["inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ring-1",n?"bg-primary/15 text-primary ring-primary/30":"bg-emerald-500/15 text-emerald-300 ring-emerald-500/30"].join(" "),children:[i.jsx(d7,{target:t,compact:!0}),i.jsxs("span",{children:["@",t.label]}),i.jsx("button",{type:"button",onClick:e,"aria-label":`Remove mention of ${t.label}`,className:"text-current opacity-60 hover:opacity-100",children:"×"})]})}function d7({target:t,compact:e=!1}){var n;return t.kind==="team"?i.jsx("span",{"aria-hidden":"true",className:`inline-flex items-center justify-center rounded ${e?"h-3 w-3 text-[8px]":"h-5 w-5 text-[10px]"} bg-primary/20 font-semibold text-primary`,children:"T"}):i.jsxs("span",{"aria-hidden":"true",className:`relative inline-flex items-center justify-center rounded-full bg-emerald-500/20 font-semibold text-emerald-300 ${e?"h-3 w-3 text-[8px]":"h-5 w-5 text-[10px]"}`,children:[((n=t.label[0])==null?void 0:n.toUpperCase())??"?",t.presence&&i.jsx("span",{"aria-hidden":"true",className:`absolute -bottom-0.5 -right-0.5 inline-block h-1.5 w-1.5 rounded-full ring-2 ring-surface-dark ${Wve[t.presence]}`})]})}function o4(t,e){const n=t.slice(0,e),s=n.lastIndexOf("@");if(s<0||s>0&&!/\s/.test(n[s-1]))return null;const r=n.slice(s+1);return/\s/.test(r)?null:{start:s,partial:r}}function Kve(t,e){const n=e.trim().toLowerCase(),s=r=>!n||r.label.toLowerCase().includes(n);return{teams:t.filter(r=>r.kind==="team"&&s(r)),agents:t.filter(r=>r.kind==="agent"&&s(r))}}const l4=20,qve=50;function c4(t){return[...t].sort((e,n)=>{const s=Date.parse(e.createdAt),r=Date.parse(n.createdAt);return Number.isFinite(s)&&Number.isFinite(r)&&s!==r?s-r:e.seq!==n.seq?e.seq-n.seq:e.id<n.id?-1:e.id>n.id?1:0})}const Xve=1e4;function d4(t){const e=[],n=new Set;for(const s of t){if(n.has(s.id))continue;const r=Date.parse(s.createdAt);e.some(o=>{var c,d;if(o.channelId!==s.channelId||(((c=o.author)==null?void 0:c.id)??"")!==(((d=s.author)==null?void 0:d.id)??"")||o.content!==s.content)return!1;const l=Date.parse(o.createdAt);return!Number.isFinite(r)||!Number.isFinite(l)?!0:Math.abs(r-l)<=Xve})||(n.add(s.id),e.push(s))}return e}function Yve(t){const e=hm(),[n,s]=w.useState([]),[r,a]=w.useState(!1),[o,l]=w.useState(null),[c,d]=w.useState(!1),u=[...t].sort().join("\0"),h=w.useRef(t);h.current=t;const[f,p]=w.useState(l4);w.useEffect(()=>{p(l4)},[u]);const x=w.useCallback(()=>{p(g=>g+qve)},[]);w.useEffect(()=>{const g=h.current;if(g.length===0){s([]),d(!1),a(!1);return}let v=!1;return a(!0),l(null),Promise.all(g.map(b=>e.listMessages(b).then(S=>S.messages).catch(()=>[]))).then(b=>{if(v)return;const S=d4(c4(b.flat()));s(S),d(qM(S))}).catch(b=>{v||l(b instanceof Error?b:new Error(String(b)))}).finally(()=>{v||a(!1)}),()=>{v=!0}},[u,e]),w.useEffect(()=>{const g=h.current;if(g.length===0)return;const v=g.map(b=>e.subscribeToChannel(b,S=>{S.type==="message"&&s(k=>{const E=d4(c4(t7(k,S.message)));return d(qM(E)),E})}));return()=>v.forEach(b=>b.unsubscribe())},[u,e]);const y=w.useMemo(()=>n.length>f?n.slice(n.length-f):n,[n,f]),m=n.length>f;return{messages:y,loading:r,error:o,agentThinking:c,hasMore:m,loadMore:x}}function Jve(t,e={}){const n=[],s=[],r=[];for(const a of t){const o=a.type??"dm";if(o==="huddle")s.push(nA(a,"channel"));else if(o==="channel"){if(e.workspaceId&&a.teamId!==e.workspaceId)continue;n.push(nA(a,"channel"))}else r.push(nA(a,"dm"))}return n.sort(sA),s.sort(sA),r.sort(sA),[{id:"channels",label:"Channels",rows:n},{id:"huddles",label:"Huddles",rows:s},{id:"dms",label:"Direct Messages",rows:r}]}function Zve(t,e={}){return w.useMemo(()=>Jve(t,e),[t,e.workspaceId])}function nA(t,e){return{id:t.id,kind:e,title:t.name,subtitle:t.purpose,lastMessageAt:t.lastMessageAt,presence:e==="dm"?Qve(t.presence):void 0,agentSession:e==="dm"?t.agentSession:void 0}}function Qve(t){if(t)return t}function sA(t,e){const n=t.lastMessageAt?Date.parse(t.lastMessageAt):NaN,s=e.lastMessageAt?Date.parse(e.lastMessageAt):NaN,r=Number.isFinite(n),a=Number.isFinite(s);return r&&a?s-n:r?-1:a?1:t.title.localeCompare(e.title)}function YM({headline:t,body:e,cta:n,testId:s}){return i.jsxs("div",{role:"status","data-testid":s,className:"flex h-full flex-col items-center justify-center gap-3 px-8 py-12 text-center",children:[i.jsx("h3",{className:"text-base font-semibold text-text-primary-dark",children:t}),i.jsx("div",{className:"max-w-md text-sm text-text-secondary-dark",children:e}),n&&i.jsx("div",{className:"mt-2",children:n})]})}function ebe({teamName:t}){return i.jsx(YM,{testId:"empty-no-channels",headline:`${t} has no conversations yet.`,body:i.jsx(i.Fragment,{children:"Channels are project-level discussions; direct messages are private pings to a single agent. Try one of the quick actions below to get started."}),cta:i.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-2 text-xs",children:[i.jsx(de,{type:"button",variant:"secondary",size:"xs",children:"Message team lead"}),i.jsx(de,{type:"button",variant:"secondary",size:"xs",children:"Open project channel"}),i.jsx(de,{type:"button",variant:"secondary",size:"xs",children:"Start DM"})]})})}function tbe({kind:t,recipientName:e}){return t==="dm"?i.jsx(YM,{testId:"empty-no-messages-dm",headline:e?`Start a private chat with ${e}`:"Start a private chat",body:i.jsxs(i.Fragment,{children:["Direct messages notify ",e??"this agent"," without broadcasting to the team. Try a starter prompt:",i.jsxs("ul",{className:"mt-3 flex list-inside list-disc flex-col items-start gap-1 text-left",children:[i.jsx("li",{children:'"What are you working on right now?"'}),i.jsx("li",{children:'"Pull the latest from main and share the diff"'})]})]})}):i.jsx(YM,{testId:"empty-no-messages-channel",headline:"No messages yet",body:i.jsxs(i.Fragment,{children:["Use this channel for project coordination and handoffs. Try a starter prompt:",i.jsxs("ul",{className:"mt-3 flex list-inside list-disc flex-col items-start gap-1 text-left",children:[i.jsx("li",{children:'"@team — kicking off the next sprint, blockers welcome"'}),i.jsx("li",{children:'"Anyone able to review PR #326?"'})]})]})})}function nbe({message:t,detail:e,onDismiss:n}){return i.jsxs("div",{role:"alert","data-testid":"chat-error-toast",className:"fixed bottom-4 right-4 z-50 flex max-w-md items-start gap-3 rounded-2xl border border-rose-700/40 bg-rose-900/30 px-4 py-3 text-sm text-rose-100 shadow-lg backdrop-blur-sm",children:[i.jsxs("div",{className:"flex-1",children:[i.jsx("div",{className:"font-medium",children:t}),e&&i.jsx("div",{className:"mt-0.5 text-xs opacity-80","data-testid":"chat-error-toast-detail",children:e})]}),n&&i.jsx(zt,{icon:cs,size:"xs",onClick:n,"aria-label":"Dismiss error","data-testid":"chat-error-toast-dismiss",className:"shrink-0 text-rose-200 hover:bg-rose-800/40 hover:text-rose-100"})]})}async function sbe(){var n;const e=await(await fetch("/api/chat/agents")).json();return((n=e==null?void 0:e.data)==null?void 0:n.agents)??[]}function rbe({onClose:t,onCreate:e,loadAgents:n=sbe}){const[s,r]=w.useState([]),[a,o]=w.useState(!0),[l,c]=w.useState(null),[d,u]=w.useState(""),[h,f]=w.useState(new Set),[p,x]=w.useState(!1),[y,m]=w.useState(null);w.useEffect(()=>{let k=!1;return(async()=>{try{const E=await n();k||r(E)}catch(E){k||c(E instanceof Error?E.message:String(E))}finally{k||o(!1)}})(),()=>{k=!0}},[n]);const g=k=>{f(E=>{const N=new Set(E);return N.has(k)?N.delete(k):N.add(k),N})},v=w.useMemo(()=>d.trim().length>0&&h.size>=2&&!p,[d,h,p]),b=async()=>{if(v){x(!0),m(null);try{await e(d.trim(),[...h])}catch(k){m(k instanceof Error?k.message:String(k)),x(!1)}}},S=i.jsxs(i.Fragment,{children:[i.jsxs("span",{className:"text-xs text-text-secondary-dark",children:[h.size," selected"]}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(de,{type:"button",variant:"secondary",size:"sm",onClick:t,children:"Cancel"}),i.jsx(de,{type:"button",size:"sm",onClick:()=>void b(),disabled:!v,"data-testid":"create-group-submit",children:p?"Creating…":"Create group"})]})]});return i.jsx(Fi,{isOpen:!0,onClose:t,title:"New group chat",subtitle:"Pull two or more agents into one room. Messages reach everyone.",size:"md",footer:S,footerAlign:"space-between",children:i.jsxs("div",{className:"space-y-3","data-testid":"create-group-modal",children:[i.jsx(Ut,{type:"text",value:d,onChange:k=>u(k.target.value),placeholder:"Group name (e.g. Launch crew)","aria-label":"Group name"}),i.jsxs("div",{className:"-mx-2 max-h-[45vh] overflow-y-auto border-t border-border-dark pt-2",children:[a&&i.jsx(Ht,{size:"sm",text:"Loading agents…",className:"py-2"}),l&&i.jsxs(tt,{variant:"error",children:["Failed to load agents: ",l]}),!a&&!l&&s.length===0&&i.jsx("p",{className:"px-2 py-2 text-sm text-text-secondary-dark",children:"No agents available."}),s.map(k=>{const E=h.has(k.agentSession);return i.jsxs("label",{className:"flex cursor-pointer items-center gap-3 rounded-2xl px-2 py-2 hover:bg-background-dark",children:[i.jsx("input",{type:"checkbox",checked:E,onChange:()=>g(k.agentSession),className:"h-4 w-4 accent-primary"}),i.jsxs("span",{className:"min-w-0",children:[i.jsx("span",{className:"block truncate text-sm text-text-primary-dark",children:k.name}),i.jsx("span",{className:"block truncate text-xs text-text-secondary-dark",children:k.role})]})]},k.agentSession)})]}),y&&i.jsx(tt,{variant:"error",children:y})]})})}const u7="crewly-chat-pinned",ibe=[Hu];function abe(){try{const t=localStorage.getItem(u7);if(t){const e=JSON.parse(t);if(Array.isArray(e))return new Set(e.filter(n=>typeof n=="string"))}}catch{}return new Set(ibe)}function obe(){const[t,e]=w.useState(abe),n=w.useCallback(r=>{e(a=>{const o=new Set(a);o.has(r)?o.delete(r):o.add(r);try{localStorage.setItem(u7,JSON.stringify([...o]))}catch{}return o})},[]),s=w.useCallback(r=>t.has(r),[t]);return{pinned:t,isPinned:s,toggle:n}}const lbe="home";function cbe(t){return`team:${t}`}function dbe({backendURL:t,authToken:e,client:n,mentionables:s=[],initialConversationId:r,directoryAgents:a=[],teams:o=[],onEnsureDm:l}){return i.jsx(cve,{mode:"real",backendURL:t,authToken:e,client:n,children:i.jsx(ube,{mentionables:s,initialConversationId:r,directoryAgents:a,teams:o,onEnsureDm:l})})}const rA="agent:",c_="slack-";function vg(t){return t.id.startsWith(c_)?t.id:t.agentSession||t.id}function JM(t){return t.flatMap(e=>[...e.rows,...JM(e.subGroups??[])])}function ube({mentionables:t,initialConversationId:e,directoryAgents:n,teams:s,onEnsureDm:r}){var G;const{channels:a,loading:o,error:l,refresh:c}=gve(),d=hm(),u=obe(),[h,f]=w.useState(!1),p=w.useMemo(()=>{const V=new Set(a.filter($=>($.type??"dm")==="dm"&&$.agentSession).map($=>$.agentSession)),H=n.filter($=>$.agentSession&&!V.has($.agentSession)).map($=>({id:`${rA}${$.agentSession}`,agentSession:$.agentSession,name:$.name,purpose:$.role,createdAt:"",type:"dm",presence:$.presence==="online"?"online":$.presence==="busy"?"busy":"offline"}));return H.length>0?[...a,...H]:a},[a,n]),[x,y]=w.useState(e??null),m=Zve(p,{workspaceId:void 0}),g=w.useMemo(()=>{var V;return((V=m.find(H=>H.id==="channels"))==null?void 0:V.rows)??[]},[m]),v=w.useMemo(()=>{var V;return((V=m.find(H=>H.id==="huddles"))==null?void 0:V.rows)??[]},[m]),b=w.useMemo(()=>{var V;return((V=m.find(H=>H.id==="dms"))==null?void 0:V.rows)??[]},[m]),S=w.useMemo(()=>{var V;return(V=b.find(H=>H.agentSession===Hu&&!H.id.startsWith(c_)))==null?void 0:V.id},[b]),k=w.useMemo(()=>b.filter(V=>V.id.startsWith(c_)).map(V=>V.id),[b]),E=w.useMemo(()=>{const V=new Map;for(const H of p)(H.type??"dm")==="channel"&&H.teamId&&V.set(H.id,H.teamId);return V},[p]),N=w.useMemo(()=>{const V=new Map(n.map(Y=>[Y.agentSession,Y.role])),H=new Set(s.flatMap(Y=>Y.leaderSessions)),$=Y=>Y==="team-leader",P=Y=>{const ne=Y.agentSession?V.get(Y.agentSession):void 0,ie=!!Y.agentSession&&H.has(Y.agentSession)||$(ne);let me=Y;return ne&&(me={...me,subtitle:ne}),ie&&(me={...me,badge:"Lead"}),me},B=Y=>{var ie;const ne=E.get(Y);return ne?(ie=s.find(me=>me.id===ne))==null?void 0:ie.name:void 0},R=g.map(Y=>{const ne=B(Y.id);return ne?{...Y,title:ne}:Y}),D=b.filter(Y=>Y.agentSession&&!Y.id.startsWith(c_)),K=Y=>Y==="online"?0:Y==="busy"?1:Y==="offline"?2:3,U=(Y,ne)=>{if(Y.agentSession===Hu)return-1;if(ne.agentSession===Hu)return 1;const ie=K(Y.presence)-K(ne.presence);if(ie!==0)return ie;const me=Y.lastMessageAt??"",Z=ne.lastMessageAt??"";return me!==Z?Z.localeCompare(me):Y.title.localeCompare(ne.title)},X=[...D].filter(Y=>u.isPinned(vg(Y))).sort(U).map(P),te=new Set(X.map(Y=>vg(Y))),Q=[...D].filter(Y=>!te.has(vg(Y))).sort(U).map(P),z=[];return X.length>0&&z.push({id:"pinned",label:"Pinned",rows:X}),R.length>0&&z.push({id:"channels",label:"Channels",rows:R}),Q.length>0&&z.push({id:"dms",label:"Direct messages",rows:Q}),v.length>0&&z.push({id:"huddles",label:"Group chats",rows:v}),z},[s,b,v,g,E,u,n]),T=w.useMemo(()=>N.reduce((V,H)=>V+H.rows.length,0),[N]),A=x??((G=JM(N).find(V=>!V.id.startsWith(rA)))==null?void 0:G.id)??null,M=w.useCallback(async V=>{if(V.id.startsWith(rA)&&V.agentSession&&r){const H=await r(V.agentSession);await c(),y(H);return}y(V.id)},[r,c]),L=w.useCallback(async(V,H)=>{const $=await d.createHuddle({name:V,memberSessions:H});await c(),y($.id),f(!1)},[d,c]),I=w.useMemo(()=>JM(N).find(V=>V.id===A),[N,A]),F=w.useMemo(()=>!S||(I==null?void 0:I.id)!==S||k.length===0?null:[S,...k],[I,S,k]);return i.jsxs("div",{className:"flex h-full w-full bg-background-dark","data-testid":"team-chat-page","data-loading":o?"true":"false","data-error":l?"true":"false",children:[i.jsx(Dve,{workspaceName:"Home",groups:N,activeConversationId:A,onSelectConversation:M,isPinned:V=>u.isPinned(vg(V)),onTogglePin:V=>u.toggle(vg(V)),headerAction:i.jsx(zt,{icon:ts,size:"xs",onClick:()=>f(!0),className:"hover:text-primary","data-testid":"new-group-button",title:"Create a multi-agent group chat","aria-label":"Create a multi-agent group chat"}),emptyState:T===0&&!o?i.jsx(ebe,{teamName:"This workspace"}):void 0}),i.jsx(hbe,{conversation:I,mentionables:t,mergeChannelIds:F}),h&&i.jsx(rbe,{onClose:()=>f(!1),onCreate:L})]})}function hbe({conversation:t,mentionables:e,mergeChannelIds:n}){return t?n&&n.length>0?i.jsx(pbe,{conversation:t,mentionables:e,channelIds:n}):i.jsx(fbe,{conversation:t,mentionables:e}):i.jsx("section",{className:"flex flex-1 items-center justify-center bg-background-dark text-sm text-text-secondary-dark","data-testid":"team-chat-right-panel","aria-label":"Conversation thread",children:"Select a conversation from the list to start chatting."})}function fbe({conversation:t,mentionables:e}){const{messages:n,agentThinking:s,hasMore:r,loadMore:a}=n7(t.id);return i.jsx(h7,{conversation:t,mentionables:e,messages:n,agentThinking:s,hasMore:r,onLoadMore:a})}function pbe({conversation:t,mentionables:e,channelIds:n}){const{messages:s,agentThinking:r,hasMore:a,loadMore:o}=Yve(n);return i.jsx(h7,{conversation:t,mentionables:e,messages:s,agentThinking:r,hasMore:a,onLoadMore:o})}function h7({conversation:t,mentionables:e,messages:n,agentThinking:s,hasMore:r,onLoadMore:a}){const{send:o,error:l,reset:c}=Ive(),[d,u]=w.useState(null);w.useEffect(()=>{u(null)},[t.id]);const h=w.useMemo(()=>gbe(l),[l]),f=t.kind==="dm"?t.title:void 0,p=w.useMemo(()=>d?n.find(b=>b.id===d):void 0,[n,d]),x=w.useMemo(()=>d?xve(n,d):[],[n,d]),y=w.useCallback(async b=>{const S=b.mentions.map(k=>k.id);try{await o(t.id,{content:b.content,mentions:S,threadId:d??void 0})}catch{}},[t.id,o,d]),m=w.useCallback(b=>{u(b.id)},[]),g=w.useCallback(()=>{u(null)},[]),v=d!==null;return i.jsxs("section",{className:"flex flex-1 bg-background-dark","data-testid":"team-chat-right-panel","aria-label":`Conversation with ${t.title}`,"data-thread-active":v?"true":"false",children:[i.jsxs("div",{className:"flex min-w-0 flex-1 flex-col bg-background-dark",children:[i.jsxs("header",{className:"flex items-center justify-between gap-4 border-b border-border-dark bg-background-dark/30 px-6 py-3 backdrop-blur-md",children:[i.jsxs("div",{className:"min-w-0 leading-tight",children:[i.jsx("h2",{className:"truncate text-base font-bold text-text-primary-dark",children:t.kind==="channel"?`#${t.title.replace(/^#+\s*/,"")}`:t.title}),t.subtitle&&i.jsx("p",{className:"truncate text-[11px] text-text-secondary-dark",children:t.subtitle})]}),i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx(u4,{label:"Search",icon:V_}),i.jsx(u4,{label:"Conversation info",icon:th})]})]}),i.jsx(vve,{channelId:t.id,agentName:f,layout:"flat",hideReplies:!0,onReplyInThread:m,messages:n,agentThinking:s,hasMore:r,onLoadMore:a,emptyState:i.jsx(tbe,{kind:t.kind==="dm"?"dm":"channel",recipientName:f})}),i.jsx(c7,{mentionables:e,onSend:y})]}),v&&i.jsx(mbe,{rootMessage:p,replies:x,mentionables:e,onClose:g,onSend:y}),h&&i.jsx(nbe,{message:h.message,detail:h.detail,onDismiss:c})]})}function u4({label:t,icon:e}){return i.jsx(zt,{type:"button",icon:e,"aria-label":t,title:t})}function mbe({rootMessage:t,replies:e,mentionables:n,onClose:s,onSend:r}){const a=e.length;return i.jsxs("aside",{"data-testid":"thread-panel","aria-label":"Thread",className:"flex w-[380px] shrink-0 flex-col border-l border-border-dark bg-background-dark",children:[i.jsxs("header",{className:"flex items-center justify-between gap-4 border-b border-border-dark bg-background-dark/30 px-4 py-3 backdrop-blur-md",children:[i.jsxs("div",{className:"leading-tight",children:[i.jsx("h3",{className:"text-sm font-bold text-text-primary-dark",children:"Thread"}),a>0&&i.jsxs("p",{className:"text-[11px] text-text-secondary-dark",children:[a," ",a===1?"reply":"replies"]})]}),i.jsx(zt,{type:"button",icon:cs,onClick:s,"data-testid":"thread-close","aria-label":"Close thread"})]}),i.jsxs("div",{className:"chat-scrollbar flex flex-1 flex-col gap-3 overflow-y-auto px-4 py-4",children:[t?i.jsx(h4,{message:t,isRoot:!0}):i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"Thread root unavailable."}),i.jsxs("div",{className:"flex items-center gap-3 py-1",children:[i.jsx("span",{className:"h-[1px] flex-1 bg-border-dark/30","aria-hidden":"true"}),i.jsxs("span",{className:"text-[10px] font-bold uppercase tracking-widest text-text-secondary-dark",children:[a," ",a===1?"reply":"replies"]}),i.jsx("span",{className:"h-[1px] flex-1 bg-border-dark/30","aria-hidden":"true"})]}),e.map(o=>i.jsx(h4,{message:o},o.id))]}),i.jsx(c7,{mentionables:n,onSend:r,placeholder:"Reply…"})]})}function h4({message:t,isRoot:e=!1}){const n=t.author.role!=="user",s=t.author.name??t.author.id,r=(()=>{try{return new Date(t.createdAt).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}catch{return""}})();return i.jsxs("div",{className:"flex flex-col","data-testid":`thread-msg-${t.id}`,"data-author-role":t.author.role,children:[i.jsxs("div",{className:"flex items-baseline gap-2",children:[i.jsx("span",{className:`text-[13px] font-bold ${n?"text-primary":"text-text-primary-dark"}`,children:s}),i.jsx("time",{className:"text-[10px] text-text-secondary-dark",children:r})]}),i.jsx("div",{className:"mt-0.5 max-w-full whitespace-pre-wrap break-words text-sm leading-relaxed text-text-primary-dark",children:i7(t.content)})]})}function gbe(t){if(!t)return null;const e=t;switch(e.code){case"validation_error":return{message:"Could not send message — request was rejected.",detail:e.message};case"payload_too_large":return{message:"Message is too large to send.",detail:e.message};case"channel_not_found":case"channel_archived":return{message:"This conversation is no longer available.",detail:e.message};case"forbidden":return{message:"You do not have permission to send here.",detail:e.message};case"rate_limited":return{message:"Slow down — too many sends in a short window.",detail:e.message};case"network_error":return{message:"Network error — message did not send.",detail:e.message};default:return{message:"Could not send message.",detail:t.message}}}function xbe(){return({}.VITE_CHAT_MODE??"").toString().toLowerCase()==="mock"?"mock":"real"}function ybe(){const t=({}.VITE_CHAT_BACKEND_URL??"").toString();return t?t.replace(/\/+$/,""):typeof window<"u"?window.location.origin:""}async function iA(t,e){var n;try{const r=await(await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).json();return((n=r==null?void 0:r.data)==null?void 0:n.id)??null}catch{return null}}function vbe(){const[t]=xh(),{teams:e}=U8(),{isCollapsed:n,collapseSidebar:s,expandSidebar:r}=N1();w.useEffect(()=>{const E=!n;return s(),()=>{E&&r()}},[]);const a=xbe(),o=a==="real"?ybe():void 0,l=w.useMemo(()=>Zne(e),[e]),c=w.useMemo(()=>Qne(e),[e]),d=w.useMemo(()=>{const E=new Set,N=[];for(const T of e)for(const A of T.members??[]){const M=A.sessionName;!M||E.has(M)||(E.add(M),N.push({agentSession:M,name:A.name,presence:X8(A.agentStatus),teamName:T.name,role:A.role}))}return N},[e]),u=w.useMemo(()=>e.map(E=>{var I;const N=(I=E.leaderIds)!=null&&I.length?E.leaderIds:E.leaderId?[E.leaderId]:[],T=new Set(N),A=E.members??[],M=A.filter(F=>F.sessionName&&(T.has(F.id)||F.hierarchyLevel===1)).map(F=>F.sessionName),L=A.filter(F=>F.sessionName).map(F=>F.sessionName);return{id:E.id,name:E.name,leaderSessions:M,memberSessions:L,parentTeamId:E.parentTeamId}}),[e]),h=t.get(Yl)||null,f=w.useCallback(async E=>{const N=d.find(A=>A.agentSession===E);return await iA("/api/chat/channels/dm/ensure",{agentSession:E,name:(N==null?void 0:N.name)??E})??""},[d]),p=w.useMemo(()=>u.map(E=>E.id),[u]),x=`${h??"__none__"}|${p.join(",")}`,[y,m]=w.useState(null),[g,v]=w.useState(null),b=a!=="real"||y===x;if(w.useEffect(()=>{if(a!=="real")return;let E=!1;return(async()=>{const N=await iA("/api/chat/channels/dm/ensure",{agentSession:Hu,name:K8,purpose:"Talk to the orchestrator"});await Promise.all(p.map(T=>iA("/api/chat/channels/team/ensure",{teamId:T}))),E||(N&&v(N),m(x))})(),()=>{E=!0}},[a,x,p]),!b)return i.jsx("div",{className:"flex h-full items-center justify-center text-sm text-text-secondary-dark",role:"status",children:"Opening chat…"});const S=h?cbe(h):lbe,k=h?null:g;return i.jsx(dbe,{backendURL:o,teamLabels:l,mentionables:c,initialWorkspaceId:S,initialConversationId:k,directoryAgents:d,teams:u,onEnsureDm:f})}async function hb(t){const e=await t.json();if(!t.ok||!(e!=null&&e.success))throw new Error((e==null?void 0:e.error)||`Request failed (${t.status})`);return e.data}const bbe=()=>{const[t,e]=w.useState(null),[n,s]=w.useState(!0),[r,a]=w.useState(null),[o,l]=w.useState(""),[c,d]=w.useState({}),[u,h]=w.useState(null),f=w.useCallback(async()=>{try{a(null);const m=await fetch("/api/slack/team-channels"),g=await hb(m),v=Array.isArray(g==null?void 0:g.teams)?g.teams:[],b=(g==null?void 0:g.settings)??{autoCreate:!0,channelPrefix:""};e({settings:b,teams:v}),l(b.channelPrefix??"")}catch(m){a(m instanceof Error?m.message:"Failed to load team channels")}finally{s(!1)}},[]);w.useEffect(()=>{f()},[f]);const p=async m=>{try{a(null);const g=await fetch("/api/slack/team-channels/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(m)}),v=await hb(g);e(b=>b&&{...b,settings:v}),l(v.channelPrefix??"")}catch(g){a(g instanceof Error?g.message:"Failed to save settings")}},x=async(m,g)=>{h(m);try{a(null);const v=await fetch("/api/slack/team-channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(g?{teamId:m,slackChannelId:g}:{teamId:m})});await hb(v),d(b=>({...b,[m]:""})),await f()}catch(v){a(v instanceof Error?v.message:"Failed to create channel")}finally{h(null)}},y=async m=>{if(!m.mapping)return;const g=m.mapping.autoCreated?window.confirm(`Also archive #${m.mapping.slackChannelName} in Slack?`):!1;h(m.teamId);try{a(null);const v=await fetch(`/api/slack/team-channels/${encodeURIComponent(m.teamId)}${g?"?archive=true":""}`,{method:"DELETE"});await hb(v),await f()}catch(v){a(v instanceof Error?v.message:"Failed to unlink channel")}finally{h(null)}};return i.jsxs(dt,{padding:"lg",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-4",children:[i.jsxs("div",{children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide",children:"Team Channels"}),i.jsxs("p",{className:"text-xs text-text-secondary-dark mt-1",children:["Each team gets its own Slack channel. Everyone on the team sees the conversation,",i.jsx("code",{className:"mx-1 text-xs bg-background-dark px-1 py-0.5 rounded",children:"@name"}),"picks a specific agent, and replies show up under each agent's own name."]})]}),i.jsx(de,{variant:"ghost",size:"sm",onClick:f,icon:an,"aria-label":"Reload team channels",children:"Reload"})]}),r&&i.jsx("div",{className:"mb-4",children:i.jsx(tt,{variant:"error",onClose:()=>a(null),children:r})}),n?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Loading team channels..."}):t?i.jsxs("div",{className:"space-y-5",children:[i.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between",children:[i.jsx(Vs,{id:"slack-team-channels-auto",label:"Auto-create a channel for every new team",checked:t.settings.autoCreate,onChange:m=>p({autoCreate:m.target.checked})}),i.jsxs("div",{className:"flex items-end gap-2",children:[i.jsxs("div",{children:[i.jsx("label",{htmlFor:"slack-team-channels-prefix",className:"block text-xs text-text-secondary-dark mb-1",children:"Channel name prefix"}),i.jsx(Ut,{id:"slack-team-channels-prefix",value:o,onChange:m=>l(m.target.value),placeholder:"e.g. crew-",className:"w-40"})]}),i.jsx(de,{variant:"secondary",size:"sm",disabled:o===(t.settings.channelPrefix??""),onClick:()=>p({channelPrefix:o}),children:"Save prefix"})]})]}),t.teams.length>0&&i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:[t.teams.filter(m=>m.mapping).length," of ",t.teams.length," teams have a channel.",t.teams.some(m=>!m.mapping)&&" Teams without one are listed below."]}),t.teams.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No teams yet. Create a team and its channel will appear here."}):i.jsx("ul",{className:"divide-y divide-border-dark",children:[...t.teams].sort((m,g)=>+!!g.mapping-+!!m.mapping).map(m=>i.jsxs("li",{className:"py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"text-sm font-medium truncate",children:m.teamName}),i.jsxs("div",{className:"text-xs text-text-secondary-dark",children:[m.memberCount," ",m.memberCount===1?"agent":"agents",m.mapping&&i.jsxs(i.Fragment,{children:[" · ",i.jsx(OT,{className:"inline w-3 h-3 -mt-0.5"}),m.mapping.slackChannelName," · ",m.mapping.autoCreated?"created by Crewly":"linked"]})]})]}),m.mapping?i.jsx(de,{variant:"danger-ghost",size:"sm",icon:yl,disabled:u===m.teamId,onClick:()=>y(m),children:"Unlink"}):i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(Ut,{"aria-label":`Slack channel ID to link for ${m.teamName}`,value:c[m.teamId]??"",onChange:g=>d(v=>({...v,[m.teamId]:g.target.value})),placeholder:"C0123… to link",className:"w-40"}),i.jsx(de,{variant:"secondary",size:"sm",icon:Gl,disabled:u===m.teamId||!(c[m.teamId]??"").trim(),onClick:()=>x(m.teamId,(c[m.teamId]??"").trim()),children:"Link"}),i.jsx(de,{variant:"primary",size:"sm",icon:OT,disabled:u===m.teamId,loading:u===m.teamId,onClick:()=>x(m.teamId),children:"Create channel"})]})]},m.teamId))})]}):null]})};async function bg(t){const e=await t.json();if(!t.ok||!(e!=null&&e.success))throw new Error((e==null?void 0:e.error)||`Request failed (${t.status})`);return e.data}function _be(t){const e=s=>s.toLowerCase().replace(/\s+/g,"-"),n={};for(const s of t)for(const r of s.members??[]){const a=r.sessionName||(r.id&&r.name&&s.name?`${e(s.name)}-${e(r.name)}-${r.id.substring(0,8)}`:"");a&&(n[a]={teamName:s.name??"Team",memberName:r.name??a})}return n}function aA(t){return t.some(e=>q8(e.agentSession))}const Sbe=({pendingInstalls:t=[]})=>{var P,B,R,D,K,U;const[e,n]=w.useState(null),[s,r]=w.useState({}),[a,o]=w.useState(!1);w.useEffect(()=>{let X=!1;return fetch("/api/teams").then(te=>te.json()).then(te=>{X||!(te!=null&&te.success)||!Array.isArray(te.data)||r(_be(te.data))}).catch(()=>{}),()=>{X=!0}},[]);const l=async()=>{o(!0),p(null);try{await bg(await fetch("/api/slack/cloud/agents/sync",{method:"POST"})),await S(!0)}catch(X){p(X instanceof Error?X.message:"Sync failed")}finally{o(!1)}},[c,d]=w.useState(null),[u,h]=w.useState(!0),[f,p]=w.useState(null),[x,y]=w.useState(""),[m,g]=w.useState(""),[v,b]=w.useState(!1),S=w.useCallback(async(X=!1)=>{var te,Q;try{p(null);const z=await fetch(`/api/slack/agent-identities${X?"?refresh=1":""}`),Y=await z.json();if(z.status===401||z.status===503){d((Y==null?void 0:Y.error)||"Unavailable"),n(null);return}if(!z.ok||!(Y!=null&&Y.success))throw new Error((Y==null?void 0:Y.error)||`Request failed (${z.status})`);d(null),n({cloud:(te=Y.data)==null?void 0:te.cloud,identities:Array.isArray((Q=Y.data)==null?void 0:Q.identities)?Y.data.identities:[]})}catch(z){p(z instanceof Error?z.message:"Failed to load agent identities")}finally{h(!1)}},[]);w.useEffect(()=>{S()},[S]);const k=async X=>{X.preventDefault(),b(!0);try{p(null);const te=await fetch("/api/slack/agent-identities/config-token",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:x,refreshToken:m})});await bg(te),y(""),g(""),await S()}catch(te){p(te instanceof Error?te.message:"Failed to save the configuration token")}finally{b(!1)}},E=async()=>{if(window.confirm("Remove the Slack app configuration token from Crewly Cloud?"))try{p(null),await bg(await fetch("/api/slack/agent-identities/config-token",{method:"DELETE"})),await S()}catch(X){p(X instanceof Error?X.message:"Failed to remove the token")}},N=async X=>{if(window.confirm(`Delete the Slack app for ${X.displayName}?`))try{p(null),await bg(await fetch(`/api/slack/agent-identities/${encodeURIComponent(X.agentSession)}`,{method:"DELETE"})),await S()}catch(te){p(te instanceof Error?te.message:"Failed to delete the identity")}},T=async X=>{if(window.confirm(`Remove ${X.displayName}'s bot from Slack? You can install it again later.`))try{p(null),await bg(await fetch(`/api/slack/agent-identities/${encodeURIComponent(X.agentSession)}/uninstall`,{method:"POST"})),await S()}catch(te){p(te instanceof Error?te.message:"Failed to uninstall the bot")}},A=!!((B=(P=e==null?void 0:e.cloud)==null?void 0:P.configToken)!=null&&B.configured),M=((D=(R=e==null?void 0:e.cloud)==null?void 0:R.configToken)==null?void 0:D.status)==="invalid",L=new Set(((e==null?void 0:e.identities)??[]).map(X=>X.agentSession)),I=t.filter(X=>!L.has(X.agentSession)),F=[...(e==null?void 0:e.identities)??[],...I.map(X=>{var te;return{agentSession:X.agentSession,displayName:((te=s[X.agentSession])==null?void 0:te.memberName)??X.agentSession,appId:"",status:"pending_install",installUrl:X.url,hasToken:!1}})],G=new Map;for(const X of F){const te=q8(X.agentSession)?K8:((K=s[X.agentSession])==null?void 0:K.teamName)??"Other agents";G.has(te)||G.set(te,[]),G.get(te).push(X)}const V=[...G.entries()].sort(([,X],[,te])=>Number(aA(te))-Number(aA(X))),H=F.filter(X=>X.status==="installed").length,$=F.filter(X=>X.status==="installed"&&X.reinstall);return i.jsxs(dt,{padding:"lg",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-4",children:[i.jsxs("div",{children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide",children:"Agent Identities"}),i.jsxs("p",{className:"text-xs text-text-secondary-dark mt-1",children:["Give each agent its own Slack bot user, so it shows up in the member list and can be",i.jsx("code",{className:"mx-1 text-xs bg-background-dark px-1 py-0.5 rounded",children:"@"}),"mentioned natively. Provisioned through Crewly Cloud; each new agent needs one install click from you."]})]}),i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(de,{variant:"ghost",size:"sm",onClick:l,loading:a,disabled:a,"aria-label":"Sync agents with Crewly Cloud",children:"Sync agents"}),i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>S(!0),icon:an,"aria-label":"Refresh agent identities",children:"Refresh"})]})]}),f&&i.jsx("div",{className:"mb-4",children:i.jsx(tt,{variant:"error",onClose:()=>p(null),children:f})}),u?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Loading agent identities..."}):c?i.jsx(tt,{variant:"warning",children:c}):e&&!((U=e.cloud)!=null&&U.enabled)?i.jsx(tt,{variant:"warning",children:"Agent identities are not enabled on Crewly Cloud yet."}):e?i.jsxs("div",{className:"space-y-5",children:[A?i.jsxs("div",{className:"flex items-center justify-between gap-3 text-sm",children:[i.jsxs("span",{children:[i.jsx(k1,{className:"inline w-4 h-4 -mt-0.5 mr-1"}),M?i.jsxs("span",{className:"text-red-400",children:["Configuration token is no longer valid",e.cloud.configToken.lastError?` (${e.cloud.configToken.lastError})`:"",". Paste a new one below."]}):i.jsx("span",{children:"Slack app configuration token stored on Crewly Cloud."})]}),i.jsx(de,{variant:"danger-ghost",size:"sm",icon:Vr,onClick:E,children:"Remove token"})]}):null,(!A||M)&&i.jsxs("form",{onSubmit:k,className:"space-y-3",children:[i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:["Generate an ",i.jsx("strong",{children:"App Configuration Token"})," at"," ",i.jsxs("a",{href:"https://api.slack.com/apps",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline inline-flex items-center gap-1",children:["api.slack.com/apps",i.jsx(ws,{className:"w-3 h-3"})]})," ","(“Your App Configuration Tokens” → Generate) and paste both values. Crewly Cloud keeps it refreshed."]}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsxs("div",{children:[i.jsx("label",{htmlFor:"slack-config-token",className:"block text-xs text-text-secondary-dark mb-1",children:"Access token (xoxe.xoxp-…)"}),i.jsx(Ut,{id:"slack-config-token",type:"password",value:x,onChange:X=>y(X.target.value),placeholder:"xoxe.xoxp-…",autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx("label",{htmlFor:"slack-config-refresh",className:"block text-xs text-text-secondary-dark mb-1",children:"Refresh token (xoxe-…)"}),i.jsx(Ut,{id:"slack-config-refresh",type:"password",value:m,onChange:X=>g(X.target.value),placeholder:"xoxe-…",autoComplete:"off",required:!0})]})]}),i.jsx(de,{type:"submit",size:"sm",disabled:v||!m.trim(),loading:v,children:v?"Saving…":"Save configuration token"})]}),F.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No agent identities yet. They are created automatically for members of teams that have a Slack channel."}):i.jsxs("div",{className:"space-y-4","data-testid":"slack-identity-groups",children:[i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:[H," of ",F.length," agents installed. Installed agents join their team channel by themselves."]}),$.length>0&&i.jsxs("div",{className:"mb-3 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2",children:[i.jsxs("p",{className:"text-xs text-amber-300",children:[i.jsxs("strong",{children:[$.length," installed ",$.length===1?"agent needs":"agents need"," re-authorization."]})," ","They are running but a newer permission is missing, so part of what they do fails — reading an image you send them, for instance. Their rows below carry an “Authorize” link."]}),i.jsx("p",{className:"mt-1 text-xs text-amber-300/80",children:$.map(X=>X.displayName||X.agentSession).join(" · ")})]}),V.map(([X,te])=>{const Q=te.filter(Y=>Y.status==="installed").length,z=aA(te);return i.jsxs("details",{open:Q<te.length,className:z?"group rounded-lg border border-primary/50 bg-primary/5 px-3":"group","data-testid":z?"slack-identity-group-orchestrator":void 0,children:[i.jsxs("summary",{className:"cursor-pointer list-none flex items-center justify-between gap-3 py-2 border-b border-border-dark",children:[i.jsxs("span",{className:"text-sm font-medium flex items-center gap-2",children:[X,z&&i.jsx("span",{className:"text-xs font-normal text-primary border border-primary/50 rounded px-1.5 py-0.5",children:"talks to this machine"})]}),i.jsx("span",{className:`text-xs ${Q===te.length?"text-green-400":"text-text-secondary-dark"}`,children:Q===te.length?"all installed":`${Q} / ${te.length} installed`})]}),i.jsx("ul",{className:"divide-y divide-border-dark",children:te.map(Y=>i.jsxs("li",{className:"py-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsxs("div",{className:"text-sm truncate",children:[Y.status==="installed"&&i.jsx("span",{className:"text-green-400 mr-1",children:"✓"}),Y.displayName]}),i.jsxs("div",{className:"text-xs text-text-secondary-dark",children:[Y.status==="installed"&&!Y.reinstall&&`Installed · bot ${Y.botUserId??""}`,Y.status==="installed"&&Y.reinstall&&"Installed · new permissions need your re-authorization",Y.status==="pending_install"&&"Waiting for your install click",Y.status==="error"&&`Install failed${Y.error?`: ${Y.error}`:""}`]})]}),i.jsxs("div",{className:"flex items-center gap-2",children:[(Y.status!=="installed"||Y.reinstall)&&Y.installUrl&&i.jsxs("a",{href:Y.installUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-primary hover:underline inline-flex items-center gap-1",children:[Y.status==="installed"?"Re-authorize":"Install"," ",Y.displayName,i.jsx(ws,{className:"w-3 h-3"})]}),Y.status==="installed"&&i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>T(Y),"aria-label":`Uninstall ${Y.displayName} from Slack`,children:"Uninstall"}),Y.appId&&i.jsx(de,{variant:"danger-ghost",size:"sm",icon:Vr,onClick:()=>N(Y),"aria-label":`Delete identity for ${Y.displayName}`,children:"Delete"})]})]},Y.agentSession))})]},X)})]})]}):null]})};async function fb(t){const e=await t.json();if(!t.ok||!(e!=null&&e.success))throw new Error((e==null?void 0:e.error)||`Request failed (${t.status})`);return e.data}function wbe(){return`${window.location.origin}/settings?tab=slack`}const Cbe=({status:t,onRefresh:e})=>{const[n,s]=w.useState(null),[r,a]=w.useState(null),[o,l]=w.useState(""),c=async(b,S)=>{s(b),a(null);try{await S()}catch(k){a(k instanceof Error?k.message:"Request failed")}finally{s(null)}},d=()=>c("connect",async()=>{const b=await fetch(`/api/slack/cloud/install-url?returnUrl=${encodeURIComponent(wbe())}`),{url:S}=await fb(b);window.location.assign(S)}),u=b=>c("workspace",async()=>{await fb(await fetch("/api/slack/cloud/workspace",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({slackTeamId:b})})),await e(!0)}),h=b=>c("primary",async()=>{await fb(await fetch("/api/slack/cloud/primary",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({primary:b})})),await e()}),f=()=>c("disconnect",async()=>{window.confirm("Remove this Slack workspace from your Crewly account? Every Crewly instance serving it loses Slack.")&&(await fb(await fetch("/api/slack/cloud/workspace",{method:"DELETE"})),await e())}),p=(t==null?void 0:t.workspace)??null,x=!!(t!=null&&t.cloudConnected),y=(t==null?void 0:t.sourceMode)==="env",m=t!=null&&t.availableWorkspaces&&t.availableWorkspaces.length>0?t.availableWorkspaces:null,g=t!=null&&t.workspaces&&t.workspaces.length>1?t.workspaces:null,v=(b,S)=>i.jsxs("div",{className:"flex items-center gap-2","data-testid":"slack-cloud-workspace-picker",children:[i.jsx("div",{className:"min-w-[12rem]",children:i.jsxs(pn,{value:o||S||"",onChange:k=>l(k.target.value),"aria-label":"Slack workspace for this instance",disabled:n!==null,children:[!S&&!o&&i.jsx("option",{value:"",children:"Choose a workspace…"}),b.map(k=>i.jsx("option",{value:k.slackTeamId,children:k.slackTeamName},k.slackTeamId))]})}),i.jsx(de,{size:"sm",onClick:()=>u(o||S||""),loading:n==="workspace",disabled:n!==null||!(o||S)||(o||S)===S,children:"Use this workspace"})]});return i.jsxs(dt,{padding:"lg",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-4",children:[i.jsxs("div",{children:[i.jsxs("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide",children:[i.jsx(eh,{className:"inline w-4 h-4 -mt-0.5 mr-1"}),"Slack via Crewly Cloud"]}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Install the Crewly app in your Slack workspace once; every Crewly instance signed in to your Crewly account gets team channels and agent identities automatically — no tokens to copy."})]}),i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>e(!0),icon:an,"aria-label":"Refresh Cloud Slack status",children:"Refresh"})]}),r&&i.jsx("div",{className:"mb-4",children:i.jsx(tt,{variant:"error",onClose:()=>a(null),children:r})}),t?y?i.jsxs(tt,{variant:"info",children:[i.jsx("code",{className:"text-xs bg-background-dark px-1 py-0.5 rounded",children:"CREWLY_SLACK_SOURCE=env"})," is set: this instance only uses its self-hosted Slack app tokens (see Advanced below)."]}):x?!p&&m?i.jsxs("div",{className:"space-y-3",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["Your Crewly account has ",m.length," Slack workspaces. Pick the one this instance should serve, or connect another one."]}),v(m,null),i.jsx(de,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:ws,children:"Connect another workspace"})]}):p?i.jsxs("div",{className:"space-y-5",children:[i.jsxs("div",{className:"space-y-2","data-testid":"slack-cloud-workspace-card",children:[i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Workspace"}),i.jsx("span",{className:"text-sm font-medium",children:p.slackTeamName})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot user"}),i.jsx("span",{className:"text-sm font-medium font-mono",children:p.botUserId})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Events"}),i.jsx("span",{className:"text-sm font-medium",children:t.connected&&t.transport==="cloud"?"Delivered by Crewly Cloud (no Socket Mode)":t.connected?"Self-hosted Socket Mode (Cloud config ignored)":"Not connected on this instance yet"})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Agent identities"}),i.jsxs("span",{className:"text-sm font-medium",children:[p.agentIdentities," installed"]})]}),i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"This instance"}),i.jsxs("span",{className:"text-sm font-medium",children:[t.instanceId?i.jsx("code",{className:"text-xs",children:t.instanceId}):"not registered",t.lastHeartbeatAt&&i.jsxs("span",{className:"text-xs text-text-secondary-dark ml-2",children:["· registered ",new Date(t.lastHeartbeatAt).toLocaleString()]})]})]}),t.registryError&&i.jsxs("p",{className:"text-xs text-amber-400/80",children:["Registry: ",t.registryError]})]}),i.jsxs("div",{className:"space-y-2",children:[g&&i.jsxs(i.Fragment,{children:[i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:["Your account has ",g.length," workspaces. This instance serves one of them:"]}),v(g,p.slackTeamId)]}),i.jsx(de,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:ws,children:"Connect another workspace"})]}),i.jsx("div",{className:"flex items-start gap-3",children:i.jsx(Vs,{id:"slack-cloud-primary",checked:t.primary,disabled:n!==null,onChange:b=>h(b.target.checked),label:"Make this the primary instance","aria-label":"Make this the primary instance"})}),i.jsx("p",{className:"text-xs text-text-secondary-dark -mt-3",children:"Direct messages to the Crewly bot and channels no team owns go to the primary instance. Team channels always reach the instance running that team."}),i.jsx("div",{className:"flex items-center gap-3",children:i.jsx(de,{variant:"danger-ghost",size:"sm",icon:yl,onClick:f,loading:n==="disconnect",disabled:n!==null,children:"Disconnect workspace"})})]}):i.jsxs("div",{className:"space-y-3",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No Slack workspace is connected to your Crewly account yet."}),i.jsx(de,{onClick:d,loading:n==="connect",disabled:n!==null,icon:ws,children:n==="connect"?"Opening Slack...":"Connect Slack"}),t.configError&&i.jsxs("p",{className:"text-xs text-amber-400/80",children:["Last Cloud check failed: ",t.configError]})]}):i.jsxs(tt,{variant:"warning",children:["Log in to Crewly Cloud first (",i.jsx("a",{href:"/cloud",className:"underline",children:"Settings → Cloud"}),") — Slack is installed through your Crewly account."]}):i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Loading Cloud Slack status..."})]})};function f4(){try{return new URLSearchParams(window.location.search).get("slack")==="connected"}catch{return!1}}const kbe=()=>{const[t,e]=w.useState({connected:!1}),[n,s]=w.useState(null),[r,a]=w.useState(!0),[o,l]=w.useState(!1),[c,d]=w.useState(null),[u,h]=w.useState(()=>f4()),[f,p]=w.useState(!1),[x,y]=w.useState({botToken:"",appToken:"",signingSecret:"",defaultChannel:""}),m=w.useCallback(async()=>{var T,A,M,L,I,F,G;try{d(null);const H=await(await fetch("/api/slack/status")).json();H.success?e({connected:((T=H.data)==null?void 0:T.isConfigured)||!1,workspaceName:(A=H.data)==null?void 0:A.workspaceName,botName:(M=H.data)==null?void 0:M.botName,channels:(L=H.data)==null?void 0:L.channels,lastMessageAt:(I=H.data)==null?void 0:I.lastMessageAt,messagesSent:(F=H.data)==null?void 0:F.messagesSent,messagesReceived:(G=H.data)==null?void 0:G.messagesReceived}):e({connected:!1,error:H.error})}catch{e({connected:!1,error:"Failed to fetch status"})}finally{a(!1)}},[]),g=w.useCallback(async(T=!1)=>{try{const A=await fetch(`/api/slack/cloud/status${T?"?refresh=1":""}`),M=await A.json();A.ok&&(M!=null&&M.success)&&M.data&&typeof M.data.cloudConnected=="boolean"?s(M.data):s(null)}catch{s(null)}},[]),v=w.useCallback(async(T=!1)=>{await g(T),await m()},[g,m]);w.useEffect(()=>{g(f4()),m()},[m,g]),w.useEffect(()=>{((n==null?void 0:n.activeSource)==="env"||n&&!n.workspace&&(n.local.env||n.local.saved))&&p(!0)},[n]);const b=T=>{const{name:A,value:M}=T.target;y(L=>({...L,[A]:M}))},S=async T=>{T.preventDefault(),l(!0),d(null);try{const A=await fetch("/api/slack/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({botToken:x.botToken,appToken:x.appToken,signingSecret:x.signingSecret,defaultChannelId:x.defaultChannel||void 0})}),M=await A.json();if(!A.ok||!M.success)throw new Error(M.error||"Connection failed");y({botToken:"",appToken:"",signingSecret:"",defaultChannel:""}),await m()}catch(A){d(A instanceof Error?A.message:"Failed to connect to Slack")}finally{l(!1)}},k=async()=>{if(window.confirm("Are you sure you want to disconnect from Slack?"))try{d(null);const T=await fetch("/api/slack/disconnect",{method:"POST"}),A=await T.json();if(!T.ok||!A.success)throw new Error(A.error||"Disconnect failed");await m()}catch(T){d(T instanceof Error?T.message:"Failed to disconnect")}};if(r)return i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(Ht,{text:"Loading Slack status..."})});const E=(n==null?void 0:n.activeSource)==="cloud",N=i.jsxs("details",{open:f,onToggle:T=>p(T.currentTarget.open),className:"group","data-testid":"slack-advanced",children:[i.jsx("summary",{className:"cursor-pointer text-sm font-medium text-text-secondary-dark hover:text-text-primary-dark select-none",children:"Advanced: self-hosted app"}),i.jsxs("div",{className:"mt-4 space-y-6",children:[i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:["Run your own Slack app with Socket Mode instead of Crewly Cloud. Set"," ",i.jsx("code",{className:"text-xs bg-background-dark px-1 py-0.5 rounded",children:"CREWLY_SLACK_SOURCE=env"})," to keep using it even when a Cloud workspace exists."]}),i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Setup Instructions"}),i.jsxs("ol",{className:"list-decimal list-inside space-y-3 text-sm text-text-secondary-dark",children:[i.jsxs("li",{children:["Create a Slack App at"," ",i.jsxs("a",{href:"https://api.slack.com/apps",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline inline-flex items-center gap-1",children:["api.slack.com/apps",i.jsx(ws,{className:"w-3 h-3"})]})]}),i.jsx("li",{children:"Enable Socket Mode in your app settings and create an App Token (starts with xapp-)"}),i.jsxs("li",{children:["Add Bot Token Scopes under OAuth & Permissions:",i.jsxs("ul",{className:"list-disc list-inside ml-4 mt-1.5 space-y-1",children:[i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"chat:write"})," - Send messages"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"channels:read"})," - View channels"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"app_mentions:read"})," - Respond to mentions"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"im:read"}),", ",i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"im:write"})," - Direct messages"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"files:read"})," - Receive images from Slack"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"files:write"})," - Upload images to Slack"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"reactions:write"})," - Typing/completion indicators (optional)"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"channels:manage"}),", ",i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"channels:join"})," - Create and join team channels"]}),i.jsxs("li",{children:[i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"chat:write.customize"})," - Let each agent post under its own name and icon"]})]}),i.jsxs("p",{className:"text-xs text-amber-400/80 mt-1.5 ml-4",children:["Note: Adding ",i.jsx("code",{className:"text-xs bg-background-dark px-1 py-0.5 rounded",children:"files:read"})," and ",i.jsx("code",{className:"text-xs bg-background-dark px-1 py-0.5 rounded",children:"files:write"})," scopes requires reinstalling the app to your workspace."]})]}),i.jsx("li",{children:"Install the app to your workspace"}),i.jsx("li",{children:"Copy the Bot Token (xoxb-...), App Token (xapp-...), and Signing Secret"})]})]}),i.jsx(dt,{padding:"lg",children:i.jsxs("form",{onSubmit:S,className:"space-y-4",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Self-hosted app credentials"}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"botToken",required:!0,children:"Bot Token (xoxb-...)"}),i.jsx(Ut,{id:"botToken",name:"botToken",type:"password",value:x.botToken,onChange:b,placeholder:"xoxb-your-bot-token",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"appToken",required:!0,children:"App Token (xapp-...)"}),i.jsx(Ut,{id:"appToken",name:"appToken",type:"password",value:x.appToken,onChange:b,placeholder:"xapp-your-app-token",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"signingSecret",required:!0,children:"Signing Secret"}),i.jsx(Ut,{id:"signingSecret",name:"signingSecret",type:"password",value:x.signingSecret,onChange:b,placeholder:"Your signing secret",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"defaultChannel",children:"Default Channel (optional)"}),i.jsx(Ut,{id:"defaultChannel",name:"defaultChannel",type:"text",value:x.defaultChannel,onChange:b,placeholder:"C1234567890 or #crewly"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Channel ID or name where notifications will be sent by default"})]}),i.jsx("div",{className:"pt-2",children:i.jsx(de,{type:"submit",disabled:o||!x.botToken||!x.appToken||!x.signingSecret,loading:o,fullWidth:!0,children:o?"Connecting...":"Connect to Slack"})})]})})]})]});return i.jsxs("div",{className:"space-y-6 max-w-3xl",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-lg font-semibold",children:"Slack Integration"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Connect Slack to talk to the orchestrator and your teams from your phone or desktop Slack app."})]}),c&&i.jsx(tt,{variant:"error",onClose:()=>d(null),children:c}),u&&i.jsx(tt,{variant:"success",onClose:()=>h(!1),children:"Slack workspace connected to your Crewly account. This instance picks it up automatically."}),t.connected?i.jsxs(tt,{variant:"success",children:["Connected to Slack",E?" via Crewly Cloud":""]}):i.jsx(tt,{variant:"warning",children:"Not connected to Slack"}),i.jsx(Cbe,{status:n,onRefresh:v}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Connection Details"}),i.jsxs("div",{className:"space-y-3",children:[t.workspaceName&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Workspace"}),i.jsx("span",{className:"text-sm font-medium",children:t.workspaceName})]}),t.botName&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot Name"}),i.jsx("span",{className:"text-sm font-medium",children:t.botName})]}),t.channels&&t.channels.length>0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Channels"}),i.jsx("span",{className:"text-sm font-medium",children:t.channels.join(", ")})]}),t.messagesSent!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Sent"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesSent})]}),t.messagesReceived!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Received"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesReceived})]}),t.lastMessageAt&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Last Activity"}),i.jsx("span",{className:"text-sm font-medium",children:new Date(t.lastMessageAt).toLocaleString()})]})]})]}),i.jsx(bbe,{}),i.jsx(Sbe,{pendingInstalls:(n==null?void 0:n.pendingInstalls)??[]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(de,{variant:"secondary",onClick:()=>v(),icon:an,children:"Refresh Status"}),!E&&i.jsx(de,{variant:"danger",onClick:k,icon:yl,children:"Disconnect"})]}),N]}):i.jsx("div",{className:"space-y-6",children:N})]})},bf="/api/whatsapp",_f=Object.freeze({STATUS:`${bf}/status`,CONNECT:`${bf}/connect`,DISCONNECT:`${bf}/disconnect`,PENDING_DRAFTS:`${bf}/drafts?status=pending`,draftSend:t=>`${bf}/drafts/${encodeURIComponent(t)}/send`,draftDiscard:t=>`${bf}/drafts/${encodeURIComponent(t)}/discard`}),f7=Object.freeze({INBOX:"inbox",ASSISTANT:"assistant"}),Ebe=f7.INBOX,Ug=Object.freeze({TITLE:"收件箱模式 · Inbox mode",ZH:"只读+起草,发送前需要你确认;不会自动回复任何人。",EN:"Read-only + drafts: nothing is sent until you confirm, and Crewly never auto-replies to anyone.",TOS:"Connects as a linked device through an unofficial client (like WhatsApp Web). WhatsApp does not allow automated messaging and may ban numbers that do it, which is why every send waits for you.",ASSISTANT_WARNING:"Assistant mode: incoming messages are routed to the orchestrator and answered automatically. Disconnect and reconnect to switch to inbox mode."});function Abe(t){return Array.isArray(t)?t.filter(e=>!!e&&typeof e=="object"&&typeof e.id=="string"):[]}const Tbe=()=>i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-4 space-y-1","data-testid":"whatsapp-inbox-notice",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide",children:Ug.TITLE}),i.jsx("p",{className:"text-sm",children:Ug.ZH}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:Ug.EN}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:Ug.TOS})]}),Mbe=()=>{const[t,e]=w.useState({connected:!1}),[n,s]=w.useState(!0),[r,a]=w.useState(!1),[o,l]=w.useState(null),[c,d]=w.useState([]),[u,h]=w.useState(null),f=w.useCallback(async()=>{var g,v,b,S,k,E,N;try{l(null);const A=await(await fetch(_f.STATUS)).json();A.success?e({connected:((g=A.data)==null?void 0:g.isConfigured)||((v=A.data)==null?void 0:v.connected)||!1,phoneNumber:(b=A.data)==null?void 0:b.phoneNumber,qrCode:(S=A.data)==null?void 0:S.qrCode,messagesSent:(k=A.data)==null?void 0:k.messagesSent,messagesReceived:(E=A.data)==null?void 0:E.messagesReceived,mode:((N=A.data)==null?void 0:N.mode)??null}):e({connected:!1,error:A.error})}catch{e({connected:!1,error:"Failed to fetch WhatsApp status"})}finally{s(!1)}},[]),p=w.useCallback(async()=>{try{const v=await(await fetch(_f.PENDING_DRAFTS)).json();d(v!=null&&v.success?Abe(v.data):[])}catch{d([])}},[]);w.useEffect(()=>{f(),p()},[f,p]);const x=async(g,v)=>{h(g.id),l(null);try{const b=v==="send"?_f.draftSend(g.id):_f.draftDiscard(g.id),S=await fetch(b,{method:"POST",headers:{...t_}}),k=await S.json();if(!S.ok||!k.success)throw new Error(k.error||`Could not ${v} draft ${g.code}`);await p(),v==="send"&&await f()}catch(b){l(b instanceof Error?b.message:`Could not ${v} draft ${g.code}`),await p()}finally{h(null)}},y=async()=>{var g;a(!0),l(null);try{const v=await fetch(_f.CONNECT,{method:"POST",headers:{"Content-Type":"application/json",...t_},body:JSON.stringify({mode:Ebe})}),b=await v.json();if(!v.ok||!b.success)throw new Error(b.error||"Connection failed");(g=b.data)!=null&&g.qrCode&&e(S=>({...S,qrCode:b.data.qrCode})),await f()}catch(v){l(v instanceof Error?v.message:"Failed to connect WhatsApp")}finally{a(!1)}},m=async()=>{if(window.confirm("Are you sure you want to disconnect from WhatsApp?"))try{l(null);const g=await fetch(_f.DISCONNECT,{method:"POST",headers:{...t_}}),v=await g.json();if(!g.ok||!v.success)throw new Error(v.error||"Disconnect failed");await f()}catch(g){l(g instanceof Error?g.message:"Failed to disconnect")}};return n?i.jsx("div",{className:"flex justify-center py-8",children:i.jsx(Ht,{size:"md",text:"Loading WhatsApp status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(tt,{variant:"error",onClose:()=>l(null),children:o}),t.mode===f7.ASSISTANT?i.jsx(tt,{variant:"warning",children:Ug.ASSISTANT_WARNING}):i.jsx(Tbe,{}),t.connected?i.jsxs("div",{className:"space-y-5",children:[i.jsx(tt,{variant:"success",children:"Connected to WhatsApp"}),i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-5",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide mb-3",children:"Connection Details"}),i.jsxs("div",{className:"space-y-2",children:[t.mode&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Mode"}),i.jsx("span",{className:"text-sm font-medium","data-testid":"whatsapp-mode",children:t.mode})]}),t.phoneNumber&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Phone Number"}),i.jsx("span",{className:"text-sm font-medium",children:t.phoneNumber})]}),t.messagesSent!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Sent"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesSent})]}),t.messagesReceived!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Received"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesReceived})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(de,{variant:"secondary",onClick:f,icon:an,children:"Refresh Status"}),i.jsx(de,{variant:"danger",onClick:m,icon:yl,children:"Disconnect"})]})]}):i.jsx("div",{className:"space-y-5",children:t.qrCode?i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-6 flex flex-col items-center gap-4",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide",children:"Scan QR Code"}),i.jsx("p",{className:"text-xs text-text-secondary-dark text-center max-w-sm",children:"Open WhatsApp on your phone, go to Settings > Linked Devices > Link a Device, then scan this QR code."}),i.jsx("div",{className:"bg-white p-4 rounded-lg",children:i.jsx("img",{src:`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(t.qrCode)}`,alt:"WhatsApp QR Code",className:"w-48 h-48","data-testid":"whatsapp-qr-code"})}),i.jsx(de,{variant:"secondary",onClick:f,icon:an,children:"Refresh QR Code"})]}):i.jsxs("div",{className:"space-y-4",children:[i.jsx(tt,{variant:"warning",children:"Not connected to WhatsApp"}),i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-5",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide mb-3",children:"How to Connect"}),i.jsxs("ol",{className:"list-decimal list-inside space-y-2 text-sm text-text-secondary-dark",children:[i.jsx("li",{children:'Click "Connect WhatsApp" below to generate a QR code'}),i.jsx("li",{children:"Open WhatsApp on your phone"}),i.jsxs("li",{children:["Go to ",i.jsx("strong",{children:"Settings"})," > ",i.jsx("strong",{children:"Linked Devices"})," > ",i.jsx("strong",{children:"Link a Device"})]}),i.jsx("li",{children:"Scan the QR code displayed here"})]})]}),i.jsx(de,{onClick:y,disabled:r,loading:r,icon:Uz,fullWidth:!0,children:r?"Initializing...":"Connect WhatsApp"})]})}),i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-5","data-testid":"whatsapp-drafts",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide mb-3",children:"待发送草稿 · Pending drafts"}),c.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No pending drafts. Replies your agents draft appear here for you to send or discard."}):i.jsx("ul",{className:"space-y-3",children:c.map(g=>i.jsxs("li",{className:"border border-border-dark rounded-lg p-3 space-y-2","data-testid":`whatsapp-draft-${g.code}`,children:[i.jsxs("div",{className:"flex items-center justify-between gap-2",children:[i.jsxs("span",{className:"text-sm font-medium",children:[i.jsx("span",{className:"text-text-secondary-dark mr-2",children:g.code}),"→ ",g.recipient]}),g.createdBy&&i.jsxs("span",{className:"text-xs text-text-secondary-dark",children:["by ",g.createdBy]})]}),i.jsx("p",{className:"text-sm whitespace-pre-wrap break-words",children:g.text}),g.lastError&&i.jsxs("p",{className:"text-xs text-rose-400",children:["Last attempt failed: ",g.lastError]}),i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(de,{size:"sm",icon:g0,onClick:()=>x(g,"send"),disabled:u!==null,loading:u===g.id,"aria-label":`发送 ${g.code}`,children:"发送"}),i.jsx(de,{size:"sm",variant:"secondary",icon:Vr,onClick:()=>x(g,"discard"),disabled:u!==null,"aria-label":`丢弃 ${g.code}`,children:"丢弃"})]})]},g.id))})]})]})},Nbe="/api/messengers/status",jbe="/api/messengers/discord/connect",Rbe="/api/messengers/discord/disconnect",Ibe=()=>{const[t,e]=w.useState({connected:!1}),[n,s]=w.useState(!0),[r,a]=w.useState(!1),[o,l]=w.useState(null),[c,d]=w.useState({token:"",allowedChannels:""}),u=w.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Nbe)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(k=>k.platform==="discord");e(S?{connected:S.connected,botName:(x=S.details)==null?void 0:x.botName,botId:(y=S.details)==null?void 0:y.botId,messagesSent:(m=S.details)==null?void 0:m.messagesSent,messagesReceived:(g=S.details)==null?void 0:g.messagesReceived}:{connected:!1})}else e({connected:!1,error:b.error||"Failed to fetch status"})}catch{e({connected:!1,error:"Failed to fetch status"})}finally{s(!1)}},[]);w.useEffect(()=>{u()},[u]);const h=x=>{const{name:y,value:m}=x.target;d(g=>({...g,[y]:m}))},f=async x=>{x.preventDefault(),a(!0),l(null);try{const y={token:c.token};c.allowedChannels.trim()&&(y.allowedChannels=c.allowedChannels.split(",").map(v=>v.trim()).filter(Boolean));const m=await fetch(jbe,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(y)}),g=await m.json();if(!m.ok||!g.success)throw new Error(g.error||"Connection failed");d({token:"",allowedChannels:""}),await u()}catch(y){l(y instanceof Error?y.message:"Failed to connect to Discord")}finally{a(!1)}},p=async()=>{if(window.confirm("Are you sure you want to disconnect from Discord?"))try{l(null);const x=await fetch(Rbe,{method:"POST"}),y=await x.json();if(!x.ok||!y.success)throw new Error(y.error||"Disconnect failed");await u()}catch(x){l(x instanceof Error?x.message:"Failed to disconnect")}};return n?i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(Ht,{text:"Loading Discord status..."})}):i.jsxs("div",{className:"space-y-6 max-w-3xl",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Discord Integration"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Connect a Discord bot to communicate with the orchestrator via your Discord server."})]}),o&&i.jsx(tt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(tt,{variant:"success",children:"Connected to Discord"}),i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Connection Details"}),i.jsxs("div",{className:"space-y-3",children:[t.botName&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot Name"}),i.jsx("span",{className:"text-sm font-medium",children:t.botName})]}),t.botId&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot ID"}),i.jsx("span",{className:"text-sm font-medium",children:t.botId})]}),t.messagesSent!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Sent"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesSent})]}),t.messagesReceived!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Received"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesReceived})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(de,{variant:"secondary",onClick:u,icon:an,children:"Refresh Status"}),i.jsx(de,{variant:"danger",onClick:p,icon:yl,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(tt,{variant:"warning",children:"Not connected to Discord"}),i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Setup Instructions"}),i.jsxs("ol",{className:"list-decimal list-inside space-y-3 text-sm text-text-secondary-dark",children:[i.jsxs("li",{children:["Go to the"," ",i.jsxs("a",{href:"https://discord.com/developers/applications",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline inline-flex items-center gap-1",children:["Discord Developer Portal",i.jsx(ws,{className:"w-3 h-3"})]})]}),i.jsx("li",{children:"Create a New Application and navigate to the Bot section"}),i.jsx("li",{children:'Click "Reset Token" to generate a bot token and copy it'}),i.jsxs("li",{children:["Under OAuth2 → URL Generator, select the"," ",i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"bot"})," scope and grant permissions:",i.jsxs("ul",{className:"list-disc list-inside ml-4 mt-1.5 space-y-1",children:[i.jsx("li",{children:i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"Send Messages"})}),i.jsx("li",{children:i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"Read Message History"})}),i.jsx("li",{children:i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"Add Reactions"})})]})]}),i.jsx("li",{children:"Use the generated URL to invite the bot to your server"}),i.jsx("li",{children:"Paste the bot token below and click Connect"})]})]}),i.jsx(dt,{padding:"lg",children:i.jsxs("form",{onSubmit:f,className:"space-y-4",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Connect to Discord"}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"token",required:!0,children:"Bot Token"}),i.jsx(Ut,{id:"token",name:"token",type:"password",value:c.token,onChange:h,placeholder:"MTEyMzQ1Njc4OTAxMjM0NTY3OC...",required:!0,autoComplete:"off"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"The bot token from Discord Developer Portal"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"allowedChannels",children:"Allowed Channels (optional)"}),i.jsx(Ut,{id:"allowedChannels",name:"allowedChannels",type:"text",value:c.allowedChannels,onChange:h,placeholder:"1234567890123456789, 9876543210987654321"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Comma-separated channel IDs to restrict the bot to specific channels"})]}),i.jsx("div",{className:"pt-2",children:i.jsx(de,{type:"submit",disabled:r||!c.token,loading:r,fullWidth:!0,children:r?"Connecting...":"Connect to Discord"})})]})})]})]})},Pbe="/api/messengers/status",Lbe="/api/messengers/telegram/connect",Dbe="/api/messengers/telegram/disconnect",Obe=()=>{const[t,e]=w.useState({connected:!1}),[n,s]=w.useState(!0),[r,a]=w.useState(!1),[o,l]=w.useState(null),[c,d]=w.useState({botToken:"",allowedChats:""}),u=w.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Pbe)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(k=>k.platform==="telegram");e(S?{connected:S.connected,botName:(x=S.details)==null?void 0:x.botName,botId:(y=S.details)==null?void 0:y.botId,messagesSent:(m=S.details)==null?void 0:m.messagesSent,messagesReceived:(g=S.details)==null?void 0:g.messagesReceived}:{connected:!1})}else e({connected:!1,error:b.error||"Failed to fetch status"})}catch{e({connected:!1,error:"Failed to fetch status"})}finally{s(!1)}},[]);w.useEffect(()=>{u()},[u]);const h=x=>{const{name:y,value:m}=x.target;d(g=>({...g,[y]:m}))},f=async x=>{x.preventDefault(),a(!0),l(null);try{const y={token:c.botToken};c.allowedChats.trim()&&(y.allowedChats=c.allowedChats.split(",").map(v=>v.trim()).filter(Boolean));const m=await fetch(Lbe,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(y)}),g=await m.json();if(!m.ok||!g.success)throw new Error(g.error||"Connection failed");d({botToken:"",allowedChats:""}),await u()}catch(y){l(y instanceof Error?y.message:"Failed to connect to Telegram")}finally{a(!1)}},p=async()=>{if(window.confirm("Are you sure you want to disconnect from Telegram?"))try{l(null);const x=await fetch(Dbe,{method:"POST"}),y=await x.json();if(!x.ok||!y.success)throw new Error(y.error||"Disconnect failed");await u()}catch(x){l(x instanceof Error?x.message:"Failed to disconnect")}};return n?i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(Ht,{text:"Loading Telegram status..."})}):i.jsxs("div",{className:"space-y-6 max-w-3xl",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Telegram Integration"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Connect a Telegram bot to communicate with the orchestrator via Telegram."})]}),o&&i.jsx(tt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(tt,{variant:"success",children:"Connected to Telegram"}),i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Connection Details"}),i.jsxs("div",{className:"space-y-3",children:[t.botName&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot Name"}),i.jsx("span",{className:"text-sm font-medium",children:t.botName})]}),t.botId&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Bot ID"}),i.jsx("span",{className:"text-sm font-medium",children:t.botId})]}),t.messagesSent!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-b border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Sent"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesSent})]}),t.messagesReceived!==void 0&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Messages Received"}),i.jsx("span",{className:"text-sm font-medium",children:t.messagesReceived})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(de,{variant:"secondary",onClick:u,icon:an,children:"Refresh Status"}),i.jsx(de,{variant:"danger",onClick:p,icon:yl,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(tt,{variant:"warning",children:"Not connected to Telegram"}),i.jsxs(dt,{padding:"lg",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Setup Instructions"}),i.jsxs("ol",{className:"list-decimal list-inside space-y-3 text-sm text-text-secondary-dark",children:[i.jsxs("li",{children:["Open Telegram and search for"," ",i.jsxs("a",{href:"https://t.me/BotFather",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline inline-flex items-center gap-1",children:["@BotFather",i.jsx(ws,{className:"w-3 h-3"})]})]}),i.jsxs("li",{children:["Send ",i.jsx("code",{className:"text-xs bg-background-dark px-1.5 py-0.5 rounded",children:"/newbot"})," and follow the prompts to create a bot"]}),i.jsx("li",{children:"Copy the HTTP API token provided by BotFather"}),i.jsx("li",{children:"Paste the token below and click Connect"})]})]}),i.jsx(dt,{padding:"lg",children:i.jsxs("form",{onSubmit:f,className:"space-y-4",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-4",children:"Connect to Telegram"}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"botToken",required:!0,children:"Bot Token"}),i.jsx(Ut,{id:"botToken",name:"botToken",type:"password",value:c.botToken,onChange:h,placeholder:"123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",required:!0,autoComplete:"off"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"The HTTP API token from @BotFather"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"allowedChats",children:"Allowed Chats (optional)"}),i.jsx(Ut,{id:"allowedChats",name:"allowedChats",type:"text",value:c.allowedChats,onChange:h,placeholder:"-1001234567890, -1009876543210"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Comma-separated chat IDs to restrict the bot to specific groups"})]}),i.jsx("div",{className:"pt-2",children:i.jsx(de,{type:"submit",disabled:r||!c.botToken,loading:r,fullWidth:!0,children:r?"Connecting...":"Connect to Telegram"})})]})})]})]})},Bbe=()=>{const[t,e]=w.useState({connected:!1}),[n,s]=w.useState(!0),[r,a]=w.useState(!1),[o,l]=w.useState(null),[c,d]=w.useState("pubsub"),[u,h]=w.useState("service_account"),[f,p]=w.useState(""),[x,y]=w.useState(""),[m,g]=w.useState(""),[v,b]=w.useState(""),[S,k]=w.useState(!1),[E,N]=w.useState(null),[T,A]=w.useState(!1),[M,L]=w.useState(null),[I,F]=w.useState(""),[G,V]=w.useState(""),H=w.useRef(null),$=w.useCallback(async()=>{var te;try{l(null);const z=await(await fetch("/api/messengers/status")).json();if(z.success&&Array.isArray(z.data)){const Y=z.data.find(ne=>ne.platform==="google-chat");if(Y){let ne=Y.details||{};if(Y.connected&&((te=Y.details)==null?void 0:te.mode)==="pubsub")try{const me=await(await fetch("/api/messengers/google-chat/status")).json();me.success&&(ne={...ne,...me.data})}catch{}e({connected:Y.connected,mode:ne.mode,authMode:ne.authMode,serviceAccountEmail:ne.serviceAccountEmail,pullActive:ne.pullActive,pullPaused:ne.pullPaused,subscriptionName:ne.subscriptionName,projectId:ne.projectId,consecutiveFailures:ne.consecutiveFailures,lastPullAt:ne.lastPullAt})}}}catch{e({connected:!1,error:"Failed to fetch status"})}finally{s(!1)}},[]);w.useEffect(()=>{$()},[$]),w.useEffect(()=>(t.connected&&t.mode==="pubsub"&&(H.current=setInterval(()=>{$()},1e4)),()=>{H.current&&(clearInterval(H.current),H.current=null)}),[t.connected,t.mode,$]);const P=async te=>{te.preventDefault(),a(!0),l(null);try{let Q;c==="webhook"?Q={webhookUrl:f}:u==="adc"?(Q={authMode:"adc"},c==="pubsub"&&(Q.projectId=m,Q.subscriptionName=v),G.trim()&&(Q.serviceAccountEmail=G.trim())):c==="service-account"?Q={serviceAccountKey:x}:Q={serviceAccountKey:x,projectId:m,subscriptionName:v};const z=await fetch("/api/messengers/google-chat/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Q)}),Y=await z.json();if(!z.ok||!Y.success)throw new Error(Y.error||"Connection failed");p(""),y(""),g(""),b(""),V(""),await $()}catch(Q){l(Q instanceof Error?Q.message:"Failed to connect")}finally{a(!1)}},B=async()=>{if(window.confirm("Are you sure you want to disconnect from Google Chat?"))try{l(null);const te=await fetch("/api/messengers/google-chat/disconnect",{method:"POST"}),Q=await te.json();if(!te.ok||!Q.success)throw new Error(Q.error||"Disconnect failed");await $()}catch(te){l(te instanceof Error?te.message:"Failed to disconnect")}},R=async()=>{k(!0),N(null);try{const te=await fetch("/api/messengers/google-chat/pull",{method:"POST"}),Q=await te.json();if(!te.ok||!Q.success)throw new Error(Q.error||"Pull failed");const z=Q.messagesReceived||0;N(z>0?`Pulled ${z} message${z!==1?"s":""}`:"No new messages"),await $()}catch(te){N(te instanceof Error?te.message:"Pull failed")}finally{k(!1)}},D=async()=>{if(I.trim()){A(!0),L(null);try{const te=await fetch("/api/messengers/google-chat/test-send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({space:I.trim(),text:"Test message from Crewly"})}),Q=await te.json();if(!te.ok||!Q.success)throw new Error(Q.error||"Test send failed");L("Message sent successfully")}catch(te){L(te instanceof Error?te.message:"Test send failed")}finally{A(!1)}}},K=te=>{switch(te){case"webhook":return"Webhook";case"service-account":return"Service Account";case"pubsub":return"Pub/Sub (Bidirectional)";default:return"Unknown"}},U=te=>te==="adc"?"Application Default Credentials":"Service Account Key",X=()=>c==="webhook"?!!f:u==="adc"?c==="pubsub"?!!(m&&v):!0:c==="service-account"?!!x:!!(x&&m&&v);return n?i.jsx("div",{className:"flex justify-center py-8",children:i.jsx(Ht,{size:"md",text:"Loading Google Chat status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(tt,{variant:"error",onClose:()=>l(null),children:i.jsx("span",{className:"text-sm",children:o})}),t.connected?i.jsxs("div",{className:"space-y-5",children:[i.jsx(tt,{variant:"success",children:i.jsx("span",{className:"font-medium text-sm",children:"Connected to Google Chat"})}),i.jsxs(dt,{padding:"lg",className:"bg-background-dark",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide mb-3",children:"Connection Details"}),i.jsxs("div",{className:"space-y-2",children:[i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Mode"}),i.jsx("span",{className:"text-sm font-medium",children:K(t.mode)})]}),(t.mode==="pubsub"||t.mode==="service-account")&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Auth"}),i.jsx("span",{className:"text-sm font-medium",children:U(t.authMode)})]}),t.serviceAccountEmail&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Impersonating"}),i.jsx("span",{className:"text-sm font-mono truncate max-w-[280px]","data-testid":"sa-email-display",children:t.serviceAccountEmail})]}),t.mode==="pubsub"&&i.jsxs(i.Fragment,{children:[i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Project ID"}),i.jsx("span",{className:"text-sm font-mono",children:t.projectId})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Subscription"}),i.jsx("span",{className:"text-sm font-mono text-text-secondary-dark/80 truncate max-w-[240px]",children:t.subscriptionName})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Pull Loop"}),i.jsxs("span",{className:"flex items-center gap-2",children:[i.jsx("span",{className:`w-2 h-2 rounded-full ${t.pullPaused?"bg-amber-400":t.pullActive?"bg-emerald-400 animate-pulse":"bg-text-secondary-dark"}`}),i.jsx("span",{className:`text-sm font-medium ${t.pullPaused?"text-amber-400":t.pullActive?"text-emerald-400":"text-text-secondary-dark"}`,children:t.pullPaused?"Paused (errors)":t.pullActive?"Running":"Stopped"})]})]}),i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Last Pull"}),i.jsx("span",{className:"text-sm font-mono","data-testid":"last-pull-at",children:t.lastPullAt?new Date(t.lastPullAt).toLocaleTimeString():"Never"})]}),(t.consecutiveFailures??0)>0&&i.jsxs("div",{className:"flex items-center justify-between py-2 border-t border-border-dark",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Consecutive Failures"}),i.jsx("span",{className:"text-sm font-medium text-amber-400","data-testid":"consecutive-failures",children:t.consecutiveFailures})]})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[t.mode==="pubsub"&&i.jsx(de,{variant:"primary",onClick:R,disabled:S,loading:S,icon:vh,"data-testid":"pull-now-btn",children:S?"Pulling...":"Pull Now"}),i.jsx(de,{variant:"secondary",onClick:$,icon:an,children:"Refresh Status"}),i.jsx(de,{variant:"danger",onClick:B,icon:yl,children:"Disconnect"})]}),E&&i.jsx("div",{className:`text-sm px-3 py-2 rounded-lg ${E.startsWith("Pulled")?"bg-emerald-500/10 text-emerald-400":E==="No new messages"?"bg-blue-500/10 text-blue-400":"bg-rose-500/10 text-rose-400"}`,"data-testid":"pull-result",children:E}),(t.mode==="pubsub"||t.mode==="service-account")&&i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-4 space-y-3",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide",children:"Test Send"}),i.jsxs("div",{className:"flex items-end gap-2",children:[i.jsxs("div",{className:"flex-1",children:[i.jsx(bt,{htmlFor:"test-send-space",children:"Space Name"}),i.jsx(Ut,{id:"test-send-space",name:"testSendSpace",type:"text",value:I,onChange:te=>F(te.target.value),placeholder:"spaces/AAAA...",autoComplete:"off","data-testid":"test-send-space"})]}),i.jsx(de,{variant:"primary",onClick:D,disabled:T||!I.trim(),loading:T,icon:g0,"data-testid":"test-send-btn",children:T?"Sending...":"Test Send"})]}),M&&i.jsx("div",{className:`text-sm px-3 py-2 rounded-lg ${M==="Message sent successfully"?"bg-emerald-500/10 text-emerald-400":"bg-rose-500/10 text-rose-400"}`,"data-testid":"test-send-result",children:M})]})]}):i.jsxs("div",{className:"space-y-5",children:[i.jsx(tt,{variant:"warning",children:i.jsx("span",{className:"font-medium text-sm",children:"Not connected to Google Chat"})}),i.jsx(ao,{"aria-label":"Connection mode",options:[{value:"pubsub",label:"Pub/Sub (Recommended)","data-testid":"mode-pubsub"},{value:"webhook",label:"Webhook","data-testid":"mode-webhook"},{value:"service-account",label:"Service Account","data-testid":"mode-service-account"}],value:c,onChange:d}),i.jsxs("div",{className:"bg-background-dark border border-border-dark rounded-lg p-5",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wide mb-3",children:c==="pubsub"?"Pub/Sub Setup (Bidirectional)":c==="webhook"?"Webhook Setup (Send-only)":"Service Account Setup (Send-only)"}),c==="pubsub"?i.jsxs("ol",{className:"list-decimal list-inside space-y-2 text-sm text-text-secondary-dark",children:[i.jsxs("li",{children:["Go to ",i.jsx("strong",{children:"Google Cloud Console"})," > ",i.jsx("strong",{children:"APIs & Services"})]}),i.jsxs("li",{children:["Enable the ",i.jsx("strong",{children:"Google Chat API"})," and ",i.jsx("strong",{children:"Cloud Pub/Sub API"})]}),i.jsxs("li",{children:["Create a ",i.jsx("strong",{children:"Service Account"})," and download the JSON key"]}),i.jsxs("li",{children:["In the Chat API settings, create a ",i.jsx("strong",{children:"Chat App"})," and select ",i.jsx("strong",{children:"Cloud Pub/Sub"})," as the connection type"]}),i.jsxs("li",{children:["Enter a ",i.jsx("strong",{children:"Pub/Sub topic name"})," (e.g., ",i.jsx("code",{className:"bg-surface-dark px-1 rounded",children:"projects/my-project/topics/google-chat-events"}),")"]}),i.jsxs("li",{children:["Create a ",i.jsx("strong",{children:"Pub/Sub subscription"})," for that topic (pull mode)"]}),i.jsxs("li",{children:["Grant the service account ",i.jsx("strong",{children:"Pub/Sub Subscriber"})," role on the subscription"]}),i.jsx("li",{children:"Fill in the details below"})]}):c==="webhook"?i.jsxs("ol",{className:"list-decimal list-inside space-y-2 text-sm text-text-secondary-dark",children:[i.jsx("li",{children:"Open your Google Chat space"}),i.jsxs("li",{children:["Click the space name > ",i.jsx("strong",{children:"Apps & integrations"})," > ",i.jsx("strong",{children:"Manage webhooks"})]}),i.jsx("li",{children:"Create a new webhook and copy the URL"}),i.jsx("li",{children:"Paste the webhook URL below"})]}):i.jsxs("ol",{className:"list-decimal list-inside space-y-2 text-sm text-text-secondary-dark",children:[i.jsxs("li",{children:["Go to the ",i.jsx("strong",{children:"Google Cloud Console"})," > ",i.jsx("strong",{children:"APIs & Services"})]}),i.jsxs("li",{children:["Enable the ",i.jsx("strong",{children:"Google Chat API"})]}),i.jsxs("li",{children:["Create a ",i.jsx("strong",{children:"Service Account"})," and download the JSON key"]}),i.jsx("li",{children:"Grant the service account access to your Chat space"}),i.jsx("li",{children:"Paste the JSON key contents below"})]})]}),i.jsxs("form",{onSubmit:P,className:"space-y-4",children:[c==="webhook"?i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"gchat-webhook",required:!0,children:"Webhook URL"}),i.jsx(Ut,{id:"gchat-webhook",name:"webhookUrl",type:"url",value:f,onChange:te=>p(te.target.value),placeholder:"https://chat.googleapis.com/v1/spaces/...",required:!0,autoComplete:"off"})]}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(bt,{children:"Authentication Method"}),i.jsx(ao,{size:"sm",className:"mt-1","aria-label":"Authentication method",options:[{value:"service_account",label:"Service Account Key","data-testid":"auth-service-account"},{value:"adc",label:"Application Default Credentials","data-testid":"auth-adc"}],value:u,onChange:h})]}),c==="pubsub"&&i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"gchat-project-id",required:!0,children:"GCP Project ID"}),i.jsx(Ut,{id:"gchat-project-id",name:"projectId",type:"text",value:m,onChange:te=>g(te.target.value),placeholder:"my-gcp-project-id",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"gchat-subscription",required:!0,children:"Pub/Sub Subscription Name"}),i.jsx(Ut,{id:"gchat-subscription",name:"subscriptionName",type:"text",value:v,onChange:te=>b(te.target.value),placeholder:"google-chat-events-sub",required:!0,autoComplete:"off"}),i.jsx("p",{className:"mt-1 text-xs text-text-secondary-dark",children:"Just the subscription name, not the full resource path"})]})]}),u==="adc"?i.jsxs(i.Fragment,{children:[i.jsxs("div",{className:"bg-blue-500/10 border border-blue-500/30 rounded-lg p-4",children:[i.jsx("p",{className:"text-sm text-blue-300 mb-2",children:"Using Application Default Credentials from your local gcloud CLI."}),i.jsx("p",{className:"text-xs text-text-secondary-dark mb-2",children:"Run this command if you haven't already:"}),i.jsx("code",{className:"block bg-background-dark px-3 py-2 rounded text-xs text-text-primary-dark font-mono break-all",children:"gcloud auth application-default login --scopes=https://www.googleapis.com/auth/chat.bot,https://www.googleapis.com/auth/pubsub,https://www.googleapis.com/auth/cloud-platform"})]}),i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"gchat-sa-email",children:"Service Account Email (for impersonation)"}),i.jsx(Ut,{id:"gchat-sa-email",name:"serviceAccountEmail",type:"email",value:G,onChange:te=>V(te.target.value),placeholder:"chatbot@project.iam.gserviceaccount.com",autoComplete:"off","data-testid":"sa-email-input"}),i.jsx("p",{className:"mt-1 text-xs text-text-secondary-dark",children:"Required for sending messages. Your user needs the Service Account Token Creator IAM role."})]})]}):i.jsxs("div",{children:[i.jsx(bt,{htmlFor:"gchat-sa-key",required:!0,children:"Service Account Key (JSON)"}),i.jsx(Xs,{id:"gchat-sa-key",name:"serviceAccountKey",value:x,onChange:te=>y(te.target.value),placeholder:'{"type": "service_account", "project_id": "...", ...}',required:!0,rows:6,className:"font-mono"})]})]}),i.jsx(de,{type:"submit",disabled:r||!X(),loading:r,fullWidth:!0,children:r?"Connecting...":"Connect Google Chat"})]})]})]})},Fbe="/api/google/status",Ube="/api/google/connect-url",zbe="/api/google/disconnect",Hbe="/api/google/default",Gbe="/connections?platform=google-workspace",Wbe="google",_g=[{id:"gmail",name:"Gmail",blurb:"Read your mail and send on your behalf",restricted:!0},{id:"calendar",name:"Calendar",blurb:"Read your calendar and manage events",restricted:!1},{id:"drive",name:"Drive, Docs, Sheets & Slides",blurb:"Search and read your files, and create new ones",restricted:!0}];function Vbe(t,e={}){var s;const n=new URLSearchParams({returnUrl:`${t}${Gbe}`});return(s=e.products)!=null&&s.length&&n.set("products",e.products.join(",")),e.replace&&n.set("replace","1"),e.loginHint&&n.set("loginHint",e.loginHint),e.chooseAccount&&n.set("chooseAccount","1"),`${Ube}?${n.toString()}`}const $be=()=>{const[t,e]=w.useState({connected:!1,cloudConnected:!1,connections:[]}),[n,s]=w.useState(!0),[r,a]=w.useState(!1),[o,l]=w.useState(!1),[c,d]=w.useState(null),[u,h]=w.useState(null),f=w.useCallback(async()=>{try{d(null);const v=await fetch(Fbe),b=await v.json();if(v.ok&&b.success){const S=b.data;e({...S,connections:S.connections??[]})}else e({connected:!1,cloudConnected:!1,connections:[]}),d(b.hint||b.message||b.error||"Failed to fetch Google status")}catch{e({connected:!1,cloudConnected:!1,connections:[]}),d("Failed to fetch Google status")}finally{s(!1)}},[]);w.useEffect(()=>{f();try{const v=new URLSearchParams(window.location.search).get(Wbe);v==="connected"?h("Google account connected."):v==="error"&&d("Google connection failed. Please try again.")}catch{}},[f]);const p=async(v={})=>{var b;a(!0),d(null);try{const S=await fetch(Vbe(window.location.origin,v)),k=await S.json();if(!S.ok||!k.success||!((b=k.data)!=null&&b.url))throw new Error(k.hint||k.message||k.error||"Could not start Google sign-in");window.location.href=k.data.url}catch(S){d(S instanceof Error?S.message:"Could not start Google sign-in"),a(!1)}},x=async(v,b)=>{var N;const S=v.products.filter(T=>T!==b),k=((N=_g.find(T=>T.id===b))==null?void 0:N.name)??b;if(S.length===0){await y(v.email);return}const E=_g.filter(T=>S.includes(T.id)).map(T=>T.name).join(" and ");window.confirm(`Remove ${k} from ${v.email}?
4919
4919
 
@@ -4960,4 +4960,4 @@ Deployed to staging
4960
4960
  95% code coverage`})]}),T&&i.jsx("div",{"data-testid":"create-mission-error",children:i.jsx(tt,{variant:"error",children:T})})]})}),i.jsxs(fc,{children:[i.jsx(de,{variant:"ghost",size:"sm",onClick:e,disabled:E,children:"Cancel"}),i.jsx(de,{variant:"primary",size:"sm",onClick:G,loading:E,"data-testid":"create-mission-submit",children:E?"Creating...":"Create Mission"})]})]}):null},hV={number:"count",percentage:"%",boolean:"done",currency:"$"},XF={number:"Number",percentage:"Percentage",boolean:"Yes / No",currency:"Currency"},YF={title:"",metricType:"number",baseline:"0",target:"",unit:hV.number,measurementSource:"manual"};function rje(t){if(!t)return"never";try{return new Date(t).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return t}}function Ag(t){if(t.trim()==="")return null;const e=Number(t);return Number.isFinite(e)?e:null}const ije=({missionId:t,onChanged:e})=>{const[n,s]=w.useState([]),[r,a]=w.useState(!0),[o,l]=w.useState(null),[c,d]=w.useState(null),[u,h]=w.useState(!1),[f,p]=w.useState(!1),[x,y]=w.useState(YF),[m,g]=w.useState(null),[v,b]=w.useState(""),[S,k]=w.useState(""),[E,N]=w.useState(null),[T,A]=w.useState(null),[M,L]=w.useState(null),I=w.useCallback(async()=>{l(null);try{const R=await yt.getKeyResults(t);s(R)}catch(R){l(R instanceof Error?R.message:"Failed to load key results")}finally{a(!1)}},[t]);w.useEffect(()=>{a(!0),I()},[I]);const F=w.useCallback(async R=>{h(!0),d(null);try{return await R(),await I(),e==null||e(),!0}catch(D){return d(D instanceof Error?D.message:"Request failed"),!1}finally{h(!1)}},[I,e]),G=async()=>{const R=Ag(x.baseline),D=Ag(x.target);if(!x.title.trim()){d("Title is required");return}if(R===null||D===null){d("Baseline and target must be numbers");return}if(R===D){d("Baseline and target must be different");return}if(!x.unit.trim()){d("Unit is required");return}const K={title:x.title.trim(),metricType:x.metricType,baseline:R,target:D,unit:x.unit.trim(),measurementSource:x.measurementSource};await F(async()=>{await yt.createKeyResult(t,K)})&&(y(YF),p(!1))},V=R=>{d(null),N(null),g(R.id),b(String(R.current)),k("")},H=async R=>{const D=Ag(v);if(D===null){d("Measurement value must be a number");return}await F(async()=>{await yt.measureKeyResult(t,R,{value:D,source:"user",...S.trim()?{note:S.trim()}:{}})})&&g(null)},$=R=>{d(null),g(null),N(R.id),A({target:String(R.target),current:String(R.current),measurementSource:R.measurementSource})},P=async R=>{if(!T)return;const D=Ag(T.target),K=Ag(T.current);if(D===null||K===null){d("Target and current must be numbers");return}if(D===R.baseline){d("Target must differ from the baseline");return}await F(async()=>{await yt.updateKeyResult(t,R.id,{...D!==R.target?{target:D}:{},...K!==R.current?{current:K}:{},...T.measurementSource!==R.measurementSource?{measurementSource:T.measurementSource}:{}})})&&(N(null),A(null))},B=async()=>{if(!M)return;const R=M;await F(async()=>{await yt.deleteKeyResult(t,R)})&&L(null)};return i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark","data-testid":"key-results-section",children:[i.jsxs("div",{className:"flex items-center justify-between mb-3 gap-2",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide flex items-center gap-1.5",children:[i.jsx(x2,{className:"h-4 w-4"}),"Key Results (",n.length,")"]}),i.jsx(de,{variant:"ghost",size:"sm",icon:f?cs:ts,onClick:()=>{p(R=>!R),d(null)},"data-testid":"kr-add-toggle",children:f?"Cancel":"Add KR"})]}),c&&i.jsx("div",{className:"mb-3","data-testid":"kr-action-error",children:i.jsx(tt,{variant:"error",onClose:()=>d(null),children:c})}),f&&i.jsxs("div",{className:"mb-4 rounded-lg border border-border-dark bg-background-dark/60 p-3 space-y-2","data-testid":"kr-add-form",children:[i.jsx(ys,{"aria-label":"KR title",placeholder:"e.g. Reach $5k MRR",value:x.title,onChange:R=>y(D=>({...D,title:R.target.value})),fullWidth:!0,"data-testid":"kr-new-title"}),i.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-2",children:[i.jsx(pn,{"aria-label":"Metric type",value:x.metricType,onChange:R=>{const D=R.target.value;y(K=>({...K,metricType:D,unit:hV[D]}))},"data-testid":"kr-new-metric",children:fse.map(R=>i.jsx("option",{value:R,children:XF[R]},R))}),i.jsx(ys,{"aria-label":"Baseline",type:"number",placeholder:"Baseline",value:x.baseline,onChange:R=>y(D=>({...D,baseline:R.target.value})),"data-testid":"kr-new-baseline"}),i.jsx(ys,{"aria-label":"Target",type:"number",placeholder:"Target",value:x.target,onChange:R=>y(D=>({...D,target:R.target.value})),"data-testid":"kr-new-target"}),i.jsx(ys,{"aria-label":"Unit",placeholder:"Unit",value:x.unit,onChange:R=>y(D=>({...D,unit:R.target.value})),"data-testid":"kr-new-unit"})]}),i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(pn,{"aria-label":"Measurement source",value:x.measurementSource,onChange:R=>y(D=>({...D,measurementSource:R.target.value})),"data-testid":"kr-new-source",children:X3.map(R=>i.jsx("option",{value:R,children:jk[R]},R))}),i.jsx(de,{variant:"primary",size:"sm",onClick:G,disabled:u,"data-testid":"kr-new-submit",children:u?"Saving…":"Create KR"})]})]}),r?i.jsx("p",{className:"text-sm text-text-secondary-dark","data-testid":"kr-loading",children:"Loading key results…"}):o?i.jsx("div",{"data-testid":"kr-error",children:i.jsxs(tt,{variant:"error",children:[o,i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>{a(!0),I()},className:"mt-2",children:"Retry"})]})}):n.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark","data-testid":"kr-empty",children:"No key results yet. Add one to make this mission measurable."}):i.jsx("div",{className:"overflow-x-auto",children:i.jsxs("table",{className:"w-full text-sm","data-testid":"kr-table",children:[i.jsx("thead",{children:i.jsxs("tr",{className:"text-left text-[11px] uppercase tracking-wide text-text-secondary-dark border-b border-border-dark",children:[i.jsx("th",{className:"py-2 pr-3 font-medium",children:"Key result"}),i.jsx("th",{className:"py-2 pr-3 font-medium",children:"Type"}),i.jsx("th",{className:"py-2 pr-3 font-medium whitespace-nowrap",children:"Baseline → Current → Target"}),i.jsx("th",{className:"py-2 pr-3 font-medium min-w-[140px]",children:"Progress"}),i.jsx("th",{className:"py-2 pr-3 font-medium",children:"Status"}),i.jsx("th",{className:"py-2 pr-3 font-medium",children:"Source"}),i.jsx("th",{className:"py-2 pr-3 font-medium whitespace-nowrap",children:"Last measured"}),i.jsx("th",{className:"py-2 font-medium text-right",children:"Actions"})]})}),i.jsx("tbody",{children:n.map(R=>{var te;const D=tj(R),K=(te=R.measurements)==null?void 0:te[0],U=m===R.id,X=E===R.id&&T!==null;return i.jsxs(jn.Fragment,{children:[i.jsxs("tr",{className:"border-b border-border-dark/60 align-top","data-testid":`kr-row-${R.id}`,children:[i.jsx("td",{className:"py-2 pr-3 text-text-primary-dark font-medium",children:R.title}),i.jsx("td",{className:"py-2 pr-3 text-text-secondary-dark",children:XF[R.metricType]}),i.jsxs("td",{className:"py-2 pr-3 font-mono text-xs text-text-primary-dark whitespace-nowrap","data-testid":`kr-values-${R.id}`,children:[tx(R.baseline,R.metricType,R.unit),i.jsx("span",{className:"text-text-secondary-dark",children:" → "}),i.jsx("span",{className:"font-semibold",children:tx(R.current,R.metricType,R.unit)}),i.jsx("span",{className:"text-text-secondary-dark",children:" → "}),tx(R.target,R.metricType,R.unit)]}),i.jsx("td",{className:"py-2 pr-3",children:i.jsx(Gx,{percent:D,status:R.status,"data-testid":`kr-progress-${R.id}`})}),i.jsx("td",{className:"py-2 pr-3",children:i.jsx(ft,{variant:pse[R.status],size:"sm","data-testid":`kr-status-${R.id}`,children:xM[R.status]})}),i.jsx("td",{className:"py-2 pr-3 text-xs text-text-secondary-dark",children:jk[R.measurementSource]??R.measurementSource}),i.jsx("td",{className:"py-2 pr-3 text-xs text-text-secondary-dark whitespace-nowrap","data-testid":`kr-last-${R.id}`,children:rje(K==null?void 0:K.measuredAt)}),i.jsx("td",{className:"py-2 text-right whitespace-nowrap",children:i.jsxs("div",{className:"inline-flex items-center gap-1",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:hY,onClick:()=>V(R),disabled:u,"data-testid":`kr-measure-${R.id}`,"aria-label":"Record measurement",children:"Measure"}),i.jsx(de,{variant:"ghost",size:"icon",className:"h-8 w-8",icon:E1,onClick:()=>$(R),disabled:u,"data-testid":`kr-edit-${R.id}`,"aria-label":"Edit key result"}),i.jsx(de,{variant:"danger-ghost",size:"icon",className:"h-8 w-8",icon:Vr,onClick:()=>L(R.id),disabled:u,"data-testid":`kr-delete-${R.id}`,"aria-label":"Delete key result"})]})})]}),U&&i.jsx("tr",{className:"border-b border-border-dark/60 bg-background-dark/40","data-testid":`kr-measure-form-${R.id}`,children:i.jsx("td",{colSpan:8,className:"py-2 px-2",children:i.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[i.jsx("span",{className:"text-xs text-text-secondary-dark",children:"Record measurement:"}),i.jsx(ys,{"aria-label":"Measurement value",type:"number",value:v,onChange:Q=>b(Q.target.value),className:"w-32","data-testid":`kr-measure-value-${R.id}`}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:R.unit}),i.jsx(ys,{"aria-label":"Measurement note",placeholder:"Note (optional)",value:S,onChange:Q=>k(Q.target.value),className:"flex-1 min-w-[160px]","data-testid":`kr-measure-note-${R.id}`}),i.jsx(de,{variant:"primary",size:"sm",icon:vd,onClick:()=>H(R.id),disabled:u,"data-testid":`kr-measure-submit-${R.id}`,children:u?"Saving…":"Save"}),i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>g(null),disabled:u,children:"Cancel"})]})})}),X&&T&&i.jsx("tr",{className:"border-b border-border-dark/60 bg-background-dark/40","data-testid":`kr-edit-form-${R.id}`,children:i.jsx("td",{colSpan:8,className:"py-2 px-2",children:i.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[i.jsx("span",{className:"text-xs text-text-secondary-dark",children:"Edit:"}),i.jsx("label",{className:"text-xs text-text-secondary-dark",children:"Target"}),i.jsx(ys,{"aria-label":"Edit target",type:"number",value:T.target,onChange:Q=>A(z=>z&&{...z,target:Q.target.value}),className:"w-28","data-testid":`kr-edit-target-${R.id}`}),i.jsx("label",{className:"text-xs text-text-secondary-dark",children:"Current"}),i.jsx(ys,{"aria-label":"Edit current",type:"number",value:T.current,onChange:Q=>A(z=>z&&{...z,current:Q.target.value}),className:"w-28","data-testid":`kr-edit-current-${R.id}`}),i.jsx(pn,{"aria-label":"Edit measurement source",value:T.measurementSource,onChange:Q=>A(z=>z&&{...z,measurementSource:Q.target.value}),"data-testid":`kr-edit-source-${R.id}`,children:X3.map(Q=>i.jsx("option",{value:Q,children:jk[Q]},Q))}),i.jsx(de,{variant:"primary",size:"sm",icon:vd,onClick:()=>P(R),disabled:u,"data-testid":`kr-edit-submit-${R.id}`,children:u?"Saving…":"Save"}),i.jsx(de,{variant:"ghost",size:"sm",onClick:()=>{N(null),A(null)},disabled:u,children:"Cancel"})]})})})]},R.id)})})]})}),i.jsx(W1,{isOpen:M!==null,title:"Delete key result",message:"This removes the key result and its measurement history. This cannot be undone.",confirmLabel:"Delete",confirmVariant:"danger",loading:u,onCancel:()=>L(null),onConfirm:B})]})},aje={continue:"Continue",adjust_strategy:"Adjust strategy",replan:"Replan",escalate:"Escalate"};function JF(t,e){return e.get(t)??t.slice(0,8)}const oje=({missionId:t,level:e,parentMissionId:n,missionNames:s,refreshKey:r=0})=>{const a=ms(),[o,l]=w.useState(null),[c,d]=w.useState(!0),[u,h]=w.useState(null),f=w.useCallback(async()=>{d(!0),h(null);try{l(await yt.getCascadeSummary(t))}catch(p){h(p instanceof Error?p.message:"Failed to load cascade")}finally{d(!1)}},[t]);return w.useEffect(()=>{f()},[f,r]),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark","data-testid":"cascade-section",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(Sp,{className:"h-4 w-4"}),"Cascade"]}),i.jsxs("div",{className:"mb-3",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide block mb-1",children:"Parent"}),n?i.jsx(de,{type:"button",variant:"link",icon:Ox,onClick:()=>a(`/missions/${n}`),className:"text-left","data-testid":"cascade-parent-link",children:JF(n,s)}):i.jsxs("span",{className:"text-sm text-text-secondary-dark","data-testid":"cascade-parent-none",children:["None — this is a ",e," root."]})]}),c?i.jsx("p",{className:"text-sm text-text-secondary-dark","data-testid":"cascade-loading",children:"Loading roll-up…"}):u?i.jsx("div",{"data-testid":"cascade-error",children:i.jsx(tt,{variant:"error",children:u})}):o?i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{"data-testid":"cascade-rollup",children:[i.jsxs("div",{className:"flex items-center justify-between mb-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Rolled-up progress"}),i.jsx("span",{className:"text-[11px] text-text-secondary-dark","data-testid":"cascade-recommendation",children:aje[o.recommendation]??o.recommendation})]}),i.jsx(Gx,{percent:o.rolledUpProgress,"data-testid":"cascade-rollup-bar"}),i.jsxs("div",{className:"mt-1 flex items-center justify-between gap-2 flex-wrap",children:[i.jsxs("span",{className:"text-[11px] text-text-secondary-dark",children:["Own progress ",Math.round(o.overallProgress),"% · ",o.totalKRs," KR",o.totalKRs===1?"":"s"]}),i.jsx(sj,{counts:Q8(o)})]})]}),i.jsxs("div",{children:[i.jsxs("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide block mb-1",children:["Children (",o.childMissionCount,")"]}),o.children.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark","data-testid":"cascade-children-empty",children:"No approved child missions."}):i.jsx("ul",{className:"space-y-2","data-testid":"cascade-children",children:o.children.map(p=>i.jsx("li",{"data-testid":`cascade-child-${p.missionId}`,children:i.jsxs("button",{type:"button",onClick:()=>a(`/missions/${p.missionId}`),className:"w-full text-left rounded-lg border border-border-dark px-3 py-2 hover:border-primary/30 transition-colors",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[i.jsx(C0,{level:p.level}),i.jsx("span",{className:"text-sm text-text-primary-dark truncate",children:JF(p.missionId,s)}),p.childMissionCount>0&&i.jsxs("span",{className:"text-[11px] text-text-secondary-dark ml-auto flex-shrink-0",children:[p.childMissionCount," child",p.childMissionCount===1?"":"ren"]})]}),i.jsx(Gx,{percent:p.rolledUpProgress,"data-testid":`cascade-child-progress-${p.missionId}`})]})},p.missionId))})]})]}):null]})},lje=({parentMissionId:t,onDecided:e})=>{const n=ms(),[s,r]=w.useState([]),[a,o]=w.useState(!1),l=w.useCallback(async()=>{try{r(await yt.getProposals(t))}catch{r([])}finally{o(!0)}},[t]);w.useEffect(()=>{l()},[l]);const c=d=>{r(u=>u.filter(h=>h.id!==d.id)),e==null||e(d)};return!a||s.length===0?null:i.jsxs(dt,{variant:"default",padding:"md",className:"border border-yellow-500/40","data-testid":"proposals-section",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(bh,{className:"h-4 w-4 text-yellow-400"}),"Proposals awaiting approval (",s.length,")"]}),i.jsx("ul",{className:"space-y-2",children:s.map(d=>{var u,h,f,p,x;return i.jsx("li",{className:"rounded-lg border border-border-dark px-3 py-2","data-testid":`proposal-${d.id}`,children:i.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[d.level&&i.jsx(C0,{level:d.level}),i.jsx("button",{type:"button",onClick:()=>n(`/missions/${d.id}`),className:"text-sm font-medium text-text-primary-dark hover:text-primary text-left","data-testid":`proposal-link-${d.id}`,children:d.objective})]}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap text-[11px] text-text-secondary-dark",children:[i.jsxs(ft,{variant:"default",size:"sm",children:["Team: ",d.ownerTeamId.slice(0,16)]}),((u=d.approval)==null?void 0:u.proposedBy)&&i.jsxs("span",{children:["Proposed by ",d.approval.proposedBy]}),(((h=d.keyResults)==null?void 0:h.length)??0)>0&&i.jsxs("span",{children:[(f=d.keyResults)==null?void 0:f.length," KR",((p=d.keyResults)==null?void 0:p.length)===1?"":"s"]})]}),((x=d.successCriteria)==null?void 0:x.length)>0&&i.jsx("ul",{className:"mt-1 text-xs text-text-secondary-dark list-disc pl-4",children:d.successCriteria.slice(0,3).map((y,m)=>i.jsx("li",{children:y},m))})]}),i.jsx(VR,{missionId:d.id,onDecided:c})]})},d.id)})})]})},cje=[{key:"completedTasks",label:"Done",dot:"bg-emerald-500"},{key:"runningTasks",label:"Running",dot:"bg-blue-500"},{key:"queuedTasks",label:"Queued",dot:"bg-border-dark"},{key:"blockedTasks",label:"Blocked",dot:"bg-amber-500"},{key:"failedTasks",label:"Failed",dot:"bg-rose-500"}],dje=({missionId:t,refreshKey:e=0})=>{const[n,s]=w.useState(null),[r,a]=w.useState(!0),[o,l]=w.useState(null),c=w.useCallback(async()=>{a(!0),l(null);try{s(await yt.getMissionProgress(t))}catch(d){l(d instanceof Error?d.message:"Failed to load progress")}finally{a(!1)}},[t]);return w.useEffect(()=>{c()},[c,e]),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark","data-testid":"mission-progress-section",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(dl,{className:"h-4 w-4"}),"Execution Progress"]}),r?i.jsx("p",{className:"text-sm text-text-secondary-dark","data-testid":"mission-progress-loading",children:"Loading progress…"}):o?i.jsx("div",{"data-testid":"mission-progress-error",children:i.jsx(tt,{variant:"error",children:o})}):n?i.jsxs("div",{className:"space-y-3 text-sm",children:[i.jsx(Gx,{percent:n.progressPercent,label:`${n.completedTasks}/${n.totalTasks} tasks`,"data-testid":"mission-progress-bar"}),n.totalTasks===0?i.jsx("p",{className:"text-xs text-text-secondary-dark","data-testid":"mission-progress-empty",children:"No work items under this mission yet."}):i.jsx("ul",{className:"space-y-1.5","data-testid":"mission-progress-rows",children:cje.map(d=>i.jsxs("li",{className:"flex items-center justify-between","data-testid":`mission-progress-${d.key}`,children:[i.jsxs("span",{className:"flex items-center gap-2 text-text-secondary-dark",children:[i.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${d.dot}`}),d.label]}),i.jsx("span",{className:"text-text-primary-dark font-mono text-xs",children:n[d.key]})]},d.key))}),i.jsxs("div",{className:"flex items-center justify-between border-t border-border-dark pt-2",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Phase"}),i.jsx("span",{className:"text-text-primary-dark font-mono text-xs",children:n.phase})]}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Cost"}),i.jsxs("span",{className:"text-text-primary-dark font-mono text-xs","data-testid":"mission-progress-cost",children:["$",n.totalCost.toFixed(2)]})]})]}):null]})};function kf(t){try{return new Date(t).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return t}}function uje(t){var e,n,s,r;return{objective:t.objective,status:t.status,priority:t.priority??"medium",ownerTeamId:t.ownerTeamId,currentStrategy:t.currentStrategy??"",cadence:t.cadence??"",successCriteriaText:(t.successCriteria??[]).join(`
4961
4961
  `),periodLabel:((e=t.period)==null?void 0:e.label)??"",periodType:((n=t.period)==null?void 0:n.type)??"",periodStart:(s=t.period)!=null&&s.startDate?t.period.startDate.slice(0,10):"",periodEnd:(r=t.period)!=null&&r.endDate?t.period.endDate.slice(0,10):"",parentMissionId:t.parentMissionId??""}}function hje(t){const e={objective:t.objective.trim(),status:t.status,priority:t.priority,ownerTeamId:t.ownerTeamId.trim(),currentStrategy:t.currentStrategy,cadence:t.cadence.trim(),successCriteria:t.successCriteriaText.split(`
4962
4962
  `).map(n=>n.trim()).filter(Boolean),parentMissionId:t.parentMissionId||""};return t.periodType&&t.periodStart&&t.periodEnd?e.period={type:t.periodType,startDate:new Date(t.periodStart).toISOString(),endDate:new Date(t.periodEnd).toISOString(),...t.periodLabel?{label:t.periodLabel}:{}}:!t.periodType&&!t.periodStart&&!t.periodEnd&&(e.period=null),e}const fV=()=>{var $,P,B,R,D;const{id:t}=gh(),e=ms(),[n,s]=w.useState(null),[r,a]=w.useState(!0),[o,l]=w.useState(null),[c,d]=w.useState(!1),[u,h]=w.useState(!1),[f,p]=w.useState(null),[x,y]=w.useState(!1),[m,g]=w.useState(null),[v,b]=w.useState(new Map),[S,k]=w.useState(new Map),[E,N]=w.useState(0),T=w.useCallback(async(K=!0)=>{if(t){K?a(!0):d(!0),l(null);try{const U=await yt.getMission(t);s(U)}catch(U){const X=U instanceof Error?U.message:"Failed to load mission";l(X)}finally{a(!1),d(!1)}}},[t]);w.useEffect(()=>{T()},[T]),w.useEffect(()=>{let K=!1;return(async()=>{try{const U=await yt.getMissions();if(K)return;b(new Map(U.map(X=>[X.id,X.objective]))),k(new Map(U.map(X=>[X.id,{level:X.level,parentMissionId:X.parentMissionId}])))}catch{}})(),()=>{K=!0}},[t]);const A=w.useCallback(()=>{N(K=>K+1),T(!1)},[T]),M=w.useCallback(K=>{s(U=>U&&U.id===K.id?{...U,...K}:U),A()},[A]),L=w.useCallback(()=>{n&&(p(uje(n)),g(null),h(!0))},[n]),I=w.useCallback(()=>{h(!1),p(null),g(null)},[]),F=w.useCallback(async()=>{if(!(!t||!f)){if(!f.objective.trim()){g("Objective cannot be empty.");return}if(!f.ownerTeamId.trim()){g("Owner team cannot be empty.");return}y(!0),g(null);try{const K=await yt.updateMission(t,hje(f));s(K),h(!1),p(null)}catch(K){const U=K instanceof Error?K.message:"Failed to save mission";g(U)}finally{y(!1)}}},[t,f]),G=w.useMemo(()=>(K,U)=>{p(X=>X&&{...X,[K]:U})},[]);if(r)return i.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:i.jsx(Ht,{size:"xl",text:"Loading mission..."})});if(o)return i.jsxs("div",{className:"p-6 max-w-[1000px] mx-auto","data-testid":"mission-detail-error",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:()=>e("/missions"),className:"mb-6",children:"Back to Missions"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"flex flex-col items-center text-center py-8",children:[i.jsx("p",{className:"text-red-400 mb-2",children:o}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:()=>T(),children:"Retry"})]})})]});if(!n)return i.jsxs("div",{className:"p-6 max-w-[1000px] mx-auto",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:()=>e("/missions"),className:"mb-6",children:"Back to Missions"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsx(Cs,{icon:nh,title:"Mission not found.",compact:!0})})]});const V=ej(n,S),H=($=n.approval)==null?void 0:$.state;return i.jsxs("div",{className:"p-6 max-w-[1000px] mx-auto","data-testid":"mission-detail-page",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:()=>e("/missions"),className:"mb-6","data-testid":"mission-detail-back",children:"Back to Missions"}),i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-6",children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[u&&f?i.jsx(ys,{"aria-label":"Objective",value:f.objective,onChange:K=>G("objective",K.target.value),fullWidth:!0,"data-testid":"edit-objective"}):i.jsx("h1",{className:"text-2xl font-bold text-text-primary-dark mb-2",children:n.objective}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap mt-2",children:[i.jsx(C0,{level:V}),i.jsx(Lo,{status:Z2(n.status),children:J_(n.status)}),H&&(H!=="approved"||((P=n.approval)==null?void 0:P.decidedAt))&&i.jsx(nj,{state:H}),n.priority&&i.jsx(ft,{variant:J8[n.priority],size:"sm",children:mM[n.priority]}),((B=n.period)==null?void 0:B.label)&&i.jsx(ft,{variant:"info",size:"sm",children:n.period.label}),i.jsx(ft,{variant:"default",size:"sm",children:n.id.slice(0,12)})]}),H==="pending_approval"&&!u&&i.jsxs("div",{className:"mt-3 flex items-center gap-3 flex-wrap","data-testid":"mission-pending-banner",children:[i.jsxs("span",{className:"text-xs text-yellow-400",children:["Proposed",(R=n.approval)!=null&&R.proposedBy?` by ${n.approval.proposedBy}`:""," — awaiting your decision."]}),i.jsx(VR,{missionId:n.id,onDecided:M})]}),H==="rejected"&&((D=n.approval)==null?void 0:D.rejectionReason)&&i.jsxs("p",{className:"mt-2 text-xs text-red-400","data-testid":"mission-rejection-reason",children:["Rejected: ",n.approval.rejectionReason]})]}),i.jsx("div",{className:"flex items-center gap-2 flex-shrink-0",children:u?i.jsxs(i.Fragment,{children:[i.jsx(de,{variant:"primary",size:"sm",icon:vd,onClick:F,disabled:x,"data-testid":"mission-save",children:x?"Saving…":"Save"}),i.jsx(de,{variant:"ghost",size:"sm",icon:cs,onClick:I,disabled:x,"data-testid":"mission-cancel",children:"Cancel"})]}):i.jsxs(i.Fragment,{children:[i.jsx(de,{variant:"primary",size:"sm",icon:E1,onClick:L,"data-testid":"mission-edit",children:"Edit"}),i.jsx(de,{variant:"ghost",size:"sm",icon:an,onClick:()=>T(!1),loading:c,"aria-label":"Refresh mission",children:"Refresh"})]})})]}),m&&i.jsx("div",{"data-testid":"mission-save-error",className:"mb-4",children:i.jsx(tt,{variant:"error",onClose:()=>g(null),children:m})}),i.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[i.jsxs("div",{className:"lg:col-span-2 flex flex-col gap-4",children:[i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-2 flex items-center gap-1.5",children:[i.jsx(nh,{className:"h-4 w-4"}),"Current Strategy"]}),u&&f?i.jsx(Xs,{"aria-label":"Current Strategy",rows:4,value:f.currentStrategy,onChange:K=>G("currentStrategy",K.target.value),"data-testid":"edit-strategy"}):i.jsx("p",{className:"text-sm text-text-primary-dark leading-relaxed whitespace-pre-wrap",children:n.currentStrategy||"No strategy defined."})]}),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(ia,{className:"h-4 w-4"}),"Success Criteria (",n.successCriteria.length,")"]}),u&&f?i.jsx(Xs,{"aria-label":"Success Criteria (one per line)",rows:5,placeholder:"One criterion per line",value:f.successCriteriaText,onChange:K=>G("successCriteriaText",K.target.value),"data-testid":"edit-success-criteria"}):n.successCriteria.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No success criteria defined."}):i.jsx("ul",{className:"space-y-2",children:n.successCriteria.map((K,U)=>i.jsxs("li",{className:"flex items-start gap-2 text-sm text-text-primary-dark",children:[i.jsx("span",{className:"text-primary mt-0.5 flex-shrink-0",children:i.jsx(v2,{className:"h-4 w-4"})}),K]},U))})]}),!u&&i.jsx(ije,{missionId:n.id,onChanged:A}),!u&&i.jsx(lje,{parentMissionId:n.id,onDecided:M}),!u&&i.jsx(oje,{missionId:n.id,level:V,parentMissionId:n.parentMissionId,missionNames:v,refreshKey:E}),!u&&n.learnings&&n.learnings.length>0&&i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(f0,{className:"h-4 w-4"}),"Learnings (",n.learnings.length,")"]}),i.jsx("ul",{className:"space-y-2",children:n.learnings.map((K,U)=>i.jsx("li",{className:"text-sm text-text-primary-dark pl-4 border-l-2 border-border-dark",children:K},U))})]})]}),i.jsxs("div",{className:"flex flex-col gap-4",children:[!u&&i.jsx(dje,{missionId:n.id,refreshKey:E}),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(as,{className:"h-4 w-4"}),"Team & Settings"]}),i.jsxs("div",{className:"space-y-3 text-sm",children:[i.jsxs("div",{className:"flex flex-col gap-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Owner Team"}),u&&f?i.jsx(ys,{"aria-label":"Owner Team",value:f.ownerTeamId,onChange:K=>G("ownerTeamId",K.target.value),fullWidth:!0,"data-testid":"edit-owner-team"}):i.jsx("span",{className:"text-text-primary-dark font-mono text-xs",children:n.ownerTeamId})]}),i.jsxs("div",{className:"flex flex-col gap-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Status"}),u&&f?i.jsxs(pn,{value:f.status,onChange:K=>G("status",K.target.value),"data-testid":"edit-status",children:[i.jsx("option",{value:"active",children:"Active"}),i.jsx("option",{value:"paused",children:"Paused"}),i.jsx("option",{value:"completed",children:"Completed"}),i.jsx("option",{value:"cancelled",children:"Cancelled"})]}):i.jsx("span",{className:"text-text-primary-dark",children:J_(n.status)})]}),i.jsxs("div",{className:"flex flex-col gap-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Priority"}),u&&f?i.jsxs(pn,{value:f.priority,onChange:K=>G("priority",K.target.value),"data-testid":"edit-priority",children:[i.jsx("option",{value:"critical",children:"Critical"}),i.jsx("option",{value:"high",children:"High"}),i.jsx("option",{value:"medium",children:"Medium"}),i.jsx("option",{value:"low",children:"Low"})]}):i.jsx("span",{className:"text-text-primary-dark",children:mM[n.priority??"medium"]})]}),i.jsxs("div",{className:"flex flex-col gap-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Parent Mission"}),u&&f?i.jsx(ys,{"aria-label":"Parent Mission ID",placeholder:"(none)",value:f.parentMissionId,onChange:K=>G("parentMissionId",K.target.value),fullWidth:!0,"data-testid":"edit-parent"}):n.parentMissionId?i.jsx(de,{type:"button",variant:"link",size:"xs",onClick:()=>e(`/missions/${n.parentMissionId}`),className:"truncate max-w-full","data-testid":"mission-parent-link",children:v.get(n.parentMissionId)??n.parentMissionId}):i.jsx("span",{className:"text-text-primary-dark font-mono text-xs",children:"—"})]}),!u&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Level"}),i.jsx("span",{className:"text-text-primary-dark","data-testid":"mission-level",children:V})]}),!u&&n.projectId&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Project"}),i.jsx(de,{type:"button",variant:"link",size:"xs",onClick:()=>e(`/projects/${n.projectId}`),className:"font-mono","data-testid":"mission-project-link",children:n.projectId.slice(0,12)})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Active Tasks"}),i.jsx("span",{className:"text-text-primary-dark",children:n.activeProjectTaskIds.length})]}),i.jsxs("div",{className:"flex flex-col gap-1",children:[i.jsx("span",{className:"text-text-secondary-dark text-xs uppercase tracking-wide",children:"Cadence (cron)"}),u&&f?i.jsx(ys,{"aria-label":"Cadence",value:f.cadence,onChange:K=>G("cadence",K.target.value),fullWidth:!0,"data-testid":"edit-cadence"}):i.jsx("span",{className:"text-text-primary-dark font-mono text-xs",children:n.cadence||"N/A"})]})]})]}),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(PT,{className:"h-4 w-4"}),"OKR Period"]}),u&&f?i.jsxs("div",{className:"space-y-2",children:[i.jsxs(pn,{value:f.periodType,onChange:K=>G("periodType",K.target.value),"data-testid":"edit-period-type",children:[i.jsx("option",{value:"",children:"— No period —"}),i.jsx("option",{value:"weekly",children:"Weekly"}),i.jsx("option",{value:"biweekly",children:"Biweekly"}),i.jsx("option",{value:"monthly",children:"Monthly"}),i.jsx("option",{value:"quarterly",children:"Quarterly"}),i.jsx("option",{value:"custom",children:"Custom"})]}),i.jsx(ys,{type:"date","aria-label":"Period start",value:f.periodStart,onChange:K=>G("periodStart",K.target.value),fullWidth:!0,"data-testid":"edit-period-start"}),i.jsx(ys,{type:"date","aria-label":"Period end",value:f.periodEnd,onChange:K=>G("periodEnd",K.target.value),fullWidth:!0,"data-testid":"edit-period-end"}),i.jsx(ys,{"aria-label":"Period label",placeholder:"Label (optional)",value:f.periodLabel,onChange:K=>G("periodLabel",K.target.value),fullWidth:!0,"data-testid":"edit-period-label"})]}):n.period?i.jsxs("div",{className:"space-y-2 text-sm",children:[i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Type"}),i.jsx("span",{className:"text-text-primary-dark",children:n.period.type})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Start"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.period.startDate)})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"End"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.period.endDate)})]}),n.period.label&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Label"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:n.period.label})]})]}):i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"No period defined."})]}),i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(PT,{className:"h-4 w-4"}),"Timestamps"]}),i.jsxs("div",{className:"space-y-2 text-sm",children:[i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Created"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.createdAt)})]}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Updated"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.updatedAt)})]}),n.lastReviewAt&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Last Review"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.lastReviewAt)})]}),n.nextReviewAt&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Next Review"}),i.jsx("span",{className:"text-text-primary-dark text-xs",children:kf(n.nextReviewAt)})]})]})]}),!u&&n.activeProjectTaskIds.length>0&&i.jsxs(dt,{variant:"default",padding:"md",className:"border border-border-dark",children:[i.jsxs("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide mb-3 flex items-center gap-1.5",children:[i.jsx(ps,{className:"h-4 w-4"}),"Active Task IDs"]}),i.jsx("div",{className:"flex flex-wrap gap-1.5",children:n.activeProjectTaskIds.map(K=>i.jsx(ft,{variant:"default",size:"sm",children:K.slice(0,12)},K))})]})]})]})]})};fV.displayName="MissionDetail";const pV="/api/tickets",fje=15e3,pje=300,mje=24*60*60*1e3,mV=["idea","todo","in_progress","blocked","to_review","done"],gN={idea:"想法",todo:"待处理",in_progress:"进行中",blocked:"阻塞",to_review:"待验收",done:"已完成",cancelled:"已取消"},$R={issue:"问题",feature:"需求",idea:"想法"},gV=["issue","feature","idea"],h_="all",gje="全部",xje=[{value:"urgent",label:"P0"},{value:"high",label:"P1"},{value:"normal",label:"P2"},{value:"low",label:"P3"}],yje={P0:"error",P1:"warning",P2:"primary",P3:"default"},vje={owner:"我",decompose:"拆解",reject:"打回",agent:"Agent"},jA={auto:"自动",judgment:"人工"},bje={"slack-channel":"Slack 频道","slack-dm":"Slack 私信",chat:"聊天",portal:"门户",mobile:"手机","bug-button":"Bug 按钮",agent:"Agent",cron:"定时任务",mission:"Mission",legacy:"旧记录"},ZF={not_in_review:"这张单子不在待验收,不能打回",already_done:"这张单子已经完成了",open_work:"还有未完成的工作项,暂时不能验收",cancelled:"这张单子已取消",invalid:"输入无效"},cn={PAGE_TITLE:"工单",PAGE_SUBTITLE:"你说过的每一件事都在这里",SEARCH_PLACEHOLDER:"搜索工单…",KIND_FILTER_ARIA:"类型筛选",REFRESH:"刷新",EMPTY_COLUMN:"暂无",EMPTY_BOARD_TITLE:"还没有工单",EMPTY_BOARD_DESC:"在 Slack 或聊天里说「请帮我…」,就会自动生成工单。",LOAD_FAILED:"加载工单失败",UNASSIGNED:"未分配",REJECT_BADGE:"打回",AUTO_ACCEPT_IN_DAYS:"天后自动验收",AUTO_ACCEPT_SOON:"即将自动验收",DETAIL_LOADING:"加载中…",TITLE_LABEL:"标题",SAVE:"保存",PRIORITY_LABEL:"优先级",KIND_LABEL:"类型",ORIGIN_LABEL:"来源",ASSIGNEE_LABEL:"负责人",DESCRIPTION_LABEL:"描述",REPLY_LABEL:"Agent 的回答",NO_REPLY:"还没有回答",DISCUSSION_LABEL:"讨论",NO_DISCUSSION:"暂无讨论",ACCEPTANCE_LABEL:"验收标准",NO_ACCEPTANCE:"还没有验收标准",ACCEPTANCE_ADD_PLACEHOLDER:"新增一条验收标准…",ACCEPTANCE_CHECK_ARIA:"检查方式",ACCEPTANCE_ADD:"添加",ACCEPTANCE_REMOVE:"删除",SELF_CHECK_PASS:"自检通过",SELF_CHECK_FAIL:"自检未过",VERIFY:"验过了",REJECT:"打回",DISMISS:"不用记",REJECT_REASON_LABEL:"打回原因",REJECT_REASON_PLACEHOLDER:"哪里不对?这条会变成新的验收标准",REJECT_REASON_REQUIRED:"请填写打回原因",REJECT_CONFIRM:"确认打回",CANCEL:"取消",REJECTED_TIMES:"次打回",SUBMITTED_TIMES:"次提交"};class KR extends Error{constructor(n,s,r){super(n);On(this,"status");On(this,"code");this.name="TicketApiError",this.status=s,this.code=r}}function _je(t){return t instanceof KR}function Sje(t){const e={};for(const n of mV)e[n]=[];e.cancelled=[];for(const n of t)(e[n.column]??(e[n.column]=[])).push(n);return e}function wje(t,e=Date.now()){if(!t)return null;const n=Date.parse(t);return Number.isNaN(n)?null:Math.max(0,Math.ceil((n-e)/mje))}function xV(t,e=Date.now()){const n=wje(t,e);return n===null?null:n<=0?cn.AUTO_ACCEPT_SOON:`${n}${cn.AUTO_ACCEPT_IN_DAYS}`}function Cje(t){if(!t)return null;const e=bje[t.channel]??t.channel,n=t.authorName||t.author;return n?`${e} · ${n}`:e}function QF(t){if(!t)return"";const e=Date.parse(t);return Number.isNaN(e)?t:new Date(e).toLocaleString()}function e5(t){return(t??[]).map(e=>({text:e.text,...e.check?{check:e.check}:{}}))}function xN(t){return _je(t)&&t.code&&ZF[t.code]?ZF[t.code]:t instanceof Error&&t.message?t.message:String(t)}const kje=({ticket:t,onOpen:e,now:n})=>{var l;const s=t.column==="to_review",r=s?xV(t.autoAcceptAt,n):null,a=t.rejectCount??0,o=c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),e(t))};return i.jsxs(dt,{padding:"sm",interactive:!0,role:"button",tabIndex:0,"aria-label":`${t.tkt??""} ${t.title}`.trim(),"data-testid":`ticket-card-${t.id}`,onClick:()=>e(t),onKeyDown:o,className:"rounded-2xl focus:outline-none focus:ring-1 focus:ring-primary",children:[i.jsxs("div",{className:"flex items-center justify-between gap-2",children:[i.jsx("span",{className:"text-xs font-semibold text-text-secondary-dark",children:t.tkt??""}),i.jsxs("div",{className:"flex items-center gap-1",children:[a>0&&i.jsxs(ft,{variant:"error",size:"sm","data-testid":"ticket-reject-badge",children:[cn.REJECT_BADGE," ×",a]}),i.jsx(ft,{variant:yje[t.priorityLabel]??"default",size:"sm",children:t.priorityLabel})]})]}),i.jsx("p",{className:"mt-1 text-sm font-medium text-text-primary-dark break-words",children:t.title}),s&&((l=t.reply)==null?void 0:l.excerpt)&&i.jsx("p",{className:"mt-2 text-xs text-text-secondary-dark line-clamp-3 break-words","data-testid":"ticket-reply-excerpt",children:t.reply.excerpt}),i.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-1",children:[i.jsx(ft,{size:"sm",children:$R[t.kind]??t.kind}),i.jsx("span",{className:"text-xs text-text-secondary-dark truncate",children:t.assignee||cn.UNASSIGNED})]}),r&&i.jsx("p",{className:"mt-2 text-xs text-primary","data-testid":"ticket-auto-accept",children:r})]})};async function Nh(t,e){const n=await fetch(t,e);let s={};try{s=await n.json()}catch{s={}}if(!n.ok||s.success===!1)throw new KR(s.error||s.message||`HTTP ${n.status}`,n.status,s.code);return s.data}function G0(t,e){return{method:t,headers:{"Content-Type":"application/json"},...e!==void 0?{body:JSON.stringify(e)}:{}}}function mm(t,e=""){return`${pV}/${encodeURIComponent(t)}${e}`}function Eje(t={}){var r;const e=new URLSearchParams;t.column&&e.set("column",t.column),t.kind&&e.set("kind",t.kind);const n=(r=t.q)==null?void 0:r.trim();n&&e.set("q",n),t.includeLegacy&&e.set("includeLegacy","true");const s=e.toString();return s?`?${s}`:""}async function Aje(t={}){const e=await Nh(`${pV}${Eje(t)}`);return{tickets:(e==null?void 0:e.tickets)??[],columns:(e==null?void 0:e.columns)??{}}}function Tje(t){return Nh(mm(t))}function Mje(t){return Nh(mm(t,"/verify"),G0("POST"))}function Nje(t,e){const n=e.trim();return n?Nh(mm(t,"/reject"),G0("POST",{reason:n})):Promise.reject(new KR("A reason is required",400,"invalid"))}function jje(t){return Nh(mm(t,"/dismiss"),G0("POST"))}function Rje(t,e){return Nh(mm(t,"/acceptance"),G0("PUT",{items:e}))}function Ije(t,e){return Nh(mm(t),G0("PATCH",e))}const t5="judgment",Pje=({acceptance:t,onSave:e,disabled:n=!1})=>{const[s,r]=w.useState(""),[a,o]=w.useState(t5),[l,c]=w.useState(!1),d=n||l,u=async p=>{c(!0);try{return await e(p),!0}catch{return!1}finally{c(!1)}},h=async p=>{const x=e5(t).filter((y,m)=>m!==p);await u(x)},f=async p=>{p.preventDefault();const x=s.trim();if(!x)return;await u([...e5(t),{text:x,check:a}])&&(r(""),o(t5))};return i.jsxs("div",{"data-testid":"ticket-acceptance",children:[t.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:cn.NO_ACCEPTANCE}):i.jsx("ul",{className:"space-y-2",children:t.map((p,x)=>i.jsxs("li",{className:"flex items-start gap-2 rounded-2xl border border-border-dark bg-background-dark p-3","data-testid":"ticket-acceptance-item",children:[i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsx("p",{className:"text-sm text-text-primary-dark break-words",children:p.text}),i.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-1",children:[i.jsx(ft,{size:"sm",variant:p.source==="reject"?"error":"default",children:vje[p.source??"owner"]}),i.jsx(ft,{size:"sm",variant:p.check==="auto"?"info":"default",children:jA[p.check??"judgment"]}),p.selfCheck&&i.jsx(ft,{size:"sm",variant:p.selfCheck==="pass"?"success":"error",children:p.selfCheck==="pass"?cn.SELF_CHECK_PASS:cn.SELF_CHECK_FAIL})]}),p.evidence&&i.jsx("p",{className:"mt-1 text-xs text-text-secondary-dark break-words",children:p.evidence})]}),i.jsx(zt,{icon:Vr,variant:"ghost","aria-label":`${cn.ACCEPTANCE_REMOVE} ${p.text}`,disabled:d,onClick:()=>void h(x)})]},`${x}-${p.text}`))}),i.jsxs("form",{className:"mt-3 flex flex-col gap-2 sm:flex-row",onSubmit:p=>void f(p),children:[i.jsx("div",{className:"flex-1",children:i.jsx(Ut,{value:s,onChange:p=>r(p.target.value),placeholder:cn.ACCEPTANCE_ADD_PLACEHOLDER,"aria-label":cn.ACCEPTANCE_ADD_PLACEHOLDER,disabled:d})}),i.jsx("div",{className:"sm:w-28",children:i.jsxs(pn,{value:a,onChange:p=>o(p.target.value),"aria-label":cn.ACCEPTANCE_CHECK_ARIA,disabled:d,children:[i.jsx("option",{value:"judgment",children:jA.judgment}),i.jsx("option",{value:"auto",children:jA.auto})]})}),i.jsx(de,{type:"submit",variant:"secondary",icon:ts,disabled:d||!s.trim(),children:cn.ACCEPTANCE_ADD})]})]})},Lje=new Set(["done","cancelled"]),Tb=({title:t,children:e})=>i.jsxs("section",{className:"space-y-2",children:[i.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-text-secondary-dark",children:t}),e]}),Dje=({ticketId:t,onClose:e,onChanged:n,now:s})=>{const[r,a]=w.useState(null),[o,l]=w.useState(null),[c,d]=w.useState(null),[u,h]=w.useState(null),[f,p]=w.useState(""),[x,y]=w.useState(!1),[m,g]=w.useState(""),[v,b]=w.useState(null),S=w.useCallback(async P=>{try{const B=await Tje(P);a(B),p(B.board.title),l(null)}catch(B){l(xN(B))}},[]);w.useEffect(()=>{a(null),l(null),d(null),y(!1),g(""),b(null),t&&S(t)},[t,S]);const k=async(P,B,R=!1)=>{if(!t)return!1;h(P),d(null);try{return await B(),n(),R?e():await S(t),!0}catch(D){return d(xN(D)),!1}finally{h(null)}},E=P=>{t&&k("patch",()=>Ije(t,P))},N=async P=>{if(!t)return;if(!await k("acceptance",()=>Rje(t,P)))throw new Error("acceptance save failed")},T=()=>{if(!t)return;const P=m.trim();if(!P){b(cn.REJECT_REASON_REQUIRED);return}b(null),k("reject",()=>Nje(t,P)).then(B=>{B&&(y(!1),g(""))})},A=(r==null?void 0:r.board)??null,M=t!==null,L=A!==null&&!Lje.has(A.column),I=(A==null?void 0:A.column)==="to_review",F=A!==null&&f.trim()!==""&&f.trim()!==A.title,G=(r==null?void 0:r.ticket.discussion)??[],V=(A==null?void 0:A.description)||(r==null?void 0:r.ticket.description)||"",H=I?xV(A==null?void 0:A.autoAcceptAt,s):null,$=A&&L?x?i.jsxs("div",{className:"flex w-full flex-col gap-2","data-testid":"ticket-reject-form",children:[i.jsx("label",{htmlFor:"ticket-reject-reason",className:"text-sm text-text-secondary-dark",children:cn.REJECT_REASON_LABEL}),i.jsx(Xs,{id:"ticket-reject-reason",rows:3,value:m,error:v!==null,placeholder:cn.REJECT_REASON_PLACEHOLDER,onChange:P=>{g(P.target.value),v&&b(null)}}),v&&i.jsx("p",{className:"text-xs text-red-400",role:"alert",children:v}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(de,{variant:"ghost",onClick:()=>y(!1),disabled:u!==null,children:cn.CANCEL}),i.jsx(de,{variant:"warning",icon:qL,onClick:T,loading:u==="reject",children:cn.REJECT_CONFIRM})]})]}):i.jsxs("div",{className:"flex w-full flex-wrap items-center justify-end gap-2",children:[i.jsx(de,{variant:"danger-ghost",icon:cs,onClick:()=>void k("dismiss",()=>jje(t),!0),loading:u==="dismiss",disabled:u!==null&&u!=="dismiss",children:cn.DISMISS}),I&&i.jsx(de,{variant:"warning",icon:qL,onClick:()=>y(!0),disabled:u!==null,children:cn.REJECT}),i.jsx(de,{variant:"success",icon:Kn,onClick:()=>void k("verify",()=>Mje(t),!0),loading:u==="verify",disabled:u!==null&&u!=="verify",children:cn.VERIFY})]}):void 0;return i.jsxs(AJ,{isOpen:M,onClose:e,size:"lg",title:(A==null?void 0:A.tkt)??(A==null?void 0:A.title)??cn.DETAIL_LOADING,subtitle:A?gN[A.column]??A.column:void 0,footer:$,"data-testid":"ticket-detail-drawer",children:[!A&&!o&&i.jsx("div",{className:"flex justify-center py-8",children:i.jsx(Ht,{})}),o&&i.jsx(tt,{variant:"error",size:"sm",children:o}),A&&i.jsxs("div",{className:"space-y-6",children:[c&&i.jsx(tt,{variant:"error",size:"sm",onClose:()=>d(null),"data-testid":"ticket-action-error",children:c}),i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{children:[i.jsx("label",{htmlFor:"ticket-title",className:"mb-1 block text-sm text-text-secondary-dark",children:cn.TITLE_LABEL}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(Ut,{id:"ticket-title",value:f,onChange:P=>p(P.target.value)}),F&&i.jsx(de,{variant:"secondary",onClick:()=>E({title:f.trim()}),loading:u==="patch",children:cn.SAVE})]})]}),i.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[i.jsxs("div",{children:[i.jsx("label",{htmlFor:"ticket-priority",className:"mb-1 block text-sm text-text-secondary-dark",children:cn.PRIORITY_LABEL}),i.jsx(pn,{id:"ticket-priority",value:A.priority,disabled:u!==null,onChange:P=>E({priority:P.target.value}),children:xje.map(P=>i.jsx("option",{value:P.value,children:P.label},P.value))})]}),i.jsxs("div",{children:[i.jsx("label",{htmlFor:"ticket-kind",className:"mb-1 block text-sm text-text-secondary-dark",children:cn.KIND_LABEL}),i.jsx(pn,{id:"ticket-kind",value:A.kind,disabled:u!==null,onChange:P=>E({kind:P.target.value}),children:gV.map(P=>i.jsx("option",{value:P,children:$R[P]},P))})]})]}),i.jsxs("dl",{className:"grid grid-cols-1 gap-2 text-sm sm:grid-cols-2",children:[i.jsxs("div",{children:[i.jsx("dt",{className:"text-text-secondary-dark",children:cn.ORIGIN_LABEL}),i.jsx("dd",{className:"text-text-primary-dark","data-testid":"ticket-origin",children:Cje(A.origin)??"—"})]}),i.jsxs("div",{children:[i.jsx("dt",{className:"text-text-secondary-dark",children:cn.ASSIGNEE_LABEL}),i.jsx("dd",{className:"text-text-primary-dark",children:A.assignee||cn.UNASSIGNED})]})]}),i.jsxs("div",{className:"flex flex-wrap gap-1",children:[(A.rejectCount??0)>0&&i.jsxs(ft,{variant:"error",size:"sm",children:[A.rejectCount,cn.REJECTED_TIMES]}),(A.submitCount??0)>0&&i.jsxs(ft,{size:"sm",children:[A.submitCount,cn.SUBMITTED_TIMES]}),H&&i.jsx(ft,{variant:"primary",size:"sm",children:H})]})]}),V&&i.jsx(Tb,{title:cn.DESCRIPTION_LABEL,children:i.jsx("p",{className:"whitespace-pre-wrap break-words text-sm text-text-primary-dark",children:V})}),i.jsx(Tb,{title:cn.REPLY_LABEL,children:A.reply?i.jsxs("div",{className:"rounded-2xl border border-border-dark bg-background-dark p-3","data-testid":"ticket-reply",children:[i.jsx("p",{className:"whitespace-pre-wrap break-words text-sm text-text-primary-dark",children:A.reply.excerpt}),i.jsxs("p",{className:"mt-1 text-xs text-text-secondary-dark",children:[A.reply.by," · ",QF(A.reply.at)]})]}):i.jsx("p",{className:"text-sm text-text-secondary-dark",children:cn.NO_REPLY})}),i.jsx(Tb,{title:cn.ACCEPTANCE_LABEL,children:i.jsx(Pje,{acceptance:A.acceptance??[],onSave:N,disabled:u!==null&&u!=="acceptance"})}),i.jsx(Tb,{title:cn.DISCUSSION_LABEL,children:G.length===0?i.jsx("p",{className:"text-sm text-text-secondary-dark",children:cn.NO_DISCUSSION}):i.jsx("ul",{className:"space-y-2","data-testid":"ticket-discussion",children:G.map((P,B)=>i.jsxs("li",{className:"rounded-2xl border border-border-dark p-3",children:[i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:[P.author," · ",QF(P.at)]}),i.jsx("p",{className:"mt-1 whitespace-pre-wrap break-words text-sm text-text-primary-dark",children:P.text})]},`${P.ref}-${B}`))})})]})]})},Oje=[{value:h_,label:gje},...gV.map(t=>({value:t,label:$R[t]}))],Bje=({now:t})=>{const[e,n]=w.useState(""),[s,r]=w.useState(""),[a,o]=w.useState(h_),[l,c]=w.useState(null),[d,u]=w.useState(!0),[h,f]=w.useState(null),[p,x]=w.useState(null),y=w.useRef(0);w.useEffect(()=>{const k=setTimeout(()=>r(e),pje);return()=>clearTimeout(k)},[e]);const m=w.useCallback(async()=>{const k=++y.current;try{const E=await Aje({...a!==h_?{kind:a}:{},...s.trim()?{q:s}:{}});if(k!==y.current)return;c(E),f(null)}catch(E){if(k!==y.current)return;f(xN(E))}finally{k===y.current&&u(!1)}},[a,s]);w.useEffect(()=>{m();const k=setInterval(()=>void m(),fje);return()=>clearInterval(k)},[m]);const g=w.useMemo(()=>Sje((l==null?void 0:l.tickets)??[]),[l]),v=a!==h_||s.trim()!=="",b=l!==null&&l.tickets.length===0&&!v,S=w.useCallback(k=>x(k.id),[]);return i.jsxs("div",{className:"flex min-w-0 max-w-full flex-col gap-4","data-testid":"tickets-page",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("h1",{className:"text-2xl font-bold text-text-primary-dark",children:cn.PAGE_TITLE}),i.jsx("p",{className:"mt-1 text-sm text-text-secondary-dark",children:cn.PAGE_SUBTITLE})]}),i.jsx(zt,{icon:an,variant:"ghost","aria-label":cn.REFRESH,onClick:()=>void m()})]}),i.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center",children:[i.jsx("div",{className:"w-full sm:max-w-xs",children:i.jsx(ys,{type:"search",value:e,onChange:k=>n(k.target.value),placeholder:cn.SEARCH_PLACEHOLDER,"aria-label":cn.SEARCH_PLACEHOLDER,fullWidth:!0})}),i.jsx("div",{className:"max-w-full overflow-x-auto",children:i.jsx(ao,{options:Oje,value:a,onChange:o,size:"sm","aria-label":cn.KIND_FILTER_ARIA})})]}),h&&i.jsx(tt,{variant:"error",size:"sm",title:cn.LOAD_FAILED,children:h}),d&&!l?i.jsx("div",{className:"flex justify-center py-12",children:i.jsx(Ht,{})}):b?i.jsx(Cs,{icon:Wz,title:cn.EMPTY_BOARD_TITLE,description:cn.EMPTY_BOARD_DESC}):i.jsx("div",{className:"w-full min-w-0 overflow-x-auto pb-2","data-testid":"tickets-board",children:i.jsx("div",{className:"flex gap-3 snap-x",children:mV.map(k=>{var T;const E=g[k]??[],N=((T=l==null?void 0:l.columns)==null?void 0:T[k])??E.length;return i.jsxs("section",{"aria-label":gN[k],"data-testid":`tickets-column-${k}`,className:"flex w-64 shrink-0 snap-start flex-col rounded-2xl border border-border-dark bg-surface-dark/50 p-2 sm:w-72",children:[i.jsxs("header",{className:"flex items-center justify-between px-1 pb-2",children:[i.jsx("h2",{className:"text-sm font-semibold text-text-primary-dark",children:gN[k]}),i.jsx(ft,{size:"sm",variant:k==="to_review"&&N>0?"primary":"default",children:N})]}),i.jsx("div",{className:"flex flex-col gap-2",children:E.length===0?i.jsx("p",{className:"px-1 py-4 text-center text-xs text-text-secondary-dark",children:cn.EMPTY_COLUMN}):E.map(A=>i.jsx(kje,{ticket:A,onOpen:S,now:t},A.id))})]},k)})})}),i.jsx(Dje,{ticketId:p,onClose:()=>x(null),onChanged:()=>void m(),now:t})]})};function qR(t){return{queued:"pending",scheduled:"paused",running:"running",blocked:"blocked",done:"completed",failed:"error",cancelled:"inactive"}[t]??"pending"}function XR(t){return{queued:"Queued",scheduled:"Scheduled",running:"Running",blocked:"Blocked",done:"Completed",failed:"Failed",cancelled:"Cancelled"}[t]??t}function YR(t){return{delegate:"primary",project_task:"info",check:"default",notify:"success",cron_run:"warning",review:"info",confirm:"warning",reconcile:"default"}[t]??"default"}function JR(t){return{delegate:"Delegate",project_task:"Project Task",check:"Check",notify:"Notify",cron_run:"Cron Run",review:"Review",confirm:"Confirm",reconcile:"Reconcile"}[t]??t}function Fje(t){return{orchestrator:"Orchestrator",team_lead:"Team Lead",agent:"Agent",system:"System"}[t]??t}function Hw(t){const e=Date.now(),n=new Date(t).getTime(),s=e-n,r=Math.floor(s/6e4),a=Math.floor(r/60),o=Math.floor(a/24);return r<1?"just now":r<60?`${r}m ago`:a<24?`${a}h ago`:`${o}d ago`}function Gg(t){const e=new Date(t);return isNaN(e.getTime())?t:e.toLocaleString("en-US",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!0})}function yV(t){return t===0?"—":t<.01?`$${t.toFixed(4)}`:`$${t.toFixed(2)}`}function gx(t){return t===0?"—":t<1e3?t.toString():t<1e6?`${(t/1e3).toFixed(1)}K`:`${(t/1e6).toFixed(1)}M`}function vV(t){const e=[];if(e.push({id:`${t.id}-created`,kind:"status_change",label:"QUEUED",detail:"WorkItem created and added to pool.",timestamp:t.createdAt,status:"queued"}),t.startedAt&&e.push({id:`${t.id}-started`,kind:"status_change",label:"RUNNING",detail:t.target?`Claimed by agent: ${t.target}`:"Execution started.",timestamp:t.startedAt,status:"running"}),t.error){const n=t.completedAt||t.startedAt||t.createdAt;e.push({id:`${t.id}-error`,kind:"error",label:"ERROR",detail:t.error,timestamp:n,status:"failed"})}if(t.completedAt&&t.status==="done"&&e.push({id:`${t.id}-done`,kind:"status_change",label:"COMPLETED",detail:"Execution completed successfully.",timestamp:t.completedAt,status:"done"}),t.completedAt&&t.status==="failed"&&e.push({id:`${t.id}-failed`,kind:"status_change",label:"FAILED",detail:`Execution failed after ${t.retryCount}/${t.maxRetries} retries.`,timestamp:t.completedAt,status:"failed"}),t.status==="cancelled"){const n=t.completedAt||t.createdAt,s=t.cancelReason,r=typeof s=="string"&&s.length>0?`Cancelled: ${s}`:"Cancelled (no reason recorded).";e.push({id:`${t.id}-cancelled`,kind:"status_change",label:"CANCELLED",detail:r,timestamp:n,status:"cancelled"})}if(t.status==="blocked"){const n=t.blockedReason,s=typeof n=="string"&&n.length>0?`Blocked: ${n}`:"Blocked (no reason recorded).";e.push({id:`${t.id}-blocked`,kind:"status_change",label:"BLOCKED",detail:s,timestamp:t.startedAt||t.createdAt,status:"blocked"})}if(t.result&&Object.keys(t.result).length>0){const n=t.completedAt||t.startedAt||t.createdAt;e.push({id:`${t.id}-result`,kind:"progress_update",label:"RESULT DATA",detail:JSON.stringify(t.result,null,2),timestamp:n})}return e.sort((n,s)=>new Date(s.timestamp).getTime()-new Date(n.timestamp).getTime())}function Uje(t,e){if(t==="error")return ul;if(t==="progress_update")return x2;if(t==="agent_reasoning"||t==="tool_action")return di;switch(e){case"queued":return ps;case"running":return di;case"done":return ia;case"failed":return ul;case"cancelled":return zX;case"blocked":return yh;default:return ps}}function zje(t,e){if(t==="error")return"text-red-400";if(t==="progress_update")return"text-blue-400";switch(e){case"queued":return"text-text-secondary-dark";case"running":return"text-green-400";case"done":return"text-blue-400";case"failed":return"text-red-400";case"cancelled":return"text-text-secondary-dark";case"blocked":return"text-yellow-400";default:return"text-text-secondary-dark"}}function Hje(t,e){return t==="error"?"border-red-500/30":e==="done"?"border-blue-500/30":e==="running"?"border-green-500/30":"border-border-dark"}const ZR=({events:t})=>t.length===0?i.jsx("div",{className:"flex items-center justify-center py-8 text-text-secondary-dark text-sm","data-testid":"timeline-empty",children:"No activity recorded yet."}):i.jsx("div",{className:"relative","data-testid":"workitem-timeline",children:t.map((e,n)=>{const s=Uje(e.kind,e.status),r=zje(e.kind,e.status),a=Hje(e.kind,e.status),o=n===t.length-1;return i.jsxs("div",{className:"relative flex gap-4 pb-6","data-testid":`timeline-event-${e.id}`,children:[!o&&i.jsx("div",{className:`absolute left-[15px] top-8 bottom-0 w-px border-l ${a}`}),i.jsx("div",{className:"relative z-10 flex-shrink-0 mt-0.5",children:i.jsx("div",{className:`p-1 rounded-full bg-surface-dark ${r}`,children:i.jsx(s,{className:"h-5 w-5"})})}),i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx("span",{className:`text-sm font-semibold ${r}`,children:e.label}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:Gg(e.timestamp)})]}),e.detail&&i.jsx("div",{className:`mt-1 text-sm ${e.kind==="error"?"bg-red-500/10 border border-red-500/20 rounded-md p-2 text-red-300":e.kind==="progress_update"?"bg-surface-dark border border-border-dark rounded-md p-2 text-text-secondary-dark font-mono text-xs whitespace-pre-wrap overflow-x-auto max-h-40 overflow-y-auto":"text-text-secondary-dark"}`,children:e.detail})]})]},e.id)})});ZR.displayName="WorkItemTimeline";const Ga=({icon:t,label:e,value:n,valueClass:s="text-text-primary-dark"})=>i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsxs("div",{className:"flex items-center gap-2 text-text-secondary-dark",children:[i.jsx(t,{className:"h-4 w-4"}),i.jsx("span",{className:"text-sm",children:e})]}),i.jsx("span",{className:`text-sm font-medium ${s}`,children:n})]}),bV=({item:t})=>{const e=Gje(t);return i.jsxs("div",{className:"space-y-4","data-testid":"workitem-metrics",children:[i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:"Token Usage"}),i.jsxs("div",{className:"divide-y divide-border-dark",children:[i.jsx(Ga,{icon:Bx,label:"Input Tokens",value:gx(t.inputTokens)}),i.jsx(Ga,{icon:Bx,label:"Output Tokens",value:gx(t.outputTokens)}),i.jsx(Ga,{icon:y2,label:"Cost",value:yV(t.cost),valueClass:t.cost>0?"text-yellow-400":"text-text-primary-dark"})]})]}),i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:"Execution"}),i.jsxs("div",{className:"divide-y divide-border-dark",children:[i.jsx(Ga,{icon:an,label:"Retries",value:`${t.retryCount} / ${t.maxRetries}`}),i.jsx(Ga,{icon:ps,label:"Duration",value:e}),i.jsx(Ga,{icon:Yp,label:"Owner",value:Fje(t.owner)}),t.target&&i.jsx(Ga,{icon:nh,label:"Agent",value:t.target})]})]}),(t.requestId||t.missionId||t.projectTaskId||t.triggerId)&&i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:"Linked References"}),i.jsxs("div",{className:"divide-y divide-border-dark",children:[t.requestId&&i.jsx(Ga,{icon:Gl,label:"Request",value:Tg(t.requestId)}),t.missionId&&i.jsx(Ga,{icon:Gl,label:"Mission",value:Tg(t.missionId)}),t.projectTaskId&&i.jsx(Ga,{icon:Gl,label:"Project Task",value:Tg(t.projectTaskId)}),t.triggerId&&i.jsx(Ga,{icon:Gl,label:"Trigger",value:Tg(t.triggerId)}),t.parentWorkItemId&&i.jsx(Ga,{icon:Gl,label:"Parent Item",value:Tg(t.parentWorkItemId)})]})]}),i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h3",{className:"text-xs font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:"Timestamps"}),i.jsxs("div",{className:"space-y-2 text-sm",children:[i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Created"}),i.jsx("span",{className:"text-text-primary-dark",children:Gg(t.createdAt)})]}),t.startedAt&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Started"}),i.jsx("span",{className:"text-text-primary-dark",children:Gg(t.startedAt)})]}),t.completedAt&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Completed"}),i.jsx("span",{className:"text-text-primary-dark",children:Gg(t.completedAt)})]}),t.scheduledAt&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Scheduled"}),i.jsx("span",{className:"text-text-primary-dark",children:Gg(t.scheduledAt)})]})]})]})]})};bV.displayName="WorkItemMetrics";function Gje(t){const e=t.startedAt?new Date(t.startedAt).getTime():null,n=t.completedAt?new Date(t.completedAt).getTime():t.startedAt?Date.now():null;if(!e||!n)return"--";const s=n-e,r=Math.floor(s/1e3)%60,a=Math.floor(s/6e4)%60,o=Math.floor(s/36e5);return o>0?`${o}h ${a}m`:a>0?`${a}m ${r}s`:`${r}s`}function Tg(t){return t.length<=12?t:`${t.slice(0,8)}...`}function Wje(t){const e={total:t.length,running:0,queued:0,done:0,failed:0,blocked:0};for(const n of t)switch(n.status){case"running":e.running++;break;case"queued":case"scheduled":e.queued++;break;case"done":e.done++;break;case"failed":e.failed++;break;case"blocked":e.blocked++;break}return e}const Vje=({stats:t})=>t?i.jsxs(A2,{variant:"horizontal",className:"grid-cols-3 md:grid-cols-6","data-testid":"workitem-summary-bar",children:[i.jsx(ii,{label:"Total",value:t.total}),i.jsx(ii,{label:"Running",children:i.jsx("span",{className:"text-blue-400",children:t.running})}),i.jsx(ii,{label:"Queued",children:i.jsx("span",{className:"text-yellow-400",children:t.queued})}),i.jsx(ii,{label:"Done",children:i.jsx("span",{className:"text-green-400",children:t.done})}),i.jsx(ii,{label:"Failed",children:i.jsx("span",{className:"text-red-400",children:t.failed})}),i.jsx(ii,{label:"Blocked",children:i.jsx("span",{className:"text-orange-400",children:t.blocked})})]}):null,_V=()=>{const t=ms(),[e,n]=w.useState([]),[s,r]=w.useState(!0),[a,o]=w.useState(null),[l,c]=w.useState("all"),[d,u]=w.useState(""),[h,f]=w.useState(""),p=w.useRef(),x=w.useCallback(k=>{f(k),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{u(k)},300)},[]);w.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const y=w.useCallback(async()=>{r(!0),o(null);try{const k=await yt.getWorkItems();if(!Array.isArray(k)){console.warn("[WorkItems] getWorkItems returned non-array:",typeof k,k),n([]);return}n(k)}catch(k){console.warn("[WorkItems] loadItems error:",k),o(k instanceof Error?k.message:"Failed to load work items")}finally{r(!1)}},[]);w.useEffect(()=>{y()},[y]);const m=w.useMemo(()=>{let k=e;if(l!=="all"&&(k=k.filter(N=>N.status===l)),d.trim()){const N=d.toLowerCase();k=k.filter(T=>{var A;return T.title.toLowerCase().includes(N)||T.id.toLowerCase().includes(N)||((A=T.target)==null?void 0:A.toLowerCase().includes(N))||T.type.toLowerCase().includes(N)})}const E={running:0,blocked:1,failed:2,done:3,completed:3,cancelled:4,queued:5,scheduled:5};return k.sort((N,T)=>{const A=E[N.status]??5,M=E[T.status]??5;return A!==M?A-M:new Date(T.createdAt).getTime()-new Date(N.createdAt).getTime()})},[e,l,d]),g=w.useMemo(()=>{const k={all:e.length};for(const E of e)k[E.status]=(k[E.status]||0)+1;return k},[e]),v=w.useMemo(()=>e.length>0?Wje(e):null,[e]),b=[{key:"all",label:"All"},{key:"running",label:"Running"},{key:"queued",label:"Queued"},{key:"done",label:"Completed"},{key:"failed",label:"Failed"},{key:"blocked",label:"Blocked"},{key:"cancelled",label:"Cancelled"}],S=w.useCallback((k,E)=>{(k.key==="Enter"||k.key===" ")&&(k.preventDefault(),t(`/workitems/${E}`))},[t]);return i.jsxs("div",{className:"p-6 max-w-7xl mx-auto","data-testid":"workitems-page",children:[i.jsxs("div",{className:"mb-6",children:[i.jsxs("div",{className:"flex items-center justify-between mb-2",children:[i.jsx("h1",{className:"text-2xl font-bold text-text-primary-dark",children:"Work Items"}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:y,loading:s,"data-testid":"workitems-refresh",children:"Refresh"})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Execution-level view of all system tasks in the task pool."})]}),!s&&i.jsx(Vje,{stats:v}),i.jsx(Id,{tabs:b.map(k=>({value:k.key,label:k.label,count:g[k.key]})),activeTab:l,onTabChange:k=>c(k),searchPlaceholder:"Search by title, ID, agent...",searchValue:h,onSearchChange:x}),s&&i.jsx("div",{"data-testid":"workitems-loading",children:i.jsx(j1,{count:4})}),a&&!s&&i.jsxs(tt,{variant:"error",title:"Failed to load work items",onClose:()=>o(null),"data-testid":"workitems-error",children:[a,i.jsx(de,{variant:"ghost",size:"sm",onClick:y,className:"mt-2",children:"Retry"})]}),!s&&!a&&m.length===0&&i.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-16 text-text-secondary-dark","data-testid":"workitems-empty",children:[i.jsx(bh,{className:"h-10 w-10 opacity-40"}),i.jsx("span",{className:"text-sm",children:e.length===0?"No work items in the pool yet.":"No work items match the current filters."})]}),!s&&!a&&m.length>0&&i.jsx("div",{className:"flex flex-col gap-2","data-testid":"workitems-list",children:m.map(k=>i.jsx(dt,{variant:"default",padding:"md",interactive:!0,className:"hover:border-primary/40",role:"button",tabIndex:0,onClick:()=>t(`/workitems/${k.id}`),onKeyDown:E=>S(E,k.id),"data-testid":`workitem-row-${k.id}`,children:i.jsxs("div",{className:"flex items-center justify-between gap-4",children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsx("div",{className:"flex items-center gap-2 mb-1",children:i.jsx("span",{className:"text-base font-medium text-text-primary-dark truncate",children:k.title})}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Lo,{status:qR(k.status),children:XR(k.status)}),i.jsx(ft,{variant:YR(k.type),size:"sm",children:JR(k.type)}),k.target&&i.jsx(ft,{variant:"default",size:"sm",children:k.target}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:Hw(k.createdAt)})]})]}),i.jsx("span",{className:"text-xs text-text-secondary-dark font-mono flex-shrink-0",children:k.id.slice(0,8)})]})},k.id))})]})};_V.displayName="WorkItems";const SV=()=>{const{id:t}=gh(),e=ms(),[n,s]=w.useState(null),[r,a]=w.useState(!0),[o,l]=w.useState(null),[c,d]=w.useState(!1),u=w.useCallback(async(x=!0)=>{if(t){x?a(!0):d(!0),l(null);try{const y=await yt.getWorkItem(t);s(y)}catch(y){const m=y instanceof Error?y.message:"Failed to load WorkItem";l(m)}finally{a(!1),d(!1)}}},[t]);w.useEffect(()=>{u(!0)},[u]),w.useEffect(()=>{if(!n||n.status!=="running")return;const x=setInterval(()=>{u(!1)},1e4);return()=>clearInterval(x)},[n==null?void 0:n.status,u]);const h=()=>{e("/workitems")},f=()=>{u(!1)};if(r)return i.jsx("div",{className:"flex items-center justify-center h-64","data-testid":"workitem-detail-loading",children:i.jsx(Ht,{})});if(o)return i.jsxs("div",{className:"p-6","data-testid":"workitem-detail-error",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:h,className:"mb-6",children:"Back to WorkItems"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"flex flex-col items-center text-center py-8",children:[i.jsx("p",{className:"text-red-400 text-lg font-medium mb-2",children:"Failed to load WorkItem"}),i.jsx("p",{className:"text-text-secondary-dark text-sm mb-4",children:o}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:()=>u(!0),children:"Retry"})]})})]});if(!n)return i.jsxs("div",{className:"p-6","data-testid":"workitem-detail-not-found",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:h,className:"mb-6",children:"Back to WorkItems"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsx(Cs,{icon:YX,title:"WorkItem not found.",compact:!0})})]});const p=vV(n);return i.jsxs("div",{className:"p-6 max-w-[1400px] mx-auto","data-testid":"workitem-detail",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:h,className:"mb-4","data-testid":"workitem-detail-back",children:"Back to WorkItems"}),i.jsxs("div",{className:"mb-6","data-testid":"workitem-detail-header",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-3",children:[i.jsx("div",{className:"flex-1 min-w-0",children:i.jsxs("h1",{className:"text-xl font-bold text-text-primary-dark truncate",children:["WorkItem: ",RA(n.id)," — ",n.title]})}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:f,loading:c,"data-testid":"workitem-detail-refresh",children:"Refresh"})]}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Lo,{status:qR(n.status),children:XR(n.status)}),i.jsx(ft,{variant:YR(n.type),children:JR(n.type)}),i.jsxs(ft,{variant:"default",children:["Retry ",n.retryCount,"/",n.maxRetries]}),n.requestId&&i.jsx(ft,{variant:"info",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(ws,{className:"h-3 w-3"}),"Request: ",RA(n.requestId)]})}),n.missionId&&i.jsx(ft,{variant:"info",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(ws,{className:"h-3 w-3"}),"Mission: ",RA(n.missionId)]})}),i.jsxs("span",{className:"text-xs text-text-secondary-dark ml-2",children:["Created ",Hw(n.createdAt)]}),n.target&&i.jsxs(ft,{variant:"primary",children:["Agent: ",n.target]})]}),n.description&&i.jsx("p",{className:"mt-3 text-sm text-text-secondary-dark leading-relaxed",children:n.description})]}),i.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[i.jsx("div",{className:"lg:col-span-2",children:i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wider mb-4",children:"Activity Timeline"}),i.jsx(ZR,{events:p})]})}),i.jsx("div",{className:"lg:col-span-1",children:i.jsx(bV,{item:n})})]})]})};SV.displayName="WorkItemDetail";function RA(t){return t.length<=12?t:t.slice(0,8)}const $je=({stats:t})=>t?i.jsxs(A2,{variant:"horizontal",className:"grid-cols-2 md:grid-cols-6","data-testid":"request-summary-bar",children:[i.jsx(ii,{label:"Total Incoming",value:t.total}),i.jsx(ii,{label:"Active",value:t.active}),i.jsx(ii,{label:"Blocked",children:i.jsx("span",{className:"text-red-400",children:t.blocked})}),i.jsx(ii,{label:"Waiting",children:i.jsx("span",{className:"text-yellow-400",children:t.waitingConfirmation})}),i.jsx(ii,{label:"Done",children:i.jsx("span",{className:"text-blue-400",children:t.done})}),i.jsx(ii,{label:"Total Cost",children:i.jsx("span",{className:"text-emerald-400",children:t.totalCost>0?`$${t.totalCost.toFixed(2)}`:"$0.00"})})]}):null;function Kje(t){return{active:"Active",blocked:"Blocked",waiting_confirmation:"Waiting Confirmation",done:"Done"}[t]??t}function qje(t){return{critical:"error",high:"warning",medium:"info",low:"default"}[t]??"default"}function Xje(t){return{critical:"Critical",high:"High",medium:"Medium",low:"Low"}[t]??t}function Yje(t){return t.charAt(0).toUpperCase()+t.slice(1)}function Jje(t){const e=Date.now(),n=new Date(t).getTime(),s=e-n,r=Math.floor(s/6e4),a=Math.floor(r/60),o=Math.floor(a/24);return r<1?"just now":r<60?`${r}m ago`:a<24?`${a}h ago`:`${o}d ago`}function Zje(t){return{total:t.length,active:t.filter(e=>e.status==="active").length,blocked:t.filter(e=>e.status==="blocked").length,waitingConfirmation:t.filter(e=>e.status==="waiting_confirmation").length,done:t.filter(e=>e.status==="done").length,totalCost:t.reduce((e,n)=>e+(n.totalCost||0),0)}}const Qje={active:"bg-amber-500/10 text-amber-400 border-amber-500/20",blocked:"bg-red-500/10 text-red-400 border-red-500/20",waiting_confirmation:"bg-primary/10 text-primary border-primary/20",done:"bg-green-500/10 text-green-400 border-green-500/20"},eRe={active:"bg-amber-400",blocked:"bg-red-400",waiting_confirmation:"bg-primary",done:"bg-green-400"},tRe=({status:t,label:e,className:n=""})=>{const s=Qje[t],r=eRe[t],a=e??Kje(t),o=t==="active";return i.jsxs("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 text-xs font-medium rounded-full border ${s} ${n}`.trim(),"data-status":t,"data-testid":`request-status-pill-${t}`,children:[i.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${r} ${o?"animate-pulse":""}`.trim(),"aria-hidden":"true"}),a]})},nRe={slack:Xp,email:Lz,chat:Dz,api:A1,manual:Oz},sRe=({item:t})=>{const e=t.status==="done"?"active":t.status==="in_progress"?"connecting":"inactive";return i.jsxs("div",{className:"flex items-center gap-2.5 py-1.5 border-b border-border-dark last:border-b-0","data-testid":`request-child-${t.id}`,children:[i.jsx(No,{status:e,size:"sm",pulse:!1}),i.jsx("span",{className:"flex-1 text-xs text-text-secondary-dark",children:t.label}),t.tag&&i.jsx(ft,{variant:"error",size:"sm",children:t.tag}),t.progress!==void 0&&i.jsx("div",{className:"w-20 h-1.5 bg-background-dark rounded-full overflow-hidden",children:i.jsx("div",{className:"h-full bg-primary rounded-full transition-all duration-300",style:{width:`${t.progress}%`}})}),t.assignee&&i.jsx("span",{className:"text-xs text-text-secondary-dark/60",children:t.assignee}),t.dueDate&&i.jsx("span",{className:"text-xs text-text-secondary-dark/60 whitespace-nowrap",children:t.dueDate})]})},rRe=({request:t})=>{const[e,n]=w.useState(!1),s=ms(),r=!!(t.childItems&&t.childItems.length>0),a=w.useCallback(()=>{s(`/tasks/${t.id}`)},[s,t.id]),o=w.useCallback(f=>{f.stopPropagation(),r&&n(p=>!p)},[r]),l=w.useCallback(f=>{f.key==="Enter"?(f.preventDefault(),a()):f.key===" "&&(f.preventDefault(),r&&n(p=>!p))},[a,r]),c=nRe[t.source]??bh,d=qje(t.priority),u=Yje(t.source),h=Jje(t.updatedAt);return i.jsx("li",{className:"list-none",children:i.jsxs(dt,{variant:"default",padding:"none",className:"overflow-hidden hover:border-border-light transition-colors","data-testid":`request-row-${t.id}`,children:[i.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 cursor-pointer hover:bg-background-dark/30 transition-colors",role:"button",tabIndex:0,"aria-label":`Open request: ${t.title}`,onClick:a,onKeyDown:l,children:[i.jsx(c,{className:"h-5 w-5 text-text-secondary-dark flex-shrink-0","aria-label":u}),i.jsxs("div",{className:"flex-1 min-w-0 flex flex-col gap-1",children:[i.jsxs("div",{className:"flex items-start gap-2","data-testid":"request-tier-top",children:[i.jsx("span",{className:"text-[15px] font-semibold leading-5 text-text-primary-dark line-clamp-2 flex-1 min-w-0",children:t.title}),i.jsx(tRe,{status:t.status,className:"flex-shrink-0"})]}),i.jsxs("div",{className:"flex items-center gap-3 text-xs text-text-secondary-dark/70 flex-wrap","data-testid":"request-tier-bottom",children:[i.jsx(ft,{variant:d,size:"sm",children:Xje(t.priority)}),t.category&&i.jsx("span",{"data-testid":"request-meta-category",className:"text-text-secondary-dark",children:t.category}),t.missionLink&&i.jsxs("span",{"data-testid":"request-meta-mission",className:"whitespace-nowrap",children:["Mission: ",i.jsx("span",{className:"text-primary",children:t.missionLink})]}),i.jsxs("span",{"data-testid":"request-meta-workitems",className:"inline-flex items-center gap-1 whitespace-nowrap",title:`${t.workItemCount} work item${t.workItemCount===1?"":"s"}`,children:[i.jsx(Fx,{className:"h-3 w-3","aria-hidden":"true"}),t.workItemCount,i.jsxs("span",{className:"sr-only",children:[" ","work item",t.workItemCount===1?"":"s"]})]}),i.jsx("span",{"data-testid":"request-meta-updated",className:"ml-auto whitespace-nowrap",children:h})]})]}),r&&i.jsx(zt,{icon:e?$r:Wr,size:"xs",onClick:o,className:"flex-shrink-0","aria-label":e?"Collapse work items":"Expand work items"})]}),e&&i.jsxs("div",{className:"border-t border-border-dark px-4 py-2 space-y-1.5","data-testid":"request-children",children:[i.jsxs("div",{className:"flex items-center gap-2 text-xs text-text-secondary-dark/60",children:[i.jsx("span",{className:"uppercase tracking-wide",children:"Source"}),i.jsx(ft,{variant:"default",size:"sm",children:u}),t.ownerAgent&&i.jsxs("span",{className:"text-text-secondary-dark",children:["via ",t.ownerAgent]})]}),r&&i.jsx("div",{children:t.childItems.map(f=>i.jsx(sRe,{item:f},f.id))})]})]})})};function iRe(t){switch(t){case"open":case"ready":case"running":return"active";case"blocked":return"blocked";case"waiting_confirmation":return"waiting_confirmation";case"done":case"cancelled":return"done";default:return typeof console<"u"&&t&&console.warn("[RequestList] Unknown backend Request status:",t),"active"}}function aRe(t){switch(t){case"high":return"high";case"low":return"low";default:return"medium"}}function oRe(t){return t.map(e=>{const n=Array.isArray(e.workItemIds)?e.workItemIds:[],s=e.intentCategory;return{id:e.id||"",title:e.title||"Untitled Request",status:iRe(e.status||""),priority:aRe(e.priority||""),source:(e.tags||[]).includes("slack")?"slack":"api",requester:"user",category:s&&s.length>0?s:void 0,workItemCount:n.length,updatedAt:e.updatedAt||e.createdAt||new Date().toISOString(),missionLink:e.missionId?`Mission: ${e.missionId.slice(0,8)}`:void 0,totalInputTokens:e.totalInputTokens||0,totalOutputTokens:e.totalOutputTokens||0,totalCost:e.totalCost||0,ownerAgent:e.ownerAgent||void 0}}).sort((e,n)=>new Date(n.updatedAt).getTime()-new Date(e.updatedAt).getTime())}const lRe=new Set(["critical","high"]),cRe=({activeFilter:t,secondaryFilters:e,searchQuery:n,onStatsLoaded:s})=>{const[r,a]=w.useState([]),[o,l]=w.useState(!0),[c,d]=w.useState(null),u=w.useCallback(async()=>{l(!0),d(null);try{const p=await yt.getRequests();if(!Array.isArray(p)){console.warn("[RequestList] getRequests returned non-array:",typeof p,p),a([]);return}const x=oRe(p);a(x)}catch(p){console.warn("[RequestList] loadRequests error:",p),d(p instanceof Error?p.message:"Failed to load requests"),a([])}finally{l(!1)}},[]);w.useEffect(()=>{u()},[u]);const h=w.useMemo(()=>Zje(r),[r]);w.useEffect(()=>{s(h)},[h,s]);const f=w.useMemo(()=>{let p=r;if(t!=="all"&&(p=p.filter(x=>x.status===t)),e&&e.size>0&&(e.has("urgent")&&(p=p.filter(x=>lRe.has(x.priority))),e.has("assigned_to_me")&&(p=p.filter(x=>x.requester==="user"))),n.trim()){const x=n.toLowerCase();p=p.filter(y=>{var m;return y.title.toLowerCase().includes(x)||y.requester.toLowerCase().includes(x)||((m=y.missionLink)==null?void 0:m.toLowerCase().includes(x))})}return p},[r,t,e,n]);return o?i.jsx("div",{"data-testid":"request-list-loading",children:i.jsx(j1,{count:4})}):c?i.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-16 text-text-secondary-dark","data-testid":"request-list-error",children:[i.jsx("span",{className:"text-sm text-red-400",children:c}),i.jsx(de,{variant:"link",onClick:u,children:"Retry"})]}):f.length===0?i.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-16 text-text-secondary-dark","data-testid":"request-list-empty",children:[i.jsx(bh,{className:"h-10 w-10 opacity-40"}),i.jsx("span",{className:"text-sm",children:r.length===0?"No requests found. Requests will appear here when user messages are processed.":"No requests match the current filters."})]}):i.jsx("div",{className:"flex flex-col gap-2","data-testid":"request-list",children:f.map(p=>i.jsx(rRe,{request:p},p.id))})},dRe=()=>{const[t,e]=w.useState(null),[n,s]=w.useState("active"),[r,a]=w.useState(new Set),[o,l]=w.useState(""),c=w.useCallback(f=>{e(f)},[]),d=w.useCallback(f=>{a(p=>{const x=new Set(p);return x.has(f)?x.delete(f):x.add(f),x})},[]),u=w.useMemo(()=>[{value:"all",label:"All",count:t==null?void 0:t.total},{value:"active",label:"Active",count:t==null?void 0:t.active},{value:"blocked",label:"Blocked",count:t==null?void 0:t.blocked},{value:"waiting_confirmation",label:"Waiting",count:t==null?void 0:t.waitingConfirmation},{value:"done",label:"Done",count:t==null?void 0:t.done}],[t]),h=w.useMemo(()=>[{value:"assigned_to_me",label:"Assigned to Me"},{value:"urgent",label:"Urgent"}],[]);return i.jsxs("div",{className:"p-6 max-w-7xl mx-auto","data-testid":"requests-page",children:[i.jsxs("div",{className:"mb-6","data-testid":"requests-page-header",children:[i.jsx("h1",{className:"text-2xl font-bold text-text-primary-dark",children:"Requests"}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Monitor and triage incoming work from all channels."})]}),i.jsx($je,{stats:t}),i.jsx(Id,{tabs:u,activeTab:n,onTabChange:f=>s(f),searchPlaceholder:"Search requests...",searchValue:o,onSearchChange:l,secondaryFilters:h,activeSecondaryFilters:r,onSecondaryFilterToggle:f=>d(f)}),i.jsx(cRe,{activeFilter:n,secondaryFilters:r,searchQuery:o,onStatsLoaded:c})]})},n5={open:"text-blue-400",in_progress:"text-amber-400",blocked:"text-red-400",waiting_confirmation:"text-primary",done:"text-green-400",cancelled:"text-text-secondary-dark"};function yN(t){return{open:"Open",in_progress:"In Progress",blocked:"Blocked",waiting_confirmation:"Waiting Confirmation",done:"Completed",cancelled:"Cancelled"}[t]??t}function uRe(t){return{open:"active",in_progress:"running",blocked:"blocked",waiting_confirmation:"paused",done:"completed",cancelled:"inactive"}[t]??"pending"}const s5=["open","in_progress","done"],hRe=({currentStatus:t})=>{const e=s5.indexOf(t),n=t==="cancelled",s=t==="blocked";return i.jsxs("div",{className:"flex items-center gap-1","data-testid":"request-progress-rail",children:[s5.map((r,a)=>{const o=e>=0&&a<=e,l=r===t;return i.jsxs(jn.Fragment,{children:[a>0&&i.jsx("div",{className:`flex-1 h-0.5 ${o?"bg-green-500":"bg-border-dark"}`}),i.jsxs("div",{className:`flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium ${l?`${n5[r]||"text-blue-400"} bg-surface-dark border border-primary/30`:o?"text-green-400 bg-green-500/10":"text-text-secondary-dark bg-surface-dark"}`,children:[o&&!l&&i.jsx(ia,{className:"h-3 w-3"}),yN(r)]})]},r)}),(n||s)&&i.jsxs(i.Fragment,{children:[i.jsx("div",{className:"flex-1 h-0.5 bg-border-dark"}),i.jsx("div",{className:`flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium ${n5[t]||"text-text-secondary-dark"} bg-surface-dark border border-red-500/30`,children:yN(t)})]})]})},fRe=({workItems:t,onItemClick:e})=>{const[n,s]=w.useState(null);return t.length===0?i.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-12 text-text-secondary-dark","data-testid":"request-workitems-empty",children:[i.jsx(bh,{className:"h-8 w-8 opacity-40"}),i.jsx("span",{className:"text-sm",children:"No work items associated with this request yet."})]}):i.jsx("div",{className:"flex flex-col gap-2","data-testid":"request-workitems-list",children:t.map(r=>{const a=n===r.id,o=a?vV(r):[];return i.jsxs(dt,{variant:"default",padding:"none",className:"overflow-hidden hover:border-primary/40 transition-colors","data-testid":`request-workitem-${r.id}`,children:[i.jsxs("div",{className:"flex items-center gap-3 px-4 py-3 cursor-pointer hover:bg-background-dark/30 transition-colors",role:"button",tabIndex:0,onClick:()=>s(a?null:r.id),onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),s(a?null:r.id))},children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsx("div",{className:"flex items-center gap-2 mb-1",children:i.jsx("span",{className:"text-sm font-medium text-text-primary-dark truncate",children:r.title})}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Lo,{status:qR(r.status),children:XR(r.status)}),i.jsx(ft,{variant:YR(r.type),size:"sm",children:JR(r.type)}),r.target&&i.jsx(ft,{variant:"default",size:"sm",children:r.target}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:Hw(r.createdAt)})]})]}),i.jsx(de,{variant:"link",size:"xs",onClick:l=>{l.stopPropagation(),e(r.id)},className:"flex-shrink-0","data-testid":`request-workitem-detail-link-${r.id}`,children:"Details"})]}),a&&i.jsx("div",{className:"border-t border-border-dark px-4 py-3","data-testid":`request-workitem-timeline-${r.id}`,children:i.jsx(ZR,{events:o})})]},r.id)})})},wV=()=>{const{id:t}=gh(),e=ms(),[n,s]=w.useState(null),[r,a]=w.useState([]),[o,l]=w.useState(!0),[c,d]=w.useState(null),[u,h]=w.useState(!1),f=w.useCallback(async(b=!0)=>{if(t){b?l(!0):h(!0),d(null);try{const[S,k]=await Promise.all([yt.getRequest(t),yt.getWorkItemsByRequest(t)]);s(S),a(k.sort((E,N)=>new Date(N.createdAt).getTime()-new Date(E.createdAt).getTime()))}catch(S){const k=S instanceof Error?S.message:"Failed to load request";d(k)}finally{l(!1),h(!1)}}},[t]);w.useEffect(()=>{f(!0)},[f]),w.useEffect(()=>{if(!n||n.status==="done"||n.status==="cancelled")return;const b=setInterval(()=>{f(!1)},15e3);return()=>clearInterval(b)},[n==null?void 0:n.status,f]);const p=w.useCallback(()=>{e("/tasks")},[e]),x=w.useCallback(b=>{e(`/workitems/${b}`)},[e]),y=w.useCallback(()=>{f(!1)},[f]),m=w.useCallback(async b=>{if(t)try{const S=b==="confirmed"?"done":"cancelled";await yt.updateRequest(t,{status:S}),f(!1)}catch(S){const k=S instanceof Error?S.message:"Failed to update request";d(k)}},[t,f]),g=w.useMemo(()=>n?n.totalInputTokens+n.totalOutputTokens:0,[n]),v=w.useMemo(()=>{if(!n)return"";const b=new Date(n.createdAt).getTime(),k=(n.completedAt?new Date(n.completedAt).getTime():Date.now())-b,E=Math.floor(k/6e4),N=Math.floor(E/60);return E<1?"< 1m":N<1?`${E}m`:`${N}h ${E%60}m`},[n]);return o?i.jsx("div",{className:"flex items-center justify-center h-64","data-testid":"request-detail-loading",children:i.jsx(Ht,{})}):c?i.jsxs("div",{className:"p-6","data-testid":"request-detail-error",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:p,className:"mb-6",children:"Back to Requests"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"flex flex-col items-center text-center py-8",children:[i.jsx("p",{className:"text-red-400 text-lg font-medium mb-2",children:"Failed to load Request"}),i.jsx("p",{className:"text-text-secondary-dark text-sm mb-4",children:c}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:()=>f(!0),children:"Retry"})]})})]}):n?i.jsxs("div",{className:"p-6 max-w-[1200px] mx-auto","data-testid":"request-detail",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:p,className:"mb-4","data-testid":"request-detail-back",children:"Back to Requests"}),i.jsxs("div",{className:"mb-6","data-testid":"request-detail-header",children:[i.jsxs("div",{className:"flex items-start justify-between gap-4 mb-3",children:[i.jsx("div",{className:"flex-1 min-w-0",children:i.jsx("h1",{className:"text-xl font-bold text-text-primary-dark",children:n.title})}),i.jsx(de,{variant:"secondary",size:"sm",icon:an,onClick:y,loading:u,"data-testid":"request-detail-refresh",children:"Refresh"})]}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap mb-4",children:[i.jsx(Lo,{status:uRe(n.status),children:yN(n.status)}),n.priority&&n.priority!=="normal"&&i.jsx(ft,{variant:n.priority==="high"?"warning":"default",size:"sm",children:n.priority.charAt(0).toUpperCase()+n.priority.slice(1)}),n.intentCategory&&i.jsx(ft,{variant:"info",size:"sm",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(Gz,{className:"h-3 w-3"}),n.intentCategory.replace(/_/g," ")]})}),n.intentLevel&&i.jsx(ft,{variant:"default",size:"sm",children:n.intentLevel}),n.requiresConfirmation&&i.jsx(ft,{variant:"warning",size:"sm",children:"Requires Confirmation"}),i.jsxs("span",{className:"text-xs text-text-secondary-dark ml-2",children:["Created ",Hw(n.createdAt)]})]}),i.jsx(hRe,{currentStatus:n.status})]}),n.requiresConfirmation&&n.status==="waiting_confirmation"&&i.jsxs(dt,{padding:"md",className:"flex gap-3 mt-4","data-testid":"request-action-area",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark mr-auto flex items-center",children:"This request requires your confirmation before completing"}),i.jsx(de,{variant:"secondary",size:"sm",onClick:()=>m("rejected"),children:"Reject"}),i.jsx(de,{variant:"primary",size:"sm",onClick:()=>m("confirmed"),children:"Approve"})]}),i.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6",children:[i.jsx("div",{className:"lg:col-span-2",children:i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:i.jsxs("span",{className:"flex items-center gap-1.5",children:[i.jsx(Za,{className:"h-4 w-4"}),"Original Message"]})}),n.description?i.jsx("p",{className:"text-sm text-text-primary-dark leading-relaxed whitespace-pre-wrap",children:n.description}):i.jsx("p",{className:"text-sm text-text-secondary-dark italic",children:"No description provided."}),n.sourceConversationItemId&&i.jsx("div",{className:"mt-4 pt-4 border-t border-border-dark",children:i.jsxs("span",{className:"text-xs text-text-secondary-dark",children:["Source: ",i.jsx("span",{className:"font-mono",children:n.sourceConversationItemId})]})}),n.tags.length>0&&i.jsx("div",{className:"mt-4 pt-4 border-t border-border-dark flex items-center gap-2 flex-wrap",children:n.tags.map(b=>i.jsx(ft,{variant:"default",size:"sm",children:b},b))})]})}),i.jsx("div",{className:"lg:col-span-1",children:i.jsxs(dt,{variant:"default",padding:"md",children:[i.jsx("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:"Statistics"}),i.jsxs("div",{className:"flex flex-col gap-3",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark",children:[i.jsx(Bx,{className:"h-3.5 w-3.5"}),"Total Tokens"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:gx(g)})]}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark pl-5",children:"Input"}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:gx(n.totalInputTokens)})]}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark pl-5",children:"Output"}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:gx(n.totalOutputTokens)})]}),i.jsx("div",{className:"border-t border-border-dark"}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark",children:[i.jsx(y2,{className:"h-3.5 w-3.5"}),"Total Cost"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:yV(n.totalCost)})]}),i.jsx("div",{className:"border-t border-border-dark"}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark",children:[i.jsx(ps,{className:"h-3.5 w-3.5"}),"Elapsed Time"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:v})]}),i.jsx("div",{className:"border-t border-border-dark"}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-text-secondary-dark",children:[i.jsx(Fx,{className:"h-3.5 w-3.5"}),"Work Items"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:r.length})]})]})]})})]}),i.jsxs("div",{"data-testid":"request-detail-workitems",children:[i.jsx("h2",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wider mb-3",children:i.jsxs("span",{className:"flex items-center gap-1.5",children:[i.jsx(Fx,{className:"h-4 w-4"}),"Execution Timeline (",r.length," work items)"]})}),i.jsx(fRe,{workItems:r,onItemClick:x})]})]}):i.jsxs("div",{className:"p-6","data-testid":"request-detail-not-found",children:[i.jsx(de,{variant:"ghost",size:"sm",icon:Hr,onClick:p,className:"mb-6",children:"Back to Requests"}),i.jsx(dt,{variant:"default",padding:"lg",children:i.jsx(Cs,{icon:Za,title:"Request not found.",compact:!0})})]})};wV.displayName="RequestDetail";const pRe=()=>{},mRe=({onSaved:t})=>{const[e,n]=w.useState(!1),[s,r]=w.useState(""),[a,o]=w.useState(!1);w.useEffect(()=>{const c=()=>{o(!!w0()),n(!0)};return window.addEventListener(sM,c),()=>window.removeEventListener(sM,c)},[]);const l=w.useCallback(c=>{c.preventDefault();const d=s.trim();d&&(f8(d),n(!1),t?t():window.location.reload())},[s,t]);return e?i.jsx("div",{className:"relative z-[100]",children:i.jsx(Kr,{isOpen:!0,onClose:pRe,closable:!1,title:"Access token required",size:"md","data-testid":"api-token-prompt",children:i.jsxs("form",{onSubmit:l,className:"space-y-4",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark leading-relaxed",children:[a?"The stored access token was rejected. Paste the current token to continue.":"This dashboard is being opened from another machine. Paste the access token to continue."," ","Run ",i.jsx("code",{className:"font-mono",children:"crewly token"})," on the server to print it (or ",i.jsx("code",{className:"font-mono",children:"crewly token --url"})," for a ready-to-open link)."]}),i.jsx(ys,{id:"api-token-input",label:"Access token",type:"password",value:s,onChange:c=>r(c.target.value),placeholder:"paste token",autoComplete:"off",autoFocus:!0,fullWidth:!0,className:"font-mono","data-testid":"api-token-input"}),i.jsx("div",{className:"flex justify-end",children:i.jsx(de,{type:"submit",icon:k1,disabled:!s.trim(),"data-testid":"api-token-submit",children:"Save and reload"})})]})})}):null};function gRe(t=Qg.PENDING_POLL_INTERVAL_MS){const[e,n]=w.useState([]),[s,r]=w.useState(!0),a=w.useRef(!0),o=w.useCallback(async()=>{try{const l=await Ge.get(Qg.PENDING_ENDPOINT,{timeout:Qg.PENDING_REQUEST_TIMEOUT_MS});if(!a.current)return;l.data.success&&Array.isArray(l.data.data)&&n(l.data.data)}catch{}finally{a.current&&r(!1)}},[]);return w.useEffect(()=>{a.current=!0,o();const l=setInterval(()=>{o()},t);return()=>{a.current=!1,clearInterval(l)}},[o,t]),{pending:e,isLoading:s,refresh:o}}function xRe(t){return t.map(e=>`${e.sessionName}|${e.url??""}|${e.code??""}`).sort().join(";")}const yRe=()=>{const{pending:t,isLoading:e}=gRe(),[n,s]=w.useState(null),r=w.useMemo(()=>xRe(t),[t]);return e||t.length===0||n===r?null:i.jsxs("div",{role:"status","data-testid":"pending-logins-banner",className:"fixed top-0 inset-x-0 z-50 flex items-center justify-between gap-3 px-4 py-2.5 border-b bg-amber-500/15 border-amber-500/40 backdrop-blur-sm",children:[i.jsxs("div",{className:"flex items-center gap-3 min-w-0 flex-wrap",children:[i.jsx(k1,{className:"shrink-0 text-amber-400",size:18}),i.jsx("span",{className:"font-semibold text-amber-300 text-sm",children:t.length===1?"1 agent needs you to sign in":`${t.length} agents need you to sign in`}),i.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:t.map(a=>i.jsxs("div",{className:"flex items-center gap-1 text-xs text-amber-200/90",children:[i.jsx("span",{className:"font-mono",children:a.sessionName}),i.jsx(G1,{loginRequired:a,agentLabel:a.sessionName})]},a.sessionName))})]}),i.jsx(zt,{icon:cs,size:"xs",onClick:()=>s(r),className:"shrink-0 text-amber-300 hover:bg-amber-500/20 hover:text-amber-200","aria-label":"Dismiss sign-in banner"})]})};function vRe(t){if(!t.orcHarness)return!0;const e=t.harnesses.find(n=>n.id===t.orcHarness);return e?e.installed?e.loginState==="logged_out":!0:!1}function r5(t){return!Nte.some(e=>t===e||t.startsWith(`${e}/`))}function i5(){try{return window.localStorage.getItem(dM)==="1"}catch{return!1}}function bRe(t){try{t?window.localStorage.setItem(dM,"1"):window.localStorage.removeItem(dM)}catch{}}const _Re=()=>{const t=co(),e=ms(),n=w.useRef(t.pathname);return n.current=t.pathname,w.useEffect(()=>{if(i5()||!r5(n.current))return;let s=!1;return Eo.getStatus().then(r=>{s||i5()||!r5(n.current)||vRe(r)&&e(q2,{replace:!0})}).catch(()=>{}),()=>{s=!0}},[]),null},SRe=({steps:t,currentStep:e})=>i.jsx("div",{className:"flex items-center justify-center gap-0","data-testid":"step-indicator",children:t.map((n,s)=>{const r=s<e,a=s===e,o=s===t.length-1;return i.jsxs(jn.Fragment,{children:[i.jsxs("div",{className:"flex flex-col items-center","data-testid":`step-${s}`,children:[i.jsx("div",{className:sa("flex items-center justify-center w-8 h-8 rounded-full text-xs font-bold transition-colors duration-200",r&&"bg-primary text-white",a&&"bg-primary/20 text-primary border-2 border-primary",!r&&!a&&"bg-surface-dark text-text-secondary-dark border border-border-dark"),"aria-current":a?"step":void 0,children:r?i.jsx(Kn,{className:"w-4 h-4"}):s+1}),i.jsx("span",{className:sa("mt-1.5 text-[10px] font-medium uppercase tracking-wide",a?"text-primary":"text-text-secondary-dark"),children:n})]}),!o&&i.jsx("div",{className:sa("h-0.5 w-12 mx-1 mt-[-12px] transition-colors duration-200",r?"bg-primary":"bg-border-dark")})]},n)})});function a5(t){return t.status!=="running"}function wRe(t){const e={};for(const n of t)n.type==="multiselect"?e[n.id]=Array.isArray(n.default)?[...n.default]:n.default?[n.default]:[]:e[n.id]=typeof n.default=="string"?n.default:"";return e}function CRe(t,e){return t.filter(n=>{if(!n.required)return!1;const s=e[n.id];return Array.isArray(s)?s.length===0:!s||s.trim()===""}).map(n=>n.id)}const kRe=({questions:t,submitLabel:e,submitting:n=!1,error:s=null,serverProblems:r=[],onSubmit:a})=>{const[o,l]=w.useState(()=>wRe(t)),[c,d]=w.useState([]),u=new Set([...c,...r]),h=(x,y)=>{l(m=>({...m,[x]:y})),d(m=>m.filter(g=>g!==x))},f=(x,y)=>{const m=o[x],g=Array.isArray(m)?m:[];h(x,g.includes(y)?g.filter(v=>v!==y):[...g,y])},p=x=>{x.preventDefault();const y=CRe(t,o);d(y),y.length===0&&a(o)};return i.jsxs("form",{className:"space-y-4",onSubmit:p,noValidate:!0,"data-testid":"bundle-questions",children:[t.map(x=>{const y=`bundle-q-${x.id}`,m=o[x.id],g=u.has(x.id);return i.jsxs(Ai,{children:[i.jsx(bt,{id:`${y}-label`,htmlFor:x.type==="multiselect"?void 0:y,required:x.required,children:x.label}),x.type==="text"&&i.jsx(Ut,{id:y,value:typeof m=="string"?m:"",placeholder:x.placeholder,error:g,onChange:v=>h(x.id,v.target.value)}),x.type==="textarea"&&i.jsx(Xs,{id:y,rows:3,value:typeof m=="string"?m:"",placeholder:x.placeholder,error:g,onChange:v=>h(x.id,v.target.value)}),x.type==="select"&&i.jsxs(pn,{id:y,value:typeof m=="string"?m:"",error:g,onChange:v=>h(x.id,v.target.value),children:[!x.required&&x.default===""&&i.jsx("option",{value:"",children:"—"}),x.required&&i.jsx("option",{value:"",children:"请选择"}),(x.options??[]).map(v=>i.jsx("option",{value:v.value,children:v.label??v.value},v.value))]}),x.type==="multiselect"&&i.jsx("div",{role:"group","aria-labelledby":`${y}-label`,className:"flex flex-wrap gap-2",id:y,children:(x.options??[]).map(v=>{const b=Array.isArray(m)&&m.includes(v.value);return i.jsx(de,{type:"button",size:"sm",variant:b?"primary":"secondary","aria-pressed":b,"data-testid":`bundle-option-${x.id}-${v.value}`,onClick:()=>f(x.id,v.value),children:v.label??v.value},v.value)})}),x.help&&i.jsx(ec,{children:x.help}),g&&i.jsx("p",{className:"mt-1 text-xs text-red-400",role:"alert","data-testid":`bundle-missing-${x.id}`,children:x.type==="multiselect"?"请至少选一个":"这一项必填"})]},x.id)}),s&&i.jsx(tt,{variant:"error",size:"sm",children:s}),i.jsx(de,{type:"submit",fullWidth:!0,loading:n,"data-testid":"bundle-deploy",children:e})]})},IA={LIST:"/api/bundles",detail:t=>`/api/bundles/${encodeURIComponent(t)}`,APPLY:"/api/bundles/apply",job:t=>`/api/bundles/apply/${encodeURIComponent(t)}`},ERe=1500,ARe={queued:"等待",running:"进行中",done:"完成",failed:"出错",pending:"稍后自动完成",skipped:"跳过"},TRe={"crewly-agent":"Crewly Agent(DeepSeek)","claude-code":"Claude Code","codex-cli":"Codex","gemini-cli":"Gemini CLI","opencode-cli":"OpenCode"},MRe={entry:"入门(2 核 4 GB)",standard:"标准(4 核 8 GB)",advanced:"进阶(8 核 16 GB)"};class f_ extends Error{constructor(e,n=null,s=[],r=[]){super(e),this.code=n,this.missing=s,this.invalid=r,this.name="BundleRequestError"}}async function PA(t,e){var s;let n;try{n=(await t()).data}catch(r){if(U1(r)){const a=((s=r.response)==null?void 0:s.data)??{};throw new f_(a.error||r.message||e,a.code??null,a.missing??[],a.invalid??[])}throw r instanceof Error?r:new f_(e)}if(!(n!=null&&n.success)||n.data===void 0||n.data===null)throw new f_((n==null?void 0:n.error)||e);return n.data}class NRe{async getBundle(e){return PA(()=>Ge.get(IA.detail(e)),"无法读取这个方案")}async apply(e,n,s){return(await PA(()=>Ge.post(IA.APPLY,{templateId:e,answers:n,...s?{runtime:s}:{}}),"部署失败")).deployment}async getJob(e){return PA(()=>Ge.get(IA.job(e)),"无法读取部署进度")}}const Mb=new NRe,jRe=({status:t})=>t==="done"?i.jsx(ia,{className:"h-4 w-4 shrink-0 text-emerald-400","aria-hidden":!0}):t==="failed"?i.jsx(ul,{className:"h-4 w-4 shrink-0 text-red-400","aria-hidden":!0}):t==="running"?i.jsx(FT,{className:"h-4 w-4 shrink-0 animate-spin text-primary","aria-hidden":!0}):t==="pending"?i.jsx(ps,{className:"h-4 w-4 shrink-0 text-amber-400","aria-hidden":!0}):i.jsx(_p,{className:"h-4 w-4 shrink-0 text-text-secondary-dark","aria-hidden":!0}),RRe=({templateId:t,onBack:e,onDone:n,pollIntervalMs:s=ERe})=>{const[r,a]=w.useState(null),[o,l]=w.useState(null),[c,d]=w.useState(null),[u,h]=w.useState(!1),[f,p]=w.useState(null),[x,y]=w.useState([]),m=w.useRef(null),g=w.useCallback(async()=>{l(null);try{const k=await Mb.getBundle(t);a(k.bundle),k.deployment&&d(k.deployment)}catch(k){l(k instanceof Error?k.message:String(k))}},[t]);w.useEffect(()=>{g()},[g]),w.useEffect(()=>{if(!(!c||a5(c)))return m.current=setTimeout(()=>{Mb.getJob(c.jobId).then(d).catch(k=>p(k instanceof Error?k.message:String(k)))},s),()=>{m.current&&clearTimeout(m.current)}},[c,s]);const v=async k=>{h(!0),p(null),y([]);try{d(await Mb.apply(t,k))}catch(E){E instanceof f_&&y([...E.missing,...E.invalid].map(N=>N.id)),p(E instanceof Error?E.message:String(E))}finally{h(!1)}},b=async()=>{h(!0),p(null);try{d(await Mb.apply(t,{}))}catch(k){p(k instanceof Error?k.message:String(k))}finally{h(!1)}},S=()=>{const k=(c==null?void 0:c.teams[0])??null;n({starterId:t,teamId:(k==null?void 0:k.teamId)??null,teamName:(k==null?void 0:k.name)??null,suggestions:[],bundle:!0})};if(o)return i.jsx(tt,{variant:"error",title:"无法读取这个方案",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:o}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:()=>void g(),children:"重试"}),i.jsx(de,{type:"button",size:"sm",variant:"ghost",icon:Hr,onClick:e,children:"换一个"})]})]})});if(!r)return i.jsx(Ht,{centered:!0,text:"正在读取方案…"});if(c){const k=a5(c),E=c.steps.some(T=>T.status==="failed"),N=c.connectors.filter(T=>T.status!=="connected");return i.jsxs("div",{className:"space-y-4","data-testid":"bundle-progress",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:k?`「${r.label}」已部署。`:`正在部署「${r.label}」…`}),i.jsx("ul",{className:"space-y-2",children:c.steps.map(T=>i.jsxs("li",{className:"flex items-start gap-2 text-sm","data-testid":`bundle-step-${T.id}`,children:[i.jsx(jRe,{status:T.status}),i.jsxs("div",{className:"min-w-0",children:[i.jsx("span",{className:"text-text-primary-dark",children:T.label})," ",i.jsxs("span",{className:"text-xs text-text-secondary-dark",children:["· ",ARe[T.status]]}),(T.error??T.message)&&i.jsx("p",{className:"text-xs text-text-secondary-dark",children:T.error??T.message})]})]},T.id))}),N.length>0&&i.jsx(tt,{variant:"info",size:"sm",title:"还要连上这些服务(手机上也能点)",children:i.jsx("ul",{className:"space-y-1","data-testid":"bundle-connect-list",children:N.map(T=>i.jsxs("li",{children:[i.jsxs("a",{className:"text-primary underline",href:T.connectPath,children:[T.id,T.products.length>0?`(${T.products.join("、")})`:""]}),T.required?"":"(可选)",":",T.why]},T.id))})}),f&&i.jsx(tt,{variant:"error",size:"sm",children:f}),k&&i.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row",children:[E&&i.jsx(de,{type:"button",variant:"secondary",icon:an,loading:u,onClick:()=>void b(),"data-testid":"bundle-retry",children:"重试出错的步骤"}),i.jsx(de,{type:"button",fullWidth:!0,onClick:S,"data-testid":"bundle-finish",children:"下一步"})]})]})}return i.jsxs("div",{className:"space-y-4","data-testid":"bundle-deploy-step",children:[i.jsxs("div",{children:[i.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[i.jsx("h3",{className:"font-semibold text-text-primary-dark",children:r.label}),i.jsx(ft,{variant:"primary",children:TRe[r.recommendedRuntime]??r.recommendedRuntime}),i.jsx(ft,{children:MRe[r.serverTier]??r.serverTier})]}),i.jsx("p",{className:"mt-2 whitespace-pre-line text-sm text-text-secondary-dark",children:r.ownerSummary}),r.ownerDoes.length>0&&i.jsxs("div",{className:"mt-2 text-sm text-text-secondary-dark",children:[i.jsx("p",{className:"font-medium text-text-primary-dark",children:"你需要做的:"}),i.jsx("ul",{className:"list-disc pl-5",children:r.ownerDoes.map(k=>i.jsx("li",{children:k},k))})]}),i.jsxs("p",{className:"mt-2 text-xs text-text-secondary-dark",children:["成员:",r.teams.flatMap(k=>k.members.map(E=>`${E.name}(${E.title})`)).join("、")]})]}),i.jsx(kRe,{questions:r.questions,submitLabel:`部署「${r.label}」`,submitting:u,error:f,serverProblems:x,onSubmit:k=>void v(k)}),i.jsx(de,{type:"button",variant:"ghost",icon:Hr,onClick:e,children:"换一个"})]})},IRe=({onDone:t})=>{const[e,n]=w.useState(null),[s,r]=w.useState(null),[a,o]=w.useState(null),[l,c]=w.useState(null),[d,u]=w.useState(!1),[h,f]=w.useState(null),p=async()=>{o(null);try{const m=await lc.getStarters();n(m),r(g=>{var v;return g??((v=m.find(b=>b.recommended)??m[0])==null?void 0:v.id)??null})}catch(m){o(m instanceof Error?m.message:String(m))}};w.useEffect(()=>{p()},[]);const x=async()=>{var g,v;const m=e==null?void 0:e.find(b=>b.id===s);if(m){if(m.kind==="bundle"){f(m.id);return}u(!0),c(null);try{const b=await lc.createStarterTeam(m.id);t({starterId:m.id,teamId:((g=b.team)==null?void 0:g.id)??null,teamName:((v=b.team)==null?void 0:v.name)??null,suggestions:m.suggestions})}catch(b){c(b instanceof Error?b.message:String(b))}finally{u(!1)}}};if(a)return i.jsx(tt,{variant:"error",title:"无法读取团队模板",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:a}),i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:()=>void p(),children:"重试"})]})});if(!e)return i.jsx(Ht,{centered:!0,text:"正在读取团队模板…"});if(h)return i.jsx(RRe,{templateId:h,onBack:()=>f(null),onDone:t});const y=e.find(m=>m.id===s)??null;return i.jsxs("div",{className:"space-y-3","data-testid":"starter-team-step",children:[i.jsx("div",{role:"radiogroup","aria-label":"第一个团队",className:"space-y-3",children:e.map(m=>{const g=m.id===s;return i.jsx(dt,{role:"radio","aria-checked":g,tabIndex:0,interactive:!0,padding:"md","data-testid":`starter-${m.id}`,className:g?"border-primary ring-1 ring-primary cursor-pointer":"cursor-pointer",onClick:()=>r(m.id),onKeyDown:v=>{(v.key==="Enter"||v.key===" ")&&(v.preventDefault(),r(m.id))},children:i.jsxs("div",{className:"flex items-start justify-between gap-3",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[i.jsx("span",{className:"font-semibold text-text-primary-dark",children:m.label}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:m.name}),m.recommended&&i.jsx(ft,{variant:"primary",children:"推荐"}),m.kind==="bundle"&&i.jsx(ft,{variant:"info",children:"成套方案"})]}),i.jsx("p",{className:"mt-1 text-sm text-text-secondary-dark",children:m.tagline}),m.members.length>0&&i.jsxs("p",{className:"mt-2 flex items-center gap-1 text-xs text-text-secondary-dark",children:[i.jsx(as,{className:"h-3.5 w-3.5 shrink-0","aria-hidden":!0}),m.members.map(v=>v.name).join("、")]})]}),g&&i.jsx(Kn,{className:"h-5 w-5 shrink-0 text-primary","aria-hidden":!0})]})},m.id)})}),l&&i.jsx(tt,{variant:"error",size:"sm",children:l}),i.jsx(de,{type:"button",fullWidth:!0,loading:d,disabled:!y,onClick:()=>void x(),"data-testid":"starter-create",children:(y==null?void 0:y.members.length)===0?"先只用 Orc":(y==null?void 0:y.kind)==="bundle"?`下一步:填写「${y.label}」的信息`:`创建「${(y==null?void 0:y.label)??""}」`})]})},PRe=4e3,LRe=({suggestions:t,teamId:e,teamName:n,onSent:s})=>{const[r,a]=w.useState(""),[o,l]=w.useState(!1),[c,d]=w.useState(null),[u,h]=w.useState(null),f=r.trim(),p=async()=>{if(f){l(!0),d(null);try{const x=await lc.sendFirstTask(f,e);h(x),s(x)}catch(x){d(x instanceof Error?x.message:String(x))}finally{l(!1)}}};return u?i.jsx(tt,{variant:"success",title:"已交给 Orc","data-testid":"first-task-sent",children:u.message?"等 Orc 上线就会开始处理。":"Orc 会安排团队去做,进展会在聊天和 Slack 里告诉你。"}):i.jsxs("div",{className:"space-y-3","data-testid":"first-task-step",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:[n?`交给「${n}」`:"交给 Orc",",一句话说清楚就行。"]}),i.jsx(Xs,{"aria-label":"第一件事",rows:4,maxLength:PRe,placeholder:"例如:每天早上 8 点给我一份简报",value:r,onChange:x=>a(x.target.value)}),t.length>0&&i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"试试这些:"}),i.jsx("div",{className:"flex flex-col gap-2",children:t.map(x=>i.jsx(de,{type:"button",size:"sm",variant:"outline",className:"h-auto min-h-9 justify-start whitespace-normal py-2 text-left font-normal",onClick:()=>a(x),children:x},x))})]}),c&&i.jsx(tt,{variant:"error",size:"sm",children:c}),i.jsx(de,{type:"button",fullWidth:!0,icon:g0,loading:o,disabled:!f,onClick:()=>void p(),"data-testid":"first-task-send",children:"派出去"})]})};async function LA(t,e){var s;let n;try{n=(await t()).data}catch(r){if(U1(r)){const a=(s=r.response)==null?void 0:s.data;throw new Error((a==null?void 0:a.error)||(a==null?void 0:a.message)||r.message||e)}throw r instanceof Error?r:new Error(e)}if(!(n!=null&&n.success)||!n.data)throw new Error((n==null?void 0:n.error)||(n==null?void 0:n.message)||e);return n.data}class DRe{async start(e){return LA(()=>Ge.post(Sk.START,e?{deviceName:e}:{}),"Could not reach Crewly Cloud")}async status(){return LA(()=>Ge.get(Sk.STATUS),"Could not read pairing status")}async cancel(){return LA(()=>Ge.post(Sk.CANCEL),"Could not cancel")}}const DA=new DRe,ORe={start:"用手机连接 Crewly Cloud",intro:"不用在这台电脑前:用手机扫码或打开链接,登录后点「批准」,这台电脑会自己连上。",scan:"用手机扫码,或打开:",code:"核对这个代码",waiting:"等待你在手机上批准…",cancel:"取消",connected:t=>`已连接 Crewly Cloud${t?`(${t})`:""}`,expired:"链接已过期,重新生成一个。",denied:"在 crewlyai.com 上被拒绝了。",cancelled:"已取消。",retry:"重新生成"},BRe={start:"Connect with your phone",intro:"No need to be at this machine: scan the code or open the link on your phone, sign in and tap Approve. This machine connects by itself.",scan:"Scan with your phone, or open:",code:"Check the code matches",waiting:"Waiting for you to approve on your phone…",cancel:"Cancel",connected:t=>`Connected to Crewly Cloud${t?` (${t})`:""}`,expired:"The link expired. Get a new one.",denied:"The request was denied on crewlyai.com.",cancelled:"Cancelled.",retry:"Get a new link"},FRe=({labels:t=BRe,autoStart:e=!1,onConnected:n})=>{const[s,r]=w.useState(null),[a,o]=w.useState(null),[l,c]=w.useState(!1),d=w.useRef(!1),u=w.useCallback(async()=>{c(!0),o(null);try{r(await DA.start())}catch(y){o(y instanceof Error?y.message:String(y))}finally{c(!1)}},[]);w.useEffect(()=>{e&&u()},[e,u]);const h=(s==null?void 0:s.state)==="pending";w.useEffect(()=>{if(!h)return;const y=setInterval(()=>{DA.status().then(r).catch(()=>{})},Ste);return()=>clearInterval(y)},[h]),w.useEffect(()=>{(s==null?void 0:s.state)==="connected"&&!d.current&&(d.current=!0,n==null||n(s.tier))},[s,n]);const f=async()=>{try{r(await DA.cancel())}catch(y){o(y instanceof Error?y.message:String(y))}};if((s==null?void 0:s.state)==="connected")return i.jsx(tt,{variant:"success",icon:ia,title:t.connected(s.tier),"data-testid":"cloud-pairing-connected",children:s.email??""});if((s==null?void 0:s.state)==="pending"&&s.verificationUrl)return i.jsxs("div",{className:"space-y-4","data-testid":"cloud-pairing-pending",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:t.intro}),i.jsxs("div",{className:"flex flex-col items-center gap-3 rounded-2xl border border-border-dark p-4",children:[i.jsx("div",{className:"rounded-xl bg-white p-2","data-testid":"cloud-pairing-qr",children:i.jsx(I1,{value:s.verificationUrl,size:wte,level:"M"})}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:t.scan}),i.jsxs("a",{href:s.verificationUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-flex max-w-full items-center gap-1 break-all text-sm text-primary underline","data-testid":"cloud-pairing-link",children:[s.verificationUrl," ",i.jsx(ws,{className:"h-3 w-3 shrink-0","aria-hidden":!0})]}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:t.code}),i.jsx("p",{className:"font-mono text-2xl font-bold tracking-widest text-text-primary-dark","data-testid":"cloud-pairing-code",children:s.userCode})]}),i.jsxs("div",{className:"flex items-center justify-between gap-3",children:[i.jsxs("span",{className:"flex items-center gap-2 text-sm text-text-secondary-dark","data-testid":"cloud-pairing-waiting",children:[i.jsx(Ht,{size:"xs",centered:!1}),t.waiting]}),i.jsx(de,{type:"button",variant:"ghost",size:"sm",onClick:()=>void f(),"data-testid":"cloud-pairing-cancel",children:t.cancel})]})]});const p={expired:t.expired,denied:t.denied,cancelled:t.cancelled},x=s?p[s.state]??(s.state==="error"?s.error:void 0):void 0;return i.jsxs("div",{className:"space-y-3","data-testid":"cloud-pairing-idle",children:[(a||x)&&i.jsx(tt,{variant:a||(s==null?void 0:s.state)==="error"||(s==null?void 0:s.state)==="denied"?"error":"warning",size:"sm",children:a??x}),i.jsx(de,{type:"button",fullWidth:!0,icon:Hz,loading:l,onClick:()=>void u(),"data-testid":"cloud-pairing-start",children:s||a?t.retry:t.start})]})},URe=({connected:t,tier:e,tokenPageSignInUrl:n,onConnected:s,navigateTo:r=a=>window.location.assign(a)})=>{const[a,o]=w.useState(!1),[l,c]=w.useState(""),[d,u]=w.useState(""),[h,f]=w.useState(!1),[p,x]=w.useState(null);if(t)return i.jsxs(tt,{variant:"success",icon:ia,title:"已连接 Crewly Cloud","data-testid":"cloud-connected",children:[e?`当前套餐:${e}。`:"","可以在手机上用 Crewly 了。"]});const y=async()=>{f(!0),x(null);try{await lc.connectCloud(l.trim(),d.trim()||void 0),c(""),u(""),s()}catch(m){x(m instanceof Error?m.message:String(m))}finally{f(!1)}};return i.jsxs("div",{className:"space-y-4","data-testid":"cloud-connect-step",children:[i.jsxs("ul",{className:"space-y-1 text-sm text-text-secondary-dark",children:[i.jsx("li",{children:"· 在手机上随时查看和指挥团队"}),i.jsx("li",{children:"· 自动备份,换电脑也能恢复"}),i.jsx("li",{children:"· 连接 Slack 需要先连 Cloud"})]}),i.jsx(FRe,{autoStart:!0,labels:ORe,onConnected:()=>s()}),i.jsxs("div",{className:"space-y-1 border-t border-border-dark pt-3",children:[i.jsx(de,{type:"button",variant:"secondary",fullWidth:!0,icon:eh,onClick:()=>r(Tte(window.location.origin,V2("cloud"))),"data-testid":"cloud-sign-in",children:"或者:在这个浏览器里用 Google 登录"}),i.jsx("p",{className:"text-xs text-text-secondary-dark",children:"登录后会自动回到这一页。"})]}),a?i.jsxs("div",{className:"space-y-3 rounded-2xl border border-border-dark p-3","data-testid":"cloud-paste",children:[i.jsxs("p",{className:"text-sm text-text-secondary-dark",children:["1. 打开"," ",i.jsxs("a",{href:n,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary underline",children:["Crewly Cloud 登录页 ",i.jsx(ws,{className:"h-3 w-3","aria-hidden":!0})]}),",登录后会显示两段 token。"]}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"2. 分别复制过来:"}),i.jsxs("div",{className:"space-y-1",children:[i.jsx(bt,{htmlFor:"cloud-token",children:"Token"}),i.jsx(Ut,{id:"cloud-token",autoComplete:"off",spellCheck:!1,value:l,onChange:m=>c(m.target.value)})]}),i.jsxs("div",{className:"space-y-1",children:[i.jsx(bt,{htmlFor:"cloud-refresh-token",children:"Refresh token(保持长期登录)"}),i.jsx(Ut,{id:"cloud-refresh-token",autoComplete:"off",spellCheck:!1,value:d,onChange:m=>u(m.target.value)})]}),!d.trim()&&l.trim()&&i.jsx("p",{className:"text-xs text-yellow-400",children:"没有 refresh token 的话,大约一小时后需要重新登录。"}),p&&i.jsx(tt,{variant:"error",size:"sm",children:p}),i.jsx(de,{type:"button",fullWidth:!0,loading:h,disabled:!l.trim(),onClick:()=>void y(),"data-testid":"cloud-paste-save",children:"连接"})]}):i.jsx(de,{type:"button",variant:"link",onClick:()=>o(!0),"data-testid":"cloud-show-paste",children:"没有自动回来?改用复制粘贴"})]})},zRe="/connections?platform=slack",HRe=({connected:t,cloudConnected:e,onGoToCloud:n,onConnected:s,navigateTo:r=a=>window.location.assign(a)})=>{const[a,o]=w.useState(!1),[l,c]=w.useState(null),d=w.useRef(!1);if(w.useEffect(()=>{t||!e||d.current||(d.current=!0,lc.refreshSlack().then(h=>{h.connected&&s()}).catch(()=>{}))},[t,e,s]),t)return i.jsx(tt,{variant:"success",icon:ia,title:"已连接 Slack","data-testid":"slack-connected",children:"在 Slack 里私信 Crewly 或在团队频道 @ 它就行。"});if(!e)return i.jsxs("div",{className:"space-y-3","data-testid":"slack-needs-cloud",children:[i.jsx(tt,{variant:"info",size:"sm",children:"Slack 通过 Crewly Cloud 安装,请先连接 Crewly Cloud。"}),i.jsx(de,{type:"button",variant:"secondary",fullWidth:!0,onClick:n,children:"去连接 Crewly Cloud"})]});const u=async()=>{o(!0),c(null);try{const h=await lc.getSlackInstallUrl(`${window.location.origin}${V2("slack")}`);r(h)}catch(h){c(h instanceof Error?h.message:String(h)),o(!1)}};return i.jsxs("div",{className:"space-y-3","data-testid":"slack-connect-step",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"把 Crewly 装进你的 Slack 工作区,之后在 Slack 里就能派活、看进展。"}),l&&i.jsx(tt,{variant:"error",size:"sm",children:l}),i.jsx(de,{type:"button",fullWidth:!0,icon:Xp,loading:a,onClick:()=>void u(),"data-testid":"slack-install",children:"在 Slack 里安装 Crewly"}),i.jsxs("a",{href:zRe,className:"inline-flex items-center gap-1 text-xs text-primary underline",children:["更多 Slack 设置 ",i.jsx(ws,{className:"h-3 w-3","aria-hidden":!0})]})]})},GRe=["harness","team","first_task","cloud","slack"];function WRe(t){return typeof t=="string"&&GRe.includes(t)}function p_(t,e){return t==null?void 0:t.steps.find(n=>n.id===e)}const Zn={HARNESS:0,ORC:1,LOGIN:2,TEAM:3,TASK:4,CLOUD:5,SLACK:6,DONE:7},VRe={harness:Zn.HARNESS,team:Zn.TEAM,first_task:Zn.TASK,cloud:Zn.CLOUD,slack:Zn.SLACK};function $Re(t){return WRe(t)?VRe[t]:Zn.HARNESS}function o5(t,e){var r;const n=((r=p_(t,"team"))==null?void 0:r.detail.teams[0])??null,s=(n!=null&&n.templateId?e.find(a=>a.id===n.templateId):void 0)??e.find(a=>a.members.length===0)??e[0];return{teamId:(n==null?void 0:n.id)??null,teamName:(n==null?void 0:n.name)??null,suggestions:(s==null?void 0:s.suggestions)??[]}}const Vc=({title:t,subtitle:e})=>i.jsxs("div",{className:"mb-4",children:[i.jsx("h2",{className:"text-xl font-semibold text-text-primary-dark",children:t}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:e})]}),Nb=({onBack:t,onNext:e,nextLabel:n,primary:s})=>i.jsxs("div",{className:"mt-6 flex justify-between gap-3",children:[i.jsx(de,{type:"button",variant:"ghost",icon:Hr,onClick:t,children:"上一步"}),i.jsx(de,{type:"button",variant:s?"primary":"secondary",icon:rp,iconPosition:"right",onClick:e,children:n})]}),KRe=()=>{const t=ms(),[e]=xh(),{overview:n,loading:s,error:r,refresh:a,setOrcHarness:o,savingOrc:l,replaceHarness:c}=X9(),{checklist:d,loading:u,refresh:h}=A8(),[f,p]=w.useState(()=>$Re(e.get(k8))),[x,y]=w.useState(K2),[m,g]=w.useState(null),[v,b]=w.useState(null),[S,k]=w.useState(!1),E=e.get("error"),N=(n==null?void 0:n.harnesses)??[],T=N.some(P=>P.installed),A=N.find(P=>P.id===(n==null?void 0:n.orcHarness))??null;w.useEffect(()=>{if(f!==Zn.TASK||v||u)return;let P=!1;return lc.getStarters().then(B=>{P||b(o5(d,B))}).catch(()=>{P||b(o5(d,[]))}),()=>{P=!0}},[f,v,d,u]);const M=()=>{bRe(!0),t(T3,{replace:!0})},L=()=>{g(Rye(N,(n==null?void 0:n.orcHarness)??null,x)),p(Zn.ORC)},I=async()=>{m&&(m!==(n==null?void 0:n.orcHarness)&&!await o(m)||p(Zn.LOGIN))},F=P=>{b({teamId:P.teamId,teamName:P.teamName,suggestions:P.suggestions,bundle:P.bundle}),h(),p(Zn.TASK)},G=w.useCallback(()=>{h()},[h]),V=()=>u?i.jsx(Ht,{centered:!0}):i.jsx(tt,{variant:"error",size:"sm",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:"无法读取设置清单。"}),i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:G,children:"重试"})]})}),H=()=>s?i.jsx(Ht,{centered:!0,text:"正在检查编程助手…"}):i.jsx(tt,{variant:"error",title:"无法读取编程助手状态 / Couldn't load harness status",children:i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{children:r}),i.jsx(de,{type:"button",size:"sm",variant:"secondary",icon:an,onClick:()=>void a(),children:"重试 / Retry"})]})}),$=()=>{var P;if(f<=Zn.LOGIN&&!n)return H();switch(f){case Zn.HARNESS:return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"选择并安装编程助手",subtitle:"Crewly 的 AI 员工通过编程助手工作。推荐 Claude Code。Pick and install a coding harness."}),i.jsx(Y9,{harnesses:N,systemTools:(n==null?void 0:n.systemTools)??[],selectedId:x,onSelect:y,onInstallFinished:()=>void a()}),i.jsx("div",{className:"mt-6 flex justify-end",children:i.jsx(de,{type:"button",icon:rp,iconPosition:"right",disabled:!T,onClick:L,children:"下一步"})}),!T&&i.jsx("p",{className:"mt-2 text-right text-xs text-text-secondary-dark",children:"安装至少一个后才能继续。Install at least one to continue."})]});case Zn.ORC:return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"Orc 用哪个编程助手?",subtitle:"The orchestrator (Orc) coordinates your team. Choose its harness."}),i.jsx(J9,{harnesses:N,value:m,onChange:g,disabled:l}),r&&i.jsx(tt,{variant:"error",size:"sm",className:"mt-3",children:r}),i.jsxs("div",{className:"mt-6 flex justify-between gap-3",children:[i.jsx(de,{type:"button",variant:"ghost",icon:Hr,onClick:()=>p(Zn.HARNESS),children:"上一步"}),i.jsx(de,{type:"button",icon:rp,iconPosition:"right",loading:l,disabled:!m,onClick:()=>void I(),children:"下一步"})]})]});case Zn.LOGIN:{const B=(A==null?void 0:A.loginState)==="logged_in";return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"登录",subtitle:"Sign in so the orchestrator can work."}),A?i.jsx(Q9,{harness:A,onLoggedIn:()=>void a(),onHarnessUpdated:c}):i.jsx(tt,{variant:"warning",size:"sm",children:"请先回到上一步选择 Orc 的编程助手。"}),i.jsxs("div",{className:"mt-6 flex justify-between gap-3",children:[i.jsx(de,{type:"button",variant:"ghost",icon:Hr,onClick:()=>p(Zn.ORC),children:"上一步"}),i.jsx(de,{type:"button",variant:B?"primary":"secondary",icon:rp,iconPosition:"right",onClick:()=>p(Zn.TEAM),children:B?"下一步":"稍后登录"})]})]})}case Zn.TEAM:{const B=((P=p_(d,"team"))==null?void 0:P.detail.teams)??[];return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"建第一个团队",subtitle:"Pick a starter team. You can add more later."}),B.length>0&&i.jsxs(tt,{variant:"success",size:"sm",className:"mb-3",children:["已有团队:",B.map(R=>R.name).join("、"),"。可以直接下一步,也可以再建一个。"]}),i.jsx(IRe,{onDone:F}),i.jsx(Nb,{onBack:()=>p(Zn.LOGIN),onNext:()=>p(Zn.TASK),nextLabel:"跳过",primary:!1})]})}case Zn.TASK:return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"派第一件事",subtitle:"Give your team its first task."}),(v==null?void 0:v.bundle)&&i.jsx(tt,{variant:"success",size:"sm",className:"mb-3","data-testid":"setup-bundle-first-week",children:"第一周的工作已经排好,团队会按天开始做。还想加一件事,也可以写在下面。"}),v?i.jsx(LRe,{suggestions:v.suggestions,teamId:v.teamId,teamName:v.teamName,onSent:()=>{k(!0),G()}}):i.jsx(Ht,{centered:!0}),i.jsx(Nb,{onBack:()=>p(Zn.TEAM),onNext:()=>p(Zn.CLOUD),nextLabel:S?"下一步":"跳过",primary:S})]});case Zn.CLOUD:{const B=p_(d,"cloud");return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"连接 Crewly Cloud",subtitle:"Manage Crewly from your phone; needed for Slack."}),E&&!(B!=null&&B.done)&&i.jsxs(tt,{variant:"warning",size:"sm",className:"mb-3",children:["登录没有完成(",E,"),可以再试一次或改用复制粘贴。"]}),B?i.jsx(URe,{connected:B.done,tier:B.detail.tier,tokenPageSignInUrl:B.detail.tokenPageSignInUrl,onConnected:G}):V(),i.jsx(Nb,{onBack:()=>p(Zn.TASK),onNext:()=>p(Zn.SLACK),nextLabel:B!=null&&B.done?"下一步":"跳过",primary:!!(B!=null&&B.done)})]})}case Zn.SLACK:{const B=p_(d,"slack");return i.jsxs(i.Fragment,{children:[i.jsx(Vc,{title:"连接 Slack",subtitle:"Talk to your team from Slack."}),B?i.jsx(HRe,{connected:B.done,cloudConnected:B.detail.cloudConnected,onGoToCloud:()=>p(Zn.CLOUD),onConnected:G}):V(),i.jsx(Nb,{onBack:()=>p(Zn.CLOUD),onNext:()=>p(Zn.DONE),nextLabel:B!=null&&B.done?"下一步":"跳过",primary:!!(B!=null&&B.done)})]})}default:{const B=A?V1[A.loginState]:null;return i.jsxs("div",{className:"space-y-4","data-testid":"setup-done",children:[i.jsxs("div",{className:"text-center",children:[i.jsx(ia,{className:"mx-auto h-12 w-12 text-emerald-400"}),i.jsx(Vc,{title:"设置完成",subtitle:"You're ready to use Crewly."})]}),A&&B&&i.jsxs("p",{className:"text-center text-sm text-text-secondary-dark",children:["Orc 使用 ",i.jsx("span",{className:"font-semibold text-text-primary-dark",children:A.displayName})," ",i.jsx(ft,{variant:B.variant,children:B.label})]}),d&&i.jsx("ul",{className:"space-y-2","data-testid":"setup-done-checklist",children:d.steps.map(R=>i.jsxs("li",{className:"flex items-center gap-2 text-sm",children:[R.done?i.jsx(ia,{className:"h-4 w-4 text-emerald-400","aria-label":"已完成"}):i.jsx(_p,{className:"h-4 w-4 text-text-secondary-dark","aria-label":"未完成"}),i.jsx("span",{className:R.done?"text-text-primary-dark":"text-text-secondary-dark",children:cM[R.id]})]},R.id))}),i.jsx("p",{className:"text-center text-xs text-text-secondary-dark",children:"没做完的步骤会留在首页的「开始使用」里;登录过期时,可在「设置 → Harness」里重新登录。"}),i.jsx("div",{className:"text-center",children:i.jsx(de,{type:"button",size:"default",onClick:()=>t(T3,{replace:!0}),children:"进入 Crewly"})})]})}}};return i.jsx(bY,{className:"min-h-screen px-4 py-6 sm:py-10",children:i.jsxs("div",{className:"mx-auto w-full max-w-2xl",children:[i.jsxs("header",{className:"mb-6 flex items-center justify-between gap-3",children:[i.jsxs("div",{children:[i.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Crewly 初始设置"}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"First-run setup"})]}),f!==Zn.DONE&&i.jsx(de,{type:"button",variant:"link",onClick:M,"data-testid":"setup-skip",children:"稍后再说 / Skip for now"})]}),i.jsxs("p",{className:"mb-4 text-sm text-text-secondary-dark sm:hidden","data-testid":"setup-step-counter",children:["第 ",f+1,"/",wk.length," 步 · ",wk[f]]}),i.jsx("div",{className:"mb-6 hidden overflow-x-auto sm:block",children:i.jsx(SRe,{steps:[...wk],currentStep:f})}),i.jsx(dt,{padding:"none",className:"p-4 sm:p-6",children:$()})]})})};function qRe(){const{id:t}=gh();return i.jsx(Gb,{to:`/tasks/${t??""}`,replace:!0})}function XRe(){return i.jsx(EQ,{children:i.jsx(mte,{children:i.jsx(BQ,{children:i.jsxs(vY,{children:[i.jsx(mRe,{}),i.jsx(yRe,{}),i.jsxs(NX,{children:[i.jsx(_Re,{}),i.jsxs(_X,{children:[i.jsx(Mn,{path:"/auth/callback",element:i.jsx(k2e,{})}),i.jsx(Mn,{path:"/auth",element:i.jsx(A2e,{})}),i.jsx(Mn,{path:"/setup",element:i.jsx(KRe,{})}),i.jsxs(Mn,{path:"/",element:i.jsx(xte,{}),children:[i.jsx(Mn,{index:!0,element:i.jsx(Lte,{})}),i.jsx(Mn,{path:"projects",element:i.jsx(Bte,{})}),i.jsx(Mn,{path:"projects/:id",element:i.jsx(jne,{})}),i.jsx(Mn,{path:"teams",element:i.jsx(ese,{})}),i.jsx(Mn,{path:"teams/:id",element:i.jsx(Bse,{})}),i.jsx(Mn,{path:"assignments",element:i.jsx(Vse,{})}),i.jsx(Mn,{path:"scheduled-checkins",element:i.jsx(Zse,{})}),i.jsx(Mn,{path:"triggers",element:i.jsx(dre,{})}),i.jsx(Mn,{path:"factory",element:i.jsx(H0e,{})}),i.jsx(Mn,{path:"connections",element:i.jsx(y_e,{})}),i.jsx(Mn,{path:"browser",element:i.jsx(T_e,{})}),i.jsx(Mn,{path:"marketplace",element:i.jsx(z_e,{})}),i.jsx(Mn,{path:"marketplace/:id",element:i.jsx(W_e,{})}),i.jsx(Mn,{path:"wiki",element:i.jsx(NNe,{})}),i.jsx(Mn,{path:"security",element:i.jsx(lV,{})}),i.jsx(Mn,{path:"monitoring/costs",element:i.jsx(KF,{})}),i.jsx(Mn,{path:"usage",element:i.jsx(KF,{})}),i.jsx(Mn,{path:"settings",element:i.jsx(Wye,{})}),i.jsx(Mn,{path:"pricing",element:i.jsx(N2e,{})}),i.jsx(Mn,{path:"cloud",element:i.jsx(q2e,{})}),i.jsx(Mn,{path:"tasks",element:i.jsx(dRe,{})}),i.jsx(Mn,{path:"tasks/:id",element:i.jsx(wV,{})}),i.jsx(Mn,{path:"requests",element:i.jsx(Gb,{to:"/tasks",replace:!0})}),i.jsx(Mn,{path:"requests/:id",element:i.jsx(qRe,{})}),i.jsx(Mn,{path:"missions",element:i.jsx(uV,{})}),i.jsx(Mn,{path:"missions/:id",element:i.jsx(fV,{})}),i.jsx(Mn,{path:"tickets",element:i.jsx(Bje,{})}),i.jsx(Mn,{path:"workitems",element:i.jsx(_V,{})}),i.jsx(Mn,{path:"workitems/:id",element:i.jsx(SV,{})}),i.jsx(Mn,{path:"team-chat",element:i.jsx(vbe,{})}),i.jsx(Mn,{path:"chat",element:i.jsx(Gb,{to:"/team-chat",replace:!0})}),i.jsx(Mn,{path:"agents",element:i.jsx(Gb,{to:"/team-chat",replace:!0})})]})]})]})]})})})})}Wee();OA.createRoot(document.getElementById("root")).render(i.jsx(jn.StrictMode,{children:i.jsx(XRe,{})}));
4963
- //# sourceMappingURL=index-2c7ee4a6.js.map
4963
+ //# sourceMappingURL=index-b4d5575e.js.map