import type { WorkspaceAgentActivityTimelineItem } from "../../workspaceAgentTimelineTypes"; import type { AgentCollaborationVM } from "../contracts/agentCollaborationVM"; export const COLLABORATION_TIMELINE_ITEM_TYPE = "collaboration"; export function isCollaborationTimelineItem( item: Pick ): boolean { return ( item.itemType.trim().toLowerCase() === COLLABORATION_TIMELINE_ITEM_TYPE ); } /** * Pure projection of one durable collaboration message payload into the typed * card view model. Returns null when the payload has no run identity, so a * malformed row degrades to a plain assistant message instead of a broken * card. */ export function projectAgentCollaborationVM( item: Pick< WorkspaceAgentActivityTimelineItem, "agentSessionId" | "payload" | "status" | "workspaceId" > ): AgentCollaborationVM | null { const payload = normalizedPayload(item.payload); if (!payload) { return null; } const runId = stringField(payload, "runId"); const mode = stringField(payload, "mode"); if (!runId || !mode) { return null; } const status = stringField(payload, "status") ?? item.status?.trim() ?? "running"; return { kind: "collaboration", runId, workspaceId: item.workspaceId?.trim() || null, agentSessionId: item.agentSessionId.trim() || null, mode, status, triggerSource: stringField(payload, "triggerSource") ?? "user", triggerReason: stringField(payload, "triggerReason"), targetSessionId: stringField(payload, "targetSessionId"), targetAgentTargetId: stringField(payload, "targetAgentTargetId"), modelPlanId: stringField(payload, "modelPlanId"), modelPlanName: stringField(payload, "modelPlanName") ?? stringField(payload, "planName"), model: stringField(payload, "model"), contextScope: stringField(payload, "contextScope"), resultText: stringField(payload, "resultText"), failureReason: stringField(payload, "failureReason"), durationMs: positiveNumberField(payload, "durationMs"), usage: usageField(payload), adoption: stringField(payload, "adoption") ?? "not_applicable" }; } function usageField( payload: Record ): AgentCollaborationVM["usage"] { const usage = normalizedPayload( payload.usage as WorkspaceAgentActivityTimelineItem["payload"] ); if (!usage) { return null; } const inputTokens = nonNegativeNumberValue(usage.inputTokens); const outputTokens = nonNegativeNumberValue(usage.outputTokens); if (inputTokens === null && outputTokens === null) { return null; } return { inputTokens: inputTokens ?? 0, outputTokens: outputTokens ?? 0 }; } function normalizedPayload( payload: WorkspaceAgentActivityTimelineItem["payload"] ): Record | null { return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null; } function stringField( payload: Record, key: string ): string | null { const value = payload[key]; return typeof value === "string" && value.trim() ? value.trim() : null; } function positiveNumberField( payload: Record, key: string ): number | null { const value = nonNegativeNumberValue(payload[key]); return value !== null && value > 0 ? value : null; } function nonNegativeNumberValue(value: unknown): number | null { return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null; }