clustr-ai 0.1.27 → 0.1.28
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.
|
@@ -108,4 +108,4 @@ WARNING: This link could potentially be dangerous`)){const _=window.open();if(_)
|
|
|
108
108
|
`)):M.write(`\r
|
|
109
109
|
\x1B[31mFailed to upload image\x1B[0m\r
|
|
110
110
|
`)},A=Y=>{var ae,X;const Z=(ae=Y.clipboardData)==null?void 0:ae.items;if(!Z)return;for(const H of Z)if(H.type.startsWith("image/")){Y.preventDefault(),Y.stopPropagation();const re=H.getAsFile();re&&U(re);return}const ie=(X=Y.clipboardData)==null?void 0:X.getData("text/plain");if(ie){Y.preventDefault(),Y.stopPropagation();const H=ie.replace(/\r\n|\r|\n/g," ");f.emit("agent:input",K,H)}},I=Y=>{var Z,ie;(ie=(Z=Y.dataTransfer)==null?void 0:Z.types)!=null&&ie.includes("Files")&&(Y.preventDefault(),Y.stopPropagation())},P=Y=>{var ie;const Z=(ie=Y.dataTransfer)==null?void 0:ie.files;if(!(!Z||Z.length===0)){for(const ae of Z)if(ae.type.startsWith("image/")){Y.preventDefault(),Y.stopPropagation(),U(ae);return}}};q==null||q.addEventListener("paste",A,!0),q==null||q.addEventListener("dragover",I,!0),q==null||q.addEventListener("drop",P,!0);const j=()=>{f.off(F,B),O.dispose(),V.disconnect(),q==null||q.removeEventListener("paste",A,!0),q==null||q.removeEventListener("dragover",I,!0),q==null||q.removeEventListener("drop",P,!0)};w.set(D.id,{term:M,fit:W,cleanup:j})}return()=>{var D;for(const[,L]of w)(D=L.cleanup)==null||D.call(L),L.term.dispose();w.clear()}},[c.map(f=>f.id).join(","),r.current]);const b=Q.useCallback(f=>{a(f.id);const d=o.current.get(f.id);d&&d.term.focus(),i==null||i(f)},[i]),C=Q.useCallback((f,d)=>{if(!S.current)return;const w=S.current.offsetWidth,k=d/w*100;p(R=>{const D=[...R],L=10,M=D[f]+k,W=D[f+1]-k;return M>=L&&W>=L&&(D[f]=M,D[f+1]=W),D})},[]),u=c.length;if(u===0)return N.jsxs("div",{className:"multi-term-empty",children:[N.jsx("div",{className:"multi-term-empty-icon",children:"_"}),N.jsx("div",{className:"multi-term-empty-text",children:"No running agents"})]});const _=l.length===u?l:Array(u).fill(100/u);return N.jsx("div",{className:"multi-term-container",ref:S,children:c.map((f,d)=>N.jsxs($u.Fragment,{children:[N.jsxs("div",{className:`multi-term-pane ${y===f.id?"focused":""}`,style:{flexBasis:`${_[d]}%`},onClick:()=>b(f),onPointerDownCapture:()=>b(f),children:[N.jsxs("div",{className:"multi-term-pane-header",children:[N.jsx("span",{className:"multi-term-status-dot",style:{background:Zb(f.status)}}),N.jsx("span",{className:"multi-term-pane-name",children:f.name}),N.jsx("span",{className:"multi-term-pane-task",children:f.task})]}),N.jsx("div",{className:"multi-term-pane-body",ref:x(f.id)})]}),d<u-1&&N.jsx(eE,{orientation:"horizontal",onDrag:w=>C(d,w)})]},f.id))})}function rE({agent:e,socket:r,onClose:i}){const o=Q.useRef(null),h=Q.useRef(null),S=Q.useRef(null),y=Q.useRef(null),a=Q.useRef(!1),l=()=>{if(h.current||!o.current||a.current)return;a.current=!0;const p=new dh.Terminal({theme:{background:"#050505",foreground:"#c7c7c7",cursor:"#f5f5f5",cursorAccent:"#050505",selectionBackground:"rgba(255, 255, 255, 0.14)",black:"#0a0a0a",red:"#f87171",green:"#4ade80",yellow:"#fbbf24",blue:"#93c5fd",magenta:"#c4b5fd",cyan:"#67e8f9",white:"#c7c7c7",brightBlack:"#555555",brightRed:"#fca5a5",brightGreen:"#86efac",brightYellow:"#fde68a",brightBlue:"#bfdbfe",brightMagenta:"#ddd6fe",brightCyan:"#a5f3fc",brightWhite:"#f5f5f5"},fontSize:12,fontFamily:'"JetBrains Mono", "SF Mono", "Fira Code", "Cascadia Code", monospace',lineHeight:1.25,cursorBlink:!0,cursorStyle:"bar",cursorWidth:1,scrollback:8e3,allowProposedApi:!0,minimumContrastRatio:1,drawBoldTextInBrightColors:!0}),v=new fh.FitAddon;p.loadAddon(v);try{const c=new _h;p.loadAddon(c),p.unicode.activeVersion="11"}catch{}try{p.loadAddon(new gh)}catch{}p.open(o.current);try{v.fit()}catch{}h.current=p,S.current=v};return Q.useEffect(()=>{l();const p=o.current;if(!p)return;const v=new ResizeObserver(()=>{var x;try{(x=S.current)==null||x.fit()}catch{}const c=y.current,m=h.current;c&&m&&r.current&&r.current.emit("user-shell:resize",c,m.cols,m.rows)});return v.observe(p),()=>{var c;v.disconnect(),(c=h.current)==null||c.dispose(),h.current=null,S.current=null,a.current=!1}},[]),Q.useEffect(()=>{var C;l();const p=h.current,v=r.current;if(!e||!p||!v){y.current=null;return}const c=y.current;y.current=e.id,c!==e.id&&p.write("\x1B[2J\x1B[3J\x1B[H"),Vt(`/api/agents/${e.id}/user-shell/start`,{method:"POST"}).then(u=>u.ok?u.json():u.json().then(_=>Promise.reject(_))).then(u=>{y.current===e.id&&(u!=null&&u.cwd)&&p.writeln(`\x1B[90mUser shell cwd: ${u.cwd}\x1B[0m`)}).catch(u=>{y.current===e.id&&p.writeln(`\x1B[31mFailed to start user shell: ${(u==null?void 0:u.error)||(u==null?void 0:u.message)||"unknown error"}\x1B[0m`)}),Vt(`/api/agents/${e.id}/user-shell/scrollback`).then(u=>u.ok?u.json():null).then(u=>{u!=null&&u.scrollback&&y.current===e.id&&p&&(p.write(u.scrollback),p.scrollToBottom())}).catch(()=>{});const m=`user-shell:pty:${e.id}`,x=u=>{if(y.current===e.id&&p){const _=p.buffer.active,f=_.viewportY>=_.baseY-1;p.write(u),f&&p.scrollToBottom()}};v.on(m,x);const b=p.onData(u=>{v.emit("user-shell:input",e.id,u)});try{(C=S.current)==null||C.fit(),v.emit("user-shell:resize",e.id,p.cols,p.rows)}catch{}return p.focus(),()=>{v.off(m,x),b.dispose()}},[e,r]),N.jsxs("section",{className:"user-shell-panel",children:[N.jsxs("header",{className:"user-shell-header",children:[N.jsxs("div",{children:[N.jsx("span",{className:"user-shell-title",children:"User Shell"}),N.jsx("span",{className:"user-shell-subtitle",children:e!=null&&e.name?`${e.name}${e.agent_cwd?` · ${e.agent_cwd}`:""}`:"Select an agent"})]}),N.jsx("button",{className:"user-shell-close",onClick:i,title:"Close user shell",children:"Close"})]}),N.jsx("div",{className:"user-shell-terminal",ref:o,onClick:()=>{var p;return(p=h.current)==null?void 0:p.focus()},onPointerDownCapture:()=>{var p;return(p=h.current)==null?void 0:p.focus()}})]})}const nE=["all","error","warn","info","debug"],Xa="ERROR|FATAL|WARN|WARNING|INFO|DEBUG|TRACE",Sm=String.raw`\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:[,.]\d+)?(?:Z|[+-]\d{2}:?\d{2})?`,iE=new RegExp(String.raw`^\[([^\]]+)\]\s*(${Xa})\s*(\[[^\]]*\])?\s*(.*)$`,"i"),sE=new RegExp(String.raw`^(${Sm})\s+-\s+([^\s]+)\s+-\s+(${Xa})\s+-\s*(.*)$`,"i"),oE=new RegExp(String.raw`^(${Sm})\s+\[?(${Xa})\]?\s*(\[[^\]]*\])?\s*(.*)$`,"i"),aE=new RegExp(String.raw`^(${Xa}):\s*(.*)$`,"i"),lE=/^([A-Za-z_][\w.-]*(?:\.[\w.-]+)+):\s*(.*)$/,cE=/^(module=[^:\s]+):\s*(.*)$/i,uE=/\b(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\s+["/][^"]*\s+HTTP\/\d(?:\.\d)?"?\s+\d{3}\b/i,hE=/\b(uvicorn|fastapi|django|flask|gunicorn|werkzeug|localhost|127\.0\.0\.1|0\.0\.0\.0|listening|started server|application startup|traceback|exception|module=)\b/i;function dE(e){return e==="all"?"All levels":e.toUpperCase()}function fE(e){return`agent-log-level ${e}`}function la(e){const r=e.toLowerCase();return r==="fatal"?"error":r==="warning"?"warn":r==="trace"?"debug":r}function pu(e){var i;const r=e.match(/\d{2}:\d{2}:\d{2}(?:[,.]\d+)?/);return((i=r==null?void 0:r[0])==null?void 0:i.replace(",","."))??e}function u_(e){return(e==null?void 0:e.replace(/^\[|\]$/g,"").trim())||void 0}function Cm(e){return e.replace(/^\s*[⎿│┃┆┊]\s?/,"").replace(/^\s{2,}(?=\[?\d{4}-\d{2}-\d{2}|(?:DEBUG|INFO|WARN|WARNING|ERROR|TRACE|FATAL)\b|module=)/i,"").trim()}function _u(e){const r=e.match(cE);if(r)return{context:r[1],message:r[2]};const i=e.match(lE);return i?{context:i[1],message:i[2]}:{message:e}}function xm(e){const r=Cm(e),i=r.match(sE);if(i){const[,y,a,l,p]=i;return{timestamp:pu(y),level:la(l),context:a,message:p}}const o=r.match(iE);if(o){const[,y,a,l,p]=o,v=_u(p);return{timestamp:pu(y),level:la(a),context:v.context??u_(l),message:v.message}}const h=r.match(oE);if(h){const[,y,a,l,p]=h,v=_u(p);return{timestamp:pu(y),level:la(a),context:u_(l)??v.context,message:v.message}}const S=r.match(aE);if(S){const[,y,a]=S,l=_u(a);return{level:la(y),context:l.context,message:l.message}}return{message:r}}function pE(e){const r=Cm(e.text),i=xm(r);return!!(i.timestamp||i.context||uE.test(r)||hE.test(r))}function h_(e,r){const i=new Map;for(const o of[...e,...r])i.set(o.id,o);return[...i.values()].sort((o,h)=>o.id-h.id).slice(-2e3)}function _E(e){return e>0?"No logs match the current filters.":"No server-like output found in this agent terminal yet. Turn off Server only to see raw agent terminal logs."}function gE({agents:e,selectedAgent:r,socket:i,onSelectAgent:o}){const[h,S]=Q.useState([]),[y,a]=Q.useState(""),[l,p]=Q.useState("all"),[v,c]=Q.useState(!0),[m,x]=Q.useState(!0),b=Q.useRef(null),C=Q.useMemo(()=>e.filter(w=>w.status!=="dead"),[e]),u=r??C[0]??null;Q.useEffect(()=>{if(!u){S([]);return}let w=!1;return S([]),Vt(`/api/agents/${u.id}/logs?source=agent`).then(k=>k.ok?k.json():null).then(k=>{if(w)return;const R=Array.isArray(k==null?void 0:k.logs)?k.logs:[];S(D=>h_(R,D))}).catch(()=>{w||S([])}),()=>{w=!0}},[u==null?void 0:u.id]),Q.useEffect(()=>{const w=i.current;if(!w||!u)return;const k=`agent:logs:${u.id}`,R=D=>{D.source==="agent"&&S(L=>h_(L,[D]))};return w.on(k,R),()=>{w.off(k,R)}},[u==null?void 0:u.id,i]);const _=Q.useMemo(()=>{const w=y.trim().toLowerCase();return h.filter(k=>l!=="all"&&k.level!==l||v&&!pE(k)?!1:w?k.text.toLowerCase().includes(w):!0)},[h,l,y,v]);Q.useEffect(()=>{var w;m&&((w=b.current)==null||w.scrollIntoView({block:"end"}))},[_,m]);const f=w=>{const k=e.find(R=>R.id===w);k&&o(k)},d=_E(h.length);return N.jsxs("div",{className:"agent-logs",children:[N.jsxs("div",{className:"agent-logs-header",children:[N.jsxs("div",{className:"agent-logs-title",children:[N.jsxs("div",{children:[N.jsx("span",{children:"Server Logs"}),N.jsx("span",{className:"agent-logs-subtitle",children:"Agent terminal stream"})]}),N.jsxs("span",{className:"agent-logs-count",children:[_.length,"/",h.length]})]}),N.jsxs("div",{className:"agent-logs-controls",children:[N.jsxs("select",{value:(u==null?void 0:u.id)??"",onChange:w=>f(w.target.value),disabled:C.length===0,"aria-label":"Select agent logs",children:[C.length===0&&N.jsx("option",{value:"",children:"No agents"}),C.map(w=>N.jsx("option",{value:w.id,children:w.name},w.id))]}),N.jsx("select",{value:l,onChange:w=>p(w.target.value),"aria-label":"Filter log level",children:nE.map(w=>N.jsx("option",{value:w,children:dE(w)},w))}),N.jsx("input",{value:y,onChange:w=>a(w.target.value),placeholder:"Search logs...","aria-label":"Search logs"}),N.jsxs("label",{className:"agent-logs-autoscroll",children:[N.jsx("input",{type:"checkbox",checked:v,onChange:w=>c(w.target.checked)}),"Server only"]}),N.jsxs("label",{className:"agent-logs-autoscroll",children:[N.jsx("input",{type:"checkbox",checked:m,onChange:w=>x(w.target.checked)}),"Auto-scroll"]}),N.jsx("button",{onClick:()=>S([]),disabled:h.length===0,children:"Clear View"})]})]}),N.jsxs("div",{className:"agent-logs-list",children:[!u&&N.jsx("div",{className:"agent-logs-empty",children:"Spawn an agent and run a server command. Logs from Claude/Codex terminal output will appear here."}),u&&_.length===0&&N.jsx("div",{className:"agent-logs-empty",children:d}),_.map(w=>{const k=xm(w.text),R=k.level??w.level,D=k.timestamp??new Date(w.timestamp).toLocaleTimeString(),L=k.context||w.stream;return N.jsxs("div",{className:`agent-log-row ${R}`,children:[N.jsx("span",{className:"agent-log-time",children:D}),N.jsx("span",{className:fE(R),children:R}),N.jsxs("span",{className:"agent-log-text",children:[L&&N.jsx("span",{className:`agent-log-source ${w.stream??"stdout"}`,children:L}),N.jsx("span",{className:"agent-log-message",children:k.message})]})]},w.id)}),N.jsx("div",{ref:b})]})]})}function mE({messages:e,agents:r,selectedAgentId:i,onClear:o}){const h=Q.useRef(null),S=Q.useMemo(()=>{const a={user:"User"};return r.forEach(l=>{a[l.id]=l.name}),a},[r]),y=Q.useMemo(()=>i?e.filter(a=>a.from_agent===i||a.to_agent===i):e,[e,i]);return Q.useEffect(()=>{var a;(a=h.current)==null||a.scrollIntoView({behavior:"smooth"})},[y]),N.jsxs("div",{className:"message-feed",children:[N.jsxs("div",{className:"message-feed-header",children:[N.jsx("span",{children:i?`Messages for ${S[i]||i}`:"All Messages"}),y.length>0&&N.jsx("button",{className:"clear-messages-btn",onClick:o,children:"Clear All"})]}),N.jsxs("div",{className:"message-feed-list",children:[y.length===0&&N.jsx("div",{className:"message-feed-empty",children:"No messages yet"}),[...y].reverse().map(a=>N.jsxs("div",{className:"message-item",children:[N.jsxs("div",{className:"message-meta",children:[N.jsx("span",{className:"message-from",children:S[a.from_agent]||a.from_agent.slice(0,8)}),N.jsx("span",{className:"message-arrow",children:" → "}),N.jsx("span",{className:"message-to",children:a.to_agent==="all"?"All":S[a.to_agent]||a.to_agent.slice(0,8)}),N.jsx("span",{className:"message-time",children:new Date(a.created_at).toLocaleTimeString()})]}),N.jsx("div",{className:"message-content",children:a.content})]},a.id)),N.jsx("div",{ref:h})]})]})}function vE({entries:e,onRemove:r}){return N.jsxs("div",{className:"context-viewer",children:[N.jsx("div",{className:"context-header",children:"Shared Context"}),e.length===0&&N.jsx("div",{className:"context-empty",children:"No context entries yet"}),N.jsxs("table",{className:"context-table",children:[N.jsx("thead",{children:N.jsxs("tr",{children:[N.jsx("th",{children:"Key"}),N.jsx("th",{children:"Value"}),N.jsx("th",{children:"Updated By"}),N.jsx("th",{children:"Updated At"}),N.jsx("th",{})]})}),N.jsx("tbody",{children:e.map(i=>N.jsxs("tr",{children:[N.jsx("td",{className:"context-key",children:i.key}),N.jsx("td",{className:"context-value",children:i.value}),N.jsx("td",{children:i.updated_by||"—"}),N.jsx("td",{className:"context-time",children:i.updated_at?new Date(i.updated_at).toLocaleTimeString():"—"}),N.jsx("td",{children:N.jsx("button",{className:"context-remove-btn",onClick:()=>r(i.key),title:`Remove "${i.key}"`,children:"✕"})})]},i.key))})]})]})}function yE({diff:e,fileName:r}){const i=e.split(`
|
|
111
|
-
`);return N.jsxs("div",{className:"diff-viewer",children:[r&&N.jsx("div",{className:"diff-filename",children:r}),N.jsx("pre",{className:"diff-content",children:i.map((o,h)=>{let S="diff-line";return o.startsWith("+")&&!o.startsWith("+++")?S+=" diff-add":o.startsWith("-")&&!o.startsWith("---")?S+=" diff-del":o.startsWith("@@")?S+=" diff-hunk":o.startsWith("\\")&&(S+=" diff-meta"),N.jsx("div",{className:S,children:o},h)})})]})}function wE(e){switch(e){case"add":return"A";case"change":return"M";case"unlink":return"D";default:return"?"}}function SE(e){switch(e){case"add":return"#4ade80";case"change":return"#fbbf24";case"unlink":return"#f87171";default:return"#666"}}function CE({changes:e,agents:r,onClear:i}){const[o,h]=Q.useState(null),S=Q.useMemo(()=>{const y=new Map;for(const a of r)y.set(a.id,a.name);return y},[r]);return N.jsxs("div",{className:"file-changes",children:[N.jsxs("div",{className:"file-changes-header",children:[N.jsxs("span",{children:["File Changes (",e.length,")"]}),e.length>0&&N.jsx("button",{className:"file-changes-clear-btn",onClick:i,children:"Clear"})]}),N.jsxs("div",{className:"file-changes-list",children:[e.length===0&&N.jsx("div",{className:"file-changes-empty",children:"No file changes detected yet. Changes will appear here as agents edit files."}),e.map(y=>{const a=y.agent_id?S.get(y.agent_id):null;return N.jsxs("div",{className:"file-change-item",children:[N.jsxs("div",{className:"file-change-row",onClick:()=>h(o===y.id?null:y.id),children:[N.jsx("span",{className:"file-change-type",style:{color:SE(y.change_type)},children:wE(y.change_type)}),N.jsx("span",{className:"file-change-path",children:y.file_path}),a&&N.jsx("span",{className:"file-change-agent",title:"Agent that made this change",children:a}),N.jsx("span",{className:"file-change-time",children:new Date(y.created_at).toLocaleTimeString()}),N.jsx("span",{className:"file-change-expand",children:y.diff_text?o===y.id?"▼":"▶":""})]}),o===y.id&&y.diff_text&&N.jsx(yE,{diff:y.diff_text})]},y.id)})]})]})}function ca(e){const r=Date.now()-new Date(e).getTime(),i=Math.floor(r/6e4);if(i<1)return"just now";if(i<60)return`${i}m ago`;const o=Math.floor(i/60);if(o<24)return`${o}h ago`;const h=Math.floor(o/24);return h<30?`${h}d ago`:`${Math.floor(h/30)}mo ago`}function xE(e){return!e||e.length===0?{icon:"",cls:""}:e.some(o=>o.conclusion==="FAILURE"||o.conclusion==="failure")?{icon:"✗",cls:"failure"}:e.some(o=>!o.conclusion||o.status==="IN_PROGRESS"||o.status==="QUEUED")?{icon:"○",cls:"pending"}:{icon:"✓",cls:"success"}}function bE(e){switch(e){case"APPROVED":return{text:"Approved",cls:"approved"};case"CHANGES_REQUESTED":return{text:"Changes",cls:"changes_requested"};case"REVIEW_REQUIRED":return{text:"Review",cls:"review_required"};default:return null}}function EE({prs:e,branches:r,currentBranch:i,ghAvailable:o,repoInfo:h,agents:S,fetchPRDetail:y}){const[a,l]=Q.useState("all"),[p,v]=Q.useState(null),[c,m]=Q.useState(null),[x,b]=Q.useState(!1),[C,u]=Q.useState(!0),_=Q.useMemo(()=>a==="all"?e:e.filter(k=>k.state.toUpperCase()===a.toUpperCase()),[e,a]),f=Q.useMemo(()=>new Set(S.map(k=>k.name.toLowerCase())),[S]),d=async k=>{if(p===k){v(null),m(null);return}v(k),m(null),b(!0);const R=await y(k);m(R),b(!1)},w=k=>{const R=k.name.toLowerCase();for(const L of f)if(R.includes(L))return L;const D=k.author.toLowerCase();for(const L of f)if(D.includes(L))return L;return null};return N.jsxs("div",{className:"prs-tab",children:[N.jsxs("div",{className:"prs-header",children:[N.jsxs("div",{className:"prs-header-left",children:[N.jsxs("span",{children:["Pull Requests (",_.length,")"]}),N.jsxs("select",{className:"prs-filter",value:a,onChange:k=>l(k.target.value),children:[N.jsx("option",{value:"all",children:"All"}),N.jsx("option",{value:"open",children:"Open"}),N.jsx("option",{value:"closed",children:"Closed"}),N.jsx("option",{value:"merged",children:"Merged"})]})]}),h&&N.jsx("a",{className:"prs-repo-link",href:h.url,target:"_blank",rel:"noopener noreferrer",onClick:k=>{k.preventDefault(),window.open(h.url,"_blank")},children:h.nameWithOwner})]}),N.jsxs("div",{className:"prs-list",children:[o===!1&&N.jsxs("div",{className:"prs-unavailable",children:["GitHub CLI not available.",N.jsx("br",{}),"Install ",N.jsx("code",{children:"gh"})," and run ",N.jsx("code",{children:"gh auth login"})," to see PRs."]}),o!==!1&&_.length===0&&N.jsx("div",{className:"prs-empty",children:"No pull requests found."}),_.map(k=>{const R=k.isDraft?"draft":k.state.toLowerCase(),D=xE(k.statusCheckRollup),L=bE(k.reviewDecision),M=p===k.number;return N.jsxs("div",{className:"pr-item",children:[N.jsxs("div",{className:"pr-row",onClick:()=>d(k.number),children:[N.jsx("span",{className:"pr-expand",children:M?"▼":"▶"}),N.jsx("span",{className:`pr-status-badge ${R}`}),N.jsxs("span",{className:"pr-number",children:["#",k.number]}),N.jsx("span",{className:"pr-title",children:k.title}),L&&N.jsx("span",{className:`pr-review ${L.cls}`,children:L.text}),D.icon&&N.jsx("span",{className:`pr-ci ${D.cls}`,children:D.icon}),N.jsx("span",{className:"pr-branch",title:k.headRefName,children:k.headRefName}),N.jsx("span",{className:"pr-author",children:k.author.login}),N.jsx("span",{className:"pr-time",children:ca(k.createdAt)}),N.jsx("button",{className:"pr-link-btn",title:"Open in GitHub",onClick:W=>{W.stopPropagation(),window.open(k.url,"_blank")},children:"↗"})]}),M&&N.jsxs("div",{className:"pr-detail",children:[x&&N.jsx("div",{className:"pr-detail-loading",children:"Loading..."}),c&&c.number===k.number&&N.jsxs(N.Fragment,{children:[c.body&&N.jsx("div",{className:"pr-detail-body",children:c.body}),c.statusCheckRollup&&c.statusCheckRollup.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Checks"}),N.jsx("div",{className:"pr-detail-checks",children:c.statusCheckRollup.map((W,z)=>{var F,B,O,V;return N.jsxs("span",{className:`pr-check ${((F=W.conclusion)==null?void 0:F.toLowerCase())==="success"?"success":((B=W.conclusion)==null?void 0:B.toLowerCase())==="failure"?"failure":"pending"}`,children:[((O=W.conclusion)==null?void 0:O.toLowerCase())==="success"?"✓":((V=W.conclusion)==null?void 0:V.toLowerCase())==="failure"?"✗":"○"," ",W.name]},z)})})]}),c.reviews&&c.reviews.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Reviews"}),c.reviews.map((W,z)=>N.jsxs("div",{className:"pr-comment",children:[N.jsxs("div",{className:"pr-comment-header",children:[N.jsx("strong",{children:W.author.login})," ",W.state.toLowerCase().replace("_"," ")," ",ca(W.submittedAt)]}),W.body&&N.jsx("div",{className:"pr-comment-body",children:W.body})]},z))]}),c.comments&&c.comments.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Comments"}),c.comments.map((W,z)=>N.jsxs("div",{className:"pr-comment",children:[N.jsxs("div",{className:"pr-comment-header",children:[N.jsx("strong",{children:W.author.login})," ",ca(W.createdAt)]}),N.jsx("div",{className:"pr-comment-body",children:W.body})]},z))]}),(!c.reviews||c.reviews.length===0)&&(!c.comments||c.comments.length===0)&&!c.body&&N.jsx("div",{className:"pr-detail-loading",children:"No details available."})]})]})]},k.number)})]}),N.jsxs("div",{className:"branches-section",children:[N.jsxs("div",{className:"branches-header",onClick:()=>u(k=>!k),children:[N.jsxs("span",{children:["Branches (",r.length,")",i?` — ${i}`:""]}),N.jsx("span",{className:"branches-toggle",children:C?"▼":"▶"})]}),C&&N.jsxs("div",{className:"branches-list",children:[r.length===0&&N.jsx("div",{className:"prs-empty",children:"No branches found."}),r.map(k=>{const R=w(k);return N.jsxs("div",{className:`branch-item ${k.isCurrent?"current":""}`,children:[N.jsx("span",{className:"branch-current-marker",children:k.isCurrent?"●":""}),N.jsx("span",{className:`branch-name ${k.isCurrent?"current":""}`,title:k.name,children:k.name}),N.jsx("span",{className:"branch-message",children:k.lastCommitMessage}),R&&N.jsx("span",{className:"pr-branch",children:R}),N.jsx("span",{className:"branch-author",children:k.author}),N.jsxs("div",{className:"branch-ahead-behind",children:[k.ahead>0&&N.jsxs("span",{className:"branch-badge ahead",children:[k.ahead,"\\u2191"]}),k.behind>0&&N.jsxs("span",{className:"branch-badge behind",children:[k.behind,"\\u2193"]})]}),N.jsx("span",{className:"branch-time",children:k.lastCommitDate?ca(k.lastCommitDate):""})]},k.name)})]})]})]})}function kE({content:e,onChange:r}){const[i,o]=Q.useState(e),[h,S]=Q.useState(!1),[y,a]=Q.useState(!1),l=Q.useRef(null);Q.useEffect(()=>{y||o(e)},[e,y]);const p=m=>{o(m),a(!0)},v=async()=>{S(!0);try{await fetch("/api/crewmd",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:i})}),r(i),a(!1)}catch{}S(!1)},c=m=>{(m.metaKey||m.ctrlKey)&&m.key==="s"&&(m.preventDefault(),y&&v())};return N.jsxs("div",{className:"crewmd-editor",children:[N.jsxs("div",{className:"crewmd-header",children:[N.jsx("span",{className:"crewmd-title",children:"Rules"}),N.jsxs("div",{className:"crewmd-actions",children:[y&&N.jsx("span",{className:"crewmd-dirty",children:"unsaved"}),N.jsx("button",{className:"crewmd-save-btn",onClick:v,disabled:!y||h,children:h?"Saving...":"Save"})]})]}),N.jsx("textarea",{ref:l,className:"crewmd-textarea",value:i,onChange:m=>p(m.target.value),onKeyDown:c,spellCheck:!1,placeholder:"Write global instructions for all agents..."})]})}function LE(e){const[r,i]=Q.useState([]),[o,h]=Q.useState([]),[S,y]=Q.useState(""),[a,l]=Q.useState(null),[p,v]=Q.useState(null),[c,m]=Q.useState(!0);Q.useEffect(()=>{fetch("/api/github/status").then(b=>b.json()).then(b=>{l(b.available),v(b.repo||null)}).catch(()=>l(!1)),fetch("/api/github/prs?state=all").then(b=>b.json()).then(b=>{Array.isArray(b)&&i(b)}).catch(()=>{}),fetch("/api/git/branches").then(b=>b.json()).then(b=>{b.current&&y(b.current),Array.isArray(b.branches)&&h(b.branches)}).catch(()=>{}).finally(()=>m(!1))},[]),Q.useEffect(()=>{const b=e.current;if(!b)return;const C=_=>{Array.isArray(_)&&i(_)},u=_=>{_.current&&y(_.current),Array.isArray(_.branches)&&h(_.branches)};return b.on("github:prs:updated",C),b.on("git:branches:updated",u),()=>{b.off("github:prs:updated",C),b.off("git:branches:updated",u)}},[e]);const x=Q.useCallback(async b=>{try{const C=await fetch(`/api/github/prs/${b}`);return C.ok?await C.json():null}catch{return null}},[]);return{prs:r,branches:o,currentBranch:S,ghAvailable:a,repoInfo:p,loading:c,fetchPRDetail:x}}function RE({onSpawn:e,onClose:r,initialMode:i="spawn",error:o}){const[h,S]=Q.useState(i),[y,a]=Q.useState(""),[l,p]=Q.useState(""),[v,c]=Q.useState(""),[m,x]=Q.useState("claude"),[b,C]=Q.useState(!1),u=async()=>{C(!0);try{const d=await(await fetch("/api/pick-folder",{method:"POST"})).json();d.path&&c(d.path)}catch{}C(!1)},_=()=>{if(h==="open"){if(!v.trim())return;const f=v.trim().split("/").filter(Boolean).pop()||"project";e(y.trim()||f,l.trim()||`Work on the project at ${v.trim()}. Explore the codebase and wait for instructions.`,v.trim(),m)}else{if(!y.trim()||!l.trim())return;e(y.trim(),l.trim(),v.trim()||void 0,m)}};return N.jsx("div",{className:"dialog-overlay",onClick:r,children:N.jsxs("div",{className:"dialog",onClick:f=>f.stopPropagation(),children:[N.jsxs("div",{className:"dialog-mode-tabs",children:[N.jsx("button",{className:`dialog-mode-tab ${h==="spawn"?"active":""}`,onClick:()=>S("spawn"),children:"Spawn Agent"}),N.jsx("button",{className:`dialog-mode-tab ${h==="open"?"active":""}`,onClick:()=>S("open"),children:"Open Project"})]}),N.jsxs("label",{children:["Agent Service",N.jsxs("div",{className:"service-selector",children:[N.jsx("button",{type:"button",className:`service-btn ${m==="claude"?"active":""}`,onClick:()=>x("claude"),children:"Claude"}),N.jsx("button",{type:"button",className:`service-btn ${m==="codex"?"active":""}`,onClick:()=>x("codex"),children:"Codex"})]})]}),h==="open"?N.jsxs(N.Fragment,{children:[N.jsxs("label",{children:["Project Directory",N.jsxs("div",{className:"browse-row",children:[N.jsx("input",{type:"text",value:v,onChange:f=>c(f.target.value),placeholder:"/Users/you/your-project",autoFocus:!0}),N.jsx("button",{type:"button",className:"browse-btn",onClick:u,disabled:b,children:b?"...":"Browse"})]})]}),N.jsxs("label",{children:["Agent Name ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsx("input",{type:"text",value:y,onChange:f=>a(f.target.value),placeholder:"Auto-detected from path"})]}),N.jsxs("label",{children:["Initial Task ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsx("textarea",{value:l,onChange:f=>p(f.target.value),placeholder:"Explore the codebase and wait for instructions...",rows:3})]})]}):N.jsxs(N.Fragment,{children:[N.jsxs("label",{children:["Name",N.jsx("input",{type:"text",value:y,onChange:f=>a(f.target.value),placeholder:"e.g. researcher",autoFocus:!0})]}),N.jsxs("label",{children:["Task",N.jsx("textarea",{value:l,onChange:f=>p(f.target.value),placeholder:"Describe what this agent should do...",rows:4})]}),N.jsxs("label",{children:["Working Directory ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsxs("div",{className:"browse-row",children:[N.jsx("input",{type:"text",value:v,onChange:f=>c(f.target.value),placeholder:"e.g. /Users/you/project (leave blank for server cwd)"}),N.jsx("button",{type:"button",className:"browse-btn",onClick:u,disabled:b,children:b?"...":"Browse"})]})]})]}),o&&N.jsx("div",{className:"dialog-error",children:o}),N.jsxs("div",{className:"dialog-actions",children:[N.jsx("button",{onClick:r,children:"Cancel"}),N.jsx("button",{className:"primary",onClick:_,children:h==="open"?"Open":"Spawn"})]})]})})}function DE({size:e=28}){return N.jsxs("svg",{width:e,height:e,viewBox:"0 0 100 100",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[N.jsx("path",{d:"M50 5 A45 45 0 1 1 15 75",stroke:"currentColor",strokeWidth:"6",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M30 18 Q55 45 78 30",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M20 55 Q50 35 75 65",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M22 72 Q50 60 50 90",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("circle",{cx:"30",cy:"18",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"78",cy:"30",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"75",cy:"65",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"22",cy:"72",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"50",cy:"90",r:"5.5",fill:"currentColor"})]})}function TE(){var be;const{socket:e,agents:r,messages:i,contextEntries:o,crewMd:h,setCrewMd:S,fileChanges:y}=iy(),{prs:a,branches:l,currentBranch:p,ghAvailable:v,repoInfo:c,fetchPRDetail:m}=LE(e),[x,b]=Q.useState(null),C=r.find(le=>le.id===x)??null,[u,_]=Q.useState("graph"),[f,d]=Q.useState(!1),[w,k]=Q.useState("spawn"),[R,D]=Q.useState(""),[L,M]=Q.useState("all"),[W,z]=Q.useState("multi"),[F,B]=Q.useState(!1),[O,V]=Q.useState(()=>window.innerWidth>=768),[q,K]=Q.useState(!1),[U,A]=Q.useState(null),[I,P]=Q.useState(null),j=Q.useCallback(async()=>{K(!0),P(null);try{const le=await fetch("/api/pair");if(!le.ok){const Re=await le.text();P(Re||`Error ${le.status}`);return}const Pe=await le.json();A(Pe)}catch(le){P(le.message||"Failed to load pairing info")}},[]),[Y,Z]=Q.useState(null),ie=Q.useCallback(async(le,Pe,Re,Ie)=>{Z(null);try{const qe=await Vt("/api/spawn",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:le,task:Pe,cwd:Re,service:Ie||"claude"})}),nt=await qe.json();if(!qe.ok){Z(nt.error||"Unknown error");return}d(!1),Z(null)}catch(qe){Z(qe.message||"Failed to connect to server")}},[]),ae=Q.useCallback(async le=>{await fetch(`/api/agents/${le}`,{method:"DELETE"})},[]),X=Q.useCallback(async le=>{await fetch(`/api/agents/${le}/remove`,{method:"DELETE"}),x===le&&b(null)},[x]),H=Q.useCallback(async le=>{await fetch(`/api/agents/${le.id}/remove`,{method:"DELETE"});const Re=await(await Vt("/api/spawn",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:le.name,task:le.task,cwd:le.agent_cwd||void 0,service:le.service||"claude"})})).json();Re.id&&(b(Re.id),_("terminal"))},[]),re=Q.useCallback(async le=>{await fetch(`/api/context/${encodeURIComponent(le)}`,{method:"DELETE"})},[]),te=Q.useCallback(async()=>{if(!R.trim())return;const le=L,Pe=R;if(D(""),le!=="all")await fetch(`/api/agents/${le}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:Pe})}).catch(()=>{}),await Vt("/api/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:"user",to:le,content:Pe})});else{const Re=r.filter(Ie=>Ie.status==="running");await Promise.all(Re.map(Ie=>fetch(`/api/agents/${Ie.id}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:Pe})}).catch(()=>{}))),await Vt("/api/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:"user",to:"all",content:Pe})})}},[R,L,r]),ue=Q.useCallback(async()=>{await Vt("/api/messages",{method:"DELETE"})},[]),ce=Q.useCallback(async()=>{await Vt("/api/file-changes",{method:"DELETE"})},[]),pe=Q.useCallback(le=>{b(le.id),_("terminal")},[]),we=Q.useCallback(le=>{k(le),d(!0)},[]);Q.useEffect(()=>{const le=["graph","terminal","logs","files","prs","messages","context","crewmd"],Pe=Re=>{const Ie=Re.target,qe=Ie.tagName==="INPUT"||Ie.tagName==="TEXTAREA"||Ie.tagName==="SELECT",nt=Ie.closest(".xterm"),$e=Re.metaKey||Re.ctrlKey;if(Re.key==="Escape"){d(!1);return}const St=$e&&(Re.key==="["||Re.key==="]"||Re.key==="\\");if(nt&&St)Re.stopPropagation();else if(qe||nt)return;if(!$e)return;const Ge=parseInt(Re.key);if(Ge>=1&&Ge<=le.length){Re.preventDefault(),_(le[Ge-1]);return}switch(Re.key){case"n":Re.preventDefault(),k("spawn"),d(!0);break;case"o":Re.preventDefault(),k("open"),d(!0);break;case"[":{Re.preventDefault();const Oe=r.filter(dt=>dt.status!=="dead");if(Oe.length===0)break;const it=Oe.findIndex(dt=>dt.id===x),Ze=it<=0?Oe.length-1:it-1;b(Oe[Ze].id),_("terminal");break}case"]":{Re.preventDefault();const Oe=r.filter(dt=>dt.status!=="dead");if(Oe.length===0)break;const it=Oe.findIndex(dt=>dt.id===x),Ze=it>=Oe.length-1?0:it+1;b(Oe[Ze].id),_("terminal");break}case"\\":Re.preventDefault(),z(Oe=>Oe==="multi"?"single":"multi");break}};return document.addEventListener("keydown",Pe,!0),()=>document.removeEventListener("keydown",Pe,!0)},[r,x]),Q.useEffect(()=>{C!=null&&C.agent_cwd||B(!1)},[C==null?void 0:C.agent_cwd]);const xe=[{key:"graph",label:"Graph"},{key:"terminal",label:"Terminal"},{key:"logs",label:"Logs"},{key:"files",label:"Files"},{key:"prs",label:"PRs"},{key:"messages",label:"Messages"},{key:"context",label:"Context"},{key:"crewmd",label:"Rules"}];return N.jsxs("div",{className:"app",children:[N.jsxs("header",{className:"app-header",children:[N.jsx("button",{className:"header-hamburger",onClick:()=>V(le=>!le),title:"Toggle sidebar",children:"☰"}),N.jsxs("div",{className:"header-brand",children:[N.jsx(DE,{size:26}),N.jsx("h1",{children:"Clustr"})]}),(()=>{const le=r.reduce((Pe,Re)=>Pe+(Re.total_cost||0),0);return le>0?N.jsxs("span",{className:"header-total-cost",children:["Total: $",le.toFixed(4)]}):null})(),N.jsxs("div",{className:"header-actions",children:[window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"?N.jsx("button",{className:"header-connect-phone",onClick:j,title:"Connect phone",children:"Connect Phone"}):null,N.jsx("button",{onClick:()=>we("open"),children:"Open Project"}),N.jsx("button",{className:"primary",onClick:()=>we("spawn"),children:"New Agent"})]})]}),N.jsxs("div",{className:"app-body",children:[O&&N.jsx("div",{className:"sidebar-backdrop",onClick:()=>V(!1)}),N.jsxs("aside",{className:`sidebar ${O?"":"collapsed"}`,children:[N.jsx("button",{className:"sidebar-toggle",onClick:()=>V(le=>!le),title:O?"Collapse sidebar":"Expand sidebar",children:O?"‹":"›"}),O&&N.jsx(oy,{agents:r,selectedId:x,onSelect:le=>{b(le.id),_("terminal"),window.innerWidth<768&&V(!1)},onKill:ae,onRemove:X,onRestart:H})]}),N.jsxs("main",{className:"main-content",children:[N.jsxs("nav",{className:"tabs",children:[xe.map(le=>N.jsx("button",{className:u===le.key?"tab active":"tab",onClick:()=>_(le.key),children:le.label},le.key)),u==="terminal"&&N.jsxs("div",{className:"terminal-view-toggle",children:[(C==null?void 0:C.agent_cwd)&&N.jsx("button",{className:`user-shell-toggle ${F?"active":""}`,onClick:()=>B(le=>!le),title:"Open a user-controlled shell in the selected agent directory",children:"User Shell"}),N.jsx("button",{className:`view-toggle-btn ${W==="multi"?"active":""}`,onClick:()=>z("multi"),title:"Split view — all agents",children:"⊞"}),N.jsx("button",{className:`view-toggle-btn ${W==="single"?"active":""}`,onClick:()=>z("single"),title:"Single view — selected agent",children:"☐"})]})]}),N.jsxs("div",{className:"tab-content",children:[u==="graph"&&N.jsx(_b,{agents:r,messages:i,onSelectAgent:pe}),u==="terminal"&&W==="multi"&&N.jsx(tE,{agents:r,socket:e,onSelectAgent:le=>b(le.id)}),u==="terminal"&&W==="single"&&N.jsx(Gb,{agent:C,socket:e}),u==="terminal"&&F&&N.jsx(rE,{agent:C,socket:e,onClose:()=>B(!1)}),u==="logs"&&N.jsx(gE,{agents:r,selectedAgent:C,socket:e,onSelectAgent:le=>b(le.id)}),u==="messages"&&N.jsx(mE,{messages:i,agents:r,selectedAgentId:(C==null?void 0:C.id)??null,onClear:ue}),u==="context"&&N.jsx(vE,{entries:o,onRemove:re}),u==="files"&&N.jsx(CE,{changes:y,agents:r,onClear:ce}),u==="prs"&&N.jsx(EE,{prs:a,branches:l,currentBranch:p,ghAvailable:v,repoInfo:c,agents:r,fetchPRDetail:m}),u==="crewmd"&&N.jsx(kE,{content:h,onChange:S})]})]})]}),N.jsxs("footer",{className:"app-footer",children:[N.jsxs("select",{value:L,onChange:le=>M(le.target.value),children:[N.jsx("option",{value:"all",children:"All Agents"}),r.filter(le=>le.status==="running").map(le=>N.jsx("option",{value:le.id,children:le.name},le.id))]}),N.jsx("input",{type:"text",placeholder:L==="all"?"Broadcast message to all agents...":`Send message to ${((be=r.find(le=>le.id===L))==null?void 0:be.name)||"agent"}...`,value:R,onChange:le=>D(le.target.value),onKeyDown:le=>le.key==="Enter"&&te()}),N.jsx("button",{className:"primary",onClick:te,disabled:!R.trim(),children:"Send"})]}),f&&N.jsx(RE,{onSpawn:ie,onClose:()=>{d(!1),Z(null)},initialMode:w,error:Y}),q&&N.jsx("div",{className:"pair-modal-overlay",onClick:()=>K(!1),children:N.jsxs("div",{className:"pair-modal",onClick:le=>le.stopPropagation(),children:[N.jsxs("div",{className:"pair-modal-header",children:[N.jsx("h2",{children:"Connect Phone"}),N.jsx("button",{className:"pair-modal-close",onClick:()=>K(!1),children:"✕"})]}),I?N.jsx("p",{className:"pair-modal-error",children:I}):U?N.jsxs(N.Fragment,{children:[N.jsx("p",{className:"pair-modal-hint",children:"Scan to open Clustr on your phone's browser"}),N.jsx("img",{className:"pair-qr",src:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(U.qrSvg)}`,alt:"QR code to connect phone"}),N.jsxs("div",{className:"pair-urls",children:[N.jsxs("div",{className:"pair-url-row",children:[N.jsx("span",{className:"pair-url-label",children:"Local"}),N.jsxs("span",{className:"pair-url-text",children:[U.localUrl,"?token=…"]}),N.jsx("button",{onClick:()=>navigator.clipboard.writeText(`${U.localUrl}?token=${U.token}`),children:"Copy"})]}),U.remoteUrl&&N.jsxs("div",{className:"pair-url-row",children:[N.jsx("span",{className:"pair-url-label",children:"Remote"}),N.jsxs("span",{className:"pair-url-text",children:[U.remoteUrl,"?token=…"]}),N.jsx("button",{onClick:()=>navigator.clipboard.writeText(`${U.remoteUrl}?token=${U.token}`),children:"Copy"})]}),!U.remoteUrl&&N.jsxs("p",{className:"pair-tunnel-hint",children:["Set ",N.jsx("code",{children:"CLUSTR_TUNNEL=1"})," to enable remote access via Cloudflare Tunnel."]})]})]}):N.jsx("p",{className:"pair-modal-loading",children:"Loading pairing info…"})]})})]})}uv.createRoot(document.getElementById("root")).render(N.jsx($u.StrictMode,{children:N.jsx(TE,{})}));
|
|
111
|
+
`);return N.jsxs("div",{className:"diff-viewer",children:[r&&N.jsx("div",{className:"diff-filename",children:r}),N.jsx("pre",{className:"diff-content",children:i.map((o,h)=>{let S="diff-line";return o.startsWith("+")&&!o.startsWith("+++")?S+=" diff-add":o.startsWith("-")&&!o.startsWith("---")?S+=" diff-del":o.startsWith("@@")?S+=" diff-hunk":o.startsWith("\\")&&(S+=" diff-meta"),N.jsx("div",{className:S,children:o},h)})})]})}function wE(e){switch(e){case"add":return"A";case"change":return"M";case"unlink":return"D";default:return"?"}}function SE(e){switch(e){case"add":return"#4ade80";case"change":return"#fbbf24";case"unlink":return"#f87171";default:return"#666"}}function CE({changes:e,agents:r,onClear:i}){const[o,h]=Q.useState(null),S=Q.useMemo(()=>{const y=new Map;for(const a of r)y.set(a.id,a.name);return y},[r]);return N.jsxs("div",{className:"file-changes",children:[N.jsxs("div",{className:"file-changes-header",children:[N.jsxs("span",{children:["File Changes (",e.length,")"]}),e.length>0&&N.jsx("button",{className:"file-changes-clear-btn",onClick:i,children:"Clear"})]}),N.jsxs("div",{className:"file-changes-list",children:[e.length===0&&N.jsx("div",{className:"file-changes-empty",children:"No file changes detected yet. Changes will appear here as agents edit files."}),e.map(y=>{const a=y.agent_id?S.get(y.agent_id):null;return N.jsxs("div",{className:"file-change-item",children:[N.jsxs("div",{className:"file-change-row",onClick:()=>h(o===y.id?null:y.id),children:[N.jsx("span",{className:"file-change-type",style:{color:SE(y.change_type)},children:wE(y.change_type)}),N.jsx("span",{className:"file-change-path",children:y.file_path}),a&&N.jsx("span",{className:"file-change-agent",title:"Agent that made this change",children:a}),N.jsx("span",{className:"file-change-time",children:new Date(y.created_at).toLocaleTimeString()}),N.jsx("span",{className:"file-change-expand",children:y.diff_text?o===y.id?"▼":"▶":""})]}),o===y.id&&y.diff_text&&N.jsx(yE,{diff:y.diff_text})]},y.id)})]})]})}function ca(e){const r=Date.now()-new Date(e).getTime(),i=Math.floor(r/6e4);if(i<1)return"just now";if(i<60)return`${i}m ago`;const o=Math.floor(i/60);if(o<24)return`${o}h ago`;const h=Math.floor(o/24);return h<30?`${h}d ago`:`${Math.floor(h/30)}mo ago`}function xE(e){return!e||e.length===0?{icon:"",cls:""}:e.some(o=>o.conclusion==="FAILURE"||o.conclusion==="failure")?{icon:"✗",cls:"failure"}:e.some(o=>!o.conclusion||o.status==="IN_PROGRESS"||o.status==="QUEUED")?{icon:"○",cls:"pending"}:{icon:"✓",cls:"success"}}function bE(e){switch(e){case"APPROVED":return{text:"Approved",cls:"approved"};case"CHANGES_REQUESTED":return{text:"Changes",cls:"changes_requested"};case"REVIEW_REQUIRED":return{text:"Review",cls:"review_required"};default:return null}}function EE({prs:e,branches:r,currentBranch:i,ghAvailable:o,repoInfo:h,agents:S,fetchPRDetail:y}){const[a,l]=Q.useState("all"),[p,v]=Q.useState(null),[c,m]=Q.useState(null),[x,b]=Q.useState(!1),[C,u]=Q.useState(!0),_=Q.useMemo(()=>a==="all"?e:e.filter(k=>k.state.toUpperCase()===a.toUpperCase()),[e,a]),f=Q.useMemo(()=>new Set(S.map(k=>k.name.toLowerCase())),[S]),d=async k=>{if(p===k){v(null),m(null);return}v(k),m(null),b(!0);const R=await y(k);m(R),b(!1)},w=k=>{const R=k.name.toLowerCase();for(const L of f)if(R.includes(L))return L;const D=k.author.toLowerCase();for(const L of f)if(D.includes(L))return L;return null};return N.jsxs("div",{className:"prs-tab",children:[N.jsxs("div",{className:"prs-header",children:[N.jsxs("div",{className:"prs-header-left",children:[N.jsxs("span",{children:["Pull Requests (",_.length,")"]}),N.jsxs("select",{className:"prs-filter",value:a,onChange:k=>l(k.target.value),children:[N.jsx("option",{value:"all",children:"All"}),N.jsx("option",{value:"open",children:"Open"}),N.jsx("option",{value:"closed",children:"Closed"}),N.jsx("option",{value:"merged",children:"Merged"})]})]}),h&&N.jsx("a",{className:"prs-repo-link",href:h.url,target:"_blank",rel:"noopener noreferrer",onClick:k=>{k.preventDefault(),window.open(h.url,"_blank")},children:h.nameWithOwner})]}),N.jsxs("div",{className:"prs-list",children:[o===!1&&N.jsxs("div",{className:"prs-unavailable",children:["GitHub CLI not available.",N.jsx("br",{}),"Install ",N.jsx("code",{children:"gh"})," and run ",N.jsx("code",{children:"gh auth login"})," to see PRs."]}),o!==!1&&_.length===0&&N.jsx("div",{className:"prs-empty",children:"No pull requests found."}),_.map(k=>{const R=k.isDraft?"draft":k.state.toLowerCase(),D=xE(k.statusCheckRollup),L=bE(k.reviewDecision),M=p===k.number;return N.jsxs("div",{className:"pr-item",children:[N.jsxs("div",{className:"pr-row",onClick:()=>d(k.number),children:[N.jsx("span",{className:"pr-expand",children:M?"▼":"▶"}),N.jsx("span",{className:`pr-status-badge ${R}`}),N.jsxs("span",{className:"pr-number",children:["#",k.number]}),N.jsx("span",{className:"pr-title",children:k.title}),L&&N.jsx("span",{className:`pr-review ${L.cls}`,children:L.text}),D.icon&&N.jsx("span",{className:`pr-ci ${D.cls}`,children:D.icon}),N.jsx("span",{className:"pr-branch",title:k.headRefName,children:k.headRefName}),N.jsx("span",{className:"pr-author",children:k.author.login}),N.jsx("span",{className:"pr-time",children:ca(k.createdAt)}),N.jsx("button",{className:"pr-link-btn",title:"Open in GitHub",onClick:W=>{W.stopPropagation(),window.open(k.url,"_blank")},children:"↗"})]}),M&&N.jsxs("div",{className:"pr-detail",children:[x&&N.jsx("div",{className:"pr-detail-loading",children:"Loading..."}),c&&c.number===k.number&&N.jsxs(N.Fragment,{children:[c.body&&N.jsx("div",{className:"pr-detail-body",children:c.body}),c.statusCheckRollup&&c.statusCheckRollup.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Checks"}),N.jsx("div",{className:"pr-detail-checks",children:c.statusCheckRollup.map((W,z)=>{var F,B,O,V;return N.jsxs("span",{className:`pr-check ${((F=W.conclusion)==null?void 0:F.toLowerCase())==="success"?"success":((B=W.conclusion)==null?void 0:B.toLowerCase())==="failure"?"failure":"pending"}`,children:[((O=W.conclusion)==null?void 0:O.toLowerCase())==="success"?"✓":((V=W.conclusion)==null?void 0:V.toLowerCase())==="failure"?"✗":"○"," ",W.name]},z)})})]}),c.reviews&&c.reviews.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Reviews"}),c.reviews.map((W,z)=>N.jsxs("div",{className:"pr-comment",children:[N.jsxs("div",{className:"pr-comment-header",children:[N.jsx("strong",{children:W.author.login})," ",W.state.toLowerCase().replace("_"," ")," ",ca(W.submittedAt)]}),W.body&&N.jsx("div",{className:"pr-comment-body",children:W.body})]},z))]}),c.comments&&c.comments.length>0&&N.jsxs(N.Fragment,{children:[N.jsx("div",{className:"pr-detail-section-title",children:"Comments"}),c.comments.map((W,z)=>N.jsxs("div",{className:"pr-comment",children:[N.jsxs("div",{className:"pr-comment-header",children:[N.jsx("strong",{children:W.author.login})," ",ca(W.createdAt)]}),N.jsx("div",{className:"pr-comment-body",children:W.body})]},z))]}),(!c.reviews||c.reviews.length===0)&&(!c.comments||c.comments.length===0)&&!c.body&&N.jsx("div",{className:"pr-detail-loading",children:"No details available."})]})]})]},k.number)})]}),N.jsxs("div",{className:"branches-section",children:[N.jsxs("div",{className:"branches-header",onClick:()=>u(k=>!k),children:[N.jsxs("span",{children:["Branches (",r.length,")",i?` — ${i}`:""]}),N.jsx("span",{className:"branches-toggle",children:C?"▼":"▶"})]}),C&&N.jsxs("div",{className:"branches-list",children:[r.length===0&&N.jsx("div",{className:"prs-empty",children:"No branches found."}),r.map(k=>{const R=w(k);return N.jsxs("div",{className:`branch-item ${k.isCurrent?"current":""}`,children:[N.jsx("span",{className:"branch-current-marker",children:k.isCurrent?"●":""}),N.jsx("span",{className:`branch-name ${k.isCurrent?"current":""}`,title:k.name,children:k.name}),N.jsx("span",{className:"branch-message",children:k.lastCommitMessage}),R&&N.jsx("span",{className:"pr-branch",children:R}),N.jsx("span",{className:"branch-author",children:k.author}),N.jsxs("div",{className:"branch-ahead-behind",children:[k.ahead>0&&N.jsxs("span",{className:"branch-badge ahead",children:[k.ahead,"\\u2191"]}),k.behind>0&&N.jsxs("span",{className:"branch-badge behind",children:[k.behind,"\\u2193"]})]}),N.jsx("span",{className:"branch-time",children:k.lastCommitDate?ca(k.lastCommitDate):""})]},k.name)})]})]})]})}function kE({content:e,onChange:r}){const[i,o]=Q.useState(e),[h,S]=Q.useState(!1),[y,a]=Q.useState(!1),l=Q.useRef(null);Q.useEffect(()=>{y||o(e)},[e,y]);const p=m=>{o(m),a(!0)},v=async()=>{S(!0);try{await fetch("/api/crewmd",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:i})}),r(i),a(!1)}catch{}S(!1)},c=m=>{(m.metaKey||m.ctrlKey)&&m.key==="s"&&(m.preventDefault(),y&&v())};return N.jsxs("div",{className:"crewmd-editor",children:[N.jsxs("div",{className:"crewmd-header",children:[N.jsx("span",{className:"crewmd-title",children:"Rules"}),N.jsxs("div",{className:"crewmd-actions",children:[y&&N.jsx("span",{className:"crewmd-dirty",children:"unsaved"}),N.jsx("button",{className:"crewmd-save-btn",onClick:v,disabled:!y||h,children:h?"Saving...":"Save"})]})]}),N.jsx("textarea",{ref:l,className:"crewmd-textarea",value:i,onChange:m=>p(m.target.value),onKeyDown:c,spellCheck:!1,placeholder:"Write global instructions for all agents..."})]})}function LE(e){const[r,i]=Q.useState([]),[o,h]=Q.useState([]),[S,y]=Q.useState(""),[a,l]=Q.useState(null),[p,v]=Q.useState(null),[c,m]=Q.useState(!0);Q.useEffect(()=>{fetch("/api/github/status").then(b=>b.json()).then(b=>{l(b.available),v(b.repo||null)}).catch(()=>l(!1)),fetch("/api/github/prs?state=all").then(b=>b.json()).then(b=>{Array.isArray(b)&&i(b)}).catch(()=>{}),fetch("/api/git/branches").then(b=>b.json()).then(b=>{b.current&&y(b.current),Array.isArray(b.branches)&&h(b.branches)}).catch(()=>{}).finally(()=>m(!1))},[]),Q.useEffect(()=>{const b=e.current;if(!b)return;const C=_=>{Array.isArray(_)&&i(_)},u=_=>{_.current&&y(_.current),Array.isArray(_.branches)&&h(_.branches)};return b.on("github:prs:updated",C),b.on("git:branches:updated",u),()=>{b.off("github:prs:updated",C),b.off("git:branches:updated",u)}},[e]);const x=Q.useCallback(async b=>{try{const C=await fetch(`/api/github/prs/${b}`);return C.ok?await C.json():null}catch{return null}},[]);return{prs:r,branches:o,currentBranch:S,ghAvailable:a,repoInfo:p,loading:c,fetchPRDetail:x}}function RE({onSpawn:e,onClose:r,initialMode:i="spawn",error:o}){const[h,S]=Q.useState(i),[y,a]=Q.useState(""),[l,p]=Q.useState(""),[v,c]=Q.useState(""),[m,x]=Q.useState("claude"),[b,C]=Q.useState(!1),u=async()=>{C(!0);try{const d=await(await fetch("/api/pick-folder",{method:"POST"})).json();d.path&&c(d.path)}catch{}C(!1)},_=()=>{if(h==="open"){if(!v.trim())return;const f=v.trim().split("/").filter(Boolean).pop()||"project";e(y.trim()||f,l.trim(),v.trim(),m)}else{if(!y.trim()||!l.trim())return;e(y.trim(),l.trim(),v.trim()||void 0,m)}};return N.jsx("div",{className:"dialog-overlay",onClick:r,children:N.jsxs("div",{className:"dialog",onClick:f=>f.stopPropagation(),children:[N.jsxs("div",{className:"dialog-mode-tabs",children:[N.jsx("button",{className:`dialog-mode-tab ${h==="spawn"?"active":""}`,onClick:()=>S("spawn"),children:"Spawn Agent"}),N.jsx("button",{className:`dialog-mode-tab ${h==="open"?"active":""}`,onClick:()=>S("open"),children:"Open Project"})]}),N.jsxs("label",{children:["Agent Service",N.jsxs("div",{className:"service-selector",children:[N.jsx("button",{type:"button",className:`service-btn ${m==="claude"?"active":""}`,onClick:()=>x("claude"),children:"Claude"}),N.jsx("button",{type:"button",className:`service-btn ${m==="codex"?"active":""}`,onClick:()=>x("codex"),children:"Codex"})]})]}),h==="open"?N.jsxs(N.Fragment,{children:[N.jsxs("label",{children:["Project Directory",N.jsxs("div",{className:"browse-row",children:[N.jsx("input",{type:"text",value:v,onChange:f=>c(f.target.value),placeholder:"/Users/you/your-project",autoFocus:!0}),N.jsx("button",{type:"button",className:"browse-btn",onClick:u,disabled:b,children:b?"...":"Browse"})]})]}),N.jsxs("label",{children:["Agent Name ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsx("input",{type:"text",value:y,onChange:f=>a(f.target.value),placeholder:"Auto-detected from path"})]}),N.jsxs("label",{children:["Initial Task ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsx("textarea",{value:l,onChange:f=>p(f.target.value),placeholder:"Leave blank to register with Clustr and wait for instructions…",rows:3})]})]}):N.jsxs(N.Fragment,{children:[N.jsxs("label",{children:["Name",N.jsx("input",{type:"text",value:y,onChange:f=>a(f.target.value),placeholder:"e.g. researcher",autoFocus:!0})]}),N.jsxs("label",{children:["Task",N.jsx("textarea",{value:l,onChange:f=>p(f.target.value),placeholder:"Describe what this agent should do...",rows:4})]}),N.jsxs("label",{children:["Working Directory ",N.jsx("span",{className:"optional",children:"(optional)"}),N.jsxs("div",{className:"browse-row",children:[N.jsx("input",{type:"text",value:v,onChange:f=>c(f.target.value),placeholder:"e.g. /Users/you/project (leave blank for server cwd)"}),N.jsx("button",{type:"button",className:"browse-btn",onClick:u,disabled:b,children:b?"...":"Browse"})]})]})]}),o&&N.jsx("div",{className:"dialog-error",children:o}),N.jsxs("div",{className:"dialog-actions",children:[N.jsx("button",{onClick:r,children:"Cancel"}),N.jsx("button",{className:"primary",onClick:_,children:h==="open"?"Open":"Spawn"})]})]})})}function DE({size:e=28}){return N.jsxs("svg",{width:e,height:e,viewBox:"0 0 100 100",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[N.jsx("path",{d:"M50 5 A45 45 0 1 1 15 75",stroke:"currentColor",strokeWidth:"6",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M30 18 Q55 45 78 30",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M20 55 Q50 35 75 65",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("path",{d:"M22 72 Q50 60 50 90",stroke:"currentColor",strokeWidth:"5",strokeLinecap:"round",fill:"none"}),N.jsx("circle",{cx:"30",cy:"18",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"78",cy:"30",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"75",cy:"65",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"22",cy:"72",r:"6",fill:"currentColor"}),N.jsx("circle",{cx:"50",cy:"90",r:"5.5",fill:"currentColor"})]})}function TE(){var be;const{socket:e,agents:r,messages:i,contextEntries:o,crewMd:h,setCrewMd:S,fileChanges:y}=iy(),{prs:a,branches:l,currentBranch:p,ghAvailable:v,repoInfo:c,fetchPRDetail:m}=LE(e),[x,b]=Q.useState(null),C=r.find(le=>le.id===x)??null,[u,_]=Q.useState("graph"),[f,d]=Q.useState(!1),[w,k]=Q.useState("spawn"),[R,D]=Q.useState(""),[L,M]=Q.useState("all"),[W,z]=Q.useState("multi"),[F,B]=Q.useState(!1),[O,V]=Q.useState(()=>window.innerWidth>=768),[q,K]=Q.useState(!1),[U,A]=Q.useState(null),[I,P]=Q.useState(null),j=Q.useCallback(async()=>{K(!0),P(null);try{const le=await fetch("/api/pair");if(!le.ok){const Re=await le.text();P(Re||`Error ${le.status}`);return}const Pe=await le.json();A(Pe)}catch(le){P(le.message||"Failed to load pairing info")}},[]),[Y,Z]=Q.useState(null),ie=Q.useCallback(async(le,Pe,Re,Ie)=>{Z(null);try{const qe=await Vt("/api/spawn",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:le,task:Pe,cwd:Re,service:Ie||"claude"})}),nt=await qe.json();if(!qe.ok){Z(nt.error||"Unknown error");return}d(!1),Z(null)}catch(qe){Z(qe.message||"Failed to connect to server")}},[]),ae=Q.useCallback(async le=>{await fetch(`/api/agents/${le}`,{method:"DELETE"})},[]),X=Q.useCallback(async le=>{await fetch(`/api/agents/${le}/remove`,{method:"DELETE"}),x===le&&b(null)},[x]),H=Q.useCallback(async le=>{await fetch(`/api/agents/${le.id}/remove`,{method:"DELETE"});const Re=await(await Vt("/api/spawn",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:le.name,task:le.task,cwd:le.agent_cwd||void 0,service:le.service||"claude"})})).json();Re.id&&(b(Re.id),_("terminal"))},[]),re=Q.useCallback(async le=>{await fetch(`/api/context/${encodeURIComponent(le)}`,{method:"DELETE"})},[]),te=Q.useCallback(async()=>{if(!R.trim())return;const le=L,Pe=R;if(D(""),le!=="all")await fetch(`/api/agents/${le}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:Pe})}).catch(()=>{}),await Vt("/api/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:"user",to:le,content:Pe})});else{const Re=r.filter(Ie=>Ie.status==="running");await Promise.all(Re.map(Ie=>fetch(`/api/agents/${Ie.id}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:Pe})}).catch(()=>{}))),await Vt("/api/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:"user",to:"all",content:Pe})})}},[R,L,r]),ue=Q.useCallback(async()=>{await Vt("/api/messages",{method:"DELETE"})},[]),ce=Q.useCallback(async()=>{await Vt("/api/file-changes",{method:"DELETE"})},[]),pe=Q.useCallback(le=>{b(le.id),_("terminal")},[]),we=Q.useCallback(le=>{k(le),d(!0)},[]);Q.useEffect(()=>{const le=["graph","terminal","logs","files","prs","messages","context","crewmd"],Pe=Re=>{const Ie=Re.target,qe=Ie.tagName==="INPUT"||Ie.tagName==="TEXTAREA"||Ie.tagName==="SELECT",nt=Ie.closest(".xterm"),$e=Re.metaKey||Re.ctrlKey;if(Re.key==="Escape"){d(!1);return}const St=$e&&(Re.key==="["||Re.key==="]"||Re.key==="\\");if(nt&&St)Re.stopPropagation();else if(qe||nt)return;if(!$e)return;const Ge=parseInt(Re.key);if(Ge>=1&&Ge<=le.length){Re.preventDefault(),_(le[Ge-1]);return}switch(Re.key){case"n":Re.preventDefault(),k("spawn"),d(!0);break;case"o":Re.preventDefault(),k("open"),d(!0);break;case"[":{Re.preventDefault();const Oe=r.filter(dt=>dt.status!=="dead");if(Oe.length===0)break;const it=Oe.findIndex(dt=>dt.id===x),Ze=it<=0?Oe.length-1:it-1;b(Oe[Ze].id),_("terminal");break}case"]":{Re.preventDefault();const Oe=r.filter(dt=>dt.status!=="dead");if(Oe.length===0)break;const it=Oe.findIndex(dt=>dt.id===x),Ze=it>=Oe.length-1?0:it+1;b(Oe[Ze].id),_("terminal");break}case"\\":Re.preventDefault(),z(Oe=>Oe==="multi"?"single":"multi");break}};return document.addEventListener("keydown",Pe,!0),()=>document.removeEventListener("keydown",Pe,!0)},[r,x]),Q.useEffect(()=>{C!=null&&C.agent_cwd||B(!1)},[C==null?void 0:C.agent_cwd]);const xe=[{key:"graph",label:"Graph"},{key:"terminal",label:"Terminal"},{key:"logs",label:"Logs"},{key:"files",label:"Files"},{key:"prs",label:"PRs"},{key:"messages",label:"Messages"},{key:"context",label:"Context"},{key:"crewmd",label:"Rules"}];return N.jsxs("div",{className:"app",children:[N.jsxs("header",{className:"app-header",children:[N.jsx("button",{className:"header-hamburger",onClick:()=>V(le=>!le),title:"Toggle sidebar",children:"☰"}),N.jsxs("div",{className:"header-brand",children:[N.jsx(DE,{size:26}),N.jsx("h1",{children:"Clustr"})]}),(()=>{const le=r.reduce((Pe,Re)=>Pe+(Re.total_cost||0),0);return le>0?N.jsxs("span",{className:"header-total-cost",children:["Total: $",le.toFixed(4)]}):null})(),N.jsxs("div",{className:"header-actions",children:[window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"?N.jsx("button",{className:"header-connect-phone",onClick:j,title:"Connect phone",children:"Connect Phone"}):null,N.jsx("button",{onClick:()=>we("open"),children:"Open Project"}),N.jsx("button",{className:"primary",onClick:()=>we("spawn"),children:"New Agent"})]})]}),N.jsxs("div",{className:"app-body",children:[O&&N.jsx("div",{className:"sidebar-backdrop",onClick:()=>V(!1)}),N.jsxs("aside",{className:`sidebar ${O?"":"collapsed"}`,children:[N.jsx("button",{className:"sidebar-toggle",onClick:()=>V(le=>!le),title:O?"Collapse sidebar":"Expand sidebar",children:O?"‹":"›"}),O&&N.jsx(oy,{agents:r,selectedId:x,onSelect:le=>{b(le.id),_("terminal"),window.innerWidth<768&&V(!1)},onKill:ae,onRemove:X,onRestart:H})]}),N.jsxs("main",{className:"main-content",children:[N.jsxs("nav",{className:"tabs",children:[xe.map(le=>N.jsx("button",{className:u===le.key?"tab active":"tab",onClick:()=>_(le.key),children:le.label},le.key)),u==="terminal"&&N.jsxs("div",{className:"terminal-view-toggle",children:[(C==null?void 0:C.agent_cwd)&&N.jsx("button",{className:`user-shell-toggle ${F?"active":""}`,onClick:()=>B(le=>!le),title:"Open a user-controlled shell in the selected agent directory",children:"User Shell"}),N.jsx("button",{className:`view-toggle-btn ${W==="multi"?"active":""}`,onClick:()=>z("multi"),title:"Split view — all agents",children:"⊞"}),N.jsx("button",{className:`view-toggle-btn ${W==="single"?"active":""}`,onClick:()=>z("single"),title:"Single view — selected agent",children:"☐"})]})]}),N.jsxs("div",{className:"tab-content",children:[u==="graph"&&N.jsx(_b,{agents:r,messages:i,onSelectAgent:pe}),u==="terminal"&&W==="multi"&&N.jsx(tE,{agents:r,socket:e,onSelectAgent:le=>b(le.id)}),u==="terminal"&&W==="single"&&N.jsx(Gb,{agent:C,socket:e}),u==="terminal"&&F&&N.jsx(rE,{agent:C,socket:e,onClose:()=>B(!1)}),u==="logs"&&N.jsx(gE,{agents:r,selectedAgent:C,socket:e,onSelectAgent:le=>b(le.id)}),u==="messages"&&N.jsx(mE,{messages:i,agents:r,selectedAgentId:(C==null?void 0:C.id)??null,onClear:ue}),u==="context"&&N.jsx(vE,{entries:o,onRemove:re}),u==="files"&&N.jsx(CE,{changes:y,agents:r,onClear:ce}),u==="prs"&&N.jsx(EE,{prs:a,branches:l,currentBranch:p,ghAvailable:v,repoInfo:c,agents:r,fetchPRDetail:m}),u==="crewmd"&&N.jsx(kE,{content:h,onChange:S})]})]})]}),N.jsxs("footer",{className:"app-footer",children:[N.jsxs("select",{value:L,onChange:le=>M(le.target.value),children:[N.jsx("option",{value:"all",children:"All Agents"}),r.filter(le=>le.status==="running").map(le=>N.jsx("option",{value:le.id,children:le.name},le.id))]}),N.jsx("input",{type:"text",placeholder:L==="all"?"Broadcast message to all agents...":`Send message to ${((be=r.find(le=>le.id===L))==null?void 0:be.name)||"agent"}...`,value:R,onChange:le=>D(le.target.value),onKeyDown:le=>le.key==="Enter"&&te()}),N.jsx("button",{className:"primary",onClick:te,disabled:!R.trim(),children:"Send"})]}),f&&N.jsx(RE,{onSpawn:ie,onClose:()=>{d(!1),Z(null)},initialMode:w,error:Y}),q&&N.jsx("div",{className:"pair-modal-overlay",onClick:()=>K(!1),children:N.jsxs("div",{className:"pair-modal",onClick:le=>le.stopPropagation(),children:[N.jsxs("div",{className:"pair-modal-header",children:[N.jsx("h2",{children:"Connect Phone"}),N.jsx("button",{className:"pair-modal-close",onClick:()=>K(!1),children:"✕"})]}),I?N.jsx("p",{className:"pair-modal-error",children:I}):U?N.jsxs(N.Fragment,{children:[N.jsx("p",{className:"pair-modal-hint",children:"Scan to open Clustr on your phone's browser"}),N.jsx("img",{className:"pair-qr",src:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(U.qrSvg)}`,alt:"QR code to connect phone"}),N.jsxs("div",{className:"pair-urls",children:[N.jsxs("div",{className:"pair-url-row",children:[N.jsx("span",{className:"pair-url-label",children:"Local"}),N.jsxs("span",{className:"pair-url-text",children:[U.localUrl,"?token=…"]}),N.jsx("button",{onClick:()=>navigator.clipboard.writeText(`${U.localUrl}?token=${U.token}`),children:"Copy"})]}),U.remoteUrl&&N.jsxs("div",{className:"pair-url-row",children:[N.jsx("span",{className:"pair-url-label",children:"Remote"}),N.jsxs("span",{className:"pair-url-text",children:[U.remoteUrl,"?token=…"]}),N.jsx("button",{onClick:()=>navigator.clipboard.writeText(`${U.remoteUrl}?token=${U.token}`),children:"Copy"})]}),!U.remoteUrl&&N.jsxs("p",{className:"pair-tunnel-hint",children:["Set ",N.jsx("code",{children:"CLUSTR_TUNNEL=1"})," to enable remote access via Cloudflare Tunnel."]})]})]}):N.jsx("p",{className:"pair-modal-loading",children:"Loading pairing info…"})]})})]})}uv.createRoot(document.getElementById("root")).render(N.jsx($u.StrictMode,{children:N.jsx(TE,{})}));
|
package/dist/client/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<link rel="manifest" href="/manifest.json" />
|
|
8
8
|
<meta name="theme-color" content="#000000" />
|
|
9
9
|
<title>Clustr</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-DKrFI5vI.js"></script>
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-CKrQDT3Q.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|