import type { Agent, WorkspaceDescriptor } from "@/stores/session-store"; import { deriveSidebarStateBucket } from "./sidebar-agent-state"; export interface WorkspaceAgentActivity { agentId: string; status: WorkspaceDescriptor["status"]; enteredAt: Date | null; } export function buildWorkspaceAgentActivityIndex( agents: ReadonlyMap, previous?: ReadonlyMap, ): Map { const activityByWorkspaceId = new Map(); const latestActivityAtByWorkspaceId = new Map(); for (const agent of agents.values()) { if (agent.archivedAt || agent.parentAgentId || !agent.workspaceId) { continue; } const enteredAt = agent.attentionTimestamp ?? agent.updatedAt; const latestActivityAt = latestActivityAtByWorkspaceId.get(agent.workspaceId); if (latestActivityAt && enteredAt <= latestActivityAt) { continue; } latestActivityAtByWorkspaceId.set(agent.workspaceId, enteredAt); const status = deriveSidebarStateBucket({ status: agent.status, pendingPermissionCount: agent.pendingPermissions.length, requiresAttention: agent.requiresAttention, attentionReason: agent.attentionReason, }); activityByWorkspaceId.set(agent.workspaceId, { agentId: agent.id, status, enteredAt, }); } for (const [workspaceId, activity] of activityByWorkspaceId) { const previousActivity = previous?.get(workspaceId); if ( previousActivity?.agentId === activity.agentId && previousActivity.status === activity.status ) { activityByWorkspaceId.set(workspaceId, previousActivity); } } if (previous && areWorkspaceAgentActivityIndexesIdentical(previous, activityByWorkspaceId)) { return previous instanceof Map ? previous : new Map(previous); } return activityByWorkspaceId; } function areWorkspaceAgentActivityIndexesIdentical( previous: ReadonlyMap, next: ReadonlyMap, ): boolean { if (previous.size !== next.size) { return false; } for (const [workspaceId, activity] of next) { if (previous.get(workspaceId) !== activity) { return false; } } return true; }