import type { Positionable, Position3D } from "$lib/types/positionable.js"; import type { AISessionConfig, AISessionResponse, ModelType } from "./RemoteComputeManager.svelte"; export type ComputeStatus = "disconnected" | "ready" | "running" | "stopped" | "initializing"; export class RemoteCompute implements Positionable { readonly id: string; // Reactive state using Svelte 5 runes position = $state({ x: 0, y: 0, z: 0 }); name = $state(""); status = $state("disconnected"); modelType = $state("act"); // Default to ACT model // Session data sessionId = $state(null); sessionConfig = $state(null); sessionData = $state(null); // Derived reactive values hasSession = $derived(this.sessionId !== null); isRunning = $derived(this.status === "running"); canStart = $derived(this.status === "ready" || this.status === "stopped"); canStop = $derived(this.status === "running"); constructor(id: string, name?: string) { this.id = id; this.name = name || `Compute ${id}`; } /** * Get input connections (camera and joint inputs) */ get inputConnections() { if (!this.sessionData) return null; return { cameras: this.sessionData.camera_room_ids, jointInput: this.sessionData.joint_input_room_id, workspaceId: this.sessionData.workspace_id }; } /** * Get output connections (joint output) */ get outputConnections() { if (!this.sessionData) return null; return { jointOutput: this.sessionData.joint_output_room_id, workspaceId: this.sessionData.workspace_id }; } /** * Get display information for UI */ get displayInfo() { return { id: this.id, name: this.name, status: this.status, sessionId: this.sessionId, policyPath: this.sessionConfig?.policyPath, cameraNames: this.sessionConfig?.cameraNames || [], hasSession: this.hasSession, isRunning: this.isRunning, canStart: this.canStart, canStop: this.canStop }; } /** * Get status for billboard display */ get statusInfo() { const status = this.status; let statusText = ""; let statusColor = ""; switch (status) { case "disconnected": statusText = "Disconnected"; statusColor = "rgb(107, 114, 128)"; // gray break; case "ready": statusText = "Ready"; statusColor = "rgb(245, 158, 11)"; // yellow break; case "running": statusText = "Running"; statusColor = "rgb(34, 197, 94)"; // green break; case "stopped": statusText = "Stopped"; statusColor = "rgb(239, 68, 68)"; // red break; case "initializing": statusText = "Initializing"; statusColor = "rgb(59, 130, 246)"; // blue break; } return { status, statusText, statusColor, emoji: this.getStatusEmoji() }; } private getStatusEmoji(): string { switch (this.status) { case "disconnected": return "⚪"; case "ready": return "🟡"; case "running": return "🟢"; case "stopped": return "🔴"; case "initializing": return "🟠"; default: return "⚪"; } } /** * Reset session data */ resetSession(): void { this.sessionId = null; this.sessionConfig = null; this.sessionData = null; this.status = "disconnected"; } /** * Update position */ updatePosition(newPosition: Position3D): void { this.position = { ...newPosition }; } /** * Update name */ updateName(newName: string): void { this.name = newName; } }