@rubytech/create-sitedesk-code 0.1.510 → 0.1.511

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-sitedesk-code",
3
- "version": "0.1.510",
3
+ "version": "0.1.511",
4
4
  "description": "Install SiteDesk — automated back office for independent building contractors",
5
5
  "bin": {
6
6
  "create-sitedesk-code": "./dist/index.js"
@@ -9,6 +9,10 @@ Invoked by the admin agent directly.
9
9
 
10
10
  This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
11
11
 
12
+ ## 2026-07-26 (0.1.511)
13
+
14
+ - Fixed a dashboard bug where the Host CPU card could sit on a loading skeleton for a full minute after its figure had already arrived, even though the sidebar was showing the same number.
15
+
12
16
  ## 2026-07-26 (0.1.510)
13
17
 
14
18
  - The admin screens load faster: page assets are now sent pre-compressed, and the sessions list reads from disk without holding up everything else on the server.
@@ -0,0 +1 @@
1
+ import{o as e}from"./chunk-CltuBf4Z.js";import{B as t,D as n,K as r,V as i,W as a,a as o,l as s,m as c,p as l,s as u,v as d}from"./useSubAccountSwitcher-CJKjEPNN.js";import{n as f,t as p}from"./AdminLoginScreens-bksN0XPe.js";import{s as m}from"./useVoiceRecorder-ChnBrzbZ.js";import{a as h,b as g,f as _,t as v,y as ee}from"./AdminShell-BMPEWNZk.js";import{a as y,i as b,n as x,r as te}from"./page-BWFHRIAH.js";import{t as S}from"./chevron-left-DqYv3oFh.js";import{t as ne}from"./chevron-right-CQfPGsFb.js";import{t as re}from"./file-text-DMKw3nIk.js";import"./graph-labels-BZgd0L6n.js";var C=a(),w=e(r(),1),T=t();function E({onOpen:e}){return(0,T.jsx)(`footer`,{className:`admin-footer`,children:(0,T.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,T.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function D({sessionId:e,projectDir:t,sessionKey:n,contactName:r,onBack:i}){return(0,T.jsxs)(`div`,{className:`wa-web`,children:[(0,T.jsxs)(`header`,{className:`wa-web-header`,children:[i&&(0,T.jsx)(`button`,{type:`button`,className:`wa-web-back`,onClick:i,"aria-label":`Back`,children:(0,T.jsx)(S,{size:20})}),(0,T.jsx)(`span`,{className:`wa-web-avatar`,"aria-hidden":!0,children:(0,T.jsx)(y,{size:20})}),(0,T.jsx)(`div`,{className:`wa-web-titles`,children:(0,T.jsx)(`span`,{className:`wa-web-name`,children:r})})]}),(0,T.jsx)(`div`,{className:`wa-web-body`,children:(0,T.jsx)(m,{sessionId:e,projectDir:t,sessionKey:n,forceDeliveredOnly:!0})})]})}var O=6e4,k=60*O,A=24*k,j=O,M=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],N=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function P(e){return e<10?`0${e}`:String(e)}function F(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function I(e,t){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t))return`—`;let n=t-e;if(n<-j)return`—`;let r=n<0?0:n;if(r<O)return`just now`;if(r<k)return`${Math.floor(r/O)}m`;if(r<A)return`${Math.floor(r/k)}h`;let i=new Date(t),a=new Date(e),o=Math.round((F(i)-F(a))/A);if(o===1)return`yesterday`;if(o>=2&&o<=6)return N[a.getDay()];let s=P(a.getDate()),c=M[a.getMonth()];return a.getFullYear()===i.getFullYear()?`${s} ${c}`:`${s} ${c} ${a.getFullYear()}`}var ie={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Web chat`};function L({variant:e=`row`,count:t=1}){return(0,T.jsx)(T.Fragment,{children:Array.from({length:t},(t,n)=>(0,T.jsx)(`span`,{className:`dashboard-skeleton dashboard-skeleton--${e}`,"data-testid":`dashboard-skeleton`,"aria-hidden":`true`},n))})}var R=6e4;function ae(e){return e<12?`morning`:e<18?`afternoon`:`evening`}function z(e){return e&&e.trim().split(/\s+/)[0]||`there`}function B(e){if(!e)return`everything is running normally.`;let t=e.cpuPct,n=e.memUsedPct;return t!==null&&t>=.98||n!==null&&n>=.98?`system load is critical.`:t!==null&&t>=.9||n!==null&&n>=.9?`system load is high.`:`everything is running normally.`}function V(e){return e==null?`—`:`${Math.round(e*100)}%`}function H(e){return e.operatorName??e.whatsappName??e.senderId??e.title}function U(e,t){if(!e)return!1;let n=Date.parse(e);if(!Number.isFinite(n))return!1;let r=new Date(n),i=new Date(t);return r.getFullYear()===i.getFullYear()&&r.getMonth()===i.getMonth()&&r.getDate()===i.getDate()}function W(e){return e?e.replace(/^claude-/,``):null}var G=new Set([`sessions`,`conversations`,`tasks`,`artefacts`,`skills`,`stats`]),K=!1;function q(e,t,n,r){let i=e=>t.get(e)??null,a=r?r.getEntriesByType(`navigation`)[0]:void 0,o=r?r.getEntriesByType(`resource`).filter(e=>new URL(e.name,`http://x`).pathname.startsWith(`/assets/`)):[],s=e=>e===void 0||!Number.isFinite(e)?null:Math.round(e),c=e=>e?s(e):null;return{batchMs:e,sessionsMs:i(`sessions`),conversationsMs:i(`conversations`),tasksMs:i(`tasks`),artefactsMs:i(`artefacts`),skillsMs:i(`skills`),statsMs:i(`stats`),failed:[...G].filter(e=>n.has(e)).join(`,`)||`none`,ttfbMs:s(a?.responseStart),domContentLoadedMs:c(a?.domContentLoadedEventEnd),loadMs:c(a?.loadEventEnd),assetCount:o.length,assetBytes:o.reduce((e,t)=>e+(t.transferSize||0),0),assetMs:o.length?s(Math.max(...o.map(e=>e.responseEnd))):null}}function J({cacheKey:e,userName:t,onSelectWhatsappConversation:r}){let a=c(e),[l,f]=(0,w.useState)(null),[p,m]=(0,w.useState)(null),[h,v]=(0,w.useState)(null),y=(0,w.useRef)(!1),[b,x]=(0,w.useState)(null),[S,C]=(0,w.useState)(null),[E,D]=(0,w.useState)(null),[O,k]=(0,w.useState)(null),[A,j]=(0,w.useState)(new Set),[M,N]=(0,w.useState)(()=>new Set),P=(0,w.useCallback)(e=>{N(t=>t.has(e)?t:new Set(t).add(e))},[]),F=Date.now(),G=(0,w.useRef)(!1),J=(0,w.useRef)(new Map),Y=(0,w.useRef)(new Set);(0,w.useEffect)(()=>{if(!e)return;let t=!1;async function n(e,n,r,i){let o=Date.now();try{let s=await a(n);if(!s.ok)throw Error(`status ${s.status}`);let c=await s.json();t||i(r(c)),console.info(`[admin-ui] op=dashboard-fetch slice=${e} url=${n} outcome=ok ms=${Date.now()-o}`)}catch(t){Y.current.add(e),console.error(`[admin-ui] dashboard-fetch-failed slice=${e} url=${n} ms=${Date.now()-o} reason=${t instanceof Error?t.message:String(t)}`)}finally{J.current.set(e,Date.now()-o),P(e)}}let r={"sidebar-sessions":()=>n(`sessions`,`/api/admin/sidebar-sessions`,e=>e.sessions??[],f),"conversations-all":()=>n(`conversations`,`/api/whatsapp-reader/conversations-all`,e=>e.conversations??[],m),"tasks-list":()=>n(`tasks`,`/api/admin/tasks-list`,e=>e,C),"sidebar-artefacts":()=>n(`artefacts`,`/api/admin/sidebar-artefacts`,e=>e.artefacts??[],D),skills:()=>n(`skills`,`/api/admin/skills`,e=>e.skills??[],k)};async function o(){if(G.current)return;G.current=!0;let e=Date.now();try{await Promise.all([...Object.values(r).map(e=>e()),n(`stats`,`/api/admin/system-stats`,e=>e,x)])}finally{G.current=!1;let t=Date.now()-e;if(console.info(`[admin-ui] op=dashboard-refresh-settled ms=${t}`),!K){K=!0;try{let e=q(t,J.current,Y.current,typeof performance>`u`?null:performance);fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`dashboard-load`,...e}),keepalive:!0}).catch(()=>{})}catch{}}}}o();let s=null;try{s=new EventSource(i(`/api/admin/events`,e)),s.onmessage=e=>{if(document.visibilityState===`visible`)try{let{resource:t}=JSON.parse(e.data),n=t?r[t]:void 0;n&&n()}catch{}},s.onerror=()=>{console.error(`[admin-ui] dashboard-events stream error`)}}catch(e){console.error(`[admin-ui] dashboard-events unavailable reason=${e instanceof Error?e.message:String(e)}`)}let c=setInterval(()=>{document.visibilityState===`visible`&&o()},R),l=()=>{document.visibilityState===`visible`&&o()};return document.addEventListener(`visibilitychange`,l),()=>{t=!0,G.current=!1,clearInterval(c),s?.close(),document.removeEventListener(`visibilitychange`,l)}},[e,a]);let X=(0,w.useMemo)(()=>(l??[]).filter(e=>!e.isSubagent),[l]),Z=(0,w.useMemo)(()=>X.filter(e=>e.live),[X]),oe=(0,w.useMemo)(()=>(p??[]).filter(e=>U(e.lastMessageAt,F)).length,[p,F]),se=S?.open.length??0,Q=(0,w.useMemo)(()=>{let e=new Map;for(let t of p??[]){let n=e.get(t.channel)??[];n.push(t),e.set(t.channel,n)}return[...e.entries()].map(([e,t])=>{let n=t.reduce((e,t)=>t.lastMessageAt&&(!e||Date.parse(t.lastMessageAt)>Date.parse(e.lastMessageAt??``))?t:e,null);return{channel:e,count:t.length,preview:n?H(n):``,rows:t}})},[p]);(0,w.useEffect)(()=>{y.current||Q.length!==0&&(y.current=!0,v(Q[0].channel))},[Q]);let ce=(0,w.useCallback)(async e=>{if(!A.has(e)){j(t=>new Set(t).add(e));try{let t=await a(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e})});if(!t.ok){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} status=${t.status}`);return}console.info(`[admin-ui] dashboard-session-stop sessionId=${e}`),f(t=>(t??[]).map(t=>t.sessionId===e?{...t,live:!1}:t))}catch(t){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} reason=${t instanceof Error?t.message:String(t)}`)}finally{j(t=>{let n=new Set(t);return n.delete(e),n})}}},[a,A]),le=(0,w.useCallback)(t=>{if(!e||!t.downloadPath){console.error(`[admin-ui] dashboard-artefact-download-blocked id=${t.id} reason=${e?`not-downloadable`:`no-cache-key`}`);return}te(e,t.downloadPath,t.downloadRoot??`data`)},[e]),$=ae(new Date(F).getHours());return(0,T.jsxs)(`div`,{className:`dashboard-home`,children:[(0,T.jsx)(`p`,{className:`dashboard-greeting`,children:M.has(`stats`)?`Good ${$}, ${z(t)} — ${B(b)}`:`Good ${$}, ${z(t)}`}),(0,T.jsxs)(`div`,{className:`dashboard-stats`,children:[(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Live sessions`}),M.has(`sessions`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:Z.length}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`of `,X.length,` total`]})]}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Messages today`}),M.has(`conversations`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:oe}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`a`,{className:`admin-stat-card dashboard-stat-card dashboard-stat-card--link`,href:`/tasks`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Open tasks`}),M.has(`tasks`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:se}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Host CPU`}),M.has(`stats`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:V(b?.cpuPct??null)}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`RAM `,V(b?.memUsedPct??null)]})]}):(0,T.jsx)(L,{variant:`value`})]})]}),(0,T.jsxs)(`div`,{className:`dashboard-columns`,children:[(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Live now`}),M.has(`sessions`)?Z.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No live sessions right now.`}):Z.map(e=>{let t=[e.sessionId.slice(0,8),W(e.model),I(Date.parse(e.startedAt),F)].filter(Boolean).join(` · `);return(0,T.jsxs)(`div`,{className:`admin-card dashboard-live-card`,children:[(0,T.jsx)(`span`,{className:`admin-status-dot is-live`}),(0,T.jsxs)(`div`,{className:`dashboard-live-main`,children:[(0,T.jsx)(`span`,{className:`dashboard-live-name`,children:e.title}),(0,T.jsx)(`span`,{className:`dashboard-live-meta`,children:t})]}),(0,T.jsx)(`a`,{className:`admin-btn-cta dashboard-open-btn`,href:`/chat?session=${encodeURIComponent(e.sessionId)}`,children:`Open`}),(0,T.jsx)(`button`,{type:`button`,className:`dashboard-stop-btn`,"aria-label":`Stop ${e.title}`,disabled:A.has(e.sessionId),onClick:()=>void ce(e.sessionId),children:(0,T.jsx)(d,{size:12})})]},e.sessionId)}):(0,T.jsx)(L,{variant:`card`,count:2}),(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Recent artefacts`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-artefacts`,children:M.has(`artefacts`)?(E??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No recent artefacts.`}):(E??[]).slice(0,6).map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-artefact-row`,onClick:()=>le(e),children:[(0,T.jsx)(`span`,{className:`dashboard-artefact-icon`,children:e.kind===`agent-template`?(0,T.jsx)(g,{size:16}):(0,T.jsx)(re,{size:16})}),(0,T.jsx)(`div`,{className:`dashboard-artefact-body`,children:(0,T.jsx)(`span`,{className:`dashboard-artefact-name`,children:e.name})}),(0,T.jsx)(`span`,{className:`dashboard-artefact-time`,children:I(Date.parse(e.updatedAt),F)})]},e.id)):(0,T.jsx)(L,{count:3})}),(0,T.jsx)(`a`,{className:`admin-section-label dashboard-col-label dashboard-skills-label`,href:`/skills`,children:`Skills`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-skills`,children:M.has(`skills`)?(O??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No skills yet.`}):(O??[]).map(e=>(0,T.jsxs)(`a`,{className:`admin-row dashboard-skill-row`,href:`/skills`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-icon`,children:(0,T.jsx)(_,{size:16})}),(0,T.jsxs)(`div`,{className:`dashboard-skill-body`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-name`,children:e.skill}),(0,T.jsx)(`span`,{className:`dashboard-skill-plugin`,children:e.plugin})]})]},`${e.plugin}/${e.skill}`)):(0,T.jsx)(L,{count:2})})]}),(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Channels`}),M.has(`conversations`)?Q.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No channel activity.`}):Q.map(e=>{let t=h===e.channel;return(0,T.jsxs)(`div`,{className:`admin-card dashboard-channel-card`,children:[(0,T.jsxs)(`button`,{type:`button`,className:`dashboard-channel-head`,"aria-expanded":t,onClick:()=>v(t=>t===e.channel?null:e.channel),children:[(0,T.jsx)(`span`,{className:`dashboard-channel-glyph`,children:e.channel===`whatsapp`||e.channel===`telegram`?(0,T.jsx)(s,{channel:e.channel,size:16}):(0,T.jsx)(n,{size:16})}),(0,T.jsx)(`span`,{className:`dashboard-channel-name`,children:ie[e.channel]??e.channel}),(0,T.jsx)(`span`,{className:`dashboard-channel-badge`,children:e.count}),(0,T.jsx)(`span`,{className:`dashboard-channel-chevron`,children:t?(0,T.jsx)(ee,{size:14}):(0,T.jsx)(ne,{size:14})})]}),t?(0,T.jsx)(`div`,{className:`dashboard-channel-convs`,children:e.rows.map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-channel-conv-row`,onClick:()=>r(e),title:e.title,children:[(0,T.jsx)(`span`,{className:`dashboard-channel-conv-name`,children:o(e)}),(0,T.jsx)(`span`,{className:`dashboard-channel-conv-tag`,children:e.isHouse?`House`:`Client`}),e.lastMessageAt&&(0,T.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:I(Date.parse(e.lastMessageAt),F)})]},u(e)))}):e.preview&&(0,T.jsx)(`span`,{className:`dashboard-channel-preview`,children:e.preview})]},e.channel)}):(0,T.jsx)(L,{variant:`card`,count:2})]})]})]})}function Y(){let e=f(),[t,n]=(0,w.useState)(!1);(0,w.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let r=(0,w.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t){console.info(`[admin-ui] claude-info-open cached=true ms=0`);return}let r=Date.now();if(!e.cacheKey){console.error(`[admin-ui] claude-info-fetch-skipped reason=no-session-key`);return}try{let t=await fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(e.cacheKey)}`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}console.info(`[admin-ui] claude-info-open cached=false ms=${Date.now()-r}`)}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),i=(0,w.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,T.jsx)(l,{cacheKey:e.cacheKey,onSessionExpired:i,surface:`chat`,children:(0,T.jsx)(v,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,claudeConnected:e.claudeConnected,onConnectClaude:()=>e.setAppState(`connect-claude`),userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(E,{onOpen:r}),(0,T.jsx)(h,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,T.jsx)(T.Fragment,{children:t.dataOpen&&e.cacheKey?(0,T.jsx)(x,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.remoteJid&&t.selectedWhatsapp.accountId?(0,T.jsx)(b,{accountId:t.selectedWhatsapp.accountId,remoteJid:t.selectedWhatsapp.remoteJid,contactName:o(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(D,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,contactName:o(t.selectedWhatsapp),onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(J,{cacheKey:e.cacheKey,userName:e.userName,onSelectWhatsappConversation:t.onSelectWhatsappConversation})})})}):(0,T.jsx)(p,{auth:e})}(0,C.createRoot)(document.getElementById(`root`)).render((0,T.jsx)(Y,{}));
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>SiteDesk</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-DGr1HuPg.js"></script>
8
+ <script type="module" crossorigin src="/assets/admin-Do53K90C.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-CltuBf4Z.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-CJKjEPNN.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/graph-labels-BZgd0L6n.js">
@@ -1 +0,0 @@
1
- import{o as e}from"./chunk-CltuBf4Z.js";import{B as t,D as n,K as r,V as i,W as a,a as o,l as s,m as c,p as l,s as u,v as d}from"./useSubAccountSwitcher-CJKjEPNN.js";import{n as f,t as p}from"./AdminLoginScreens-bksN0XPe.js";import{s as m}from"./useVoiceRecorder-ChnBrzbZ.js";import{a as h,b as g,f as _,t as v,y as ee}from"./AdminShell-BMPEWNZk.js";import{a as y,i as b,n as x,r as te}from"./page-BWFHRIAH.js";import{t as S}from"./chevron-left-DqYv3oFh.js";import{t as ne}from"./chevron-right-CQfPGsFb.js";import{t as re}from"./file-text-DMKw3nIk.js";import"./graph-labels-BZgd0L6n.js";var C=a(),w=e(r(),1),T=t();function E({onOpen:e}){return(0,T.jsx)(`footer`,{className:`admin-footer`,children:(0,T.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,T.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function D({sessionId:e,projectDir:t,sessionKey:n,contactName:r,onBack:i}){return(0,T.jsxs)(`div`,{className:`wa-web`,children:[(0,T.jsxs)(`header`,{className:`wa-web-header`,children:[i&&(0,T.jsx)(`button`,{type:`button`,className:`wa-web-back`,onClick:i,"aria-label":`Back`,children:(0,T.jsx)(S,{size:20})}),(0,T.jsx)(`span`,{className:`wa-web-avatar`,"aria-hidden":!0,children:(0,T.jsx)(y,{size:20})}),(0,T.jsx)(`div`,{className:`wa-web-titles`,children:(0,T.jsx)(`span`,{className:`wa-web-name`,children:r})})]}),(0,T.jsx)(`div`,{className:`wa-web-body`,children:(0,T.jsx)(m,{sessionId:e,projectDir:t,sessionKey:n,forceDeliveredOnly:!0})})]})}var O=6e4,k=60*O,A=24*k,j=O,M=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],N=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function P(e){return e<10?`0${e}`:String(e)}function F(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function I(e,t){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t))return`—`;let n=t-e;if(n<-j)return`—`;let r=n<0?0:n;if(r<O)return`just now`;if(r<k)return`${Math.floor(r/O)}m`;if(r<A)return`${Math.floor(r/k)}h`;let i=new Date(t),a=new Date(e),o=Math.round((F(i)-F(a))/A);if(o===1)return`yesterday`;if(o>=2&&o<=6)return N[a.getDay()];let s=P(a.getDate()),c=M[a.getMonth()];return a.getFullYear()===i.getFullYear()?`${s} ${c}`:`${s} ${c} ${a.getFullYear()}`}var ie={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Web chat`};function L({variant:e=`row`,count:t=1}){return(0,T.jsx)(T.Fragment,{children:Array.from({length:t},(t,n)=>(0,T.jsx)(`span`,{className:`dashboard-skeleton dashboard-skeleton--${e}`,"data-testid":`dashboard-skeleton`,"aria-hidden":`true`},n))})}var R=6e4;function ae(e){return e<12?`morning`:e<18?`afternoon`:`evening`}function z(e){return e&&e.trim().split(/\s+/)[0]||`there`}function B(e){if(!e)return`everything is running normally.`;let t=e.cpuPct,n=e.memUsedPct;return t!==null&&t>=.98||n!==null&&n>=.98?`system load is critical.`:t!==null&&t>=.9||n!==null&&n>=.9?`system load is high.`:`everything is running normally.`}function V(e){return e==null?`—`:`${Math.round(e*100)}%`}function H(e){return e.operatorName??e.whatsappName??e.senderId??e.title}function U(e,t){if(!e)return!1;let n=Date.parse(e);if(!Number.isFinite(n))return!1;let r=new Date(n),i=new Date(t);return r.getFullYear()===i.getFullYear()&&r.getMonth()===i.getMonth()&&r.getDate()===i.getDate()}function W(e){return e?e.replace(/^claude-/,``):null}var G=new Set([`sessions`,`conversations`,`tasks`,`artefacts`,`skills`,`stats`]),K=!1;function q(e,t,n,r){let i=e=>t.get(e)??null,a=r?r.getEntriesByType(`navigation`)[0]:void 0,o=r?r.getEntriesByType(`resource`).filter(e=>new URL(e.name,`http://x`).pathname.startsWith(`/assets/`)):[],s=e=>e===void 0||!Number.isFinite(e)?null:Math.round(e),c=e=>e?s(e):null;return{batchMs:e,sessionsMs:i(`sessions`),conversationsMs:i(`conversations`),tasksMs:i(`tasks`),artefactsMs:i(`artefacts`),skillsMs:i(`skills`),statsMs:i(`stats`),failed:[...G].filter(e=>n.has(e)).join(`,`)||`none`,ttfbMs:s(a?.responseStart),domContentLoadedMs:c(a?.domContentLoadedEventEnd),loadMs:c(a?.loadEventEnd),assetCount:o.length,assetBytes:o.reduce((e,t)=>e+(t.transferSize||0),0),assetMs:o.length?s(Math.max(...o.map(e=>e.responseEnd))):null}}function J({cacheKey:e,userName:t,onSelectWhatsappConversation:r}){let a=c(e),[l,f]=(0,w.useState)(null),[p,m]=(0,w.useState)(null),[h,v]=(0,w.useState)(null),y=(0,w.useRef)(!1),[b,x]=(0,w.useState)(null),[S,C]=(0,w.useState)(null),[E,D]=(0,w.useState)(null),[O,k]=(0,w.useState)(null),[A,j]=(0,w.useState)(new Set),[M,N]=(0,w.useState)(()=>new Set),P=(0,w.useCallback)(e=>{N(t=>t.has(e)?t:new Set(t).add(e))},[]),F=Date.now(),G=(0,w.useRef)(!1),J=(0,w.useRef)(new Map),Y=(0,w.useRef)(new Set);(0,w.useEffect)(()=>{if(!e)return;let t=!1;async function n(e,n,r,i){let o=Date.now();try{let s=await a(n);if(!s.ok)throw Error(`status ${s.status}`);let c=await s.json();t||i(r(c)),console.info(`[admin-ui] op=dashboard-fetch slice=${e} url=${n} outcome=ok ms=${Date.now()-o}`)}catch(t){Y.current.add(e),console.error(`[admin-ui] dashboard-fetch-failed slice=${e} url=${n} ms=${Date.now()-o} reason=${t instanceof Error?t.message:String(t)}`)}finally{J.current.set(e,Date.now()-o),t||P(e)}}let r={"sidebar-sessions":()=>n(`sessions`,`/api/admin/sidebar-sessions`,e=>e.sessions??[],f),"conversations-all":()=>n(`conversations`,`/api/whatsapp-reader/conversations-all`,e=>e.conversations??[],m),"tasks-list":()=>n(`tasks`,`/api/admin/tasks-list`,e=>e,C),"sidebar-artefacts":()=>n(`artefacts`,`/api/admin/sidebar-artefacts`,e=>e.artefacts??[],D),skills:()=>n(`skills`,`/api/admin/skills`,e=>e.skills??[],k)};async function o(){if(G.current)return;G.current=!0;let e=Date.now();try{await Promise.all([...Object.values(r).map(e=>e()),n(`stats`,`/api/admin/system-stats`,e=>e,x)])}finally{G.current=!1;let t=Date.now()-e;if(console.info(`[admin-ui] op=dashboard-refresh-settled ms=${t}`),!K){K=!0;try{let e=q(t,J.current,Y.current,typeof performance>`u`?null:performance);fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`dashboard-load`,...e}),keepalive:!0}).catch(()=>{})}catch{}}}}o();let s=null;try{s=new EventSource(i(`/api/admin/events`,e)),s.onmessage=e=>{if(document.visibilityState===`visible`)try{let{resource:t}=JSON.parse(e.data),n=t?r[t]:void 0;n&&n()}catch{}},s.onerror=()=>{console.error(`[admin-ui] dashboard-events stream error`)}}catch(e){console.error(`[admin-ui] dashboard-events unavailable reason=${e instanceof Error?e.message:String(e)}`)}let c=setInterval(()=>{document.visibilityState===`visible`&&o()},R),l=()=>{document.visibilityState===`visible`&&o()};return document.addEventListener(`visibilitychange`,l),()=>{t=!0,clearInterval(c),s?.close(),document.removeEventListener(`visibilitychange`,l)}},[e,a]);let X=(0,w.useMemo)(()=>(l??[]).filter(e=>!e.isSubagent),[l]),Z=(0,w.useMemo)(()=>X.filter(e=>e.live),[X]),oe=(0,w.useMemo)(()=>(p??[]).filter(e=>U(e.lastMessageAt,F)).length,[p,F]),se=S?.open.length??0,Q=(0,w.useMemo)(()=>{let e=new Map;for(let t of p??[]){let n=e.get(t.channel)??[];n.push(t),e.set(t.channel,n)}return[...e.entries()].map(([e,t])=>{let n=t.reduce((e,t)=>t.lastMessageAt&&(!e||Date.parse(t.lastMessageAt)>Date.parse(e.lastMessageAt??``))?t:e,null);return{channel:e,count:t.length,preview:n?H(n):``,rows:t}})},[p]);(0,w.useEffect)(()=>{y.current||Q.length!==0&&(y.current=!0,v(Q[0].channel))},[Q]);let ce=(0,w.useCallback)(async e=>{if(!A.has(e)){j(t=>new Set(t).add(e));try{let t=await a(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e})});if(!t.ok){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} status=${t.status}`);return}console.info(`[admin-ui] dashboard-session-stop sessionId=${e}`),f(t=>(t??[]).map(t=>t.sessionId===e?{...t,live:!1}:t))}catch(t){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} reason=${t instanceof Error?t.message:String(t)}`)}finally{j(t=>{let n=new Set(t);return n.delete(e),n})}}},[a,A]),le=(0,w.useCallback)(t=>{if(!e||!t.downloadPath){console.error(`[admin-ui] dashboard-artefact-download-blocked id=${t.id} reason=${e?`not-downloadable`:`no-cache-key`}`);return}te(e,t.downloadPath,t.downloadRoot??`data`)},[e]),$=ae(new Date(F).getHours());return(0,T.jsxs)(`div`,{className:`dashboard-home`,children:[(0,T.jsx)(`p`,{className:`dashboard-greeting`,children:M.has(`stats`)?`Good ${$}, ${z(t)} — ${B(b)}`:`Good ${$}, ${z(t)}`}),(0,T.jsxs)(`div`,{className:`dashboard-stats`,children:[(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Live sessions`}),M.has(`sessions`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:Z.length}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`of `,X.length,` total`]})]}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Messages today`}),M.has(`conversations`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:oe}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`a`,{className:`admin-stat-card dashboard-stat-card dashboard-stat-card--link`,href:`/tasks`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Open tasks`}),M.has(`tasks`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:se}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Host CPU`}),M.has(`stats`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:V(b?.cpuPct??null)}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`RAM `,V(b?.memUsedPct??null)]})]}):(0,T.jsx)(L,{variant:`value`})]})]}),(0,T.jsxs)(`div`,{className:`dashboard-columns`,children:[(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Live now`}),M.has(`sessions`)?Z.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No live sessions right now.`}):Z.map(e=>{let t=[e.sessionId.slice(0,8),W(e.model),I(Date.parse(e.startedAt),F)].filter(Boolean).join(` · `);return(0,T.jsxs)(`div`,{className:`admin-card dashboard-live-card`,children:[(0,T.jsx)(`span`,{className:`admin-status-dot is-live`}),(0,T.jsxs)(`div`,{className:`dashboard-live-main`,children:[(0,T.jsx)(`span`,{className:`dashboard-live-name`,children:e.title}),(0,T.jsx)(`span`,{className:`dashboard-live-meta`,children:t})]}),(0,T.jsx)(`a`,{className:`admin-btn-cta dashboard-open-btn`,href:`/chat?session=${encodeURIComponent(e.sessionId)}`,children:`Open`}),(0,T.jsx)(`button`,{type:`button`,className:`dashboard-stop-btn`,"aria-label":`Stop ${e.title}`,disabled:A.has(e.sessionId),onClick:()=>void ce(e.sessionId),children:(0,T.jsx)(d,{size:12})})]},e.sessionId)}):(0,T.jsx)(L,{variant:`card`,count:2}),(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Recent artefacts`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-artefacts`,children:M.has(`artefacts`)?(E??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No recent artefacts.`}):(E??[]).slice(0,6).map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-artefact-row`,onClick:()=>le(e),children:[(0,T.jsx)(`span`,{className:`dashboard-artefact-icon`,children:e.kind===`agent-template`?(0,T.jsx)(g,{size:16}):(0,T.jsx)(re,{size:16})}),(0,T.jsx)(`div`,{className:`dashboard-artefact-body`,children:(0,T.jsx)(`span`,{className:`dashboard-artefact-name`,children:e.name})}),(0,T.jsx)(`span`,{className:`dashboard-artefact-time`,children:I(Date.parse(e.updatedAt),F)})]},e.id)):(0,T.jsx)(L,{count:3})}),(0,T.jsx)(`a`,{className:`admin-section-label dashboard-col-label dashboard-skills-label`,href:`/skills`,children:`Skills`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-skills`,children:M.has(`skills`)?(O??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No skills yet.`}):(O??[]).map(e=>(0,T.jsxs)(`a`,{className:`admin-row dashboard-skill-row`,href:`/skills`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-icon`,children:(0,T.jsx)(_,{size:16})}),(0,T.jsxs)(`div`,{className:`dashboard-skill-body`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-name`,children:e.skill}),(0,T.jsx)(`span`,{className:`dashboard-skill-plugin`,children:e.plugin})]})]},`${e.plugin}/${e.skill}`)):(0,T.jsx)(L,{count:2})})]}),(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Channels`}),M.has(`conversations`)?Q.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No channel activity.`}):Q.map(e=>{let t=h===e.channel;return(0,T.jsxs)(`div`,{className:`admin-card dashboard-channel-card`,children:[(0,T.jsxs)(`button`,{type:`button`,className:`dashboard-channel-head`,"aria-expanded":t,onClick:()=>v(t=>t===e.channel?null:e.channel),children:[(0,T.jsx)(`span`,{className:`dashboard-channel-glyph`,children:e.channel===`whatsapp`||e.channel===`telegram`?(0,T.jsx)(s,{channel:e.channel,size:16}):(0,T.jsx)(n,{size:16})}),(0,T.jsx)(`span`,{className:`dashboard-channel-name`,children:ie[e.channel]??e.channel}),(0,T.jsx)(`span`,{className:`dashboard-channel-badge`,children:e.count}),(0,T.jsx)(`span`,{className:`dashboard-channel-chevron`,children:t?(0,T.jsx)(ee,{size:14}):(0,T.jsx)(ne,{size:14})})]}),t?(0,T.jsx)(`div`,{className:`dashboard-channel-convs`,children:e.rows.map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-channel-conv-row`,onClick:()=>r(e),title:e.title,children:[(0,T.jsx)(`span`,{className:`dashboard-channel-conv-name`,children:o(e)}),(0,T.jsx)(`span`,{className:`dashboard-channel-conv-tag`,children:e.isHouse?`House`:`Client`}),e.lastMessageAt&&(0,T.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:I(Date.parse(e.lastMessageAt),F)})]},u(e)))}):e.preview&&(0,T.jsx)(`span`,{className:`dashboard-channel-preview`,children:e.preview})]},e.channel)}):(0,T.jsx)(L,{variant:`card`,count:2})]})]})]})}function Y(){let e=f(),[t,n]=(0,w.useState)(!1);(0,w.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let r=(0,w.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t){console.info(`[admin-ui] claude-info-open cached=true ms=0`);return}let r=Date.now();if(!e.cacheKey){console.error(`[admin-ui] claude-info-fetch-skipped reason=no-session-key`);return}try{let t=await fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(e.cacheKey)}`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}console.info(`[admin-ui] claude-info-open cached=false ms=${Date.now()-r}`)}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),i=(0,w.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,T.jsx)(l,{cacheKey:e.cacheKey,onSessionExpired:i,surface:`chat`,children:(0,T.jsx)(v,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,claudeConnected:e.claudeConnected,onConnectClaude:()=>e.setAppState(`connect-claude`),userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(E,{onOpen:r}),(0,T.jsx)(h,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,T.jsx)(T.Fragment,{children:t.dataOpen&&e.cacheKey?(0,T.jsx)(x,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.remoteJid&&t.selectedWhatsapp.accountId?(0,T.jsx)(b,{accountId:t.selectedWhatsapp.accountId,remoteJid:t.selectedWhatsapp.remoteJid,contactName:o(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(D,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,contactName:o(t.selectedWhatsapp),onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(J,{cacheKey:e.cacheKey,userName:e.userName,onSelectWhatsappConversation:t.onSelectWhatsappConversation})})})}):(0,T.jsx)(p,{auth:e})}(0,C.createRoot)(document.getElementById(`root`)).render((0,T.jsx)(Y,{}));