import { AgentMessage } from "@vertesia/common"; import { cn } from "@vertesia/ui/core"; import { CheckCircle, Clock } from "lucide-react"; import { useUITranslation } from '../../../../i18n/index.js'; import { i18nInstance, NAMESPACE } from '../../../../i18n/instance.js'; import { getWorkstreamId } from "./utils"; interface WorkstreamTabsProps { workstreams: Map; // Map of workstream_id to displayName activeWorkstream: string; onSelectWorkstream: (id: string) => void; count?: Map; // Optional count of messages per workstream completionStatus?: Map; // Optional completion status per workstream } /** * Component that displays tabs for different workstreams */ export default function WorkstreamTabs({ workstreams, activeWorkstream, onSelectWorkstream, count, completionStatus, }: WorkstreamTabsProps) { const { t } = useUITranslation(); // Create a new map with just the core workstreams const filteredWorkstreams = new Map(); filteredWorkstreams.set("all", t('agent.allMessages')); filteredWorkstreams.set("main", t('agent.main')); // Only add actual workstreams from messages (not our test workstreams) workstreams.forEach((name, id) => { if ( id !== "all" && id !== "main" && id !== "research_france" && id !== "statistics" ) { filteredWorkstreams.set(id, name); } }); // Replace workstreams with our filtered version workstreams = filteredWorkstreams; // Sort workstream entries in a predictable order: // 1. 'all' first // 2. 'main' second // 3. The rest alphabetically by ID const sortedWorkstreams = Array.from(workstreams.entries()).sort( ([idA], [idB]) => { if (idA === "all") return -1; if (idB === "all") return 1; if (idA === "main") return -1; if (idB === "main") return 1; return idA.localeCompare(idB); }, ); // Only show tabs if there are multiple workstreams (more than just 'all' and 'main') const hasMultipleWorkstreams = sortedWorkstreams.length > 2; // If there are no multiple workstreams, return an empty div to maintain layout if (!hasMultipleWorkstreams) { return
; } return (
{sortedWorkstreams.map(([id, name]) => ( ))}
); } /** * Helper function to extract workstream information from messages */ export function extractWorkstreams( messages: AgentMessage[], ): Map { const workstreams = new Map(); const t = i18nInstance.getFixedT(null, NAMESPACE); // Always include "all" and "main" workstreams workstreams.set("all", t('agent.allMessages')); workstreams.set("main", t('agent.main')); // Extract workstream IDs directly from message.workstream_id only messages.forEach((message) => { if ( message.workstream_id && message.workstream_id !== "main" && message.workstream_id !== "all" && !workstreams.has(message.workstream_id) ) { // Use the workstream_id as both the ID and the display name workstreams.set(message.workstream_id, message.workstream_id); console.log(`Found workstream: ${message.workstream_id}`); } }); // Special case: if there's only the 'main' workstream, we want to explicitly make sure it exists // This ensures that both 'all' and 'main' are added if no additional workstreams are found if (workstreams.size <= 2 && !workstreams.has("main")) { workstreams.set("main", t('agent.main')); } console.log("Final workstreams map:", workstreams); return workstreams; } /** * Filter messages by workstream */ export function filterMessagesByWorkstream( messages: AgentMessage[], workstreamId: string, ): AgentMessage[] { if (workstreamId === "all") { // Show all messages, no filtering needed return [...messages]; } else if (workstreamId === "main") { // For the main workstream, show only messages that belong to the main workstream // This excludes messages that belong to specific tasks/workstreams return messages.filter((message) => { const msgWorkstreamId = getWorkstreamId(message); return msgWorkstreamId === "main"; }); } else { // For specific workstreams, show only messages that match the workstream_id return messages.filter((message) => { const msgWorkstreamId = getWorkstreamId(message); return msgWorkstreamId === workstreamId; }); } }