ai-agent-session-center 2.4.7 → 2.7.1

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.
Files changed (35) hide show
  1. package/README.md +93 -21
  2. package/dist/client/assets/{AnalyticsView-BIehPYTj.js → AnalyticsView-G_cvUfoT.js} +1 -1
  3. package/dist/client/assets/{Charts.module-Dcvmbd12.js → Charts.module-Bxd2FHVJ.js} +1 -1
  4. package/dist/client/assets/{CyberdromeScene-B4h21eHD.js → CyberdromeScene-DIcjNW2r.js} +1 -1
  5. package/dist/client/assets/HistoryView-BAupwH2L.js +1 -0
  6. package/dist/client/assets/HistoryView-O-oQ87Dj.css +1 -0
  7. package/dist/client/assets/{ProjectBrowserView-BU9iZZrY.js → ProjectBrowserView-CXjXTXKL.js} +1 -1
  8. package/dist/client/assets/QueueView-CwHsNYTr.js +1 -0
  9. package/dist/client/assets/{TimelineView-ChZ6Uqfu.js → TimelineView-vGe6uk9c.js} +1 -1
  10. package/dist/client/assets/index-BcrRZAMD.css +1 -0
  11. package/dist/client/assets/index-BjuGsMul.js +193 -0
  12. package/dist/client/assets/{useQuery-C3bdk-O1.js → useQuery-C2Vi372Q.js} +1 -1
  13. package/dist/client/assets/{with-selector-DGgNkBL1.js → with-selector-hPHYbRc2.js} +1 -1
  14. package/dist/client/index.html +2 -2
  15. package/dist/client/screenshot-project-tab-compact.png +0 -0
  16. package/dist/client/screenshot-project-tab-detailed.png +0 -0
  17. package/hooks/dashboard-hook-codex.sh +9 -1
  18. package/hooks/dashboard-hook-gemini.sh +9 -1
  19. package/hooks/dashboard-hook.ps1 +12 -0
  20. package/hooks/dashboard-hook.sh +10 -1
  21. package/package.json +12 -9
  22. package/server/apiRouter.ts +187 -59
  23. package/server/db.ts +5 -1
  24. package/server/fileIndexCache.ts +189 -0
  25. package/server/index.ts +107 -8
  26. package/server/sessionStore.ts +52 -4
  27. package/server/sshManager.ts +4 -2
  28. package/server/wsManager.ts +3 -3
  29. package/static/screenshot-project-tab-compact.png +0 -0
  30. package/static/screenshot-project-tab-detailed.png +0 -0
  31. package/dist/client/assets/HistoryView-YHUVpKzh.js +0 -1
  32. package/dist/client/assets/HistoryView-khsGJftp.css +0 -1
  33. package/dist/client/assets/QueueView-Bz6nilD3.js +0 -1
  34. package/dist/client/assets/index-BXcolqev.js +0 -153
  35. package/dist/client/assets/index-QXMtnI3d.css +0 -1
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # AI Agent Session Center
2
2
 
3
- Real-time 3D dashboard for monitoring and controlling Claude Code, Gemini CLI, and Codex sessions — live SSH terminals, prompt history, tool logs, and queuing. Runs on any device.
4
-
5
- Every session spawns an animated robot in an interactive cyberdrome that visually reflects what the agent is doing — running when executing tools, waving when prompting, waiting when it needs your approval.
3
+ A lightweight, real-time dashboard that replaces heavy IDEs like VS Code and JetBrains for AI agent workflows. Monitor and control all your Claude Code, Gemini CLI, and Codex sessions from one place with live SSH terminals, prompt history, tool logs, and queuing. Every session spawns an animated 3D robot in an interactive cyberdrome that visually reflects what the agent is doing. Runs on any device, anywhere.
6
4
 
7
5
  [![npm version](https://img.shields.io/npm/v/ai-agent-session-center.svg)](https://www.npmjs.com/package/ai-agent-session-center)
8
6
  [![npm downloads](https://img.shields.io/npm/dm/ai-agent-session-center.svg)](https://www.npmjs.com/package/ai-agent-session-center)
@@ -21,8 +19,8 @@ Every session spawns an animated robot in an interactive cyberdrome that visuall
21
19
  <td><img src="static/screenshot-terminal.png" alt="SSH terminal session — control agents from the dashboard" width="400"></td>
22
20
  </tr>
23
21
  <tr>
24
- <td><img src="static/screenshot-project-tab.png" alt="Project file browser with split view — terminal and code side by side" width="400"></td>
25
- <td><img src="static/screenshot-detail.png" alt="Session detail panel with prompts, queue, and activity tabs" width="400"></td>
22
+ <td><img src="static/screenshot-project-tab-detailed.png" alt="Split view with detailed session switcher cards — terminal and project file browser side by side" width="400"></td>
23
+ <td><img src="static/screenshot-project-tab-compact.png" alt="Split view with compact session switcher — terminal and project file browser side by side" width="400"></td>
26
24
  </tr>
27
25
  </table>
28
26
 
@@ -47,23 +45,97 @@ When you're running multiple AI coding agents across different terminals — Cla
47
45
 
48
46
  ## Features
49
47
 
50
- - **One agent, one robot** — every AI coding session gets its own animated 3D character in the cyberdrome
51
- - **Live activity tracking** — robots animate based on what the agent is actually doing (writing, reading, running commands, waiting for approval)
52
- - **Multi-CLI support** — monitors Claude Code, Gemini CLI, and Codex simultaneously
53
- - **SSH terminal sessions** — create and manage SSH/local terminal connections directly from the dashboard
54
- - **Dynamic room system** — organize sessions into rooms with a full 3D office layout (rooms, coffee lounge, gym, corridor desks)
55
- - **Project file browser** — browse, search, and view project files with syntax highlighting, sub-tabs, and file bookmarks
56
- - **Terminal & file bookmarks** — save positions in terminal scrollback and code viewer lines for quick reference with notes
57
- - **Prompt queue** — stage, reorder, and send prompts to agents with drag-and-drop
58
- - **Split view** — view terminal and project files side-by-side with a draggable divider (ratio persisted per session)
59
- - **Team visualization** — sub-agent teams render as connected robots with animated laser-line beams
60
- - **Approval alerts** — screaming yellow card, visor flash, and 3-burst alarm when tools need your approval
61
- - **Session resume** — reconnect to disconnected Claude sessions with one click
48
+ ### 3D Cyberdrome Scene
49
+
50
+ - **One agent, one robot** — every AI coding session gets its own animated 3D character in an interactive cyberdrome
51
+ - **8 animation states** — robots idle, walk, run, wait, dance, wave, or go offline based on real-time session status
52
+ - **6 procedural robot models** — robot, mech, drone, spider, orb, and tank variants with auto-assigned neon colors
53
+ - **Dynamic room system** — four-quadrant office layout with desks, coffee lounge, gym, corridor rooms, and spatial navigation AI
54
+ - **Subagent connections** — parent-child agent teams render as connected robots with animated laser-line beams
55
+ - **Speech bubbles & particles** — floating dialogue shows current tool/prompt, burst particles on state transitions
56
+ - **Camera fly-to** — smooth animated camera focuses on the selected robot; OrbitControls for manual pan/zoom/rotate
57
+ - **Flat list fallback** — 2D sidebar list auto-activates if 3D crashes or for low-resource environments
58
+
59
+ ### Session Detail Panel
60
+
61
+ - **Resizable detail panel** — slides in from the right (320px–95vw) with 7 tabs: Terminal, Prompts, Project, Queue, Notes, Activity, Summary
62
+ - **Session switcher** — horizontal tab strip shows all active sessions with sequence numbers, pin/unpin, compact/detailed display modes
63
+ - **Editable metadata** — inline-edit title, label, accent color (customizes robot glow), and pin state; all persisted to SQLite + IndexedDB
64
+ - **Session controls** — Resume, Kill, Archive, Delete, Summarize, Alert, room assignment, and label chips (ONEOFF, HEAVY, IMPORTANT)
65
+ - **Split view** — Terminal and Project side-by-side with a draggable divider (ratio persisted per session)
66
+ - **Approval alerts** — yellow card, visor flash, and 3-burst alarm when tools need user approval
67
+
68
+ ### Terminal & SSH
69
+
70
+ - **Full terminal emulation** — xterm.js 5 with 256 colors, Unicode 11, WebLinks, and FitAddon
71
+ - **Local & SSH sessions** — create terminals with working directory, command, SSH host/key/password, tmux wrap/attach
72
+ - **Session resume** — reconnect to disconnected Claude sessions via `claude --resume` with one click
73
+ - **Terminal bookmarks** — save scroll positions with notes, jump back to any bookmarked line
74
+ - **Terminal toolbar** — fullscreen, clear, copy, paste, theme selector (auto, light, dark, Solarized, Dracula, custom)
75
+ - **Bidirectional WebSocket relay** — real-time I/O, 50ms debounced resize, Escape forwards `\x1b` to SSH
76
+
77
+ ### Project File Browser
78
+
79
+ - **Browse & search** — navigate project directories, full-text file search with cached results
80
+ - **Syntax highlighting** — code viewer with line numbers, word wrap toggle, and markdown outline panel
81
+ - **Sub-tab system** — open multiple directories/files in tabs within the Project panel
82
+ - **File bookmarks** — save line references with notes; bookmarked lines highlighted in the code viewer; cross-file navigation
83
+ - **Sort & filter** — sort by name or date, toggle date/time display, file size shown per entry
84
+ - **File editing** — inline editor with save support for quick edits
85
+
86
+ ### Multi-CLI Monitoring
87
+
88
+ - **Three AI CLIs** — Claude Code (up to 14 events), Gemini CLI (4 events), and Codex (1 event)
89
+ - **3 hook density levels** — High (full monitoring), Medium (default, 12 events), Low (5 events, minimal overhead)
90
+ - **File-based message queue** — hooks append to JSONL queue file via atomic POSIX append (~0.1ms); HTTP POST fallback
91
+ - **3–17ms end-to-end latency** — from hook fired to browser updated
92
+ - **5-priority session matching** — pending resume, terminal ID, working directory, path scan, PID parent check
93
+ - **Approval detection** — tool-category timeouts with child-process check; `PermissionRequest` event for reliable signal
94
+ - **CLI badge detection** — auto-detects CLAUDE, GEMINI, CODEX, or AIDER from launch command
95
+
96
+ ### Prompt Queue
97
+
98
+ - **Global queue view** — see all pending prompts across every session in one place
99
+ - **Per-session queue** — compose, reorder (drag-and-drop), send, and move prompts between sessions
100
+ - **Auto-send mode** — queued prompts auto-dispatch when the target session becomes idle
101
+
102
+ ### Analytics & History
103
+
104
+ - **History search** — full-text search across titles, projects, and labels with date range, status, and sort filters
105
+ - **Analytics dashboard** — summary cards, 7-day activity heatmap, tool usage breakdown, active projects ranking
106
+ - **Timeline view** — time-series visualization (hourly, daily, weekly) of sessions, prompts, and tool calls
107
+
108
+ ### Theming & Sound
109
+
62
110
  - **9 scene themes** — Command Center, Cyberpunk, Dracula, Nord, Monokai, Solarized, Light, Warm, Blonde
63
- - **Sound system** — 16 synthesized tones, per-CLI profiles, 6 ambient presets (rain, lo-fi, server room, deep space, coffee shop)
64
- - **Analytics** — usage heatmaps, tool breakdowns, project rankings, and timeline visualization
65
- - **History search** — full-text search across all prompts, responses, and tool names
66
- - **Keyboard shortcuts** — full keyboard navigation for power users
111
+ - **16 synthesized sounds** — per-CLI profiles with per-event sound mapping (chime, ping, alarm, fanfare, etc.)
112
+ - **6 ambient presets** — rain, lo-fi, server room, deep space, coffee shop, or off
113
+ - **Visual effects** — glowing card borders, pulsing animations, scanline CRT overlay, status particles, fog depth by theme
114
+
115
+ ### Notes & Summaries
116
+
117
+ - **Session notes** — plain-text notes with full CRUD, stored in both SQLite and IndexedDB
118
+ - **AI-powered summaries** — generate session summaries via configured LLM API with customizable prompt templates
119
+
120
+ ### Authentication & Security
121
+
122
+ - **Password protection** — optional login with HttpOnly cookie (1-hour TTL), rate-limited (5 attempts/15min)
123
+ - **Security headers** — X-Frame-Options, CSP, CORS, localhost-only hook endpoint, shell metacharacter injection prevention
124
+ - **Directory traversal protection** — `resolveProjectPath()` validates all file browser paths
125
+
126
+ ### Keyboard Shortcuts
127
+
128
+ - **Full keyboard navigation** — `/` search, `T` new terminal, `K` kill, `A` archive, `M` mute, `S` settings, `?` shortcuts panel
129
+ - **Rebindable shortcuts** — customize every shortcut from Settings with conflict detection
130
+ - **Session switching** — `Alt+Cmd+1`–`9` to select Nth session by status priority
131
+
132
+ ### Data Persistence
133
+
134
+ - **Dual storage** — SQLite on server (sessions, prompts, tools, events, notes) + IndexedDB via Dexie in browser (12 tables)
135
+ - **Auto-snapshots** — server saves full state every 10 seconds; SSH terminals auto-respawn on restart
136
+ - **Session ID migration** — seamless re-keying when sessions resume with new IDs
137
+
138
+ > See [docs/feature/README.md](docs/feature/README.md) for the complete features reference with architecture details and API documentation.
67
139
 
68
140
  ## Requirements
69
141
 
@@ -1 +1 @@
1
- import{j as e,r as y,a as P}from"./index-BXcolqev.js";import{u}from"./useQuery-C3bdk-O1.js";import{m as n,R as j,B as b,C as v,X as S,Y as _,T as C,n as T,o as $}from"./Charts.module-Dcvmbd12.js";import"./with-selector-DGgNkBL1.js";function g(){const t=getComputedStyle(document.documentElement);return{cyan:t.getPropertyValue("--accent-cyan").trim()||"#00e5ff",green:t.getPropertyValue("--accent-green").trim()||"#00ff88",orange:t.getPropertyValue("--accent-orange").trim()||"#ff9100",textDim:t.getPropertyValue("--text-dim").trim()||"#8888aa",textPrimary:t.getPropertyValue("--text-primary").trim()||"#e0e0ff",bgCard:t.getPropertyValue("--bg-card").trim()||"#12122a",borderSubtle:t.getPropertyValue("--border-subtle").trim()||"rgba(255,255,255,0.04)",bgPrimary:t.getPropertyValue("--bg-primary").trim()||"#0a0a1a"}}const N=t=>{const a=new MutationObserver(t);return a.observe(document.body,{attributes:!0,attributeFilter:["data-theme"]}),()=>a.disconnect()};function x(){return y.useSyncExternalStore(N,g,g)}async function m(t){const a=await P(t);if(!a.ok)throw new Error(`API error: ${a.status}`);return a.json()}function l(t){return t>=1e6?(t/1e6).toFixed(1)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}function w(t,a,r,i){const o=a===0?0:Math.max(0,Math.min(1,t/a));return`color-mix(in srgb, ${i} ${Math.round(o*100)}%, ${r})`}const f=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];function q(){const{data:t}=u({queryKey:["analytics-summary"],queryFn:()=>m("/api/db/analytics/summary"),staleTime:3e4}),{data:a}=u({queryKey:["analytics-tools"],queryFn:()=>m("/api/db/analytics/tools"),staleTime:3e4}),{data:r}=u({queryKey:["analytics-projects"],queryFn:()=>m("/api/db/analytics/projects"),staleTime:3e4}),{data:i}=u({queryKey:["analytics-heatmap"],queryFn:()=>m("/api/db/analytics/heatmap"),staleTime:3e4});return e.jsxs("div",{className:n.analyticsView,"data-testid":"analytics-view",children:[e.jsx(A,{summary:t??null}),e.jsxs("div",{className:n.analyticsGrid,children:[e.jsxs("div",{className:n.analyticsCard,children:[e.jsx("h4",{children:"Tool Usage"}),e.jsx(k,{data:a??[]})]}),e.jsxs("div",{className:n.analyticsCard,children:[e.jsx("h4",{children:"Active Projects"}),e.jsx(D,{data:r??[]})]}),e.jsxs("div",{className:n.analyticsCard,style:{gridColumn:"1 / -1"},children:[e.jsx("h4",{children:"Activity Heatmap"}),e.jsx(M,{data:i??[]})]})]})]})}function A({summary:t}){const a=[{label:"Total Sessions",value:l(t?.total_sessions??0),detail:"all time"},{label:"Total Prompts",value:l(t?.total_prompts??0),detail:"all time"},{label:"Total Tool Calls",value:l(t?.total_tool_calls??0),detail:"all time"},{label:"Active Sessions",value:l(t?.active_sessions??0),detail:"currently running"},{label:"Most Used Tool",value:t?.most_used_tool?.tool_name??"N/A",detail:t?.most_used_tool?l(t.most_used_tool.count)+" calls":""},{label:"Busiest Project",value:t?.busiest_project?.name??"N/A",detail:t?.busiest_project?l(t.busiest_project.count)+" sessions":""}];return e.jsx("div",{className:n.analyticsSummary,children:a.map(r=>e.jsxs("div",{className:n.summaryStat,children:[e.jsx("div",{className:n.statLabel,children:r.label}),e.jsx("div",{className:n.statValue,children:r.value}),e.jsx("div",{className:n.statDetail,children:r.detail})]},r.label))})}function k({data:t}){const a=x(),r=t.slice(0,15);return r.length===0?e.jsx(p,{message:"No tool data"}):e.jsx(j,{width:"100%",height:Math.max(200,r.length*28),children:e.jsxs(b,{data:r,layout:"vertical",margin:{top:4,right:40,bottom:4,left:100},children:[e.jsx(v,{strokeDasharray:"3 3",stroke:a.borderSubtle}),e.jsx(S,{type:"number",tick:{fill:a.textDim,fontSize:10}}),e.jsx(_,{type:"category",dataKey:"tool_name",tick:{fill:a.textDim,fontSize:10},width:96}),e.jsx(C,{contentStyle:{background:a.bgCard,border:`1px solid ${a.cyan}`,borderRadius:4,fontSize:11,color:a.textPrimary},formatter:((i,o,s)=>[`${l(i)} (${s.payload.percentage}%)`,"Calls"])}),e.jsx(T,{dataKey:"count",radius:[0,4,4,0],children:r.map((i,o)=>e.jsx($,{fill:a.cyan,fillOpacity:.85},o))})]})})}function D({data:t}){const a=x(),r=y.useMemo(()=>[...t].sort((i,o)=>o.session_count-i.session_count).slice(0,15),[t]);return r.length===0?e.jsx(p,{message:"No project data"}):e.jsx(j,{width:"100%",height:Math.max(200,r.length*28),children:e.jsxs(b,{data:r,layout:"vertical",margin:{top:4,right:40,bottom:4,left:120},children:[e.jsx(v,{strokeDasharray:"3 3",stroke:a.borderSubtle}),e.jsx(S,{type:"number",tick:{fill:a.textDim,fontSize:10}}),e.jsx(_,{type:"category",dataKey:"project_name",tick:{fill:a.textDim,fontSize:10},width:116}),e.jsx(C,{contentStyle:{background:a.bgCard,border:`1px solid ${a.cyan}`,borderRadius:4,fontSize:11,color:a.textPrimary},formatter:(i=>[l(i)+" sessions","Sessions"])}),e.jsx(T,{dataKey:"session_count",radius:[0,4,4,0],children:r.map((i,o)=>e.jsx($,{fill:a.green,fillOpacity:.85},o))})]})})}function M({data:t}){const a=x(),{grid:r,maxVal:i}=y.useMemo(()=>{const o=new Map;let s=0;for(const c of t){const d=`${c.day_of_week}-${c.hour}`;o.set(d,c.count),c.count>s&&(s=c.count)}return{grid:o,maxVal:s}},[t]);return t.length===0?e.jsx(p,{message:"No heatmap data"}):e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"40px repeat(24, 14px)",gridTemplateRows:"14px repeat(7, 14px)",gap:"2px",alignItems:"center"},children:[e.jsx("div",{}),Array.from({length:24},(o,s)=>e.jsx("div",{style:{fontSize:"9px",color:a.textDim,textAlign:"center"},children:s},`h-${s}`)),Array.from({length:7},(o,s)=>e.jsxs(y.Fragment,{children:[e.jsx("div",{style:{fontSize:"10px",color:a.textDim,textAlign:"right",paddingRight:"4px"},children:f[s]}),Array.from({length:24},(c,d)=>{const h=r.get(`${s}-${d}`)??0;return e.jsx("div",{className:n.heatmapCell,title:`${f[s]} ${String(d).padStart(2,"0")}:00 - ${h} events`,style:{backgroundColor:w(h,i,a.bgPrimary,a.green)}},`${s}-${d}`)})]},`row-${s}`))]})}function p({message:t}){return e.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",minHeight:"120px",color:"var(--text-dim, #555577)",fontSize:"0.85rem"},children:t})}export{q as default};
1
+ import{j as e,r as y,a as P}from"./index-BjuGsMul.js";import{u}from"./useQuery-C2Vi372Q.js";import{m as n,R as j,B as b,C as v,X as S,Y as _,T as C,n as T,o as $}from"./Charts.module-Bxd2FHVJ.js";import"./with-selector-hPHYbRc2.js";function g(){const t=getComputedStyle(document.documentElement);return{cyan:t.getPropertyValue("--accent-cyan").trim()||"#00e5ff",green:t.getPropertyValue("--accent-green").trim()||"#00ff88",orange:t.getPropertyValue("--accent-orange").trim()||"#ff9100",textDim:t.getPropertyValue("--text-dim").trim()||"#8888aa",textPrimary:t.getPropertyValue("--text-primary").trim()||"#e0e0ff",bgCard:t.getPropertyValue("--bg-card").trim()||"#12122a",borderSubtle:t.getPropertyValue("--border-subtle").trim()||"rgba(255,255,255,0.04)",bgPrimary:t.getPropertyValue("--bg-primary").trim()||"#0a0a1a"}}const N=t=>{const a=new MutationObserver(t);return a.observe(document.body,{attributes:!0,attributeFilter:["data-theme"]}),()=>a.disconnect()};function x(){return y.useSyncExternalStore(N,g,g)}async function m(t){const a=await P(t);if(!a.ok)throw new Error(`API error: ${a.status}`);return a.json()}function l(t){return t>=1e6?(t/1e6).toFixed(1)+"M":t>=1e3?(t/1e3).toFixed(1)+"K":String(t)}function w(t,a,r,i){const o=a===0?0:Math.max(0,Math.min(1,t/a));return`color-mix(in srgb, ${i} ${Math.round(o*100)}%, ${r})`}const f=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];function q(){const{data:t}=u({queryKey:["analytics-summary"],queryFn:()=>m("/api/db/analytics/summary"),staleTime:3e4}),{data:a}=u({queryKey:["analytics-tools"],queryFn:()=>m("/api/db/analytics/tools"),staleTime:3e4}),{data:r}=u({queryKey:["analytics-projects"],queryFn:()=>m("/api/db/analytics/projects"),staleTime:3e4}),{data:i}=u({queryKey:["analytics-heatmap"],queryFn:()=>m("/api/db/analytics/heatmap"),staleTime:3e4});return e.jsxs("div",{className:n.analyticsView,"data-testid":"analytics-view",children:[e.jsx(A,{summary:t??null}),e.jsxs("div",{className:n.analyticsGrid,children:[e.jsxs("div",{className:n.analyticsCard,children:[e.jsx("h4",{children:"Tool Usage"}),e.jsx(k,{data:a??[]})]}),e.jsxs("div",{className:n.analyticsCard,children:[e.jsx("h4",{children:"Active Projects"}),e.jsx(D,{data:r??[]})]}),e.jsxs("div",{className:n.analyticsCard,style:{gridColumn:"1 / -1"},children:[e.jsx("h4",{children:"Activity Heatmap"}),e.jsx(M,{data:i??[]})]})]})]})}function A({summary:t}){const a=[{label:"Total Sessions",value:l(t?.total_sessions??0),detail:"all time"},{label:"Total Prompts",value:l(t?.total_prompts??0),detail:"all time"},{label:"Total Tool Calls",value:l(t?.total_tool_calls??0),detail:"all time"},{label:"Active Sessions",value:l(t?.active_sessions??0),detail:"currently running"},{label:"Most Used Tool",value:t?.most_used_tool?.tool_name??"N/A",detail:t?.most_used_tool?l(t.most_used_tool.count)+" calls":""},{label:"Busiest Project",value:t?.busiest_project?.name??"N/A",detail:t?.busiest_project?l(t.busiest_project.count)+" sessions":""}];return e.jsx("div",{className:n.analyticsSummary,children:a.map(r=>e.jsxs("div",{className:n.summaryStat,children:[e.jsx("div",{className:n.statLabel,children:r.label}),e.jsx("div",{className:n.statValue,children:r.value}),e.jsx("div",{className:n.statDetail,children:r.detail})]},r.label))})}function k({data:t}){const a=x(),r=t.slice(0,15);return r.length===0?e.jsx(p,{message:"No tool data"}):e.jsx(j,{width:"100%",height:Math.max(200,r.length*28),children:e.jsxs(b,{data:r,layout:"vertical",margin:{top:4,right:40,bottom:4,left:100},children:[e.jsx(v,{strokeDasharray:"3 3",stroke:a.borderSubtle}),e.jsx(S,{type:"number",tick:{fill:a.textDim,fontSize:10}}),e.jsx(_,{type:"category",dataKey:"tool_name",tick:{fill:a.textDim,fontSize:10},width:96}),e.jsx(C,{contentStyle:{background:a.bgCard,border:`1px solid ${a.cyan}`,borderRadius:4,fontSize:11,color:a.textPrimary},formatter:((i,o,s)=>[`${l(i)} (${s.payload.percentage}%)`,"Calls"])}),e.jsx(T,{dataKey:"count",radius:[0,4,4,0],children:r.map((i,o)=>e.jsx($,{fill:a.cyan,fillOpacity:.85},o))})]})})}function D({data:t}){const a=x(),r=y.useMemo(()=>[...t].sort((i,o)=>o.session_count-i.session_count).slice(0,15),[t]);return r.length===0?e.jsx(p,{message:"No project data"}):e.jsx(j,{width:"100%",height:Math.max(200,r.length*28),children:e.jsxs(b,{data:r,layout:"vertical",margin:{top:4,right:40,bottom:4,left:120},children:[e.jsx(v,{strokeDasharray:"3 3",stroke:a.borderSubtle}),e.jsx(S,{type:"number",tick:{fill:a.textDim,fontSize:10}}),e.jsx(_,{type:"category",dataKey:"project_name",tick:{fill:a.textDim,fontSize:10},width:116}),e.jsx(C,{contentStyle:{background:a.bgCard,border:`1px solid ${a.cyan}`,borderRadius:4,fontSize:11,color:a.textPrimary},formatter:(i=>[l(i)+" sessions","Sessions"])}),e.jsx(T,{dataKey:"session_count",radius:[0,4,4,0],children:r.map((i,o)=>e.jsx($,{fill:a.green,fillOpacity:.85},o))})]})})}function M({data:t}){const a=x(),{grid:r,maxVal:i}=y.useMemo(()=>{const o=new Map;let s=0;for(const c of t){const d=`${c.day_of_week}-${c.hour}`;o.set(d,c.count),c.count>s&&(s=c.count)}return{grid:o,maxVal:s}},[t]);return t.length===0?e.jsx(p,{message:"No heatmap data"}):e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"40px repeat(24, 14px)",gridTemplateRows:"14px repeat(7, 14px)",gap:"2px",alignItems:"center"},children:[e.jsx("div",{}),Array.from({length:24},(o,s)=>e.jsx("div",{style:{fontSize:"9px",color:a.textDim,textAlign:"center"},children:s},`h-${s}`)),Array.from({length:7},(o,s)=>e.jsxs(y.Fragment,{children:[e.jsx("div",{style:{fontSize:"10px",color:a.textDim,textAlign:"right",paddingRight:"4px"},children:f[s]}),Array.from({length:24},(c,d)=>{const h=r.get(`${s}-${d}`)??0;return e.jsx("div",{className:n.heatmapCell,title:`${f[s]} ${String(d).padStart(2,"0")}:00 - ${h} events`,style:{backgroundColor:w(h,i,a.bgPrimary,a.green)}},`${s}-${d}`)})]},`row-${s}`))]})}function p({message:t}){return e.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",minHeight:"120px",color:"var(--text-dim, #555577)",fontSize:"0.85rem"},children:t})}export{q as default};