@opengeni/react 7.6.1-canary.37062299158001 → 7.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -19
- package/dist/{browser-viewer-63TXMINB.js → browser-viewer-5X47I6T2.js} +5 -6
- package/dist/{chunk-TKB4SB44.js → chunk-45GE35O7.js} +2 -10
- package/dist/chunk-45GE35O7.js.map +1 -0
- package/dist/{chunk-DOJWJQ3F.js → chunk-5EXGU7UF.js} +3 -3
- package/dist/{chunk-YN7I3STW.js → chunk-6NEZPF53.js} +32 -153
- package/dist/chunk-6NEZPF53.js.map +1 -0
- package/dist/{chunk-I7IWRQLN.js → chunk-BI57CQUV.js} +2 -2
- package/dist/{chunk-6ZSWSH4I.js → chunk-CHPKSLPN.js} +1 -3
- package/dist/chunk-CHPKSLPN.js.map +1 -0
- package/dist/{chunk-Q5QBEZIQ.js → chunk-DV2DBNPQ.js} +29 -48
- package/dist/chunk-DV2DBNPQ.js.map +1 -0
- package/dist/{chunk-RDKBXMWX.js → chunk-FGBCYQOT.js} +74 -120
- package/dist/chunk-FGBCYQOT.js.map +1 -0
- package/dist/{chunk-AAG4R3QN.js → chunk-KGENSZKS.js} +3 -4
- package/dist/chunk-KGENSZKS.js.map +1 -0
- package/dist/{chunk-YQEAA6LT.js → chunk-KZ73RL76.js} +3 -7
- package/dist/chunk-KZ73RL76.js.map +1 -0
- package/dist/{chunk-LFXYGZWK.js → chunk-LZ3KHA55.js} +60 -169
- package/dist/chunk-LZ3KHA55.js.map +1 -0
- package/dist/{chunk-2QUSQVF2.js → chunk-UINDK6C3.js} +3 -3
- package/dist/{chunk-UTRTG6LH.js → chunk-UJRYEWZI.js} +8 -48
- package/dist/chunk-UJRYEWZI.js.map +1 -0
- package/dist/{chunk-XOAMRDDK.js → chunk-VGIKFIO2.js} +3 -6
- package/dist/chunk-VGIKFIO2.js.map +1 -0
- package/dist/{chunk-ELCE5SXV.js → chunk-WZ55DVGK.js} +4 -8
- package/dist/chunk-WZ55DVGK.js.map +1 -0
- package/dist/{chunk-IQUCRAT7.js → chunk-XA6R7DJQ.js} +3 -3
- package/dist/{chunk-TOAH2BKA.js → chunk-YCGBREUV.js} +2 -6
- package/dist/{chunk-TOAH2BKA.js.map → chunk-YCGBREUV.js.map} +1 -1
- package/dist/{chunk-HNFCAQ5R.js → chunk-YRYF2GLG.js} +31 -39
- package/dist/chunk-YRYF2GLG.js.map +1 -0
- package/dist/{chunk-GISEVGS6.js → chunk-YSMMDOOE.js} +2 -10
- package/dist/chunk-YSMMDOOE.js.map +1 -0
- package/dist/{chunk-CWWKTNKK.js → chunk-Z3DISEQN.js} +18 -35
- package/dist/chunk-Z3DISEQN.js.map +1 -0
- package/dist/client.d.ts +1 -4
- package/dist/commands/types.d.ts +0 -2
- package/dist/components/approval-surface.d.ts +0 -15
- package/dist/composer.js +7 -8
- package/dist/{computer-viewer-X2MBRZY4.js → computer-viewer-7GF35SNY.js} +4 -5
- package/dist/connect.js +3 -3
- package/dist/hooks/use-browser-session.d.ts +0 -4
- package/dist/hooks/use-composer.d.ts +0 -2
- package/dist/hooks/use-computer-session.d.ts +0 -2
- package/dist/hooks/use-file-attachments.d.ts +0 -2
- package/dist/hooks/use-session-events.d.ts +1 -1
- package/dist/hooks/use-workspace-sessions.d.ts +5 -15
- package/dist/index.d.ts +2 -2
- package/dist/index.js +21 -28
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.js +5 -6
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-CNEZ5KAN.js → latest-question-3BJGKQQ6.js} +3 -3
- package/dist/lib/format.d.ts +3 -27
- package/dist/lib/interaction-errors.d.ts +0 -3
- package/dist/machines.js +4 -5
- package/dist/{model-policy-picker-menu-JSA64TNN.js → model-policy-picker-menu-PUTA5JOB.js} +4 -4
- package/dist/model-policy.js +1 -1
- package/dist/provider.d.ts +1 -5
- package/dist/{queue-surface-implementation-HENWYFWA.js → queue-surface-implementation-2CAQAIHM.js} +2 -3
- package/dist/{queue-surface-implementation-HENWYFWA.js.map → queue-surface-implementation-2CAQAIHM.js.map} +1 -1
- package/dist/realtime.js +2 -2
- package/dist/{sandbox-files-BBC47SLD.js → sandbox-files-AEJTWGT4.js} +3 -4
- package/dist/session-ui.d.ts +1 -1
- package/dist/session-ui.js +12 -13
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +6 -7
- package/dist/usage.js +1 -2
- package/dist/usage.js.map +1 -1
- package/package.json +3 -3
- package/src/client.ts +1 -5
- package/src/commands/registry.ts +15 -18
- package/src/commands/types.ts +0 -2
- package/src/components/approval-surface.tsx +42 -166
- package/src/components/browser-viewer.tsx +9 -38
- package/src/components/composer.tsx +2 -9
- package/src/components/computer-viewer.tsx +30 -160
- package/src/components/generated-video-player.tsx +2 -4
- package/src/components/human-input-form.tsx +5 -18
- package/src/components/message-timeline.tsx +2 -4
- package/src/components/open-geni-chat.tsx +4 -11
- package/src/components/queue-surface-state.tsx +1 -3
- package/src/components/session-chrome.tsx +2 -5
- package/src/components/session-commands-panel.tsx +1 -3
- package/src/components/session-conversation.tsx +2 -4
- package/src/components/session-list.tsx +5 -7
- package/src/components/session-mcp-capability-card.tsx +1 -11
- package/src/hooks/internal.ts +2 -3
- package/src/hooks/use-browser-session.ts +79 -115
- package/src/hooks/use-composer.ts +31 -70
- package/src/hooks/use-computer-session.ts +6 -57
- package/src/hooks/use-file-attachments.ts +3 -16
- package/src/hooks/use-goal.ts +1 -2
- package/src/hooks/use-session-capabilities.ts +2 -3
- package/src/hooks/use-session-events.ts +8 -15
- package/src/hooks/use-slash-commands.ts +11 -6
- package/src/hooks/use-turn-queue.ts +1 -2
- package/src/hooks/use-workspace-sessions.ts +7 -40
- package/src/index.ts +2 -7
- package/src/interaction.ts +0 -1
- package/src/lib/format.ts +9 -73
- package/src/lib/interaction-errors.ts +0 -15
- package/src/model-policy.ts +0 -5
- package/src/provider.tsx +4 -12
- package/src/session-ui.ts +1 -1
- package/src/timeline/projection.ts +1 -12
- package/styles/compiled.css +0 -14
- package/dist/chunk-6ZSWSH4I.js.map +0 -1
- package/dist/chunk-AAG4R3QN.js.map +0 -1
- package/dist/chunk-CWWKTNKK.js.map +0 -1
- package/dist/chunk-ELCE5SXV.js.map +0 -1
- package/dist/chunk-GISEVGS6.js.map +0 -1
- package/dist/chunk-HNFCAQ5R.js.map +0 -1
- package/dist/chunk-LFXYGZWK.js.map +0 -1
- package/dist/chunk-Q5QBEZIQ.js.map +0 -1
- package/dist/chunk-RDKBXMWX.js.map +0 -1
- package/dist/chunk-TKB4SB44.js.map +0 -1
- package/dist/chunk-UGLEYEMP.js +0 -33
- package/dist/chunk-UGLEYEMP.js.map +0 -1
- package/dist/chunk-UTRTG6LH.js.map +0 -1
- package/dist/chunk-XOAMRDDK.js.map +0 -1
- package/dist/chunk-YN7I3STW.js.map +0 -1
- package/dist/chunk-YQEAA6LT.js.map +0 -1
- package/dist/lib/error-message.d.ts +0 -7
- package/src/lib/error-message.ts +0 -37
- /package/dist/{browser-viewer-63TXMINB.js.map → browser-viewer-5X47I6T2.js.map} +0 -0
- /package/dist/{chunk-DOJWJQ3F.js.map → chunk-5EXGU7UF.js.map} +0 -0
- /package/dist/{chunk-I7IWRQLN.js.map → chunk-BI57CQUV.js.map} +0 -0
- /package/dist/{chunk-2QUSQVF2.js.map → chunk-UINDK6C3.js.map} +0 -0
- /package/dist/{chunk-IQUCRAT7.js.map → chunk-XA6R7DJQ.js.map} +0 -0
- /package/dist/{computer-viewer-X2MBRZY4.js.map → computer-viewer-7GF35SNY.js.map} +0 -0
- /package/dist/{latest-question-CNEZ5KAN.js.map → latest-question-3BJGKQQ6.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-JSA64TNN.js.map → model-policy-picker-menu-PUTA5JOB.js.map} +0 -0
- /package/dist/{sandbox-files-BBC47SLD.js.map → sandbox-files-AEJTWGT4.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/computer-viewer.tsx","../src/hooks/use-computer-frame-stream.ts","../src/hooks/use-computer-session.ts","../src/hooks/use-computer-sessions.ts"],"sourcesContent":["import type {\n ComputerAction,\n ComputerClipboard,\n ComputerFrame,\n ComputerObservation,\n ComputerSession,\n ComputerTarget,\n InteractionIntervention,\n InteractionSemanticNode,\n} from \"@opengeni/sdk/interaction\";\nimport { interactionControlFailureFromError } from \"@opengeni/sdk/interaction\";\nimport type { DesktopStreamCapability } from \"@opengeni/sdk\";\nimport {\n ChevronDownIcon,\n CircleAlertIcon,\n KeyboardIcon,\n LoaderCircleIcon,\n LockKeyholeIcon,\n MonitorIcon,\n MousePointer2Icon,\n PanelsTopLeftIcon,\n PlusIcon,\n RefreshCwIcon,\n RotateCcwIcon,\n} from \"lucide-react\";\nimport {\n type ClipboardEvent,\n type CompositionEvent,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n type ReactNode,\n type WheelEvent,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport {\n type ComputerFrameWebSocketFactory,\n useComputerFrameStream,\n} from \"../hooks/use-computer-frame-stream\";\nimport { useComputerSession } from \"../hooks/use-computer-session\";\nimport { useComputerSessions } from \"../hooks/use-computer-sessions\";\nimport { useInteractionInterventions } from \"../hooks/use-interaction-interventions\";\nimport { cn } from \"../lib/cn\";\nimport { copyTextToClipboard } from \"../lib/clipboard\";\nimport { isSourcePlacementChangedError } from \"../lib/interaction-errors\";\nimport type { EmbeddedComputerInteractionClientOverride } from \"../session-context\";\nimport { InteractionInterventionBanner } from \"./interaction-intervention-banner\";\nimport { DesktopViewer } from \"./desktop-viewer\";\n\nexport type ComputerViewerNotification = { kind: \"error\" | \"info\"; message: string };\n\nexport type ComputerViewerProps = EmbeddedComputerInteractionClientOverride & {\n /** Selected OpenGeni agent/session. Peer ComputerSessions remain visible. */\n sessionId: string;\n enabled?: boolean | undefined;\n className?: string | undefined;\n onNotify?: ((notification: ComputerViewerNotification) => void) | undefined;\n /** Tests/demos only. Production uses the browser's native WebSocket. */\n webSocketFactory?: ComputerFrameWebSocketFactory | undefined;\n renderEmpty?: ((create: () => void, creating: boolean) => ReactNode) | undefined;\n /** Host navigation request for one exact ComputerSession. */\n requestedComputerSessionId?: string | null | undefined;\n requestedComputerRequestId?: string | number | null | undefined;\n /** Restore and report the Desktop session selected in this task's dock. */\n initialComputerSessionId?: string | null | undefined;\n onComputerSessionIdChange?: ((computerSessionId: string | null) => void) | undefined;\n};\n\ntype ComputerSelection = { sessionId: string; pinned: boolean } | null;\ntype PointerStart = { x: number; y: number; pointerId: number; frame: ComputerFrame };\n\n/** Full ComputerSession surface: workspace discovery, peer switching, app/window/\n * screen navigation, semantic controls, exact-frame input, and live media. */\nexport function ComputerViewer({\n sessionId,\n enabled = true,\n className,\n onNotify,\n webSocketFactory,\n renderEmpty,\n requestedComputerSessionId,\n requestedComputerRequestId,\n initialComputerSessionId,\n onComputerSessionIdChange,\n ...override\n}: ComputerViewerProps) {\n const registry = useComputerSessions({ ...override, sessionId, enabled });\n const createSession = registry.create;\n const refreshRegistry = registry.refresh;\n const liveRelevant = useMemo(\n () => registry.relevantSessions.filter((session) => isLiveComputer(session)),\n [registry.relevantSessions],\n );\n const connectedPlacementLoss = useMemo(\n () =>\n registry.relevantSessions.find(\n (session) =>\n session.lifecycle === \"lost\" &&\n session.failureCode === \"source_placement_changed\" &&\n session.placement.kind === \"connected_machine\",\n ) ?? null,\n [registry.relevantSessions],\n );\n const recentRelevantFailure = useMemo(\n () =>\n liveRelevant.length === 0\n ? (registry.relevantSessions.find(\n (session) =>\n [\"failed\", \"lost\"].includes(session.lifecycle) &&\n !(\n session.failureCode === \"source_placement_changed\" &&\n session.placement.kind === \"connected_machine\"\n ),\n ) ?? null)\n : null,\n [liveRelevant.length, registry.relevantSessions],\n );\n const liveSessions = useMemo(() => {\n const sessions = registry.sessions.filter((session) => isLiveComputer(session));\n return recentRelevantFailure ? [...sessions, recentRelevantFailure] : sessions;\n }, [recentRelevantFailure, registry.sessions]);\n const relevant = useMemo(\n () =>\n liveRelevant.length > 0 ? liveRelevant : recentRelevantFailure ? [recentRelevantFailure] : [],\n [liveRelevant, recentRelevantFailure],\n );\n const [selection, setSelection] = useState<ComputerSelection>(() =>\n initialComputerSessionId ? { sessionId: initialComputerSessionId, pinned: true } : null,\n );\n const selectComputerSession = useCallback(\n (next: ComputerSelection) => {\n setSelection(next);\n onComputerSessionIdChange?.(next?.sessionId ?? null);\n },\n [onComputerSessionIdChange],\n );\n const interventions = useInteractionInterventions({\n ...override,\n enabled,\n resourceKind: \"computer_session\",\n });\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<Error | null>(null);\n const [showControls, setShowControls] = useState(false);\n const previousSessionIdRef = useRef(sessionId);\n const handledRequestRef = useRef<string | null>(null);\n const seenInterventionIdsRef = useRef(new Set<string>());\n const createInFlightRef = useRef(false);\n const autoCreateSessionRef = useRef<string | null>(null);\n const emptyCatalogConfirmationRef = useRef<string | null>(null);\n const endedGenerationLossRef = useRef(new Set<string>());\n const recreatedPlacementLossRef = useRef(new Set<string>());\n const [suppressGenericCreate, setSuppressGenericCreate] = useState(false);\n const endStaleComputer = registry.end;\n useEffect(() => {\n if (!enabled) return;\n for (const session of registry.sessions) {\n if (!isAttachedChromeGenerationLoss(session)) continue;\n setSuppressGenericCreate(true);\n if (endedGenerationLossRef.current.has(session.id)) continue;\n endedGenerationLossRef.current.add(session.id);\n void endStaleComputer(session.id).catch(() => {\n endedGenerationLossRef.current.delete(session.id);\n });\n }\n }, [enabled, endStaleComputer, registry.sessions]);\n\n const notifyError = useCallback(\n (cause: unknown, fallback: string) => {\n onNotify?.({\n kind: \"error\",\n message: cause instanceof Error ? cause.message : fallback,\n });\n },\n [onNotify],\n );\n\n useEffect(() => {\n if (previousSessionIdRef.current === sessionId) return;\n previousSessionIdRef.current = sessionId;\n handledRequestRef.current = null;\n autoCreateSessionRef.current = null;\n emptyCatalogConfirmationRef.current = null;\n recreatedPlacementLossRef.current.clear();\n setSuppressGenericCreate(false);\n setCreateError(null);\n setSelection(\n initialComputerSessionId ? { sessionId: initialComputerSessionId, pinned: true } : null,\n );\n }, [initialComputerSessionId, sessionId]);\n\n useEffect(() => {\n if (!enabled || registry.loading) return;\n const requested = requestedComputerSessionId\n ? (liveSessions.find((session) => session.id === requestedComputerSessionId) ?? null)\n : null;\n const requestKey = requested\n ? `${requestedComputerRequestId ?? \"default\"}:${requested.id}`\n : null;\n if (requested && requestKey && handledRequestRef.current !== requestKey) {\n handledRequestRef.current = requestKey;\n selectComputerSession({ sessionId: requested.id, pinned: true });\n return;\n }\n\n const selectedStillLive = liveSessions.some((session) => session.id === selection?.sessionId);\n // Peer computers remain one click away, but never become the implicit\n // computer for another agent. Otherwise opening a sandbox's Computer tab\n // can silently select—and send input to—a connected user's Mac.\n if (selection?.pinned && selectedStillLive) return;\n const preferred = relevant[0] ?? null;\n if (!preferred) {\n if (selection) selectComputerSession(null);\n return;\n }\n if (!selectedStillLive || !selection?.pinned) {\n if (selection?.sessionId !== preferred.id || selection.pinned) {\n selectComputerSession({ sessionId: preferred.id, pinned: false });\n }\n }\n }, [\n liveSessions,\n enabled,\n registry.loading,\n relevant,\n requestedComputerRequestId,\n requestedComputerSessionId,\n selectComputerSession,\n selection,\n ]);\n\n const selectedRegistrySession = useMemo(\n () => liveSessions.find((session) => session.id === selection?.sessionId) ?? null,\n [liveSessions, selection?.sessionId],\n );\n const interventionCounts = useMemo(\n () => countInterventions(interventions.interventions),\n [interventions.interventions],\n );\n const selectedInterventions = useMemo(\n () =>\n interventions.interventions.filter(\n (intervention) => intervention.resourceId === selection?.sessionId,\n ),\n [interventions.interventions, selection?.sessionId],\n );\n const controllerReady = selectedRegistrySession?.lifecycle === \"active\";\n const computer = useComputerSession({\n ...override,\n computerSessionId: selection?.sessionId ?? null,\n enabled: enabled && selection !== null && controllerReady,\n });\n useEffect(() => {\n if (!isSourcePlacementChangedError(computer.error, \"computer_session\")) return;\n void refreshRegistry();\n }, [computer.error, refreshRegistry]);\n const act = computer.act;\n const actFromFrame = computer.actFromFrame;\n const refreshComputer = computer.refresh;\n const frames = useComputerFrameStream({\n ...override,\n computerSessionId: selection?.sessionId ?? null,\n targetId: computer.selectedTarget?.id ?? null,\n enabled:\n enabled &&\n selection !== null &&\n controllerReady &&\n computer.selectedTarget !== null &&\n isComputerFrameTarget(computer.selectedTarget),\n stream: {\n format: \"jpeg\",\n quality: 78,\n maxWidth: 1_920,\n maxHeight: 1_200,\n everyNthFrame: 1,\n },\n ...(webSocketFactory ? { webSocketFactory } : {}),\n });\n const displayedFrame =\n frames.frame &&\n frames.frame.computerSessionId === selection?.sessionId &&\n frames.frame.targetId === computer.selectedTarget?.id &&\n frames.frame.targetGeneration === computer.selectedTarget?.targetGeneration\n ? frames.frame\n : null;\n const rfbStream =\n frames.attachment?.stream.kind === \"direct_rfb\" ? frames.attachment.stream : null;\n const machineLocked = selectedRegistrySession?.failureCode === \"machine_locked\";\n const controlUnavailable = computer.controlError !== null;\n const connectionState = controlUnavailable ? \"error\" : frames.state;\n // RFB has one combined input switch; partial native input stays view-only.\n const rfbInputEnabled =\n !machineLocked &&\n !controlUnavailable &&\n computer.session?.capabilities?.pointerInput === true &&\n computer.session?.capabilities?.keyboardInput === true;\n const rfbCapability = useMemo<DesktopStreamCapability | null>(() => {\n if (!rfbStream || !frames.attachment) return null;\n const bounds = computer.selectedTarget?.bounds;\n return {\n transport: \"vnc-ws\",\n client: \"novnc\",\n mode: rfbInputEnabled ? \"interactive\" : \"read-only\",\n url: rfbStream.url,\n token: null,\n expiresAt: frames.attachment.expiresAt,\n resolution: [bounds?.width ?? 1_440, bounds?.height ?? 900],\n unredacted: true,\n requiresAcknowledgment: false,\n acknowledged: true,\n shared: false,\n sharedSessionIds: [],\n reason: null,\n };\n }, [computer.selectedTarget?.bounds, frames.attachment, rfbInputEnabled, rfbStream]);\n const currentIds = useMemo(() => new Set(relevant.map((session) => session.id)), [relevant]);\n\n useEffect(() => {\n for (const intervention of interventions.interventions) {\n if (seenInterventionIdsRef.current.has(intervention.id)) continue;\n seenInterventionIdsRef.current.add(intervention.id);\n onNotify?.({\n kind: \"info\",\n message: `${interventionTitle(intervention)}: ${intervention.reason}`,\n });\n }\n }, [interventions.interventions, onNotify]);\n\n const resolveIntervention = useCallback(\n (intervention: InteractionIntervention, outcome: \"completed\" | \"dismissed\") => {\n void interventions\n .resolve(intervention.id, {\n expectedVersion: intervention.version,\n outcome,\n })\n .then(() => {\n onNotify?.({\n kind: \"info\",\n message:\n outcome === \"completed\" ? \"Agent notified. Continuing work.\" : \"Request cancelled.\",\n });\n })\n .catch((cause) => notifyError(cause, \"Could not update the desktop request.\"));\n },\n [interventions, notifyError, onNotify],\n );\n\n const createComputer = useCallback(() => {\n if (createInFlightRef.current) return;\n createInFlightRef.current = true;\n setCreateError(null);\n setCreating(true);\n void createSession({ sessionId, name: \"Desktop\" })\n .then((response) => {\n selectComputerSession({ sessionId: response.session.id, pinned: false });\n })\n .catch((cause) => {\n const error = cause instanceof Error ? cause : new Error(\"Could not open a desktop.\");\n setCreateError(error);\n notifyError(error, \"Could not open a desktop.\");\n })\n .finally(() => {\n createInFlightRef.current = false;\n setCreating(false);\n });\n }, [createSession, notifyError, selectComputerSession, sessionId]);\n\n useEffect(() => {\n if (\n !enabled ||\n registry.loading ||\n registry.refreshing ||\n liveRelevant.length > 0 ||\n !connectedPlacementLoss ||\n recreatedPlacementLossRef.current.has(connectedPlacementLoss.id)\n ) {\n return;\n }\n recreatedPlacementLossRef.current.add(connectedPlacementLoss.id);\n autoCreateSessionRef.current = sessionId;\n emptyCatalogConfirmationRef.current = null;\n createComputer();\n }, [\n connectedPlacementLoss,\n createComputer,\n enabled,\n liveRelevant.length,\n registry.loading,\n registry.refreshing,\n sessionId,\n ]);\n\n useEffect(() => {\n // Once this task's Desktop has been observed, a later transient empty\n // registry snapshot must not create a second one. This can happen while the\n // lazy surface is disabled/re-enabled or while an invalidation refresh\n // briefly races the association projection. The existing Desktop remains\n // the task's authority; explicit New desktop is still available.\n if (relevant.length > 0) {\n autoCreateSessionRef.current = sessionId;\n emptyCatalogConfirmationRef.current = null;\n }\n }, [relevant.length, sessionId]);\n\n useEffect(() => {\n if (\n !enabled ||\n registry.loading ||\n registry.refreshing ||\n registry.error ||\n relevant.length > 0 ||\n suppressGenericCreate ||\n autoCreateSessionRef.current === sessionId\n ) {\n return;\n }\n // A lazy surface can momentarily publish an empty settled projection while\n // its initial catalog and a workspace invalidation cross. Confirm the empty\n // result with one authoritative refresh before creating anything. A real\n // empty catalog creates on the following render; an existing association\n // appears and cancels this path.\n if (emptyCatalogConfirmationRef.current !== sessionId) {\n emptyCatalogConfirmationRef.current = sessionId;\n void refreshRegistry();\n return;\n }\n autoCreateSessionRef.current = sessionId;\n createComputer();\n }, [\n createComputer,\n enabled,\n refreshRegistry,\n registry.error,\n registry.loading,\n registry.refreshing,\n relevant.length,\n sessionId,\n suppressGenericCreate,\n ]);\n\n const perform = useCallback(\n async (action: ComputerAction, frame: ComputerFrame | null): Promise<void> => {\n if (computer.controlError) throw computer.controlError;\n let receipt;\n if (action.type === \"pointer\") {\n if (!frame) throw new Error(\"Desktop view is not ready for pointer input.\");\n receipt = await actFromFrame(action, frame);\n } else {\n receipt = await act(action);\n }\n if (receipt.state !== \"completed\") {\n throw new Error(receipt.error?.message ?? \"Desktop input did not complete.\");\n }\n },\n [act, actFromFrame, computer.controlError],\n );\n\n const reconnect = () => {\n void refreshComputer();\n frames.reconnect();\n };\n\n const copyFromRfb = useCallback(\n (event: ClipboardEvent<HTMLDivElement>) => {\n if (!rfbInputEnabled || !rfbStream || computer.session?.capabilities?.clipboard !== true)\n return;\n event.preventDefault();\n event.stopPropagation();\n void perform({ type: \"clipboard\", operation: \"copy\" }, null)\n .then(() => computer.readClipboard())\n .then(async (clipboard) => {\n if (clipboard.text && !(await copyTextToClipboard(clipboard.text))) {\n throw new Error(\"Desktop text could not be copied to the local clipboard\");\n }\n })\n .catch((cause) => notifyError(cause, \"Could not copy from the desktop.\"));\n },\n [computer, notifyError, perform, rfbInputEnabled, rfbStream],\n );\n\n const pasteIntoRfb = useCallback(\n (text: string): boolean => {\n if (!rfbInputEnabled || !rfbStream || computer.session?.capabilities?.clipboard !== true)\n return false;\n // Keep paste on the canonical ComputerSession action path. RFB\n // ClientCutText synchronization varies by server and can acknowledge a\n // local paste without ever updating the remote graphical seat. These two\n // awaited actions run against the exact selected ComputerSession/target.\n // Read-after-write is the causal readiness barrier on X11: clipboard\n // ownership is asynchronous, so a successful write response alone does\n // not prove that the graphical seat can already serve the selection.\n void (async () => {\n await perform({ type: \"clipboard\", operation: \"write\", text }, null);\n assertExactComputerClipboard(await computer.readClipboard(), text);\n await perform({ type: \"clipboard\", operation: \"paste\" }, null);\n })().catch((cause) => notifyError(cause, \"Could not paste into the desktop.\"));\n return true;\n },\n [computer, notifyError, perform, rfbInputEnabled, rfbStream],\n );\n\n const hideGenericCreate = suppressGenericCreate && liveRelevant.length === 0;\n const generationLossSelected =\n selectedRegistrySession !== null && isAttachedChromeGenerationLoss(selectedRegistrySession);\n const generationLossFrames = isAttachedChromeGenerationLossError(frames.error);\n\n if (!enabled) return null;\n if (registry.loading && liveSessions.length === 0) {\n return (\n <ComputerNotice\n icon={<LoaderCircleIcon className=\"size-4 animate-spin\" />}\n text=\"Finding workspace desktops…\"\n {...(className ? { className } : {})}\n />\n );\n }\n if (liveSessions.length === 0) {\n if (hideGenericCreate) {\n return (\n <div className={cn(\"grid h-full place-items-center bg-og-bg p-6\", className)}>\n <div className=\"max-w-sm text-center\">\n <CircleAlertIcon className=\"mx-auto size-5 text-og-danger\" />\n <p className=\"mt-3 text-og-menu font-medium text-og-fg\">\n Chrome reconnected—open a fresh browser/desktop.\n </p>\n <p className=\"mt-1 text-og-control leading-5 text-og-fg-muted\">\n This Chrome profile is live again, but the previous desktop cannot move to the new\n connection. Use Browser → New browser → Connected Chrome.\n </p>\n </div>\n </div>\n );\n }\n if (renderEmpty) return renderEmpty(createComputer, creating);\n const error = createError ?? registry.error;\n return (\n <div className={cn(\"grid h-full place-items-center bg-og-bg p-6\", className)}>\n <div className=\"max-w-sm text-center\">\n <span className=\"mx-auto grid size-10 place-items-center rounded-og-lg border border-og-border bg-og-surface-1 text-og-fg-muted\">\n {error ? (\n <CircleAlertIcon className=\"size-5 text-og-danger\" />\n ) : (\n <LoaderCircleIcon className=\"size-5 animate-spin\" />\n )}\n </span>\n <p className=\"mt-3 text-og-menu font-medium text-og-fg\">\n {error ? \"Desktop didn’t open\" : \"Opening desktop…\"}\n </p>\n <p className=\"mt-1 text-og-control leading-5 text-og-fg-muted\">\n {error?.message ?? \"Preparing this agent’s desktop. It will appear here when ready.\"}\n </p>\n {error ? (\n <button\n type=\"button\"\n onClick={createError ? createComputer : () => void refreshRegistry()}\n disabled={creating || registry.refreshing}\n className=\"mt-4 inline-flex h-8 items-center gap-1.5 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 text-og-control font-medium transition hover:bg-og-primary-hover disabled:opacity-50\"\n >\n {creating || registry.refreshing ? (\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" />\n ) : (\n <RotateCcwIcon className=\"size-3.5\" />\n )}\n Try again\n </button>\n ) : null}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n \"@container/computer-viewer flex h-full min-h-0 min-w-0 flex-col overflow-hidden bg-og-bg\",\n className,\n )}\n >\n <ComputerToolbar\n sessions={liveSessions}\n relevantSessionIds={currentIds}\n selectedSessionId={selection?.sessionId ?? null}\n creating={creating}\n refreshing={registry.refreshing}\n interventionCounts={interventionCounts}\n onSelect={(computerSessionId) =>\n selectComputerSession({ sessionId: computerSessionId, pinned: true })\n }\n onFollow={() => {\n if (relevant[0]) selectComputerSession({ sessionId: relevant[0].id, pinned: false });\n }}\n onCreate={hideGenericCreate ? undefined : createComputer}\n onRefresh={() => {\n if (connectionState === \"error\" && !generationLossSelected && !generationLossFrames) {\n frames.reconnect();\n }\n void Promise.all([refreshRegistry(), refreshComputer()]);\n }}\n />\n <InteractionInterventionBanner\n interventions={selectedInterventions}\n activeTargetId={computer.selectedTarget?.id ?? null}\n mutating={interventions.mutating}\n onOpen={(intervention) =>\n void computer\n .selectTarget(intervention.targetId)\n .catch((cause) => notifyError(cause, \"Could not open the requested desktop view.\"))\n }\n onResolve={resolveIntervention}\n />\n {!selectedRegistrySession ? (\n <ComputerUnselectedPanel\n peerCount={liveSessions.length}\n creating={creating}\n error={createError}\n generationLoss={suppressGenericCreate}\n onCreate={createComputer}\n />\n ) : !controllerReady ? (\n <ComputerLifecyclePanel\n session={selectedRegistrySession}\n creating={creating}\n onRefresh={registry.refresh}\n onRetry={createComputer}\n />\n ) : (\n <>\n <ComputerTargetRail\n targets={computer.targets}\n selectedTargetId={computer.selectedTarget?.id ?? null}\n loading={computer.loading}\n onSelect={(targetId) =>\n void computer\n .selectTarget(targetId)\n .catch((cause) => notifyError(cause, \"Could not switch desktop views.\"))\n }\n />\n <div className=\"flex min-h-0 flex-1 flex-col @xl/computer-viewer:flex-row\">\n {rfbStream ? (\n <div className=\"relative min-h-0 flex-1 bg-black\" onCopyCapture={copyFromRfb}>\n <DesktopViewer\n capability={rfbCapability}\n interactive={rfbInputEnabled}\n showControlToggle={false}\n webSocketProtocols={rfbStream.protocols}\n onPasteText={pasteIntoRfb}\n targetPlatform={computer.session?.platform ?? null}\n className=\"h-full\"\n />\n {!rfbInputEnabled ? (\n <div className=\"pointer-events-none absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full border border-white/10 bg-black/70 px-3 py-1 text-[11px] text-white/80 backdrop-blur\">\n {controlUnavailable ? (\n <>\n Desktop controls unavailable{\" \"}\n <button\n type=\"button\"\n onClick={reconnect}\n className=\"pointer-events-auto ml-2 font-medium underline\"\n >\n Reconnect\n </button>\n </>\n ) : (\n \"View only · direct input unavailable\"\n )}\n </div>\n ) : null}\n </div>\n ) : (\n <ComputerViewport\n key={JSON.stringify([\n selection?.sessionId,\n computer.selectedTarget?.id,\n computer.selectedTarget?.targetGeneration,\n frames.attachment?.controllerGeneration,\n ])}\n frame={machineLocked ? null : displayedFrame}\n observation={computer.observation}\n target={computer.selectedTarget}\n machineLocked={machineLocked}\n controlUnavailable={controlUnavailable}\n connectionState={connectionState}\n connectionError={computer.controlError ?? frames.error ?? computer.error}\n mutating={computer.mutating}\n backgroundActions={computer.session?.capabilities?.backgroundActions === true}\n backgroundInput={computer.session?.capabilities?.backgroundInput === true}\n clipboardEnabled={computer.session?.capabilities?.clipboard === true}\n pointerInput={computer.session?.capabilities?.pointerInput === true}\n keyboardInput={computer.session?.capabilities?.keyboardInput === true}\n onAction={perform}\n onReadClipboard={computer.readClipboard}\n onReconnect={\n generationLossSelected || generationLossFrames ? () => undefined : reconnect\n }\n onError={(cause) => notifyError(cause, \"Desktop input failed.\")}\n />\n )}\n {showControls ? (\n <ComputerSemanticPanel\n observation={computer.observation}\n mutating={computer.mutating || controlUnavailable}\n controlUnavailable={controlUnavailable}\n onAction={(action) =>\n void perform(action, null).catch((cause) =>\n notifyError(cause, \"Desktop action failed.\"),\n )\n }\n />\n ) : null}\n </div>\n <ComputerStatusBar\n session={computer.session}\n target={computer.selectedTarget}\n connectionState={connectionState}\n controlUnavailable={controlUnavailable}\n refreshing={registry.refreshing}\n showControls={showControls}\n controlCount={semanticControls(computer.observation).length}\n onToggleControls={() => setShowControls((current) => !current)}\n />\n </>\n )}\n </div>\n );\n}\n\nfunction ComputerUnselectedPanel(props: {\n peerCount: number;\n creating: boolean;\n error: Error | null;\n generationLoss: boolean;\n onCreate: () => void;\n}) {\n return (\n <div className=\"grid min-h-0 flex-1 place-items-center bg-og-bg p-6 text-center\">\n <div className=\"max-w-sm\">\n <span className=\"mx-auto grid size-10 place-items-center rounded-og-md border border-og-border bg-og-surface-1 text-og-fg-muted\">\n {props.error || props.generationLoss ? (\n <CircleAlertIcon className=\"size-4.5 text-og-danger\" />\n ) : (\n <LoaderCircleIcon className=\"size-4.5 animate-spin\" />\n )}\n </span>\n <p className=\"mt-3 text-og-menu font-medium text-og-fg\">\n {props.generationLoss\n ? \"Chrome reconnected—open a fresh browser/desktop.\"\n : props.error\n ? \"Desktop didn’t open\"\n : \"Opening desktop…\"}\n </p>\n <p className=\"mt-1 text-og-control leading-5 text-og-fg-muted\">\n {props.generationLoss\n ? \"This Chrome profile is live again, but the previous desktop cannot move to the new connection. Use Browser → New browser → Connected Chrome.\"\n : (props.error?.message ??\n (props.peerCount === 1\n ? \"Preparing this agent’s desktop. One peer desktop remains available from the menu.\"\n : `Preparing this agent’s desktop. ${props.peerCount} peer desktops remain available from the menu.`))}\n </p>\n {props.error && !props.generationLoss ? (\n <button\n type=\"button\"\n disabled={props.creating}\n onClick={props.onCreate}\n className=\"mt-4 inline-flex h-8 items-center gap-1.5 rounded-og-sm border border-og-border bg-og-surface-1 px-3 text-og-control font-medium text-og-fg transition hover:bg-og-surface-2 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {props.creating ? (\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" />\n ) : (\n <RotateCcwIcon className=\"size-3.5\" />\n )}\n Try again\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction ComputerToolbar(props: {\n sessions: ComputerSession[];\n relevantSessionIds: Set<string>;\n selectedSessionId: string | null;\n creating: boolean;\n refreshing: boolean;\n interventionCounts: Map<string, number>;\n onSelect: (id: string) => void;\n onFollow: () => void;\n onCreate?: (() => void) | undefined;\n onRefresh: () => void;\n}) {\n const detailsRef = useRef<HTMLDetailsElement | null>(null);\n const selected = props.sessions.find((session) => session.id === props.selectedSessionId);\n const current = props.sessions.filter((session) => props.relevantSessionIds.has(session.id));\n const others = props.sessions.filter((session) => !props.relevantSessionIds.has(session.id));\n const choose = (id: string) => {\n props.onSelect(id);\n detailsRef.current?.removeAttribute(\"open\");\n };\n return (\n <div className=\"flex h-10 shrink-0 items-center gap-1.5 border-b border-og-border bg-og-surface-1 px-2\">\n <details ref={detailsRef} className=\"relative min-w-0\">\n <summary className=\"flex h-7 max-w-52 cursor-pointer list-none items-center gap-2 rounded-og-sm px-2 text-og-control text-og-fg transition hover:bg-og-surface-2 [&::-webkit-details-marker]:hidden\">\n <MonitorIcon className=\"size-3.5 shrink-0 text-og-fg-muted\" />\n <span className=\"truncate font-medium\">\n {selected?.name === \"Computer\" ? \"Desktop\" : (selected?.name ?? \"Desktop\")}\n </span>\n {(props.interventionCounts.get(selected?.id ?? \"\") ?? 0) > 0 ? (\n <span className=\"size-1.5 shrink-0 rounded-full bg-og-status-waiting\" />\n ) : null}\n <ChevronDownIcon className=\"size-3 shrink-0 text-og-fg-subtle\" />\n </summary>\n <div className=\"absolute left-0 top-8 z-30 w-72 overflow-hidden rounded-og-md border border-og-border bg-og-surface-1 p-1 shadow-xl\">\n <ComputerSessionGroup\n label=\"Current agent\"\n sessions={current}\n selectedId={props.selectedSessionId}\n interventionCounts={props.interventionCounts}\n onSelect={choose}\n />\n <ComputerSessionGroup\n label=\"Other agents\"\n sessions={others}\n selectedId={props.selectedSessionId}\n interventionCounts={props.interventionCounts}\n onSelect={choose}\n />\n <div className=\"mt-1 flex gap-1 border-t border-og-border pt-1\">\n {current.length > 0 ? (\n <MenuButton onClick={props.onFollow}>Follow agent</MenuButton>\n ) : null}\n {props.onCreate ? (\n <MenuButton onClick={props.onCreate} disabled={props.creating}>\n <PlusIcon className=\"size-3.5\" /> New desktop\n </MenuButton>\n ) : null}\n </div>\n </div>\n </details>\n <span className=\"min-w-0 flex-1 truncate text-og-xs text-og-fg-subtle\">\n {selected ? `${platformLabel(selected)} · ${placementLabel(selected)}` : \"\"}\n </span>\n <button\n type=\"button\"\n onClick={props.onRefresh}\n className=\"grid size-7 place-items-center rounded-og-sm text-og-fg-muted transition hover:bg-og-surface-2 hover:text-og-fg\"\n aria-label=\"Refresh desktops\"\n >\n <RefreshCwIcon className={cn(\"size-3.5\", props.refreshing && \"animate-spin\")} />\n </button>\n {props.onCreate ? (\n <button\n type=\"button\"\n onClick={props.onCreate}\n disabled={props.creating}\n className=\"grid size-7 place-items-center rounded-og-sm text-og-fg-muted transition hover:bg-og-surface-2 hover:text-og-fg disabled:opacity-40\"\n aria-label=\"Open a new desktop\"\n >\n {props.creating ? (\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" />\n ) : (\n <PlusIcon className=\"size-3.5\" />\n )}\n </button>\n ) : null}\n </div>\n );\n}\n\nfunction ComputerSessionGroup(props: {\n label: string;\n sessions: ComputerSession[];\n selectedId: string | null;\n interventionCounts: Map<string, number>;\n onSelect: (id: string) => void;\n}) {\n if (props.sessions.length === 0) return null;\n return (\n <div className=\"py-1\">\n <p className=\"px-2 pb-1 text-[10px] font-medium uppercase tracking-[0.12em] text-og-fg-subtle\">\n {props.label}\n </p>\n {props.sessions.map((session) => {\n const interventionCount = props.interventionCounts.get(session.id) ?? 0;\n return (\n <button\n key={session.id}\n type=\"button\"\n onClick={() => props.onSelect(session.id)}\n className={cn(\n \"flex w-full items-center gap-2 rounded-og-sm px-2 py-1.5 text-left transition hover:bg-og-surface-2\",\n session.id === props.selectedId && \"bg-og-surface-2\",\n )}\n >\n <span\n className={cn(\n \"size-1.5 rounded-full\",\n session.lifecycle === \"active\" ? \"bg-og-status-running\" : \"bg-og-muted\",\n )}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-og-control text-og-fg\">{session.name}</span>\n <span className=\"block truncate text-og-xs text-og-fg-subtle\">\n {platformLabel(session)} · {placementLabel(session)}\n </span>\n </span>\n {interventionCount > 0 ? (\n <span className=\"rounded-full bg-og-status-waiting/10 px-1.5 py-0.5 text-[10px] font-medium text-og-status-waiting\">\n {interventionCount}\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n );\n}\n\nfunction MenuButton(props: { children: ReactNode; onClick: () => void; disabled?: boolean }) {\n return (\n <button\n type=\"button\"\n onClick={props.onClick}\n disabled={props.disabled}\n className=\"flex h-7 flex-1 items-center justify-center gap-1 rounded-og-sm px-2 text-og-control text-og-fg-muted transition hover:bg-og-surface-2 hover:text-og-fg disabled:opacity-50\"\n >\n {props.children}\n </button>\n );\n}\n\nfunction ComputerTargetRail(props: {\n targets: ComputerTarget[];\n selectedTargetId: string | null;\n loading: boolean;\n onSelect: (id: string) => void;\n}) {\n const visualTargets = props.targets.filter(isRenderableComputerView);\n return (\n <div\n className=\"flex h-10 shrink-0 items-center gap-1 overflow-x-auto border-b border-og-border bg-og-surface-1 px-2\"\n aria-label=\"Desktop views\"\n >\n {visualTargets.map((target) => (\n <button\n key={target.id}\n type=\"button\"\n onClick={() => props.onSelect(target.id)}\n className={cn(\n \"flex h-7 max-w-56 shrink-0 items-center gap-1.5 rounded-og-sm border px-2 text-og-control transition\",\n target.id === props.selectedTargetId\n ? \"border-og-border-strong bg-og-surface-2 text-og-fg\"\n : \"border-transparent text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg\",\n )}\n aria-pressed={target.id === props.selectedTargetId}\n >\n {target.kind === \"screen\" ? (\n <MonitorIcon className=\"size-3.5 shrink-0\" />\n ) : (\n <PanelsTopLeftIcon className=\"size-3.5 shrink-0\" />\n )}\n <span className=\"truncate\">{target.title || target.applicationId || target.kind}</span>\n {target.focused ? (\n <span\n className=\"size-1.5 shrink-0 rounded-full bg-og-status-running\"\n aria-label=\"Focused\"\n />\n ) : null}\n </button>\n ))}\n {props.loading ? (\n <LoaderCircleIcon className=\"ml-1 size-3.5 animate-spin text-og-fg-muted\" />\n ) : null}\n {!props.loading && visualTargets.length === 0 ? (\n <span className=\"text-og-xs text-og-fg-subtle\">Waiting for apps and screens…</span>\n ) : null}\n </div>\n );\n}\n\nfunction isRenderableComputerView(target: ComputerTarget): boolean {\n if (target.kind === \"screen\") return true;\n if (target.kind !== \"window\" || !target.bounds) return false;\n // AX exposes applications and tiny utility/menu windows as valid semantic\n // targets. Keep those available to tools, but do not present them as visual\n // desktop tabs when they cannot form a useful live view.\n return target.bounds.width >= 160 && target.bounds.height >= 90;\n}\n\nfunction isComputerFrameTarget(target: ComputerTarget): boolean {\n return target.kind === \"window\" || target.kind === \"screen\";\n}\n\nfunction ComputerLifecyclePanel(props: {\n session: ComputerSession;\n creating: boolean;\n onRefresh: () => Promise<void>;\n onRetry: () => void;\n}) {\n const generationLoss = isAttachedChromeGenerationLoss(props.session);\n const failed = [\"failed\", \"lost\", \"repair_required\"].includes(props.session.lifecycle);\n const retryCreatesSession = [\"failed\", \"lost\"].includes(props.session.lifecycle);\n return (\n <div className=\"grid min-h-0 flex-1 place-items-center bg-og-bg p-6\">\n <div className=\"max-w-sm text-center\">\n {failed ? (\n <CircleAlertIcon className=\"mx-auto size-5 text-og-danger\" />\n ) : (\n <LoaderCircleIcon className=\"mx-auto size-5 animate-spin text-og-fg-muted\" />\n )}\n <p className=\"mt-3 text-og-menu font-medium text-og-fg\">\n {generationLoss\n ? \"Chrome reconnected—open a fresh browser/desktop.\"\n : failed\n ? \"Desktop needs attention\"\n : lifecycleLabel(props.session.lifecycle)}\n </p>\n <p className=\"mt-1 text-og-control leading-5 text-og-fg-muted\">\n {generationLoss\n ? \"This Chrome profile is live again, but the previous desktop cannot move to the new connection. Use Browser → New browser → Connected Chrome.\"\n : (computerFailureMessage(props.session) ??\n \"The desktop is being prepared on its placement. It will appear here when ready.\")}\n </p>\n {failed && !generationLoss ? (\n <button\n type=\"button\"\n onClick={() => (retryCreatesSession ? props.onRetry() : void props.onRefresh())}\n disabled={props.creating}\n className=\"mt-4 inline-flex h-8 items-center gap-1.5 rounded-og-sm border border-og-border bg-og-surface-1 px-3 text-og-control font-medium text-og-fg transition hover:bg-og-surface-2\"\n >\n {props.creating ? (\n <LoaderCircleIcon className=\"size-3.5 animate-spin\" />\n ) : (\n <RotateCcwIcon className=\"size-3.5\" />\n )}\n {retryCreatesSession ? \"Try again\" : \"Check again\"}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction ComputerViewport(props: {\n frame: ComputerFrame | null;\n observation: ComputerObservation | null;\n target: ComputerTarget | null;\n machineLocked: boolean;\n controlUnavailable: boolean;\n connectionState: string;\n connectionError: Error | null;\n mutating: boolean;\n backgroundActions: boolean;\n backgroundInput: boolean;\n clipboardEnabled: boolean;\n pointerInput: boolean;\n keyboardInput: boolean;\n onAction: (action: ComputerAction, frame: ComputerFrame | null) => Promise<void>;\n onReadClipboard: () => Promise<ComputerClipboard>;\n onReconnect: () => void;\n onError: (cause: unknown) => void;\n}) {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n const composingRef = useRef(false);\n const pointerStartRef = useRef<PointerStart | null>(null);\n const clickTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastClickRef = useRef<{\n at: number;\n x: number;\n y: number;\n frame: ComputerFrame;\n } | null>(null);\n const wheelRef = useRef<{\n x: number;\n y: number;\n deltaX: number;\n deltaY: number;\n frame: ComputerFrame;\n timer: ReturnType<typeof setTimeout> | null;\n } | null>(null);\n const pendingTextRef = useRef<{\n text: string;\n timer: ReturnType<typeof setTimeout>;\n } | null>(null);\n const actionRef = useRef(props.onAction);\n const readClipboardRef = useRef(props.onReadClipboard);\n const errorRef = useRef(props.onError);\n const actionTailRef = useRef<Promise<void>>(Promise.resolve());\n const actionQueueEpochRef = useRef(0);\n const queuedFrameRef = useRef<ComputerFrame | null>(null);\n const currentFrameRef = useRef<ComputerFrame | null>(props.frame);\n const paintedFrameRef = useRef<ComputerFrame | null>(null);\n const [paintedFrame, setPaintedFrame] = useState<ComputerFrame | null>(null);\n const decodingFrameRef = useRef(false);\n const mountedRef = useRef(true);\n actionRef.current = props.onAction;\n readClipboardRef.current = props.onReadClipboard;\n errorRef.current = props.onError;\n const streamFailed = props.connectionState === \"error\";\n const rawInputEnabled =\n !streamFailed &&\n !props.controlUnavailable &&\n !props.machineLocked &&\n (props.backgroundInput ||\n !props.backgroundActions ||\n props.target?.kind === \"screen\" ||\n props.target?.focused === true);\n\n const clearBufferedInput = useCallback(() => {\n if (clickTimerRef.current) clearTimeout(clickTimerRef.current);\n if (wheelRef.current?.timer) clearTimeout(wheelRef.current.timer);\n if (pendingTextRef.current?.timer) clearTimeout(pendingTextRef.current.timer);\n clickTimerRef.current = null;\n wheelRef.current = null;\n pendingTextRef.current = null;\n pointerStartRef.current = null;\n lastClickRef.current = null;\n composingRef.current = false;\n if (inputRef.current) inputRef.current.value = \"\";\n }, []);\n\n const pointerInputEnabled = rawInputEnabled && props.pointerInput;\n const keyboardInputEnabled = rawInputEnabled && props.keyboardInput;\n\n useLayoutEffect(() => {\n const canvas = canvasRef.current;\n const viewport = canvas?.parentElement;\n if (!canvas || !viewport) return;\n const fit = () => fitComputerCanvas(canvas);\n fit();\n if (typeof ResizeObserver === \"undefined\") {\n window.addEventListener(\"resize\", fit);\n return () => window.removeEventListener(\"resize\", fit);\n }\n // The canvas is absolute, so fitting it cannot resize the observed dock.\n const observer = new ResizeObserver(fit);\n observer.observe(viewport);\n return () => observer.disconnect();\n }, []);\n\n const paintQueuedFrames = useCallback(() => {\n if (decodingFrameRef.current) return;\n decodingFrameRef.current = true;\n void (async () => {\n try {\n while (mountedRef.current) {\n const frame = queuedFrameRef.current;\n queuedFrameRef.current = null;\n if (!frame) break;\n let objectUrl: string | null = null;\n try {\n const blob = new Blob([frame.data.slice().buffer], { type: frame.mediaType });\n if (typeof createImageBitmap === \"function\") {\n const bitmap = await createImageBitmap(blob);\n try {\n const canvas = canvasRef.current;\n if (\n mountedRef.current &&\n canvas &&\n currentFrameRef.current &&\n sameComputerTarget(frame, currentFrameRef.current)\n ) {\n paintCanvas(canvas, bitmap, frame.width, frame.height);\n paintedFrameRef.current = frame;\n setPaintedFrame(frame);\n }\n } finally {\n bitmap.close();\n }\n continue;\n }\n objectUrl = URL.createObjectURL(blob);\n const image = await loadImage(objectUrl);\n const canvas = canvasRef.current;\n if (\n mountedRef.current &&\n canvas &&\n currentFrameRef.current &&\n sameComputerTarget(frame, currentFrameRef.current)\n ) {\n paintCanvas(canvas, image, frame.width, frame.height);\n paintedFrameRef.current = frame;\n setPaintedFrame(frame);\n }\n } catch (cause) {\n if (\n mountedRef.current &&\n currentFrameRef.current &&\n sameComputerTarget(frame, currentFrameRef.current)\n )\n errorRef.current(cause);\n } finally {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n }\n }\n } finally {\n decodingFrameRef.current = false;\n if (mountedRef.current && queuedFrameRef.current) paintQueuedFrames();\n }\n })();\n }, []);\n\n useLayoutEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n actionQueueEpochRef.current += 1;\n queuedFrameRef.current = null;\n clearBufferedInput();\n };\n }, [clearBufferedInput]);\n\n useLayoutEffect(() => {\n if (currentFrameRef.current && !props.frame) {\n actionQueueEpochRef.current += 1;\n clearBufferedInput();\n }\n currentFrameRef.current = props.frame;\n if (!props.frame) {\n queuedFrameRef.current = null;\n paintedFrameRef.current = null;\n setPaintedFrame(null);\n return;\n }\n queuedFrameRef.current = props.frame;\n paintQueuedFrames();\n }, [clearBufferedInput, paintQueuedFrames, props.frame]);\n\n useLayoutEffect(() => {\n if (!rawInputEnabled || !props.pointerInput || !props.keyboardInput) {\n actionQueueEpochRef.current += 1;\n clearBufferedInput();\n }\n }, [clearBufferedInput, props.keyboardInput, props.pointerInput, rawInputEnabled]);\n\n const enqueue = useCallback(\n (\n action: ComputerAction,\n frame: ComputerFrame | null,\n after?: (isCurrent: () => boolean) => Promise<void>,\n ) => {\n const epoch = actionQueueEpochRef.current;\n const dispatch = actionRef.current;\n const isCurrent = () => mountedRef.current && epoch === actionQueueEpochRef.current;\n actionTailRef.current = actionTailRef.current\n .catch(() => undefined)\n .then(async () => {\n if (!isCurrent()) return;\n await dispatch(action, frame);\n if (!isCurrent()) return;\n await after?.(isCurrent);\n })\n .catch((cause) => {\n if (!isCurrent()) return;\n actionQueueEpochRef.current += 1;\n clearBufferedInput();\n errorRef.current(cause);\n });\n },\n [clearBufferedInput],\n );\n\n const point = useCallback(\n (frame: ComputerFrame, clientX: number, clientY: number) =>\n computerPoint(canvasRef.current, frame, clientX, clientY),\n [],\n );\n\n const flushPendingText = useCallback(() => {\n const pending = pendingTextRef.current;\n if (!pending) return;\n clearTimeout(pending.timer);\n pendingTextRef.current = null;\n enqueue({ type: \"keyboard\", action: \"type\", value: pending.text }, null);\n }, [enqueue]);\n\n const flushPendingClick = useCallback(() => {\n const pending = lastClickRef.current;\n if (!pending) return;\n if (clickTimerRef.current) clearTimeout(clickTimerRef.current);\n clickTimerRef.current = null;\n lastClickRef.current = null;\n enqueue(\n {\n type: \"pointer\",\n frameId: pending.frame.frameId,\n action: \"click\",\n x: pending.x,\n y: pending.y,\n },\n pending.frame,\n );\n }, [enqueue]);\n\n const flushPendingWheel = useCallback(() => {\n const batch = wheelRef.current;\n if (!batch) return;\n if (batch.timer) clearTimeout(batch.timer);\n wheelRef.current = null;\n enqueue(\n {\n type: \"pointer\",\n frameId: batch.frame.frameId,\n action: \"scroll\",\n x: batch.x,\n y: batch.y,\n deltaX: batch.deltaX,\n deltaY: batch.deltaY,\n },\n batch.frame,\n );\n }, [enqueue]);\n\n const pointerDown = (event: PointerEvent<HTMLCanvasElement>) => {\n const frame = paintedFrameRef.current;\n if (!frame || props.mutating || !rawInputEnabled || event.button !== 0) return;\n // Preserve the keyboard sink's focus through the canvas pointer default action.\n event.preventDefault();\n if (keyboardInputEnabled) inputRef.current?.focus({ preventScroll: true });\n if (!pointerInputEnabled) return;\n flushPendingWheel();\n flushPendingText();\n pointerStartRef.current = {\n x: event.clientX,\n y: event.clientY,\n pointerId: event.pointerId,\n frame,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const pointerUp = (event: PointerEvent<HTMLCanvasElement>) => {\n if (!pointerInputEnabled) return;\n const start = pointerStartRef.current;\n pointerStartRef.current = null;\n if (!start || start.pointerId !== event.pointerId) return;\n const from = point(start.frame, start.x, start.y);\n const to = point(start.frame, event.clientX, event.clientY);\n if (!from || !to) return;\n if (Math.hypot(event.clientX - start.x, event.clientY - start.y) > 5) {\n flushPendingClick();\n enqueue(\n {\n type: \"pointer\",\n frameId: start.frame.frameId,\n action: \"drag\",\n x: from.x,\n y: from.y,\n endX: to.x,\n endY: to.y,\n },\n start.frame,\n );\n return;\n }\n const now = Date.now();\n const previous = lastClickRef.current;\n if (\n previous &&\n now - previous.at < 280 &&\n Math.hypot(previous.x - to.x, previous.y - to.y) < 6 &&\n sameFrameFence(previous.frame, start.frame)\n ) {\n if (clickTimerRef.current) clearTimeout(clickTimerRef.current);\n clickTimerRef.current = null;\n lastClickRef.current = null;\n enqueue(\n {\n type: \"pointer\",\n frameId: start.frame.frameId,\n action: \"double_click\",\n x: to.x,\n y: to.y,\n },\n start.frame,\n );\n return;\n }\n lastClickRef.current = { at: now, x: to.x, y: to.y, frame: start.frame };\n clickTimerRef.current = setTimeout(() => {\n clickTimerRef.current = null;\n lastClickRef.current = null;\n enqueue(\n {\n type: \"pointer\",\n frameId: start.frame.frameId,\n action: \"click\",\n x: to.x,\n y: to.y,\n },\n start.frame,\n );\n }, 280);\n };\n\n const contextMenu = (event: MouseEvent<HTMLCanvasElement>) => {\n event.preventDefault();\n if (!pointerInputEnabled) return;\n const frame = paintedFrameRef.current;\n if (!frame) return;\n flushPendingWheel();\n flushPendingText();\n flushPendingClick();\n const at = point(frame, event.clientX, event.clientY);\n if (at) {\n enqueue(\n {\n type: \"pointer\",\n frameId: frame.frameId,\n action: \"click\",\n x: at.x,\n y: at.y,\n button: \"right\",\n },\n frame,\n );\n }\n };\n\n const wheel = (event: WheelEvent<HTMLCanvasElement>) => {\n if (!pointerInputEnabled) return;\n const frame = paintedFrameRef.current;\n if (!frame) return;\n const at = point(frame, event.clientX, event.clientY);\n if (!at) return;\n flushPendingText();\n flushPendingClick();\n event.preventDefault();\n let pending = wheelRef.current;\n if (\n pending &&\n (!sameComputerTarget(pending.frame, frame) ||\n Math.hypot(pending.x - at.x, pending.y - at.y) > 6)\n ) {\n flushPendingWheel();\n pending = null;\n }\n wheelRef.current = {\n x: at.x,\n y: at.y,\n deltaX: (pending?.deltaX ?? 0) + event.deltaX,\n deltaY: (pending?.deltaY ?? 0) + event.deltaY,\n frame,\n timer: pending?.timer ?? setTimeout(flushPendingWheel, 45),\n };\n };\n\n const keyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (!keyboardInputEnabled) return;\n if (\n composingRef.current ||\n event.nativeEvent.isComposing ||\n event.nativeEvent.keyCode === 229\n ) {\n return;\n }\n flushPendingWheel();\n const command = event.metaKey || event.ctrlKey;\n if (\n props.clipboardEnabled &&\n command &&\n !event.altKey &&\n [\"c\", \"v\"].includes(event.key.toLowerCase())\n ) {\n flushPendingText();\n return;\n }\n const key = computerKey(event);\n if (!key) return;\n event.preventDefault();\n flushPendingText();\n flushPendingClick();\n enqueue({ type: \"keyboard\", action: \"press\", value: key }, null);\n };\n\n const copy = (event: ClipboardEvent<HTMLTextAreaElement>) => {\n if (!props.clipboardEnabled || !keyboardInputEnabled) return;\n event.preventDefault();\n flushPendingWheel();\n flushPendingText();\n flushPendingClick();\n const readClipboard = readClipboardRef.current;\n enqueue({ type: \"clipboard\", operation: \"copy\" }, null, async (isCurrent) => {\n const clipboard = await readClipboard();\n if (!isCurrent()) return;\n if (!clipboard.text) return;\n if (!(await copyTextToClipboard(clipboard.text))) {\n throw new Error(\"Desktop text could not be copied to the local clipboard\");\n }\n });\n };\n\n const paste = (event: ClipboardEvent<HTMLTextAreaElement>) => {\n if (!props.clipboardEnabled || !keyboardInputEnabled) return;\n event.preventDefault();\n flushPendingWheel();\n flushPendingText();\n flushPendingClick();\n const text = event.clipboardData.getData(\"text/plain\");\n const readClipboard = readClipboardRef.current;\n const dispatch = actionRef.current;\n enqueue({ type: \"clipboard\", operation: \"write\", text }, null, async (isCurrent) => {\n const clipboard = await readClipboard();\n if (!isCurrent()) return;\n assertExactComputerClipboard(clipboard, text);\n await dispatch({ type: \"clipboard\", operation: \"paste\" }, null);\n });\n };\n\n const input = (value: string, nativeComposing = false) => {\n if (composingRef.current || nativeComposing) return;\n if (!value || !keyboardInputEnabled) return;\n flushPendingWheel();\n flushPendingClick();\n const pending = pendingTextRef.current;\n if (pending) {\n clearTimeout(pending.timer);\n pending.text += value;\n pending.timer = setTimeout(flushPendingText, 16);\n } else {\n pendingTextRef.current = {\n text: value,\n timer: setTimeout(flushPendingText, 16),\n };\n }\n if (inputRef.current) inputRef.current.value = \"\";\n };\n\n const compositionEnd = (event: CompositionEvent<HTMLTextAreaElement>) => {\n composingRef.current = false;\n input(event.currentTarget.value || event.data);\n };\n\n const showCanvas =\n props.frame !== null &&\n paintedFrame !== null &&\n sameComputerTarget(props.frame, paintedFrame) &&\n !props.machineLocked &&\n !streamFailed;\n return (\n <div className=\"relative min-h-0 flex-1 overflow-hidden bg-black\">\n <canvas\n ref={canvasRef}\n className={cn(\n \"absolute inset-0 m-auto max-h-full max-w-full touch-none focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent\",\n !showCanvas && \"invisible\",\n !pointerInputEnabled && \"cursor-default\",\n )}\n onPointerDown={pointerDown}\n onPointerUp={pointerUp}\n onPointerCancel={() => {\n pointerStartRef.current = null;\n }}\n onContextMenu={contextMenu}\n onWheel={wheel}\n aria-label={`Interactive ${props.target?.kind ?? \"desktop\"} view`}\n />\n <textarea\n ref={inputRef}\n defaultValue=\"\"\n onInput={(event) =>\n input(event.currentTarget.value, (event.nativeEvent as InputEvent).isComposing)\n }\n onCompositionStart={() => {\n composingRef.current = true;\n }}\n onCompositionEnd={compositionEnd}\n onKeyDown={keyDown}\n onCopy={copy}\n onPaste={paste}\n className=\"pointer-events-none absolute left-1/2 top-1/2 size-px resize-none overflow-hidden opacity-0\"\n aria-label=\"Desktop keyboard input\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n disabled={!keyboardInputEnabled}\n />\n {!showCanvas ? (\n <ComputerViewportFallback\n observation={props.observation}\n machineLocked={props.machineLocked}\n controlUnavailable={props.controlUnavailable}\n connectionState={props.connectionState}\n error={props.connectionError}\n onAction={(action) => enqueue(action, null)}\n onReconnect={props.onReconnect}\n />\n ) : null}\n {props.mutating ? (\n <div className=\"pointer-events-none absolute right-3 top-3 flex items-center gap-1.5 rounded-full border border-white/10 bg-black/65 px-2.5 py-1 text-[11px] text-white/80 backdrop-blur\">\n <LoaderCircleIcon className=\"size-3 animate-spin\" /> Acting\n </div>\n ) : null}\n {showCanvas && (!rawInputEnabled || !props.pointerInput || !props.keyboardInput) ? (\n <div className=\"absolute bottom-3 left-1/2 flex w-max max-w-[calc(100%-1.5rem)] -translate-x-1/2 items-center gap-2 rounded-full border border-white/10 bg-black/70 py-1 pl-3 pr-1 text-[11px] text-white/80 backdrop-blur\">\n <span>\n {!rawInputEnabled && (props.pointerInput || props.keyboardInput)\n ? \"Background view · use app controls\"\n : !props.pointerInput && !props.keyboardInput\n ? \"View only · mouse and keyboard unavailable\"\n : props.keyboardInput\n ? \"Keyboard only · mouse unavailable\"\n : \"Mouse only · keyboard unavailable\"}\n </span>\n {!rawInputEnabled && props.target && (props.pointerInput || props.keyboardInput) ? (\n <button\n type=\"button\"\n disabled={props.mutating}\n onClick={() => enqueue({ type: \"focus\", targetId: props.target!.id }, null)}\n className=\"shrink-0 whitespace-nowrap rounded-full bg-white/10 px-2 py-0.5 font-medium text-white transition hover:bg-white/20 disabled:opacity-50\"\n >\n Bring to front\n </button>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction assertExactComputerClipboard(clipboard: ComputerClipboard, expected: string): void {\n if (clipboard.truncated || clipboard.text !== expected) {\n throw new Error(\"Desktop clipboard did not accept the exact pasted text\");\n }\n}\n\nfunction ComputerViewportFallback(props: {\n observation: ComputerObservation | null;\n machineLocked: boolean;\n controlUnavailable: boolean;\n connectionState: string;\n error: Error | null;\n onAction: (action: ComputerAction) => void;\n onReconnect: () => void;\n}) {\n if (props.machineLocked) {\n return (\n <div className=\"absolute inset-0 grid place-items-center bg-og-bg p-6\">\n <div className=\"max-w-sm text-center\">\n <LockKeyholeIcon className=\"mx-auto size-6 text-og-fg-muted\" />\n <p className=\"mt-3 text-og-menu font-medium text-og-fg\">Machine locked</p>\n <p className=\"mt-1 text-og-control leading-5 text-og-fg-muted\">\n Live frames and input stay private until someone unlocks the machine.\n </p>\n </div>\n </div>\n );\n }\n const controlFailure = interactionControlFailureFromError(props.error);\n const interactive = semanticControls(props.observation)\n .filter((node) => semanticAction(node) !== null)\n .slice(0, 10);\n return (\n <div className=\"absolute inset-0 grid place-items-center bg-og-bg p-6\">\n <div className=\"w-full max-w-md rounded-og-lg border border-og-border bg-og-surface-1 p-4 shadow-lg\">\n <div className=\"flex items-center gap-2\">\n {props.error ? (\n <CircleAlertIcon className=\"size-4 text-og-danger\" />\n ) : (\n <LoaderCircleIcon className=\"size-4 animate-spin text-og-fg-muted\" />\n )}\n <p className=\"text-og-menu font-medium text-og-fg\">\n {isAttachedChromeGenerationLossError(props.error)\n ? \"Chrome reconnected—open a fresh browser/desktop.\"\n : props.controlUnavailable\n ? \"Desktop controls unavailable\"\n : props.error\n ? \"Live view disconnected\"\n : computerConnectionLabel(props.connectionState)}\n </p>\n </div>\n {props.error ? (\n <p className=\"mt-2 text-og-control leading-5 text-og-fg-muted\">\n {isAttachedChromeGenerationLossError(props.error)\n ? \"Chrome reconnected—open a fresh browser/desktop. Use Browser → New browser → Connected Chrome.\"\n : (controlFailure?.message ?? props.error.message)}\n </p>\n ) : null}\n {interactive.length > 0 && !props.controlUnavailable ? (\n <div className=\"mt-3 border-t border-og-border pt-3\">\n <p className=\"mb-2 text-og-xs text-og-fg-subtle\">App controls remain available</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {interactive.map((node) => (\n <button\n key={node.ref}\n type=\"button\"\n onClick={() => {\n const action = semanticAction(node);\n if (action) props.onAction(action);\n }}\n className=\"rounded-og-sm border border-og-border bg-og-surface-1 px-2 py-1 text-og-control text-og-fg transition hover:bg-og-surface-2\"\n >\n {node.name || node.role}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n {props.error && !isAttachedChromeGenerationLossError(props.error) ? (\n <button\n type=\"button\"\n onClick={props.onReconnect}\n className=\"mt-3 text-og-control font-medium text-og-accent hover:underline\"\n >\n {controlFailure?.retryable === false ? \"Try again\" : \"Reconnect\"}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction ComputerSemanticPanel(props: {\n observation: ComputerObservation | null;\n mutating: boolean;\n controlUnavailable: boolean;\n onAction: (action: ComputerAction) => void;\n}) {\n const nodes = semanticControls(props.observation).slice(0, 100);\n return (\n <aside className=\"box-border max-h-[40%] w-full shrink-0 overflow-y-auto border-t border-og-border bg-og-surface-1 p-2 @xl/computer-viewer:max-h-none @xl/computer-viewer:w-64 @xl/computer-viewer:border-t-0 @xl/computer-viewer:border-l\">\n <div className=\"mb-2 flex items-center gap-1.5 px-1 text-og-xs font-medium uppercase tracking-[0.1em] text-og-fg-subtle\">\n <KeyboardIcon className=\"size-3\" /> App controls\n </div>\n {props.controlUnavailable ? (\n <p className=\"px-1 py-2 text-og-control leading-5 text-og-fg-muted\">\n Reconnect to use app controls.\n </p>\n ) : null}\n {nodes.length === 0 ? (\n props.controlUnavailable ? null : (\n <p className=\"px-1 py-2 text-og-control leading-5 text-og-fg-muted\">\n This view has no accessibility controls. Use the live image instead.\n </p>\n )\n ) : (\n <div className=\"space-y-0.5\">\n {nodes.map((node) => (\n <ComputerSemanticControl\n key={node.ref}\n node={node}\n mutating={props.mutating}\n onAction={props.onAction}\n />\n ))}\n </div>\n )}\n </aside>\n );\n}\n\nfunction ComputerSemanticControl(props: {\n node: InteractionSemanticNode;\n mutating: boolean;\n onAction: (action: ComputerAction) => void;\n}) {\n const { node } = props;\n const editable = node.actions.includes(\"set_value\");\n const action = semanticAction(node);\n const observedValue = semanticValue(node) ?? \"\";\n const [value, setValue] = useState(() => observedValue);\n\n useEffect(() => {\n setValue(observedValue);\n }, [node.ref, observedValue]);\n\n if (editable) {\n return (\n <form\n className=\"rounded-og-sm px-2 py-1.5 hover:bg-og-surface-2\"\n onSubmit={(event) => {\n event.preventDefault();\n props.onAction({\n type: \"semantic\",\n locator: { kind: \"ref\", ref: node.ref },\n action: \"set_value\",\n value,\n });\n }}\n >\n <label className=\"block truncate text-[10px] uppercase text-og-fg-subtle\">\n {node.name || node.identifier || node.role}\n </label>\n <div className=\"mt-1 flex gap-1\">\n <input\n value={value}\n disabled={props.mutating}\n onChange={(event) => setValue(event.currentTarget.value)}\n className=\"min-w-0 flex-1 rounded-og-sm border border-og-border bg-og-surface-1 px-1.5 py-1 text-og-control text-og-fg outline-hidden focus:border-og-accent\"\n aria-label={`Set ${node.name || node.identifier || node.role}`}\n />\n <button\n type=\"submit\"\n disabled={props.mutating}\n className=\"rounded-og-sm border border-og-border bg-og-surface-1 px-2 text-og-control font-medium text-og-fg transition hover:bg-og-surface-2 disabled:opacity-50\"\n >\n Set\n </button>\n </div>\n </form>\n );\n }\n\n return (\n <button\n type=\"button\"\n disabled={!action || props.mutating}\n onClick={() => {\n if (action) props.onAction(action);\n }}\n className=\"flex w-full items-start gap-2 rounded-og-sm px-2 py-1.5 text-left transition hover:bg-og-surface-2 disabled:cursor-default disabled:hover:bg-transparent\"\n >\n <span className=\"mt-0.5 text-[10px] uppercase text-og-fg-subtle\">{node.role}</span>\n <span className=\"min-w-0 flex-1 truncate text-og-control text-og-fg\">\n {node.name || semanticValue(node) || node.identifier || \"Unnamed control\"}\n </span>\n </button>\n );\n}\n\nfunction ComputerStatusBar(props: {\n session: ComputerSession | null;\n target: ComputerTarget | null;\n connectionState: string;\n controlUnavailable: boolean;\n refreshing: boolean;\n showControls: boolean;\n controlCount: number;\n onToggleControls: () => void;\n}) {\n const screen = props.target?.kind === \"screen\";\n return (\n <div className=\"flex h-8 shrink-0 items-center gap-2 border-t border-og-border bg-og-surface-1 px-2 text-og-xs text-og-fg-subtle\">\n <span\n className={cn(\n \"size-1.5 rounded-full\",\n props.connectionState === \"live\" ? \"bg-og-status-running\" : \"bg-og-muted\",\n )}\n />\n <span>\n {props.controlUnavailable\n ? \"Controls unavailable\"\n : props.connectionState === \"live\"\n ? \"Live\"\n : computerConnectionLabel(props.connectionState)}\n </span>\n <span className=\"min-w-0 flex-1 truncate\">\n {props.controlUnavailable\n ? \"Reconnect to use desktop input\"\n : screen\n ? \"Full screen · input may move pointer and focus\"\n : props.session?.capabilities?.backgroundInput\n ? \"Window · clicks and typing stay in the background\"\n : props.session?.capabilities?.backgroundActions\n ? \"Window · app controls work in the background\"\n : (props.target?.kind ?? \"Desktop\")}\n </span>\n {screen ? <MousePointer2Icon className=\"size-3\" aria-hidden /> : null}\n {props.refreshing ? <LoaderCircleIcon className=\"size-3 animate-spin\" /> : null}\n <button\n type=\"button\"\n onClick={props.onToggleControls}\n aria-pressed={props.showControls}\n className={cn(\n \"rounded px-1.5 py-0.5 transition hover:bg-og-surface-2 hover:text-og-fg\",\n props.showControls && \"bg-og-surface-2 text-og-fg\",\n )}\n >\n Controls {props.controlCount}\n </button>\n </div>\n );\n}\n\nfunction ComputerNotice(props: { icon: ReactNode; text: string; className?: string }) {\n return (\n <div\n className={cn(\n \"grid h-full place-items-center bg-og-bg text-og-control text-og-fg-muted\",\n props.className,\n )}\n >\n <div className=\"flex items-center gap-2\">\n {props.icon}\n {props.text}\n </div>\n </div>\n );\n}\n\nconst structuralRoles = new Set([\n \"frame\",\n \"panel\",\n \"section\",\n \"document\",\n \"document web\",\n \"static\",\n \"static text\",\n \"heading\",\n \"paragraph\",\n \"notification\",\n \"separator\",\n \"tool bar\",\n \"page tab list\",\n]);\n\nfunction semanticControls(observation: ComputerObservation | null): InteractionSemanticNode[] {\n if (observation?.semantic?.kind !== \"snapshot\") return [];\n const result: InteractionSemanticNode[] = [];\n const visit = (node: InteractionSemanticNode) => {\n const role = node.role.trim().toLowerCase();\n const label = node.name?.trim() || node.identifier?.trim();\n if (\n node.actions.includes(\"set_value\") ||\n (label &&\n label.toLowerCase() !== role &&\n !structuralRoles.has(role) &&\n semanticAction(node) !== null)\n ) {\n result.push(node);\n }\n node.children?.forEach(visit);\n };\n observation.semantic.roots.forEach(visit);\n return result;\n}\n\nfunction semanticAction(node: InteractionSemanticNode): ComputerAction | null {\n const invoke = [\"invoke\", \"press\", \"click\"].some((action) => node.actions.includes(action));\n if (invoke) {\n return {\n type: \"semantic\",\n locator: { kind: \"ref\", ref: node.ref },\n action: \"invoke\",\n };\n }\n // A row in the background-native controls panel must never become an\n // implicit foregrounding gesture. Focus remains available through the typed\n // SDK/tool action when the caller explicitly intends to take the shared seat.\n return null;\n}\n\nfunction semanticValue(node: InteractionSemanticNode): string | null {\n return typeof node.value === \"string\" ? node.value : null;\n}\n\nfunction paintCanvas(\n canvas: HTMLCanvasElement,\n image: CanvasImageSource,\n width: number,\n height: number,\n): void {\n const dimensionsChanged = canvas.width !== width || canvas.height !== height;\n canvas.width = width;\n canvas.height = height;\n const context = canvas.getContext(\"2d\", { alpha: false });\n if (!context) throw new Error(\"Desktop canvas is unavailable.\");\n context.drawImage(image, 0, 0, width, height);\n if (dimensionsChanged) fitComputerCanvas(canvas);\n}\n\nfunction fitComputerCanvas(canvas: HTMLCanvasElement): void {\n const viewport = canvas.parentElement;\n if (!viewport || canvas.width <= 0 || canvas.height <= 0) return;\n const scale = Math.min(\n viewport.clientWidth / canvas.width,\n viewport.clientHeight / canvas.height,\n );\n // Hidden docks retain their previous fit until their content box is visible.\n if (!Number.isFinite(scale) || scale <= 0) return;\n canvas.style.width = `${canvas.width * scale}px`;\n canvas.style.height = `${canvas.height * scale}px`;\n}\n\nfunction loadImage(url: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const image = new Image();\n image.onload = () => resolve(image);\n image.onerror = () => reject(new Error(\"Desktop frame image could not be decoded.\"));\n image.src = url;\n });\n}\n\nfunction computerPoint(\n canvas: HTMLCanvasElement | null,\n frame: ComputerFrame,\n clientX: number,\n clientY: number,\n): { x: number; y: number } | null {\n if (!canvas) return null;\n const rect = canvas.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return null;\n return {\n x: Math.max(0, Math.min(frame.width - 1, ((clientX - rect.left) / rect.width) * frame.width)),\n y: Math.max(0, Math.min(frame.height - 1, ((clientY - rect.top) / rect.height) * frame.height)),\n };\n}\n\nexport function computerKey(\n event: Pick<\n KeyboardEvent<HTMLTextAreaElement>,\n \"altKey\" | \"ctrlKey\" | \"key\" | \"metaKey\" | \"shiftKey\"\n >,\n): string | null {\n if ([\"Alt\", \"AltGraph\", \"Control\", \"Meta\", \"Shift\"].includes(event.key)) return null;\n const special = new Set([\n \"Enter\",\n \"Tab\",\n \"Escape\",\n \"Backspace\",\n \"Delete\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"ArrowLeft\",\n \"ArrowRight\",\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n ]);\n const modified = event.altKey || event.ctrlKey || event.metaKey;\n if (!modified && !special.has(event.key)) return null;\n const parts: string[] = [];\n if (event.ctrlKey) parts.push(\"Control\");\n if (event.altKey) parts.push(\"Alt\");\n if (event.metaKey) parts.push(\"Meta\");\n if (event.shiftKey) parts.push(\"Shift\");\n parts.push(event.key === \" \" ? \"Space\" : event.key);\n return parts.join(\"+\");\n}\n\nfunction sameFrameFence(left: ComputerFrame, right: ComputerFrame): boolean {\n return left.frameId === right.frameId && sameComputerTarget(left, right);\n}\n\nfunction sameComputerTarget(left: ComputerFrame, right: ComputerFrame): boolean {\n return (\n left.computerSessionId === right.computerSessionId &&\n left.controllerGeneration === right.controllerGeneration &&\n left.targetId === right.targetId &&\n left.targetGeneration === right.targetGeneration\n );\n}\n\nfunction isLiveComputer(session: ComputerSession): boolean {\n return ![\"ending\", \"ended\", \"failed\", \"lost\"].includes(session.lifecycle);\n}\n\nfunction computerFailureMessage(session: ComputerSession): string | null {\n switch (session.failureCode) {\n case \"machine_locked\":\n return \"Unlock the connected Mac, then try again.\";\n case \"controller_heartbeat_expired\":\n return \"The desktop connection was lost. Try opening it again.\";\n case \"controller_transition_expired\":\n return session.placement.kind === \"attached_device\"\n ? \"Chrome reconnected—open a fresh browser/desktop. Use Browser → New browser → Connected Chrome.\"\n : \"The desktop connection expired. Open a new desktop.\";\n case null:\n return null;\n default:\n return \"The desktop could not be opened. Try again.\";\n }\n}\n\nfunction isAttachedChromeGenerationLoss(session: ComputerSession): boolean {\n return (\n session.lifecycle === \"lost\" &&\n session.failureCode === \"controller_transition_expired\" &&\n session.placement.kind === \"attached_device\"\n );\n}\n\nfunction isAttachedChromeGenerationLossError(error: Error | null): boolean {\n if (!error) return false;\n return /placement instance changed|controller authority changed/i.test(error.message);\n}\n\nfunction countInterventions(\n interventions: readonly InteractionIntervention[],\n): Map<string, number> {\n const counts = new Map<string, number>();\n for (const intervention of interventions) {\n counts.set(intervention.resourceId, (counts.get(intervention.resourceId) ?? 0) + 1);\n }\n return counts;\n}\n\nfunction interventionTitle(intervention: InteractionIntervention): string {\n switch (intervention.kind) {\n case \"manual_login\":\n return \"Sign in needed\";\n case \"mfa\":\n return \"Verification needed\";\n case \"external_action\":\n case \"confirmation\":\n return \"Action needed\";\n case \"other\":\n return \"Desktop needs your help\";\n }\n}\n\nfunction platformLabel(session: ComputerSession): string {\n switch (session.platform) {\n case \"macos\":\n return \"Mac\";\n case \"linux\":\n return \"Linux\";\n case \"windows\":\n return \"Windows\";\n default:\n return \"Desktop\";\n }\n}\n\nfunction placementLabel(session: ComputerSession): string {\n switch (session.placement.kind) {\n case \"sandbox_group\":\n return \"Agent sandbox\";\n case \"connected_machine\":\n return \"Connected machine\";\n case \"attached_device\":\n return \"Your machine\";\n case \"external_provider\":\n return \"Cloud desktop\";\n }\n}\n\nfunction lifecycleLabel(lifecycle: ComputerSession[\"lifecycle\"]): string {\n switch (lifecycle) {\n case \"starting\":\n return \"Opening desktop…\";\n case \"suspending\":\n return \"Pausing desktop…\";\n case \"suspended\":\n return \"Desktop paused\";\n case \"restoring\":\n return \"Restoring desktop…\";\n case \"ending\":\n return \"Closing desktop…\";\n default:\n return \"Connecting to desktop…\";\n }\n}\n\nfunction computerConnectionLabel(state: string): string {\n switch (state) {\n case \"attaching\":\n return \"Opening desktop view…\";\n case \"connecting\":\n return \"Connecting…\";\n case \"reconnecting\":\n return \"Reconnecting…\";\n case \"error\":\n return \"Disconnected\";\n default:\n return \"Waiting for desktop…\";\n }\n}\n","import {\n computerFrameSocketUrl,\n decodeComputerFrameMessage,\n type ComputerFrame,\n type ComputerFrameStreamOptions,\n type ComputerSessionAttachment,\n} from \"@opengeni/sdk/interaction\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n decodeStreamFrame,\n decodeStreamOpenAck,\n encodeStreamClose,\n encodeStreamOpen,\n STREAM_CLOSE_REASON_NORMAL,\n STREAM_KIND_COMPUTER,\n STREAM_ROLE_CLIENT,\n} from \"../lib/relay-wire\";\nimport {\n type EmbeddedComputerInteractionClientOverride,\n useEmbeddedComputerInteraction,\n} from \"../session-context\";\n\nexport type ComputerFrameConnectionState =\n | \"idle\"\n | \"attaching\"\n | \"connecting\"\n | \"live\"\n | \"reconnecting\"\n | \"error\";\n\nexport type ComputerFrameWebSocket = Pick<\n WebSocket,\n \"binaryType\" | \"readyState\" | \"close\" | \"addEventListener\" | \"removeEventListener\"\n> & { send(data: ArrayBuffer): void };\n\nexport type ComputerFrameWebSocketFactory = (\n url: string,\n protocols: string[],\n) => ComputerFrameWebSocket;\n\nconst RELAY_TAG_OPEN = 1;\nconst RELAY_TAG_OPEN_ACK = 2;\nconst RELAY_TAG_FRAME = 3;\nconst RELAY_TAG_CLOSE = 4;\nconst MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME = 2;\n\nexport type UseComputerFrameStreamOptions = EmbeddedComputerInteractionClientOverride & {\n computerSessionId: string | null;\n targetId: string | null;\n enabled?: boolean | undefined;\n stream?: ComputerFrameStreamOptions | undefined;\n webSocketFactory?: ComputerFrameWebSocketFactory | undefined;\n};\n\nexport type UseComputerFrameStreamResult = {\n state: ComputerFrameConnectionState;\n frame: ComputerFrame | null;\n attachment: Pick<\n ComputerSessionAttachment,\n \"computerSessionId\" | \"controllerGeneration\" | \"targetId\" | \"stream\" | \"expiresAt\"\n > | null;\n error: Error | null;\n reconnect: () => void;\n};\n\n/** Reconnecting, latest-only ComputerSession media attachment. Grants remain in\n * WebSocket subprotocols or the relay's authenticated first binary message. */\nexport function useComputerFrameStream(\n options: UseComputerFrameStreamOptions,\n): UseComputerFrameStreamResult {\n const { client, workspaceId } = useEmbeddedComputerInteraction(options);\n const enabled = options.enabled ?? true;\n const [nonce, setNonce] = useState(0);\n const [result, setResult] = useState<Omit<UseComputerFrameStreamResult, \"reconnect\">>({\n state: \"idle\",\n frame: null,\n attachment: null,\n error: null,\n });\n const latestRef = useRef<{ key: string; sequence: number }>({\n key: \"\",\n sequence: -1,\n });\n const factoryRef = useRef(options.webSocketFactory);\n const streamRef = useRef(options.stream);\n factoryRef.current = options.webSocketFactory;\n streamRef.current = options.stream;\n\n const reconnect = useCallback(() => setNonce((value) => value + 1), []);\n\n useEffect(() => {\n const computerSessionId = options.computerSessionId;\n const targetId = options.targetId;\n if (!enabled || !computerSessionId || !targetId || typeof window === \"undefined\") {\n setResult({ state: \"idle\", frame: null, attachment: null, error: null });\n return;\n }\n\n latestRef.current = { key: \"\", sequence: -1 };\n setResult({\n state: \"attaching\",\n frame: null,\n attachment: null,\n error: null,\n });\n\n let disposed = false;\n let socket: ComputerFrameWebSocket | null = null;\n let socketHandlers: {\n open: () => void;\n message: (event: MessageEvent) => void;\n error: () => void;\n close: () => void;\n } | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let expiryTimer: ReturnType<typeof setTimeout> | null = null;\n let failures = 0;\n let controllerGeneration: string | null = null;\n let activeAttachment: ComputerSessionAttachment | null = null;\n let activeStream: ComputerSessionAttachment[\"stream\"] | null = null;\n let attachmentExpiresAt = 0;\n let lastRelaySequence: string | null = null;\n let relayAccepted = false;\n let pendingFrame: { bytes: Uint8Array; source: ComputerFrameWebSocket } | null = null;\n let decodingFrame = false;\n const attachmentAbort = new AbortController();\n\n const clearSocket = (terminateProducer = false) => {\n if (!socket) return;\n const current = socket;\n const handlers = socketHandlers;\n if (terminateProducer && activeStream?.kind === \"relay\" && socket.readyState === 1) {\n try {\n socket.send(\n relayDatagram(\n RELAY_TAG_CLOSE,\n encodeStreamClose({\n channelId: activeStream.channel.channelId,\n reason: STREAM_CLOSE_REASON_NORMAL,\n message: \"viewer detached\",\n }),\n ),\n );\n } catch {\n // OPEN can race a transport close. Local teardown must still finish.\n }\n }\n if (handlers) {\n current.removeEventListener(\"open\", handlers.open);\n current.removeEventListener(\"message\", handlers.message);\n current.removeEventListener(\"error\", handlers.error);\n current.removeEventListener(\"close\", handlers.close);\n }\n if (current.readyState === 0 || current.readyState === 1) {\n current.close(1000, \"viewer detached\");\n }\n socket = null;\n socketHandlers = null;\n pendingFrame = null;\n };\n\n const clearRecoveryTimers = () => {\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (expiryTimer) clearTimeout(expiryTimer);\n reconnectTimer = null;\n expiryTimer = null;\n };\n\n const scheduleReconnect = () => {\n if (disposed || reconnectTimer) return;\n if (failures >= MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME) {\n clearRecoveryTimers();\n return;\n }\n const delay = Math.min(5_000, 250 * 2 ** Math.min(failures, 5));\n failures += 1;\n setResult((current) => ({ ...current, state: \"reconnecting\" }));\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connectSocket();\n }, delay);\n };\n\n const fail = (cause: unknown, reconnectAutomatically = true) => {\n if (disposed) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n setResult((current) => ({ ...current, state: \"error\", error }));\n clearSocket();\n if (reconnectAutomatically) scheduleReconnect();\n else clearRecoveryTimers();\n };\n\n const onOpen = (source: ComputerFrameWebSocket) => {\n if (disposed || source !== socket) return;\n if (activeStream?.kind === \"relay\") {\n const body = encodeStreamOpen({\n channel: { ...activeStream.channel, kind: STREAM_KIND_COMPUTER },\n token: activeStream.token,\n role: STREAM_ROLE_CLIENT,\n resumeFromSeq:\n lastRelaySequence === null ? \"0\" : (BigInt(lastRelaySequence) + 1n).toString(),\n });\n try {\n source.send(relayDatagram(RELAY_TAG_OPEN, body));\n } catch (error) {\n fail(error);\n }\n return;\n }\n setResult((current) => ({ ...current, state: \"live\", error: null }));\n };\n\n const drainLatestFrame = async () => {\n if (decodingFrame) return;\n decodingFrame = true;\n try {\n while (pendingFrame) {\n if (disposed) break;\n const pending = pendingFrame;\n pendingFrame = null;\n const { bytes, source } = pending;\n const frame = await decodeComputerFrameMessage(bytes);\n if (disposed || source !== socket) continue;\n if (frame.computerSessionId !== computerSessionId || frame.targetId !== targetId) {\n throw new Error(\"desktop frame belongs to another resource\");\n }\n if (!controllerGeneration || frame.controllerGeneration !== controllerGeneration) {\n throw new Error(\"desktop frame belongs to a stale controller\");\n }\n const key = `${computerSessionId}:${targetId}:${frame.controllerGeneration}:${frame.targetGeneration}`;\n if (latestRef.current.key === key && frame.sequence <= latestRef.current.sequence)\n continue;\n latestRef.current = { key, sequence: frame.sequence };\n // A real decoded frame—not merely a socket handshake—is the recovery\n // boundary. Resetting on `open` caused a dead producer to reconnect\n // forever and continuously spawn fresh relay/SCK work.\n failures = 0;\n setResult((current) => ({\n ...current,\n state: \"live\",\n frame,\n error: null,\n }));\n }\n } catch (cause) {\n fail(cause);\n } finally {\n decodingFrame = false;\n if (!disposed && pendingFrame) void drainLatestFrame();\n }\n };\n\n const onMessage = (source: ComputerFrameWebSocket, event: MessageEvent) => {\n void (async () => {\n try {\n const bytes = await messageBytes(event.data);\n if (disposed || source !== socket) return;\n let frameBytes = bytes;\n if (activeStream?.kind === \"relay\") {\n if (bytes.length < 1) throw new Error(\"desktop relay returned an empty message\");\n const tag = bytes[0];\n const body = bytes.subarray(1);\n if (tag === RELAY_TAG_OPEN_ACK) {\n const ack = decodeStreamOpenAck(body);\n if (!ack.accepted) {\n activeAttachment = null;\n activeStream = null;\n attachmentExpiresAt = 0;\n throw new Error(ack.error?.message ?? \"desktop stream was rejected by the relay\");\n }\n relayAccepted = true;\n return;\n }\n if (tag === RELAY_TAG_CLOSE) {\n // A relay close is terminal for this producer/channel. Reusing\n // the same attachment only reconnects to a dead channel forever;\n // invalidate it so the retry mints a fresh producer.\n activeAttachment = null;\n activeStream = null;\n attachmentExpiresAt = 0;\n lastRelaySequence = null;\n relayAccepted = false;\n fail(new Error(\"Desktop frame source ended.\"), false);\n return;\n }\n if (tag !== RELAY_TAG_FRAME || !relayAccepted) return;\n const relayFrame = decodeStreamFrame(body);\n lastRelaySequence = relayFrame.seq;\n frameBytes = relayFrame.data;\n }\n // Digest verification can take longer than an inter-frame interval on\n // low-power clients. Keep exactly one pending encoded frame and replace\n // it with newer input while a decode is in flight; never build latency.\n pendingFrame = { bytes: frameBytes, source };\n void drainLatestFrame();\n } catch (cause) {\n fail(cause);\n }\n })();\n };\n\n const onError = (source: ComputerFrameWebSocket) => {\n if (source !== socket) return;\n fail(new Error(\"Desktop view lost connection.\"));\n };\n\n const onClose = (source: ComputerFrameWebSocket) => {\n if (disposed || source !== socket) return;\n fail(new Error(\"Desktop view lost connection.\"));\n };\n\n const connectSocket = () => {\n if (disposed) return;\n clearSocket();\n if (!activeAttachment || !activeStream || attachmentExpiresAt <= Date.now() + 1_000) {\n void attach();\n return;\n }\n if (activeStream.kind === \"direct_rfb\") {\n setResult((current) => ({ ...current, state: \"live\", error: null }));\n return;\n }\n relayAccepted = false;\n setResult((current) => ({\n ...current,\n state: \"connecting\",\n error: null,\n }));\n const createSocket =\n factoryRef.current ?? ((url: string, protocols: string[]) => new WebSocket(url, protocols));\n const openedSocket = createSocket(\n activeStream.kind === \"relay\"\n ? activeStream.url\n : computerFrameSocketUrl(activeAttachment, streamRef.current),\n activeStream.kind === \"direct_websocket\" ? [...activeStream.protocols] : [],\n );\n socket = openedSocket;\n socketHandlers = {\n open: () => onOpen(openedSocket),\n message: (event) => onMessage(openedSocket, event),\n error: () => onError(openedSocket),\n close: () => onClose(openedSocket),\n };\n openedSocket.binaryType = \"arraybuffer\";\n openedSocket.addEventListener(\"open\", socketHandlers.open);\n openedSocket.addEventListener(\"message\", socketHandlers.message);\n openedSocket.addEventListener(\"error\", socketHandlers.error);\n openedSocket.addEventListener(\"close\", socketHandlers.close);\n };\n\n const attach = async () => {\n if (disposed) return;\n clearSocket();\n if (expiryTimer) clearTimeout(expiryTimer);\n setResult((current) => ({\n ...current,\n state: current.attachment ? \"reconnecting\" : \"attaching\",\n error: null,\n }));\n try {\n const attachment = await client.attachComputerSession(\n workspaceId,\n computerSessionId,\n {\n targetId,\n expiresInSeconds: 120,\n ...(streamRef.current ? { stream: streamRef.current } : {}),\n },\n { signal: attachmentAbort.signal },\n );\n if (disposed) return;\n if (\n attachment.computerSessionId !== computerSessionId ||\n attachment.targetId !== targetId\n ) {\n throw new Error(\"desktop attachment does not match the requested resource\");\n }\n controllerGeneration = attachment.controllerGeneration;\n // A fresh attachment owns a new producer whose sequence can restart.\n // Transport reconnects reuse the attachment and retain their sequence fence.\n latestRef.current = { key: \"\", sequence: -1 };\n activeAttachment = attachment;\n activeStream = attachment.stream;\n attachmentExpiresAt = Date.parse(attachment.expiresAt);\n lastRelaySequence = null;\n relayAccepted = false;\n setResult((current) => ({\n ...current,\n state: \"connecting\",\n attachment: {\n computerSessionId: attachment.computerSessionId,\n controllerGeneration: attachment.controllerGeneration,\n targetId: attachment.targetId,\n stream: attachment.stream,\n expiresAt: attachment.expiresAt,\n },\n error: null,\n }));\n const refreshIn = Number.isFinite(attachmentExpiresAt)\n ? Math.max(1_000, attachmentExpiresAt - Date.now() - 5_000)\n : 60_000;\n expiryTimer = setTimeout(() => {\n if (disposed) return;\n clearSocket(true);\n activeAttachment = null;\n activeStream = null;\n attachmentExpiresAt = 0;\n void attach();\n }, refreshIn);\n connectSocket();\n } catch (cause) {\n if (attachmentAbort.signal.aborted || disposed) return;\n fail(cause, !isPlacementGenerationLossError(cause));\n }\n };\n\n void attach();\n return () => {\n disposed = true;\n pendingFrame = null;\n attachmentAbort.abort();\n clearRecoveryTimers();\n clearSocket(true);\n };\n }, [client, enabled, nonce, options.computerSessionId, options.targetId, workspaceId]);\n\n return { ...result, reconnect };\n}\n\nfunction relayDatagram(tag: number, body: Uint8Array): ArrayBuffer {\n const message = new Uint8Array(body.length + 1);\n message[0] = tag;\n message.set(body, 1);\n return message.buffer as ArrayBuffer;\n}\n\nasync function messageBytes(value: unknown): Promise<Uint8Array> {\n if (value instanceof ArrayBuffer) return new Uint8Array(value);\n if (ArrayBuffer.isView(value)) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength).slice();\n }\n if (typeof Blob !== \"undefined\" && value instanceof Blob) {\n return new Uint8Array(await value.arrayBuffer());\n }\n throw new Error(\"desktop frame stream returned a non-binary message\");\n}\n\nfunction isPlacementGenerationLossError(cause: unknown): boolean {\n const message = cause instanceof Error ? cause.message : String(cause);\n return /placement instance changed|controller authority changed/i.test(message);\n}\n","import type {\n ComputerAction,\n ComputerActionReceipt,\n ComputerClipboard,\n ComputerFrame,\n ComputerObservation,\n ComputerSession,\n ComputerTarget,\n} from \"@opengeni/sdk/interaction\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n isInteractionControlUnavailable,\n isNonRetryableInteractionError,\n} from \"../lib/interaction-errors\";\nimport {\n type EmbeddedComputerInteractionClientOverride,\n useEmbeddedComputerInteraction,\n} from \"../session-context\";\nimport { usePageLiveActivity } from \"./internal\";\n\nexport type UseComputerSessionOptions = EmbeddedComputerInteractionClientOverride & {\n computerSessionId: string | null;\n enabled?: boolean | undefined;\n pollIntervalMs?: number | undefined;\n};\n\nexport type UseComputerSessionResult = {\n session: ComputerSession | null;\n targets: ComputerTarget[];\n selectedTarget: ComputerTarget | null;\n observation: ComputerObservation | null;\n loading: boolean;\n mutating: boolean;\n error: Error | null;\n /** Control service loss, independent of target accessibility inspection and media. */\n controlError: Error | null;\n refresh: () => Promise<void>;\n readClipboard: () => Promise<ComputerClipboard>;\n /** Changes only this viewer's target cursor; it never takes ownership or\n * foregrounds an application. */\n selectTarget: (targetId: string) => Promise<ComputerTarget>;\n act: (action: ComputerAction, operationId?: string) => Promise<ComputerActionReceipt>;\n /** Dispatch pointer input against the exact displayed frame. */\n actFromFrame: (\n action: Extract<ComputerAction, { type: \"pointer\" }>,\n frame: ComputerFrame,\n operationId?: string,\n ) => Promise<ComputerActionReceipt>;\n};\n\n/** Selected ComputerSession state. Semantic and pixel input share the same\n * generation-fenced controller operation stream used by agents. */\nexport function useComputerSession(options: UseComputerSessionOptions): UseComputerSessionResult {\n const { client, workspaceId } = useEmbeddedComputerInteraction(options);\n const computerSessionId = options.computerSessionId;\n const enabled = (options.enabled ?? true) && computerSessionId !== null;\n const pageLive = usePageLiveActivity();\n const pollIntervalMs = Math.max(750, options.pollIntervalMs ?? 2_000);\n const [state, setState] = useState<ComputerControlState>(() =>\n emptyState(computerSessionId, enabled),\n );\n const visible =\n state.computerSessionId === computerSessionId ? state : emptyState(computerSessionId, enabled);\n const refreshBlocked = isNonRetryableInteractionError(visible.error);\n const selectedTargetIdRef = useRef<string | null>(visible.selectedTargetId);\n selectedTargetIdRef.current = visible.selectedTargetId;\n const targetsRef = useRef<{\n computerSessionId: string | null;\n targets: ComputerTarget[];\n }>({\n computerSessionId,\n targets: visible.targets,\n });\n const observationRef = useRef<{\n computerSessionId: string | null;\n observation: ComputerObservation | null;\n }>({ computerSessionId, observation: visible.observation });\n if (targetsRef.current.computerSessionId !== computerSessionId) {\n targetsRef.current = { computerSessionId, targets: visible.targets };\n observationRef.current = {\n computerSessionId,\n observation: visible.observation,\n };\n } else {\n targetsRef.current.targets = visible.targets;\n observationRef.current.observation = visible.observation;\n }\n const requestRef = useRef<{ id: number; controller: AbortController | null }>({\n id: 0,\n controller: null,\n });\n const mutationRef = useRef<{\n computerSessionId: string | null;\n count: number;\n }>({\n computerSessionId,\n count: 0,\n });\n const mountedRef = useRef(true);\n\n const invalidateRefresh = useCallback(() => {\n const id = requestRef.current.id + 1;\n requestRef.current.controller?.abort();\n requestRef.current = { id, controller: null };\n }, []);\n\n const refresh = useCallback(async (): Promise<void> => {\n if (!enabled || !computerSessionId) return;\n const id = requestRef.current.id + 1;\n requestRef.current.controller?.abort();\n const controller = new AbortController();\n requestRef.current = { id, controller };\n let discoveryCompleted = false;\n try {\n const [session, targetResponse] = await Promise.all([\n client.getComputerSession(workspaceId, computerSessionId, {\n signal: controller.signal,\n }),\n client.listComputerTargets(workspaceId, computerSessionId, {\n signal: controller.signal,\n }),\n ]);\n discoveryCompleted = true;\n if (!mountedRef.current || requestRef.current.id !== id) return;\n const targets = sortComputerTargets(targetResponse.targets);\n const selected = chooseTarget(targets, selectedTargetIdRef.current, session.platform);\n // Discovery is useful independently of semantic observation. Publish it\n // now so a slow/unresponsive application cannot block the frame stream\n // or prevent the person from choosing a different window or screen.\n const previous = observationRef.current.observation;\n const retainedObservation =\n selected &&\n previous?.target.id === selected.id &&\n previous.target.controllerGeneration === selected.controllerGeneration &&\n previous.target.targetGeneration === selected.targetGeneration\n ? previous\n : null;\n selectedTargetIdRef.current = selected?.id ?? null;\n targetsRef.current = { computerSessionId, targets };\n observationRef.current = { computerSessionId, observation: retainedObservation };\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n session,\n targets,\n selectedTargetId: selected?.id ?? null,\n observation: retainedObservation,\n loading: false,\n error: null,\n controlError: null,\n }\n : current,\n );\n const observation = selected\n ? await client.observeComputerTarget(workspaceId, computerSessionId, selected.id, {\n signal: controller.signal,\n })\n : null;\n if (!mountedRef.current || requestRef.current.id !== id) return;\n selectedTargetIdRef.current = selected?.id ?? null;\n targetsRef.current = { computerSessionId, targets };\n observationRef.current = { computerSessionId, observation };\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n session,\n targets,\n selectedTargetId: selected?.id ?? null,\n observation,\n loading: false,\n error: null,\n }\n : current,\n );\n } catch (cause) {\n if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n loading: false,\n error,\n controlError: isInteractionControlUnavailable(\n error,\n discoveryCompleted ? \"observation\" : \"control\",\n )\n ? error\n : current.controlError,\n }\n : current,\n );\n } finally {\n if (requestRef.current.id === id) requestRef.current = { id, controller: null };\n }\n }, [client, computerSessionId, enabled, workspaceId]);\n\n useEffect(() => {\n mountedRef.current = true;\n if (!enabled) {\n invalidateRefresh();\n setState(emptyState(computerSessionId, false));\n return;\n }\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? { ...current, loading: true }\n : emptyState(computerSessionId, true),\n );\n void refresh();\n return () => {\n mountedRef.current = false;\n invalidateRefresh();\n };\n }, [computerSessionId, enabled, invalidateRefresh, refresh]);\n\n useEffect(() => {\n if (!enabled || !pageLive || visible.mutating || refreshBlocked) return;\n const timer = setInterval(() => {\n if (!requestRef.current.controller) void refresh();\n }, pollIntervalMs);\n return () => clearInterval(timer);\n }, [enabled, pageLive, pollIntervalMs, refresh, refreshBlocked, visible.mutating]);\n\n useEffect(() => {\n if (!enabled || !computerSessionId || !pageLive || refreshBlocked) return;\n let disposed = false;\n const timer = setInterval(() => {\n void client.heartbeatComputerSession(workspaceId, computerSessionId).catch(() => {\n if (!disposed) void refresh();\n });\n }, 30_000);\n return () => {\n disposed = true;\n clearInterval(timer);\n };\n }, [client, computerSessionId, enabled, pageLive, refresh, refreshBlocked, workspaceId]);\n\n const runMutation = useCallback(\n async <T>(scopeComputerSessionId: string, operation: () => Promise<T>): Promise<T> => {\n invalidateRefresh();\n if (mutationRef.current.computerSessionId !== scopeComputerSessionId) {\n mutationRef.current = {\n computerSessionId: scopeComputerSessionId,\n count: 0,\n };\n }\n mutationRef.current.count += 1;\n setState((current) =>\n current.computerSessionId === scopeComputerSessionId\n ? { ...current, mutating: true, error: null }\n : current,\n );\n try {\n const result = await operation();\n setState((current) =>\n current.computerSessionId === scopeComputerSessionId\n ? { ...current, controlError: null }\n : current,\n );\n return result;\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n setState((current) =>\n current.computerSessionId === scopeComputerSessionId\n ? {\n ...current,\n error,\n controlError: isInteractionControlUnavailable(error) ? error : current.controlError,\n }\n : current,\n );\n throw error;\n } finally {\n if (mutationRef.current.computerSessionId === scopeComputerSessionId) {\n mutationRef.current.count = Math.max(0, mutationRef.current.count - 1);\n const mutating = mutationRef.current.count > 0;\n setState((current) =>\n current.computerSessionId === scopeComputerSessionId\n ? { ...current, mutating }\n : current,\n );\n }\n }\n },\n [invalidateRefresh],\n );\n\n const selectTarget = useCallback(\n async (targetId: string): Promise<ComputerTarget> => {\n if (!computerSessionId) throw new Error(\"No desktop is selected.\");\n const target = targetsRef.current.targets.find((candidate) => candidate.id === targetId);\n if (!target) throw new Error(\"The selected desktop target is no longer available.\");\n invalidateRefresh();\n selectedTargetIdRef.current = target.id;\n observationRef.current = { computerSessionId, observation: null };\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n selectedTargetId: target.id,\n observation: null,\n loading: true,\n error: null,\n }\n : current,\n );\n try {\n const observation = await client.observeComputerTarget(\n workspaceId,\n computerSessionId,\n target.id,\n );\n if (selectedTargetIdRef.current !== target.id) return target;\n observationRef.current = { computerSessionId, observation };\n setState((current) =>\n current.computerSessionId === computerSessionId && current.selectedTargetId === target.id\n ? { ...current, observation, loading: false, error: null }\n : current,\n );\n return observation.target;\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n setState((current) =>\n current.computerSessionId === computerSessionId && current.selectedTargetId === target.id\n ? {\n ...current,\n loading: false,\n error,\n controlError: isInteractionControlUnavailable(error, \"observation\")\n ? error\n : current.controlError,\n }\n : current,\n );\n throw error;\n }\n },\n [client, computerSessionId, invalidateRefresh, workspaceId],\n );\n\n const dispatchAction = useCallback(\n async (\n action: ComputerAction,\n operationId: string,\n frame: ComputerFrame | null,\n ): Promise<ComputerActionReceipt> => {\n if (!computerSessionId) throw new Error(\"No desktop is selected.\");\n if (frame && frame.computerSessionId !== computerSessionId) {\n throw new Error(\"The displayed desktop frame belongs to another desktop session.\");\n }\n const currentObservation =\n observationRef.current.computerSessionId === computerSessionId\n ? observationRef.current.observation\n : null;\n const focusTarget =\n action.type === \"focus\"\n ? (targetsRef.current.targets.find((candidate) => candidate.id === action.targetId) ??\n null)\n : null;\n const frameTarget = frame\n ? (targetsRef.current.targets.find((candidate) => candidate.id === frame.targetId) ??\n (currentObservation?.target.id === frame.targetId ? currentObservation.target : null))\n : null;\n const inputTarget =\n (action.type === \"keyboard\" || action.type === \"clipboard\") &&\n targetsRef.current.computerSessionId === computerSessionId\n ? targetsRef.current.targets.find(\n (candidate) => candidate.id === selectedTargetIdRef.current,\n )\n : null;\n const target =\n frameTarget ?? focusTarget ?? currentObservation?.target ?? inputTarget ?? null;\n if (!target) throw new Error(\"The desktop target is not ready for input.\");\n if (frame && frame.targetId !== selectedTargetIdRef.current) {\n throw new Error(\"The displayed desktop frame is no longer selected.\");\n }\n if (action.type === \"pointer\") {\n const expectedFrameId = frame?.frameId ?? currentObservation?.frameId ?? null;\n if (!expectedFrameId || action.frameId !== expectedFrameId) {\n throw new Error(\"Pointer input must reference the exact displayed desktop frame.\");\n }\n }\n if (action.type === \"semantic\" && !currentObservation) {\n throw new Error(\"The desktop accessibility tree is not ready for input.\");\n }\n\n return await runMutation(computerSessionId, async () => {\n const receipt = await client.actInComputer(workspaceId, computerSessionId, {\n operationId,\n targetId: target.id,\n expectedTargetGeneration: frame?.targetGeneration ?? target.targetGeneration,\n expectedObservationId:\n action.type === \"pointer\" ? null : (currentObservation?.observationId ?? null),\n expectedFrameId: action.type === \"pointer\" ? action.frameId : null,\n action,\n });\n if (receipt.observation) {\n const observation = receipt.observation;\n observationRef.current = { computerSessionId, observation };\n selectedTargetIdRef.current = observation.target.id;\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n observation,\n selectedTargetId: observation.target.id,\n targets: replaceTarget(current.targets, observation.target),\n }\n : current,\n );\n } else {\n void refresh();\n }\n return receipt;\n });\n },\n [client, computerSessionId, refresh, runMutation, workspaceId],\n );\n\n const act = useCallback(\n async (\n action: ComputerAction,\n operationId: string = crypto.randomUUID(),\n ): Promise<ComputerActionReceipt> => await dispatchAction(action, operationId, null),\n [dispatchAction],\n );\n\n const actFromFrame = useCallback(\n async (\n action: Extract<ComputerAction, { type: \"pointer\" }>,\n frame: ComputerFrame,\n operationId: string = crypto.randomUUID(),\n ): Promise<ComputerActionReceipt> => await dispatchAction(action, operationId, frame),\n [dispatchAction],\n );\n\n const readClipboard = useCallback(async (): Promise<ComputerClipboard> => {\n if (!computerSessionId) throw new Error(\"No desktop is selected.\");\n try {\n return await client.readComputerClipboard(workspaceId, computerSessionId);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n setState((current) =>\n current.computerSessionId === computerSessionId\n ? {\n ...current,\n error,\n controlError: isInteractionControlUnavailable(error) ? error : current.controlError,\n }\n : current,\n );\n throw error;\n }\n }, [client, computerSessionId, workspaceId]);\n\n return {\n session: visible.session,\n targets: visible.targets,\n selectedTarget:\n visible.targets.find((target) => target.id === visible.selectedTargetId) ?? null,\n observation: visible.observation,\n loading: visible.loading,\n mutating: visible.mutating,\n error: visible.error,\n controlError: visible.controlError,\n refresh,\n readClipboard,\n selectTarget,\n act,\n actFromFrame,\n };\n}\n\ntype ComputerControlState = {\n computerSessionId: string | null;\n session: ComputerSession | null;\n targets: ComputerTarget[];\n selectedTargetId: string | null;\n observation: ComputerObservation | null;\n loading: boolean;\n mutating: boolean;\n error: Error | null;\n controlError: Error | null;\n};\n\nfunction emptyState(computerSessionId: string | null, loading: boolean): ComputerControlState {\n return {\n computerSessionId,\n session: null,\n targets: [],\n selectedTargetId: null,\n observation: null,\n loading,\n mutating: false,\n error: null,\n controlError: null,\n };\n}\n\nfunction chooseTarget(\n targets: readonly ComputerTarget[],\n preferredId: string | null,\n platform: ComputerSession[\"platform\"],\n): ComputerTarget | null {\n const preferred = targets.find((target) => target.id === preferredId);\n if (preferred) return preferred;\n if (platform === \"linux\") {\n return (\n targets.find((target) => target.focused && target.kind === \"screen\") ??\n targets.find((target) => target.kind === \"screen\") ??\n targets.find((target) => target.focused && target.kind === \"window\") ??\n targets.find((target) => target.kind === \"window\") ??\n targets[0] ??\n null\n );\n }\n return (\n targets.find((target) => target.focused && target.kind === \"window\") ??\n targets.find((target) => target.kind === \"window\") ??\n targets.find((target) => target.kind === \"screen\") ??\n targets.find((target) => target.focused && target.kind === \"app\") ??\n targets.find((target) => target.kind === \"app\") ??\n targets[0] ??\n null\n );\n}\n\nfunction sortComputerTargets(targets: readonly ComputerTarget[]): ComputerTarget[] {\n const rank = { window: 0, app: 1, screen: 2 } as const;\n return [...targets].sort(\n (left, right) =>\n Number(right.focused) - Number(left.focused) ||\n rank[left.kind] - rank[right.kind] ||\n left.title.localeCompare(right.title) ||\n left.id.localeCompare(right.id),\n );\n}\n\nfunction replaceTarget(\n targets: readonly ComputerTarget[],\n target: ComputerTarget,\n): ComputerTarget[] {\n return sortComputerTargets([\n ...targets.filter((candidate) => candidate.id !== target.id),\n target,\n ]);\n}\n","import type {\n ComputerSession,\n ComputerSessionMutationResponse,\n CreateComputerSessionRequest,\n} from \"@opengeni/sdk/interaction\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { EmbeddedComputerInteractionClientLike } from \"../client\";\nimport {\n type EmbeddedComputerInteractionClientOverride,\n useEmbeddedComputerInteraction,\n} from \"../session-context\";\nimport { useInteractionInvalidation } from \"./use-interaction-invalidation\";\n\nexport type UseComputerSessionsOptions = EmbeddedComputerInteractionClientOverride & {\n /** Current agent/session relevance. Workspace peers remain in `sessions`. */\n sessionId?: string | undefined;\n enabled?: boolean | undefined;\n /** Polling fallback used only while the workspace invalidation stream is unavailable. */\n pollIntervalMs?: number | undefined;\n};\n\nexport type UseComputerSessionsResult = {\n revision: number;\n sessions: ComputerSession[];\n relevantSessions: ComputerSession[];\n loading: boolean;\n refreshing: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (\n request: Omit<CreateComputerSessionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ) => Promise<ComputerSessionMutationResponse>;\n end: (\n computerSessionId: string,\n operationId?: string,\n ) => Promise<ComputerSessionMutationResponse>;\n};\n\n/** Workspace-wide ComputerSession registry. Associations rank relevance but\n * never hide peer resources or create an ownership boundary. */\nexport function useComputerSessions(\n options: UseComputerSessionsOptions = {},\n): UseComputerSessionsResult {\n const {\n client,\n workspaceId,\n registerSessionReconciler,\n workspaceInteractionEvent,\n workspaceInteractionConnectionState,\n } = useEmbeddedComputerInteraction(options);\n const enabled = options.enabled ?? true;\n const [state, setState] = useState<ComputerRegistryState>(() => emptyState(workspaceId, enabled));\n const requestRef = useRef<{ id: number; controller: AbortController | null }>({\n id: 0,\n controller: null,\n });\n const mountedRef = useRef(true);\n const visible = state.workspaceId === workspaceId ? state : emptyState(workspaceId, enabled);\n\n const cancelLoad = useCallback(() => {\n const id = requestRef.current.id + 1;\n requestRef.current.controller?.abort();\n requestRef.current = { id, controller: null };\n }, []);\n\n const load = useCallback(\n async (foreground: boolean): Promise<void> => {\n if (!enabled) return;\n const id = requestRef.current.id + 1;\n requestRef.current.controller?.abort();\n const controller = new AbortController();\n requestRef.current = { id, controller };\n setState((current) => ({\n ...(current.workspaceId === workspaceId ? current : emptyState(workspaceId, true)),\n active: true,\n loading: foreground,\n refreshing: !foreground,\n error: foreground || current.workspaceId !== workspaceId ? null : current.error,\n }));\n try {\n const response = await client.listComputerSessions(workspaceId, {\n signal: controller.signal,\n });\n if (!mountedRef.current || requestRef.current.id !== id) return;\n setState({\n workspaceId,\n active: true,\n revision: response.revision,\n sessions: sortComputerSessions(response.sessions),\n loading: false,\n refreshing: false,\n error: null,\n });\n } catch (cause) {\n if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id)\n return;\n setState((current) => ({\n ...(current.workspaceId === workspaceId ? current : emptyState(workspaceId, true)),\n loading: false,\n refreshing: false,\n error: cause instanceof Error ? cause : new Error(String(cause)),\n }));\n } finally {\n if (requestRef.current.id === id) requestRef.current = { id, controller: null };\n }\n },\n [client, enabled, workspaceId],\n );\n\n const refresh = useCallback(async () => await load(false), [load]);\n\n useEffect(() => {\n mountedRef.current = true;\n if (!enabled) {\n cancelLoad();\n setState(emptyState(workspaceId, false));\n return;\n }\n void load(true);\n return () => {\n mountedRef.current = false;\n cancelLoad();\n };\n }, [cancelLoad, enabled, load, workspaceId]);\n\n useInteractionInvalidation({\n workspaceId,\n key: workspaceId,\n enabled,\n event: workspaceInteractionEvent,\n connectionState: workspaceInteractionConnectionState,\n knownRevision: visible.revision,\n refresh,\n fallbackPollIntervalMs: options.pollIntervalMs,\n });\n\n useEffect(() => {\n if (!enabled || !options.sessionId) return;\n return registerSessionReconciler(\n options.sessionId,\n `computer-sessions:${workspaceId}`,\n refresh,\n );\n }, [enabled, options.sessionId, refresh, registerSessionReconciler, workspaceId]);\n\n const create = useCallback(\n async (\n request: Omit<CreateComputerSessionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ): Promise<ComputerSessionMutationResponse> => {\n const response = await client.createComputerSession(workspaceId, {\n ...request,\n operationId: request.operationId ?? crypto.randomUUID(),\n });\n setState((current) => mergeSession(current, workspaceId, response.session));\n return response;\n },\n [client, workspaceId],\n );\n\n const end = useCallback(\n async (\n computerSessionId: string,\n operationId: string = crypto.randomUUID(),\n ): Promise<ComputerSessionMutationResponse> => {\n const response = await client.endComputerSession(workspaceId, computerSessionId, {\n operationId,\n });\n setState((current) => mergeSession(current, workspaceId, response.session));\n return response;\n },\n [client, workspaceId],\n );\n\n const relevantSessions = useMemo(\n () =>\n options.sessionId\n ? visible.sessions.filter((session) =>\n session.associations.some((association) => association.sessionId === options.sessionId),\n )\n : [],\n [options.sessionId, visible.sessions],\n );\n\n return {\n revision: visible.revision,\n sessions: visible.sessions,\n relevantSessions,\n // A disabled registry is deliberately empty. When its surface becomes\n // visible again, expose that transition as loading in the same render so\n // consumers cannot mistake the stale empty snapshot for a completed list.\n loading: enabled ? !visible.active || visible.loading : false,\n refreshing: visible.refreshing,\n error: visible.error,\n refresh,\n create,\n end,\n };\n}\n\ntype ComputerRegistryState = {\n workspaceId: string;\n active: boolean;\n revision: number;\n sessions: ComputerSession[];\n loading: boolean;\n refreshing: boolean;\n error: Error | null;\n};\n\nfunction emptyState(workspaceId: string, loading: boolean): ComputerRegistryState {\n return {\n workspaceId,\n active: loading,\n revision: 0,\n sessions: [],\n loading,\n refreshing: false,\n error: null,\n };\n}\n\nfunction sortComputerSessions(sessions: readonly ComputerSession[]): ComputerSession[] {\n return [...sessions].sort((left, right) => {\n const live = Number(isLiveComputer(right)) - Number(isLiveComputer(left));\n return (\n live ||\n timestamp(right.lastUsedAt) - timestamp(left.lastUsedAt) ||\n left.id.localeCompare(right.id)\n );\n });\n}\n\nfunction isLiveComputer(session: ComputerSession): boolean {\n return ![\"ending\", \"ended\", \"failed\", \"lost\"].includes(session.lifecycle);\n}\n\nfunction timestamp(value: string): number {\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction mergeSession(\n current: ComputerRegistryState,\n workspaceId: string,\n session: ComputerSession,\n): ComputerRegistryState {\n if (current.workspaceId !== workspaceId) return current;\n const sessions = current.sessions.filter((candidate) => candidate.id !== session.id);\n sessions.push(session);\n return { ...current, sessions: sortComputerSessions(sessions), error: null };\n}\n\n/** Exported for narrow proxy implementations and tests. */\nexport type ComputerSessionsClient = EmbeddedComputerInteractionClientLike;\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useEffect","useRef","useState","useState","emptyState","useRef","useCallback","useEffect","useMemo","isLiveComputer","useState","useCallback","useRef","useEffect","canvas"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/internal.ts"],"sourcesContent":["import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { EmbeddedSessionEventClientLike } from \"../client\";\nimport { normalizeError } from \"../lib/error-message\";\n\nconst HIDDEN_STREAM_GRACE_MS = 2_000;\n\n/**\n * Keep live browser work active while the page is visible, then suspend it\n * after a short hidden-tab grace period. Returning to the page re-enables the\n * caller, which must reconcile durable state before resuming live delivery.\n */\nexport function usePageLiveActivity(hiddenGraceMs = HIDDEN_STREAM_GRACE_MS): boolean {\n // Keep the server and initial browser render identical; the effect applies\n // visibility after mount and preserves the intentional hidden-tab grace.\n const [active, setActive] = useState(true);\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n let hiddenTimer: ReturnType<typeof setTimeout> | null = null;\n const cancelHiddenTimer = () => {\n if (hiddenTimer !== null) {\n clearTimeout(hiddenTimer);\n hiddenTimer = null;\n }\n };\n const sync = () => {\n cancelHiddenTimer();\n if (document.visibilityState !== \"hidden\") {\n setActive(true);\n return;\n }\n hiddenTimer = setTimeout(() => {\n hiddenTimer = null;\n if (document.visibilityState === \"hidden\") setActive(false);\n }, hiddenGraceMs);\n };\n document.addEventListener(\"visibilitychange\", sync);\n window.addEventListener(\"pageshow\", sync);\n sync();\n return () => {\n cancelHiddenTimer();\n document.removeEventListener(\"visibilitychange\", sync);\n window.removeEventListener(\"pageshow\", sync);\n };\n }, [hiddenGraceMs]);\n\n return active;\n}\n\nexport type AsyncListState<T> = {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Shared fetch + optional polling loop for the list/read hooks. Stale\n * responses (superseded by a newer load or an unmount) are dropped.\n */\nexport function usePolledValue<T>(\n load: (signal?: AbortSignal) => Promise<T>,\n options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {},\n): AsyncListState<T> {\n const enabled = options.enabled ?? true;\n const pollIntervalMs = options.pollIntervalMs;\n const pageLive = usePageLiveActivity();\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const generation = useRef(0);\n const activeLoadRef = useRef(load);\n useLayoutEffect(() => {\n activeLoadRef.current = load;\n }, [load]);\n const requestAbortRef = useRef<AbortController | null>(null);\n const inFlightRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);\n const trailingRefreshRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);\n const [stateIdentity, setStateIdentity] = useState<{ load: typeof load }>(() => ({ load }));\n\n // A new loader identity means a new query (different session/workspace/...):\n // drop the previous result instead of showing it as the new query's data.\n useEffect(() => {\n if (stateIdentity.load !== load) {\n setStateIdentity({ load });\n setData(null);\n setError(null);\n }\n }, [load, stateIdentity.load]);\n\n const run = useCallback((): Promise<void> => {\n // A callback retained by a completed mutation from the previous query must\n // not supersede or settle the current query's request.\n if (activeLoadRef.current !== load) return Promise.resolve();\n const existing = inFlightRef.current;\n if (existing?.load === load) return existing.promise;\n const ticket = ++generation.current;\n const requestAbort = new AbortController();\n requestAbortRef.current = requestAbort;\n let promise!: Promise<void>;\n promise = (async () => {\n try {\n const result = await load(requestAbort.signal);\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setData(result);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setError(normalizeError(cause));\n setLoading(false);\n }\n } finally {\n if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;\n if (inFlightRef.current?.promise === promise) inFlightRef.current = null;\n }\n })();\n inFlightRef.current = { load, promise };\n return promise;\n }, [load]);\n\n const refresh = useCallback((): Promise<void> => {\n const existing = inFlightRef.current;\n if (existing?.load !== load) return run();\n const trailing = trailingRefreshRef.current;\n if (trailing?.load === load) return trailing.promise;\n let promise!: Promise<void>;\n promise = existing.promise.then(async () => {\n if (trailingRefreshRef.current?.promise === promise) {\n trailingRefreshRef.current = null;\n }\n if (activeLoadRef.current === load) await run();\n });\n trailingRefreshRef.current = { load, promise };\n return promise;\n }, [load, run]);\n\n useEffect(() => {\n if (!enabled || !pageLive) {\n setLoading(false);\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n return;\n }\n setLoading(true);\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const schedule = () => {\n if (cancelled || pollIntervalMs === undefined || pollIntervalMs <= 0) return;\n timer = setTimeout(() => {\n timer = null;\n void run().finally(schedule);\n }, pollIntervalMs);\n };\n void run().finally(schedule);\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n cancelled = true;\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n };\n }\n return () => {\n cancelled = true;\n if (timer !== null) clearTimeout(timer);\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n };\n }, [run, enabled, pageLive, pollIntervalMs]);\n\n const identityMatches = stateIdentity.load === load;\n return {\n data: identityMatches ? data : null,\n loading: identityMatches ? loading : enabled,\n error: identityMatches ? error : null,\n refresh,\n };\n}\n\nexport type MutationState = {\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Shared async mutation runner for the write hooks. `run` resolves with the\n * operation's value, or `null` after capturing the error in `mutationError`\n * (callers then roll back optimistic state).\n */\nexport function useMutationRunner(identity: unknown = undefined): MutationState & {\n run: <T>(operation: () => Promise<T>) => Promise<T | null>;\n} {\n const [mutating, setMutating] = useState(false);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState<unknown>(() => identity);\n const inFlight = useRef(0);\n const generation = useRef(0);\n const identityRef = useRef(identity);\n useLayoutEffect(() => {\n if (Object.is(identityRef.current, identity)) return;\n identityRef.current = identity;\n generation.current += 1;\n inFlight.current = 0;\n }, [identity]);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n useEffect(() => {\n if (!Object.is(stateIdentity, identity)) {\n setStateIdentity(() => identity);\n setMutating(false);\n setMutationError(null);\n }\n }, [identity, stateIdentity]);\n const run = useCallback(\n async <T>(operation: () => Promise<T>): Promise<T | null> => {\n const ownedIdentity = identity;\n const ownedGeneration = generation.current;\n if (!Object.is(identityRef.current, ownedIdentity)) return null;\n inFlight.current += 1;\n if (mounted.current) {\n setMutating(true);\n setMutationError(null);\n }\n try {\n const result = await operation();\n if (\n !mounted.current ||\n generation.current !== ownedGeneration ||\n !Object.is(identityRef.current, ownedIdentity)\n ) {\n return null;\n }\n return result;\n } catch (cause) {\n if (\n mounted.current &&\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n setMutationError(normalizeError(cause));\n }\n return null;\n } finally {\n if (\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n inFlight.current -= 1;\n if (mounted.current && inFlight.current === 0) {\n setMutating(false);\n }\n }\n }\n },\n [identity],\n );\n const identityMatches = Object.is(stateIdentity, identity);\n return {\n mutating: identityMatches && mutating,\n mutationError: identityMatches ? mutationError : null,\n clearMutationError: useCallback(() => {\n if (Object.is(identityRef.current, identity)) setMutationError(null);\n }, [identity]),\n run,\n };\n}\n\nexport type SessionEventFeedOptions = {\n /**\n * Share an existing event log (from `useSessionEvents`) instead of opening\n * a second stream. When omitted the hook tails the session's event stream\n * itself, starting at the current `lastSequence`.\n */\n events?: SessionEvent[] | undefined;\n enabled?: boolean | undefined;\n};\n\n/**\n * Invoke `onEvent` for every session event matching `match` — the live-update\n * primitive behind `useTurnQueue` and `useGoal`. Either watches a shared\n * `events` log or tails the stream directly (reconnect handled by the SDK).\n */\nexport function useSessionEventTrigger(\n client: EmbeddedSessionEventClientLike,\n workspaceId: string,\n sessionId: string | null | undefined,\n match: (event: SessionEvent) => boolean,\n onEvent: (event: SessionEvent) => void,\n options: SessionEventFeedOptions = {},\n reconcileBeforeLive?: (() => void | Promise<void>) | undefined,\n): void {\n const enabled = options.enabled ?? true;\n const pageLive = usePageLiveActivity();\n const liveEnabled = enabled && pageLive;\n const events = options.events;\n const sharedFeed = events !== undefined;\n const matchRef = useRef(match);\n const onEventRef = useRef(onEvent);\n const reconcileBeforeLiveRef = useRef(reconcileBeforeLive);\n useLayoutEffect(() => {\n matchRef.current = match;\n onEventRef.current = onEvent;\n reconcileBeforeLiveRef.current = reconcileBeforeLive;\n }, [match, onEvent, reconcileBeforeLive]);\n const consumedRef = useRef(0);\n const feedKeyRef = useRef<string | null>(null);\n const sharedFeedHasEventsRef = useRef(false);\n\n // Shared-log mode: scan only the unseen tail on every append.\n useEffect(() => {\n if (!sharedFeed || !liveEnabled || !sessionId) {\n return;\n }\n const feedKey = `${workspaceId}\\u0000${sessionId}`;\n const firstSequence = events[0]?.sequence ?? 0;\n if (feedKeyRef.current !== feedKey) {\n feedKeyRef.current = feedKey;\n sharedFeedHasEventsRef.current = events.length > 0;\n // The caller has already loaded its authoritative initial projection.\n // Seed from the shared log's current tail so mounting a large historical\n // session cannot replay every old event as a new live trigger.\n consumedRef.current = events.at(-1)?.sequence ?? 0;\n return;\n }\n const firstNonEmptyBatch = !sharedFeedHasEventsRef.current && events.length > 0;\n if (firstNonEmptyBatch || firstSequence > consumedRef.current + 1) {\n // The usual shared feed mounts empty, then receives a historical tail.\n // A later discontinuity can likewise replace the retained browser\n // window. In either case, reconcile once from the latest relevant event\n // instead of replaying the whole retained window as live traffic.\n sharedFeedHasEventsRef.current = events.length > 0;\n consumedRef.current = events.at(-1)?.sequence ?? consumedRef.current;\n let latestMatch: SessionEvent | undefined;\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event && matchRef.current(event)) {\n latestMatch = event;\n break;\n }\n }\n if (latestMatch) {\n onEventRef.current(latestMatch);\n }\n return;\n }\n sharedFeedHasEventsRef.current ||= events.length > 0;\n for (const event of events) {\n if (event.sequence <= consumedRef.current) {\n continue;\n }\n consumedRef.current = event.sequence;\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n }, [sharedFeed, liveEnabled, events, workspaceId, sessionId]);\n\n // Self-stream mode: tail from the session's current lastSequence.\n useEffect(() => {\n if (sharedFeed || !liveEnabled || !sessionId) {\n return;\n }\n const controller = new AbortController();\n void (async () => {\n try {\n const session = await client.getSession(workspaceId, sessionId);\n if (controller.signal.aborted) {\n return;\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: session.lastSequence,\n signal: controller.signal,\n onOpen: () => {\n // Start reconciliation without delaying consumption of live SSE.\n void Promise.resolve()\n .then(() => reconcileBeforeLiveRef.current?.())\n .catch(() => undefined);\n },\n });\n for await (const event of stream) {\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n } catch {\n // Live updates are best-effort: the read hooks still expose refresh()\n // and the initial load already populated state.\n }\n })();\n return () => {\n controller.abort();\n };\n }, [sharedFeed, liveEnabled, client, workspaceId, sessionId]);\n}\n\n/** Debounce rapid event bursts into one trailing call (default 150ms). */\nexport function useDebouncedCallback(callback: () => void, delayMs = 150): () => void {\n const callbackRef = useRef(callback);\n useLayoutEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n return useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n callbackRef.current();\n }, delayMs);\n }, [delayMs]);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/** Original diagnostic error and the library's neutral, state-aware display copy. */
|
|
2
|
-
export type ErrorMessageFormatter = (error: unknown, defaultMessage: string) => string | undefined;
|
|
3
|
-
export declare const ErrorMessageContext: import("react").Context<ErrorMessageFormatter | undefined>;
|
|
4
|
-
/** Keep existing Error-typed state while retaining non-Error rejections privately. */
|
|
5
|
-
export declare function normalizeError(cause: unknown): Error;
|
|
6
|
-
/** Presentation only: callers retain their errors and delivery/retry state. */
|
|
7
|
-
export declare function useErrorMessage(): (error: unknown, defaultMessage?: string) => string;
|
package/src/lib/error-message.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { formatErrorMessage } from "@opengeni/sdk";
|
|
2
|
-
import { createContext, useCallback, useContext, useRef } from "react";
|
|
3
|
-
|
|
4
|
-
/** Original diagnostic error and the library's neutral, state-aware display copy. */
|
|
5
|
-
export type ErrorMessageFormatter = (error: unknown, defaultMessage: string) => string | undefined;
|
|
6
|
-
|
|
7
|
-
export const ErrorMessageContext = createContext<ErrorMessageFormatter | undefined>(undefined);
|
|
8
|
-
|
|
9
|
-
const originalCauses = new WeakMap<Error, unknown>();
|
|
10
|
-
|
|
11
|
-
/** Keep existing Error-typed state while retaining non-Error rejections privately. */
|
|
12
|
-
export function normalizeError(cause: unknown): Error {
|
|
13
|
-
if (cause instanceof Error) return cause;
|
|
14
|
-
const error = new Error(String(cause));
|
|
15
|
-
originalCauses.set(error, cause);
|
|
16
|
-
return error;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Presentation only: callers retain their errors and delivery/retry state. */
|
|
20
|
-
export function useErrorMessage(): (error: unknown, defaultMessage?: string) => string {
|
|
21
|
-
const formatter = useContext(ErrorMessageContext);
|
|
22
|
-
const formatterRef = useRef(formatter);
|
|
23
|
-
formatterRef.current = formatter;
|
|
24
|
-
return useCallback((error, fallback) => {
|
|
25
|
-
const original =
|
|
26
|
-
error instanceof Error && originalCauses.has(error) ? originalCauses.get(error) : error;
|
|
27
|
-
const defaultMessage = fallback ?? formatErrorMessage(original);
|
|
28
|
-
try {
|
|
29
|
-
const message = formatterRef.current?.(original, defaultMessage);
|
|
30
|
-
return typeof message === "string" && message ? message : defaultMessage;
|
|
31
|
-
} catch {
|
|
32
|
-
// Host presentation must never interrupt delivery-state settlement or
|
|
33
|
-
// cause an already-started mutation to be retried.
|
|
34
|
-
return defaultMessage;
|
|
35
|
-
}
|
|
36
|
-
}, []);
|
|
37
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/{model-policy-picker-menu-JSA64TNN.js.map → model-policy-picker-menu-PUTA5JOB.js.map}
RENAMED
|
File without changes
|
|
File without changes
|