diff --git a/public/app.js b/public/app.js index e1fd290..31a58e9 100644 --- a/public/app.js +++ b/public/app.js @@ -116,13 +116,41 @@ function renderBoard() { const cardEl = document.createElement('div'); cardEl.className = 'card'; cardEl.innerHTML = ` -
-

${escapeHtml(task.title)}

- ${task.priority} +
+

${agent.emoji || '🤖'} ${escapeHtml(agent.name)}

+ ${agent.status} +
+
+ 🧠 ${agent.model || 'unknown'} + ⏰ ${agent.lastActivity ? new Date(agent.lastActivity).toLocaleString() : 'Never'} +
+
+ 📋 ${agent.workload} active task${agent.workload !== 1 ? 's' : ''} +
+
+
+

📋 Current Task

+

${agent.currentTask || 'No active task'}

-

${escapeHtml(task.description || '')}

-

${task.assignee || 'Unassigned'}

-

${task.tags.map((t) => `${escapeHtml(t)}`).join(' ')}

+
+

🛠️ Tools

+
+ ${agent.tools.length ? agent.tools.slice(0, 5).map((tool) => \`\${escapeHtml(tool)}\`).join('') : 'No tools'} + ${agent.tools.length > 5 ? \`+\${agent.tools.length - 5} more\` : ''} +
+
+
+

📄 Recent Files

+
+ ${agent.files.length ? agent.files.slice(0, 5).map((file) => \`\${escapeHtml(file)}\`).join('') : 'No files'} +
+
+
+
+ + +
+ `${escapeHtml(t)}`).join(' ')}

+
+ + +
+ `${escapeHtml(tool)}`).join('') : 'No tools'} ${agent.tools.length > 5 ? `+${agent.tools.length - 5} more` : ''} diff --git a/server.js b/server.js index 5c927b1..ce3df85 100644 --- a/server.js +++ b/server.js @@ -558,12 +558,44 @@ app.get('/api/agents', (req, res) => { }); }; - const agentPromises = agentDirs.map(async (agentName) => { - const agentPath = path.join(AGENTS_DIR, agentName); - const workspacePath = path.join(agentPath, 'workspace'); + // Load openclaw config for identity info + let emoji = '🤖'; + let model = 'unknown'; + let identityName = agentName; + + if (fs.existsSync(OPENCLAW_CONFIG)) { + try { + const openclawConfig = JSON.parse(fs.readFileSync(OPENCLAW_CONFIG, 'utf8')); + const agentConfig = openclawConfig.agents?.list?.find(a => a.id === agentName); + if (agentConfig) { + emoji = agentConfig.identity?.emoji || '🤖'; + model = agentConfig.model?.primary || 'unknown'; + identityName = agentConfig.identity?.name || agentName; + } + } catch {} + } + + // Get last activity from session files + let lastActivity = null; + const sessionsPath = path.join(agentPath, 'sessions'); + if (fs.existsSync(sessionsPath)) { + const sessionFiles = fs.readdirSync(sessionsPath).filter(f => f.endsWith('.jsonl')); + if (sessionFiles.length > 0) { + const latestSession = sessionFiles + .map(f => ({ file: f, mtime: fs.statSync(path.join(sessionsPath, f)).mtime })) + .sort((a, b) => b.mtime - a.mtime)[0]; + if (latestSession) { + lastActivity = latestSession.mtime.toISOString(); + } + } + } const agent = { - name: agentName, + id: agentName, + name: identityName, + emoji, + model, + lastActivity, status: 'active', currentTask: null, tools: [], @@ -574,10 +606,6 @@ app.get('/api/agents', (req, res) => { completedTasks: [], capabilities: [] }; - - if (fs.existsSync(workspacePath)) { - const files = fs.readdirSync(workspacePath); - agent.files = files.filter(f => f.endsWith('.md')); const memoryPath = path.join(workspacePath, 'MEMORY.md'); if (fs.existsSync(memoryPath)) {