crewswarm 0.9.4 → 1.0.0
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/.env.example +8 -1
- package/README.md +58 -9
- package/apps/dashboard/README.md +49 -0
- package/apps/dashboard/dist/assets/{index-D-sRshvg.css → index-C5-vlIwl.css} +1 -1
- package/apps/dashboard/dist/assets/index-CSooN9fi.js +2 -0
- package/apps/dashboard/dist/assets/index-CSooN9fi.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-spending-tab-DcXD5TQY.js +1 -0
- package/apps/dashboard/dist/assets/tab-spending-tab-DcXD5TQY.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-testing-tab-Ea5K-rsb.js +1 -0
- package/apps/dashboard/dist/index.html +85 -7
- package/apps/dashboard/dist/index.html.br +0 -0
- package/contrib/openclaw-plugin/index.ts +20 -11
- package/install.sh +2 -2
- package/lib/autoharness/index.mjs +151 -1
- package/lib/chat/history.mjs +1 -1
- package/lib/contacts/identity-linker.mjs +24 -3
- package/lib/contacts/index.mjs +2 -1
- package/lib/crew-lead/chat-handler.mjs +56 -33
- package/lib/crew-lead/llm-caller.mjs +71 -14
- package/lib/crew-lead/prompts.mjs +4 -2
- package/lib/crew-lead/wave-dispatcher.mjs +53 -3
- package/lib/crew-lead/worktree.mjs +258 -0
- package/lib/crew-lead/ws-router.mjs +43 -0
- package/lib/engines/rt-envelope.mjs +4 -1
- package/lib/memory/relevance-scorer.mjs +199 -0
- package/lib/memory/shared-adapter.mjs +85 -19
- package/package.json +10 -3
- package/scripts/dashboard.mjs +398 -28
- package/scripts/health-check.mjs +70 -28
- package/scripts/install-docker.sh +1 -1
- package/scripts/restart-all-from-repo.sh +25 -21
- package/scripts/start.mjs +81 -26
- package/apps/dashboard/dist/assets/chat-core-uXb_C0GM.js.br +0 -0
- package/apps/dashboard/dist/assets/cli-process-CNZ_UBCt.js.br +0 -0
- package/apps/dashboard/dist/assets/components-BS9fQjE_.js.br +0 -0
- package/apps/dashboard/dist/assets/core-utils-CmOkXgzi.js.br +0 -0
- package/apps/dashboard/dist/assets/index-BeVllEj_.js +0 -2
- package/apps/dashboard/dist/assets/index-BeVllEj_.js.br +0 -0
- package/apps/dashboard/dist/assets/index-D-sRshvg.css.br +0 -0
- package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
- package/apps/dashboard/dist/assets/setup-wizard-CA0Or47w.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-agents-tab-BgpIsjkw.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-benchmarks-tab-BHjKCPm3.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-comms-tab-kguqTIzD.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-contacts-tab-DiOyMYth.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-engines-tab-BsdZVvU0.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-memory-tab-Cu6u13EQ.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-models-tab-dNRgsTOO.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-pm-loop-tab-DiAPTJXu.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-projects-tab-SFH4E--a.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-prompts-tab-DVkUNaJd.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-services-tab-DU_LH3uG.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-CuvH_Fj_.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-DR7PJ7NB.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js +0 -1
- package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BNrd88-r.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-swarm-tab-B1AcjL1W.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js +0 -1
- package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-usage-tab-BIOOnB-Y.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-workflows-tab-B-soSy1k.js.br +0 -0
- package/apps/dashboard/dist/index.html.gz +0 -0
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/tab-benchmarks-tab-BHjKCPm3.js","assets/core-utils-CmOkXgzi.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
var e,t,n;import{a as o,g as a,b as s,s as i,p as r,d as l,c,k as d,r as p,h as m,l as u,m as g,e as h}from"./core-utils-CmOkXgzi.js";import{c as v}from"./setup-wizard-CA0Or47w.js";import{i as f}from"./components-BS9fQjE_.js";import{s as y}from"./orchestration-Ca2DLWN-.js";import"./cli-process-CNZ_UBCt.js";import{i as w}from"./chat-core-uXb_C0GM.js";import{i as b,s as x,h as k}from"./tab-swarm-chat-tab-BNrd88-r.js";import{i as C}from"./tab-waves-tab-SaJDkb4x.js";import{i as E,s as I}from"./tab-workflows-tab-B-soSy1k.js";import{c as T,m as B,s as S,l as j,a as A}from"./tab-memory-tab-Cu6u13EQ.js";import{i as P,s as L,l as M,a as _,r as N}from"./tab-services-tab-DU_LH3uG.js";import{i as O,s as R,l as F,a as H,t as D,b as z,c as G,d as $,e as V,f as q,g as K,h as U,j as W,k as J,m as Q,n as Y,o as X,p as Z,r as ee,q as te,u as ne,v as oe,w as ae,x as se,y as ie,z as re,A as le}from"./tab-agents-tab-BgpIsjkw.js";import{i as ce,a as de}from"./tab-prompts-tab-DVkUNaJd.js";import{i as pe,s as me,l as ue,r as ge}from"./tab-testing-tab-CezZOZcJ.js";import{s as he,a as ve,l as fe,c as ye,b as we,i as be,t as xe,d as ke,f as Ce,r as Ee,e as Ie,g as Te,u as Be}from"./tab-skills-tab-DR7PJ7NB.js";import{s as Se,i as je,a as Ae,l as Pe}from"./tab-contacts-tab-DiOyMYth.js";import{i as Le,t as Me,l as _e,d as Ne}from"./tab-engines-tab-BsdZVvU0.js";import{s as Oe,a as Re,b as Fe,c as He,t as De,d as ze,r as Ge,i as $e}from"./tab-swarm-tab-B1AcjL1W.js";import{i as Ve,s as qe,t as Ke,a as Ue,b as We,c as Je,d as Qe,e as Ye,f as Xe,g as Ze,h as et,j as tt,k as nt,l as ot,m as at}from"./tab-models-tab-dNRgsTOO.js";import{s as st,a as it,b as rt,t as lt,c as ct,d as dt,e as pt,f as mt,g as ut,h as gt,i as ht,j as vt,k as ft,l as yt,m as wt,u as bt,n as xt,o as kt,p as Ct,q as Et,r as It,v as Tt,w as Bt,x as St,y as jt,z as At,A as Pt,B as Lt,C as Mt,D as _t,E as Nt,F as Ot,G as Rt,H as Ft,I as Ht,J as Dt}from"./tab-settings-tab-CuvH_Fj_.js";import{i as zt,s as Gt,l as $t,a as Vt,b as qt,c as Kt,d as Ut,e as Wt,f as Jt,g as Qt,h as Yt,r as Xt,j as Zt}from"./tab-comms-tab-kguqTIzD.js";import{i as en,p as tn,r as nn,c as on,a as an,b as sn,e as rn,d as ln,l as cn,o as dn,f as pn,h as mn,j as un,k as gn,m as hn,n as vn,q as fn,t as yn,v as wn,w as bn}from"./tab-projects-tab-SFH4E--a.js";import{a as xn,r as kn,c as Cn,b as En,l as In,d as Tn}from"./tab-usage-tab-BIOOnB-Y.js";import{s as Bn,r as Sn,l as jn,a as An,b as Pn}from"./tab-spending-tab-DEccQHnt.js";import{i as Ln}from"./tab-pm-loop-tab-DiAPTJXu.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver(e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)}).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const Mn={};let _n=null;async function Nn(){return _n||(_n=await function(e,t){let n=Promise.resolve();if(t&&t.length>0){let e=function(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:"fulfilled",value:e}),e=>({status:"rejected",reason:e}))))};document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),a=(null==o?void 0:o.nonce)||(null==o?void 0:o.getAttribute("nonce"));n=e(t.map(e=>{if((e=function(e){return"/"+e}(e))in Mn)return;Mn[e]=!0;const t=e.endsWith(".css"),n=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${n}`))return;const o=document.createElement("link");return o.rel=t?"stylesheet":"modulepreload",t||(o.as="script"),o.crossOrigin="",o.href=e,a&&o.setAttribute("nonce",a),document.head.appendChild(o),t?new Promise((t,n)=>{o.addEventListener("load",t),o.addEventListener("error",()=>n(new Error(`Unable to preload CSS for ${e}`)))}):void 0}))}function o(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return n.then(t=>{for(const e of t||[])"rejected"===e.status&&o(e.reason);return e().catch(o)})}(()=>import("./tab-benchmarks-tab-BHjKCPm3.js"),__vite__mapDeps([0,1]))),_n}async function On(){try{const e=document.getElementById("statusDot");document.getElementById("status").textContent="online",e.className="status-dot online",await Cn();const t=await a("/api/dlq"),n=document.getElementById("dlqBadge");t.length?(n.textContent=t.length,n.classList.remove("hidden")):n.classList.add("hidden")}catch(e){document.getElementById("status").textContent="error",document.getElementById("statusDot").className="status-dot error"}}async function Rn(){await On()}function Fn(e){document.querySelectorAll(".nav-item").forEach(e=>e.classList.remove("active"));const t=document.getElementById(e);t&&t.classList.add("active")}function Hn(){u(o.activeTab),document.querySelectorAll(".view, .view-sessions").forEach(e=>{e.classList.remove("active"),e.style.display&&(e.style.display="")});const e=document.querySelector(".msg-bar");e&&(e.style.display="")}async function Dn(e){const t=document.getElementById(e),n=encodeURIComponent((null==t?void 0:t.value)||window._crewHome||""),o=await a("/api/pick-folder?default="+n).catch(()=>null);(null==o?void 0:o.path)&&t&&(t.value=o.path)}function zn(){const e=(location.hash||"#chat").slice(1),t=(e.split("?")[0]||"chat").split("/");return{view:t[0]||"chat",subtab:t[1],raw:e}}function Gn(){return zn().view}function $n(e){const t=e&&String(e).trim()&&"undefined"!==e?e:"general",n=`#chat?project=${encodeURIComponent(t)}`;location.hash!==n&&history.replaceState(null,"",n)}async function Vn(){try{const e=await a("/api/ui/active-project");return String((null==e?void 0:e.projectId)||"").trim()||"general"}catch{return"general"}}async function qn(e){const t=e&&String(e).trim()&&"undefined"!==e?String(e).trim():"general";try{await r("/api/ui/active-project",{projectId:t})}catch{}}async function Kn(){Hn(),document.getElementById("chatView").classList.add("active"),Fn("navChat"),o.activeTab="chat",s();const e=document.querySelector(".msg-bar");e&&(e.style.display="none"),y();const t=document.getElementById("chatMessages");"true"===(null==t?void 0:t.dataset.historyLoading)&&await io();const n=t&&"true"===t.dataset.historyLoaded&&t.children.length>0;try{const e=(await a("/api/projects")).projects||[];o.projectsData={},e.forEach(e=>{o.projectsData[e.id]=e}),s(),tn(e)}catch(c){console.warn("Failed to refresh projects dropdown:",c)}const i=new URLSearchParams(window.location.hash.replace(/^#chat\?/,"")).get("project");if(i)o.chatActiveProjectId=i;else{const e=await Vn();try{o.chatActiveProjectId=e||localStorage.getItem("crewswarm_chat_active_project_id")||"general"}catch{o.chatActiveProjectId=e||"general"}}window.location.hash.includes("?project=")||$n(o.chatActiveProjectId),console.log("🔵 [INIT] Active project from URL:",o.chatActiveProjectId);const r=document.getElementById("chatProjectTabs");r&&Array.from(r.children).forEach(e=>{e.dataset.projectId===o.chatActiveProjectId?e.classList.add("active"):e.classList.remove("active")});const l=document.getElementById("chatProjectSelect");l&&o.chatActiveProjectId&&l.querySelector('option[value="'+o.chatActiveProjectId+'"]')&&(l.value=o.chatActiveProjectId),qn(o.chatActiveProjectId),Cn(),Qn(),async function(){try{const e=((await a("/api/agents-config")).agents||[]).find(e=>"crew-lead"===e.id);if(!e)return;window._crewLeadInfo={emoji:e.emoji||"🧠",name:e.name||"crew-lead",theme:e.theme||""};const t=document.getElementById("chatAgentTitle"),n=document.getElementById("chatAgentSub");t&&(t.textContent=(e.emoji||"🧠")+" "+(e.name||"Crew Lead")),n&&e.theme&&(n.textContent=e.theme+" — chat naturally, dispatch tasks to the crew")}catch(c){}}(),window.loadChatAgentSelector&&window.loadChatAgentSelector(),n?m("chat"):await so()}function Un(){Hn(),document.getElementById("filesView").classList.add("active"),Fn("navFiles"),o.activeTab="files",s(),bo()}function Wn(){return"owner"}P({hideAllViews:Hn,setNavActive:Fn}),O({hideAllViews:Hn,setNavActive:Fn,refreshAgents:F}),ce({hideAllViews:Hn,setNavActive:Fn}),$e({hideAllViews:Hn,setNavActive:Fn}),C(),E({hideAllViews:Hn,setNavActive:Fn}),pe({hideAllViews:Hn,setNavActive:Fn});let Jn=null;function Qn(){if(Jn)return;const e=`http://${window.location.hostname||"127.0.0.1"}:5010/events`;console.log("[crewswarm] Starting EventSource listener for",e),Jn=new EventSource(e);const t="undefined"!=typeof localStorage&&"1"===localStorage.getItem("crewswarm_debug_sse");Jn.onmessage=e=>{if(e.data)try{const a=JSON.parse(e.data),s=e=>e&&"general"!==e?e:"general",r="owner";t&&console.log("[crewswarm] SSE:",a.type,e.data.slice(0,120));const l=document.getElementById("chatMessages");if(k(a))return;if("chat_stream"===a.type&&a.sessionId===r){const e=s(a.projectId);if(s(o.chatActiveProjectId)!==e)return;let t=document.getElementById("streaming-bubble");if(!t){const e=document.createElement("div");e.id="streaming-wrapper",e.style.cssText="display:flex;flex-direction:column;align-items:flex-start;gap:4px;";const n=document.createElement("div");n.style.cssText="font-size:11px;color:var(--text-3);padding:0 6px;";const o=window._crewLeadInfo||{emoji:"🧠",name:"crew-lead"};n.textContent=o.emoji+" "+o.name+" (streaming...)",t=document.createElement("div"),t.id="streaming-bubble",t.className="chat-bubble assistant",t.style.cssText="max-width:80%;padding:10px 14px;border-radius:14px 14px 14px 4px;background:var(--surface-2);color:var(--text-2);font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word;border:1px solid var(--border);",t._textNode=document.createTextNode(""),t.appendChild(t._textNode),e.appendChild(n),e.appendChild(t),l&&l.appendChild(e)}const n=(t.dataset.streamChunk||"")+a.token;return t.dataset.streamChunk=n,void(t._rafId||(t._rafId=requestAnimationFrame(()=>{const e=t.dataset.streamChunk||"";e&&(t._textNode||(t._textNode=document.createTextNode(""),t.appendChild(t._textNode)),t._textNode.textContent+=e,t.dataset.streamChunk=""),l&&(l.scrollTop=l.scrollHeight),t._rafId=null})))}if("draft_discarded"===a.type&&a.draftId){const e=document.querySelector('[data-draft-id="'+a.draftId+'"]');return void(e&&e.remove())}if("context_warning"===a.type&&"owner"===a.sessionId){const e=document.getElementById("contextWarningBanner");e&&e.remove();const t=document.createElement("div");t.id="contextWarningBanner";const n="critical"===a.level;t.style.cssText=`display:flex;align-items:center;gap:10px;padding:8px 14px;border-radius:8px;margin:6px 0;font-size:12px;background:${n?"rgba(239,68,68,0.1)":"rgba(245,158,11,0.1)"};border:1px solid ${n?"rgba(239,68,68,0.3)":"rgba(245,158,11,0.3)"};color:${n?"#f87171":"#f59e0b"};`,t.innerHTML=`<span style="flex:1;">${a.message}</span><button onclick="clearChatHistory()" style="padding:2px 8px;font-size:11px;border-radius:4px;border:1px solid currentColor;background:transparent;color:inherit;cursor:pointer;">Clear now</button><button onclick="this.parentElement.remove()" style="background:none;border:none;cursor:pointer;color:inherit;font-size:14px;padding:0 2px;">✕</button>`;const o=document.getElementById("chatMessages");return void(o&&(o.appendChild(t),o.scrollTop=o.scrollHeight))}if("chat_message"===a.type&&"owner"===a.sessionId){const e=s(o.chatActiveProjectId),t=s(a.projectId);if(e!==t)return void console.log("[crewswarm] ❌ SKIP - projectId mismatch:",{current:e||"(General)",message:t||"(General)"});if(console.log("[crewswarm] ✅ Displaying message for current session"),"user"===a.role){if(a.content===ao)return console.log("[crewswarm] Skipping SSE echo of locally-sent message"),void(ao=null);a.content!==oo?(console.log("[crewswarm] Appending user bubble:",a.content.slice(0,50)),g("user",a.content),oo=a.content):console.log("[crewswarm] Skipping duplicate user message")}else if("assistant"===a.role){document.querySelectorAll('[id^="typing-"]').forEach(e=>e.remove());const e=String(a.content||"").trim();if(e&&function(e){if(!e)return"";for(let t=e.children.length-1;t>=0;t--){const n=e.children[t];if("streaming-wrapper"!==n.id&&!(n.children.length<2)&&String(n.style.alignItems||"").includes("flex-start"))return(n.children[1].textContent||"").trim()}return""}(l)===e)return no=a.content,void(l&&(l.scrollTop=l.scrollHeight));const t=document.getElementById("streaming-wrapper"),n=document.getElementById("streaming-bubble");if(n){n._rafId&&cancelAnimationFrame(n._rafId),n._rafId=null;const e=n.dataset.streamChunk||"";e&&(n._textNode||(n._textNode=document.createTextNode(""),n.appendChild(n._textNode)),n._textNode.textContent+=e,n.dataset.streamChunk="")}if(t&&n){const e=window._crewLeadInfo||{emoji:"🧠",name:"crew-lead"},o=t.firstElementChild;o&&o!==n&&(o.textContent=e.emoji+" "+e.name);const s=a.content??"";n._textNode?n._textNode.textContent=s:n.textContent=s,t.removeAttribute("id"),n.removeAttribute("id"),delete n.dataset.streamChunk,no=a.content}else{t&&t.remove();const e=a.content===no&&function(e,t){if(!e||null==t)return!1;const n=String(t).trim();if(!n)return!1;for(let o=e.children.length-1;o>=0;o--){const t=e.children[o];if("streaming-wrapper"!==t.id&&(!(t.children.length<2)&&String(t.style.alignItems||"").includes("flex-start")&&(t.children[1].textContent||"").trim()===n))return!0}return!1}(l,a.content);e?console.log("[crewswarm] Skipping duplicate assistant message"):(console.log("[crewswarm] Appending assistant bubble (final)"),g("assistant",a.content,a.fallbackModel,a.fallbackReason,a.model,a.engineUsed),no=a.content)}}return void(l&&(l.scrollTop=l.scrollHeight))}if("pending_project"===a.type&&"owner"===a.sessionId&&a.pendingProject&&l)return to(l,a.pendingProject),void(l.scrollTop=l.scrollHeight);if("agent_working"===a.type&&a.agent){const e=document.getElementById("coding-dot-"+a.agent);e&&(e.style.display="inline-flex")}if("agent_idle"===a.type&&a.agent){const e=document.getElementById("coding-dot-"+a.agent);e&&(e.style.display="none")}if("opencode_event"===a.type){const e=document.getElementById("ocFeed"),t=document.getElementById("ocFeedDot");if(!e)return;t&&(t.style.display="inline-block");const o=document.createElement("div");o.style.cssText="display:flex;align-items:center;gap:8px;padding:5px 10px;border-radius:8px;background:var(--bg-2);font-size:12px;font-family:var(--font-mono,monospace);animation:fadeIn .25s ease;";const s=new Date(a.ts||Date.now()).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"});let i="⚙️",r="";if("session_start"===a.kind){i="▶",o.style.borderLeft="3px solid var(--green-hi)";var n=a.dir||"";r="session started"+(n?" — "+n.split("/").pop():"")}else if("session_end"===a.kind)i="■",o.style.borderLeft="3px solid var(--text-3)",r="session ended",t&&(t.style.display="none");else if("file_edit"===a.kind)i="✏️",o.style.borderLeft="3px solid var(--amber)",r=(a.file||a.path||"")+(a.extra?' <span style="opacity:.5;">'+a.extra+"</span>":"");else if("error"===a.kind)i="✗",o.style.borderLeft="3px solid var(--red-hi)",o.style.color="var(--red-hi)",r=a.message||"error";else if("tool"===a.kind){const e={read_file:"var(--accent)",write_file:"var(--amber)",bash:"var(--purple)",list_directory:"var(--green)",grep:"var(--green)"}[a.tool]||"var(--text-2)";i="done"===a.phase?"✓":"→",o.style.borderLeft="3px solid "+e,o.style.color="done"===a.phase?"var(--text-2)":"var(--text-1)",r='<span style="color:'+e+';font-weight:600;">'+(a.tool||"")+"</span>"+(a.label?' <span style="opacity:.6;">'+a.label+"</span>":"")}for(o.innerHTML='<span style="opacity:.4;flex-shrink:0;">'+s+'</span><span style="flex-shrink:0;">'+i+'</span><span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">'+r+"</span>",e.appendChild(o);e.children.length>80;)e.removeChild(e.firstChild);return void(e.scrollTop=e.scrollHeight)}if("agent_working"===a.type&&a.agent){const e="agent-spinner-"+(a.taskId||a.agent);if(l&&!document.getElementById(e)){const t=document.createElement("div");t.id=e,t.className="msg a",t.style.cssText="opacity:.7; font-style:italic;",t.innerHTML='<div class="meta"><strong>'+a.agent+'</strong> · working…</div><div class="t" style="display:flex;align-items:center;gap:8px;"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--accent);animation:pulse 1s ease-in-out infinite;"></span>Processing task…</div>',l.appendChild(t),l.scrollTop=l.scrollHeight}return}if("agent_reply"===a.type||a.from&&a.content){if(!a.from||!a.content)return;if(a._passthroughSummary)return;const e="agent-spinner-"+(a.taskId||a.from),t=document.getElementById(e);t&&t.remove();const n=document.getElementById("agent-spinner-"+a.from);return n&&n.remove(),g("🤖 "+a.from,a.content,!1,null,null,a.engineUsed),l&&(l.scrollTop=l.scrollHeight),void i(a.from+" finished a task")}if("task.timeout"===a.type&&a.agent){const e="agent-spinner-"+(a.taskId||a.agent),t=document.getElementById(e);t&&t.remove();const n=document.getElementById("agent-spinner-"+a.agent);n&&n.remove();const o="[crew-lead] Task to "+a.agent+" timed out (no reply in 90s). Consider @@SERVICE restart "+a.agent+" or re-dispatch to another agent.";if(l){const e=document.createElement("div");e.className="msg a",e.style.cssText="opacity:.85; font-style:italic; color:var(--text-3);",e.innerHTML='<div class="meta"><strong>'+a.agent+'</strong> · no reply</div><div class="t">'+h(o)+"</div>",l.appendChild(e),l.scrollTop=l.scrollHeight}return void i("Task to "+a.agent+" timed out")}if("pipeline_progress"===a.type){let e;e=a.agents?"Wave "+(a.waveIndex+1)+"/"+a.totalWaves+" → "+a.agents.join(" + "):"Step "+(a.stepIndex+1)+"/"+a.total+" → "+a.agent;const t=document.createElement("div");return t.style.cssText="font-size:11px;color:var(--text-3);padding:2px 8px;margin:2px 0;",t.textContent="↳ "+e,void(l&&(l.appendChild(t),l.scrollTop=l.scrollHeight))}if("pipeline_quality_gate"===a.type){const e=document.createElement("div"),t=a.willRetry?" — retrying wave":" — advancing anyway";return e.style.cssText="font-size:11px;color:var(--warning, #e8a030);padding:2px 8px;margin:2px 0;",e.textContent="⚠️ Wave "+(a.waveIndex+1)+" quality gate: "+(a.issues||[]).join("; ")+t,void(l&&(l.appendChild(e),l.scrollTop=l.scrollHeight))}if("project_launched"===a.type&&a.project){const e=a.project.projectId||a.project.id;return void setTimeout(async()=>{await ln(),e&&bn(e);const t=document.getElementById("chatMessages");if(t){const n=document.createElement("div");n.style.cssText="font-size:11px;color:var(--green);padding:2px 8px;margin:2px 0;",n.textContent='📁 Project "'+(a.project.name||e)+'" registered — selected in chat',t.appendChild(n),t.scrollTop=t.scrollHeight}},800)}if("pipeline_done"===a.type){const e=document.createElement("div");return e.style.cssText="font-size:11px;color:var(--green);padding:2px 8px;margin:2px 0;",e.textContent="✅ Pipeline complete",void(l&&(l.appendChild(e),l.scrollTop=l.scrollHeight))}if("confirm_run_cmd"===a.type&&a.approvalId)return void function(e,t,n){if(document.getElementById("cmd-approval-"+e))return;const o=document.createElement("div");o.id="cmd-approval-"+e,o.style.cssText=["position:fixed;bottom:80px;right:24px;z-index:9999;","background:var(--bg-card);border:1px solid var(--border);border-radius:12px;","padding:16px 20px;max-width:440px;box-shadow:0 8px 32px rgba(0,0,0,.4);","display:flex;flex-direction:column;gap:10px;"].join("");const a=document.createElement("div");a.style.cssText="font-size:13px;font-weight:600;color:var(--text-1);",a.textContent="🔐 "+t+" wants to run a command";const s=document.createElement("code");s.style.cssText="display:block;font-size:12px;color:var(--accent);background:var(--bg-1);padding:6px 10px;border-radius:6px;word-break:break-all;",s.textContent=n;const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-2);cursor:pointer;";const l=document.createElement("input");l.type="checkbox",l.style.cssText="width:14px;height:14px;cursor:pointer;accent-color:var(--green);";const c=n.trim().split(/\s+/)[0]+" *";r.appendChild(l),r.appendChild(document.createTextNode("Always allow "));const d=document.createElement("code");d.style.cssText="font-size:11px;background:var(--bg-1);padding:2px 6px;border-radius:4px;color:var(--accent);",d.textContent=c,r.appendChild(d);const p=document.createElement("div");p.style.cssText="font-size:11px;color:var(--text-3);";let m=60;p.textContent="Auto-reject in "+m+"s";const u=setInterval(()=>{m--,p.textContent="Auto-reject in "+m+"s",m<=0&&(clearInterval(u),o.remove())},1e3),g=document.createElement("div");g.style.cssText="display:flex;gap:8px;";const h=document.createElement("button");h.textContent="✅ Allow",h.style.cssText="flex:1;padding:8px;border-radius:8px;border:none;background:var(--green);color:#fff;cursor:pointer;font-weight:600;font-size:13px;",h.onclick=async()=>{clearInterval(u),o.remove(),l.checked&&(await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:c})}),i("Allowlisted: "+c)),await fetch("/api/cmd-approve",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}).catch(e=>i("Approve failed: "+e.message,!0)),l.checked||i(t+": command approved")};const v=document.createElement("button");v.textContent="⛔ Deny",v.style.cssText="flex:1;padding:8px;border-radius:8px;border:none;background:var(--red-hi);color:#fff;cursor:pointer;font-weight:600;font-size:13px;",v.onclick=async()=>{clearInterval(u),o.remove(),await fetch("/api/cmd-reject",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}).catch(e=>i("Reject failed: "+e.message,!0)),i(t+": command denied")},g.appendChild(h),g.appendChild(v),o.appendChild(a),o.appendChild(s),o.appendChild(r),o.appendChild(p),o.appendChild(g),document.body.appendChild(o)}(a.approvalId,a.agent,a.cmd);if("telemetry"===a.type&&a.payload){window._telemetryEvents=window._telemetryEvents||[],window._telemetryEvents.push(a.payload),window._telemetryEvents.length>100&&window._telemetryEvents.shift();const e=document.getElementById("toolMatrixView");e&&e.classList.contains("active")&&Tn(window._telemetryEvents)}}catch{}else console.warn("[crewswarm] SSE message with null/empty data")},Jn.onopen=()=>{console.log("[crewswarm] SSE connection opened"),window._sseReconnectDelay=2e3},Jn.onerror=e=>{console.error("[crewswarm] SSE error:",e),Jn.close(),Jn=null,window._sseReconnectTimer&&clearTimeout(window._sseReconnectTimer),window._sseReconnectTimer=setTimeout(()=>{window._sseReconnectTimer=null,window._sseReconnectDelay=Math.min(2*(window._sseReconnectDelay||2e3),3e4),Qn()},window._sseReconnectDelay||2e3)}}const Yn=[{label:"npm",pattern:"npm *",desc:"install, run, build, test…"},{label:"node",pattern:"node *",desc:"run any node script"},{label:"python",pattern:"python *",desc:"python / python3 scripts"},{label:"pip",pattern:"pip *",desc:"pip install packages"},{label:"git",pattern:"git *",desc:"all git operations"},{label:"cursor",pattern:"cursor *",desc:"open files in Cursor"},{label:"make",pattern:"make *",desc:"Makefile targets"},{label:"yarn",pattern:"yarn *",desc:"yarn install / build / run"},{label:"pnpm",pattern:"pnpm *",desc:"pnpm package manager"},{label:"ls / cat / echo",pattern:"ls *",desc:"read-only shell utilities"}];async function Xn(){const e=document.getElementById("cmdAllowlistItems"),t=document.getElementById("cmdPresets");if(!e)return;const n=(await a("/api/cmd-allowlist").catch(()=>({list:[]}))).list||[];t&&(t.innerHTML="",Yn.forEach(function(e){const o=n.includes(e.pattern),a=document.createElement("label");a.style.cssText="display:flex;align-items:center;gap:8px;cursor:pointer;padding:4px 6px;border-radius:6px;transition:background 0.1s;",a.onmouseover=function(){a.style.background="var(--bg-hover)"},a.onmouseout=function(){a.style.background=""};const s=document.createElement("input");s.type="checkbox",s.checked=o,s.style.cssText="width:14px;height:14px;cursor:pointer;accent-color:var(--green);flex-shrink:0;",s.onchange=async function(){s.checked?await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:e.pattern})}).catch(e=>i("Failed to add pattern: "+e.message,!0)):await fetch("/api/cmd-allowlist",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:e.pattern})}).catch(e=>i("Failed to remove pattern: "+e.message,!0)),Xn()};const r=document.createElement("code");r.style.cssText="font-size:12px;color:var(--accent);min-width:90px;",r.textContent=e.pattern;const l=document.createElement("span");l.style.cssText="font-size:11px;color:var(--text-3);",l.textContent=e.desc,a.appendChild(s),a.appendChild(r),a.appendChild(l),t.appendChild(a)}));const o=new Set(Yn.map(function(e){return e.pattern})),s=t?n.filter(function(e){return!o.has(e)}):n;if(e.innerHTML="",s.length)for(const a of s){const t=document.createElement("div");t.style.cssText="display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--border);";const n=document.createElement("code");n.style.cssText="flex:1;font-size:12px;color:var(--accent);",n.textContent=a;const o=document.createElement("button");o.textContent="✕",o.style.cssText="border:none;background:transparent;color:var(--text-3);cursor:pointer;font-size:14px;padding:0 4px;",o.title="Remove",o.onclick=async function(){await fetch("/api/cmd-allowlist",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:a})}).catch(e=>i("Failed to delete pattern: "+e.message,!0)),Xn()},t.appendChild(n),t.appendChild(o),e.appendChild(t)}else e.innerHTML='<div style="color:var(--text-3);font-size:12px;padding:4px 0;">'+(t?"No custom patterns yet.":"No patterns yet.")+"</div>"}async function Zn(){const e=document.getElementById("cmdAllowlistInput"),t=e?e.value.trim():"";t&&(await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:t})}).catch(e=>i("Failed to add pattern: "+e.message,!0)),e.value="",Xn())}window._telemetryEvents=window._telemetryEvents||[];const eo=()=>In(Pn);function to(e,{draftId:t,name:n,outputDir:o,roadmapMd:a}){function s(e){return(e.match(/^- \[ \]/gm)||[]).length}const i=document.createElement("div");i.setAttribute("data-draft-id",t),i.style.cssText="width:100%;display:flex;flex-direction:column;gap:4px;";const l=document.createElement("div");l.style.cssText="font-size:11px;color:var(--text-3);padding:0 6px;",l.textContent="🗺️ Roadmap draft — review before building";const c=document.createElement("div");c.style.cssText="width:100%;border:1px solid var(--border);border-radius:12px;overflow:hidden;background:var(--bg-card);";const d=document.createElement("div");d.style.cssText="background:var(--bg-card2);padding:10px 14px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--border);",d.innerHTML='<div><div style="font-size:13px;font-weight:600;color:var(--accent);">🚀 '+n+'</div><div style="font-size:11px;color:var(--blue);margin-top:2px;">'+o+'</div></div><span style="font-size:10px;color:var(--text-3);padding:2px 7px;background:var(--bg-card2);border-radius:10px;" class="task-count">'+s(a)+" tasks</span>";const p=document.createElement("textarea");p.value=a,p.spellcheck=!1,p.style.cssText="width:100%;background:var(--bg-card);border:none;outline:none;color:var(--text-1);font-size:11.5px;font-family:SF Mono,Monaco,Menlo,monospace;line-height:1.6;padding:12px 14px;resize:none;min-height:160px;max-height:320px;display:block;",setTimeout(()=>{p.style.height="",p.style.height=Math.min(p.scrollHeight,320)+"px"},50),p.addEventListener("input",()=>{p.style.height="",p.style.height=Math.min(p.scrollHeight,320)+"px",d.querySelector(".task-count").textContent=s(p.value)+" tasks"});const m=document.createElement("div");m.style.cssText="display:flex;gap:8px;align-items:center;padding:10px 14px 12px;border-top:1px solid var(--border);background:var(--bg-card2);";const u=document.createElement("button");u.textContent="▶ Start Building",u.style.cssText="background:var(--green-hi);color:#000;border:none;border-radius:8px;padding:8px 16px;font-size:12px;font-weight:700;cursor:pointer;",u.onclick=async()=>{u.disabled=!0,u.textContent="⏳ Launching…";try{const e=await r("/api/crew-lead/confirm-project",{draftId:t,roadmapMd:p.value});e.ok?(c.innerHTML='<div style="padding:14px;color:var(--green-hi);font-size:13px;font-weight:600;">✅ '+n+' — project created, PM loop running!<br><span style="color:var(--blue);font-size:11px;font-weight:400">'+(e.outputDir||o)+"</span></div>",g("assistant","🚀 "+n+" is building. Check the Projects tab to watch progress.")):(u.disabled=!1,u.textContent="▶ Start Building",v.textContent="⚠️ "+(e.error||"Launch failed"))}catch(e){u.disabled=!1,u.textContent="▶ Start Building",v.textContent="⚠️ "+e.message}};const h=document.createElement("button");h.textContent="Discard",h.style.cssText="background:none;border:1px solid var(--border);color:var(--text-3);border-radius:8px;padding:8px 14px;font-size:12px;cursor:pointer;",h.onclick=async()=>{await r("/api/crew-lead/discard-project",{draftId:t}).catch(()=>{}),i.remove()};const v=document.createElement("span");v.style.cssText="font-size:11px;color:var(--blue);margin-left:auto;",v.textContent="Edit above, then confirm",m.appendChild(u),m.appendChild(h),m.appendChild(v),c.appendChild(d),c.appendChild(p),c.appendChild(m),i.appendChild(l),i.appendChild(c),e.appendChild(i),e.scrollTop=e.scrollHeight}let no="",oo="",ao=null;const{loadChatHistory:so,waitForChatHistoryIdle:io,chatAtAtInput:ro,chatKeydown:lo,sendChat:co,clearChatHistory:po,stopAll:mo,killAll:uo,killPassthrough:go,refreshSessionIndicator:ho,clearPassthroughSession:vo,resetSendButton:fo,handleImageUpload:yo,toggleVoiceRecording:wo}=w({postJSON:r,getJSON:a,appendChatBubble:g,showNotification:i,state:o,getChatSessionId:()=>"owner",getChatActiveProjectId:()=>o.chatActiveProjectId,getCrewLeadInfo:()=>window._crewLeadInfo,appendRoadmapCard:to,getLastAppendedAssistantContent:()=>no,setLastAppendedAssistantContent:e=>{no=e},setLastAppendedUserContent:e=>{oo=e},setLastSentContent:e=>{ao=e}});async function bo(e){const t=document.getElementById("filesContent"),n=document.getElementById("filesDir").value.trim()||window._crewCwd||(window._crewHome?window._crewHome+"/CrewSwarm":"");d(t,"Scanning "+n+"...");try{const e=await a("/api/files?dir="+encodeURIComponent(n));if(!e.files||!e.files.length)return void c(t,"No files found in "+n);const o={};e.files.forEach(e=>{const t=e.path.split(".").pop().toLowerCase()||"other";o[t]||(o[t]=[]),o[t].push(e)});const s=["html","css","js","mjs","ts","json","md","sh","txt","other"],i={html:"🌐",css:"🎨",js:"⚡",mjs:"⚡",ts:"🔷",json:"📋",md:"📝",sh:"🖥️",txt:"📄",other:"📁"};let r='<div style="display:grid;gap:1rem;padding:4px 0;">';for(const t of s)o[t]&&(r+="<div>",r+='<div style="font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:0.08em;margin-bottom:8px;padding-left:2px;">'+(i[t]||"📁")+" ."+t+" — "+o[t].length+" file"+(o[t].length>1?"s":"")+"</div>",r+='<div style="display:grid;gap:6px;">',o[t].sort((e,t)=>t.mtime-e.mtime).forEach(e=>{const t=e.path.replace(n+"/",""),o=Co(e.mtime),a=Eo(e.size);r+='<div class="file-row">',r+='<div class="file-info"><span class="file-name">'+t+'</span><span class="file-meta">'+a+" · "+o+"</span></div>",r+='<div class="file-actions">',r+='<a href="cursor://file/'+e.path+'" class="file-btn file-btn-cursor" title="Open in Cursor">Cursor</a>',r+='<a href="opencode://open?path='+encodeURIComponent(e.path)+'" class="file-btn file-btn-opencode" title="Open in OpenCode">OpenCode</a>',r+='<button data-action="previewFile" data-arg=\''+e.path.replace(/'/g,"'")+'\' data-self="1" class="file-btn" title="Preview">👁</button>',r+="</div></div>"}),r+="</div></div>");r+="</div>",r+='<div id="file-preview-pane" style="display:none;margin-top:1rem;background:#0d1117;border:1px solid var(--border);border-radius:8px;overflow:hidden;"><div id="file-preview-bar" style="display:flex;align-items:center;gap:8px;padding:8px 12px;background:#0d1420;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-2);"><span id="file-preview-name"></span><button data-action="closePreviewPane" style="margin-left:auto;background:none;border:none;color:var(--text-2);cursor:pointer;">✕</button></div><pre id="file-preview-content" style="margin:0;padding:1rem;font-size:0.75rem;overflow:auto;max-height:400px;"></pre></div>',t.innerHTML=r}catch(o){l(t,"Error: "+o.message)}}async function xo(e,t){const n=document.getElementById("file-preview-pane"),o=document.getElementById("file-preview-content"),s=document.getElementById("file-preview-name");if(n){s.textContent=e.split("/").pop(),o.textContent="Loading...",n.style.display="block",n.scrollIntoView({behavior:"smooth",block:"nearest"});try{const t=await a("/api/file-content?path="+encodeURIComponent(e));o.textContent=t.content||"(empty)"}catch(i){o.textContent="Error: "+i.message}}}function ko(){const e=document.getElementById("file-preview-pane");e&&(e.style.display="none")}function Co(e){const t=Date.now()-e,n=Math.floor(t/6e4);if(n<1)return"just now";if(n<60)return n+"m ago";const o=Math.floor(n/60);return o<24?o+"h ago":Math.floor(o/24)+"d ago"}function Eo(e){return e<1024?e+"B":e<1048576?(e/1024).toFixed(1)+"KB":(e/1024/1024).toFixed(1)+"MB"}function Io(){Hn(),document.getElementById("settingsView").classList.add("active"),Fn("navSettings"),o.activeTab="settings",s();const e=(location.hash||"").replace("#settings/",""),t={system:"engines",telegram:"comms",whatsapp:"comms"}[e]||e;To(["usage","engines","comms","security","webhooks"].includes(t)?t:"usage")}function To(e){var t;["usage","engines","comms","security","webhooks"].forEach(t=>{const n=document.getElementById("stab-panel-"+t),o=document.getElementById("stab-"+t);n&&o&&(n.style.display=t===e?"usage"===t?"grid":"block":"none",o.classList.toggle("active",t===e))}),"usage"===e&&(En(),An()),"engines"===e&&(Et(),It(),Tt(),Bt(),St(),jt(),At(),Pt(),Lt(),Mt(),_t(),Nt(),Ot(),Rt(),Ft()),"comms"===e&&Zt(),"security"===e&&(Xn(),Ht()),(null==(t=document.getElementById("settingsView"))?void 0:t.classList.contains("active"))&&history.replaceState(null,"","#settings/"+e)}function Bo(){Hn(),document.getElementById("enginesView").classList.add("active"),Fn("navEngines"),_e()}null==(e=document.getElementById("attachImageBtn"))||e.addEventListener("click",()=>{document.getElementById("imageUpload").click()}),null==(t=document.getElementById("imageUpload"))||t.addEventListener("change",yo),null==(n=document.getElementById("recordVoiceBtn"))||n.addEventListener("click",wo),window.loadChatHistory=so,window.getChatSessionId=Wn,window.selectProjectTab=e=>{const t=e&&String(e).trim()&&"undefined"!==e?e:"general",n=o.chatActiveProjectId;console.log("🔵 [TAB CLICK] START",t,"- from:",n);const a=document.getElementById("chatProjectTabs");if(!a)return void console.error("🔵 [TAB CLICK] ERROR: chatProjectTabs container not found!");if(n===t)return void console.log("🔵 [TAB CLICK] Already on this tab, skipping reload");$n(t),Array.from(a.children).forEach(e=>{e.classList.remove("active")});const s=Array.from(a.children).find(e=>e.dataset.projectId===t);s&&s.classList.add("active"),o.chatActiveProjectId=t;try{localStorage.setItem("crewswarm_chat_active_project_id",t)}catch{}qn(t),console.log("🔵 [TAB CLICK] Updated state:",{projectId:o.chatActiveProjectId,sessionId:"owner",url:window.location.hash}),console.log("🔵 [TAB CLICK] Calling loadChatHistory()..."),so().then(()=>{console.log("🔵 [TAB CLICK] loadChatHistory() completed");const e=document.getElementById("chatMessages");console.log("🔵 [TAB CLICK] Messages in DOM:",(null==e?void 0:e.children.length)||0)}).catch(e=>{console.error("🔵 [TAB CLICK] loadChatHistory() ERROR:",e)})},window.addEventListener("focus",()=>{(async function(){if("chat"!==zn().view)return;const e=await Vn(),t=e&&"undefined"!==e?e:"general";t!==(o.chatActiveProjectId&&"undefined"!==o.chatActiveProjectId?o.chatActiveProjectId:"general")&&window.selectProjectTab&&window.selectProjectTab(t)})().catch(()=>{})}),zt({showSettings:Io,showSettingsTab:To}),Dt({getModels:F,populateModelDropdown:le}),at({hideAllViews:Hn,setNavActive:Fn,loadAgents:F}),Ve(),b({hideAllViews:Hn,setNavActive:Fn});const So=async()=>{Hn(),Fn("navBenchmarks");const e=document.getElementById("benchmarksView");e&&e.classList.add("active");const{showBenchmarks:t}=await Nn();t({hideAllViews:Hn,setNavActive:Fn})};function jo(){Hn(),document.getElementById("memoryView").classList.add("active"),Fn("navMemory"),A()}function Ao(){Hn(),document.getElementById("cliProcessView").classList.add("active"),Fn("navCLI"),window.initCLIProcess&&window.initCLIProcess()}function Po(){Hn(),document.getElementById("toolMatrixView").classList.add("active"),Fn("navToolMatrix"),xn()}async function Lo(){const e=document.getElementById("webhookChannel").value.trim()||"test";let t={};try{const e=document.getElementById("webhookPayload").value.trim();e&&(t=JSON.parse(e))}catch{t={raw:document.getElementById("webhookPayload").value}}const n=document.getElementById("webhookTestResult");try{const o=await fetch("/proxy-webhook/"+e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),a=await o.json();n.textContent=a.ok?"✅ Sent to RT bus":"❌ "+(a.error||"failed"),n.style.color=a.ok?"var(--green)":"var(--red)"}catch(o){n.textContent="❌ "+o.message,n.style.color="var(--red)"}}async function Mo(){document.getElementById("pendingApprovals").innerHTML='<div style="color:var(--text-3);font-size:12px;">Pending skill approvals appear here when an agent triggers a skill marked requiresApproval. You will also receive a Telegram notification with inline Approve/Reject buttons if Telegram is configured.</div>'}function _o(){un({hideAllViews:Hn,setNavActive:Fn})}function No(){mn({hideAllViews:Hn,setNavActive:Fn})}en({showChat:Kn,showBuild:_o}),On(),setInterval(On,3e4),(async()=>{try{const e=(await a("/api/projects")).projects||[];o.projectsData={},e.forEach(e=>{o.projectsData[e.id]=e}),tn(e),s(),"#projects"===location.hash&&No()}catch{}})(),document.getElementById("refreshBtn").onclick=Rn,document.getElementById("runBuildBtn").onclick=nn,document.getElementById("continuousBuildBtn").onclick=on,document.getElementById("stopBuildBtn").onclick=an,document.getElementById("stopContinuousBtn").onclick=sn,document.getElementById("enhancePromptBtn").onclick=rn,Ln(),document.getElementById("newProjectBtn").onclick=()=>{const e=document.getElementById("newProjectForm");e.style.display="none"===e.style.display?"block":"none"},document.getElementById("npCancelBtn").onclick=()=>{document.getElementById("newProjectForm").style.display="none"},document.getElementById("npCreateBtn").onclick=async()=>{const e=document.getElementById("npName").value.trim(),t=document.getElementById("npDesc").value.trim(),n=document.getElementById("npOutputDir").value.trim(),o=document.getElementById("npFeaturesDoc").value.trim();if(e&&n)try{const a=await r("/api/projects",{name:e,description:t,outputDir:n,featuresDoc:o});i(`Project "${a.project.name}" created!`),document.getElementById("newProjectForm").style.display="none",document.getElementById("npName").value="",document.getElementById("npDesc").value="",document.getElementById("npOutputDir").value="",document.getElementById("npFeaturesDoc").value="",ln()}catch(a){i("Failed: "+a.message,!0)}else i("Name and output directory required",!0)};const Oo={chat:Kn,"swarm-chat":x,swarm:Fe,rt:Re,dlq:Oe,files:Un,services:L,agents:R,models:qe,settings:Io,engines:Bo,skills:ve,"run-skills":he,benchmarks:So,"tool-matrix":Po,build:_o,messaging:Gt,projects:No,contacts:Se,memory:jo,workflows:I,"cli-process":Ao,prompts:de,testing:me};for(const[zo,Go]of Object.entries(Oo)){const e=Go,t=function(...t){const n=location.hash||"";return"chat"===zo?n.startsWith("#chat")||history.replaceState(null,"","#chat"):history.replaceState(null,"","#"+zo),e(...t)};Oo[zo]=t,window[e.name]=t}function Ro(e){const t=String(e||"chat").split("?")[0].split("/")[0];(Oo[t]||Oo.chat)()}(async()=>{if(await v())return;const{view:e,subtab:t}=zn();"1"===new URLSearchParams(window.location.search).get("focus")?setTimeout(()=>{const e=document.getElementById("chatInput");e&&(Ro("chat"),e.focus())},500):(Ro(e||"chat"),"settings"===e&&t&&To(t))})(),window.addEventListener("hashchange",()=>{const{view:e,subtab:t}=zn(),n=Do[e];n?(n(),"settings"===e&&t&&To(t)):Kn()}),fetch("/api/env").then(e=>e.json()).then(e=>{window._crewHome=e.HOME||"",window._crewCwd=e.cwd||"";const t=document.getElementById("filesDir");t&&!t.value&&(t.value=e.cwd||"")}).catch(()=>{}),F().catch(e=>console.error("Initial agents-config load failed:",e)),Rn(),function(){function e(e){if(e.closest("form"))return;const t=document.createElement("form");t.autocomplete="off",t.onsubmit=()=>!1,t.style.cssText="margin:0;padding:0;display:contents;";const n=document.createElement("input");n.type="text",n.autocomplete="username",n.setAttribute("aria-hidden","true"),n.style.cssText="display:none;position:absolute;width:0;height:0;opacity:0;",t.appendChild(n),e.parentNode.insertBefore(t,e),t.appendChild(e)}function t(t){(t||document).querySelectorAll('input[type="password"]').forEach(e)}t();new MutationObserver(n=>{for(const o of n)for(const n of o.addedNodes)1===n.nodeType&&(n.matches&&n.matches('input[type="password"]')?e(n):t(n))}).observe(document.body,{childList:!0,subtree:!0})}();const Fo={showChat:Kn,showSwarm:Fe,showRT:Re,showBuild:_o,showFiles:Un,showDLQ:Oe,showProjects:No,showAgents:R,showModels:qe,showEngines:Bo,showSkills:ve,showRunSkills:he,showBenchmarks:So,showToolMatrix:Po,showServices:L,showTesting:me,refreshTesting:()=>me(),runTests:e=>ge(e),loadRunDetail:e=>ue(e),showSettings:Io,pickFolder:e=>Dn(e),loadFiles:e=>bo(),clearChatHistory:po,clearAgentChat:()=>{const e=document.getElementById("agentChatSelector"),t=document.getElementById("agentChatMessages"),n=document.getElementById("agentChatInput");t&&(t.innerHTML='<div class="empty-state">No messages yet. Start chatting!</div>'),n&&(n.value=""),(null==e?void 0:e.value)&&i("Chat history cleared","success")},sendChat:co,stopAll:mo,killAll:uo,stopPassthrough:go,clearPassthroughSession:vo,loadServices:M,saveRTToken:kt,lockConfig:xt,unlockConfig:bt,startCrew:H,toggleEmojiPicker:e=>oe(e),bulkSetRoute:(e,t)=>ae(e,t),loadSpending:jn,resetSpending:Sn,saveGlobalCaps:Bn,loadOcStats:eo,addAllowlistPattern:Zn,sendTestWebhook:Lo,startTgBridge:Yt,stopTgBridge:Qt,saveTgConfig:Jt,loadTelegramSessions:Wt,loadTgMessages:Ut,startWaBridge:Kt,stopWaBridge:qt,saveWaConfig:Vt,loadWaMessages:$t,saveOpencodeSettings:wt,saveOpencodeModel:yt,saveGlobalFallback:ft,toggleBgConsciousness:vt,toggleCursorWaves:ht,toggleTmuxBridge:gt,toggleAutonomousMentions:ut,toggleClaudeCode:mt,toggleCodexExecutor:pt,toggleGeminiCliExecutor:dt,toggleCrewCliExecutor:ct,toggleOpencodeExecutor:lt,saveGlobalOcLoop:rt,saveGlobalOcLoopRounds:it,savePassthroughNotify:st,toggleAddSkill:ke,toggleImportSkill:xe,importSkillFromUrl:be,showSkills:ve,saveSkill:we,cancelSkillForm:ye,loadRunSkills:fe,loadBenchmarks:async()=>(await Nn()).loadBenchmarks(),loadBenchmarkLeaderboard:async()=>(await Nn()).loadBenchmarkLeaderboard(),loadBenchmarkTasks:async()=>(await Nn()).loadBenchmarkTasks(),onBenchmarkTaskSelect:async e=>(await Nn()).onBenchmarkTaskSelect(e),runBenchmarkTask:async()=>(await Nn()).runBenchmarkTask(),stopBenchmarkRun:async()=>(await Nn()).stopBenchmarkRun(),loadMemoryStats:j,searchMemory:S,migrateMemory:B,compactMemory:T,loadEngines:_e,toggleImportEngine:Me,importEngineFromUrl:Le,deleteEngine:e=>Ne(e),loadToolMatrix:xn,loadBuildProjectPicker:cn,scrollRTToBottom:()=>{const e=document.getElementById("rtView");e&&(e.scrollTop=e.scrollHeight)},toggleRTPause:De,clearRTMessages:He,togglePmAdvanced:()=>{const e=document.getElementById("pmAdvanced");e&&(e.style.display="none"===e.style.display?"block":"none")},toggleRTTokenVis:()=>{const e=document.getElementById("rtTokenInput");e&&(e.type="password"===e.type?"text":"password")},restartService:e=>N(e),stopService:e=>_(e),closePreviewPane:ko,previewFile:(e,t)=>xo(e),replayDLQ:e=>Ge(e),deleteDLQ:e=>ze(e),runSkillFromUI:e=>Ee(e),editSkill:e=>Ie(e),deleteSkill:e=>Te(e),restartAgentFromUI:e=>kn(e),saveSearchTool:e=>Qe(e),testSearchTool:e=>Ue(e),saveBuiltinKey:e=>Xe(e),testBuiltinProvider:e=>Je(e),fetchBuiltinModels:(e,t)=>et(e,t),saveOauthModel:e=>ot(e),testOauthProvider:e=>nt(e),showOauthModels:e=>tt(e),saveKey:e=>Ye(e),testKey:e=>We(e),fetchModels:(e,t)=>Ze(e,t),toggleKeyVis:(e,t)=>Ke(e,t),toggleAgentBody:e=>D(e),deleteAgent:e=>te(e),saveAgentModel:e=>Q(e),saveAgentFallback:e=>Z(e),saveAgentVoice:e=>X(e),toggleEmojiPicker:e=>oe(e),saveAgentIdentity:e=>Y(e),saveAgentPrompt:e=>J(e),resetAgentSession:e=>ee(e),saveAgentTools:e=>W(e),applyToolPreset:e=>ne(e),setRoute:(e,t)=>z(e,t),saveOpenCodeConfig:e=>V(e),saveOpenCodeFallback:e=>$(e),saveCursorCliConfig:e=>U(e),saveClaudeCodeConfig:e=>K(e),saveCodexConfig:e=>G(e),saveGeminiCliConfig:e=>q(e),saveCrewCLIConfig:e=>re(e),"pm-toggle":e=>{var t;const n=null==(t=o.projects)?void 0:t.find(t=>t.id===e);n&&n.running?yn(e):wn(e)},"edit-roadmap":e=>{var t;const n=null==(t=o.projects)?void 0:t.find(t=>t.id===e);n&&fn(e,n.roadmapFile)},"retry-failed":e=>{var t;const n=null==(t=o.projects)?void 0:t.find(t=>t.id===e);n&&vn(n.roadmapFile)},"save-roadmap":e=>hn(e),"reset-failed":e=>gn(e),showSettingsTab:e=>To(e)};let Ho=!1;document.addEventListener("touchstart",e=>{if(!(e.target instanceof Element))return;e.target.closest("[data-action]")&&(Ho=!0,setTimeout(()=>{Ho=!1},500))},{passive:!0}),document.addEventListener("click",e=>{if(!(e.target instanceof Element))return;const t=e.target.closest("[data-action]");if(!t)return;if(Ho)return void e.preventDefault();e.stopPropagation();const n=t.dataset.action,o=Fo[n];if(!o)return void console.warn("[crewswarm] unknown data-action:",n);const a=t.dataset.arg??null,s=t.dataset.arg2??null,i="1"===t.dataset.self;null!==a&&null!==s?o(a,s):null!==a&&i?o(a,t):null!==a?o(a):i?o(t):o()}),document.addEventListener("change",e=>{const t=e.target.closest("[data-onchange]");if(!t)return;const n=Fo[t.dataset.onchange];if(!n)return;const o="this.value"===t.dataset.onchangeArg?t.value:null;null!==o?n(o):n()}),document.addEventListener("DOMContentLoaded",()=>{f("activeTasksPanel"),je();const e=document.getElementById("dashSelfLink");e&&(e.href=window.location.origin,e.textContent=window.location.host),document.querySelectorAll(".nav-item").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const n=e.dataset.view;if(!n)return;if(Gn()!==n)return void(window.location.hash=n);const o=Do[n];o&&o()})});const t=document.getElementById("chatInput");t&&!t.dataset.boundChatComposer&&(t.dataset.boundChatComposer="1",t.addEventListener("keydown",lo),t.addEventListener("input",ro));const n=document.getElementById("chatSendBtn")||document.querySelector('[data-action="sendChat"]');n&&!n.dataset.boundChatComposer&&(n.dataset.boundChatComposer="1",n.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),co()}));const o=document.getElementById("cmdAllowlistInput");o&&o.addEventListener("keydown",e=>{"Enter"===e.key&&Zn()});const a=document.getElementById("waAllowedNumbers");a&&a.addEventListener("input",Xt);const s=document.getElementById("skillSearch");s&&s.addEventListener("input",e=>Ce(e.target.value));const i=document.getElementById("passthroughEngine");i&&i.addEventListener("change",()=>{ho(),function(){const e=document.getElementById("passthroughEngine"),t=document.getElementById("passthroughModel");if(!e||!t)return;const n=e.value,o={cursor:[{value:"",label:"— default (composer-2-fast) —"},{optgroup:"Cursor Defaults"},{value:"composer-2-fast",label:"🟢 Composer 2 Fast (default)"},{value:"composer-2-thinking",label:"Composer 2 Thinking"},{optgroup:"Recommended (No Rate Limits)"},{value:"gpt-5.4",label:"🟢 GPT-5.4"},{value:"gemini-3-flash",label:"🟢 Gemini 3 Flash (fastest)"},{value:"gemini-3-pro",label:"🟢 Gemini 3 Pro"},{value:"gemini-3.1-pro",label:"🟢 Gemini 3.1 Pro"},{value:"gpt-5.2-codex",label:"🟢 GPT-5.2 Codex"},{value:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{optgroup:"Claude Models (May Hit Rate Limits)"},{value:"sonnet-4.6",label:"🟡 Claude 4.6 Sonnet (current)"},{value:"opus-4.6",label:"🟡 Claude 4.6 Opus"},{optgroup:"Thinking Models (Slower)"},{value:"sonnet-4.6-thinking",label:"Claude 4.6 Sonnet Thinking"},{value:"opus-4.6-thinking",label:"Claude 4.6 Opus Thinking"},{optgroup:"Compatible Claude Models"},{value:"sonnet-4.5",label:"Claude 4.5 Sonnet"},{value:"opus-4.5",label:"Claude 4.5 Opus"},{value:"sonnet-4.5-thinking",label:"Claude 4.5 Sonnet Thinking"},{optgroup:"Other"},{value:"grok",label:"xAI Grok"},{value:"kimi-k2.5",label:"Moonshot Kimi K2.5"}],claude:[{value:"",label:"— default (Sonnet 4.6) —"},{optgroup:"Recommended"},{value:"sonnet",label:"🟢 Sonnet (alias for latest)"},{value:"Default",label:"🟢 Default (Sonnet 4.6)"},{optgroup:"Specific Versions"},{value:"claude-sonnet-4-6",label:"Sonnet 4.6 · Best for everyday tasks"},{value:"Opus",label:"Opus (Opus 4.6) · Most capable for complex work"},{value:"claude-opus-4-6",label:"Opus 4.6 · Most capable"},{value:"Haiku",label:"Haiku (Haiku 4.5) · Fastest for quick answers"},{value:"claude-haiku-4-5",label:"Haiku 4.5 · Fastest"},{optgroup:"Legacy"},{value:"claude-sonnet-4-5",label:"Sonnet 4.5 (legacy)"}],codex:[{value:"",label:"— default (gpt-5.4) —"},{optgroup:"Recommended"},{value:"gpt-5.4",label:"🟢 GPT-5.4 (current)"},{value:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{value:"gpt-5.2-codex",label:"🟢 GPT-5.2 Codex"},{optgroup:"Specialized"},{value:"gpt-5.1-codex-max",label:"GPT-5.1 Codex Max (deep reasoning)"},{value:"gpt-5.2",label:"GPT-5.2 (general purpose)"},{value:"gpt-5.1-codex-mini",label:"GPT-5.1 Codex Mini (fast & cheap)"}],opencode:[{value:"",label:"— default —"},{optgroup:"Free Models 🎁"},{value:"opencode/big-pickle",label:"🆓 Big Pickle (Free)"},{value:"opencode/minimax-m2.5-free",label:"🆓 MiniMax M2.5 Free"},{value:"openai/gpt-5-nano",label:"🆓 GPT 5 Nano (Free)"},{optgroup:"Budget Models 💰"},{value:"openai/gpt-5.1-codex-mini",label:"💰 GPT 5.1 Codex Mini ($0.25/$2)"},{value:"google/gemini-3-flash",label:"💰 Gemini 3 Flash ($0.50/$3)"},{value:"anthropic/claude-haiku-4-5",label:"💰 Claude Haiku 4.5 ($1/$5)"},{optgroup:"Interesting Models 🎯"},{value:"moonshot/kimi-k2.5",label:"Kimi K2.5 ($0.60/$3)"},{value:"moonshot/kimi-k2-thinking",label:"Kimi K2 Thinking ($0.40/$2.50)"},{value:"alibaba/qwen3-coder-480b",label:"Qwen3 Coder 480B ($0.45/$1.50)"},{value:"zhipu/glm-5",label:"GLM 5 ($1/$3.20)"},{optgroup:"Premium Claude"},{value:"anthropic/claude-sonnet-4-6",label:"Claude Sonnet 4.6 ($3/$15)"},{value:"anthropic/claude-opus-4-6",label:"Claude Opus 4.6 ($5/$25)"},{optgroup:"Premium OpenAI"},{value:"openai/gpt-5.4",label:"GPT 5.4 ($3/$15)"},{value:"openai/gpt-5.3-codex",label:"GPT 5.3 Codex ($1.75/$14)"},{value:"openai/gpt-5.2-codex",label:"GPT 5.2 Codex ($1.75/$14)"},{value:"openai/gpt-5.1-codex-max",label:"GPT 5.1 Codex Max ($1.25/$10)"},{optgroup:"Premium Google"},{value:"google/gemini-3.1-pro",label:"Gemini 3.1 Pro ($2/$12)"},{value:"google/gemini-3-pro",label:"Gemini 3 Pro ($2/$12)"}],gemini:[{value:"",label:"— default (gemini-3-flash-preview) —"},{optgroup:"Recommended (Latest)"},{value:"gemini-3-flash-preview",label:"🟢 Gemini 3 Flash Preview (current)"},{value:"gemini-3.1-pro-preview",label:"🟢 Gemini 3.1 Pro Preview"},{optgroup:"Gemini 2.5 Series"},{value:"gemini-2.5-pro",label:"Gemini 2.5 Pro"},{value:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{value:"gemini-2.5-flash-lite",label:"Gemini 2.5 Flash Lite (fastest)"}]};if(!n||!o[n])return void(t.style.display="none");t.style.display="inline-block",t.innerHTML="";let a=null;for(const s of o[n])if(s.optgroup)a=document.createElement("optgroup"),a.label=s.optgroup,t.appendChild(a);else{const e=document.createElement("option");e.value=s.value,e.textContent=s.label,a?a.appendChild(e):t.appendChild(e)}}(),fo()});const r=document.getElementById("chatProjectSelect");r&&r.addEventListener("change",ho);const l=document.getElementById("passthroughModel");l&&l.addEventListener("change",()=>{fo()})},{once:!0});const Do={chat:Kn,"swarm-chat":x,swarm:Fe,rt:Re,build:_o,files:Un,dlq:Oe,projects:No,contacts:Se,agents:R,models:qe,engines:Bo,skills:ve,"run-skills":he,waves:()=>{Hn(),document.getElementById("wavesView").style.display="block",Fn("navWaves")},workflows:I,benchmarks:So,"tool-matrix":Po,memory:jo,"cli-process":Ao,services:L,prompts:de,testing:me,settings:Io};document.addEventListener("click",e=>{const t=e.target.closest("[data-view]");if(t){const e=t.dataset.view,n=Do[e];return void(n&&(Gn()!==e?window.location.hash=e:n()))}const n=e.target.closest("[data-stab]");if(n){const e=n.dataset.stab;window.location.hash=`settings/${e}`,To(e)}const o=e.target.closest("[data-toggle-child]");if(o){const e=o.dataset.toggleChild,t=o.parentElement&&o.parentElement.querySelector(e);t&&(t.style.display="none"===t.style.display?"block":"none")}const a=e.target.closest("[data-toggle-sibling]");a&&a.nextElementSibling&&a.nextElementSibling.classList.toggle(a.dataset.toggleSibling)}),Object.assign(window,{addAllowlistPattern:Zn,applyNewAgentToolPreset:ie,applyPromptPreset:se,bulkSetRoute:ae,cancelSkillForm:ye,chatAtAtInput:ro,chatKeydown:lo,clearChatHistory:po,filterSkills:Ce,loadAllUsage:An,loadBenchmarkLeaderboard:async()=>(await Nn()).loadBenchmarkLeaderboard(),loadBenchmarks:async()=>(await Nn()).loadBenchmarks(),loadBenchmarkTasks:async()=>(await Nn()).loadBenchmarkTasks(),onBenchmarkTaskSelect:async e=>(await Nn()).onBenchmarkTaskSelect(e),runBenchmarkTask:async()=>(await Nn()).runBenchmarkTask(),stopBenchmarkRun:async()=>(await Nn()).stopBenchmarkRun(),loadMemoryStats:j,searchMemory:S,migrateMemory:B,compactMemory:T,loadBuildProjectPicker:cn,loadFiles:bo,loadOcStats:eo,loadRunSkills:fe,loadServices:M,loadSpending:jn,loadTelegramSessions:Wt,loadTgMessages:Ut,loadToolMatrix:xn,loadWaMessages:$t,onBuildProjectChange:pn,onChatProjectChange:dn,pickFolder:Dn,renderWaContactRows:Xt,resetSpending:Sn,approveSkill:async function(e){try{await fetch("/api/skills/approve",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}),i("Approved"),Mo()}catch(t){i("Failed: "+t.message,"error")}},loadPendingApprovals:Mo,rejectSkill:async function(e){try{await fetch("/api/skills/reject",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}),i("Rejected"),Mo()}catch(t){i("Failed: "+t.message,"error")}},saveGlobalCaps:Bn,saveGlobalFallback:ft,saveBgConsciousnessModel:Ct,saveOpencodeSettings:wt,saveRTToken:kt,saveSkill:we,saveTgConfig:Jt,saveWaConfig:Vt,sendChat:co,sendTestWebhook:Lo,showAgents:R,showBenchmarks:So,showBuild:_o,showChat:Kn,showContacts:Se,showDLQ:Oe,showFiles:Un,showModels:qe,showProjects:No,showRT:Re,showRunSkills:he,showServices:L,showSettings:Io,showSettingsTab:To,showSkills:ve,showSwarm:Fe,showToolMatrix:Po,showMemoryView:jo,startCrew:H,startTgBridge:Yt,startWaBridge:Kt,stopTgBridge:Qt,stopWaBridge:qt,toggleAddSkill:ke,toggleBgConsciousness:vt,toggleCursorWaves:ht,toggleTmuxBridge:gt,toggleClaudeCode:mt,toggleEmojiPicker:oe,updateSkillAuthFields:Be,navigateTo:Ro,renderStatusBadge:p,showLoading:d,showEmpty:c,showError:l,loadContacts:Pe,applyContactFilters:Ae,applyToolPreset:ne,closePreviewPane:ko,deleteAgent:te,deleteSkill:Te,editSkill:Ie,fetchBuiltinModels:et,fetchModels:Ze,previewFile:xo,resetAgentSession:ee,restartAgentFromUI:kn,restartService:N,runSkillFromUI:Ee,saveAgentFallback:Z,saveAgentVoice:X,saveAgentIdentity:Y,saveAgentModel:Q,saveAgentPrompt:J,saveAgentTools:W,saveBuiltinKey:Xe,saveCursorCliConfig:U,saveClaudeCodeConfig:K,saveGeminiCliConfig:q,saveKey:Ye,saveOpenCodeConfig:V,saveOpenCodeFallback:$,saveSearchTool:Qe,saveCodexConfig:G,setRoute:z,stopService:_,testBuiltinProvider:Je,testKey:We,testSearchTool:Ue,toggleAgentBody:D,toggleKeyVis:Ke});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as t,g as e,d as n}from"./core-utils-CmOkXgzi.js";import{e as o,l as a}from"./tab-usage-tab-BIOOnB-Y.js";var i=null,l=null;function s(){var t=i,e=l,n=document.getElementById("gtAgentCost"),o=document.getElementById("gtOcCost"),a=document.getElementById("gtTotal");n&&(null!==t&&(n.textContent="$"+t.toFixed(4)),null!==e&&(o.textContent="$"+e.toFixed(4)),null!==t&&null!==e&&(a.textContent="$"+(t+e).toFixed(4)))}function r(t){l=t,s()}async function d(){var t,e=parseInt((null==(t=document.getElementById("grandTotalDays"))?void 0:t.value)||"14"),n=document.getElementById("ocStatsDays"),o=document.getElementById("spendingDays");n&&(n.value=String(e)),o&&(o.value=String(1===e?1:e)),i=null,l=null,document.getElementById("gtAgentCost").textContent="—",document.getElementById("gtOcCost").textContent="—",document.getElementById("gtTotal").textContent="—",c(),a(r)}async function c(){var t,a,l,r,d;const c=document.getElementById("spendingWidget"),p=parseInt((null==(t=document.getElementById("spendingDays"))?void 0:t.value)||"1");try{if(p<=1){const t=await(await fetch("/api/spending")).json(),{spending:e,caps:n}=t,o=(null==(a=e.global)?void 0:a.tokens)||0,p=(null==(l=e.global)?void 0:l.costUSD)||0,g=null==(r=n.global)?void 0:r.dailyTokenLimit,m=null==(d=n.global)?void 0:d.dailyCostLimitUSD;let y='<div style="margin-bottom:10px;"><div style="font-size:11px;font-weight:600;color:var(--text-2);margin-bottom:4px;text-transform:uppercase;letter-spacing:.06em;">Global · '+(e.date||"today")+'</div><div style="display:flex;gap:20px;"><span>'+o.toLocaleString()+" tokens"+(g?" / "+Number(g).toLocaleString():"")+'</span><span style="color:var(--yellow);font-weight:600;">$'+p.toFixed(4)+"</span>"+(m?"<span> / $"+m+"</span>":"")+"</div>";if(g){const t=Math.min(100,o/g*100);y+='<div style="margin-top:4px;height:4px;background:var(--border);border-radius:2px;"><div style="width:'+t+"%;height:100%;background:"+(t>80?"var(--red)":t>50?"var(--yellow)":"var(--green)")+';border-radius:2px;transition:width .3s;"></div></div>'}y+="</div>";const u=Object.entries(e.agents||{});u.length?(y+='<div style="font-size:11px;font-weight:600;color:var(--text-2);margin-bottom:6px;text-transform:uppercase;letter-spacing:.06em;">Per Agent</div>',y+=u.map(function(t){var e=t[0],o=t[1];const a=n.agents&&n.agents[e],i=o.tokens||0,l=(o.costUSD||0).toFixed(4),s=a&&a.dailyTokenLimit,r=s?Math.min(100,i/s*100):null;let d='<div style="display:flex;align-items:center;gap:10px;margin-bottom:4px;"><span style="min-width:140px;font-size:12px;">'+e+'</span><span style="font-size:12px;">'+i.toLocaleString()+" tok"+(s?" / "+Number(s).toLocaleString():"")+' · <span style="color:var(--yellow);">$'+l+"</span></span>";if(null!==r){d+='<div style="flex:1;height:3px;background:var(--border);border-radius:2px;"><div style="width:'+r+"%;height:100%;background:"+(r>80?"var(--red)":"var(--accent)")+';border-radius:2px;"></div></div>'}return d+"</div>"}).join("")):y+='<div style="color:var(--text-3);">No per-agent data yet for today.</div>',g&&(document.getElementById("gcapTokens").value=g),m&&(document.getElementById("gcapCost").value=m),i=p,s(),c.innerHTML=y}else{const t=(await e("/api/token-usage").catch(function(){return{}})).byDay||{},n=new Date(Date.now()-864e5*p).toISOString().slice(0,10),a=Object.keys(t).filter(function(t){return t>=n}).sort().reverse();if(!a.length)return c.innerHTML='<div style="color:var(--text-3);">No data for this period.</div>',i=0,void s();const l={};var g=0;a.forEach(function(e){const n=t[e].byModel||{};Object.entries(n).forEach(function(t){var e=t[0],n=t[1];l[e]||(l[e]={prompt:0,completion:0}),l[e].prompt+=n.prompt||0,l[e].completion+=n.completion||0,(n.prompt||0)+(n.completion||0)})}),g=o(l);let r='<div style="margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;"><span style="font-size:12px;color:var(--text-3);">Last '+p+" days · "+a.length+' days of data</span><span style="font-size:16px;font-weight:700;color:var(--yellow);">$'+g.toFixed(4)+"</span></div>";const d=Math.max(...a.map(function(e){return o(t[e].byModel||{})}),1e-4),m=(new Date).toISOString().slice(0,10);r+='<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px;">',a.forEach(function(e){const n=o(t[e].byModel||{}),a=Math.max(n/d*100,n>0?2:0),i=e===m,l=((t[e].prompt||0)+(t[e].completion||0))/1e3;r+='<div style="display:flex;align-items:center;gap:8px;font-size:11px;"><span style="width:64px;color:var(--text-3);flex-shrink:0;">'+(i?"today":e.slice(5))+'</span><div style="flex:1;background:var(--bg-1);border-radius:3px;height:12px;overflow:hidden;"><div style="width:'+a.toFixed(1)+"%;height:100%;background:"+(i?"var(--accent)":"var(--green)")+';border-radius:3px;opacity:.8;"></div></div><span style="width:58px;text-align:right;color:var(--yellow);font-weight:600;">$'+n.toFixed(4)+'</span><span style="width:40px;text-align:right;color:var(--text-3);">'+l.toFixed(0)+"k</span></div>"}),r+="</div>";const y=Object.entries(l).sort(function(t,e){return o({b:e[1]})-o({a:t[1]})});y.length&&(r+='<div style="font-size:11px;color:var(--text-3);margin-bottom:4px;">By model</div>',y.slice(0,8).forEach(function(t){var e=t[0],n=t[1];const a=o({x:n}),i=((n.prompt||0)+(n.completion||0))/1e3;r+='<div style="display:flex;justify-content:space-between;font-size:11px;padding:2px 0;border-bottom:1px solid var(--border);"><code style="color:var(--accent);">'+e+'</code><span style="color:var(--text-2);">'+i.toFixed(1)+'k tok · <span style="color:var(--yellow);">$'+a.toFixed(4)+"</span></span></div>"})),i=g,s(),c.innerHTML=r}}catch(m){n(c,"Error: "+m.message)}}async function p(){if(confirm("Reset today's spending counters?"))try{await fetch("/api/spending/reset",{method:"POST",headers:{"content-type":"application/json"},body:"{}"}),c(),t("Spending reset")}catch(e){t("Reset failed",!0)}}async function g(){const e=parseInt(document.getElementById("gcapTokens").value)||null,n=parseFloat(document.getElementById("gcapCost").value)||null;t('Add to ~/.crewswarm/crewswarm.json: "globalSpendingCaps": {"dailyTokenLimit":'+(e||"null")+',"dailyCostLimitUSD":'+(n||"null")+"}","warning")}export{d as a,r as b,c as l,p as r,g as s};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as s,b as t,g as e,e as a,s as n,p as i}from"./core-utils-CmOkXgzi.js";let l=()=>{},r=()=>{};function o(s={}){l=s.hideAllViews||l,r=s.setNavActive||r}let d=null;function c(){l(),document.getElementById("testingView").classList.add("active"),r("navTesting"),s.activeTab="testing",t(),m(),g(),e("/api/tests/progress").then(s=>{s.running&&!y&&(b(),y=setInterval(b,2e3))}).catch(()=>{}),d&&clearInterval(d),d=setInterval(()=>{document.getElementById("testingView").classList.contains("active")?(m(),g()):(clearInterval(d),d=null)},3e4)}function u(s){return!s||s<=0?"-":s>=6e4?(s/6e4).toFixed(1)+"m":s>=1e3?(s/1e3).toFixed(1)+"s":Math.round(s)+"ms"}function p(s){if(!s)return"-";const t=new Date(s);return t.toLocaleDateString(void 0,{month:"short",day:"numeric"})+" "+t.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}function v(s,t){const e=s+t;return 0===e?"-":(s/e*100).toFixed(0)+"%"}const f={unit:"Unit",integration:"Integration",e2e:"E2E",all:"All",unknown:"Other"},h={unit:"#818cf8",integration:"#34d399",e2e:"#fbbf24",all:"#60a5fa",unknown:"#94a3b8"};async function m(){var s;const t=document.getElementById("testingContent");if(t)try{const n=await e("/api/tests/summary");if(!n.latest&&!n.fileCounts)return void(t.innerHTML='<div class="empty-state">No test results found. Run tests to see results here.</div>');let i="";const l=n.fileCounts||{},r=n.testCounts||{};i+='<div class="test-launch-grid">';const o=[{key:"unit",label:"Unit",files:l.unit,tests:r.unit,cmd:"test:unit",color:h.unit},{key:"integration",label:"Integration",files:l.integration,tests:r.integration,cmd:"test:integration",color:h.integration},{key:"e2e",label:"E2E",files:l.e2e,tests:r.e2e,cmd:"test:e2e",color:h.e2e},{key:"playwright",label:"Playwright",files:l.playwright,tests:r.playwright,cmd:"test:e2e:vibe",color:"#f472b6"},{key:"crew-cli",label:"crew-cli",files:l["crew-cli"],tests:r["crew-cli"],cmd:"test",color:"#10b981"}];for(const s of o){const t=s.tests?`<span class="test-launch-tests">${s.tests} tests</span>`:"",e=s.cmd?`<button class="test-launch-btn" data-action="runTests" data-arg="${s.cmd}">▶ Run</button>`:'<span class="meta" style="font-size:10px">npx playwright test</span>';i+=`\n <div class="test-launch-card" style="border-color:${s.color}30">\n <div class="test-launch-header">\n <span class="test-launch-name" style="color:${s.color}">${s.label}</span>\n ${e}\n </div>\n <div class="test-launch-counts">\n <span class="test-launch-files">${s.files||0} files</span>\n ${t}\n </div>\n </div>`}const d=Object.values(r).reduce((s,t)=>s+(t||0),0);i+=`\n <div class="test-launch-card test-launch-total" style="border-color:var(--accent)">\n <div class="test-launch-header">\n <span class="test-launch-name" style="color:var(--accent)">All</span>\n <button class="test-launch-btn" data-action="runTests" data-arg="test:all" style="background:var(--accent);color:#fff">▶ Run All</button>\n </div>\n <div class="test-launch-counts">\n <span class="test-launch-files">${l.total||0} files</span>\n ${d?`<span class="test-launch-tests">${d}+ tests</span>`:""}\n </div>\n </div>`,i+="</div>",i+='<div class="test-section-title">Latest Results by Suite</div>',i+='<div class="test-suite-grid">';for(const t of["unit","integration","e2e","all"]){const e=null==(s=n.suites)?void 0:s[t];if(!e||!e.total&&!e.passed&&!e.failed)continue;const a=(e.passed||0)+(e.failed||0),l=e.failed>0?"test-status-fail":"test-status-pass",r=e.failed>0?"FAIL":"PASS";i+=`\n <div class="test-suite-card">\n <div class="test-suite-header">\n <span class="test-suite-name" style="color:${h[t]}">${f[t]}</span>\n <span class="test-summary-status ${l}">${r}</span>\n </div>\n <div class="test-suite-stats">\n <div><span class="test-color-pass">${e.passed||0}</span> pass</div>\n <div><span class="${e.failed>0?"test-color-fail":""}">${e.failed||0}</span> fail</div>\n <div><span class="${e.skipped>0?"test-color-skip":""}">${e.skipped||0}</span> skip</div>\n <div><strong>${e.total||0}</strong> total</div>\n </div>\n <div class="test-suite-meta">\n ${v(e.passed||0,e.failed||0)} pass rate · ${u(e.duration_ms)} · ${p(e.timestamp)}\n </div>\n <div class="test-progress-bar">\n <div class="test-progress-pass" style="width:${a>0?(e.passed||0)/a*100:0}%"></div>\n <div class="test-progress-fail" style="width:${a>0?(e.failed||0)/a*100:0}%"></div>\n </div>\n </div>`}i+="</div>";const c=[];for(const s of Object.values(n.suites||{}))s.failures&&c.push(...s.failures);if(c.length>0){i+=`<div class="test-section-title">Failures (${c.length})</div>`;for(const s of c)i+=`\n <div class="test-failure-card">\n <div class="test-failure-name">${a(s.name)}</div>\n <div class="test-failure-file">${a(s.file)}</div>\n ${s.classification&&"unknown"!==s.classification?`<span class="test-failure-class">${a(s.classification)}</span>`:""}\n ${s.error?`<pre class="test-failure-error">${a(String(s.error).slice(0,500))}</pre>`:""}\n ${s.rerun_command?`<div class="test-failure-rerun"><code>${a(s.rerun_command)}</code></div>`:""}\n </div>`}const m=[];for(const[s,t]of Object.entries(n.suites||{}))t.skips&&m.push(...t.skips.map(t=>({...t,suite:s})));if(m.length>0){i+='<details class="test-skips-section">',i+=`<summary class="test-section-title" style="cursor:pointer">Skipped (${m.length}) — click to expand</summary>`,i+='<table class="test-groups-table"><thead><tr><th>Test</th><th>File</th><th>Suite</th></tr></thead><tbody>';for(const s of m.slice(0,50))i+=`<tr><td>${a(s.name)}</td><td class="meta">${a(s.file)}</td><td><span class="test-cat-badge test-cat-${a(s.suite)}">${a(s.suite)}</span></td></tr>`;m.length>50&&(i+=`<tr><td colspan="3" class="meta">...and ${m.length-50} more</td></tr>`),i+="</tbody></table></details>"}t.innerHTML=i}catch(n){t.innerHTML=`<div class="empty-state">Failed to load test results: ${a(n.message)}</div>`}}async function g(){const s=document.getElementById("testingHistory");if(s)try{const t=await e("/api/tests/history");if(!t.history||0===t.history.length)return void(s.innerHTML='<div class="meta">No run history yet.</div>');let n='<div class="test-section-title">Run History</div>';n+='\n <table class="test-history-table">\n <thead>\n <tr>\n <th>When</th>\n <th>Suite</th>\n <th>Status</th>\n <th class="num">Pass</th>\n <th class="num">Fail</th>\n <th class="num">Skip</th>\n <th class="num">Total</th>\n <th class="num">Duration</th>\n <th class="num">Rate</th>\n </tr>\n </thead>\n <tbody>';for(const s of t.history.slice(0,25)){const t=s.failed>0?"test-color-fail":"test-color-pass",e=f[s.suite]||s.suite||"?",i=h[s.suite]||h.unknown;n+=`\n <tr data-action="loadRunDetail" data-arg="${a(s.runId)}" style="cursor:pointer" class="${s.failed>0?"test-row-fail":""}">\n <td class="meta" style="white-space:nowrap">${p(s.timestamp)}</td>\n <td><span class="test-cat-badge" style="background:${i}20;color:${i}">${e}</span></td>\n <td class="${t}" style="font-weight:600">${s.failed>0?"FAIL":"PASS"} ▸</td>\n <td class="num">${s.passed}</td>\n <td class="num ${s.failed>0?"test-color-fail":""}">${s.failed}</td>\n <td class="num ${s.skipped>0?"test-color-skip":""}">${s.skipped}</td>\n <td class="num"><strong>${s.total}</strong></td>\n <td class="num">${u(s.duration_ms)}</td>\n <td class="num">${v(s.passed,s.failed)}</td>\n </tr>`}n+="</tbody></table>",n+='<div id="testingRunDetail"></div>',s.innerHTML=n}catch(t){s.innerHTML=`<div class="meta">Failed to load history: ${a(t.message)}</div>`}}async function $(s){var t,n;const i=document.getElementById("testingRunDetail");if(i){i.innerHTML='<div class="meta" style="padding:12px">Loading run detail...</div>';try{const l=await e("/api/tests/run-detail?runId="+encodeURIComponent(s));if(l.error)return void(i.innerHTML=`<div class="meta">${a(l.error)}</div>`);let r=`<div class="test-section-title">Run Detail: ${a(s)} <span class="meta" style="font-weight:400;font-size:11px;text-transform:none">${p(l.timestamp)}</span></div>`;r+=`<div class="test-suite-meta" style="margin-bottom:12px">${l.passed} pass, ${l.failed} fail, ${l.skipped} skip, ${l.total} total · ${u(l.duration_ms)} · ${v(l.passed,l.failed)} pass rate</div>`;if(!((null==(t=l.failures)?void 0:t.length)>0||(null==(n=l.skips)?void 0:n.length)>0)&&l.total>0&&(r+='<div class="meta" style="padding:8px 0;color:var(--text-2)">No detailed failure/skip data saved for this run. Run with <code>npm run test:all</code> to generate full reports.</div>'),l.failures&&l.failures.length>0){r+=`<div class="test-section-title">Failures (${l.failures.length})</div>`;for(const s of l.failures)r+=`\n <div class="test-failure-card">\n <div class="test-failure-name">${a(s.name)}</div>\n <div class="test-failure-file">${a(s.file)}</div>\n ${s.error?`<pre class="test-failure-error">${a(String(s.error).slice(0,500))}</pre>`:""}\n ${s.rerun_command?`<div class="test-failure-rerun"><code>${a(s.rerun_command)}</code></div>`:""}\n </div>`}if(l.skips&&l.skips.length>0){r+=`<details><summary class="test-section-title" style="cursor:pointer">Skipped (${l.skips.length})</summary>`,r+='<table class="test-groups-table"><thead><tr><th>Test</th><th>File</th></tr></thead><tbody>';for(const s of l.skips.slice(0,50))r+=`<tr><td>${a(s.name)}</td><td class="meta">${a(s.file)}</td></tr>`;l.skips.length>50&&(r+=`<tr><td colspan="2" class="meta">...and ${l.skips.length-50} more</td></tr>`),r+="</tbody></table></details>"}i.innerHTML=r,i.scrollIntoView({behavior:"smooth",block:"nearest"})}catch(l){i.innerHTML=`<div class="meta">Failed: ${a(l.message)}</div>`}}}let y=null;function b(){const s=document.getElementById("testProgressBar");s&&e("/api/tests/progress").then(t=>{var e;if(!t.running&&!t.finished)return void(s.innerHTML="");const n=((t.finished||Date.now())-t.started)/1e3,i=n>=60?(n/60).toFixed(1)+"m":Math.round(n)+"s",l=t.passed+t.failed+t.skipped,r=f[null==(e=t.suite)?void 0:e.replace("test:","")]||t.suite||"Tests";if(t.running){const e=t.current_file?t.current_file.split("/").pop():"";s.innerHTML=`\n <div class="test-progress-live">\n <div class="test-progress-live-header">\n <span class="test-progress-live-status">⏳ Running ${a(r)}...</span>\n <span class="meta">${i}</span>\n </div>\n <div class="test-progress-live-stats">\n <span class="test-color-pass">${t.passed} pass</span>\n <span class="test-color-fail">${t.failed} fail</span>\n <span class="test-color-skip">${t.skipped} skip</span>\n <span>${t.files_done} files</span>\n <span>${l} tests</span>\n </div>\n ${e?`<div class="test-progress-live-file">${a(e)}</div>`:""}\n <div class="test-progress-bar" style="margin-top:6px">\n <div class="test-progress-pass" style="width:${l>0?t.passed/l*100:0}%;transition:width 0.3s"></div>\n <div class="test-progress-fail" style="width:${l>0?t.failed/l*100:0}%;transition:width 0.3s"></div>\n </div>\n </div>`}else{const e=t.failed>0?"test-color-fail":"test-color-pass",n=t.failed>0?"FAILED":"PASSED";s.innerHTML=`\n <div class="test-progress-live test-progress-done">\n <div class="test-progress-live-header">\n <span class="${e}" style="font-weight:700">✓ ${a(r)} ${n}</span>\n <span class="meta">${i}</span>\n </div>\n <div class="test-progress-live-stats">\n <span class="test-color-pass">${t.passed} pass</span>\n <span class="test-color-fail">${t.failed} fail</span>\n <span class="test-color-skip">${t.skipped} skip</span>\n <span>${t.files_done} files</span>\n </div>\n </div>`,y&&(clearInterval(y),y=null),m(),g(),setTimeout(()=>{s&&(s.innerHTML="")},1e4)}}).catch(()=>{})}async function k(s){try{n(`Starting ${s}...`),await i("/api/tests/run",{suite:s}),y&&clearInterval(y),b(),y=setInterval(b,2e3)}catch(t){n("Failed to start tests: "+t.message,!0)}}export{o as i,$ as l,k as r,c as s};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|