Improve agent status dashboard: fix memory file detection, show status text and session count
- Fix departments route: use readdirSync instead of broken glob pattern to find memory files - Show global memory file info (last modified, size) when no per-agent files exist - Add status text label (Running/Idle) and session count display to AgentStatus component - Improve visual layout with fixed-width info column - Closes #2.
This commit is contained in:
parent
1cd5c252b3
commit
bbef0ebeed
2 changed files with 45 additions and 24 deletions
|
|
@ -1,22 +1,38 @@
|
|||
// GET /api/agent/departments — list departments with status
|
||||
import { execSync } from "child_process";
|
||||
import { readdirSync, statSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { DEPARTMENTS } from "@/lib/constants";
|
||||
|
||||
const MEMORY_DIR = "/home/sscoble/.openclaw/workspace/memory";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Get info about the most recent daily memory file
|
||||
let globalLastSession = null;
|
||||
let globalMemorySize = null;
|
||||
try {
|
||||
const files = readdirSync(MEMORY_DIR)
|
||||
.filter((f) => f.endsWith(".md"))
|
||||
.sort()
|
||||
.reverse();
|
||||
if (files.length > 0) {
|
||||
const latest = join(MEMORY_DIR, files[0]);
|
||||
const st = statSync(latest);
|
||||
globalLastSession = new Date(st.mtime).toISOString();
|
||||
globalMemorySize = formatBytes(st.size);
|
||||
}
|
||||
} catch {
|
||||
// memory dir not found
|
||||
}
|
||||
|
||||
const departments = DEPARTMENTS.map((d) => {
|
||||
const name = d.name.replace("@", "");
|
||||
let status = "idle";
|
||||
let lastSession = null;
|
||||
let memorySize = null;
|
||||
let lastSession = globalLastSession;
|
||||
let memorySize = globalMemorySize;
|
||||
|
||||
try {
|
||||
// Check for memory files per department
|
||||
const name = d.name.replace("@", "");
|
||||
const memPath = `/home/sscoble/.openclaw/workspace/memory/${name}-YYYY-MM-DD.md`;
|
||||
// Simple check: does a recent memory file exist?
|
||||
const today = new Date().toISOString().split("T")[0];
|
||||
const yesterday = new Date(Date.now() - 86400000).toISOString().split("T")[0];
|
||||
|
||||
// Check if the agent's process is running
|
||||
const procCheck = execSync(
|
||||
`pgrep -f 'openclaw.*${name}' || true`,
|
||||
|
|
@ -26,24 +42,21 @@ export async function GET() {
|
|||
status = "running";
|
||||
}
|
||||
|
||||
// Check memory file size
|
||||
// Check for per-agent memory file
|
||||
try {
|
||||
const stat = execSync(
|
||||
`stat --format='%Y %s' /home/sscoble/.openclaw/workspace/memory/${name}-*.md 2>/dev/null || true`,
|
||||
{ encoding: "utf-8", timeout: 2000 }
|
||||
);
|
||||
if (stat.trim()) {
|
||||
const parts = stat.trim().split(" ");
|
||||
const timestamp = parseInt(parts[0]) * 1000;
|
||||
const sizeBytes = parseInt(parts[1]);
|
||||
lastSession = new Date(timestamp).toISOString();
|
||||
memorySize = formatBytes(sizeBytes);
|
||||
const agentFiles = readdirSync(MEMORY_DIR)
|
||||
.filter((f) => f.startsWith(name) && f.endsWith(".md"));
|
||||
if (agentFiles.length > 0) {
|
||||
const latest = join(MEMORY_DIR, agentFiles.sort().reverse()[0]);
|
||||
const st = statSync(latest);
|
||||
lastSession = new Date(st.mtime).toISOString();
|
||||
memorySize = formatBytes(st.size);
|
||||
}
|
||||
} catch {
|
||||
// no memory file
|
||||
// no per-agent memory file, use global
|
||||
}
|
||||
} catch {
|
||||
// process check failed
|
||||
// process check failed, leave status as idle
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,14 @@ export default function AgentStatus({ agent }) {
|
|||
<p className="text-sm font-medium text-gray-200">{agent.name}</p>
|
||||
<p className="text-xs text-gray-500 truncate">{agent.role}</p>
|
||||
</div>
|
||||
<div className="text-right text-xs text-gray-500 flex-shrink-0">
|
||||
<div className="text-right text-xs text-gray-500 flex-shrink-0 min-w-[100px]">
|
||||
{agent.status && (
|
||||
<p className={`font-medium ${agent.status === "running" ? "text-green-400" : "text-yellow-400"}`}>
|
||||
{agent.status.charAt(0).toUpperCase() + agent.status.slice(1)}
|
||||
</p>
|
||||
)}
|
||||
{agent.lastSession && (
|
||||
<p>
|
||||
<p className="mt-0.5">
|
||||
{new Date(agent.lastSession).toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
|
|
@ -27,6 +32,9 @@ export default function AgentStatus({ agent }) {
|
|||
</p>
|
||||
)}
|
||||
{agent.memorySize && <p className="mt-0.5">{agent.memorySize}</p>}
|
||||
{agent.sessionCount !== undefined && (
|
||||
<p className="mt-0.5 text-gray-600">{agent.sessionCount} sessions</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue