import type { ExternalAgentProjectionV1, } from "pi-maestro-teammate/v1/external-agent-projections"; import type { SessionEndpoint, SessionHostSnapshot, SessionMessageRequest, SessionMessageResult, SessionViewMode, WindowThreadEntry, } from "pi-maestro-teammate/v1/sessions"; import { sanitizeExtensionStatusText } from "./extension-status.ts"; import type { AgentRow, FabricEndpointStatus, FabricHealth, FabricMonitorConnector, FabricMonitorCursor, FabricMonitorDevice, FabricMonitorEndpoint, FabricMonitorSnapshot, FabricStoreKind, } from "./types.ts"; export const SESSION_HOST_REGISTRY_EVENT = "teammate:sessions"; export const FABRIC_MONITOR_SNAPSHOT_EVENT = "fabric:monitor-snapshot"; export const SESSION_HOST_REGISTRY_KEY = Symbol.for("pi-maestro-teammate.session-host-registry.v1"); export const LEGACY_MAIN_ENDPOINT_ID = "cockpit-session/v1/main"; export const MONITOR_CONTROL_ENDPOINT_PREFIX = "cockpit-session/v1/window-control/"; export interface SessionMessageRouterLike { route(request: SessionMessageRequest): Promise; } /** Structural subset used so Cockpit can still load without the optional peer. */ export interface SessionHostRegistryLike { snapshot(): SessionHostSnapshot; subscribe( subscriber: (snapshot: SessionHostSnapshot) => void, options?: { emitCurrent?: boolean }, ): () => void; send?(request: SessionMessageRequest): Promise; requestWindowMode?(action: "enter" | "exit"): Promise; router?: SessionMessageRouterLike; } export interface SessionEventSource { on(event: string, handler: (payload: unknown) => void): () => void; } export interface CockpitEndpoint { /** Canonical registry id when available; deterministic legacy id otherwise. */ id: string; /** Source-independent identity used to migrate UI state onto canonical ids. */ logicalKey: string; kind: "root" | "agent" | "window"; label: string; ordinal: number; correlationId?: string; status: SessionEndpoint["status"]; contentRevision: string; /** Changes only when user-visible output changes, not for heartbeat/status churn. */ outputRevision?: string; /** Exact selector passed to SessionHostRegistry.send/MessageRouter. Empty for read-only external projections. */ routeSelector: string; source: "registry" | "legacy" | "external"; /** External agents are display-only and never participate in teammate routing. */ readOnly?: boolean; registryEndpoint?: SessionEndpoint; agentRow?: AgentRow; externalAgent?: ExternalAgentProjectionV1; contextPressure?: number; agentCount?: number; remoteAgents?: readonly SessionEndpoint[]; } export interface EndpointStoreSnapshot { contentRevision: string; mainEndpointId: string; viewMode: SessionViewMode; endpoints: readonly CockpitEndpoint[]; windows: readonly CockpitEndpoint[]; thread: readonly WindowThreadEntry[]; fabric?: FabricMonitorSnapshot; } export interface EndpointStoreOptions { getLegacyAgents: () => readonly AgentRow[]; } export function isMonitorControlEndpoint(endpoint: CockpitEndpoint | undefined): boolean { return endpoint?.kind === "window" && endpoint.registryEndpoint?.scope === "local"; } export interface EndpointStoreConnectOptions { registry?: SessionHostRegistryLike; events?: SessionEventSource; /** Current Cockpit Pi session; stale registry generations are rejected. */ sessionId?: string; } function legacyAgentEndpointId(correlationId: string): string { return `cockpit-session/v1/agent/${encodeURIComponent(correlationId)}`; } function externalAgentEndpointId(projection: ExternalAgentProjectionV1): string { return `cockpit-session/v1/external/${encodeURIComponent(projection.source)}/${encodeURIComponent(projection.id)}`; } function externalEndpointStatus(status: ExternalAgentProjectionV1["status"]): SessionEndpoint["status"] { if (status === "sleeping") return "sleeping"; if (status === "done" || status === "failed" || status === "terminated") return "settled"; return "running"; } function endpointLogicalKey(endpoint: Pick): string { return endpoint.kind === "root" ? "main" : `agent:${endpoint.correlationId ?? ""}`; } function cleanLabel(value: string | undefined, fallback: string): string { const clean = sanitizeExtensionStatusText(value ?? "").trim(); return clean || fallback; } const FABRIC_MONITOR_MAX_ITEMS = 100; const FABRIC_MONITOR_MAX_BYTES = 64 * 1024; const FABRIC_STORE_KINDS: readonly FabricStoreKind[] = ["registry", "lease", "presence", "invocation", "event"]; const FABRIC_HEALTH_VALUES: readonly FabricHealth[] = ["online", "degraded", "offline", "disabled", "unknown"]; const FABRIC_ENDPOINT_STATUS_VALUES: readonly FabricEndpointStatus[] = ["unknown", "online", "offline", "disabled"]; function record(value: unknown): Record | undefined { return value !== null && typeof value === "object" && !Array.isArray(value) ? value as Record : undefined; } function safeFabricIdentifier(value: unknown): string | undefined { return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(value) ? value : undefined; } function safeFabricInteger(value: unknown, minimum = 0): number | undefined { return Number.isSafeInteger(value) && (value as number) >= minimum ? value as number : undefined; } function fabricJsonByteLength(value: unknown): number | undefined { try { const serialized = JSON.stringify(value); return serialized === undefined ? undefined : new TextEncoder().encode(serialized).byteLength; } catch { return undefined; } } function parseFabricMonitorSnapshot(value: unknown): FabricMonitorSnapshot | undefined { try { const bytes = fabricJsonByteLength(value); if (bytes === undefined || bytes > FABRIC_MONITOR_MAX_BYTES) return undefined; const input = record(value); if (!input || input.version !== 1) return undefined; const sourceId = safeFabricIdentifier(input.sourceId); const revision = safeFabricInteger(input.revision, 1); const capturedAt = safeFabricInteger(input.capturedAt); if (!sourceId || revision === undefined || capturedAt === undefined || typeof input.truncated !== "boolean") return undefined; if (!Array.isArray(input.cursors) || !Array.isArray(input.connectors) || !Array.isArray(input.devices) || !Array.isArray(input.endpoints)) return undefined; const totalItems = input.connectors.length + input.devices.length + input.endpoints.length; if (totalItems > FABRIC_MONITOR_MAX_ITEMS || input.itemCount !== totalItems) return undefined; const cursors: FabricMonitorCursor[] = []; const cursorKinds = new Set(); if (input.cursors.length > FABRIC_STORE_KINDS.length) return undefined; for (const value of input.cursors) { const item = record(value); const storeKind = item?.storeKind; const cursor = safeFabricInteger(item?.cursor); if (!item || !FABRIC_STORE_KINDS.includes(storeKind as FabricStoreKind) || cursor === undefined || item.handle !== `fabric:${storeKind}` || cursorKinds.has(storeKind as FabricStoreKind)) return undefined; cursorKinds.add(storeKind as FabricStoreKind); cursors.push(Object.freeze({ handle: item.handle as string, storeKind: storeKind as FabricStoreKind, cursor, })); } const connectors: FabricMonitorConnector[] = []; for (const value of input.connectors) { const item = record(value); const connectorId = safeFabricIdentifier(item?.connectorId); const health = item?.health; const revision = safeFabricInteger(item?.revision); const connectionId = item?.connectionId === undefined ? undefined : safeFabricIdentifier(item.connectionId); const connectionGeneration = item?.connectionGeneration === undefined ? undefined : safeFabricInteger(item.connectionGeneration, 1); if (!item || item.kind !== "connector" || !connectorId || !FABRIC_HEALTH_VALUES.includes(health as FabricHealth) || typeof item.label !== "string" || typeof item.transport !== "string" || typeof item.enabled !== "boolean" || revision === undefined || (item.connectionId !== undefined && connectionId === undefined) || (item.connectionGeneration !== undefined && connectionGeneration === undefined)) return undefined; connectors.push(Object.freeze({ kind: "connector", connectorId, label: sanitizeExtensionStatusText(item.label), transport: sanitizeExtensionStatusText(item.transport), health: health as FabricHealth, enabled: item.enabled, revision, ...(connectionId === undefined ? {} : { connectionId }), ...(connectionGeneration === undefined ? {} : { connectionGeneration }), })); } const devices: FabricMonitorDevice[] = []; for (const value of input.devices) { const item = record(value); const deviceId = safeFabricIdentifier(item?.deviceId); const connectorId = safeFabricIdentifier(item?.connectorId); const health = item?.health; const revision = safeFabricInteger(item?.revision); if (!item || item.kind !== "device" || !deviceId || !connectorId || !FABRIC_HEALTH_VALUES.includes(health as FabricHealth) || typeof item.label !== "string" || typeof item.enabled !== "boolean" || revision === undefined) return undefined; devices.push(Object.freeze({ kind: "device", deviceId, connectorId, label: sanitizeExtensionStatusText(item.label), health: health as FabricHealth, enabled: item.enabled, revision, })); } const endpoints: FabricMonitorEndpoint[] = []; for (const value of input.endpoints) { const item = record(value); const endpointId = safeFabricIdentifier(item?.endpointId); const deviceId = safeFabricIdentifier(item?.deviceId); const connectorId = safeFabricIdentifier(item?.connectorId); const health = item?.health; const status = item?.status; const generation = safeFabricInteger(item?.generation, 1); const revision = safeFabricInteger(item?.revision); if (!item || item.kind !== "endpoint" || !endpointId || !deviceId || !connectorId || (item.endpointKind !== "agent" && item.endpointKind !== "mcp") || !FABRIC_HEALTH_VALUES.includes(health as FabricHealth) || !FABRIC_ENDPOINT_STATUS_VALUES.includes(status as FabricEndpointStatus) || typeof item.label !== "string" || generation === undefined || revision === undefined) return undefined; endpoints.push(Object.freeze({ kind: "endpoint", endpointId, deviceId, connectorId, endpointKind: item.endpointKind, label: sanitizeExtensionStatusText(item.label), health: health as FabricHealth, status: status as FabricEndpointStatus, generation, revision, })); } const snapshot: FabricMonitorSnapshot = Object.freeze({ version: 1, sourceId, revision, capturedAt, truncated: input.truncated, itemCount: totalItems, cursors: Object.freeze(cursors), connectors: Object.freeze(connectors), devices: Object.freeze(devices), endpoints: Object.freeze(endpoints), }); const storedBytes = fabricJsonByteLength(snapshot); return storedBytes !== undefined && storedBytes <= FABRIC_MONITOR_MAX_BYTES ? snapshot : undefined; } catch { return undefined; } } /** Stable 32-bit FNV-1a. This is change detection, not a security boundary. */ function revisionOf(value: unknown): string { const text = JSON.stringify(value); let hash = 2166136261; for (let index = 0; index < text.length; index++) { hash ^= text.charCodeAt(index); hash = Math.imul(hash, 16777619); } return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`; } function isEndpoint(value: unknown): value is SessionEndpoint { if (!value || typeof value !== "object") return false; const endpoint = value as Partial; return endpoint.version === 1 && typeof endpoint.id === "string" && endpoint.id.length > 0 && (endpoint.kind === "root" || endpoint.kind === "agent") && (endpoint.scope === "local" || endpoint.scope === "workspace-peer") && typeof endpoint.workspaceId === "string" && typeof endpoint.ownerId === "string" && typeof endpoint.ownerNonce === "string" && typeof endpoint.ordinal === "number" && Number.isSafeInteger(endpoint.ordinal) && typeof endpoint.contentRevision === "string" && (endpoint.status === "running" || endpoint.status === "sleeping" || endpoint.status === "settled"); } function sessionSnapshot(value: unknown): SessionHostSnapshot | undefined { if (!value || typeof value !== "object") return undefined; const snapshot = value as Partial; if (snapshot.version !== 1 || !Array.isArray(snapshot.endpoints)) return undefined; if (!snapshot.endpoints.every(isEndpoint)) return undefined; return snapshot as SessionHostSnapshot; } interface LocalSessionProjection { workspaceId: string; sessionId: string; sourceId: string; generation: number; } function localSessionProjection(endpoint: SessionEndpoint | undefined): LocalSessionProjection | undefined { if (!endpoint || endpoint.scope !== "local" || endpoint.kind !== "root" || endpoint.workspaceId.length === 0 || typeof endpoint.sessionId !== "string" || endpoint.sessionId.length === 0 || typeof endpoint.sourceId !== "string" || endpoint.sourceId.length === 0 || !Number.isSafeInteger(endpoint.generation) || (endpoint.generation ?? 0) < 1) return undefined; return { workspaceId: endpoint.workspaceId, sessionId: endpoint.sessionId, sourceId: endpoint.sourceId, generation: endpoint.generation!, }; } function sameLocalSessionProjection( left: LocalSessionProjection, right: LocalSessionProjection, ): boolean { return left.workspaceId === right.workspaceId && left.sessionId === right.sessionId && left.sourceId === right.sourceId && left.generation === right.generation; } function localEndpointsMatchProjection( endpoints: readonly SessionEndpoint[], projection: LocalSessionProjection, ): boolean { return endpoints.every((endpoint) => endpoint.scope !== "local" || ( endpoint.workspaceId === projection.workspaceId && endpoint.sessionId === projection.sessionId && endpoint.sourceId === projection.sourceId && endpoint.generation === projection.generation )); } export function isSessionHostRegistryLike(value: unknown): value is SessionHostRegistryLike { if (!value || typeof value !== "object") return false; const registry = value as Partial; return typeof registry.snapshot === "function" && typeof registry.subscribe === "function"; } function sameOwner(left: SessionEndpoint, right: SessionEndpoint): boolean { return left.workspaceId === right.workspaceId && left.ownerId === right.ownerId && left.ownerNonce === right.ownerNonce; } function rowOwnedByRoot(row: AgentRow, root: SessionEndpoint): boolean { return row.workspaceId === root.workspaceId && row.sessionId === root.sessionId && row.sourceId === root.sourceId && row.sessionGeneration === root.generation; } function visibleLegacyRows(rows: readonly AgentRow[]): AgentRow[] { return rows .filter((row) => !row.agent.startsWith("graph(")) .sort((left, right) => left.startedAt - right.startedAt || left.correlationId.localeCompare(right.correlationId, "en")); } function disambiguateAgentLabels(endpoints: CockpitEndpoint[]): void { const counts = new Map(); for (const endpoint of endpoints) { if (endpoint.kind !== "agent") continue; const key = endpoint.label.toLocaleLowerCase("en"); counts.set(key, (counts.get(key) ?? 0) + 1); } const ordinals = new Map(); for (const endpoint of endpoints) { if (endpoint.kind !== "agent") continue; const key = endpoint.label.toLocaleLowerCase("en"); if ((counts.get(key) ?? 0) < 2) continue; const ordinal = (ordinals.get(key) ?? 0) + 1; ordinals.set(key, ordinal); endpoint.label = `${endpoint.label}·${ordinal}`; } } /** * Canonical local endpoint projection for Cockpit. * * Registry snapshots own ids and ordinals. AgentsStore remains the content and * status fallback for older Teammate versions and for the short startup window * before the registry publishes its local root. */ export class EndpointStore { readonly #getLegacyAgents: EndpointStoreOptions["getLegacyAgents"]; #registry: SessionHostRegistryLike | undefined; #registrySnapshot: SessionHostSnapshot | undefined; #expectedSessionId: string | undefined; #acceptedLocalProjection: LocalSessionProjection | undefined; #registryDisposer: (() => void) | undefined; #eventDisposers: Array<() => void> = []; #externalAgents: readonly ExternalAgentProjectionV1[] = Object.freeze([]); #fabricSnapshot: FabricMonitorSnapshot | undefined; #fabricCapturedAtFence = -1; #lastFabricSourceId: string | undefined; #fabricRevisionFences = new Map(); #retiredFabricSources = new Set(); #mainOutputRevision: string | undefined; #snapshot: EndpointStoreSnapshot = Object.freeze({ contentRevision: revisionOf([]), mainEndpointId: LEGACY_MAIN_ENDPOINT_ID, viewMode: "agents", endpoints: Object.freeze([]), windows: Object.freeze([]), thread: Object.freeze([]), }); #subscribers = new Set<(snapshot: EndpointStoreSnapshot) => void>(); constructor(options: EndpointStoreOptions) { this.#getLegacyAgents = options.getLegacyAgents; this.refreshLegacy(); } connect(options: EndpointStoreConnectOptions = {}): void { this.disconnect(); this.#expectedSessionId = options.sessionId; this.#registry = options.registry; if (options.registry) { try { this.applyRegistrySnapshot(options.registry.snapshot()); } catch { this.#registrySnapshot = undefined; this.#acceptedLocalProjection = undefined; } try { this.#registryDisposer = options.registry.subscribe( (snapshot) => this.applyRegistrySnapshot(snapshot), { emitCurrent: false }, ); } catch { this.#registryDisposer = undefined; } } if (options.events) { try { this.#eventDisposers.push(options.events.on( SESSION_HOST_REGISTRY_EVENT, (payload) => this.applyRegistrySnapshot(payload), )); } catch { /* optional peer */ } try { this.#eventDisposers.push(options.events.on( FABRIC_MONITOR_SNAPSHOT_EVENT, (payload) => this.applyFabricSnapshot(payload), )); } catch { /* optional peer */ } } this.refreshLegacy(); } disconnect(): void { try { this.#registryDisposer?.(); } catch { /* best effort */ } for (const dispose of this.#eventDisposers) { try { dispose(); } catch { /* best effort */ } } this.#registryDisposer = undefined; this.#eventDisposers = []; this.#registry = undefined; this.#registrySnapshot = undefined; this.#expectedSessionId = undefined; this.#acceptedLocalProjection = undefined; this.#externalAgents = Object.freeze([]); this.#fabricSnapshot = undefined; this.#fabricCapturedAtFence = -1; this.#lastFabricSourceId = undefined; this.#fabricRevisionFences.clear(); this.#retiredFabricSources.clear(); this.#rebuild(); } get registry(): SessionHostRegistryLike | undefined { return this.#registry; } applyFabricSnapshot(value: unknown): boolean { if (value === undefined) { if (!this.#fabricSnapshot) return false; this.#lastFabricSourceId = this.#fabricSnapshot.sourceId; this.#fabricSnapshot = undefined; return this.#rebuild(); } const next = parseFabricMonitorSnapshot(value); if (!next || this.#retiredFabricSources.has(next.sourceId)) return false; const revisionFence = this.#fabricRevisionFences.get(next.sourceId) ?? 0; if (next.revision <= revisionFence) return false; const current = this.#fabricSnapshot; if (current?.sourceId !== next.sourceId) { const resumingClearedSource = current === undefined && next.sourceId === this.#lastFabricSourceId; if (resumingClearedSource ? next.capturedAt < this.#fabricCapturedAtFence : next.capturedAt <= this.#fabricCapturedAtFence) return false; if (current) this.#retireFabricSource(current.sourceId); } this.#fabricSnapshot = next; this.#lastFabricSourceId = next.sourceId; this.#recordFabricRevision(next.sourceId, next.revision); this.#fabricCapturedAtFence = Math.max(this.#fabricCapturedAtFence, next.capturedAt); return this.#rebuild(); } #recordFabricRevision(sourceId: string, revision: number): void { this.#fabricRevisionFences.delete(sourceId); this.#fabricRevisionFences.set(sourceId, revision); while (this.#fabricRevisionFences.size > 17) { this.#fabricRevisionFences.delete(this.#fabricRevisionFences.keys().next().value!); } } #retireFabricSource(sourceId: string): void { this.#retiredFabricSources.add(sourceId); while (this.#retiredFabricSources.size > 16) { this.#retiredFabricSources.delete(this.#retiredFabricSources.values().next().value!); } } applyRegistrySnapshot(value: unknown): boolean { const next = sessionSnapshot(value); if (!next) return false; const localRoot = next.endpoints.find((endpoint) => endpoint.scope === "local" && endpoint.kind === "root"); const nextProjection = localSessionProjection(localRoot); const sessionBound = this.#expectedSessionId !== undefined; // A session-bound Cockpit has no ownerless canonical compatibility mode: // the local root and every local endpoint must carry the full tuple. if (sessionBound && (!nextProjection || nextProjection.sessionId !== this.#expectedSessionId || !localEndpointsMatchProjection(next.endpoints, nextProjection))) return false; const accepted = this.#acceptedLocalProjection; if (accepted) { // Once a canonical local tuple is accepted, an incomplete snapshot cannot // erase it. Rebinding to a different workspace/session/source is explicit // through connect/disconnect, never inferred from an arriving snapshot. if (!nextProjection || nextProjection.workspaceId !== accepted.workspaceId || nextProjection.sessionId !== accepted.sessionId || nextProjection.sourceId !== accepted.sourceId || nextProjection.generation < accepted.generation || !localEndpointsMatchProjection(next.endpoints, nextProjection)) return false; } else if (nextProjection && !localEndpointsMatchProjection(next.endpoints, nextProjection)) { return false; } if (nextProjection && (!accepted || !sameLocalSessionProjection(accepted, nextProjection))) { this.#acceptedLocalProjection = nextProjection; } this.#registrySnapshot = next; return this.#rebuild(); } refreshLegacy(): boolean { return this.#rebuild(); } setMainOutputRevision(revision: string | undefined): boolean { if (revision === this.#mainOutputRevision) return false; this.#mainOutputRevision = revision; return this.#rebuild(); } /** Replace the current session's already-sanitized, read-only external agents. */ setExternalAgents(projections: readonly ExternalAgentProjectionV1[]): boolean { this.#externalAgents = Object.freeze([...projections]); return this.#rebuild(); } snapshot(): EndpointStoreSnapshot { return this.#snapshot; } get(id: string): CockpitEndpoint | undefined { return this.#snapshot.endpoints.find((endpoint) => endpoint.id === id) ?? this.#snapshot.windows.find((endpoint) => endpoint.id === id); } findAgent(correlationId: string): CockpitEndpoint | undefined { return this.#snapshot.endpoints.find( (endpoint) => endpoint.kind === "agent" && endpoint.correlationId === correlationId, ); } findWindow(ownerId: string): CockpitEndpoint | undefined { return this.#snapshot.windows.find((endpoint) => endpoint.registryEndpoint?.ownerId === ownerId); } subscribe( subscriber: (snapshot: EndpointStoreSnapshot) => void, options: { emitCurrent?: boolean } = {}, ): () => void { this.#subscribers.add(subscriber); if (options.emitCurrent !== false) subscriber(this.#snapshot); return () => this.#subscribers.delete(subscriber); } #rebuild(): boolean { const rows = visibleLegacyRows(this.#getLegacyAgents()); const rowsById = new Map(rows.map((row) => [row.correlationId, row])); const registrySnapshot = this.#registrySnapshot; const local = (registrySnapshot?.endpoints ?? []) .filter((endpoint) => endpoint.scope === "local") .sort((left, right) => left.ordinal - right.ordinal || left.id.localeCompare(right.id, "en")); const remote = (registrySnapshot?.endpoints ?? []) .filter((endpoint) => endpoint.scope === "workspace-peer") .sort((left, right) => left.ordinal - right.ordinal || left.id.localeCompare(right.id, "en")); const root = local.find((endpoint) => endpoint.kind === "root"); const registryAgents = root ? local.filter((endpoint) => endpoint.kind === "agent" && sameOwner(root, endpoint)) : []; const mainEndpointId = root?.id ?? LEGACY_MAIN_ENDPOINT_ID; const endpoints: CockpitEndpoint[] = [{ id: mainEndpointId, logicalKey: "main", kind: "root", label: "main", ordinal: root?.ordinal ?? 0, status: root?.status ?? "running", contentRevision: root?.contentRevision ?? "legacy-main", ...(this.#mainOutputRevision ? { outputRevision: this.#mainOutputRevision } : {}), routeSelector: root?.id ?? "main", source: root ? "registry" : "legacy", ...(root ? { registryEndpoint: root } : {}), }]; const usedRows = new Set(); for (const endpoint of registryAgents) { if (!endpoint.correlationId) continue; const candidateRow = rowsById.get(endpoint.correlationId); const row = candidateRow && root && rowOwnedByRoot(candidateRow, root) ? candidateRow : undefined; if ((row?.agent ?? endpoint.agent ?? "").startsWith("graph(")) continue; if (row) usedRows.add(row.correlationId); const output = row?.tail?.trim() || endpoint.summary?.trim(); endpoints.push({ id: endpoint.id, logicalKey: endpointLogicalKey(endpoint), kind: "agent", label: cleanLabel(row?.name || row?.role || row?.agent || endpoint.name || endpoint.agent, "agent"), ordinal: endpoint.ordinal, correlationId: endpoint.correlationId, status: endpoint.status, contentRevision: revisionOf([endpoint.contentRevision, row?.status, row?.phase, row?.lastActivityAt]), ...(output ? { outputRevision: revisionOf(output) } : {}), routeSelector: endpoint.correlationId, source: "registry", registryEndpoint: endpoint, ...(row ? { agentRow: row } : {}), }); } let ordinal = endpoints.reduce((highest, endpoint) => Math.max(highest, endpoint.ordinal), 0) + 1; for (const row of rows) { if (usedRows.has(row.correlationId) || root) continue; const output = row.tail.trim(); endpoints.push({ id: legacyAgentEndpointId(row.correlationId), logicalKey: `agent:${row.correlationId}`, kind: "agent", label: cleanLabel(row.name || row.role || row.agent, "agent"), ordinal: ordinal++, correlationId: row.correlationId, status: row.status === "sleeping" ? "sleeping" : row.status === "done" || row.status === "failed" || row.status === "terminated" ? "settled" : "running", contentRevision: revisionOf([row.correlationId, row.status, row.phase, row.lastActivityAt, row.tail]), ...(output ? { outputRevision: revisionOf(output) } : {}), routeSelector: row.correlationId, source: "legacy", agentRow: row, }); } for (const projection of this.#externalAgents) { endpoints.push({ id: externalAgentEndpointId(projection), logicalKey: `external:${projection.source}:${projection.id}`, kind: "agent", label: cleanLabel(projection.label, "external"), ordinal: ordinal++, status: externalEndpointStatus(projection.status), contentRevision: revisionOf([ projection.revision, projection.status, projection.activeTool, projection.activeToolArgs, projection.metrics, projection.updatedAt, ]), routeSelector: "", source: "external", readOnly: true, externalAgent: projection, }); } endpoints.sort((left, right) => left.ordinal - right.ordinal || left.id.localeCompare(right.id, "en")); disambiguateAgentLabels(endpoints); const thread = registrySnapshot?.thread ?? []; const viewMode = registrySnapshot?.viewMode ?? "agents"; const remoteRoots = remote.filter((endpoint) => endpoint.kind === "root"); const baseWindowLabels = new Map(remoteRoots.map((endpoint) => [ endpoint.id, cleanLabel(endpoint.sessionName, `window:${endpoint.ownerId.slice(0, 6)}`), ])); const windowLabelCounts = new Map(); for (const label of baseWindowLabels.values()) { const key = label.toLocaleLowerCase("en"); windowLabelCounts.set(key, (windowLabelCounts.get(key) ?? 0) + 1); } const monitorAggregationEnabled = viewMode === "windows" && root?.capabilities.includes("monitor-workspace-aggregation") === true; const windows: CockpitEndpoint[] = (viewMode === "agents" || monitorAggregationEnabled ? remoteRoots : []).map((endpoint) => { const remoteAgents = remote.filter((candidate) => candidate.kind === "agent" && sameOwner(endpoint, candidate) ); const peerThread = thread.filter((entry) => entry.peerOwnerId === endpoint.ownerId && entry.peerOwnerNonce === endpoint.ownerNonce ); const baseLabel = baseWindowLabels.get(endpoint.id)!; const label = (windowLabelCounts.get(baseLabel.toLocaleLowerCase("en")) ?? 0) > 1 ? `${baseLabel}·${endpoint.ownerId.slice(0, 6)}` : baseLabel; const activityRevision = revisionOf([ remoteAgents.map((agent) => agent.contentRevision), peerThread.map((entry) => entry.contentRevision), ]); return { id: endpoint.id, logicalKey: `window:${endpoint.ownerId}:${endpoint.ownerNonce}`, kind: "window" as const, label, ordinal: endpoint.ordinal, status: endpoint.status, contentRevision: revisionOf([endpoint.contentRevision, activityRevision]), ...(remoteAgents.length > 0 || peerThread.length > 0 ? { outputRevision: activityRevision } : {}), routeSelector: endpoint.id, source: "registry" as const, registryEndpoint: endpoint, ...(endpoint.contextPressure === undefined ? {} : { contextPressure: endpoint.contextPressure }), agentCount: endpoint.agentCount ?? remoteAgents.filter((agent) => agent.status !== "settled").length, remoteAgents: Object.freeze(remoteAgents), }; }); if (monitorAggregationEnabled && root) { const controlAgents = registryAgents.filter((endpoint) => !(endpoint.agent ?? "").startsWith("graph(") ); const controlActivityRevision = revisionOf([ this.#mainOutputRevision, controlAgents.map((agent) => agent.contentRevision), ]); windows.unshift({ id: `${MONITOR_CONTROL_ENDPOINT_PREFIX}${encodeURIComponent(root.id)}`, logicalKey: `monitor-control:${root.ownerId}:${root.ownerNonce}`, kind: "window", label: `control·${root.ownerId.slice(0, 6)}`, ordinal: Number.MIN_SAFE_INTEGER, status: root.status, contentRevision: revisionOf([root.contentRevision, controlActivityRevision]), ...(this.#mainOutputRevision || controlAgents.length > 0 ? { outputRevision: controlActivityRevision } : {}), routeSelector: root.id, source: "registry", registryEndpoint: root, agentCount: controlAgents.filter((agent) => agent.status !== "settled").length, remoteAgents: Object.freeze(controlAgents), }); } const contentRevision = revisionOf([ viewMode, endpoints.map((endpoint) => [ endpoint.id, endpoint.logicalKey, endpoint.ordinal, endpoint.contentRevision, endpoint.outputRevision, ]), windows.map((endpoint) => [endpoint.id, endpoint.contentRevision, endpoint.outputRevision]), this.#fabricSnapshot ? [this.#fabricSnapshot.sourceId, this.#fabricSnapshot.revision] : undefined, ]); if (contentRevision === this.#snapshot.contentRevision) return false; this.#snapshot = Object.freeze({ contentRevision, mainEndpointId, viewMode, endpoints: Object.freeze(endpoints), windows: Object.freeze(windows), thread: Object.freeze([...thread]), ...(this.#fabricSnapshot ? { fabric: this.#fabricSnapshot } : {}), }); for (const subscriber of this.#subscribers) subscriber(this.#snapshot); return true; } }