import type { RemoveEnrollmentRequest, RemoveEnrollmentResponse, MachineOperationPolicy, SwapActiveSandboxResponse, UpdateMachineOperationPolicyRequest, UpdateMachineAgentResponse } from "@opengeni/sdk"; import { type ClientOverride } from "../session-context.js"; import type { MachinesResponse, MachineView, MetricSample } from "../types/machines.js"; /** Dashboard list: cheap heartbeat read, keep the pill reasonably fresh. */ export declare const MACHINES_DASHBOARD_POLL_MS = 10000; /** Session surfaces share one poll for the same workspace+session. */ export declare const MACHINES_SESSION_POLL_MS = 15000; /** Composer polls after the first load shows a machine, or to retry a real error. */ export declare const MACHINES_COMPOSER_POLL_MS = 30000; /** * The slice of the SDK client the Machines surface needs. The method NAMES + * SIGNATURES match M10's `OpenGeniClient` (`listMachines`, `machineMetricsSeries`) * so the real SDK client satisfies this surface DIRECTLY for the read paths — no * adapter needed. It is declared structurally (not a hard `OpenGeniClient` Pick) * so a test/demo/Geni-frontend client can stand in, keeping the hook dual-consumer * safe (works in apps/web AND the separate Geni frontend). * * The active-sandbox SWAP is now a typed SDK call (`swapActiveSandbox`, the M7 * user-authenticated REST equivalent of the `sandbox_swap` MCP tool). The real * SDK client satisfies it structurally, so the default attach path is wired * WHENEVER a sessionId is in scope (the swap is session-scoped). `attachMachine` * stays an OPTIONAL escape hatch for a host that wants to supply its own swap * adapter; when neither it nor a sessionId is present, attach is a no-op and the * card hides the button. */ export type MachinesClientLike = { /** GET /v1/workspaces/:ws/machines — the dashboard list + active pointer. */ listMachines: (workspaceId: string, options?: { sessionId?: string; signal?: AbortSignal; }) => Promise; /** GET .../machines/:enrollmentId/metrics/series — the downsampled history. */ machineMetricsSeries?: (workspaceId: string, enrollmentId: string, options?: { window?: "15m" | "1h" | "6h" | "24h"; }) => Promise; /** POST .../enrollments/:enrollmentId/revoke — workspace-admin removal. */ removeEnrollment?: (workspaceId: string, enrollmentId: string, request?: RemoveEnrollmentRequest) => Promise; /** POST .../machines/:enrollmentId/update — signed, generation-fenced update. */ updateMachineAgent?: (workspaceId: string, enrollmentId: string) => Promise; /** PATCH .../machines/:enrollmentId/operation-policy — revision-fenced policy. */ updateMachineOperationPolicy?: (workspaceId: string, enrollmentId: string, request: UpdateMachineOperationPolicyRequest) => Promise; /** * POST .../sessions/:sessionId/active-sandbox — swap the session's active * sandbox to a machine. The default swap path; the real SDK client provides it. */ swapActiveSandbox?: (workspaceId: string, sessionId: string, request: { target: string; }) => Promise; /** * Host-supplied swap adapter (an escape hatch). When present it wins over the * default `swapActiveSandbox` path. Session-scoped, like the swap it backs. */ attachMachine?: (workspaceId: string, sessionId: string, sandboxId: string) => Promise; }; export type UseMachinesOptions = ClientOverride & { pollIntervalMs?: number | undefined; enabled?: boolean | undefined; /** Scope the list to a session (adds the synthetic Modal group box + pointer). */ sessionId?: string | undefined; /** * Override the client with one implementing `MachinesClientLike`. Defaults to * the provider client cast to the surface (the real SDK client satisfies the * read paths). An app supplies an adapter to wire `attachMachine` (the swap). */ machinesClient?: MachinesClientLike | undefined; }; export type UseMachinesResult = { sessionMachineAccess?: MachinesResponse["sessionMachineAccess"]; machines: MachineView[]; activeSandboxId: string | null; activeEpoch: number; loading: boolean; error: Error | null; refresh: () => Promise; /** Attach/swap the session's active sandbox to a machine (returns the new pointer). */ attach: (sandboxId: string) => Promise; /** Remove a self-hosted enrollment while retaining history. */ remove: (enrollmentId: string, request?: RemoveEnrollmentRequest) => Promise; canRemove: boolean; removingEnrollmentId: string | null; /** Start/retry the signed self-update for one Connected Machine. */ updateAgent: (enrollmentId: string) => Promise; canUpdateAgent: boolean; updatingEnrollmentId: string | null; /** Update the optional per-enrollment command memory policy. */ updateOperationPolicy: (enrollmentId: string, request: UpdateMachineOperationPolicyRequest) => Promise; canUpdateOperationPolicy: boolean; updatingOperationPolicyEnrollmentId: string | null; /** Whether the host wired an attach/swap path (drives the card affordance). */ canAttach: boolean; /** Fetch a downsampled metric series for one enrolled machine. */ fetchSeries: (enrollmentId: string, window?: "15m" | "1h" | "6h" | "24h") => Promise; attaching: boolean; /** The sandbox id of the in-flight attach (for per-card spinner gating). */ attachingSandboxId: string | null; mutationError: Error | null; clearMutationError: () => void; }; /** * The workspace Machines fleet: the selfhosted enrollments + the session's Modal * box, each with latest metrics + state, plus the active-sandbox pointer. Polls * the M10 `GET /machines` endpoint and exposes attach/swap + a metric-series * fetch. Renders via ``. Dual-consumer safe: it reads only the * structural `MachinesClientLike` surface, so it works in apps/web AND the Geni * frontend (each provides its own client/adapter). */ export declare function useMachines(options?: UseMachinesOptions): UseMachinesResult;