mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
feat: rename Active Tools to Project Insights panel
- Rename Active Tools panel to Project Insights with updated styling - Make panel bigger (450x350px) and resizable with drag handle - Add settings toggle in Display tab to enable/disable panel - Close subagent windows when parent session is killed/closed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+62
-35
@@ -443,11 +443,11 @@ class ClaudemanApp {
|
||||
this.subagentWindowZIndex = 1000;
|
||||
this.ralphStatePanelCollapsed = true; // Default to collapsed
|
||||
|
||||
// Active Bash tool tracking (for clickable file paths)
|
||||
this.activeTools = new Map(); // Map<sessionId, ActiveBashTool[]>
|
||||
// Project Insights tracking (active Bash tools with clickable file paths)
|
||||
this.projectInsights = new Map(); // Map<sessionId, ActiveBashTool[]>
|
||||
this.logViewerWindows = new Map(); // Map<windowId, { element, eventSource, filePath }>
|
||||
this.logViewerWindowZIndex = 2000;
|
||||
this.activeToolsPanelVisible = false;
|
||||
this.projectInsightsPanelVisible = false;
|
||||
|
||||
// Tab alert states: Map<sessionId, 'action' | 'idle'>
|
||||
this.tabAlerts = new Map();
|
||||
@@ -1073,8 +1073,9 @@ class ClaudemanApp {
|
||||
this.sessions.delete(data.id);
|
||||
this.terminalBuffers.delete(data.id);
|
||||
this.ralphStates.delete(data.id); // Clean up ralph state for this session
|
||||
this.activeTools.delete(data.id); // Clean up active tools for this session
|
||||
this.projectInsights.delete(data.id); // Clean up project insights for this session
|
||||
this.closeSessionLogViewerWindows(data.id); // Close log viewer windows for this session
|
||||
this.closeSessionSubagentWindows(data.id); // Close subagent windows for this session
|
||||
// Clean up idle timer for this session
|
||||
const idleTimer = this.idleTimers.get(data.id);
|
||||
if (idleTimer) {
|
||||
@@ -1088,7 +1089,7 @@ class ClaudemanApp {
|
||||
}
|
||||
this.renderSessionTabs();
|
||||
this.renderRalphStatePanel(); // Update ralph panel after session deleted
|
||||
this.renderActiveToolsPanel(); // Update active tools panel after session deleted
|
||||
this.renderProjectInsightsPanel(); // Update project insights panel after session deleted
|
||||
});
|
||||
|
||||
this.eventSource.addEventListener('session:terminal', (e) => {
|
||||
@@ -2032,8 +2033,8 @@ class ClaudemanApp {
|
||||
}
|
||||
this.renderRalphStatePanel();
|
||||
|
||||
// Update active tools panel for this session
|
||||
this.renderActiveToolsPanel();
|
||||
// Update project insights panel for this session
|
||||
this.renderProjectInsightsPanel();
|
||||
|
||||
this.terminal.focus();
|
||||
this.terminal.scrollToBottom();
|
||||
@@ -3643,6 +3644,7 @@ class ClaudemanApp {
|
||||
document.getElementById('appSettingsShowMonitor').checked = settings.showMonitor ?? true;
|
||||
document.getElementById('appSettingsSubagentTracking').checked = settings.subagentTrackingEnabled ?? true;
|
||||
document.getElementById('appSettingsShowSubagents').checked = settings.showSubagents ?? true;
|
||||
document.getElementById('appSettingsShowProjectInsights').checked = settings.showProjectInsights ?? true;
|
||||
// Claude CLI settings
|
||||
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
||||
const allowedToolsRow = document.getElementById('allowedToolsRow');
|
||||
@@ -3704,6 +3706,7 @@ class ClaudemanApp {
|
||||
showMonitor: document.getElementById('appSettingsShowMonitor').checked,
|
||||
subagentTrackingEnabled: document.getElementById('appSettingsSubagentTracking').checked,
|
||||
showSubagents: document.getElementById('appSettingsShowSubagents').checked,
|
||||
showProjectInsights: document.getElementById('appSettingsShowProjectInsights').checked,
|
||||
// Claude CLI settings
|
||||
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
||||
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
|
||||
@@ -3730,6 +3733,7 @@ class ClaudemanApp {
|
||||
// Apply header visibility immediately
|
||||
this.applyHeaderVisibilitySettings();
|
||||
this.applyMonitorVisibility();
|
||||
this.renderProjectInsightsPanel(); // Re-render to apply visibility setting
|
||||
|
||||
// Save to server (includes notification prefs for cross-browser persistence)
|
||||
try {
|
||||
@@ -5214,6 +5218,20 @@ class ClaudemanApp {
|
||||
}
|
||||
}
|
||||
|
||||
// Close all subagent windows for a session
|
||||
closeSessionSubagentWindows(sessionId) {
|
||||
const toClose = [];
|
||||
for (const [agentId, _windowData] of this.subagentWindows) {
|
||||
const agent = this.subagents.get(agentId);
|
||||
if (agent?.parentSessionId === sessionId) {
|
||||
toClose.push(agentId);
|
||||
}
|
||||
}
|
||||
for (const agentId of toClose) {
|
||||
this.closeSubagentWindow(agentId);
|
||||
}
|
||||
}
|
||||
|
||||
minimizeSubagentWindow(agentId) {
|
||||
const windowData = this.subagentWindows.get(agentId);
|
||||
if (windowData) {
|
||||
@@ -5335,76 +5353,85 @@ class ClaudemanApp {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Active Bash Tools (Clickable File Paths) ==========
|
||||
// ========== Project Insights Panel (Bash Tools with Clickable File Paths) ==========
|
||||
|
||||
handleBashToolStart(sessionId, tool) {
|
||||
let tools = this.activeTools.get(sessionId) || [];
|
||||
let tools = this.projectInsights.get(sessionId) || [];
|
||||
// Add new tool
|
||||
tools = tools.filter(t => t.id !== tool.id);
|
||||
tools.push(tool);
|
||||
this.activeTools.set(sessionId, tools);
|
||||
this.renderActiveToolsPanel();
|
||||
this.projectInsights.set(sessionId, tools);
|
||||
this.renderProjectInsightsPanel();
|
||||
}
|
||||
|
||||
handleBashToolEnd(sessionId, tool) {
|
||||
const tools = this.activeTools.get(sessionId) || [];
|
||||
const tools = this.projectInsights.get(sessionId) || [];
|
||||
const existing = tools.find(t => t.id === tool.id);
|
||||
if (existing) {
|
||||
existing.status = 'completed';
|
||||
}
|
||||
this.renderActiveToolsPanel();
|
||||
this.renderProjectInsightsPanel();
|
||||
// Remove after a short delay
|
||||
setTimeout(() => {
|
||||
const current = this.activeTools.get(sessionId) || [];
|
||||
this.activeTools.set(sessionId, current.filter(t => t.id !== tool.id));
|
||||
this.renderActiveToolsPanel();
|
||||
const current = this.projectInsights.get(sessionId) || [];
|
||||
this.projectInsights.set(sessionId, current.filter(t => t.id !== tool.id));
|
||||
this.renderProjectInsightsPanel();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
handleBashToolsUpdate(sessionId, tools) {
|
||||
this.activeTools.set(sessionId, tools);
|
||||
this.renderActiveToolsPanel();
|
||||
this.projectInsights.set(sessionId, tools);
|
||||
this.renderProjectInsightsPanel();
|
||||
}
|
||||
|
||||
renderActiveToolsPanel() {
|
||||
const panel = this.$('activeToolsPanel');
|
||||
const list = this.$('activeToolsList');
|
||||
renderProjectInsightsPanel() {
|
||||
const panel = this.$('projectInsightsPanel');
|
||||
const list = this.$('projectInsightsList');
|
||||
if (!panel || !list) return;
|
||||
|
||||
// Check if panel is enabled in settings
|
||||
const settings = this.loadAppSettingsFromStorage();
|
||||
const showProjectInsights = settings.showProjectInsights ?? true;
|
||||
if (!showProjectInsights) {
|
||||
panel.classList.remove('visible');
|
||||
this.projectInsightsPanelVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get tools for active session only
|
||||
const tools = this.activeTools.get(this.activeSessionId) || [];
|
||||
const tools = this.projectInsights.get(this.activeSessionId) || [];
|
||||
const runningTools = tools.filter(t => t.status === 'running');
|
||||
|
||||
if (runningTools.length === 0) {
|
||||
panel.classList.remove('visible');
|
||||
this.activeToolsPanelVisible = false;
|
||||
this.projectInsightsPanelVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
panel.classList.add('visible');
|
||||
this.activeToolsPanelVisible = true;
|
||||
this.projectInsightsPanelVisible = true;
|
||||
|
||||
const html = [];
|
||||
for (const tool of runningTools) {
|
||||
const cmdDisplay = tool.command.length > 40
|
||||
? tool.command.substring(0, 40) + '...'
|
||||
const cmdDisplay = tool.command.length > 50
|
||||
? tool.command.substring(0, 50) + '...'
|
||||
: tool.command;
|
||||
|
||||
html.push(`
|
||||
<div class="active-tool-item" data-tool-id="${tool.id}">
|
||||
<div class="active-tool-command">
|
||||
<div class="project-insight-item" data-tool-id="${tool.id}">
|
||||
<div class="project-insight-command">
|
||||
<span class="icon">💻</span>
|
||||
<span class="cmd" title="${this.escapeHtml(tool.command)}">${this.escapeHtml(cmdDisplay)}</span>
|
||||
<span class="active-tool-status ${tool.status}">${tool.status}</span>
|
||||
${tool.timeout ? `<span class="active-tool-timeout">${this.escapeHtml(tool.timeout)}</span>` : ''}
|
||||
<span class="project-insight-status ${tool.status}">${tool.status}</span>
|
||||
${tool.timeout ? `<span class="project-insight-timeout">${this.escapeHtml(tool.timeout)}</span>` : ''}
|
||||
</div>
|
||||
<div class="active-tool-paths">
|
||||
<div class="project-insight-paths">
|
||||
`);
|
||||
|
||||
for (const path of tool.filePaths) {
|
||||
const fileName = path.split('/').pop();
|
||||
html.push(`
|
||||
<span class="active-tool-filepath"
|
||||
<span class="project-insight-filepath"
|
||||
onclick="app.openLogViewerWindow('${this.escapeHtml(path)}', '${tool.sessionId}')"
|
||||
title="${this.escapeHtml(path)}">${this.escapeHtml(fileName)}</span>
|
||||
`);
|
||||
@@ -5419,11 +5446,11 @@ class ClaudemanApp {
|
||||
list.innerHTML = html.join('');
|
||||
}
|
||||
|
||||
closeActiveToolsPanel() {
|
||||
const panel = this.$('activeToolsPanel');
|
||||
closeProjectInsightsPanel() {
|
||||
const panel = this.$('projectInsightsPanel');
|
||||
if (panel) {
|
||||
panel.classList.remove('visible');
|
||||
this.activeToolsPanelVisible = false;
|
||||
this.projectInsightsPanelVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,13 +172,14 @@
|
||||
<div class="terminal-container" id="terminalContainer"></div>
|
||||
</main>
|
||||
|
||||
<!-- Active Tools Panel (shows file-viewing Bash commands) -->
|
||||
<div class="active-tools-panel" id="activeToolsPanel">
|
||||
<div class="active-tools-header">
|
||||
<span class="active-tools-title">Active Tools</span>
|
||||
<button class="btn-icon-sm" onclick="app.closeActiveToolsPanel()" title="Close">×</button>
|
||||
<!-- Project Insights Panel (shows file-viewing Bash commands) -->
|
||||
<div class="project-insights-panel" id="projectInsightsPanel">
|
||||
<div class="project-insights-header">
|
||||
<span class="project-insights-title">Project Insights</span>
|
||||
<button class="btn-icon-sm" onclick="app.closeProjectInsightsPanel()" title="Close">×</button>
|
||||
</div>
|
||||
<div class="active-tools-body" id="activeToolsList"></div>
|
||||
<div class="project-insights-body" id="projectInsightsList"></div>
|
||||
<div class="project-insights-resize-handle"></div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Toolbar -->
|
||||
@@ -629,6 +630,14 @@
|
||||
</label>
|
||||
<span class="form-hint">Show the Subagents panel (independent from Monitor)</span>
|
||||
</div>
|
||||
<div class="form-row form-row-switch">
|
||||
<label>Show Project Insights Panel</label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="appSettingsShowProjectInsights" checked>
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="form-hint">Show active tools and file viewers in a floating panel</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Claude CLI Tab -->
|
||||
<div class="modal-tab-content hidden" id="settings-claude">
|
||||
|
||||
+69
-47
@@ -3895,9 +3895,8 @@ kbd {
|
||||
padding: 0.5rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
background: #0a0a0a;
|
||||
color: #00ff41;
|
||||
text-shadow: 0 0 2px #00ff41;
|
||||
background: #111;
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
.subagent-window-body .activity-line {
|
||||
@@ -3908,26 +3907,24 @@ kbd {
|
||||
}
|
||||
|
||||
.subagent-window-body .activity-line .time {
|
||||
color: #00aa30;
|
||||
color: #888;
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.subagent-window-body .activity-line .tool-icon {
|
||||
flex: 0 0 auto;
|
||||
filter: brightness(1.2);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.subagent-window-body .activity-line .tool-name {
|
||||
color: #00ff41;
|
||||
font-weight: bold;
|
||||
color: #b0b0b0;
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
text-shadow: 0 0 4px #00ff41;
|
||||
}
|
||||
|
||||
.subagent-window-body .activity-line .tool-detail {
|
||||
color: #33ff66;
|
||||
color: #d0d0d0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -3935,13 +3932,12 @@ kbd {
|
||||
|
||||
.subagent-window-body .message-line {
|
||||
padding: 0.3rem 0;
|
||||
color: #00ff41;
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
.subagent-window-body .progress-line {
|
||||
color: #66ff99;
|
||||
color: #a0a0a0;
|
||||
font-style: italic;
|
||||
text-shadow: 0 0 3px #66ff99;
|
||||
}
|
||||
|
||||
/* Subagent Window Parent Tab Header */
|
||||
@@ -4007,14 +4003,16 @@ kbd {
|
||||
stroke-dashoffset: 1000;
|
||||
}
|
||||
|
||||
/* ========== Active Tools Panel (Bash File Viewers) ========== */
|
||||
/* ========== Project Insights Panel (Bash File Viewers) ========== */
|
||||
|
||||
.active-tools-panel {
|
||||
.project-insights-panel {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
top: calc(var(--header-height) + 10px);
|
||||
width: 350px;
|
||||
max-height: 200px;
|
||||
width: 450px;
|
||||
height: 350px;
|
||||
min-width: 300px;
|
||||
min-height: 200px;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
@@ -4022,13 +4020,15 @@ kbd {
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
resize: both;
|
||||
}
|
||||
|
||||
.active-tools-panel.visible {
|
||||
.project-insights-panel.visible {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.active-tools-header {
|
||||
.project-insights-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -4036,95 +4036,117 @@ kbd {
|
||||
background: var(--bg-input);
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-radius: 8px 8px 0 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.active-tools-title {
|
||||
.project-insights-title {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.active-tools-body {
|
||||
.project-insights-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.active-tool-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.4rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
background: var(--bg-input);
|
||||
margin-bottom: 0.3rem;
|
||||
.project-insights-resize-handle {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: se-resize;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.active-tool-item:last-child {
|
||||
.project-insights-resize-handle::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
bottom: 3px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-right: 2px solid var(--text-muted);
|
||||
border-bottom: 2px solid var(--text-muted);
|
||||
}
|
||||
|
||||
.project-insight-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.5rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
background: var(--bg-input);
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.project-insight-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.active-tool-command {
|
||||
.project-insight-command {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.active-tool-command .icon {
|
||||
font-size: 0.9rem;
|
||||
.project-insight-command .icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.active-tool-command .cmd {
|
||||
.project-insight-command .cmd {
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.active-tool-paths {
|
||||
.project-insight-paths {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
margin-top: 0.3rem;
|
||||
padding-left: 1.3rem;
|
||||
gap: 0.25rem;
|
||||
margin-top: 0.4rem;
|
||||
padding-left: 1.4rem;
|
||||
}
|
||||
|
||||
.active-tool-filepath {
|
||||
.project-insight-filepath {
|
||||
cursor: pointer;
|
||||
color: var(--accent);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
font-size: 0.75rem;
|
||||
text-decoration: underline;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.active-tool-filepath:hover {
|
||||
.project-insight-filepath:hover {
|
||||
color: var(--accent-hover);
|
||||
}
|
||||
|
||||
.active-tool-timeout {
|
||||
font-size: 0.65rem;
|
||||
.project-insight-timeout {
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-muted);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.active-tool-status {
|
||||
font-size: 0.65rem;
|
||||
padding: 0.1rem 0.3rem;
|
||||
.project-insight-status {
|
||||
font-size: 0.7rem;
|
||||
padding: 0.15rem 0.35rem;
|
||||
border-radius: 3px;
|
||||
margin-left: 0.3rem;
|
||||
}
|
||||
|
||||
.active-tool-status.running {
|
||||
.project-insight-status.running {
|
||||
background: var(--success);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.active-tool-status.completed {
|
||||
.project-insight-status.completed {
|
||||
background: var(--text-muted);
|
||||
color: white;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user