Spaces:
Running
Running
| 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<Position3D>({ x: 0, y: 0, z: 0 }); | |
| name = $state<string>(""); | |
| status = $state<ComputeStatus>("disconnected"); | |
| modelType = $state<ModelType>("act"); // Default to ACT model | |
| // Session data | |
| sessionId = $state<string | null>(null); | |
| sessionConfig = $state<AISessionConfig | null>(null); | |
| sessionData = $state<AISessionResponse | null>(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; | |
| } | |
| } | |