crewly 1.20.6 → 1.20.8
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.
- package/dist/backend/backend/src/constants.d.ts +16 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +16 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts +117 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +239 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js +4 -0
- package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +21 -4
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +16 -0
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +4 -1
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +2 -0
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +16 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +16 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts +117 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +239 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js +4 -0
- package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +16 -0
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.js +4 -1
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/cli/backend/src/types/slack.types.d.ts +2 -0
- package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
- package/frontend/dist/assets/{index-26f03bbd.js → index-f761b08d.js} +2 -2
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -4907,7 +4907,7 @@ vTroikaGlyphColor = uTroikaUseGlyphColors ? aTroikaGlyphColor / 255.0 : diffuse;
|
|
|
4907
4907
|
|
|
4908
4908
|
You are a...`,className:"font-mono text-sm"}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Markdown supported. This prompt defines the agent's behavior."})]})]}),i.jsxs("div",{className:"p-6 space-y-4",children:[i.jsx("h3",{className:"text-sm font-semibold text-text-secondary-dark uppercase tracking-wide",children:"Assigned Skills"}),i.jsxs("div",{className:"space-y-2",children:[a==null?void 0:a.map(b=>i.jsxs("label",{className:`flex items-start gap-3 p-3 bg-background-dark border border-border-dark rounded-lg cursor-pointer hover:border-primary/50 transition-colors ${o.assignedSkills.includes(b.id)?"border-primary/50 bg-primary/5":""}`,children:[i.jsx(os,{size:"sm",checked:o.assignedSkills.includes(b.id),onChange:()=>m(b.id)}),i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsx("span",{className:"text-sm font-medium text-text-primary-dark block",children:b.name}),i.jsx("span",{className:"text-xs text-text-secondary-dark block mt-0.5",children:b.description})]}),o.assignedSkills.includes(b.id)&&i.jsx(br,{className:"w-4 h-4 text-primary flex-shrink-0"})]},b.id)),(!a||a.length===0)&&i.jsx("p",{className:"text-sm text-text-secondary-dark text-center py-6",children:"No skills available. Create skills in the Skills tab."})]})]})]}),i.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-dark bg-background-dark sticky bottom-0",children:[i.jsx(ze,{variant:"secondary",onClick:e,type:"button",children:"Cancel"}),i.jsx(ze,{type:"submit",onClick:g,disabled:c,loading:c,children:c?"Saving...":f?"Create Role":"Save Changes"})]})]})})},hme={development:"bg-blue-500/15 text-blue-400",management:"bg-amber-500/15 text-amber-400",quality:"bg-emerald-500/15 text-emerald-400",design:"bg-pink-500/15 text-pink-400",sales:"bg-primary/15 text-primary",support:"bg-cyan-500/15 text-cyan-400",automation:"bg-orange-500/15 text-orange-400"},fme=[{value:"",label:"All Categories"},{value:"development",label:"Development"},{value:"management",label:"Management"},{value:"quality",label:"Quality"},{value:"design",label:"Design"},{value:"sales",label:"Sales"},{value:"support",label:"Support"},{value:"automation",label:"Automation"}],pme=()=>{const{roles:t,isLoading:e,error:n,createRole:r,updateRole:s,deleteRole:a,refreshFromDisk:o}=R6(),[l,c]=k.useState(null),[d,u]=k.useState(!1),[h,f]=k.useState(!1),[p,x]=k.useState(""),[y,m]=k.useState(""),[g,v]=k.useState(!1),b=k.useMemo(()=>t?t.filter(A=>{if(y&&A.category!==y)return!1;if(p){const M=p.toLowerCase();return A.displayName.toLowerCase().includes(M)||A.description.toLowerCase().includes(M)||A.category.toLowerCase().includes(M)}return!0}):[],[t,p,y]),S=()=>{c(null),f(!0),u(!0)},C=A=>{c(A),f(!1),u(!0)},E=async(A,M)=>{if(M){window.alert("Built-in roles cannot be deleted");return}window.confirm("Are you sure you want to delete this role?")&&await a(A)},N=()=>{u(!1),c(null),f(!1)},T=async()=>{v(!0);try{await o()}finally{v(!1)}};return i.jsxs("div",{className:"space-y-6",children:[i.jsxs("div",{className:"flex flex-col md:flex-row items-start md:items-center justify-between gap-4",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Roles Management"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Create and manage AI agent roles"})]}),i.jsx(ze,{onClick:S,icon:vr,children:"New Role"})]}),i.jsxs("div",{className:"flex flex-col md:flex-row items-end gap-4",children:[i.jsxs("div",{className:"flex-1 w-full md:w-auto",children:[i.jsx(Tt,{htmlFor:"category-filter",children:"Category"}),i.jsx(dr,{id:"category-filter",value:y,onChange:A=>m(A.target.value),children:fme.map(A=>i.jsx("option",{value:A.value,children:A.label},A.value))})]}),i.jsxs("div",{className:"flex-1 w-full md:w-auto",children:[i.jsx(Tt,{htmlFor:"search-filter",children:"Search"}),i.jsx(on,{id:"search-filter",type:"text",placeholder:"Search roles...",value:p,onChange:A=>x(A.target.value)})]}),i.jsx(ze,{variant:"secondary",onClick:T,disabled:e||g,icon:zn,className:g?"animate-spin":"",children:g?"Refreshing...":"Refresh"})]}),n&&i.jsx(Bt,{variant:"error",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{children:["Error: ",n]}),i.jsx(ze,{variant:"outline",size:"sm",onClick:T,children:"Retry"})]})}),e&&b.length===0&&i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{text:"Loading roles..."})}),!e&&b.length===0&&!n&&i.jsxs("div",{className:"text-center py-16",children:[i.jsx("div",{className:"flex justify-center mb-4",children:i.jsx(Ku,{className:"w-12 h-12 text-text-secondary-dark"})}),i.jsx("h3",{className:"text-lg font-semibold mb-2",children:"No Roles Found"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-6",children:p||y?"Try adjusting your filters":"Create your first role to get started"}),!p&&!y&&i.jsx(ze,{onClick:S,icon:vr,children:"Create Role"})]}),b.length>0&&i.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",children:b.map(A=>i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-lg p-4 hover:border-primary/50 transition-colors flex flex-col",children:[i.jsxs("div",{className:"flex items-start justify-between gap-2 mb-3",children:[i.jsx("h3",{className:"font-medium text-text-primary-dark",children:A.displayName}),i.jsx("span",{className:`text-xs font-medium px-2 py-0.5 rounded-full ${hme[A.category]}`,children:TM[A.category]})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark flex-grow mb-3 line-clamp-2",children:A.description}),i.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[i.jsxs("span",{className:"text-xs text-text-secondary-dark",children:[A.skillCount," skills assigned"]}),A.isDefault&&i.jsx("span",{className:"text-xs font-medium px-2 py-0.5 rounded-full bg-primary/15 text-primary",children:"Default"})]}),i.jsxs("div",{className:"flex items-center justify-between pt-3 border-t border-border-dark mt-auto",children:[A.isBuiltin&&i.jsx("span",{className:"text-xs text-text-secondary-dark italic",children:"Built-in"}),!A.isBuiltin&&i.jsx("span",{}),i.jsxs("div",{className:"flex gap-2 ml-auto",children:[i.jsx(ze,{variant:"secondary",size:"sm",onClick:()=>C(A.id),children:"Edit"}),!A.isBuiltin&&i.jsx(ze,{variant:"outline",size:"sm",onClick:()=>E(A.id,A.isBuiltin),className:"text-rose-400 hover:text-rose-300 hover:border-rose-400",icon:Vi,children:"Delete"})]})]})]},A.id))}),d&&i.jsx(ume,{roleId:h?null:l,onClose:N,onSave:async A=>{h?await r(A):l&&await s(l,A)}})]})},mme=()=>[{value:"",label:"All Categories"},...cQ.map(t=>({value:t,label:D6(t)}))],FH=mme(),gme={development:"bg-blue-500/15 text-blue-400",design:"bg-pink-500/15 text-pink-400",communication:"bg-emerald-500/15 text-emerald-400",research:"bg-primary/15 text-primary","content-creation":"bg-amber-500/15 text-amber-400",automation:"bg-primary/15 text-primary",analysis:"bg-cyan-500/15 text-cyan-400",integration:"bg-rose-500/15 text-rose-400",management:"bg-orange-500/15 text-orange-400",monitoring:"bg-teal-500/15 text-teal-400",memory:"bg-primary/15 text-primary",system:"bg-slate-500/15 text-slate-400","task-management":"bg-sky-500/15 text-sky-400",quality:"bg-lime-500/15 text-lime-400"},xme={"claude-skill":"bg-primary/15 text-primary","web-page":"bg-blue-500/15 text-blue-400"},yme=()=>{var R;const{settings:t,updateSettings:e}=XN(),[n,r]=k.useState(null),[s,a]=k.useState(!1),[o,l]=k.useState("idle");k.useEffect(()=>{t&&(r(t.skills),a(!1))},[t]);const c=(D,G)=>{n&&(r({...n,[D]:G}),a(!0),l("idle"))},d=(D,G)=>{n&&(r({...n,browserProfile:{...n.browserProfile,[D]:G}}),a(!0),l("idle"))},u=async()=>{if(n){l("saving");try{await e({skills:n}),l("saved"),a(!1),setTimeout(()=>l("idle"),2e3)}catch{l("error")}}},[h,f]=k.useState(""),[p,x]=k.useState(""),[y,m]=k.useState(!1),[g,v]=k.useState(null),[b,S]=k.useState(null),C=k.useMemo(()=>({category:h||void 0,search:p||void 0}),[h,p]),{skills:E,loading:N,error:T,refresh:A,create:M,update:P,remove:I,selectSkill:B,selectedSkill:V,clearSelection:K}=U1(C),H=k.useCallback(()=>{v(null),m(!0)},[]),$=k.useCallback(async D=>{v(D),await B(D.id),m(!0)},[B]),L=k.useCallback(async D=>{try{g!=null&&g.id?await P(g.id,D):await M(D),m(!1),v(null)}catch(G){console.error("Failed to save skill:",G)}},[g,P,M]),U=k.useCallback(async D=>{try{await I(D),S(null)}catch(G){console.error("Failed to delete skill:",G)}},[I]);return i.jsxs("div",{className:"space-y-6",children:[n&&i.jsxs(Ot,{padding:"lg",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[i.jsx(go,{className:"w-5 h-5 text-primary"}),i.jsx("h2",{className:"text-lg font-semibold",children:"Browser Automation"})]}),i.jsxs("div",{className:"space-y-5",children:[i.jsx(os,{id:"enableBrowserAutomation",label:"Enable Browser Automation",description:"Allow agents to use Playwright for browser tasks (navigate, click, screenshot, etc.)",checked:n.enableBrowserAutomation,onChange:D=>c("enableBrowserAutomation",D.target.checked)}),n.enableBrowserAutomation&&n.browserProfile&&i.jsxs("div",{className:"pl-4 border-l-2 border-border-dark space-y-4",children:[i.jsx(os,{id:"headless",label:"Headless Mode",description:"Run browser invisibly in the background (recommended)",checked:n.browserProfile.headless,onChange:D=>d("headless",D.target.checked)}),i.jsx(os,{id:"stealth",label:"Stealth Mode",description:"Use anti-detection features to avoid bot blocking (uses community fork)",checked:n.browserProfile.stealth,onChange:D=>d("stealth",D.target.checked)}),i.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"humanDelayMin",children:"Min Delay (ms)"}),i.jsx(on,{id:"humanDelayMin",type:"number",min:0,max:n.browserProfile.humanDelayMaxMs,value:n.browserProfile.humanDelayMinMs,onChange:D=>d("humanDelayMinMs",parseInt(D.target.value,10)||0)}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Minimum delay between actions"})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"humanDelayMax",children:"Max Delay (ms)"}),i.jsx(on,{id:"humanDelayMax",type:"number",min:n.browserProfile.humanDelayMinMs,max:1e4,value:n.browserProfile.humanDelayMaxMs,onChange:D=>d("humanDelayMaxMs",parseInt(D.target.value,10)||0)}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Maximum delay between actions"})]})]})]})]}),i.jsxs("div",{className:"flex items-center justify-end gap-3 mt-6 pt-4 border-t border-border-dark",children:[o==="saved"&&i.jsxs("span",{className:"text-sm text-emerald-400 flex items-center gap-1",children:[i.jsx(br,{className:"w-4 h-4"})," Saved"]}),o==="error"&&i.jsxs("span",{className:"text-sm text-rose-400 flex items-center gap-1",children:[i.jsx(Or,{className:"w-4 h-4"})," Save failed"]}),i.jsx(ze,{onClick:u,disabled:!s||o==="saving",icon:$c,size:"sm",children:o==="saving"?"Saving...":"Save"})]})]}),i.jsxs("div",{className:"flex flex-col md:flex-row items-start md:items-center justify-between gap-4",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Skills Management"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Create and manage AI agent skills"})]}),i.jsx(ze,{onClick:H,icon:vr,children:"New Skill"})]}),i.jsxs("div",{className:"flex flex-col md:flex-row items-end gap-4",children:[i.jsxs("div",{className:"flex-1 w-full md:w-auto",children:[i.jsx(Tt,{htmlFor:"category-filter",children:"Category"}),i.jsx(dr,{id:"category-filter",value:h,onChange:D=>f(D.target.value),children:FH.map(D=>i.jsx("option",{value:D.value,children:D.label},D.value))})]}),i.jsxs("div",{className:"flex-1 w-full md:w-auto",children:[i.jsx(Tt,{htmlFor:"search-filter",children:"Search"}),i.jsx(on,{id:"search-filter",type:"text",placeholder:"Search skills...",value:p,onChange:D=>x(D.target.value)})]}),i.jsx(ze,{variant:"secondary",onClick:A,disabled:N,icon:zn,className:N?"animate-spin":"",children:N?"Refreshing...":"Refresh"})]}),T&&i.jsx(Bt,{variant:"error",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{children:["Error: ",T]}),i.jsx(ze,{variant:"outline",size:"sm",onClick:A,children:"Retry"})]})}),N&&E.length===0&&i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{text:"Loading skills..."})}),!N&&E.length===0&&!T&&i.jsxs("div",{className:"text-center py-16",children:[i.jsx("div",{className:"flex justify-center mb-4",children:i.jsx(Mu,{className:"w-12 h-12 text-text-secondary-dark"})}),i.jsx("h3",{className:"text-lg font-semibold mb-2",children:"No Skills Found"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-6",children:p||h?"Try adjusting your filters":"Create your first skill to get started"}),!p&&!h&&i.jsx(ze,{onClick:H,icon:vr,children:"Create Skill"})]}),E.length>0&&i.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",children:E.map(D=>i.jsx(Sme,{skill:D,onEdit:()=>$(D),onDelete:()=>S(D.id)},D.id))}),y&&i.jsx(wme,{skill:V||g,onSave:L,onClose:()=>{m(!1),v(null),K()}}),b&&i.jsx(kme,{skillId:b,skillName:((R=E.find(D=>D.id===b))==null?void 0:R.name)||"",onConfirm:()=>U(b),onCancel:()=>S(null)})]})},vme=t=>{switch(t){case"claude-skill":return i.jsx(y3,{className:"w-3.5 h-3.5"});case"web-page":return i.jsx(vA,{className:"w-3.5 h-3.5"});default:return i.jsx(y3,{className:"w-3.5 h-3.5"})}},bme=t=>{switch(t){case"warning":return i.jsx(mp,{className:"w-4 h-4"});case"requirement":return i.jsx(Or,{className:"w-4 h-4"});case"info":default:return i.jsx(Tu,{className:"w-4 h-4"})}},_me={info:{bg:"bg-blue-500/10",border:"border-blue-500/20",icon:"text-blue-400"},warning:{bg:"bg-amber-500/10",border:"border-amber-500/20",icon:"text-amber-400"},requirement:{bg:"bg-rose-500/10",border:"border-rose-500/20",icon:"text-rose-400"}},Sme=({skill:t,onEdit:e,onDelete:n})=>{const r=t.skillType||"claude-skill";return i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-lg p-4 hover:border-primary/50 transition-colors flex flex-col",children:[i.jsxs("div",{className:"flex items-start justify-between gap-2 mb-3",children:[i.jsx("h3",{className:"font-medium text-text-primary-dark",children:t.name}),i.jsx("span",{className:`text-xs font-medium px-2 py-0.5 rounded-full ${gme[t.category]}`,children:D6(t.category)})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark flex-grow mb-3 line-clamp-2",children:t.description}),i.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[i.jsxs("span",{className:`inline-flex items-center gap-1 text-xs font-medium px-2 py-0.5 rounded ${xme[r]}`,children:[vme(r),i.jsx("span",{children:dQ(r)})]}),i.jsx("span",{className:`text-xs font-medium px-2 py-0.5 rounded-full ${t.isEnabled?"bg-emerald-500/10 text-emerald-400":"bg-gray-500/10 text-gray-400"}`,children:t.isEnabled?"Enabled":"Disabled"})]}),t.notices&&t.notices.length>0&&i.jsx("div",{className:"space-y-2 mb-3",children:t.notices.map((s,a)=>{const o=_me[s.type];return i.jsxs("div",{className:`flex gap-2 p-2 rounded ${o.bg} border ${o.border}`,children:[i.jsx("div",{className:`flex-shrink-0 ${o.icon}`,children:bme(s.type)}),i.jsxs("div",{className:"text-xs space-y-0.5",children:[i.jsx("span",{className:"font-medium text-text-primary-dark block",children:s.title}),i.jsx("span",{className:"text-text-secondary-dark block",children:s.message}),s.link&&i.jsxs("a",{href:s.link,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline inline-flex items-center gap-1",children:[s.linkText||"Learn more",i.jsx(Ps,{className:"w-3 h-3"})]})]})]},a)})}),i.jsxs("div",{className:"flex items-center justify-between pt-3 border-t border-border-dark mt-auto",children:[t.isBuiltin&&i.jsx("span",{className:"text-xs text-text-secondary-dark italic",children:"Built-in"}),i.jsxs("div",{className:"flex gap-1 ml-auto",children:[i.jsx($i,{icon:E1,onClick:e,variant:"ghost",size:"sm","aria-label":"Edit skill"}),!t.isBuiltin&&i.jsx($i,{icon:Vi,onClick:n,variant:"danger-ghost",size:"sm","aria-label":"Delete skill"})]})]})]})},wme=({skill:t,onSave:e,onClose:n})=>{const r=(t==null?void 0:t.isBuiltin)??!1,[s,a]=k.useState({name:(t==null?void 0:t.name)||"",displayName:(t==null?void 0:t.name)||"",description:(t==null?void 0:t.description)||"",category:(t==null?void 0:t.category)||"development",promptContent:(t==null?void 0:t.promptContent)||"",triggers:[],tags:[]}),[o,l]=k.useState(!1),[c,d]=k.useState(null),u=async f=>{if(f.preventDefault(),d(null),!s.displayName.trim()){d("Display Name is required");return}if(!s.name.trim()){d("ID is required");return}if(!s.description.trim()){d("Description is required");return}l(!0);try{await e(s)}catch(p){d(p instanceof Error?p.message:"Failed to save skill")}finally{l(!1)}},h=f=>{f.target===f.currentTarget&&n()};return i.jsx("div",{className:"fixed inset-0 bg-background-dark/80 backdrop-blur-sm flex items-center justify-center z-50",onClick:h,children:i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-xl shadow-lg w-full max-w-lg m-4 max-h-[90vh] overflow-hidden flex flex-col",onClick:f=>f.stopPropagation(),children:[i.jsxs("div",{className:"flex items-center justify-between p-6 border-b border-border-dark",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold text-text-primary-dark",children:t?"Edit Skill":"Create Skill"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:t?"Modify skill configuration":"Configure a new skill for your agents"})]}),i.jsx($i,{icon:On,onClick:n,variant:"ghost","aria-label":"Close"})]}),r&&t&&i.jsxs("div",{className:"mx-6 mt-4 bg-blue-500/10 border border-blue-500/30 text-blue-400 px-4 py-3 rounded-lg text-sm",children:[i.jsx("strong",{children:"Built-in Skill:"})," Changes will be saved as a user override. You can reset to defaults anytime."]}),c&&i.jsx("div",{className:"mx-6 mt-4",children:i.jsx(Bt,{variant:"error",children:c})}),i.jsxs("form",{onSubmit:u,className:"flex-1 overflow-y-auto p-6 space-y-4",children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"skill-display-name",required:!0,children:"Display Name"}),i.jsx(on,{id:"skill-display-name",type:"text",value:s.displayName,onChange:f=>a({...s,displayName:f.target.value}),placeholder:"Code Review",required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"skill-name",required:!0,children:"ID"}),i.jsx(on,{id:"skill-name",type:"text",value:s.name,onChange:f=>a({...s,name:f.target.value}),placeholder:"code-review",required:!0,disabled:!!t}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Lowercase letters, numbers, and hyphens only"})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"skill-description",required:!0,children:"Description"}),i.jsx(Ko,{id:"skill-description",value:s.description,onChange:f=>a({...s,description:f.target.value}),placeholder:"Describe what this skill does...",rows:3,required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"skill-category",children:"Category"}),i.jsx(dr,{id:"skill-category",value:s.category,onChange:f=>a({...s,category:f.target.value}),children:FH.filter(f=>f.value).map(f=>i.jsx("option",{value:f.value,children:f.label},f.value))})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"skill-prompt",children:"Instructions (Markdown)"}),i.jsx(Ko,{id:"skill-prompt",value:s.promptContent,onChange:f=>a({...s,promptContent:f.target.value}),placeholder:`# Skill Instructions
|
|
4909
4909
|
|
|
4910
|
-
Provide detailed instructions for this skill...`,rows:8,className:"font-mono text-sm"})]})]}),i.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-dark bg-background-dark",children:[i.jsx(ze,{variant:"secondary",onClick:n,type:"button",children:"Cancel"}),i.jsx(ze,{type:"submit",onClick:u,disabled:o,loading:o,children:o?"Saving...":"Save Skill"})]})]})})},kme=({skillName:t,onConfirm:e,onCancel:n})=>{const r=s=>{s.target===s.currentTarget&&n()};return i.jsx("div",{className:"fixed inset-0 bg-background-dark/80 backdrop-blur-sm flex items-center justify-center z-50",onClick:r,children:i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-xl shadow-lg w-full max-w-md m-4",onClick:s=>s.stopPropagation(),children:[i.jsx("div",{className:"p-6 border-b border-border-dark",children:i.jsx("h2",{className:"text-xl font-semibold text-text-primary-dark",children:"Delete Skill"})}),i.jsx("div",{className:"p-6",children:i.jsxs("p",{className:"text-text-secondary-dark",children:["Are you sure you want to delete ",i.jsx("strong",{className:"text-text-primary-dark",children:t}),"? This action cannot be undone."]})}),i.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-dark bg-background-dark rounded-b-xl",children:[i.jsx(ze,{variant:"secondary",onClick:n,children:"Cancel"}),i.jsx(ze,{variant:"danger",onClick:e,children:"Delete"})]})]})})};async function _v(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 Cme=()=>{const[t,e]=k.useState(null),[n,r]=k.useState(!0),[s,a]=k.useState(null),[o,l]=k.useState(""),[c,d]=k.useState({}),[u,h]=k.useState(null),f=k.useCallback(async()=>{try{a(null);const m=await fetch("/api/slack/team-channels"),g=await _v(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{r(!1)}},[]);k.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 _v(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 _v(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 _v(v),await f()}catch(v){a(v instanceof Error?v.message:"Failed to unlink channel")}finally{h(null)}};return i.jsxs(Ot,{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(ze,{variant:"ghost",size:"sm",onClick:f,icon:zn,"aria-label":"Reload team channels",children:"Reload"})]}),s&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{variant:"error",onClose:()=>a(null),children:s})}),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(os,{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(on,{id:"slack-team-channels-prefix",value:o,onChange:m=>l(m.target.value),placeholder:"e.g. crew-",className:"w-40"})]}),i.jsx(ze,{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(bA,{className:"inline w-3 h-3 -mt-0.5"}),m.mapping.slackChannelName," · ",m.mapping.autoCreated?"created by Crewly":"linked"]})]})]}),m.mapping?i.jsx(ze,{variant:"danger-ghost",size:"sm",icon:id,disabled:u===m.teamId,onClick:()=>y(m),children:"Unlink"}):i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(on,{"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(ze,{variant:"secondary",size:"sm",icon:Sl,disabled:u===m.teamId||!(c[m.teamId]??"").trim(),onClick:()=>x(m.teamId,(c[m.teamId]??"").trim()),children:"Link"}),i.jsx(ze,{variant:"primary",size:"sm",icon:bA,disabled:u===m.teamId,loading:u===m.teamId,onClick:()=>x(m.teamId),children:"Create channel"})]})]},m.teamId))})]}):null]})};async function Sv(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 Eme(t){const e=r=>r.toLowerCase().replace(/\s+/g,"-"),n={};for(const r of t)for(const s of r.members??[]){const a=s.sessionName||(s.id&&s.name&&r.name?`${e(r.name)}-${e(s.name)}-${s.id.substring(0,8)}`:"");a&&(n[a]={teamName:r.name??"Team",memberName:s.name??a})}return n}const Ame=({pendingInstalls:t=[]})=>{var K,H,$,L,U,R;const[e,n]=k.useState(null),[r,s]=k.useState({}),[a,o]=k.useState(!1);k.useEffect(()=>{let D=!1;return fetch("/api/teams").then(G=>G.json()).then(G=>{D||!(G!=null&&G.success)||!Array.isArray(G.data)||s(Eme(G.data))}).catch(()=>{}),()=>{D=!0}},[]);const l=async()=>{o(!0),p(null);try{await Sv(await fetch("/api/slack/cloud/agents/sync",{method:"POST"})),await S(!0)}catch(D){p(D instanceof Error?D.message:"Sync failed")}finally{o(!1)}},[c,d]=k.useState(null),[u,h]=k.useState(!0),[f,p]=k.useState(null),[x,y]=k.useState(""),[m,g]=k.useState(""),[v,b]=k.useState(!1),S=k.useCallback(async(D=!1)=>{var G,F;try{p(null);const J=await fetch(`/api/slack/agent-identities${D?"?refresh=1":""}`),q=await J.json();if(J.status===401||J.status===503){d((q==null?void 0:q.error)||"Unavailable"),n(null);return}if(!J.ok||!(q!=null&&q.success))throw new Error((q==null?void 0:q.error)||`Request failed (${J.status})`);d(null),n({cloud:(G=q.data)==null?void 0:G.cloud,identities:Array.isArray((F=q.data)==null?void 0:F.identities)?q.data.identities:[]})}catch(J){p(J instanceof Error?J.message:"Failed to load agent identities")}finally{h(!1)}},[]);k.useEffect(()=>{S()},[S]);const C=async D=>{D.preventDefault(),b(!0);try{p(null);const G=await fetch("/api/slack/agent-identities/config-token",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:x,refreshToken:m})});await Sv(G),y(""),g(""),await S()}catch(G){p(G instanceof Error?G.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 Sv(await fetch("/api/slack/agent-identities/config-token",{method:"DELETE"})),await S()}catch(D){p(D instanceof Error?D.message:"Failed to remove the token")}},N=async D=>{if(window.confirm(`Delete the Slack app for ${D.displayName}?`))try{p(null),await Sv(await fetch(`/api/slack/agent-identities/${encodeURIComponent(D.agentSession)}`,{method:"DELETE"})),await S()}catch(G){p(G instanceof Error?G.message:"Failed to delete the identity")}},T=!!((H=(K=e==null?void 0:e.cloud)==null?void 0:K.configToken)!=null&&H.configured),A=((L=($=e==null?void 0:e.cloud)==null?void 0:$.configToken)==null?void 0:L.status)==="invalid",M=new Set(((e==null?void 0:e.identities)??[]).map(D=>D.agentSession)),P=t.filter(D=>!M.has(D.agentSession)),I=[...(e==null?void 0:e.identities)??[],...P.map(D=>{var G;return{agentSession:D.agentSession,displayName:((G=r[D.agentSession])==null?void 0:G.memberName)??D.agentSession,appId:"",status:"pending_install",installUrl:D.url,hasToken:!1}})],B=new Map;for(const D of I){const G=((U=r[D.agentSession])==null?void 0:U.teamName)??"Other agents";B.has(G)||B.set(G,[]),B.get(G).push(D)}const V=I.filter(D=>D.status==="installed").length;return i.jsxs(Ot,{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(ze,{variant:"ghost",size:"sm",onClick:l,loading:a,disabled:a,"aria-label":"Sync agents with Crewly Cloud",children:"Sync agents"}),i.jsx(ze,{variant:"ghost",size:"sm",onClick:()=>S(!0),icon:zn,"aria-label":"Refresh agent identities",children:"Refresh"})]})]}),f&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{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(Bt,{variant:"warning",children:c}):e&&!((R=e.cloud)!=null&&R.enabled)?i.jsx(Bt,{variant:"warning",children:"Agent identities are not enabled on Crewly Cloud yet."}):e?i.jsxs("div",{className:"space-y-5",children:[T?i.jsxs("div",{className:"flex items-center justify-between gap-3 text-sm",children:[i.jsxs("span",{children:[i.jsx(C1,{className:"inline w-4 h-4 -mt-0.5 mr-1"}),A?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(ze,{variant:"danger-ghost",size:"sm",icon:Vi,onClick:E,children:"Remove token"})]}):null,(!T||A)&&i.jsxs("form",{onSubmit:C,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(Ps,{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(on,{id:"slack-config-token",type:"password",value:x,onChange:D=>y(D.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(on,{id:"slack-config-refresh",type:"password",value:m,onChange:D=>g(D.target.value),placeholder:"xoxe-…",autoComplete:"off",required:!0})]})]}),i.jsx(ze,{type:"submit",size:"sm",disabled:v||!m.trim(),loading:v,children:v?"Saving…":"Save configuration token"})]}),I.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:[V," of ",I.length," agents installed. Installed agents join their team channel by themselves."]}),[...B.entries()].map(([D,G])=>{const F=G.filter(J=>J.status==="installed").length;return i.jsxs("details",{open:F<G.length,className:"group",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.jsx("span",{className:"text-sm font-medium",children:D}),i.jsx("span",{className:`text-xs ${F===G.length?"text-green-400":"text-text-secondary-dark"}`,children:F===G.length?"all installed":`${F} / ${G.length} installed`})]}),i.jsx("ul",{className:"divide-y divide-border-dark",children:G.map(J=>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:[J.status==="installed"&&i.jsx("span",{className:"text-green-400 mr-1",children:"✓"}),J.displayName]}),i.jsxs("div",{className:"text-xs text-text-secondary-dark",children:[J.status==="installed"&&`Installed · bot ${J.botUserId??""}`,J.status==="pending_install"&&"Waiting for your install click",J.status==="error"&&`Install failed${J.error?`: ${J.error}`:""}`]})]}),i.jsxs("div",{className:"flex items-center gap-2",children:[J.status!=="installed"&&J.installUrl&&i.jsxs("a",{href:J.installUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-primary hover:underline inline-flex items-center gap-1",children:["Install ",J.displayName,i.jsx(Ps,{className:"w-3 h-3"})]}),J.appId&&i.jsx(ze,{variant:"danger-ghost",size:"sm",icon:Vi,onClick:()=>N(J),"aria-label":`Delete identity for ${J.displayName}`,children:"Delete"})]})]},J.agentSession))})]},D)})]})]}):null]})};async function wv(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 Tme(){return`${window.location.origin}/settings?tab=slack`}const Mme=({status:t,onRefresh:e})=>{const[n,r]=k.useState(null),[s,a]=k.useState(null),[o,l]=k.useState(""),c=async(b,S)=>{r(b),a(null);try{await S()}catch(C){a(C instanceof Error?C.message:"Request failed")}finally{r(null)}},d=()=>c("connect",async()=>{const b=await fetch(`/api/slack/cloud/install-url?returnUrl=${encodeURIComponent(Tme())}`),{url:S}=await wv(b);window.location.assign(S)}),u=b=>c("workspace",async()=>{await wv(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 wv(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 wv(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.jsxs("select",{className:"bg-background-dark border border-border-dark rounded px-2 py-1.5 text-sm",value:o||S||"",onChange:C=>l(C.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(C=>i.jsx("option",{value:C.slackTeamId,children:C.slackTeamName},C.slackTeamId))]}),i.jsx(ze,{size:"sm",onClick:()=>u(o||S||""),loading:n==="workspace",disabled:n!==null||!(o||S)||(o||S)===S,children:"Use this workspace"})]});return i.jsxs(Ot,{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(Hf,{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(ze,{variant:"ghost",size:"sm",onClick:()=>e(!0),icon:zn,"aria-label":"Refresh Cloud Slack status",children:"Refresh"})]}),s&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{variant:"error",onClose:()=>a(null),children:s})}),t?y?i.jsxs(Bt,{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(ze,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,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(ze,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,children:"Connect another workspace"})]}),i.jsx("div",{className:"flex items-start gap-3",children:i.jsx(os,{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(ze,{variant:"danger-ghost",size:"sm",icon:id,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(ze,{onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,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(Bt,{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 pO(){try{return new URLSearchParams(window.location.search).get("slack")==="connected"}catch{return!1}}const Nme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(null),[s,a]=k.useState(!0),[o,l]=k.useState(!1),[c,d]=k.useState(null),[u,h]=k.useState(()=>pO()),[f,p]=k.useState(!1),[x,y]=k.useState({botToken:"",appToken:"",signingSecret:"",defaultChannel:""}),m=k.useCallback(async()=>{var T,A,M,P,I,B,V;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:(P=H.data)==null?void 0:P.channels,lastMessageAt:(I=H.data)==null?void 0:I.lastMessageAt,messagesSent:(B=H.data)==null?void 0:B.messagesSent,messagesReceived:(V=H.data)==null?void 0:V.messagesReceived}):e({connected:!1,error:H.error})}catch{e({connected:!1,error:"Failed to fetch status"})}finally{a(!1)}},[]),g=k.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"?r(M.data):r(null)}catch{r(null)}},[]),v=k.useCallback(async(T=!1)=>{await g(T),await m()},[g,m]);k.useEffect(()=>{g(pO()),m()},[m,g]),k.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(P=>({...P,[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)}},C=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(s)return i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{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(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"botToken",required:!0,children:"Bot Token (xoxb-...)"}),i.jsx(on,{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(Tt,{htmlFor:"appToken",required:!0,children:"App Token (xapp-...)"}),i.jsx(on,{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(Tt,{htmlFor:"signingSecret",required:!0,children:"Signing Secret"}),i.jsx(on,{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(Tt,{htmlFor:"defaultChannel",children:"Default Channel (optional)"}),i.jsx(on,{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(ze,{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(Bt,{variant:"error",onClose:()=>d(null),children:c}),u&&i.jsx(Bt,{variant:"success",onClose:()=>h(!1),children:"Slack workspace connected to your Crewly account. This instance picks it up automatically."}),t.connected?i.jsxs(Bt,{variant:"success",children:["Connected to Slack",E?" via Crewly Cloud":""]}):i.jsx(Bt,{variant:"warning",children:"Not connected to Slack"}),i.jsx(Mme,{status:n,onRefresh:v}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsxs(Ot,{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(Cme,{}),i.jsx(Ame,{pendingInstalls:(n==null?void 0:n.pendingInstalls)??[]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(ze,{variant:"secondary",onClick:()=>v(),icon:zn,children:"Refresh Status"}),!E&&i.jsx(ze,{variant:"danger",onClick:C,icon:id,children:"Disconnect"})]}),N]}):i.jsx("div",{className:"space-y-6",children:N})]})},jme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),c=k.useCallback(async()=>{var h,f,p,x,y,m;try{l(null);const v=await(await fetch("/api/whatsapp/status")).json();v.success?e({connected:((h=v.data)==null?void 0:h.isConfigured)||((f=v.data)==null?void 0:f.connected)||!1,phoneNumber:(p=v.data)==null?void 0:p.phoneNumber,qrCode:(x=v.data)==null?void 0:x.qrCode,messagesSent:(y=v.data)==null?void 0:y.messagesSent,messagesReceived:(m=v.data)==null?void 0:m.messagesReceived}):e({connected:!1,error:v.error})}catch{e({connected:!1,error:"Failed to fetch WhatsApp status"})}finally{r(!1)}},[]);k.useEffect(()=>{c()},[c]);const d=async()=>{var h;a(!0),l(null);try{const f=await fetch("/api/whatsapp/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})}),p=await f.json();if(!f.ok||!p.success)throw new Error(p.error||"Connection failed");(h=p.data)!=null&&h.qrCode&&e(x=>({...x,qrCode:p.data.qrCode})),await c()}catch(f){l(f instanceof Error?f.message:"Failed to connect WhatsApp")}finally{a(!1)}},u=async()=>{if(window.confirm("Are you sure you want to disconnect from WhatsApp?"))try{l(null);const h=await fetch("/api/whatsapp/disconnect",{method:"POST"}),f=await h.json();if(!h.ok||!f.success)throw new Error(f.error||"Disconnect failed");await c()}catch(h){l(h instanceof Error?h.message:"Failed to disconnect")}};return n?i.jsx("div",{className:"flex justify-center py-8",children:i.jsx(sr,{size:"md",text:"Loading WhatsApp status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-5",children:[i.jsx(Bt,{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.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(ze,{variant:"secondary",onClick:c,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:u,icon:id,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(ze,{variant:"secondary",onClick:c,icon:zn,children:"Refresh QR Code"})]}):i.jsxs("div",{className:"space-y-4",children:[i.jsx(Bt,{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(ze,{onClick:d,disabled:s,loading:s,icon:JF,fullWidth:!0,children:s?"Initializing...":"Connect WhatsApp"})]})})]})},Rme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState("pubsub"),[u,h]=k.useState("service_account"),[f,p]=k.useState(""),[x,y]=k.useState(""),[m,g]=k.useState(""),[v,b]=k.useState(""),[S,C]=k.useState(!1),[E,N]=k.useState(null),[T,A]=k.useState(!1),[M,P]=k.useState(null),[I,B]=k.useState(""),[V,K]=k.useState(""),H=k.useRef(null),$=k.useCallback(async()=>{var q;try{l(null);const z=await(await fetch("/api/messengers/status")).json();if(z.success&&Array.isArray(z.data)){const Q=z.data.find(re=>re.platform==="google-chat");if(Q){let re=Q.details||{};if(Q.connected&&((q=Q.details)==null?void 0:q.mode)==="pubsub")try{const de=await(await fetch("/api/messengers/google-chat/status")).json();de.success&&(re={...re,...de.data})}catch{}e({connected:Q.connected,mode:re.mode,authMode:re.authMode,serviceAccountEmail:re.serviceAccountEmail,pullActive:re.pullActive,pullPaused:re.pullPaused,subscriptionName:re.subscriptionName,projectId:re.projectId,consecutiveFailures:re.consecutiveFailures,lastPullAt:re.lastPullAt})}}}catch{e({connected:!1,error:"Failed to fetch status"})}finally{r(!1)}},[]);k.useEffect(()=>{$()},[$]),k.useEffect(()=>(t.connected&&t.mode==="pubsub"&&(H.current=setInterval(()=>{$()},1e4)),()=>{H.current&&(clearInterval(H.current),H.current=null)}),[t.connected,t.mode,$]);const L=async q=>{q.preventDefault(),a(!0),l(null);try{let te;c==="webhook"?te={webhookUrl:f}:u==="adc"?(te={authMode:"adc"},c==="pubsub"&&(te.projectId=m,te.subscriptionName=v),V.trim()&&(te.serviceAccountEmail=V.trim())):c==="service-account"?te={serviceAccountKey:x}:te={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(te)}),Q=await z.json();if(!z.ok||!Q.success)throw new Error(Q.error||"Connection failed");p(""),y(""),g(""),b(""),K(""),await $()}catch(te){l(te instanceof Error?te.message:"Failed to connect")}finally{a(!1)}},U=async()=>{if(window.confirm("Are you sure you want to disconnect from Google Chat?"))try{l(null);const q=await fetch("/api/messengers/google-chat/disconnect",{method:"POST"}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Disconnect failed");await $()}catch(q){l(q instanceof Error?q.message:"Failed to disconnect")}},R=async()=>{C(!0),N(null);try{const q=await fetch("/api/messengers/google-chat/pull",{method:"POST"}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Pull failed");const z=te.messagesReceived||0;N(z>0?`Pulled ${z} message${z!==1?"s":""}`:"No new messages"),await $()}catch(q){N(q instanceof Error?q.message:"Pull failed")}finally{C(!1)}},D=async()=>{if(I.trim()){A(!0),P(null);try{const q=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"})}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Test send failed");P("Message sent successfully")}catch(q){P(q instanceof Error?q.message:"Test send failed")}finally{A(!1)}}},G=q=>{switch(q){case"webhook":return"Webhook";case"service-account":return"Service Account";case"pubsub":return"Pub/Sub (Bidirectional)";default:return"Unknown"}},F=q=>q==="adc"?"Application Default Credentials":"Service Account Key",J=()=>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(sr,{size:"md",text:"Loading Google Chat status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(Bt,{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(Bt,{variant:"success",children:i.jsx("span",{className:"font-medium text-sm",children:"Connected to Google Chat"})}),i.jsxs(Ot,{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:G(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:F(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-gray-500"}`}),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(ze,{variant:"primary",onClick:R,disabled:S,loading:S,icon:gp,"data-testid":"pull-now-btn",children:S?"Pulling...":"Pull Now"}),i.jsx(ze,{variant:"secondary",onClick:$,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:U,icon:id,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(Tt,{htmlFor:"test-send-space",children:"Space Name"}),i.jsx(on,{id:"test-send-space",name:"testSendSpace",type:"text",value:I,onChange:q=>B(q.target.value),placeholder:"spaces/AAAA...",autoComplete:"off","data-testid":"test-send-space"})]}),i.jsx(ze,{variant:"primary",onClick:D,disabled:T||!I.trim(),loading:T,icon:Q2,"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(Bt,{variant:"warning",children:i.jsx("span",{className:"font-medium text-sm",children:"Not connected to Google Chat"})}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="pubsub"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("pubsub"),"data-testid":"mode-pubsub",children:"Pub/Sub (Recommended)"}),i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="webhook"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("webhook"),"data-testid":"mode-webhook",children:"Webhook"}),i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="service-account"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("service-account"),"data-testid":"mode-service-account",children:"Service Account"})]}),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:L,className:"space-y-4",children:[c==="webhook"?i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-webhook",required:!0,children:"Webhook URL"}),i.jsx(on,{id:"gchat-webhook",name:"webhookUrl",type:"url",value:f,onChange:q=>p(q.target.value),placeholder:"https://chat.googleapis.com/v1/spaces/...",required:!0,autoComplete:"off"})]}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(Tt,{children:"Authentication Method"}),i.jsxs("div",{className:"flex gap-2 mt-1",children:[i.jsx("button",{type:"button",className:`px-3 py-1.5 text-xs rounded-lg border transition-colors ${u==="service_account"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>h("service_account"),"data-testid":"auth-service-account",children:"Service Account Key"}),i.jsx("button",{type:"button",className:`px-3 py-1.5 text-xs rounded-lg border transition-colors ${u==="adc"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>h("adc"),"data-testid":"auth-adc",children:"Application Default Credentials"})]})]}),c==="pubsub"&&i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-project-id",required:!0,children:"GCP Project ID"}),i.jsx(on,{id:"gchat-project-id",name:"projectId",type:"text",value:m,onChange:q=>g(q.target.value),placeholder:"my-gcp-project-id",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-subscription",required:!0,children:"Pub/Sub Subscription Name"}),i.jsx(on,{id:"gchat-subscription",name:"subscriptionName",type:"text",value:v,onChange:q=>b(q.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(Tt,{htmlFor:"gchat-sa-email",children:"Service Account Email (for impersonation)"}),i.jsx(on,{id:"gchat-sa-email",name:"serviceAccountEmail",type:"email",value:V,onChange:q=>K(q.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(Tt,{htmlFor:"gchat-sa-key",required:!0,children:"Service Account Key (JSON)"}),i.jsx(Ko,{id:"gchat-sa-key",name:"serviceAccountKey",value:x,onChange:q=>y(q.target.value),placeholder:'{"type": "service_account", "project_id": "...", ...}',required:!0,rows:6,className:"font-mono"})]})]}),i.jsx(ze,{type:"submit",disabled:s||!J(),loading:s,fullWidth:!0,children:s?"Connecting...":"Connect Google Chat"})]})]})]})},Ime="/api/messengers/status",Pme="/api/messengers/telegram/connect",Lme="/api/messengers/telegram/disconnect",Dme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState({botToken:"",allowedChats:""}),u=k.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Ime)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(C=>C.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{r(!1)}},[]);k.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(Pme,{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(Lme,{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(sr,{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(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"success",children:"Connected to Telegram"}),i.jsxs(Ot,{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(ze,{variant:"secondary",onClick:u,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:p,icon:id,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"warning",children:"Not connected to Telegram"}),i.jsxs(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"botToken",required:!0,children:"Bot Token"}),i.jsx(on,{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(Tt,{htmlFor:"allowedChats",children:"Allowed Chats (optional)"}),i.jsx(on,{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(ze,{type:"submit",disabled:s||!c.botToken,loading:s,fullWidth:!0,children:s?"Connecting...":"Connect to Telegram"})})]})})]})]})},Ome="/api/messengers/status",Bme="/api/messengers/discord/connect",Fme="/api/messengers/discord/disconnect",Ume=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState({token:"",allowedChannels:""}),u=k.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Ome)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(C=>C.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{r(!1)}},[]);k.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(Bme,{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(Fme,{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(sr,{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(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"success",children:"Connected to Discord"}),i.jsxs(Ot,{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(ze,{variant:"secondary",onClick:u,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:p,icon:id,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"warning",children:"Not connected to Discord"}),i.jsxs(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"token",required:!0,children:"Bot Token"}),i.jsx(on,{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(Tt,{htmlFor:"allowedChannels",children:"Allowed Channels (optional)"}),i.jsx(on,{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(ze,{type:"submit",disabled:s||!c.token,loading:s,fullWidth:!0,children:s?"Connecting...":"Connect to Discord"})})]})})]})]})},zme="/api/google/status",Hme="/api/google/connect-url",Gme="/api/google/disconnect",Wme="/settings?tab=integrations",Vme="google",$me={"https://www.googleapis.com/auth/gmail.readonly":"Read mail","https://www.googleapis.com/auth/gmail.send":"Send mail","https://www.googleapis.com/auth/calendar.readonly":"Read calendar","https://www.googleapis.com/auth/calendar.events":"Manage events","https://www.googleapis.com/auth/drive.readonly":"Read Drive","https://www.googleapis.com/auth/drive.file":"Drive files","https://www.googleapis.com/auth/documents.readonly":"Read Docs"};function Kme(t){return(t??[]).map(e=>$me[e]).filter(e=>!!e)}const qme=()=>{const[t,e]=k.useState({connected:!1,cloudConnected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState(null),u=k.useCallback(async()=>{try{l(null);const x=await fetch(zme),y=await x.json();x.ok&&y.success?e(y.data):(e({connected:!1,cloudConnected:!1}),l(y.hint||y.message||y.error||"Failed to fetch Google Workspace status"))}catch{e({connected:!1,cloudConnected:!1}),l("Failed to fetch Google Workspace status")}finally{r(!1)}},[]);k.useEffect(()=>{u();try{const x=new URLSearchParams(window.location.search).get(Vme);x==="connected"?d("Google Workspace connected."):x==="error"&&l("Google Workspace connection failed. Please try again.")}catch{}},[u]);const h=async()=>{var x;a(!0),l(null);try{const y=`${window.location.origin}${Wme}`,m=await fetch(`${Hme}?returnUrl=${encodeURIComponent(y)}`),g=await m.json();if(!m.ok||!g.success||!((x=g.data)!=null&&x.url))throw new Error(g.hint||g.message||g.error||"Could not start Google sign-in");window.location.href=g.data.url}catch(y){l(y instanceof Error?y.message:"Could not start Google sign-in"),a(!1)}},f=async()=>{if(window.confirm("Disconnect Google Workspace? Agents will no longer be able to read mail or the calendar.")){a(!0),l(null);try{const x=await fetch(Gme,{method:"DELETE"}),y=await x.json();if(!x.ok||!y.success)throw new Error(y.hint||y.message||y.error||"Disconnect failed");d(null),await u()}catch(x){l(x instanceof Error?x.message:"Failed to disconnect")}finally{a(!1)}}};if(n)return i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{text:"Loading Google Workspace status..."})});const p=Kme(t.scopes);return i.jsxs("div",{className:"space-y-6 max-w-3xl","data-testid":"google-workspace-tab",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Google Workspace"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Let agents read your Gmail, send mail on your behalf and manage your calendar. Crewly Cloud keeps the Google sign-in; mail content goes straight from Google to this instance."})]}),o&&i.jsx(Bt,{variant:"error",onClose:()=>l(null),children:o}),c&&i.jsx(Bt,{variant:"success",onClose:()=>d(null),children:c}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsxs(Bt,{variant:"success",children:["Connected as ",t.email??"your Google account"]}),i.jsxs(Ot,{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:[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:"Account"}),i.jsx("span",{className:"text-sm font-medium","data-testid":"google-workspace-email",children:t.email??"—"})]}),p.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:"Access"}),i.jsx("span",{className:"text-sm font-medium",children:p.join(", ")})]}),t.grantedAt&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Connected"}),i.jsx("span",{className:"text-sm font-medium",children:new Date(t.grantedAt).toLocaleString()})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(ze,{variant:"secondary",onClick:u,icon:zn,disabled:s,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:f,icon:id,loading:s,children:"Disconnect"})]})]}):i.jsx("div",{className:"space-y-6",children:t.cloudConnected?i.jsxs(i.Fragment,{children:[i.jsx(Bt,{variant:"warning",children:"Google Workspace is not connected"}),i.jsxs(Ot,{padding:"lg",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark mb-4",children:"You will be sent to Google to approve access for the account you use with Crewly Cloud, then brought back here."}),i.jsx(ze,{variant:"primary",onClick:h,icon:Ps,loading:s,children:"Connect Google Workspace"})]})]}):i.jsx(Bt,{variant:"info",children:"Sign in to Crewly Cloud first (Settings → Cloud), then connect Google Workspace here."})})]})},UH=[{id:"slack",name:"Slack",description:"Connect your Slack workspace for team communication with the orchestrator.",icon:bA,available:!0,component:Nme},{id:"whatsapp",name:"WhatsApp",description:"Connect via WhatsApp Web to communicate with the orchestrator from your phone.",icon:UK,available:!0,component:jme},{id:"discord",name:"Discord",description:"Connect a Discord bot to communicate with the orchestrator via Discord server.",icon:$F,available:!0,component:Ume},{id:"telegram",name:"Telegram",description:"Connect a Telegram bot for messaging the orchestrator via Telegram.",icon:Q2,available:!0,component:Dme},{id:"google-chat",name:"Google Chat",description:"Connect Google Chat for workspace communication with the orchestrator.",icon:Ax,available:!0,component:Rme},{id:"google-workspace",name:"Google Workspace",description:"Let agents read your Gmail, send mail on your behalf and manage your Google Calendar.",icon:VF,available:!0,component:qme}];function Xme(){try{const t=new URLSearchParams(window.location.search),e=t.get("platform")??(t.get("tab")==="slack"?"slack":null);return UH.some(n=>n.id===e&&n.available)?e:null}catch{return null}}const Yme=()=>{const[t,e]=k.useState(()=>Xme()),n=r=>{e(s=>s===r?null:r)};return i.jsxs("div",{className:"space-y-6 max-w-3xl",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Messaging Integrations"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Connect messaging platforms to communicate with the orchestrator from anywhere."})]}),i.jsx("div",{className:"space-y-3",children:UH.map(r=>{const s=t===r.id,a=r.icon;return i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-lg overflow-hidden","data-testid":`platform-card-${r.id}`,children:[i.jsxs("button",{className:`w-full flex items-center gap-4 p-4 text-left transition-colors ${r.available?"hover:bg-background-dark cursor-pointer":"opacity-60 cursor-default"}`,onClick:()=>r.available&&n(r.id),disabled:!r.available,"data-testid":`platform-toggle-${r.id}`,children:[i.jsx("div",{className:"flex items-center justify-center w-10 h-10 rounded-lg bg-background-dark border border-border-dark",children:i.jsx(a,{className:"w-5 h-5 text-text-secondary-dark"})}),i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"text-sm font-semibold",children:r.name}),!r.available&&i.jsx("span",{className:"text-xs px-2 py-0.5 rounded-full bg-background-dark text-text-secondary-dark border border-border-dark",children:"Coming Soon"})]}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-0.5 truncate",children:r.description})]}),r.available&&i.jsx("div",{className:"text-text-secondary-dark",children:s?i.jsx(ei,{className:"w-5 h-5"}):i.jsx(Si,{className:"w-5 h-5"})})]}),s&&r.component&&i.jsx("div",{className:"border-t border-border-dark p-6","data-testid":`platform-content-${r.id}`,children:i.jsx(r.component,{})})]},r.id)})})]})},UC={gemini:"Google Gemini",anthropic:"Anthropic",openai:"OpenAI",deepseek:"DeepSeek"},mO={gemini:"GOOGLE_GENERATIVE_AI_API_KEY",anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",deepseek:"DEEPSEEK_API_KEY"},Jme=2e3,Zme=()=>{const{settings:t,updateSettings:e,isLoading:n,error:r}=XN(),[s,a]=k.useState({global:{},runtimeOverrides:{},skillOverrides:{}}),[o,l]=k.useState(!1),[c,d]=k.useState("idle"),[u,h]=k.useState(null),[f,p]=k.useState({}),[x,y]=k.useState({}),[m,g]=k.useState({}),[v,b]=k.useState({});k.useEffect(()=>{t!=null&&t.apiKeys&&(a(t.apiKeys),l(!1))},[t]);const S=k.useCallback((P,I)=>{a(B=>({...B,global:{...B.global,[P]:I}})),l(!0),d("idle"),y(B=>({...B,[`global-${P}`]:"idle"}))},[]),C=k.useCallback((P,I,B,V)=>{a(K=>{var L,U,R;const $={...((U=(L=K.runtimeOverrides)==null?void 0:L[P])==null?void 0:U[I])??{key:"",source:"global"},[B]:V};return{...K,runtimeOverrides:{...K.runtimeOverrides,[P]:{...(R=K.runtimeOverrides)==null?void 0:R[P],[I]:$}}}}),l(!0),d("idle")},[]),E=async()=>{d("saving"),h(null);try{await e({apiKeys:s}),d("saved"),l(!1),setTimeout(()=>d("idle"),Jme)}catch(P){d("error"),h(P instanceof Error?P.message:"Failed to save")}},N=async(P,I,B)=>{if(!(!I||I.startsWith("••••"))){y(V=>({...V,[B]:"testing"})),g(V=>({...V,[B]:""}));try{const V=await xf.testApiKey(P,I);y(K=>({...K,[B]:V.valid?"valid":"invalid"})),!V.valid&&V.error&&g(K=>({...K,[B]:V.error}))}catch{y(V=>({...V,[B]:"invalid"})),g(V=>({...V,[B]:"Connection failed"}))}}},T=P=>{p(I=>({...I,[P]:!I[P]}))},A=P=>{b(I=>({...I,[P]:!I[P]}))},M=(P,I)=>{const B=x[I];return B==="testing"?i.jsx("span",{className:"text-xs text-text-secondary-dark animate-pulse",children:"Testing..."}):B==="valid"?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-400",children:[i.jsx(br,{className:"w-3 h-3"})," Valid"]}):B==="invalid"?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-red-400",children:[i.jsx(Or,{className:"w-3 h-3"})," ",m[I]||"Invalid"]}):P&&!P.startsWith("••••")?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-400",children:[i.jsx(br,{className:"w-3 h-3"})," Configured"]}):P&&P.startsWith("••••")?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-blue-400",children:[i.jsx(Kb,{className:"w-3 h-3"})," Saved"]}):i.jsxs("span",{className:"flex items-center gap-1 text-xs text-text-secondary-dark",children:[i.jsx(Or,{className:"w-3 h-3"})," Not set"]})};return n?i.jsx("div",{className:"text-text-secondary-dark",children:"Loading settings..."}):r?i.jsx(Bt,{variant:"error",children:r}):i.jsxs("div",{className:"space-y-8",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-lg font-semibold",children:"API Keys"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Configure AI provider API keys. Keys are encrypted at rest and never logged."})]}),i.jsx("div",{className:"flex gap-2",children:i.jsx(ze,{variant:"secondary",size:"sm",onClick:E,disabled:!o||c==="saving",children:c==="saving"?i.jsxs(i.Fragment,{children:[i.jsx(J2,{className:"w-4 h-4 animate-spin"})," Saving..."]}):c==="saved"?i.jsxs(i.Fragment,{children:[i.jsx(br,{className:"w-4 h-4"})," Saved"]}):i.jsxs(i.Fragment,{children:[i.jsx($c,{className:"w-4 h-4"})," Save Changes"]})})})]}),c==="error"&&u&&i.jsx(Bt,{variant:"error",children:u}),i.jsxs(Ot,{padding:"lg",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[i.jsx(Kb,{className:"w-5 h-5 text-primary"}),i.jsx("h3",{className:"text-lg font-medium",children:"Global API Keys"})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-6",children:"These keys are used system-wide as defaults. Runtimes and skills can override them with their own keys."}),i.jsx("div",{className:"space-y-5",children:dP.map(P=>{const I=s.global[P]||"",B=`global-${P}`,V=f[B];return i.jsxs("div",{className:"space-y-1",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx(Tt,{htmlFor:`global-${P}`,children:UC[P]}),M(I,B)]}),i.jsxs("div",{className:"flex gap-2",children:[i.jsxs("div",{className:"relative flex-1",children:[i.jsx(on,{id:`global-${P}`,type:V?"text":"password",value:I,onChange:K=>S(P,K.target.value),placeholder:`Enter ${mO[P]}`,className:"pr-10 font-mono text-sm"}),i.jsx("button",{type:"button",onClick:()=>T(B),className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-secondary-dark hover:text-text-primary-dark","aria-label":V?"Hide key":"Show key",children:V?i.jsx(v3,{className:"w-4 h-4"}):i.jsx(xA,{className:"w-4 h-4"})})]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>N(P,I,B),disabled:!I||I.startsWith("••••")||x[B]==="testing",children:[i.jsx(Uc,{className:"w-4 h-4"}),"Test"]})]}),i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:["Env var: ",i.jsx("code",{className:"bg-surface-dark px-1 rounded",children:mO[P]})]})]},P)})})]}),i.jsxs(Ot,{padding:"lg",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[i.jsx(Uc,{className:"w-5 h-5 text-primary"}),i.jsx("h3",{className:"text-lg font-medium",children:"Runtime Overrides"})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-4",children:"Override global keys for specific AI runtimes. By default, runtimes use the global key."}),i.jsx("div",{className:"space-y-2",children:L6.map(P=>{const I=v[P];return i.jsxs("div",{className:"border border-border-dark rounded-lg",children:[i.jsxs("button",{type:"button",onClick:()=>A(P),className:"w-full flex items-center justify-between px-4 py-3 text-sm font-medium hover:bg-surface-dark/50 rounded-lg",children:[i.jsx("span",{children:dg[P]}),I?i.jsx(ei,{className:"w-4 h-4 text-text-secondary-dark"}):i.jsx(Si,{className:"w-4 h-4 text-text-secondary-dark"})]}),I&&i.jsx("div",{className:"px-4 pb-4 space-y-4 border-t border-border-dark pt-4",children:dP.map(B=>{var L,U;const V=(U=(L=s.runtimeOverrides)==null?void 0:L[P])==null?void 0:U[B],K=(V==null?void 0:V.source)==="custom",H=K&&(V==null?void 0:V.key)||"",$=`runtime-${P}-${B}`;return i.jsxs("div",{className:"space-y-2",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx(Tt,{htmlFor:`${P}-${B}-toggle`,children:UC[B]}),i.jsx(os,{id:`${P}-${B}-toggle`,size:"sm",label:K?"Custom key":"Use global",checked:K,onChange:R=>C(P,B,"source",R.target.checked?"custom":"global")})]}),K&&i.jsxs("div",{className:"flex gap-2",children:[i.jsxs("div",{className:"relative flex-1",children:[i.jsx(on,{type:f[$]?"text":"password",value:H,onChange:R=>C(P,B,"key",R.target.value),placeholder:`Custom ${UC[B]} key for ${dg[P]}`,className:"pr-10 font-mono text-sm"}),i.jsx("button",{type:"button",onClick:()=>T($),className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-secondary-dark hover:text-text-primary-dark",children:f[$]?i.jsx(v3,{className:"w-4 h-4"}):i.jsx(xA,{className:"w-4 h-4"})})]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>N(B,H,$),disabled:!H||H.startsWith("••••")||x[$]==="testing",children:[i.jsx(Uc,{className:"w-4 h-4"}),"Test"]})]})]},B)})})]},P)})})]})]})},xl="/api/credentials";function gO(t,e){var n;if(Ye.isAxiosError(t)){const r=(n=t.response)==null?void 0:n.data;return r&&typeof r.error=="string"&&r.error.length>0?new Error(r.error):new Error(t.message||e)}return t instanceof Error?t:new Error(e)}class Qme{async list(){const e=await Ye.get(xl);if(!e.data.success||!e.data.data)throw new Error(e.data.error||"Failed to list credentials");return e.data.data}async get(e){const n=await Ye.get(`${xl}/${e}`);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to get credential");return n.data.data}async addApiKey(e){const n=await Ye.post(`${xl}/api-key`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to add API key");return n.data.data}async importFromGeminiCli(e){const n=await Ye.post(`${xl}/oauth/import-gemini-cli`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to import from gemini-cli");return n.data.data}async clearGeminiCliExtensionFile(){const e=await Ye.post(`${xl}/oauth/gemini-cli/clear-extension-file`);if(!e.data.success)throw new Error(e.data.error||"Failed to clear extension file")}async startGoogleOAuth(e={}){const n={};e.scopes&&e.scopes.length>0&&(n.scopes=e.scopes);try{const r=await Ye.post(`${xl}/oauth/google/start`,n);if(!r.data.success||!r.data.data)throw new Error(r.data.error||"Failed to start Google OAuth");return r.data.data}catch(r){throw gO(r,"Failed to start Google OAuth")}}async completeGoogleOAuth(e){try{const n=await Ye.post(`${xl}/oauth/google/complete`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to save Google credential");return n.data.data}catch(n){throw gO(n,"Failed to save Google credential")}}async update(e,n){const r=await Ye.patch(`${xl}/${e}`,n);if(!r.data.success||!r.data.data)throw new Error(r.data.error||"Failed to update credential");return r.data.data}async delete(e){const n=await Ye.delete(`${xl}/${e}`);if(!n.data.success)throw new Error(n.data.error||"Failed to delete credential")}}const mc=new Qme;function ege(){const[t,e]=k.useState([]),[n,r]=k.useState(!0),[s,a]=k.useState(null),o=k.useCallback(async()=>{r(!0),a(null);try{const x=await mc.list();e(x)}catch(x){a(x instanceof Error?x.message:"Failed to load credentials")}finally{r(!1)}},[]);k.useEffect(()=>{o()},[o]);const l=k.useCallback(async x=>{const y=await mc.addApiKey(x);return await o(),y},[o]),c=k.useCallback(async x=>{const y=await mc.importFromGeminiCli(x);return await o(),y},[o]),d=k.useCallback(async()=>{await mc.clearGeminiCliExtensionFile()},[]),u=k.useCallback(async(x={})=>mc.startGoogleOAuth(x),[]),h=k.useCallback(async x=>{const y=await mc.completeGoogleOAuth(x);return await o(),y},[o]),f=k.useCallback(async(x,y)=>{const m=await mc.update(x,y);return await o(),m},[o]),p=k.useCallback(async x=>{await mc.delete(x),await o()},[o]);return{credentials:t,isLoading:n,error:s,refresh:o,addApiKey:l,importFromGeminiCli:c,clearGeminiCliExtensionFile:d,startGoogleOAuth:u,completeGoogleOAuth:h,update:f,remove:p}}const xO=["openid","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/gmail.modify"],tge=[{value:"gemini",label:"Google Gemini"},{value:"anthropic",label:"Anthropic (Claude)"},{value:"openai",label:"OpenAI"},{value:"other",label:"Other (custom)"}],nge=()=>{const{credentials:t,isLoading:e,error:n,refresh:r,addApiKey:s,importFromGeminiCli:a,clearGeminiCliExtensionFile:o,startGoogleOAuth:l,completeGoogleOAuth:c,remove:d}=ege(),[u,h]=k.useState(null),[f,p]=k.useState(null),[x,y]=k.useState(null),m=k.useCallback((C,E)=>{y({kind:C,message:E}),setTimeout(()=>y(null),4e3)},[]),g=t.filter(C=>C.type==="google-oauth"),v=t.filter(C=>C.type==="api-key"),b=C=>{p(C),h("deleteConfirm")},S=async()=>{if(f)try{await d(f.id),m("success",`Deleted "${f.name}"`)}catch(C){m("error",C instanceof Error?C.message:"Delete failed")}finally{p(null),h(null)}};return i.jsxs("div",{className:"space-y-6",children:[i.jsx("div",{children:i.jsxs("div",{className:"flex items-start gap-2 p-4 bg-surface-dark rounded-lg border border-border-dark",children:[i.jsx(Tu,{className:"w-4 h-4 text-text-secondary-dark mt-0.5 flex-shrink-0"}),i.jsxs("div",{className:"text-sm text-text-secondary-dark",children:[i.jsx("p",{className:"font-medium text-text-primary-dark mb-1",children:"Credentials for third-party services your agents call"}),i.jsxs("p",{children:["Add Google accounts (Gmail, Drive, Calendar, etc.) and service API keys that skills use to act on your behalf. For the AI model powering your agents themselves, use the ",i.jsx("strong",{children:"API Keys"})," tab instead."]})]})]})}),x&&i.jsx(Bt,{variant:x.kind==="success"?"success":"error",children:x.message}),n&&!e&&i.jsx(Bt,{variant:"error",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{children:["Failed to load credentials: ",n]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>r(),children:[i.jsx(zn,{className:"w-3 h-3 mr-1"})," Retry"]})]})}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-3",children:[i.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[i.jsx(Sl,{className:"w-5 h-5"}),"Google Accounts",i.jsxs("span",{className:"text-sm font-normal text-text-secondary-dark",children:["(",g.length,")"]})]}),i.jsx("div",{className:"flex items-center gap-2",children:i.jsxs(ze,{variant:"primary",size:"sm",onClick:()=>h("addGoogleOAuth"),children:[i.jsx(vr,{className:"w-3 h-3 mr-1"})," Add Google Account"]})})]}),g.length===0&&!e&&i.jsxs(Ot,{className:"p-6 text-center text-sm text-text-secondary-dark",children:["No Google accounts added yet. Click ",i.jsx("strong",{children:"Add Google Account"})," above to sign in and link one — no CLI install required."]}),g.length>0&&i.jsx("div",{className:"space-y-2",children:g.map(C=>i.jsx(yO,{cred:C,onDelete:()=>b(C)},C.id))}),i.jsxs("div",{className:"mt-3 flex items-center gap-2 text-xs text-text-secondary-dark",children:[i.jsx(Zg,{className:"w-3 h-3"}),i.jsx("span",{children:"Developer option:"}),i.jsx("button",{type:"button",onClick:()=>h("importGeminiCli"),className:"text-primary hover:underline",children:"Import from Gemini CLI"})]})]}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-3",children:[i.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[i.jsx(Kb,{className:"w-5 h-5"}),"Service API Keys",i.jsxs("span",{className:"text-sm font-normal text-text-secondary-dark",children:["(",v.length,")"]})]}),i.jsxs(ze,{variant:"primary",size:"sm",onClick:()=>h("addApiKey"),children:[i.jsx(vr,{className:"w-3 h-3 mr-1"})," Add API Key"]})]}),v.length===0&&!e&&i.jsx(Ot,{className:"p-6 text-center text-sm text-text-secondary-dark",children:"No service API keys added yet. These are for skills that call third-party services (e.g., Gemini API for image generation)."}),v.length>0&&i.jsx("div",{className:"space-y-2",children:v.map(C=>i.jsx(yO,{cred:C,onDelete:()=>b(C)},C.id))})]}),u==="addApiKey"&&i.jsx(rge,{onClose:()=>h(null),onSubmit:async C=>{await s(C),m("success",`Added "${C.name}"`),h(null)}}),u==="addGoogleOAuth"&&i.jsx(ige,{onClose:()=>h(null),onStart:l,onComplete:async(C,E)=>{const N=await c({name:C,credentialsJson:E}),T=N.accountEmail?`${N.name} (${N.accountEmail})`:N.name;m("success",`Added Google account ${T}`),h(null)}}),u==="importGeminiCli"&&i.jsx(age,{onClose:()=>h(null),onImport:async C=>{await a({name:C}),m("success",`Added Google account "${C}"`)},onClearExtensionFile:o}),u==="deleteConfirm"&&f&&i.jsx(B1,{isOpen:!0,title:"Delete credential?",message:`Delete "${f.name}"? This cannot be undone. Skills using this credential will fail until you add a replacement.`,confirmLabel:"Delete",confirmVariant:"danger",onConfirm:S,onCancel:()=>{h(null),p(null)}})]})},yO=({cred:t,onDelete:e})=>{const n=t.type==="google-oauth",r=t.status==="revoked";return i.jsx(Ot,{className:"p-4",children:i.jsxs("div",{className:"flex items-start justify-between gap-4",children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[i.jsx("span",{className:"font-medium",children:t.name}),r&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded bg-red-500/10 text-red-400",children:[i.jsx(Or,{className:"w-3 h-3"}),"Revoked"]}),!r&&n&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded bg-green-500/10 text-green-400",children:[i.jsx(Wu,{className:"w-3 h-3"}),"Active"]})]}),i.jsxs("div",{className:"text-xs text-text-secondary-dark space-y-0.5",children:[i.jsxs("div",{children:["Provider: ",i.jsx("span",{className:"font-mono",children:t.provider}),n&&t.helper&&i.jsxs(i.Fragment,{children:[" · ","Helper: ",i.jsx("span",{className:"font-mono",children:t.helper})]})]}),t.accountEmail&&i.jsxs("div",{children:["Account: ",i.jsx("span",{className:"font-mono",children:t.accountEmail})]}),t.scopes&&t.scopes.length>0&&i.jsxs("div",{className:"truncate",title:t.scopes.join(" "),children:["Scopes (",t.scopes.length,"):"," ",i.jsx("span",{className:"font-mono",children:t.scopes.map(s=>s.replace("https://www.googleapis.com/auth/","")).join(", ")})]}),i.jsxs("div",{children:["Added ",new Date(t.createdAt).toLocaleDateString(),t.lastUsedAt&&` · Last used ${new Date(t.lastUsedAt).toLocaleDateString()}`]})]})]}),i.jsx(ze,{variant:"secondary",size:"sm",onClick:e,"aria-label":"Delete credential",children:i.jsx(Vi,{className:"w-3 h-3"})})]})})},rge=({onClose:t,onSubmit:e})=>{const[n,r]=k.useState(""),[s,a]=k.useState("gemini"),[o,l]=k.useState(""),[c,d]=k.useState(""),[u,h]=k.useState(!1),[f,p]=k.useState(null),x=async y=>{y.preventDefault(),p(null);const m=s==="other"?o.trim():s;if(!n.trim()||!m||!c.trim()){p("All fields are required");return}h(!0);try{await e({name:n.trim(),provider:m,value:c.trim()})}catch(g){p(g instanceof Error?g.message:"Failed to add API key"),h(!1)}};return i.jsx(Ka,{isOpen:!0,onClose:t,title:"Add API Key",size:"md",children:i.jsxs("form",{onSubmit:x,className:"space-y-4",children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-name",children:"Name"}),i.jsx(on,{id:"cred-apikey-name",type:"text",value:n,onChange:y=>r(y.target.value),placeholder:"e.g. gemini-main, openai-personal",required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-provider",children:"Provider"}),i.jsx("select",{id:"cred-apikey-provider",value:s,onChange:y=>a(y.target.value),className:"w-full px-3 py-2 bg-surface-dark border border-border-dark rounded text-sm",children:tge.map(y=>i.jsx("option",{value:y.value,children:y.label},y.value))})]}),s==="other"&&i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-custom-provider",children:"Custom provider identifier"}),i.jsx(on,{id:"cred-apikey-custom-provider",type:"text",value:o,onChange:y=>l(y.target.value),placeholder:"lowercase, e.g. 'groq', 'mistral'",required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-value",children:"API Key"}),i.jsx(on,{id:"cred-apikey-value",type:"password",value:c,onChange:y=>d(y.target.value),placeholder:"paste your API key",required:!0})]}),f&&i.jsx(Bt,{variant:"error",children:f}),i.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[i.jsx(ze,{type:"button",variant:"secondary",onClick:t,disabled:u,children:"Cancel"}),i.jsx(ze,{type:"submit",variant:"primary",disabled:u,children:u?"Adding…":"Add"})]})]})})};function sge(t){const e=t.toLowerCase();return e.includes("access_token")||e.includes("refresh_token")?"The sign-in info you pasted is incomplete. Open the success page again and copy the entire JSON block (from the opening { to the closing }).":e.includes("not valid json")?"That doesn't look like the JSON from the success page. Copy the whole block — don't edit it.":e.includes("app")&&(e.includes("block")||e.includes("denied"))?`This Google account doesn't allow sign-in with this app. Try the "Gmail only" scope, or use a different Google / Workspace account.`:e.includes("already")&&e.includes("exist")?"This Google account is already linked. Check the list above — it's already there.":t}const ige=({onClose:t,onStart:e,onComplete:n})=>{const[r,s]=k.useState("configure"),[a,o]=k.useState(""),[l,c]=k.useState("gmail-only"),[d,u]=k.useState(xO.join(`
|
|
4910
|
+
Provide detailed instructions for this skill...`,rows:8,className:"font-mono text-sm"})]})]}),i.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-dark bg-background-dark",children:[i.jsx(ze,{variant:"secondary",onClick:n,type:"button",children:"Cancel"}),i.jsx(ze,{type:"submit",onClick:u,disabled:o,loading:o,children:o?"Saving...":"Save Skill"})]})]})})},kme=({skillName:t,onConfirm:e,onCancel:n})=>{const r=s=>{s.target===s.currentTarget&&n()};return i.jsx("div",{className:"fixed inset-0 bg-background-dark/80 backdrop-blur-sm flex items-center justify-center z-50",onClick:r,children:i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-xl shadow-lg w-full max-w-md m-4",onClick:s=>s.stopPropagation(),children:[i.jsx("div",{className:"p-6 border-b border-border-dark",children:i.jsx("h2",{className:"text-xl font-semibold text-text-primary-dark",children:"Delete Skill"})}),i.jsx("div",{className:"p-6",children:i.jsxs("p",{className:"text-text-secondary-dark",children:["Are you sure you want to delete ",i.jsx("strong",{className:"text-text-primary-dark",children:t}),"? This action cannot be undone."]})}),i.jsxs("div",{className:"flex items-center justify-end gap-3 p-6 border-t border-border-dark bg-background-dark rounded-b-xl",children:[i.jsx(ze,{variant:"secondary",onClick:n,children:"Cancel"}),i.jsx(ze,{variant:"danger",onClick:e,children:"Delete"})]})]})})};async function _v(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 Cme=()=>{const[t,e]=k.useState(null),[n,r]=k.useState(!0),[s,a]=k.useState(null),[o,l]=k.useState(""),[c,d]=k.useState({}),[u,h]=k.useState(null),f=k.useCallback(async()=>{try{a(null);const m=await fetch("/api/slack/team-channels"),g=await _v(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{r(!1)}},[]);k.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 _v(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 _v(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 _v(v),await f()}catch(v){a(v instanceof Error?v.message:"Failed to unlink channel")}finally{h(null)}};return i.jsxs(Ot,{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(ze,{variant:"ghost",size:"sm",onClick:f,icon:zn,"aria-label":"Reload team channels",children:"Reload"})]}),s&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{variant:"error",onClose:()=>a(null),children:s})}),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(os,{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(on,{id:"slack-team-channels-prefix",value:o,onChange:m=>l(m.target.value),placeholder:"e.g. crew-",className:"w-40"})]}),i.jsx(ze,{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(bA,{className:"inline w-3 h-3 -mt-0.5"}),m.mapping.slackChannelName," · ",m.mapping.autoCreated?"created by Crewly":"linked"]})]})]}),m.mapping?i.jsx(ze,{variant:"danger-ghost",size:"sm",icon:id,disabled:u===m.teamId,onClick:()=>y(m),children:"Unlink"}):i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(on,{"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(ze,{variant:"secondary",size:"sm",icon:Sl,disabled:u===m.teamId||!(c[m.teamId]??"").trim(),onClick:()=>x(m.teamId,(c[m.teamId]??"").trim()),children:"Link"}),i.jsx(ze,{variant:"primary",size:"sm",icon:bA,disabled:u===m.teamId,loading:u===m.teamId,onClick:()=>x(m.teamId),children:"Create channel"})]})]},m.teamId))})]}):null]})};async function Sv(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 Eme(t){const e=r=>r.toLowerCase().replace(/\s+/g,"-"),n={};for(const r of t)for(const s of r.members??[]){const a=s.sessionName||(s.id&&s.name&&r.name?`${e(r.name)}-${e(s.name)}-${s.id.substring(0,8)}`:"");a&&(n[a]={teamName:r.name??"Team",memberName:s.name??a})}return n}const Ame=({pendingInstalls:t=[]})=>{var K,H,$,L,U,R;const[e,n]=k.useState(null),[r,s]=k.useState({}),[a,o]=k.useState(!1);k.useEffect(()=>{let D=!1;return fetch("/api/teams").then(G=>G.json()).then(G=>{D||!(G!=null&&G.success)||!Array.isArray(G.data)||s(Eme(G.data))}).catch(()=>{}),()=>{D=!0}},[]);const l=async()=>{o(!0),p(null);try{await Sv(await fetch("/api/slack/cloud/agents/sync",{method:"POST"})),await S(!0)}catch(D){p(D instanceof Error?D.message:"Sync failed")}finally{o(!1)}},[c,d]=k.useState(null),[u,h]=k.useState(!0),[f,p]=k.useState(null),[x,y]=k.useState(""),[m,g]=k.useState(""),[v,b]=k.useState(!1),S=k.useCallback(async(D=!1)=>{var G,F;try{p(null);const J=await fetch(`/api/slack/agent-identities${D?"?refresh=1":""}`),q=await J.json();if(J.status===401||J.status===503){d((q==null?void 0:q.error)||"Unavailable"),n(null);return}if(!J.ok||!(q!=null&&q.success))throw new Error((q==null?void 0:q.error)||`Request failed (${J.status})`);d(null),n({cloud:(G=q.data)==null?void 0:G.cloud,identities:Array.isArray((F=q.data)==null?void 0:F.identities)?q.data.identities:[]})}catch(J){p(J instanceof Error?J.message:"Failed to load agent identities")}finally{h(!1)}},[]);k.useEffect(()=>{S()},[S]);const C=async D=>{D.preventDefault(),b(!0);try{p(null);const G=await fetch("/api/slack/agent-identities/config-token",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:x,refreshToken:m})});await Sv(G),y(""),g(""),await S()}catch(G){p(G instanceof Error?G.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 Sv(await fetch("/api/slack/agent-identities/config-token",{method:"DELETE"})),await S()}catch(D){p(D instanceof Error?D.message:"Failed to remove the token")}},N=async D=>{if(window.confirm(`Delete the Slack app for ${D.displayName}?`))try{p(null),await Sv(await fetch(`/api/slack/agent-identities/${encodeURIComponent(D.agentSession)}`,{method:"DELETE"})),await S()}catch(G){p(G instanceof Error?G.message:"Failed to delete the identity")}},T=!!((H=(K=e==null?void 0:e.cloud)==null?void 0:K.configToken)!=null&&H.configured),A=((L=($=e==null?void 0:e.cloud)==null?void 0:$.configToken)==null?void 0:L.status)==="invalid",M=new Set(((e==null?void 0:e.identities)??[]).map(D=>D.agentSession)),P=t.filter(D=>!M.has(D.agentSession)),I=[...(e==null?void 0:e.identities)??[],...P.map(D=>{var G;return{agentSession:D.agentSession,displayName:((G=r[D.agentSession])==null?void 0:G.memberName)??D.agentSession,appId:"",status:"pending_install",installUrl:D.url,hasToken:!1}})],B=new Map;for(const D of I){const G=((U=r[D.agentSession])==null?void 0:U.teamName)??"Other agents";B.has(G)||B.set(G,[]),B.get(G).push(D)}const V=I.filter(D=>D.status==="installed").length;return i.jsxs(Ot,{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(ze,{variant:"ghost",size:"sm",onClick:l,loading:a,disabled:a,"aria-label":"Sync agents with Crewly Cloud",children:"Sync agents"}),i.jsx(ze,{variant:"ghost",size:"sm",onClick:()=>S(!0),icon:zn,"aria-label":"Refresh agent identities",children:"Refresh"})]})]}),f&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{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(Bt,{variant:"warning",children:c}):e&&!((R=e.cloud)!=null&&R.enabled)?i.jsx(Bt,{variant:"warning",children:"Agent identities are not enabled on Crewly Cloud yet."}):e?i.jsxs("div",{className:"space-y-5",children:[T?i.jsxs("div",{className:"flex items-center justify-between gap-3 text-sm",children:[i.jsxs("span",{children:[i.jsx(C1,{className:"inline w-4 h-4 -mt-0.5 mr-1"}),A?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(ze,{variant:"danger-ghost",size:"sm",icon:Vi,onClick:E,children:"Remove token"})]}):null,(!T||A)&&i.jsxs("form",{onSubmit:C,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(Ps,{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(on,{id:"slack-config-token",type:"password",value:x,onChange:D=>y(D.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(on,{id:"slack-config-refresh",type:"password",value:m,onChange:D=>g(D.target.value),placeholder:"xoxe-…",autoComplete:"off",required:!0})]})]}),i.jsx(ze,{type:"submit",size:"sm",disabled:v||!m.trim(),loading:v,children:v?"Saving…":"Save configuration token"})]}),I.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:[V," of ",I.length," agents installed. Installed agents join their team channel by themselves."]}),[...B.entries()].map(([D,G])=>{const F=G.filter(J=>J.status==="installed").length;return i.jsxs("details",{open:F<G.length,className:"group",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.jsx("span",{className:"text-sm font-medium",children:D}),i.jsx("span",{className:`text-xs ${F===G.length?"text-green-400":"text-text-secondary-dark"}`,children:F===G.length?"all installed":`${F} / ${G.length} installed`})]}),i.jsx("ul",{className:"divide-y divide-border-dark",children:G.map(J=>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:[J.status==="installed"&&i.jsx("span",{className:"text-green-400 mr-1",children:"✓"}),J.displayName]}),i.jsxs("div",{className:"text-xs text-text-secondary-dark",children:[J.status==="installed"&&!J.reinstall&&`Installed · bot ${J.botUserId??""}`,J.status==="installed"&&J.reinstall&&"Installed · new permissions need your re-authorization",J.status==="pending_install"&&"Waiting for your install click",J.status==="error"&&`Install failed${J.error?`: ${J.error}`:""}`]})]}),i.jsxs("div",{className:"flex items-center gap-2",children:[(J.status!=="installed"||J.reinstall)&&J.installUrl&&i.jsxs("a",{href:J.installUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-primary hover:underline inline-flex items-center gap-1",children:[J.status==="installed"?"Re-authorize":"Install"," ",J.displayName,i.jsx(Ps,{className:"w-3 h-3"})]}),J.appId&&i.jsx(ze,{variant:"danger-ghost",size:"sm",icon:Vi,onClick:()=>N(J),"aria-label":`Delete identity for ${J.displayName}`,children:"Delete"})]})]},J.agentSession))})]},D)})]})]}):null]})};async function wv(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 Tme(){return`${window.location.origin}/settings?tab=slack`}const Mme=({status:t,onRefresh:e})=>{const[n,r]=k.useState(null),[s,a]=k.useState(null),[o,l]=k.useState(""),c=async(b,S)=>{r(b),a(null);try{await S()}catch(C){a(C instanceof Error?C.message:"Request failed")}finally{r(null)}},d=()=>c("connect",async()=>{const b=await fetch(`/api/slack/cloud/install-url?returnUrl=${encodeURIComponent(Tme())}`),{url:S}=await wv(b);window.location.assign(S)}),u=b=>c("workspace",async()=>{await wv(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 wv(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 wv(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.jsxs("select",{className:"bg-background-dark border border-border-dark rounded px-2 py-1.5 text-sm",value:o||S||"",onChange:C=>l(C.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(C=>i.jsx("option",{value:C.slackTeamId,children:C.slackTeamName},C.slackTeamId))]}),i.jsx(ze,{size:"sm",onClick:()=>u(o||S||""),loading:n==="workspace",disabled:n!==null||!(o||S)||(o||S)===S,children:"Use this workspace"})]});return i.jsxs(Ot,{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(Hf,{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(ze,{variant:"ghost",size:"sm",onClick:()=>e(!0),icon:zn,"aria-label":"Refresh Cloud Slack status",children:"Refresh"})]}),s&&i.jsx("div",{className:"mb-4",children:i.jsx(Bt,{variant:"error",onClose:()=>a(null),children:s})}),t?y?i.jsxs(Bt,{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(ze,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,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(ze,{variant:"ghost",size:"sm",onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,children:"Connect another workspace"})]}),i.jsx("div",{className:"flex items-start gap-3",children:i.jsx(os,{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(ze,{variant:"danger-ghost",size:"sm",icon:id,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(ze,{onClick:d,loading:n==="connect",disabled:n!==null,icon:Ps,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(Bt,{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 pO(){try{return new URLSearchParams(window.location.search).get("slack")==="connected"}catch{return!1}}const Nme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(null),[s,a]=k.useState(!0),[o,l]=k.useState(!1),[c,d]=k.useState(null),[u,h]=k.useState(()=>pO()),[f,p]=k.useState(!1),[x,y]=k.useState({botToken:"",appToken:"",signingSecret:"",defaultChannel:""}),m=k.useCallback(async()=>{var T,A,M,P,I,B,V;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:(P=H.data)==null?void 0:P.channels,lastMessageAt:(I=H.data)==null?void 0:I.lastMessageAt,messagesSent:(B=H.data)==null?void 0:B.messagesSent,messagesReceived:(V=H.data)==null?void 0:V.messagesReceived}):e({connected:!1,error:H.error})}catch{e({connected:!1,error:"Failed to fetch status"})}finally{a(!1)}},[]),g=k.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"?r(M.data):r(null)}catch{r(null)}},[]),v=k.useCallback(async(T=!1)=>{await g(T),await m()},[g,m]);k.useEffect(()=>{g(pO()),m()},[m,g]),k.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(P=>({...P,[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)}},C=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(s)return i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{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(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"botToken",required:!0,children:"Bot Token (xoxb-...)"}),i.jsx(on,{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(Tt,{htmlFor:"appToken",required:!0,children:"App Token (xapp-...)"}),i.jsx(on,{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(Tt,{htmlFor:"signingSecret",required:!0,children:"Signing Secret"}),i.jsx(on,{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(Tt,{htmlFor:"defaultChannel",children:"Default Channel (optional)"}),i.jsx(on,{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(ze,{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(Bt,{variant:"error",onClose:()=>d(null),children:c}),u&&i.jsx(Bt,{variant:"success",onClose:()=>h(!1),children:"Slack workspace connected to your Crewly account. This instance picks it up automatically."}),t.connected?i.jsxs(Bt,{variant:"success",children:["Connected to Slack",E?" via Crewly Cloud":""]}):i.jsx(Bt,{variant:"warning",children:"Not connected to Slack"}),i.jsx(Mme,{status:n,onRefresh:v}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsxs(Ot,{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(Cme,{}),i.jsx(Ame,{pendingInstalls:(n==null?void 0:n.pendingInstalls)??[]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(ze,{variant:"secondary",onClick:()=>v(),icon:zn,children:"Refresh Status"}),!E&&i.jsx(ze,{variant:"danger",onClick:C,icon:id,children:"Disconnect"})]}),N]}):i.jsx("div",{className:"space-y-6",children:N})]})},jme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),c=k.useCallback(async()=>{var h,f,p,x,y,m;try{l(null);const v=await(await fetch("/api/whatsapp/status")).json();v.success?e({connected:((h=v.data)==null?void 0:h.isConfigured)||((f=v.data)==null?void 0:f.connected)||!1,phoneNumber:(p=v.data)==null?void 0:p.phoneNumber,qrCode:(x=v.data)==null?void 0:x.qrCode,messagesSent:(y=v.data)==null?void 0:y.messagesSent,messagesReceived:(m=v.data)==null?void 0:m.messagesReceived}):e({connected:!1,error:v.error})}catch{e({connected:!1,error:"Failed to fetch WhatsApp status"})}finally{r(!1)}},[]);k.useEffect(()=>{c()},[c]);const d=async()=>{var h;a(!0),l(null);try{const f=await fetch("/api/whatsapp/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})}),p=await f.json();if(!f.ok||!p.success)throw new Error(p.error||"Connection failed");(h=p.data)!=null&&h.qrCode&&e(x=>({...x,qrCode:p.data.qrCode})),await c()}catch(f){l(f instanceof Error?f.message:"Failed to connect WhatsApp")}finally{a(!1)}},u=async()=>{if(window.confirm("Are you sure you want to disconnect from WhatsApp?"))try{l(null);const h=await fetch("/api/whatsapp/disconnect",{method:"POST"}),f=await h.json();if(!h.ok||!f.success)throw new Error(f.error||"Disconnect failed");await c()}catch(h){l(h instanceof Error?h.message:"Failed to disconnect")}};return n?i.jsx("div",{className:"flex justify-center py-8",children:i.jsx(sr,{size:"md",text:"Loading WhatsApp status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-5",children:[i.jsx(Bt,{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.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(ze,{variant:"secondary",onClick:c,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:u,icon:id,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(ze,{variant:"secondary",onClick:c,icon:zn,children:"Refresh QR Code"})]}):i.jsxs("div",{className:"space-y-4",children:[i.jsx(Bt,{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(ze,{onClick:d,disabled:s,loading:s,icon:JF,fullWidth:!0,children:s?"Initializing...":"Connect WhatsApp"})]})})]})},Rme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState("pubsub"),[u,h]=k.useState("service_account"),[f,p]=k.useState(""),[x,y]=k.useState(""),[m,g]=k.useState(""),[v,b]=k.useState(""),[S,C]=k.useState(!1),[E,N]=k.useState(null),[T,A]=k.useState(!1),[M,P]=k.useState(null),[I,B]=k.useState(""),[V,K]=k.useState(""),H=k.useRef(null),$=k.useCallback(async()=>{var q;try{l(null);const z=await(await fetch("/api/messengers/status")).json();if(z.success&&Array.isArray(z.data)){const Q=z.data.find(re=>re.platform==="google-chat");if(Q){let re=Q.details||{};if(Q.connected&&((q=Q.details)==null?void 0:q.mode)==="pubsub")try{const de=await(await fetch("/api/messengers/google-chat/status")).json();de.success&&(re={...re,...de.data})}catch{}e({connected:Q.connected,mode:re.mode,authMode:re.authMode,serviceAccountEmail:re.serviceAccountEmail,pullActive:re.pullActive,pullPaused:re.pullPaused,subscriptionName:re.subscriptionName,projectId:re.projectId,consecutiveFailures:re.consecutiveFailures,lastPullAt:re.lastPullAt})}}}catch{e({connected:!1,error:"Failed to fetch status"})}finally{r(!1)}},[]);k.useEffect(()=>{$()},[$]),k.useEffect(()=>(t.connected&&t.mode==="pubsub"&&(H.current=setInterval(()=>{$()},1e4)),()=>{H.current&&(clearInterval(H.current),H.current=null)}),[t.connected,t.mode,$]);const L=async q=>{q.preventDefault(),a(!0),l(null);try{let te;c==="webhook"?te={webhookUrl:f}:u==="adc"?(te={authMode:"adc"},c==="pubsub"&&(te.projectId=m,te.subscriptionName=v),V.trim()&&(te.serviceAccountEmail=V.trim())):c==="service-account"?te={serviceAccountKey:x}:te={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(te)}),Q=await z.json();if(!z.ok||!Q.success)throw new Error(Q.error||"Connection failed");p(""),y(""),g(""),b(""),K(""),await $()}catch(te){l(te instanceof Error?te.message:"Failed to connect")}finally{a(!1)}},U=async()=>{if(window.confirm("Are you sure you want to disconnect from Google Chat?"))try{l(null);const q=await fetch("/api/messengers/google-chat/disconnect",{method:"POST"}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Disconnect failed");await $()}catch(q){l(q instanceof Error?q.message:"Failed to disconnect")}},R=async()=>{C(!0),N(null);try{const q=await fetch("/api/messengers/google-chat/pull",{method:"POST"}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Pull failed");const z=te.messagesReceived||0;N(z>0?`Pulled ${z} message${z!==1?"s":""}`:"No new messages"),await $()}catch(q){N(q instanceof Error?q.message:"Pull failed")}finally{C(!1)}},D=async()=>{if(I.trim()){A(!0),P(null);try{const q=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"})}),te=await q.json();if(!q.ok||!te.success)throw new Error(te.error||"Test send failed");P("Message sent successfully")}catch(q){P(q instanceof Error?q.message:"Test send failed")}finally{A(!1)}}},G=q=>{switch(q){case"webhook":return"Webhook";case"service-account":return"Service Account";case"pubsub":return"Pub/Sub (Bidirectional)";default:return"Unknown"}},F=q=>q==="adc"?"Application Default Credentials":"Service Account Key",J=()=>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(sr,{size:"md",text:"Loading Google Chat status..."})}):i.jsxs("div",{className:"space-y-5",children:[o&&i.jsx(Bt,{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(Bt,{variant:"success",children:i.jsx("span",{className:"font-medium text-sm",children:"Connected to Google Chat"})}),i.jsxs(Ot,{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:G(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:F(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-gray-500"}`}),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(ze,{variant:"primary",onClick:R,disabled:S,loading:S,icon:gp,"data-testid":"pull-now-btn",children:S?"Pulling...":"Pull Now"}),i.jsx(ze,{variant:"secondary",onClick:$,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:U,icon:id,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(Tt,{htmlFor:"test-send-space",children:"Space Name"}),i.jsx(on,{id:"test-send-space",name:"testSendSpace",type:"text",value:I,onChange:q=>B(q.target.value),placeholder:"spaces/AAAA...",autoComplete:"off","data-testid":"test-send-space"})]}),i.jsx(ze,{variant:"primary",onClick:D,disabled:T||!I.trim(),loading:T,icon:Q2,"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(Bt,{variant:"warning",children:i.jsx("span",{className:"font-medium text-sm",children:"Not connected to Google Chat"})}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="pubsub"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("pubsub"),"data-testid":"mode-pubsub",children:"Pub/Sub (Recommended)"}),i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="webhook"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("webhook"),"data-testid":"mode-webhook",children:"Webhook"}),i.jsx("button",{className:`px-4 py-2 text-sm rounded-lg border transition-colors ${c==="service-account"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>d("service-account"),"data-testid":"mode-service-account",children:"Service Account"})]}),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:L,className:"space-y-4",children:[c==="webhook"?i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-webhook",required:!0,children:"Webhook URL"}),i.jsx(on,{id:"gchat-webhook",name:"webhookUrl",type:"url",value:f,onChange:q=>p(q.target.value),placeholder:"https://chat.googleapis.com/v1/spaces/...",required:!0,autoComplete:"off"})]}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(Tt,{children:"Authentication Method"}),i.jsxs("div",{className:"flex gap-2 mt-1",children:[i.jsx("button",{type:"button",className:`px-3 py-1.5 text-xs rounded-lg border transition-colors ${u==="service_account"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>h("service_account"),"data-testid":"auth-service-account",children:"Service Account Key"}),i.jsx("button",{type:"button",className:`px-3 py-1.5 text-xs rounded-lg border transition-colors ${u==="adc"?"bg-primary/10 border-primary text-primary":"bg-surface-dark border-border-dark text-text-secondary-dark hover:text-text-primary-dark"}`,onClick:()=>h("adc"),"data-testid":"auth-adc",children:"Application Default Credentials"})]})]}),c==="pubsub"&&i.jsxs(i.Fragment,{children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-project-id",required:!0,children:"GCP Project ID"}),i.jsx(on,{id:"gchat-project-id",name:"projectId",type:"text",value:m,onChange:q=>g(q.target.value),placeholder:"my-gcp-project-id",required:!0,autoComplete:"off"})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"gchat-subscription",required:!0,children:"Pub/Sub Subscription Name"}),i.jsx(on,{id:"gchat-subscription",name:"subscriptionName",type:"text",value:v,onChange:q=>b(q.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(Tt,{htmlFor:"gchat-sa-email",children:"Service Account Email (for impersonation)"}),i.jsx(on,{id:"gchat-sa-email",name:"serviceAccountEmail",type:"email",value:V,onChange:q=>K(q.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(Tt,{htmlFor:"gchat-sa-key",required:!0,children:"Service Account Key (JSON)"}),i.jsx(Ko,{id:"gchat-sa-key",name:"serviceAccountKey",value:x,onChange:q=>y(q.target.value),placeholder:'{"type": "service_account", "project_id": "...", ...}',required:!0,rows:6,className:"font-mono"})]})]}),i.jsx(ze,{type:"submit",disabled:s||!J(),loading:s,fullWidth:!0,children:s?"Connecting...":"Connect Google Chat"})]})]})]})},Ime="/api/messengers/status",Pme="/api/messengers/telegram/connect",Lme="/api/messengers/telegram/disconnect",Dme=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState({botToken:"",allowedChats:""}),u=k.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Ime)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(C=>C.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{r(!1)}},[]);k.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(Pme,{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(Lme,{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(sr,{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(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"success",children:"Connected to Telegram"}),i.jsxs(Ot,{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(ze,{variant:"secondary",onClick:u,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:p,icon:id,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"warning",children:"Not connected to Telegram"}),i.jsxs(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"botToken",required:!0,children:"Bot Token"}),i.jsx(on,{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(Tt,{htmlFor:"allowedChats",children:"Allowed Chats (optional)"}),i.jsx(on,{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(ze,{type:"submit",disabled:s||!c.botToken,loading:s,fullWidth:!0,children:s?"Connecting...":"Connect to Telegram"})})]})})]})]})},Ome="/api/messengers/status",Bme="/api/messengers/discord/connect",Fme="/api/messengers/discord/disconnect",Ume=()=>{const[t,e]=k.useState({connected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState({token:"",allowedChannels:""}),u=k.useCallback(async()=>{var x,y,m,g;try{l(null);const b=await(await fetch(Ome)).json();if(b.success&&Array.isArray(b.data)){const S=b.data.find(C=>C.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{r(!1)}},[]);k.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(Bme,{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(Fme,{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(sr,{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(Bt,{variant:"error",onClose:()=>l(null),children:o}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"success",children:"Connected to Discord"}),i.jsxs(Ot,{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(ze,{variant:"secondary",onClick:u,icon:zn,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:p,icon:id,children:"Disconnect"})]})]}):i.jsxs("div",{className:"space-y-6",children:[i.jsx(Bt,{variant:"warning",children:"Not connected to Discord"}),i.jsxs(Ot,{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(Ps,{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(Ot,{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(Tt,{htmlFor:"token",required:!0,children:"Bot Token"}),i.jsx(on,{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(Tt,{htmlFor:"allowedChannels",children:"Allowed Channels (optional)"}),i.jsx(on,{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(ze,{type:"submit",disabled:s||!c.token,loading:s,fullWidth:!0,children:s?"Connecting...":"Connect to Discord"})})]})})]})]})},zme="/api/google/status",Hme="/api/google/connect-url",Gme="/api/google/disconnect",Wme="/settings?tab=integrations",Vme="google",$me={"https://www.googleapis.com/auth/gmail.readonly":"Read mail","https://www.googleapis.com/auth/gmail.send":"Send mail","https://www.googleapis.com/auth/calendar.readonly":"Read calendar","https://www.googleapis.com/auth/calendar.events":"Manage events","https://www.googleapis.com/auth/drive.readonly":"Read Drive","https://www.googleapis.com/auth/drive.file":"Drive files","https://www.googleapis.com/auth/documents.readonly":"Read Docs"};function Kme(t){return(t??[]).map(e=>$me[e]).filter(e=>!!e)}const qme=()=>{const[t,e]=k.useState({connected:!1,cloudConnected:!1}),[n,r]=k.useState(!0),[s,a]=k.useState(!1),[o,l]=k.useState(null),[c,d]=k.useState(null),u=k.useCallback(async()=>{try{l(null);const x=await fetch(zme),y=await x.json();x.ok&&y.success?e(y.data):(e({connected:!1,cloudConnected:!1}),l(y.hint||y.message||y.error||"Failed to fetch Google Workspace status"))}catch{e({connected:!1,cloudConnected:!1}),l("Failed to fetch Google Workspace status")}finally{r(!1)}},[]);k.useEffect(()=>{u();try{const x=new URLSearchParams(window.location.search).get(Vme);x==="connected"?d("Google Workspace connected."):x==="error"&&l("Google Workspace connection failed. Please try again.")}catch{}},[u]);const h=async()=>{var x;a(!0),l(null);try{const y=`${window.location.origin}${Wme}`,m=await fetch(`${Hme}?returnUrl=${encodeURIComponent(y)}`),g=await m.json();if(!m.ok||!g.success||!((x=g.data)!=null&&x.url))throw new Error(g.hint||g.message||g.error||"Could not start Google sign-in");window.location.href=g.data.url}catch(y){l(y instanceof Error?y.message:"Could not start Google sign-in"),a(!1)}},f=async()=>{if(window.confirm("Disconnect Google Workspace? Agents will no longer be able to read mail or the calendar.")){a(!0),l(null);try{const x=await fetch(Gme,{method:"DELETE"}),y=await x.json();if(!x.ok||!y.success)throw new Error(y.hint||y.message||y.error||"Disconnect failed");d(null),await u()}catch(x){l(x instanceof Error?x.message:"Failed to disconnect")}finally{a(!1)}}};if(n)return i.jsx("div",{className:"flex justify-center py-16",children:i.jsx(sr,{text:"Loading Google Workspace status..."})});const p=Kme(t.scopes);return i.jsxs("div",{className:"space-y-6 max-w-3xl","data-testid":"google-workspace-tab",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Google Workspace"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Let agents read your Gmail, send mail on your behalf and manage your calendar. Crewly Cloud keeps the Google sign-in; mail content goes straight from Google to this instance."})]}),o&&i.jsx(Bt,{variant:"error",onClose:()=>l(null),children:o}),c&&i.jsx(Bt,{variant:"success",onClose:()=>d(null),children:c}),t.connected?i.jsxs("div",{className:"space-y-6",children:[i.jsxs(Bt,{variant:"success",children:["Connected as ",t.email??"your Google account"]}),i.jsxs(Ot,{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:[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:"Account"}),i.jsx("span",{className:"text-sm font-medium","data-testid":"google-workspace-email",children:t.email??"—"})]}),p.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:"Access"}),i.jsx("span",{className:"text-sm font-medium",children:p.join(", ")})]}),t.grantedAt&&i.jsxs("div",{className:"flex items-center justify-between py-2",children:[i.jsx("span",{className:"text-sm text-text-secondary-dark",children:"Connected"}),i.jsx("span",{className:"text-sm font-medium",children:new Date(t.grantedAt).toLocaleString()})]})]})]}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(ze,{variant:"secondary",onClick:u,icon:zn,disabled:s,children:"Refresh Status"}),i.jsx(ze,{variant:"danger",onClick:f,icon:id,loading:s,children:"Disconnect"})]})]}):i.jsx("div",{className:"space-y-6",children:t.cloudConnected?i.jsxs(i.Fragment,{children:[i.jsx(Bt,{variant:"warning",children:"Google Workspace is not connected"}),i.jsxs(Ot,{padding:"lg",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark mb-4",children:"You will be sent to Google to approve access for the account you use with Crewly Cloud, then brought back here."}),i.jsx(ze,{variant:"primary",onClick:h,icon:Ps,loading:s,children:"Connect Google Workspace"})]})]}):i.jsx(Bt,{variant:"info",children:"Sign in to Crewly Cloud first (Settings → Cloud), then connect Google Workspace here."})})]})},UH=[{id:"slack",name:"Slack",description:"Connect your Slack workspace for team communication with the orchestrator.",icon:bA,available:!0,component:Nme},{id:"whatsapp",name:"WhatsApp",description:"Connect via WhatsApp Web to communicate with the orchestrator from your phone.",icon:UK,available:!0,component:jme},{id:"discord",name:"Discord",description:"Connect a Discord bot to communicate with the orchestrator via Discord server.",icon:$F,available:!0,component:Ume},{id:"telegram",name:"Telegram",description:"Connect a Telegram bot for messaging the orchestrator via Telegram.",icon:Q2,available:!0,component:Dme},{id:"google-chat",name:"Google Chat",description:"Connect Google Chat for workspace communication with the orchestrator.",icon:Ax,available:!0,component:Rme},{id:"google-workspace",name:"Google Workspace",description:"Let agents read your Gmail, send mail on your behalf and manage your Google Calendar.",icon:VF,available:!0,component:qme}];function Xme(){try{const t=new URLSearchParams(window.location.search),e=t.get("platform")??(t.get("tab")==="slack"?"slack":null);return UH.some(n=>n.id===e&&n.available)?e:null}catch{return null}}const Yme=()=>{const[t,e]=k.useState(()=>Xme()),n=r=>{e(s=>s===r?null:r)};return i.jsxs("div",{className:"space-y-6 max-w-3xl",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-xl font-semibold",children:"Messaging Integrations"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Connect messaging platforms to communicate with the orchestrator from anywhere."})]}),i.jsx("div",{className:"space-y-3",children:UH.map(r=>{const s=t===r.id,a=r.icon;return i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-lg overflow-hidden","data-testid":`platform-card-${r.id}`,children:[i.jsxs("button",{className:`w-full flex items-center gap-4 p-4 text-left transition-colors ${r.available?"hover:bg-background-dark cursor-pointer":"opacity-60 cursor-default"}`,onClick:()=>r.available&&n(r.id),disabled:!r.available,"data-testid":`platform-toggle-${r.id}`,children:[i.jsx("div",{className:"flex items-center justify-center w-10 h-10 rounded-lg bg-background-dark border border-border-dark",children:i.jsx(a,{className:"w-5 h-5 text-text-secondary-dark"})}),i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"text-sm font-semibold",children:r.name}),!r.available&&i.jsx("span",{className:"text-xs px-2 py-0.5 rounded-full bg-background-dark text-text-secondary-dark border border-border-dark",children:"Coming Soon"})]}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-0.5 truncate",children:r.description})]}),r.available&&i.jsx("div",{className:"text-text-secondary-dark",children:s?i.jsx(ei,{className:"w-5 h-5"}):i.jsx(Si,{className:"w-5 h-5"})})]}),s&&r.component&&i.jsx("div",{className:"border-t border-border-dark p-6","data-testid":`platform-content-${r.id}`,children:i.jsx(r.component,{})})]},r.id)})})]})},UC={gemini:"Google Gemini",anthropic:"Anthropic",openai:"OpenAI",deepseek:"DeepSeek"},mO={gemini:"GOOGLE_GENERATIVE_AI_API_KEY",anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",deepseek:"DEEPSEEK_API_KEY"},Jme=2e3,Zme=()=>{const{settings:t,updateSettings:e,isLoading:n,error:r}=XN(),[s,a]=k.useState({global:{},runtimeOverrides:{},skillOverrides:{}}),[o,l]=k.useState(!1),[c,d]=k.useState("idle"),[u,h]=k.useState(null),[f,p]=k.useState({}),[x,y]=k.useState({}),[m,g]=k.useState({}),[v,b]=k.useState({});k.useEffect(()=>{t!=null&&t.apiKeys&&(a(t.apiKeys),l(!1))},[t]);const S=k.useCallback((P,I)=>{a(B=>({...B,global:{...B.global,[P]:I}})),l(!0),d("idle"),y(B=>({...B,[`global-${P}`]:"idle"}))},[]),C=k.useCallback((P,I,B,V)=>{a(K=>{var L,U,R;const $={...((U=(L=K.runtimeOverrides)==null?void 0:L[P])==null?void 0:U[I])??{key:"",source:"global"},[B]:V};return{...K,runtimeOverrides:{...K.runtimeOverrides,[P]:{...(R=K.runtimeOverrides)==null?void 0:R[P],[I]:$}}}}),l(!0),d("idle")},[]),E=async()=>{d("saving"),h(null);try{await e({apiKeys:s}),d("saved"),l(!1),setTimeout(()=>d("idle"),Jme)}catch(P){d("error"),h(P instanceof Error?P.message:"Failed to save")}},N=async(P,I,B)=>{if(!(!I||I.startsWith("••••"))){y(V=>({...V,[B]:"testing"})),g(V=>({...V,[B]:""}));try{const V=await xf.testApiKey(P,I);y(K=>({...K,[B]:V.valid?"valid":"invalid"})),!V.valid&&V.error&&g(K=>({...K,[B]:V.error}))}catch{y(V=>({...V,[B]:"invalid"})),g(V=>({...V,[B]:"Connection failed"}))}}},T=P=>{p(I=>({...I,[P]:!I[P]}))},A=P=>{b(I=>({...I,[P]:!I[P]}))},M=(P,I)=>{const B=x[I];return B==="testing"?i.jsx("span",{className:"text-xs text-text-secondary-dark animate-pulse",children:"Testing..."}):B==="valid"?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-400",children:[i.jsx(br,{className:"w-3 h-3"})," Valid"]}):B==="invalid"?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-red-400",children:[i.jsx(Or,{className:"w-3 h-3"})," ",m[I]||"Invalid"]}):P&&!P.startsWith("••••")?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-400",children:[i.jsx(br,{className:"w-3 h-3"})," Configured"]}):P&&P.startsWith("••••")?i.jsxs("span",{className:"flex items-center gap-1 text-xs text-blue-400",children:[i.jsx(Kb,{className:"w-3 h-3"})," Saved"]}):i.jsxs("span",{className:"flex items-center gap-1 text-xs text-text-secondary-dark",children:[i.jsx(Or,{className:"w-3 h-3"})," Not set"]})};return n?i.jsx("div",{className:"text-text-secondary-dark",children:"Loading settings..."}):r?i.jsx(Bt,{variant:"error",children:r}):i.jsxs("div",{className:"space-y-8",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"text-lg font-semibold",children:"API Keys"}),i.jsx("p",{className:"text-sm text-text-secondary-dark mt-1",children:"Configure AI provider API keys. Keys are encrypted at rest and never logged."})]}),i.jsx("div",{className:"flex gap-2",children:i.jsx(ze,{variant:"secondary",size:"sm",onClick:E,disabled:!o||c==="saving",children:c==="saving"?i.jsxs(i.Fragment,{children:[i.jsx(J2,{className:"w-4 h-4 animate-spin"})," Saving..."]}):c==="saved"?i.jsxs(i.Fragment,{children:[i.jsx(br,{className:"w-4 h-4"})," Saved"]}):i.jsxs(i.Fragment,{children:[i.jsx($c,{className:"w-4 h-4"})," Save Changes"]})})})]}),c==="error"&&u&&i.jsx(Bt,{variant:"error",children:u}),i.jsxs(Ot,{padding:"lg",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[i.jsx(Kb,{className:"w-5 h-5 text-primary"}),i.jsx("h3",{className:"text-lg font-medium",children:"Global API Keys"})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-6",children:"These keys are used system-wide as defaults. Runtimes and skills can override them with their own keys."}),i.jsx("div",{className:"space-y-5",children:dP.map(P=>{const I=s.global[P]||"",B=`global-${P}`,V=f[B];return i.jsxs("div",{className:"space-y-1",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx(Tt,{htmlFor:`global-${P}`,children:UC[P]}),M(I,B)]}),i.jsxs("div",{className:"flex gap-2",children:[i.jsxs("div",{className:"relative flex-1",children:[i.jsx(on,{id:`global-${P}`,type:V?"text":"password",value:I,onChange:K=>S(P,K.target.value),placeholder:`Enter ${mO[P]}`,className:"pr-10 font-mono text-sm"}),i.jsx("button",{type:"button",onClick:()=>T(B),className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-secondary-dark hover:text-text-primary-dark","aria-label":V?"Hide key":"Show key",children:V?i.jsx(v3,{className:"w-4 h-4"}):i.jsx(xA,{className:"w-4 h-4"})})]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>N(P,I,B),disabled:!I||I.startsWith("••••")||x[B]==="testing",children:[i.jsx(Uc,{className:"w-4 h-4"}),"Test"]})]}),i.jsxs("p",{className:"text-xs text-text-secondary-dark",children:["Env var: ",i.jsx("code",{className:"bg-surface-dark px-1 rounded",children:mO[P]})]})]},P)})})]}),i.jsxs(Ot,{padding:"lg",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[i.jsx(Uc,{className:"w-5 h-5 text-primary"}),i.jsx("h3",{className:"text-lg font-medium",children:"Runtime Overrides"})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark mb-4",children:"Override global keys for specific AI runtimes. By default, runtimes use the global key."}),i.jsx("div",{className:"space-y-2",children:L6.map(P=>{const I=v[P];return i.jsxs("div",{className:"border border-border-dark rounded-lg",children:[i.jsxs("button",{type:"button",onClick:()=>A(P),className:"w-full flex items-center justify-between px-4 py-3 text-sm font-medium hover:bg-surface-dark/50 rounded-lg",children:[i.jsx("span",{children:dg[P]}),I?i.jsx(ei,{className:"w-4 h-4 text-text-secondary-dark"}):i.jsx(Si,{className:"w-4 h-4 text-text-secondary-dark"})]}),I&&i.jsx("div",{className:"px-4 pb-4 space-y-4 border-t border-border-dark pt-4",children:dP.map(B=>{var L,U;const V=(U=(L=s.runtimeOverrides)==null?void 0:L[P])==null?void 0:U[B],K=(V==null?void 0:V.source)==="custom",H=K&&(V==null?void 0:V.key)||"",$=`runtime-${P}-${B}`;return i.jsxs("div",{className:"space-y-2",children:[i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx(Tt,{htmlFor:`${P}-${B}-toggle`,children:UC[B]}),i.jsx(os,{id:`${P}-${B}-toggle`,size:"sm",label:K?"Custom key":"Use global",checked:K,onChange:R=>C(P,B,"source",R.target.checked?"custom":"global")})]}),K&&i.jsxs("div",{className:"flex gap-2",children:[i.jsxs("div",{className:"relative flex-1",children:[i.jsx(on,{type:f[$]?"text":"password",value:H,onChange:R=>C(P,B,"key",R.target.value),placeholder:`Custom ${UC[B]} key for ${dg[P]}`,className:"pr-10 font-mono text-sm"}),i.jsx("button",{type:"button",onClick:()=>T($),className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-secondary-dark hover:text-text-primary-dark",children:f[$]?i.jsx(v3,{className:"w-4 h-4"}):i.jsx(xA,{className:"w-4 h-4"})})]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>N(B,H,$),disabled:!H||H.startsWith("••••")||x[$]==="testing",children:[i.jsx(Uc,{className:"w-4 h-4"}),"Test"]})]})]},B)})})]},P)})})]})]})},xl="/api/credentials";function gO(t,e){var n;if(Ye.isAxiosError(t)){const r=(n=t.response)==null?void 0:n.data;return r&&typeof r.error=="string"&&r.error.length>0?new Error(r.error):new Error(t.message||e)}return t instanceof Error?t:new Error(e)}class Qme{async list(){const e=await Ye.get(xl);if(!e.data.success||!e.data.data)throw new Error(e.data.error||"Failed to list credentials");return e.data.data}async get(e){const n=await Ye.get(`${xl}/${e}`);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to get credential");return n.data.data}async addApiKey(e){const n=await Ye.post(`${xl}/api-key`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to add API key");return n.data.data}async importFromGeminiCli(e){const n=await Ye.post(`${xl}/oauth/import-gemini-cli`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to import from gemini-cli");return n.data.data}async clearGeminiCliExtensionFile(){const e=await Ye.post(`${xl}/oauth/gemini-cli/clear-extension-file`);if(!e.data.success)throw new Error(e.data.error||"Failed to clear extension file")}async startGoogleOAuth(e={}){const n={};e.scopes&&e.scopes.length>0&&(n.scopes=e.scopes);try{const r=await Ye.post(`${xl}/oauth/google/start`,n);if(!r.data.success||!r.data.data)throw new Error(r.data.error||"Failed to start Google OAuth");return r.data.data}catch(r){throw gO(r,"Failed to start Google OAuth")}}async completeGoogleOAuth(e){try{const n=await Ye.post(`${xl}/oauth/google/complete`,e);if(!n.data.success||!n.data.data)throw new Error(n.data.error||"Failed to save Google credential");return n.data.data}catch(n){throw gO(n,"Failed to save Google credential")}}async update(e,n){const r=await Ye.patch(`${xl}/${e}`,n);if(!r.data.success||!r.data.data)throw new Error(r.data.error||"Failed to update credential");return r.data.data}async delete(e){const n=await Ye.delete(`${xl}/${e}`);if(!n.data.success)throw new Error(n.data.error||"Failed to delete credential")}}const mc=new Qme;function ege(){const[t,e]=k.useState([]),[n,r]=k.useState(!0),[s,a]=k.useState(null),o=k.useCallback(async()=>{r(!0),a(null);try{const x=await mc.list();e(x)}catch(x){a(x instanceof Error?x.message:"Failed to load credentials")}finally{r(!1)}},[]);k.useEffect(()=>{o()},[o]);const l=k.useCallback(async x=>{const y=await mc.addApiKey(x);return await o(),y},[o]),c=k.useCallback(async x=>{const y=await mc.importFromGeminiCli(x);return await o(),y},[o]),d=k.useCallback(async()=>{await mc.clearGeminiCliExtensionFile()},[]),u=k.useCallback(async(x={})=>mc.startGoogleOAuth(x),[]),h=k.useCallback(async x=>{const y=await mc.completeGoogleOAuth(x);return await o(),y},[o]),f=k.useCallback(async(x,y)=>{const m=await mc.update(x,y);return await o(),m},[o]),p=k.useCallback(async x=>{await mc.delete(x),await o()},[o]);return{credentials:t,isLoading:n,error:s,refresh:o,addApiKey:l,importFromGeminiCli:c,clearGeminiCliExtensionFile:d,startGoogleOAuth:u,completeGoogleOAuth:h,update:f,remove:p}}const xO=["openid","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/gmail.modify"],tge=[{value:"gemini",label:"Google Gemini"},{value:"anthropic",label:"Anthropic (Claude)"},{value:"openai",label:"OpenAI"},{value:"other",label:"Other (custom)"}],nge=()=>{const{credentials:t,isLoading:e,error:n,refresh:r,addApiKey:s,importFromGeminiCli:a,clearGeminiCliExtensionFile:o,startGoogleOAuth:l,completeGoogleOAuth:c,remove:d}=ege(),[u,h]=k.useState(null),[f,p]=k.useState(null),[x,y]=k.useState(null),m=k.useCallback((C,E)=>{y({kind:C,message:E}),setTimeout(()=>y(null),4e3)},[]),g=t.filter(C=>C.type==="google-oauth"),v=t.filter(C=>C.type==="api-key"),b=C=>{p(C),h("deleteConfirm")},S=async()=>{if(f)try{await d(f.id),m("success",`Deleted "${f.name}"`)}catch(C){m("error",C instanceof Error?C.message:"Delete failed")}finally{p(null),h(null)}};return i.jsxs("div",{className:"space-y-6",children:[i.jsx("div",{children:i.jsxs("div",{className:"flex items-start gap-2 p-4 bg-surface-dark rounded-lg border border-border-dark",children:[i.jsx(Tu,{className:"w-4 h-4 text-text-secondary-dark mt-0.5 flex-shrink-0"}),i.jsxs("div",{className:"text-sm text-text-secondary-dark",children:[i.jsx("p",{className:"font-medium text-text-primary-dark mb-1",children:"Credentials for third-party services your agents call"}),i.jsxs("p",{children:["Add Google accounts (Gmail, Drive, Calendar, etc.) and service API keys that skills use to act on your behalf. For the AI model powering your agents themselves, use the ",i.jsx("strong",{children:"API Keys"})," tab instead."]})]})]})}),x&&i.jsx(Bt,{variant:x.kind==="success"?"success":"error",children:x.message}),n&&!e&&i.jsx(Bt,{variant:"error",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsxs("span",{children:["Failed to load credentials: ",n]}),i.jsxs(ze,{variant:"secondary",size:"sm",onClick:()=>r(),children:[i.jsx(zn,{className:"w-3 h-3 mr-1"})," Retry"]})]})}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-3",children:[i.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[i.jsx(Sl,{className:"w-5 h-5"}),"Google Accounts",i.jsxs("span",{className:"text-sm font-normal text-text-secondary-dark",children:["(",g.length,")"]})]}),i.jsx("div",{className:"flex items-center gap-2",children:i.jsxs(ze,{variant:"primary",size:"sm",onClick:()=>h("addGoogleOAuth"),children:[i.jsx(vr,{className:"w-3 h-3 mr-1"})," Add Google Account"]})})]}),g.length===0&&!e&&i.jsxs(Ot,{className:"p-6 text-center text-sm text-text-secondary-dark",children:["No Google accounts added yet. Click ",i.jsx("strong",{children:"Add Google Account"})," above to sign in and link one — no CLI install required."]}),g.length>0&&i.jsx("div",{className:"space-y-2",children:g.map(C=>i.jsx(yO,{cred:C,onDelete:()=>b(C)},C.id))}),i.jsxs("div",{className:"mt-3 flex items-center gap-2 text-xs text-text-secondary-dark",children:[i.jsx(Zg,{className:"w-3 h-3"}),i.jsx("span",{children:"Developer option:"}),i.jsx("button",{type:"button",onClick:()=>h("importGeminiCli"),className:"text-primary hover:underline",children:"Import from Gemini CLI"})]})]}),i.jsxs("section",{children:[i.jsxs("div",{className:"flex items-center justify-between mb-3",children:[i.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[i.jsx(Kb,{className:"w-5 h-5"}),"Service API Keys",i.jsxs("span",{className:"text-sm font-normal text-text-secondary-dark",children:["(",v.length,")"]})]}),i.jsxs(ze,{variant:"primary",size:"sm",onClick:()=>h("addApiKey"),children:[i.jsx(vr,{className:"w-3 h-3 mr-1"})," Add API Key"]})]}),v.length===0&&!e&&i.jsx(Ot,{className:"p-6 text-center text-sm text-text-secondary-dark",children:"No service API keys added yet. These are for skills that call third-party services (e.g., Gemini API for image generation)."}),v.length>0&&i.jsx("div",{className:"space-y-2",children:v.map(C=>i.jsx(yO,{cred:C,onDelete:()=>b(C)},C.id))})]}),u==="addApiKey"&&i.jsx(rge,{onClose:()=>h(null),onSubmit:async C=>{await s(C),m("success",`Added "${C.name}"`),h(null)}}),u==="addGoogleOAuth"&&i.jsx(ige,{onClose:()=>h(null),onStart:l,onComplete:async(C,E)=>{const N=await c({name:C,credentialsJson:E}),T=N.accountEmail?`${N.name} (${N.accountEmail})`:N.name;m("success",`Added Google account ${T}`),h(null)}}),u==="importGeminiCli"&&i.jsx(age,{onClose:()=>h(null),onImport:async C=>{await a({name:C}),m("success",`Added Google account "${C}"`)},onClearExtensionFile:o}),u==="deleteConfirm"&&f&&i.jsx(B1,{isOpen:!0,title:"Delete credential?",message:`Delete "${f.name}"? This cannot be undone. Skills using this credential will fail until you add a replacement.`,confirmLabel:"Delete",confirmVariant:"danger",onConfirm:S,onCancel:()=>{h(null),p(null)}})]})},yO=({cred:t,onDelete:e})=>{const n=t.type==="google-oauth",r=t.status==="revoked";return i.jsx(Ot,{className:"p-4",children:i.jsxs("div",{className:"flex items-start justify-between gap-4",children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[i.jsx("span",{className:"font-medium",children:t.name}),r&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded bg-red-500/10 text-red-400",children:[i.jsx(Or,{className:"w-3 h-3"}),"Revoked"]}),!r&&n&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded bg-green-500/10 text-green-400",children:[i.jsx(Wu,{className:"w-3 h-3"}),"Active"]})]}),i.jsxs("div",{className:"text-xs text-text-secondary-dark space-y-0.5",children:[i.jsxs("div",{children:["Provider: ",i.jsx("span",{className:"font-mono",children:t.provider}),n&&t.helper&&i.jsxs(i.Fragment,{children:[" · ","Helper: ",i.jsx("span",{className:"font-mono",children:t.helper})]})]}),t.accountEmail&&i.jsxs("div",{children:["Account: ",i.jsx("span",{className:"font-mono",children:t.accountEmail})]}),t.scopes&&t.scopes.length>0&&i.jsxs("div",{className:"truncate",title:t.scopes.join(" "),children:["Scopes (",t.scopes.length,"):"," ",i.jsx("span",{className:"font-mono",children:t.scopes.map(s=>s.replace("https://www.googleapis.com/auth/","")).join(", ")})]}),i.jsxs("div",{children:["Added ",new Date(t.createdAt).toLocaleDateString(),t.lastUsedAt&&` · Last used ${new Date(t.lastUsedAt).toLocaleDateString()}`]})]})]}),i.jsx(ze,{variant:"secondary",size:"sm",onClick:e,"aria-label":"Delete credential",children:i.jsx(Vi,{className:"w-3 h-3"})})]})})},rge=({onClose:t,onSubmit:e})=>{const[n,r]=k.useState(""),[s,a]=k.useState("gemini"),[o,l]=k.useState(""),[c,d]=k.useState(""),[u,h]=k.useState(!1),[f,p]=k.useState(null),x=async y=>{y.preventDefault(),p(null);const m=s==="other"?o.trim():s;if(!n.trim()||!m||!c.trim()){p("All fields are required");return}h(!0);try{await e({name:n.trim(),provider:m,value:c.trim()})}catch(g){p(g instanceof Error?g.message:"Failed to add API key"),h(!1)}};return i.jsx(Ka,{isOpen:!0,onClose:t,title:"Add API Key",size:"md",children:i.jsxs("form",{onSubmit:x,className:"space-y-4",children:[i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-name",children:"Name"}),i.jsx(on,{id:"cred-apikey-name",type:"text",value:n,onChange:y=>r(y.target.value),placeholder:"e.g. gemini-main, openai-personal",required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-provider",children:"Provider"}),i.jsx("select",{id:"cred-apikey-provider",value:s,onChange:y=>a(y.target.value),className:"w-full px-3 py-2 bg-surface-dark border border-border-dark rounded text-sm",children:tge.map(y=>i.jsx("option",{value:y.value,children:y.label},y.value))})]}),s==="other"&&i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-custom-provider",children:"Custom provider identifier"}),i.jsx(on,{id:"cred-apikey-custom-provider",type:"text",value:o,onChange:y=>l(y.target.value),placeholder:"lowercase, e.g. 'groq', 'mistral'",required:!0})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-apikey-value",children:"API Key"}),i.jsx(on,{id:"cred-apikey-value",type:"password",value:c,onChange:y=>d(y.target.value),placeholder:"paste your API key",required:!0})]}),f&&i.jsx(Bt,{variant:"error",children:f}),i.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[i.jsx(ze,{type:"button",variant:"secondary",onClick:t,disabled:u,children:"Cancel"}),i.jsx(ze,{type:"submit",variant:"primary",disabled:u,children:u?"Adding…":"Add"})]})]})})};function sge(t){const e=t.toLowerCase();return e.includes("access_token")||e.includes("refresh_token")?"The sign-in info you pasted is incomplete. Open the success page again and copy the entire JSON block (from the opening { to the closing }).":e.includes("not valid json")?"That doesn't look like the JSON from the success page. Copy the whole block — don't edit it.":e.includes("app")&&(e.includes("block")||e.includes("denied"))?`This Google account doesn't allow sign-in with this app. Try the "Gmail only" scope, or use a different Google / Workspace account.`:e.includes("already")&&e.includes("exist")?"This Google account is already linked. Check the list above — it's already there.":t}const ige=({onClose:t,onStart:e,onComplete:n})=>{const[r,s]=k.useState("configure"),[a,o]=k.useState(""),[l,c]=k.useState("gmail-only"),[d,u]=k.useState(xO.join(`
|
|
4911
4911
|
`)),[h,f]=k.useState(null),[p,x]=k.useState(""),[y,m]=k.useState(null),[g,v]=k.useState(!1),[b,S]=k.useState(!1);k.useEffect(()=>{if(!g)return;const M=setTimeout(()=>v(!1),1500);return()=>clearTimeout(M)},[g]);const C=k.useMemo(()=>{if(l==="gmail-only")return[...xO];if(l!=="full-workspace")return d.split(`
|
|
4912
4912
|
`).map(M=>M.trim()).filter(M=>M.length>0)},[l,d]),E=async()=>{if(m(null),!a.trim()){m('Please give this account a name (e.g. "personal-gmail").');return}if(l==="custom"&&(!C||C.length===0)){m("Custom scopes list is empty. Add at least one scope URL.");return}S(!0);try{const M=await e(C?{scopes:C}:void 0);f(M.authUrl),s("signin")}catch(M){m(M instanceof Error?M.message:"Failed to generate sign-in link")}finally{S(!1)}},N=async()=>{if(h)try{await navigator.clipboard.writeText(h),v(!0)}catch{const M=document.createElement("textarea");M.value=h,document.body.appendChild(M),M.select();try{document.execCommand("copy"),v(!0)}catch{m("Could not copy to clipboard. Copy the link manually.")}finally{document.body.removeChild(M)}}},T=async()=>{if(m(null),!p.trim()){m("Paste the JSON block from the success page below.");return}s("saving");try{await n(a.trim(),p.trim())}catch(M){const P=M instanceof Error?M.message:"Failed to save account";m(sge(P)),s("signin")}},A=r==="configure"?"Add Google account":"Sign in on any device";return i.jsxs(Ka,{isOpen:!0,onClose:t,title:A,size:"lg",children:[r==="configure"&&i.jsxs("div",{className:"space-y-4",children:[i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Link a Google account so your agents can use it for Gmail, Drive, Calendar, etc. You'll sign in on your phone or another device — no terminal needed."}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-goog-name",children:"Name (internal)"}),i.jsx(on,{id:"cred-goog-name",type:"text",value:a,onChange:M=>o(M.target.value),placeholder:"e.g. personal-gmail, info-steam-fun",autoFocus:!0}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"You'll use this name to tell agents which account to use."})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-goog-scope",children:"Access scope"}),i.jsxs("select",{id:"cred-goog-scope",value:l,onChange:M=>c(M.target.value),className:"w-full px-3 py-2 bg-surface-dark border border-border-dark rounded text-sm",children:[i.jsx("option",{value:"gmail-only",children:"Gmail only (recommended for personal accounts)"}),i.jsx("option",{value:"full-workspace",children:"Full Workspace (Gmail, Drive, Calendar, Photos)"}),i.jsx("option",{value:"custom",children:"Custom — pick scopes manually"})]}),i.jsxs("p",{className:"text-xs text-text-secondary-dark mt-1",children:["If Google blocks the sign-in page, try ",i.jsx("strong",{children:"Gmail only"})," ","first — broader scopes require a Workspace account."]})]}),l==="custom"&&i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-goog-custom-scopes",children:"Scopes (one per line)"}),i.jsx("textarea",{id:"cred-goog-custom-scopes",value:d,onChange:M=>u(M.target.value),rows:5,className:"w-full px-3 py-2 bg-surface-dark border border-border-dark rounded text-xs font-mono",spellCheck:!1}),i.jsx("p",{className:"text-xs text-text-secondary-dark mt-1",children:"Paste full OAuth scope URLs (one per line). Advanced."})]}),y&&i.jsx(Bt,{variant:"error",children:y}),i.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[i.jsx(ze,{variant:"secondary",onClick:t,disabled:b,children:"Cancel"}),i.jsx(ze,{variant:"primary",onClick:E,disabled:b,children:b?"Generating…":"Generate sign-in link"})]})]}),r==="signin"&&h&&i.jsxs("div",{className:"space-y-4",children:[i.jsx(Bt,{variant:"info",children:"Sign in as the Google account you want to link. After signing in, Google will show a success page with a JSON block — copy it and paste below."}),i.jsxs("div",{className:"flex flex-col items-center gap-3 py-2",children:[i.jsx("div",{className:"bg-white p-3 rounded-lg",children:i.jsx(aM,{value:h,size:256,level:"M",includeMargin:!1})}),i.jsx("div",{className:"text-xs text-text-secondary-dark text-center",children:"Scan with your phone camera"})]}),i.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[i.jsxs("a",{href:h,target:"_blank",rel:"noreferrer",className:"flex-1 inline-flex items-center justify-center gap-2 px-4 py-2 bg-primary text-white rounded-md text-sm hover:opacity-90",children:[i.jsx(Ps,{className:"w-4 h-4"})," Open sign-in page"]}),i.jsx(ze,{variant:"secondary",onClick:N,type:"button",children:g?i.jsxs(i.Fragment,{children:[i.jsx(br,{className:"w-4 h-4 mr-1"})," Copied"]}):i.jsxs(i.Fragment,{children:[i.jsx(K2,{className:"w-4 h-4 mr-1"})," Copy link"]})})]}),i.jsxs("div",{children:[i.jsx(Tt,{htmlFor:"cred-goog-json",children:"After signing in, paste the JSON from the success page here:"}),i.jsx("textarea",{id:"cred-goog-json",value:p,onChange:M=>x(M.target.value),rows:8,placeholder:`{
|
|
4913
4913
|
"access_token": "...",
|
|
@@ -4958,4 +4958,4 @@ Deployed to staging
|
|
|
4958
4958
|
95% code coverage`})]}),T&&i.jsx("div",{"data-testid":"create-mission-error",children:i.jsx(Bt,{variant:"error",children:T})})]})}),i.jsxs(ad,{children:[i.jsx(ze,{variant:"ghost",size:"sm",onClick:e,disabled:E,children:"Cancel"}),i.jsx(ze,{variant:"primary",size:"sm",onClick:V,disabled:E,"data-testid":"create-mission-submit",children:E?"Creating...":"Create Mission"})]})]}):null},Y9={number:"count",percentage:"%",boolean:"done",currency:"$"},u4={number:"Number",percentage:"Percentage",boolean:"Yes / No",currency:"Currency"},h4={title:"",metricType:"number",baseline:"0",target:"",unit:Y9.number,measurementSource:"manual"};function wAe(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 Fm(t){if(t.trim()==="")return null;const e=Number(t);return Number.isFinite(e)?e:null}const kAe=({missionId:t,onChanged:e})=>{const[n,r]=k.useState([]),[s,a]=k.useState(!0),[o,l]=k.useState(null),[c,d]=k.useState(null),[u,h]=k.useState(!1),[f,p]=k.useState(!1),[x,y]=k.useState(h4),[m,g]=k.useState(null),[v,b]=k.useState(""),[S,C]=k.useState(""),[E,N]=k.useState(null),[T,A]=k.useState(null),[M,P]=k.useState(null),I=k.useCallback(async()=>{l(null);try{const R=await ft.getKeyResults(t);r(R)}catch(R){l(R instanceof Error?R.message:"Failed to load key results")}finally{a(!1)}},[t]);k.useEffect(()=>{a(!0),I()},[I]);const B=k.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]),V=async()=>{const R=Fm(x.baseline),D=Fm(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 G={title:x.title.trim(),metricType:x.metricType,baseline:R,target:D,unit:x.unit.trim(),measurementSource:x.measurementSource};await B(async()=>{await ft.createKeyResult(t,G)})&&(y(h4),p(!1))},K=R=>{d(null),N(null),g(R.id),b(String(R.current)),C("")},H=async R=>{const D=Fm(v);if(D===null){d("Measurement value must be a number");return}await B(async()=>{await ft.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})},L=async R=>{if(!T)return;const D=Fm(T.target),G=Fm(T.current);if(D===null||G===null){d("Target and current must be numbers");return}if(D===R.baseline){d("Target must differ from the baseline");return}await B(async()=>{await ft.updateKeyResult(t,R.id,{...D!==R.target?{target:D}:{},...G!==R.current?{current:G}:{},...T.measurementSource!==R.measurementSource?{measurementSource:T.measurementSource}:{}})})&&(N(null),A(null))},U=async()=>{if(!M)return;const R=M;await B(async()=>{await ft.deleteKeyResult(t,R)})&&P(null)};return i.jsxs(Ot,{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(BF,{className:"h-4 w-4"}),"Key Results (",n.length,")"]}),i.jsx(ze,{variant:"ghost",size:"sm",icon:f?On:vr,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(Bt,{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(Vr,{"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(dr,{"aria-label":"Metric type",value:x.metricType,onChange:R=>{const D=R.target.value;y(G=>({...G,metricType:D,unit:Y9[D]}))},"data-testid":"kr-new-metric",children:DQ.map(R=>i.jsx("option",{value:R,children:u4[R]},R))}),i.jsx(Vr,{"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(Vr,{"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(Vr,{"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(dr,{"aria-label":"Measurement source",value:x.measurementSource,onChange:R=>y(D=>({...D,measurementSource:R.target.value})),"data-testid":"kr-new-source",children:gP.map(R=>i.jsx("option",{value:R,children:vk[R]},R))}),i.jsx(ze,{variant:"primary",size:"sm",onClick:V,disabled:u,"data-testid":"kr-new-submit",children:u?"Saving…":"Create KR"})]})]}),s?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(Bt,{variant:"error",children:[o,i.jsx(ze,{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 q;const D=RM(R),G=(q=R.measurements)==null?void 0:q[0],F=m===R.id,J=E===R.id&&T!==null;return i.jsxs(Vn.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:u4[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:[hg(R.baseline,R.metricType,R.unit),i.jsx("span",{className:"text-text-secondary-dark",children:" → "}),i.jsx("span",{className:"font-semibold",children:hg(R.current,R.metricType,R.unit)}),i.jsx("span",{className:"text-text-secondary-dark",children:" → "}),hg(R.target,R.metricType,R.unit)]}),i.jsx("td",{className:"py-2 pr-3",children:i.jsx(nx,{percent:D,status:R.status,"data-testid":`kr-progress-${R.id}`})}),i.jsx("td",{className:"py-2 pr-3",children:i.jsx(tn,{variant:OQ[R.status],size:"sm","data-testid":`kr-status-${R.id}`,children:YA[R.status]})}),i.jsx("td",{className:"py-2 pr-3 text-xs text-text-secondary-dark",children:vk[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:wAe(G==null?void 0:G.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(ze,{variant:"ghost",size:"sm",icon:HK,onClick:()=>K(R),disabled:u,"data-testid":`kr-measure-${R.id}`,"aria-label":"Record measurement",children:"Measure"}),i.jsx(ze,{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(ze,{variant:"danger-ghost",size:"icon",className:"h-8 w-8",icon:Vi,onClick:()=>P(R.id),disabled:u,"data-testid":`kr-delete-${R.id}`,"aria-label":"Delete key result"})]})})]}),F&&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(Vr,{"aria-label":"Measurement value",type:"number",value:v,onChange:te=>b(te.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(Vr,{"aria-label":"Measurement note",placeholder:"Note (optional)",value:S,onChange:te=>C(te.target.value),className:"flex-1 min-w-[160px]","data-testid":`kr-measure-note-${R.id}`}),i.jsx(ze,{variant:"primary",size:"sm",icon:$c,onClick:()=>H(R.id),disabled:u,"data-testid":`kr-measure-submit-${R.id}`,children:u?"Saving…":"Save"}),i.jsx(ze,{variant:"ghost",size:"sm",onClick:()=>g(null),disabled:u,children:"Cancel"})]})})}),J&&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(Vr,{"aria-label":"Edit target",type:"number",value:T.target,onChange:te=>A(z=>z&&{...z,target:te.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(Vr,{"aria-label":"Edit current",type:"number",value:T.current,onChange:te=>A(z=>z&&{...z,current:te.target.value}),className:"w-28","data-testid":`kr-edit-current-${R.id}`}),i.jsx(dr,{"aria-label":"Edit measurement source",value:T.measurementSource,onChange:te=>A(z=>z&&{...z,measurementSource:te.target.value}),"data-testid":`kr-edit-source-${R.id}`,children:gP.map(te=>i.jsx("option",{value:te,children:vk[te]},te))}),i.jsx(ze,{variant:"primary",size:"sm",icon:$c,onClick:()=>L(R),disabled:u,"data-testid":`kr-edit-submit-${R.id}`,children:u?"Saving…":"Save"}),i.jsx(ze,{variant:"ghost",size:"sm",onClick:()=>{N(null),A(null)},disabled:u,children:"Cancel"})]})})})]},R.id)})})]})}),i.jsx(B1,{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:()=>P(null),onConfirm:U})]})},CAe={continue:"Continue",adjust_strategy:"Adjust strategy",replan:"Replan",escalate:"Escalate"};function f4(t,e){return e.get(t)??t.slice(0,8)}const EAe=({missionId:t,level:e,parentMissionId:n,missionNames:r,refreshKey:s=0})=>{const a=_r(),[o,l]=k.useState(null),[c,d]=k.useState(!0),[u,h]=k.useState(null),f=k.useCallback(async()=>{d(!0),h(null);try{l(await ft.getCascadeSummary(t))}catch(p){h(p instanceof Error?p.message:"Failed to load cascade")}finally{d(!1)}},[t]);return k.useEffect(()=>{f()},[f,s]),i.jsxs(Ot,{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(Gf,{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.jsxs("button",{type:"button",onClick:()=>a(`/missions/${n}`),className:"flex items-center gap-1.5 text-sm text-primary hover:underline text-left","data-testid":"cascade-parent-link",children:[i.jsx(Xg,{className:"h-3.5 w-3.5"}),f4(n,r)]}):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(Bt,{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:CAe[o.recommendation]??o.recommendation})]}),i.jsx(nx,{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(PM,{counts:G6(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(Dx,{level:p.level}),i.jsx("span",{className:"text-sm text-text-primary-dark truncate",children:f4(p.missionId,r)}),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(nx,{percent:p.rolledUpProgress,"data-testid":`cascade-child-progress-${p.missionId}`})]})},p.missionId))})]})]}):null]})},AAe=({parentMissionId:t,onDecided:e})=>{const n=_r(),[r,s]=k.useState([]),[a,o]=k.useState(!1),l=k.useCallback(async()=>{try{s(await ft.getProposals(t))}catch{s([])}finally{o(!0)}},[t]);k.useEffect(()=>{l()},[l]);const c=d=>{s(u=>u.filter(h=>h.id!==d.id)),e==null||e(d)};return!a||r.length===0?null:i.jsxs(Ot,{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(Vu,{className:"h-4 w-4 text-yellow-400"}),"Proposals awaiting approval (",r.length,")"]}),i.jsx("ul",{className:"space-y-2",children:r.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(Dx,{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(tn,{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(_j,{missionId:d.id,onDecided:c})]})},d.id)})})]})},TAe=[{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"}],MAe=({missionId:t,refreshKey:e=0})=>{const[n,r]=k.useState(null),[s,a]=k.useState(!0),[o,l]=k.useState(null),c=k.useCallback(async()=>{a(!0),l(null);try{r(await ft.getMissionProgress(t))}catch(d){l(d instanceof Error?d.message:"Failed to load progress")}finally{a(!1)}},[t]);return k.useEffect(()=>{c()},[c,e]),i.jsxs(Ot,{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($o,{className:"h-4 w-4"}),"Execution Progress"]}),s?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(Bt,{variant:"error",children:o})}):n?i.jsxs("div",{className:"space-y-3 text-sm",children:[i.jsx(nx,{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:TAe.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 Kh(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 NAe(t){var e,n,r,s;return{objective:t.objective,status:t.status,priority:t.priority??"medium",ownerTeamId:t.ownerTeamId,currentStrategy:t.currentStrategy??"",cadence:t.cadence??"",successCriteriaText:(t.successCriteria??[]).join(`
|
|
4959
4959
|
`),periodLabel:((e=t.period)==null?void 0:e.label)??"",periodType:((n=t.period)==null?void 0:n.type)??"",periodStart:(r=t.period)!=null&&r.startDate?t.period.startDate.slice(0,10):"",periodEnd:(s=t.period)!=null&&s.endDate?t.period.endDate.slice(0,10):"",parentMissionId:t.parentMissionId??""}}function jAe(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(`
|
|
4960
4960
|
`).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 J9=()=>{var $,L,U,R,D;const{id:t}=Gu(),e=_r(),[n,r]=k.useState(null),[s,a]=k.useState(!0),[o,l]=k.useState(null),[c,d]=k.useState(!1),[u,h]=k.useState(!1),[f,p]=k.useState(null),[x,y]=k.useState(!1),[m,g]=k.useState(null),[v,b]=k.useState(new Map),[S,C]=k.useState(new Map),[E,N]=k.useState(0),T=k.useCallback(async(G=!0)=>{if(t){G?a(!0):d(!0),l(null);try{const F=await ft.getMission(t);r(F)}catch(F){const J=F instanceof Error?F.message:"Failed to load mission";l(J)}finally{a(!1),d(!1)}}},[t]);k.useEffect(()=>{T()},[T]),k.useEffect(()=>{let G=!1;return(async()=>{try{const F=await ft.getMissions();if(G)return;b(new Map(F.map(J=>[J.id,J.objective]))),C(new Map(F.map(J=>[J.id,{level:J.level,parentMissionId:J.parentMissionId}])))}catch{}})(),()=>{G=!0}},[t]);const A=k.useCallback(()=>{N(G=>G+1),T(!1)},[T]),M=k.useCallback(G=>{r(F=>F&&F.id===G.id?{...F,...G}:F),A()},[A]),P=k.useCallback(()=>{n&&(p(NAe(n)),g(null),h(!0))},[n]),I=k.useCallback(()=>{h(!1),p(null),g(null)},[]),B=k.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 G=await ft.updateMission(t,jAe(f));r(G),h(!1),p(null)}catch(G){const F=G instanceof Error?G.message:"Failed to save mission";g(F)}finally{y(!1)}}},[t,f]),V=k.useMemo(()=>(G,F)=>{p(J=>J&&{...J,[G]:F})},[]);if(s)return i.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:i.jsx(sr,{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.jsxs("button",{onClick:()=>e("/missions"),className:"flex items-center gap-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to Missions"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"text-center py-8",children:[i.jsx("p",{className:"text-red-400 mb-2",children:o}),i.jsx("button",{onClick:()=>T(),className:"px-4 py-2 text-sm font-medium rounded-lg bg-primary/10 text-primary hover:bg-primary/20 transition-colors",children:"Retry"})]})})]});if(!n)return i.jsxs("div",{className:"p-6 max-w-[1000px] mx-auto",children:[i.jsxs("button",{onClick:()=>e("/missions"),className:"flex items-center gap-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to Missions"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"text-center py-8 text-text-secondary-dark",children:[i.jsx(Mu,{className:"h-10 w-10 mx-auto mb-3 opacity-40"}),i.jsx("p",{children:"Mission not found."})]})})]});const K=jM(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.jsxs("button",{onClick:()=>e("/missions"),className:"flex items-center gap-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors","data-testid":"mission-detail-back",children:[i.jsx(Ua,{className:"h-4 w-4"}),"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(Vr,{"aria-label":"Objective",value:f.objective,onChange:G=>V("objective",G.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(Dx,{level:K}),i.jsx(Wl,{status:MM(n.status),children:Qb(n.status)}),H&&(H!=="approved"||((L=n.approval)==null?void 0:L.decidedAt))&&i.jsx(IM,{state:H}),n.priority&&i.jsx(tn,{variant:z6[n.priority],size:"sm",children:qA[n.priority]}),((U=n.period)==null?void 0:U.label)&&i.jsx(tn,{variant:"info",size:"sm",children:n.period.label}),i.jsx(tn,{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(_j,{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(ze,{variant:"primary",size:"sm",icon:$c,onClick:B,disabled:x,"data-testid":"mission-save",children:x?"Saving…":"Save"}),i.jsx(ze,{variant:"ghost",size:"sm",icon:On,onClick:I,disabled:x,"data-testid":"mission-cancel",children:"Cancel"})]}):i.jsxs(i.Fragment,{children:[i.jsx(ze,{variant:"primary",size:"sm",icon:E1,onClick:P,"data-testid":"mission-edit",children:"Edit"}),i.jsx(ze,{variant:"ghost",size:"sm",icon:zn,onClick:()=>T(!1),disabled:c,className:c?"animate-spin":"","aria-label":"Refresh mission",children:"Refresh"})]})})]}),m&&i.jsx("div",{"data-testid":"mission-save-error",className:"mb-4",children:i.jsx(Bt,{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(Ot,{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(Mu,{className:"h-4 w-4"}),"Current Strategy"]}),u&&f?i.jsx("textarea",{"aria-label":"Current Strategy",className:"w-full bg-background-dark border border-border-dark rounded-lg px-3 py-2 text-sm text-text-primary-dark resize-y focus:outline-none focus:border-accent-blue/50",rows:4,value:f.currentStrategy,onChange:G=>V("currentStrategy",G.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(Ot,{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(Wu,{className:"h-4 w-4"}),"Success Criteria (",n.successCriteria.length,")"]}),u&&f?i.jsx("textarea",{"aria-label":"Success Criteria (one per line)",className:"w-full bg-background-dark border border-border-dark rounded-lg px-3 py-2 text-sm text-text-primary-dark resize-y focus:outline-none focus:border-accent-blue/50",rows:5,placeholder:"One criterion per line",value:f.successCriteriaText,onChange:G=>V("successCriteriaText",G.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((G,F)=>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(HF,{className:"h-4 w-4"})}),G]},F))})]}),!u&&i.jsx(kAe,{missionId:n.id,onChanged:A}),!u&&i.jsx(AAe,{parentMissionId:n.id,onDecided:M}),!u&&i.jsx(EAe,{missionId:n.id,level:K,parentMissionId:n.parentMissionId,missionNames:v,refreshKey:E}),!u&&n.learnings&&n.learnings.length>0&&i.jsxs(Ot,{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(Ex,{className:"h-4 w-4"}),"Learnings (",n.learnings.length,")"]}),i.jsx("ul",{className:"space-y-2",children:n.learnings.map((G,F)=>i.jsx("li",{className:"text-sm text-text-primary-dark pl-4 border-l-2 border-border-dark",children:G},F))})]})]}),i.jsxs("div",{className:"flex flex-col gap-4",children:[!u&&i.jsx(MAe,{missionId:n.id,refreshKey:E}),i.jsxs(Ot,{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(rr,{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(Vr,{"aria-label":"Owner Team",value:f.ownerTeamId,onChange:G=>V("ownerTeamId",G.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(dr,{value:f.status,onChange:G=>V("status",G.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:Qb(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(dr,{value:f.priority,onChange:G=>V("priority",G.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:qA[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(Vr,{"aria-label":"Parent Mission ID",placeholder:"(none)",value:f.parentMissionId,onChange:G=>V("parentMissionId",G.target.value),fullWidth:!0,"data-testid":"edit-parent"}):n.parentMissionId?i.jsx("button",{type:"button",onClick:()=>e(`/missions/${n.parentMissionId}`),className:"text-left text-xs text-primary hover:underline truncate","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:K})]}),!u&&n.projectId&&i.jsxs("div",{className:"flex justify-between",children:[i.jsx("span",{className:"text-text-secondary-dark",children:"Project"}),i.jsx("button",{type:"button",onClick:()=>e(`/projects/${n.projectId}`),className:"text-xs text-primary hover:underline 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(Vr,{"aria-label":"Cadence",value:f.cadence,onChange:G=>V("cadence",G.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(Ot,{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(mA,{className:"h-4 w-4"}),"OKR Period"]}),u&&f?i.jsxs("div",{className:"space-y-2",children:[i.jsxs(dr,{value:f.periodType,onChange:G=>V("periodType",G.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(Vr,{type:"date","aria-label":"Period start",value:f.periodStart,onChange:G=>V("periodStart",G.target.value),fullWidth:!0,"data-testid":"edit-period-start"}),i.jsx(Vr,{type:"date","aria-label":"Period end",value:f.periodEnd,onChange:G=>V("periodEnd",G.target.value),fullWidth:!0,"data-testid":"edit-period-end"}),i.jsx(Vr,{"aria-label":"Period label",placeholder:"Label (optional)",value:f.periodLabel,onChange:G=>V("periodLabel",G.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:Kh(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:Kh(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(Ot,{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(mA,{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:Kh(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:Kh(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:Kh(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:Kh(n.nextReviewAt)})]})]})]}),!u&&n.activeProjectTaskIds.length>0&&i.jsxs(Ot,{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(fr,{className:"h-4 w-4"}),"Active Task IDs"]}),i.jsx("div",{className:"flex flex-wrap gap-1.5",children:n.activeProjectTaskIds.map(G=>i.jsx(tn,{variant:"default",size:"sm",children:G.slice(0,12)},G))})]})]})]})]})};J9.displayName="MissionDetail";function Sj(t){return{queued:"pending",scheduled:"paused",running:"running",blocked:"blocked",done:"completed",failed:"error",cancelled:"inactive"}[t]??"pending"}function wj(t){return{queued:"Queued",scheduled:"Scheduled",running:"Running",blocked:"Blocked",done:"Completed",failed:"Failed",cancelled:"Cancelled"}[t]??t}function kj(t){return{delegate:"primary",project_task:"info",check:"default",notify:"success",cron_run:"warning",review:"info",confirm:"warning",reconcile:"default"}[t]??"default"}function Cj(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 RAe(t){return{orchestrator:"Orchestrator",team_lead:"Team Lead",agent:"Agent",system:"System"}[t]??t}function DS(t){const e=Date.now(),n=new Date(t).getTime(),r=e-n,s=Math.floor(r/6e4),a=Math.floor(s/60),o=Math.floor(a/24);return s<1?"just now":s<60?`${s}m ago`:a<24?`${a}h ago`:`${o}d ago`}function Qm(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 Z9(t){return t===0?"—":t<.01?`$${t.toFixed(4)}`:`$${t.toFixed(2)}`}function Ag(t){return t===0?"—":t<1e3?t.toString():t<1e6?`${(t/1e3).toFixed(1)}K`:`${(t/1e6).toFixed(1)}M`}function Q9(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,r=t.cancelReason,s=typeof r=="string"&&r.length>0?`Cancelled: ${r}`:"Cancelled (no reason recorded).";e.push({id:`${t.id}-cancelled`,kind:"status_change",label:"CANCELLED",detail:s,timestamp:n,status:"cancelled"})}if(t.status==="blocked"){const n=t.blockedReason,r=typeof n=="string"&&n.length>0?`Blocked: ${n}`:"Blocked (no reason recorded).";e.push({id:`${t.id}-blocked`,kind:"status_change",label:"BLOCKED",detail:r,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,r)=>new Date(r.timestamp).getTime()-new Date(n.timestamp).getTime())}function IAe(t,e){if(t==="error")return Fl;if(t==="progress_update")return BF;if(t==="agent_reasoning"||t==="tool_action")return Js;switch(e){case"queued":return fr;case"running":return Js;case"done":return Wu;case"failed":return Fl;case"cancelled":return _K;case"blocked":return mp;default:return fr}}function PAe(t,e){if(t==="error")return"text-red-400";if(t==="progress_update")return"text-blue-400";switch(e){case"queued":return"text-gray-400";case"running":return"text-green-400";case"done":return"text-blue-400";case"failed":return"text-red-400";case"cancelled":return"text-gray-500";case"blocked":return"text-yellow-400";default:return"text-gray-400"}}function LAe(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 Ej=({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 r=IAe(e.kind,e.status),s=PAe(e.kind,e.status),a=LAe(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 ${s}`,children:i.jsx(r,{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 ${s}`,children:e.label}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:Qm(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)})});Ej.displayName="WorkItemTimeline";const Ma=({icon:t,label:e,value:n,valueClass:r="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 ${r}`,children:n})]}),e7=({item:t})=>{const e=DAe(t);return i.jsxs("div",{className:"space-y-4","data-testid":"workitem-metrics",children:[i.jsxs(Ot,{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(Ma,{icon:Yg,label:"Input Tokens",value:Ag(t.inputTokens)}),i.jsx(Ma,{icon:Yg,label:"Output Tokens",value:Ag(t.outputTokens)}),i.jsx(Ma,{icon:q2,label:"Cost",value:Z9(t.cost),valueClass:t.cost>0?"text-yellow-400":"text-text-primary-dark"})]})]}),i.jsxs(Ot,{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(Ma,{icon:zn,label:"Retries",value:`${t.retryCount} / ${t.maxRetries}`}),i.jsx(Ma,{icon:fr,label:"Duration",value:e}),i.jsx(Ma,{icon:Ku,label:"Owner",value:RAe(t.owner)}),t.target&&i.jsx(Ma,{icon:Mu,label:"Agent",value:t.target})]})]}),(t.requestId||t.missionId||t.projectTaskId||t.triggerId)&&i.jsxs(Ot,{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(Ma,{icon:Sl,label:"Request",value:Um(t.requestId)}),t.missionId&&i.jsx(Ma,{icon:Sl,label:"Mission",value:Um(t.missionId)}),t.projectTaskId&&i.jsx(Ma,{icon:Sl,label:"Project Task",value:Um(t.projectTaskId)}),t.triggerId&&i.jsx(Ma,{icon:Sl,label:"Trigger",value:Um(t.triggerId)}),t.parentWorkItemId&&i.jsx(Ma,{icon:Sl,label:"Parent Item",value:Um(t.parentWorkItemId)})]})]}),i.jsxs(Ot,{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:Qm(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:Qm(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:Qm(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:Qm(t.scheduledAt)})]})]})]})]})};e7.displayName="WorkItemMetrics";function DAe(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 r=n-e,s=Math.floor(r/1e3)%60,a=Math.floor(r/6e4)%60,o=Math.floor(r/36e5);return o>0?`${o}h ${a}m`:a>0?`${a}m ${s}s`:`${s}s`}function Um(t){return t.length<=12?t:`${t.slice(0,8)}...`}function OAe(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 BAe=({stats:t})=>t?i.jsxs(CM,{variant:"horizontal",className:"grid-cols-3 md:grid-cols-6","data-testid":"workitem-summary-bar",children:[i.jsx($s,{label:"Total",value:t.total}),i.jsx($s,{label:"Running",children:i.jsx("span",{className:"text-blue-400",children:t.running})}),i.jsx($s,{label:"Queued",children:i.jsx("span",{className:"text-yellow-400",children:t.queued})}),i.jsx($s,{label:"Done",children:i.jsx("span",{className:"text-green-400",children:t.done})}),i.jsx($s,{label:"Failed",children:i.jsx("span",{className:"text-red-400",children:t.failed})}),i.jsx($s,{label:"Blocked",children:i.jsx("span",{className:"text-orange-400",children:t.blocked})})]}):null,t7=()=>{const t=_r(),[e,n]=k.useState([]),[r,s]=k.useState(!0),[a,o]=k.useState(null),[l,c]=k.useState("all"),[d,u]=k.useState(""),[h,f]=k.useState(""),p=k.useRef(),x=k.useCallback(C=>{f(C),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{u(C)},300)},[]);k.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const y=k.useCallback(async()=>{s(!0),o(null);try{const C=await ft.getWorkItems();if(!Array.isArray(C)){console.warn("[WorkItems] getWorkItems returned non-array:",typeof C,C),n([]);return}n(C)}catch(C){console.warn("[WorkItems] loadItems error:",C),o(C instanceof Error?C.message:"Failed to load work items")}finally{s(!1)}},[]);k.useEffect(()=>{y()},[y]);const m=k.useMemo(()=>{let C=e;if(l!=="all"&&(C=C.filter(N=>N.status===l)),d.trim()){const N=d.toLowerCase();C=C.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 C.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=k.useMemo(()=>{const C={all:e.length};for(const E of e)C[E.status]=(C[E.status]||0)+1;return C},[e]),v=k.useMemo(()=>e.length>0?OAe(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=k.useCallback((C,E)=>{(C.key==="Enter"||C.key===" ")&&(C.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.jsxs("button",{onClick:y,disabled:r,className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark bg-surface-dark border border-border-dark rounded-lg transition-colors disabled:opacity-50","data-testid":"workitems-refresh",children:[i.jsx(zn,{className:`h-4 w-4 ${r?"animate-spin":""}`}),"Refresh"]})]}),i.jsx("p",{className:"text-sm text-text-secondary-dark",children:"Execution-level view of all system tasks in the task pool."})]}),!r&&i.jsx(BAe,{stats:v}),i.jsx(ld,{tabs:b.map(C=>({value:C.key,label:C.label,count:g[C.key]})),activeTab:l,onTabChange:C=>c(C),searchPlaceholder:"Search by title, ID, agent...",searchValue:h,onSearchChange:x}),r&&i.jsx("div",{"data-testid":"workitems-loading",children:i.jsx(LS,{count:4})}),a&&!r&&i.jsxs(Bt,{variant:"error",title:"Failed to load work items",onClose:()=>o(null),"data-testid":"workitems-error",children:[a,i.jsx(ze,{variant:"ghost",size:"sm",onClick:y,className:"mt-2",children:"Retry"})]}),!r&&!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(Vu,{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."})]}),!r&&!a&&m.length>0&&i.jsx("div",{className:"flex flex-col gap-2","data-testid":"workitems-list",children:m.map(C=>i.jsx(Ot,{variant:"default",padding:"md",interactive:!0,className:"hover:border-primary/40",role:"button",tabIndex:0,onClick:()=>t(`/workitems/${C.id}`),onKeyDown:E=>S(E,C.id),"data-testid":`workitem-row-${C.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:C.title})}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Wl,{status:Sj(C.status),children:wj(C.status)}),i.jsx(tn,{variant:kj(C.type),size:"sm",children:Cj(C.type)}),C.target&&i.jsx(tn,{variant:"default",size:"sm",children:C.target}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:DS(C.createdAt)})]})]}),i.jsx("span",{className:"text-xs text-text-secondary-dark font-mono flex-shrink-0",children:C.id.slice(0,8)})]})},C.id))})]})};t7.displayName="WorkItems";const n7=()=>{const{id:t}=Gu(),e=_r(),[n,r]=k.useState(null),[s,a]=k.useState(!0),[o,l]=k.useState(null),[c,d]=k.useState(!1),u=k.useCallback(async(x=!0)=>{if(t){x?a(!0):d(!0),l(null);try{const y=await ft.getWorkItem(t);r(y)}catch(y){const m=y instanceof Error?y.message:"Failed to load WorkItem";l(m)}finally{a(!1),d(!1)}}},[t]);k.useEffect(()=>{u(!0)},[u]),k.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(s)return i.jsx("div",{className:"flex items-center justify-center h-64","data-testid":"workitem-detail-loading",children:i.jsx(sr,{})});if(o)return i.jsxs("div",{className:"p-6","data-testid":"workitem-detail-error",children:[i.jsxs("button",{onClick:h,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to WorkItems"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"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("button",{onClick:()=>u(!0),className:"px-4 py-2 text-sm font-medium rounded-lg bg-primary/10 text-primary hover:bg-primary/20 transition-colors",children:"Retry"})]})})]});if(!n)return i.jsxs("div",{className:"p-6","data-testid":"workitem-detail-not-found",children:[i.jsxs("button",{onClick:h,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to WorkItems"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsx("p",{className:"text-center text-text-secondary-dark py-8",children:"WorkItem not found."})})]});const p=Q9(n);return i.jsxs("div",{className:"p-6 max-w-[1400px] mx-auto","data-testid":"workitem-detail",children:[i.jsxs("button",{onClick:h,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-4 transition-colors","data-testid":"workitem-detail-back",children:[i.jsx(Ua,{className:"h-4 w-4"}),"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: ",xE(n.id)," — ",n.title]})}),i.jsxs("button",{onClick:f,disabled:c,className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark bg-surface-dark border border-border-dark rounded-lg transition-colors disabled:opacity-50","data-testid":"workitem-detail-refresh",children:[i.jsx(zn,{className:`h-4 w-4 ${c?"animate-spin":""}`}),"Refresh"]})]}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Wl,{status:Sj(n.status),children:wj(n.status)}),i.jsx(tn,{variant:kj(n.type),children:Cj(n.type)}),i.jsxs(tn,{variant:"default",children:["Retry ",n.retryCount,"/",n.maxRetries]}),n.requestId&&i.jsx(tn,{variant:"info",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(Ps,{className:"h-3 w-3"}),"Request: ",xE(n.requestId)]})}),n.missionId&&i.jsx(tn,{variant:"info",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(Ps,{className:"h-3 w-3"}),"Mission: ",xE(n.missionId)]})}),i.jsxs("span",{className:"text-xs text-text-secondary-dark ml-2",children:["Created ",DS(n.createdAt)]}),n.target&&i.jsxs(tn,{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(Ot,{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(Ej,{events:p})]})}),i.jsx("div",{className:"lg:col-span-1",children:i.jsx(e7,{item:n})})]})]})};n7.displayName="WorkItemDetail";function xE(t){return t.length<=12?t:t.slice(0,8)}const FAe=({stats:t})=>t?i.jsxs(CM,{variant:"horizontal",className:"grid-cols-2 md:grid-cols-6","data-testid":"request-summary-bar",children:[i.jsx($s,{label:"Total Incoming",value:t.total}),i.jsx($s,{label:"Active",value:t.active}),i.jsx($s,{label:"Blocked",children:i.jsx("span",{className:"text-red-400",children:t.blocked})}),i.jsx($s,{label:"Waiting",children:i.jsx("span",{className:"text-yellow-400",children:t.waitingConfirmation})}),i.jsx($s,{label:"Done",children:i.jsx("span",{className:"text-blue-400",children:t.done})}),i.jsx($s,{label:"Total Cost",children:i.jsx("span",{className:"text-emerald-400",children:t.totalCost>0?`$${t.totalCost.toFixed(2)}`:"$0.00"})})]}):null;function UAe(t){return{active:"Active",blocked:"Blocked",waiting_confirmation:"Waiting Confirmation",done:"Done"}[t]??t}function zAe(t){return{critical:"error",high:"warning",medium:"info",low:"default"}[t]??"default"}function HAe(t){return{critical:"Critical",high:"High",medium:"Medium",low:"Low"}[t]??t}function GAe(t){return t.charAt(0).toUpperCase()+t.slice(1)}function WAe(t){const e=Date.now(),n=new Date(t).getTime(),r=e-n,s=Math.floor(r/6e4),a=Math.floor(s/60),o=Math.floor(a/24);return s<1?"just now":s<60?`${s}m ago`:a<24?`${a}h ago`:`${o}d ago`}function VAe(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 $Ae={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-indigo-500/10 text-indigo-300 border-indigo-500/20",done:"bg-green-500/10 text-green-400 border-green-500/20"},KAe={active:"bg-amber-400",blocked:"bg-red-400",waiting_confirmation:"bg-indigo-300",done:"bg-green-400"},qAe=({status:t,label:e,className:n=""})=>{const r=$Ae[t],s=KAe[t],a=e??UAe(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 ${r} ${n}`.trim(),"data-status":t,"data-testid":`request-status-pill-${t}`,children:[i.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${s} ${o?"animate-pulse":""}`.trim(),"aria-hidden":"true"}),a]})},XAe={slack:Ax,email:VF,chat:$F,api:zK,manual:qF},YAe=({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(Gc,{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(tn,{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})]})},JAe=({request:t})=>{const[e,n]=k.useState(!1),r=_r(),s=!!(t.childItems&&t.childItems.length>0),a=k.useCallback(()=>{r(`/tasks/${t.id}`)},[r,t.id]),o=k.useCallback(f=>{f.stopPropagation(),s&&n(p=>!p)},[s]),l=k.useCallback(f=>{f.key==="Enter"?(f.preventDefault(),a()):f.key===" "&&(f.preventDefault(),s&&n(p=>!p))},[a,s]),c=XAe[t.source]??Vu,d=zAe(t.priority),u=GAe(t.source),h=WAe(t.updatedAt);return i.jsx("li",{className:"list-none",children:i.jsxs(Ot,{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(qAe,{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(tn,{variant:d,size:"sm",children:HAe(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(Jg,{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})]})]}),s&&i.jsx("button",{onClick:o,className:"p-1 rounded hover:bg-surface-dark flex-shrink-0","aria-label":e?"Collapse work items":"Expand work items",children:e?i.jsx(ei,{className:"h-4 w-4 text-text-secondary-dark"}):i.jsx(Si,{className:"h-4 w-4 text-text-secondary-dark"})})]}),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(tn,{variant:"default",size:"sm",children:u}),t.ownerAgent&&i.jsxs("span",{className:"text-text-secondary-dark",children:["via ",t.ownerAgent]})]}),s&&i.jsx("div",{children:t.childItems.map(f=>i.jsx(YAe,{item:f},f.id))})]})]})})};function ZAe(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 QAe(t){switch(t){case"high":return"high";case"low":return"low";default:return"medium"}}function eTe(t){return t.map(e=>{const n=Array.isArray(e.workItemIds)?e.workItemIds:[],r=e.intentCategory;return{id:e.id||"",title:e.title||"Untitled Request",status:ZAe(e.status||""),priority:QAe(e.priority||""),source:(e.tags||[]).includes("slack")?"slack":"api",requester:"user",category:r&&r.length>0?r: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 tTe=new Set(["critical","high"]),nTe=({activeFilter:t,secondaryFilters:e,searchQuery:n,onStatsLoaded:r})=>{const[s,a]=k.useState([]),[o,l]=k.useState(!0),[c,d]=k.useState(null),u=k.useCallback(async()=>{l(!0),d(null);try{const p=await ft.getRequests();if(!Array.isArray(p)){console.warn("[RequestList] getRequests returned non-array:",typeof p,p),a([]);return}const x=eTe(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)}},[]);k.useEffect(()=>{u()},[u]);const h=k.useMemo(()=>VAe(s),[s]);k.useEffect(()=>{r(h)},[h,r]);const f=k.useMemo(()=>{let p=s;if(t!=="all"&&(p=p.filter(x=>x.status===t)),e&&e.size>0&&(e.has("urgent")&&(p=p.filter(x=>tTe.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},[s,t,e,n]);return o?i.jsx("div",{"data-testid":"request-list-loading",children:i.jsx(LS,{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("button",{onClick:u,className:"text-sm text-primary hover:underline",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(Vu,{className:"h-10 w-10 opacity-40"}),i.jsx("span",{className:"text-sm",children:s.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(JAe,{request:p},p.id))})},rTe=()=>{const[t,e]=k.useState(null),[n,r]=k.useState("active"),[s,a]=k.useState(new Set),[o,l]=k.useState(""),c=k.useCallback(f=>{e(f)},[]),d=k.useCallback(f=>{a(p=>{const x=new Set(p);return x.has(f)?x.delete(f):x.add(f),x})},[]),u=k.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=k.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(FAe,{stats:t}),i.jsx(ld,{tabs:u,activeTab:n,onTabChange:f=>r(f),searchPlaceholder:"Search requests...",searchValue:o,onSearchChange:l,secondaryFilters:h,activeSecondaryFilters:s,onSecondaryFilterToggle:f=>d(f)}),i.jsx(nTe,{activeFilter:n,secondaryFilters:s,searchQuery:o,onStatsLoaded:c})]})},p4={open:"text-blue-400",in_progress:"text-amber-400",blocked:"text-red-400",waiting_confirmation:"text-violet-400",done:"text-green-400",cancelled:"text-gray-400"};function KT(t){return{open:"Open",in_progress:"In Progress",blocked:"Blocked",waiting_confirmation:"Waiting Confirmation",done:"Completed",cancelled:"Cancelled"}[t]??t}function sTe(t){return{open:"active",in_progress:"running",blocked:"blocked",waiting_confirmation:"paused",done:"completed",cancelled:"inactive"}[t]??"pending"}const m4=["open","in_progress","done"],iTe=({currentStatus:t})=>{const e=m4.indexOf(t),n=t==="cancelled",r=t==="blocked";return i.jsxs("div",{className:"flex items-center gap-1","data-testid":"request-progress-rail",children:[m4.map((s,a)=>{const o=e>=0&&a<=e,l=s===t;return i.jsxs(Vn.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?`${p4[s]||"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(Wu,{className:"h-3 w-3"}),KT(s)]})]},s)}),(n||r)&&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 ${p4[t]||"text-gray-400"} bg-surface-dark border border-red-500/30`,children:KT(t)})]})]})},aTe=({workItems:t,onItemClick:e})=>{const[n,r]=k.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(Vu,{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(s=>{const a=n===s.id,o=a?Q9(s):[];return i.jsxs(Ot,{variant:"default",padding:"none",className:"overflow-hidden hover:border-primary/40 transition-colors","data-testid":`request-workitem-${s.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:()=>r(a?null:s.id),onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),r(a?null:s.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:s.title})}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i.jsx(Wl,{status:Sj(s.status),children:wj(s.status)}),i.jsx(tn,{variant:kj(s.type),size:"sm",children:Cj(s.type)}),s.target&&i.jsx(tn,{variant:"default",size:"sm",children:s.target}),i.jsx("span",{className:"text-xs text-text-secondary-dark",children:DS(s.createdAt)})]})]}),i.jsx("button",{onClick:l=>{l.stopPropagation(),e(s.id)},className:"px-2 py-1 text-xs text-primary hover:text-primary/80 hover:underline flex-shrink-0","data-testid":`request-workitem-detail-link-${s.id}`,children:"Details"})]}),a&&i.jsx("div",{className:"border-t border-border-dark px-4 py-3","data-testid":`request-workitem-timeline-${s.id}`,children:i.jsx(Ej,{events:o})})]},s.id)})})},r7=()=>{const{id:t}=Gu(),e=_r(),[n,r]=k.useState(null),[s,a]=k.useState([]),[o,l]=k.useState(!0),[c,d]=k.useState(null),[u,h]=k.useState(!1),f=k.useCallback(async(b=!0)=>{if(t){b?l(!0):h(!0),d(null);try{const[S,C]=await Promise.all([ft.getRequest(t),ft.getWorkItemsByRequest(t)]);r(S),a(C.sort((E,N)=>new Date(N.createdAt).getTime()-new Date(E.createdAt).getTime()))}catch(S){const C=S instanceof Error?S.message:"Failed to load request";d(C)}finally{l(!1),h(!1)}}},[t]);k.useEffect(()=>{f(!0)},[f]),k.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=k.useCallback(()=>{e("/tasks")},[e]),x=k.useCallback(b=>{e(`/workitems/${b}`)},[e]),y=k.useCallback(()=>{f(!1)},[f]),m=k.useCallback(async b=>{if(t)try{const S=b==="confirmed"?"done":"cancelled";await ft.updateRequest(t,{status:S}),f(!1)}catch(S){const C=S instanceof Error?S.message:"Failed to update request";d(C)}},[t,f]),g=k.useMemo(()=>n?n.totalInputTokens+n.totalOutputTokens:0,[n]),v=k.useMemo(()=>{if(!n)return"";const b=new Date(n.createdAt).getTime(),C=(n.completedAt?new Date(n.completedAt).getTime():Date.now())-b,E=Math.floor(C/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(sr,{})}):c?i.jsxs("div",{className:"p-6","data-testid":"request-detail-error",children:[i.jsxs("button",{onClick:p,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to Requests"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsxs("div",{className:"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("button",{onClick:()=>f(!0),className:"px-4 py-2 text-sm font-medium rounded-lg bg-primary/10 text-primary hover:bg-primary/20 transition-colors",children:"Retry"})]})})]}):n?i.jsxs("div",{className:"p-6 max-w-[1200px] mx-auto","data-testid":"request-detail",children:[i.jsxs("button",{onClick:p,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-4 transition-colors","data-testid":"request-detail-back",children:[i.jsx(Ua,{className:"h-4 w-4"}),"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.jsxs("button",{onClick:y,disabled:u,className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-text-secondary-dark hover:text-text-primary-dark bg-surface-dark border border-border-dark rounded-lg transition-colors disabled:opacity-50","data-testid":"request-detail-refresh",children:[i.jsx(zn,{className:`h-4 w-4 ${u?"animate-spin":""}`}),"Refresh"]})]}),i.jsxs("div",{className:"flex items-center gap-2 flex-wrap mb-4",children:[i.jsx(Wl,{status:sTe(n.status),children:KT(n.status)}),n.priority&&n.priority!=="normal"&&i.jsx(tn,{variant:n.priority==="high"?"warning":"default",size:"sm",children:n.priority.charAt(0).toUpperCase()+n.priority.slice(1)}),n.intentCategory&&i.jsx(tn,{variant:"info",size:"sm",children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(eU,{className:"h-3 w-3"}),n.intentCategory.replace(/_/g," ")]})}),n.intentLevel&&i.jsx(tn,{variant:"default",size:"sm",children:n.intentLevel}),n.requiresConfirmation&&i.jsx(tn,{variant:"warning",size:"sm",children:"Requires Confirmation"}),i.jsxs("span",{className:"text-xs text-text-secondary-dark ml-2",children:["Created ",DS(n.createdAt)]})]}),i.jsx(iTe,{currentStatus:n.status})]}),n.requiresConfirmation&&n.status==="waiting_confirmation"&&i.jsxs("div",{className:"flex gap-3 mt-4 p-4 bg-surface-dark rounded-lg border border-border-dark","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(ze,{variant:"secondary",size:"sm",onClick:()=>m("rejected"),children:"Reject"}),i.jsx(ze,{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(Ot,{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(Uo,{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(tn,{variant:"default",size:"sm",children:b},b))})]})}),i.jsx("div",{className:"lg:col-span-1",children:i.jsxs(Ot,{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(Yg,{className:"h-3.5 w-3.5"}),"Total Tokens"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:Ag(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:Ag(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:Ag(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(q2,{className:"h-3.5 w-3.5"}),"Total Cost"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:Z9(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(fr,{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(Jg,{className:"h-3.5 w-3.5"}),"Work Items"]}),i.jsx("span",{className:"text-sm font-medium text-text-primary-dark",children:s.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(Jg,{className:"h-4 w-4"}),"Execution Timeline (",s.length," work items)"]})}),i.jsx(aTe,{workItems:s,onItemClick:x})]})]}):i.jsxs("div",{className:"p-6","data-testid":"request-detail-not-found",children:[i.jsxs("button",{onClick:p,className:"flex items-center gap-2 text-sm text-text-secondary-dark hover:text-text-primary-dark mb-6 transition-colors",children:[i.jsx(Ua,{className:"h-4 w-4"}),"Back to Requests"]}),i.jsx(Ot,{variant:"default",padding:"lg",children:i.jsx("p",{className:"text-center text-text-secondary-dark py-8",children:"Request not found."})})]})};r7.displayName="RequestDetail";const oTe=({onSaved:t})=>{const[e,n]=k.useState(!1),[r,s]=k.useState(""),[a,o]=k.useState(!1);k.useEffect(()=>{const c=()=>{o(!!Lx()),n(!0)};return window.addEventListener(FA,c),()=>window.removeEventListener(FA,c)},[]);const l=k.useCallback(c=>{c.preventDefault();const d=r.trim();d&&(d6(d),n(!1),t?t():window.location.reload())},[r,t]);return e?i.jsx("div",{className:"fixed inset-0 z-[100] flex items-center justify-center bg-black/60",role:"dialog","aria-modal":"true","aria-label":"Access token required","data-testid":"api-token-prompt",children:i.jsxs("div",{className:"bg-surface-dark border border-border-dark rounded-xl shadow-2xl w-full max-w-md mx-4",children:[i.jsxs("div",{className:"flex items-center gap-2 px-5 py-4 border-b border-border-dark",children:[i.jsx(C1,{className:"w-4 h-4 text-text-secondary-dark"}),i.jsx("h3",{className:"text-sm font-semibold text-text-primary-dark",children:"Access token required"})]}),i.jsxs("form",{onSubmit:l,className:"px-5 py-4 space-y-4",children:[i.jsxs("p",{className:"text-xs 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.jsxs("div",{children:[i.jsx("label",{htmlFor:"api-token-input",className:"block text-xs font-medium text-text-secondary-dark mb-1.5",children:"Access token"}),i.jsx("input",{id:"api-token-input",type:"password",value:r,onChange:c=>s(c.target.value),placeholder:"paste token",autoComplete:"off",autoFocus:!0,className:"w-full px-3 py-2 text-xs font-mono text-text-primary-dark bg-background-dark border border-border-dark rounded-lg placeholder:text-text-secondary-dark/40 focus:outline-none focus:ring-1 focus:ring-primary/50 focus:border-primary/50","data-testid":"api-token-input"})]}),i.jsx("div",{className:"flex justify-end",children:i.jsx("button",{type:"submit",disabled:!r.trim(),className:"px-3 py-1.5 text-xs font-medium rounded-lg bg-primary text-white disabled:opacity-50","data-testid":"api-token-submit",children:"Save and reload"})})]})]})}):null};function lTe(t=cg.PENDING_POLL_INTERVAL_MS){const[e,n]=k.useState([]),[r,s]=k.useState(!0),a=k.useRef(!0),o=k.useCallback(async()=>{try{const l=await Ye.get(cg.PENDING_ENDPOINT,{timeout:cg.PENDING_REQUEST_TIMEOUT_MS});if(!a.current)return;l.data.success&&Array.isArray(l.data.data)&&n(l.data.data)}catch{}finally{a.current&&s(!1)}},[]);return k.useEffect(()=>{a.current=!0,o();const l=setInterval(()=>{o()},t);return()=>{a.current=!1,clearInterval(l)}},[o,t]),{pending:e,isLoading:r,refresh:o}}function cTe(t){return t.map(e=>`${e.sessionName}|${e.url??""}|${e.code??""}`).sort().join(";")}const dTe=()=>{const{pending:t,isLoading:e}=lTe(),[n,r]=k.useState(null),s=k.useMemo(()=>cTe(t),[t]);return e||t.length===0||n===s?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(C1,{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(O1,{loginRequired:a,agentLabel:a.sessionName})]},a.sessionName))})]}),i.jsx("button",{type:"button",onClick:()=>r(s),className:"shrink-0 p-1 rounded-md text-amber-300 hover:bg-amber-500/20 transition-colors","aria-label":"Dismiss sign-in banner",children:i.jsx(On,{size:16})})]})};function uTe(){const{id:t}=Gu();return i.jsx(Zv,{to:`/tasks/${t??""}`,replace:!0})}function hTe(){return i.jsx(aY,{children:i.jsx(qJ,{children:i.jsx(xY,{children:i.jsxs(XK,{children:[i.jsx(oTe,{}),i.jsx(dTe,{}),i.jsx(dK,{children:i.jsxs(tK,{children:[i.jsx(Fn,{path:"/auth/callback",element:i.jsx(WEe,{})}),i.jsx(Fn,{path:"/auth",element:i.jsx($Ee,{})}),i.jsxs(Fn,{path:"/",element:i.jsx(YJ,{}),children:[i.jsx(Fn,{index:!0,element:i.jsx(tZ,{})}),i.jsx(Fn,{path:"projects",element:i.jsx(iZ,{})}),i.jsx(Fn,{path:"projects/:id",element:i.jsx(ZZ,{})}),i.jsx(Fn,{path:"teams",element:i.jsx(wQ,{})}),i.jsx(Fn,{path:"teams/:id",element:i.jsx(iee,{})}),i.jsx(Fn,{path:"assignments",element:i.jsx(hee,{})}),i.jsx(Fn,{path:"scheduled-checkins",element:i.jsx(vee,{})}),i.jsx(Fn,{path:"triggers",element:i.jsx(Nee,{})}),i.jsx(Fn,{path:"factory",element:i.jsx(lme,{})}),i.jsx(Fn,{path:"marketplace",element:i.jsx(r0e,{})}),i.jsx(Fn,{path:"marketplace/:id",element:i.jsx(a0e,{})}),i.jsx(Fn,{path:"wiki",element:i.jsx(VCe,{})}),i.jsx(Fn,{path:"security",element:i.jsx($9,{})}),i.jsx(Fn,{path:"monitoring/costs",element:i.jsx(c4,{})}),i.jsx(Fn,{path:"usage",element:i.jsx(c4,{})}),i.jsx(Fn,{path:"settings",element:i.jsx(gge,{})}),i.jsx(Fn,{path:"pricing",element:i.jsx(XEe,{})}),i.jsx(Fn,{path:"cloud",element:i.jsx(fAe,{})}),i.jsx(Fn,{path:"tasks",element:i.jsx(rTe,{})}),i.jsx(Fn,{path:"tasks/:id",element:i.jsx(r7,{})}),i.jsx(Fn,{path:"requests",element:i.jsx(Zv,{to:"/tasks",replace:!0})}),i.jsx(Fn,{path:"requests/:id",element:i.jsx(uTe,{})}),i.jsx(Fn,{path:"missions",element:i.jsx(X9,{})}),i.jsx(Fn,{path:"missions/:id",element:i.jsx(J9,{})}),i.jsx(Fn,{path:"workitems",element:i.jsx(t7,{})}),i.jsx(Fn,{path:"workitems/:id",element:i.jsx(n7,{})}),i.jsx(Fn,{path:"team-chat",element:i.jsx(Vxe,{})}),i.jsx(Fn,{path:"chat",element:i.jsx(Zv,{to:"/team-chat",replace:!0})}),i.jsx(Fn,{path:"agents",element:i.jsx(Zv,{to:"/team-chat",replace:!0})})]})]})})]})})})})}wJ();yE.createRoot(document.getElementById("root")).render(i.jsx(Vn.StrictMode,{children:i.jsx(hTe,{})}));
|
|
4961
|
-
//# sourceMappingURL=index-
|
|
4961
|
+
//# sourceMappingURL=index-f761b08d.js.map
|