@opengeni/react 0.57.0 → 1.0.2-canary.37191796234001
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 +654 -22
- package/dist/accounts.d.ts +64 -0
- package/dist/accounts.js +822 -0
- package/dist/accounts.js.map +1 -0
- package/dist/approvals.d.ts +2 -1
- package/dist/artifacts-document.js +3 -2
- package/dist/artifacts-presentation.js +3 -2
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.d.ts +4 -1
- package/dist/artifacts.js +518 -42
- package/dist/artifacts.js.map +1 -1
- package/dist/browser-viewer-GTR5XQ7X.js +16 -0
- package/dist/capability-catalog-row.d.ts +20 -0
- package/dist/capability-logo-fallback.d.ts +3 -0
- package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
- package/dist/chat-interactive-block-UGBTNB3L.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-23J2ZNXT.js} +4117 -3896
- package/dist/chunk-23J2ZNXT.js.map +1 -0
- package/dist/chunk-447JLCBU.js +209 -0
- package/dist/chunk-447JLCBU.js.map +1 -0
- package/dist/chunk-4RVYOY4O.js +379 -0
- package/dist/chunk-4RVYOY4O.js.map +1 -0
- package/dist/chunk-5CVXZA3Y.js +292 -0
- package/dist/chunk-5CVXZA3Y.js.map +1 -0
- package/dist/chunk-5J4FOW6Q.js +108 -0
- package/dist/chunk-5J4FOW6Q.js.map +1 -0
- package/dist/chunk-A2PI6UMY.js +41 -0
- package/dist/chunk-A2PI6UMY.js.map +1 -0
- package/dist/{chunk-7WCLAEFV.js → chunk-A4UJB2MM.js} +37 -27
- package/dist/chunk-A4UJB2MM.js.map +1 -0
- package/dist/chunk-B3V6TG77.js +41 -0
- package/dist/chunk-B3V6TG77.js.map +1 -0
- package/dist/chunk-BRM6FVZA.js +302 -0
- package/dist/chunk-BRM6FVZA.js.map +1 -0
- package/dist/chunk-C5X5AJXK.js +182 -0
- package/dist/chunk-C5X5AJXK.js.map +1 -0
- package/dist/chunk-CR7U7HAR.js +453 -0
- package/dist/chunk-CR7U7HAR.js.map +1 -0
- package/dist/{chunk-R3AZOAB5.js → chunk-DYWBUX5Q.js} +29 -123
- package/dist/chunk-DYWBUX5Q.js.map +1 -0
- package/dist/chunk-E3G7SAYZ.js +3124 -0
- package/dist/chunk-E3G7SAYZ.js.map +1 -0
- package/dist/chunk-ELCE5SXV.js +359 -0
- package/dist/chunk-ELCE5SXV.js.map +1 -0
- package/dist/chunk-ERGYJIBB.js +21 -0
- package/dist/chunk-ERGYJIBB.js.map +1 -0
- package/dist/chunk-FFA2OVOV.js +319 -0
- package/dist/chunk-FFA2OVOV.js.map +1 -0
- package/dist/chunk-FZCP527Y.js +116 -0
- package/dist/chunk-FZCP527Y.js.map +1 -0
- package/dist/chunk-GIMRELBW.js +14 -0
- package/dist/chunk-GIMRELBW.js.map +1 -0
- package/dist/{chunk-6KLX2RH5.js → chunk-H2NJQORO.js} +1069 -79
- package/dist/chunk-H2NJQORO.js.map +1 -0
- package/dist/chunk-I7IWRQLN.js +1608 -0
- package/dist/chunk-I7IWRQLN.js.map +1 -0
- package/dist/{chunk-HA46CYQK.js → chunk-IQUCRAT7.js} +792 -537
- package/dist/chunk-IQUCRAT7.js.map +1 -0
- package/dist/chunk-IWIDV7SB.js +1 -0
- package/dist/chunk-IWIDV7SB.js.map +1 -0
- package/dist/chunk-J2QWVSQY.js +312 -0
- package/dist/chunk-J2QWVSQY.js.map +1 -0
- package/dist/chunk-JFNEV4LU.js +2733 -0
- package/dist/chunk-JFNEV4LU.js.map +1 -0
- package/dist/chunk-JT4JW7BC.js +54 -0
- package/dist/chunk-JT4JW7BC.js.map +1 -0
- package/dist/chunk-K3HQAKQX.js +24 -0
- package/dist/chunk-K3HQAKQX.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
- package/dist/chunk-NZUI76EM.js +371 -0
- package/dist/chunk-NZUI76EM.js.map +1 -0
- package/dist/{chunk-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
- package/dist/chunk-PNY3JKBJ.js.map +1 -0
- package/dist/{chunk-IGC6A2ZI.js → chunk-Q5QBEZIQ.js} +777 -246
- package/dist/chunk-Q5QBEZIQ.js.map +1 -0
- package/dist/chunk-RHREZ7BO.js +11 -0
- package/dist/chunk-RHREZ7BO.js.map +1 -0
- package/dist/chunk-SCOTPE2I.js +589 -0
- package/dist/chunk-SCOTPE2I.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-SJZDKVW2.js} +1331 -1163
- package/dist/chunk-SJZDKVW2.js.map +1 -0
- package/dist/chunk-TMJRG4YC.js +12803 -0
- package/dist/chunk-TMJRG4YC.js.map +1 -0
- package/dist/chunk-TMYGL6X5.js +742 -0
- package/dist/chunk-TMYGL6X5.js.map +1 -0
- package/dist/chunk-UGLEYEMP.js +33 -0
- package/dist/chunk-UGLEYEMP.js.map +1 -0
- package/dist/chunk-UK4TINKT.js +27 -0
- package/dist/chunk-UK4TINKT.js.map +1 -0
- package/dist/chunk-UTRTG6LH.js +220 -0
- package/dist/chunk-UTRTG6LH.js.map +1 -0
- package/dist/chunk-WEHMPOXK.js +39 -0
- package/dist/chunk-WEHMPOXK.js.map +1 -0
- package/dist/chunk-WRHIZYZF.js +988 -0
- package/dist/chunk-WRHIZYZF.js.map +1 -0
- package/dist/{chunk-HUIKIDM5.js → chunk-WUISZ3WU.js} +223 -115
- package/dist/chunk-WUISZ3WU.js.map +1 -0
- package/dist/chunk-XCHWDJ22.js +107 -0
- package/dist/chunk-XCHWDJ22.js.map +1 -0
- package/dist/chunk-XOAMRDDK.js +481 -0
- package/dist/chunk-XOAMRDDK.js.map +1 -0
- package/dist/chunk-XUW2UWQM.js +299 -0
- package/dist/chunk-XUW2UWQM.js.map +1 -0
- package/dist/{chunk-KCGXPP5V.js → chunk-Y2PRMYLC.js} +11 -6
- package/dist/chunk-Y2PRMYLC.js.map +1 -0
- package/dist/chunk-YBXQDQFX.js +1772 -0
- package/dist/chunk-YBXQDQFX.js.map +1 -0
- package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
- package/dist/chunk-YQEAA6LT.js.map +1 -0
- package/dist/chunk-YV4L3ILF.js +9 -0
- package/dist/chunk-YV4L3ILF.js.map +1 -0
- package/dist/{chunk-LLOLUHVG.js → chunk-YWFG7ZX7.js} +1358 -2746
- package/dist/chunk-YWFG7ZX7.js.map +1 -0
- package/dist/chunk-ZYRGEKWS.js +216 -0
- package/dist/chunk-ZYRGEKWS.js.map +1 -0
- package/dist/client.d.ts +7 -4
- package/dist/clipboard.js +1 -0
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/anthropic-mark.d.ts +3 -0
- package/dist/components/approval-surface.d.ts +15 -0
- package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
- package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
- package/dist/components/artifacts/artifact-surface.d.ts +3 -1
- package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
- package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
- package/dist/components/artifacts/document-editor.d.ts +4 -2
- package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
- package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
- package/dist/components/artifacts/editable-document.d.ts +1 -1
- package/dist/components/artifacts/editable-presentation.d.ts +2 -2
- package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
- package/dist/components/artifacts/index.d.ts +8 -1
- package/dist/components/artifacts/inline-html-document.d.ts +2 -0
- package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
- package/dist/components/artifacts/presentation-editor.d.ts +6 -2
- package/dist/components/artifacts/published-html-artifact-frame.d.ts +48 -3
- package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
- package/dist/components/artifacts/site-view.d.ts +23 -0
- package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
- package/dist/components/artifacts/visualization-assets.gen.d.ts +2 -0
- package/dist/components/browser-select-control.d.ts +16 -0
- package/dist/components/browser-viewer.d.ts +10 -1
- package/dist/components/chat-composer.d.ts +21 -3
- package/dist/components/child-session-link.d.ts +5 -0
- package/dist/components/claude-mark.d.ts +3 -0
- package/dist/components/code-editor.d.ts +1 -4
- package/dist/components/composer.d.ts +45 -4
- package/dist/components/computer-viewer.d.ts +4 -1
- package/dist/components/copy-button.d.ts +3 -1
- package/dist/components/desktop-viewer.d.ts +1 -1
- package/dist/components/enrollment-consent.d.ts +6 -3
- package/dist/components/file-browser.d.ts +10 -1
- package/dist/components/fleet-tile.d.ts +2 -2
- package/dist/components/grok-mark.d.ts +26 -0
- package/dist/components/human-input-form.d.ts +21 -2
- package/dist/components/human-input-surface.d.ts +6 -3
- package/dist/components/machine-card.d.ts +4 -1
- package/dist/components/machines/machine-detail.d.ts +4 -1
- package/dist/components/machines/machine-operation-policy.d.ts +11 -0
- package/dist/components/machines-dashboard.d.ts +3 -1
- package/dist/components/markdown-table-layout.d.ts +12 -0
- package/dist/components/markdown.d.ts +47 -3
- package/dist/components/message-timeline.d.ts +72 -9
- package/dist/components/model-mark.d.ts +29 -0
- package/dist/components/model-policy-picker-menu.d.ts +9 -0
- package/dist/components/model-policy-picker.d.ts +62 -13
- package/dist/components/open-geni-chat.d.ts +55 -0
- package/dist/components/open-geni-links.d.ts +68 -0
- package/dist/components/openrouter-mark.d.ts +6 -0
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/preview-loading.d.ts +2 -0
- package/dist/components/queue-item-content.d.ts +9 -0
- package/dist/components/sandbox-files.d.ts +13 -2
- package/dist/components/sandbox-workspace.d.ts +43 -3
- package/dist/components/session-capability-frame.d.ts +35 -0
- package/dist/components/session-chrome.d.ts +66 -8
- package/dist/components/session-commands-panel.d.ts +6 -0
- package/dist/components/session-commands.d.ts +6 -0
- package/dist/components/session-connection-request.d.ts +8 -0
- package/dist/components/session-conversation.d.ts +86 -0
- package/dist/components/session-list.d.ts +36 -0
- package/dist/components/session-mcp-capability-card.d.ts +41 -0
- package/dist/components/timeline-anchor.d.ts +24 -0
- package/dist/components/timeline-annotation-chrome.d.ts +25 -0
- package/dist/components/timeline-annotation-layout.d.ts +42 -0
- package/dist/components/timeline-annotation-markers.d.ts +8 -0
- package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
- package/dist/components/timeline-annotation-shared.d.ts +31 -0
- package/dist/components/timeline-annotations-dialog.d.ts +3 -2
- package/dist/components/timeline-annotations.d.ts +13 -3
- package/dist/components/timeline-reading-progress.d.ts +11 -0
- package/dist/components/timeline-search.d.ts +34 -0
- package/dist/components/timeline-settlement.d.ts +16 -0
- package/dist/components/tip-follow.d.ts +16 -0
- package/dist/components/usage-limit-notice.d.ts +49 -0
- package/dist/components/usage-member-list.d.ts +91 -0
- package/dist/components/usage-meter.d.ts +73 -0
- package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
- package/dist/components/user-message-body.d.ts +10 -1
- package/dist/components/workspace-dock.d.ts +6 -2
- package/dist/composer.d.ts +5 -4
- package/dist/composer.js +15 -9
- package/dist/computer-viewer-ENHVAZ2Q.js +19 -0
- package/dist/computer-viewer-ENHVAZ2Q.js.map +1 -0
- package/dist/connect-account-identity.d.ts +8 -0
- package/dist/connect-accounts.d.ts +15 -0
- package/dist/connect-chooser.d.ts +18 -0
- package/dist/connect-panel.d.ts +18 -0
- package/dist/connect-setup.d.ts +16 -0
- package/dist/connect.d.ts +21 -0
- package/dist/connect.js +2129 -0
- package/dist/connect.js.map +1 -0
- package/dist/connection-catalog.d.ts +38 -0
- package/dist/connection-discovery.d.ts +12 -0
- package/dist/connection-installed.d.ts +17 -0
- package/dist/connection-logo.d.ts +9 -0
- package/dist/connection-service-logo.d.ts +8 -0
- package/dist/connection-service-presentation.d.ts +13 -0
- package/dist/connection-skeleton.d.ts +5 -0
- package/dist/connection-type-picker.d.ts +6 -0
- package/dist/conversation-timeline.d.ts +5 -0
- package/dist/desktop.d.ts +7 -0
- package/dist/desktop.js +26 -0
- package/dist/desktop.js.map +1 -0
- package/dist/device-authorization.d.ts +23 -0
- package/dist/diffs.d.ts +8 -0
- package/dist/diffs.js +14 -0
- package/dist/diffs.js.map +1 -0
- package/dist/discovery-cache.d.ts +5 -0
- package/dist/editor.d.ts +7 -0
- package/dist/editor.js +21 -0
- package/dist/editor.js.map +1 -0
- package/dist/embedded-session-client.d.ts +23 -0
- package/dist/file-node-visibility.d.ts +15 -0
- package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
- package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
- package/dist/hooks/channel-cache.d.ts +23 -0
- package/dist/hooks/latest-question.d.ts +25 -0
- package/dist/hooks/shared-machines-list.d.ts +14 -0
- package/dist/hooks/use-attached-browsers.d.ts +2 -1
- package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
- package/dist/hooks/use-browser-session.d.ts +12 -1
- package/dist/hooks/use-channels.d.ts +1 -0
- package/dist/hooks/use-codex-accounts.d.ts +25 -7
- package/dist/hooks/use-composer.d.ts +45 -9
- package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
- package/dist/hooks/use-computer-input-posture.d.ts +13 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-connect.d.ts +22 -0
- package/dist/hooks/use-desktop-stream.d.ts +1 -1
- package/dist/hooks/use-file-attachments.d.ts +21 -2
- package/dist/hooks/use-machine-chip.d.ts +3 -3
- package/dist/hooks/use-machines.d.ts +19 -1
- package/dist/hooks/use-sandbox-files.d.ts +5 -1
- package/dist/hooks/use-session-background-commands.d.ts +14 -0
- package/dist/hooks/use-session-events.d.ts +30 -8
- package/dist/hooks/use-session-lineage.d.ts +4 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-session.d.ts +6 -0
- package/dist/hooks/use-turn-queue.d.ts +12 -0
- package/dist/hooks/use-usage.d.ts +40 -0
- package/dist/hooks/use-workspace-edit.d.ts +4 -0
- package/dist/hooks/use-workspace-sessions.d.ts +27 -5
- package/dist/human-input.d.ts +3 -1
- package/dist/identity-link-accounts.d.ts +11 -0
- package/dist/identity-link-consent.d.ts +18 -0
- package/dist/index.d.ts +60 -17
- package/dist/index.js +2237 -6200
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.js +35 -184
- package/dist/interaction.js.map +1 -1
- package/dist/latest-question-755OW5DS.js +117 -0
- package/dist/latest-question-755OW5DS.js.map +1 -0
- package/dist/lib/error-message.d.ts +7 -0
- package/dist/lib/format.d.ts +36 -2
- package/dist/lib/host-theme.d.ts +70 -0
- package/dist/lib/interaction-errors.d.ts +6 -0
- package/dist/lib/menu-styles.d.ts +22 -0
- package/dist/lib/pierre-diffs-loader.d.ts +20 -0
- package/dist/lib/workbench-peers.d.ts +36 -0
- package/dist/lib/xterm-theme.d.ts +7 -5
- package/dist/machines.d.ts +4 -2
- package/dist/machines.js +14 -4
- package/dist/markdown-table-layout-QXSLK4BY.js +106 -0
- package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
- package/dist/mcp-connection-status.d.ts +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js.map +1 -0
- package/dist/model-policy.d.ts +19 -3
- package/dist/model-policy.js +9 -1
- package/dist/older-history.d.ts +30 -0
- package/dist/platform-activity-row-627BFZ46.js +182 -0
- package/dist/platform-activity-row-627BFZ46.js.map +1 -0
- package/dist/plugin-details.d.ts +14 -0
- package/dist/plugin-discovery.d.ts +25 -0
- package/dist/provider.d.ts +13 -1
- package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-ZHFI5JBP.js} +131 -44
- package/dist/queue-surface-implementation-ZHFI5JBP.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +10 -3
- package/dist/realtime.js +229 -83
- package/dist/realtime.js.map +1 -1
- package/dist/sandbox-files-BBC47SLD.js +20 -0
- package/dist/sandbox-files-BBC47SLD.js.map +1 -0
- package/dist/session-auth-recommendation.d.ts +5 -0
- package/dist/session-capability-policy.d.ts +12 -0
- package/dist/session-ui.d.ts +30 -2
- package/dist/session-ui.js +85 -7
- package/dist/session-ui.js.map +1 -1
- package/dist/session.d.ts +8 -2
- package/dist/session.js +30 -19
- package/dist/sites-ui.d.ts +34 -0
- package/dist/sites.d.ts +3 -0
- package/dist/sites.js +11 -0
- package/dist/sites.js.map +1 -0
- package/dist/skill-discovery.d.ts +47 -0
- package/dist/terminal.d.ts +8 -0
- package/dist/terminal.js +31 -0
- package/dist/terminal.js.map +1 -0
- package/dist/timeline/activity-rail.d.ts +11 -2
- package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
- package/dist/timeline/compaction-copy.d.ts +10 -0
- package/dist/timeline/entrance.d.ts +13 -1
- package/dist/timeline/genie-loading.d.ts +34 -0
- package/dist/timeline/index.d.ts +6 -2
- package/dist/timeline/knowledge-receipt.d.ts +17 -0
- package/dist/timeline/platform-activity-row.d.ts +14 -0
- package/dist/timeline/presented-image.d.ts +6 -0
- package/dist/timeline/projection.d.ts +31 -2
- package/dist/timeline/registry.d.ts +2 -0
- package/dist/timeline/retained-image.d.ts +18 -0
- package/dist/timeline/rolling-activity.d.ts +11 -0
- package/dist/timeline/screenshot-lightbox.d.ts +16 -1
- package/dist/timeline/shared.d.ts +8 -3
- package/dist/timeline/startup-preference.d.ts +3 -0
- package/dist/timeline/startup-timings.d.ts +4 -0
- package/dist/timeline/tool-display-name.d.ts +2 -1
- package/dist/timeline/turn-summary.d.ts +32 -3
- package/dist/timeline/types.d.ts +141 -7
- package/dist/timeline-annotation-markers-GNDHTGBD.js +165 -0
- package/dist/timeline-annotation-markers-GNDHTGBD.js.map +1 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js +241 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js +273 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js.map +1 -0
- package/dist/types/machines.d.ts +2 -2
- package/dist/usage/allowance-copy.d.ts +25 -0
- package/dist/usage/summary.d.ts +35 -0
- package/dist/usage.d.ts +13 -0
- package/dist/usage.js +1074 -0
- package/dist/usage.js.map +1 -0
- package/package.json +44 -4
- package/src/accounts.tsx +1072 -0
- package/src/approvals.ts +8 -1
- package/src/artifacts.ts +42 -0
- package/src/assets/README.md +8 -0
- package/src/assets/gmail.ico +0 -0
- package/src/assets/outlook.ico +0 -0
- package/src/capability-catalog-row.tsx +94 -0
- package/src/capability-logo-fallback.ts +22 -0
- package/src/client.ts +22 -13
- package/src/commands/registry.ts +18 -15
- package/src/commands/types.ts +2 -0
- package/src/components/anthropic-mark.tsx +10 -0
- package/src/components/approval-surface.tsx +171 -37
- package/src/components/artifacts/artifact-chrome.tsx +413 -0
- package/src/components/artifacts/artifact-sandbox.tsx +185 -0
- package/src/components/artifacts/artifact-surface.tsx +39 -19
- package/src/components/artifacts/chat-interactive-block.tsx +260 -0
- package/src/components/artifacts/deferred-chat-media.tsx +67 -0
- package/src/components/artifacts/document-editor.tsx +141 -16
- package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
- package/src/components/artifacts/editable-artifact-view.tsx +187 -0
- package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
- package/src/components/artifacts/editable-document.tsx +37 -36
- package/src/components/artifacts/editable-presentation.tsx +36 -18
- package/src/components/artifacts/editable-spreadsheet.tsx +5 -2
- package/src/components/artifacts/index.ts +44 -0
- package/src/components/artifacts/inline-html-document.ts +24 -0
- package/src/components/artifacts/latest-task-runner.ts +49 -0
- package/src/components/artifacts/presentation-editor.tsx +323 -67
- package/src/components/artifacts/published-html-artifact-frame.tsx +338 -5
- package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
- package/src/components/artifacts/site-view.tsx +116 -0
- package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
- package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +12 -13
- package/src/components/artifacts/visualization-assets/base.css +1015 -0
- package/src/components/artifacts/visualization-assets/helpers.html +349 -0
- package/src/components/artifacts/visualization-assets.gen.ts +3 -0
- package/src/components/browser-select-control.tsx +312 -0
- package/src/components/browser-viewer.tsx +1054 -314
- package/src/components/chat-composer.tsx +131 -85
- package/src/components/child-session-link.tsx +27 -0
- package/src/components/claude-mark.tsx +10 -0
- package/src/components/code-editor.tsx +13 -16
- package/src/components/composer-transcription-control.tsx +7 -5
- package/src/components/composer.tsx +376 -49
- package/src/components/computer-viewer.tsx +1041 -329
- package/src/components/copy-button.tsx +13 -5
- package/src/components/desktop-viewer.tsx +1 -1
- package/src/components/enrollment-consent.tsx +65 -7
- package/src/components/enrollment-device-flow.tsx +1 -1
- package/src/components/file-browser.tsx +158 -34
- package/src/components/fleet-tile.tsx +8 -16
- package/src/components/generated-video-player.tsx +4 -2
- package/src/components/grok-mark.tsx +33 -0
- package/src/components/human-input-form.tsx +455 -114
- package/src/components/human-input-surface.tsx +18 -7
- package/src/components/interaction-intervention-banner.tsx +2 -2
- package/src/components/machine-card.tsx +119 -4
- package/src/components/machine-dock-bar.tsx +1 -1
- package/src/components/machine-input-display.ts +23 -2
- package/src/components/machines/machine-detail.tsx +52 -2
- package/src/components/machines/machine-operation-policy.tsx +179 -0
- package/src/components/machines-dashboard.tsx +8 -17
- package/src/components/markdown-table-layout.ts +132 -0
- package/src/components/markdown.tsx +473 -44
- package/src/components/message-timeline.tsx +2498 -663
- package/src/components/model-mark.tsx +90 -0
- package/src/components/model-picker.tsx +15 -4
- package/src/components/model-policy-picker-menu.tsx +424 -0
- package/src/components/model-policy-picker.tsx +337 -381
- package/src/components/open-geni-chat.tsx +319 -0
- package/src/components/open-geni-links.tsx +179 -0
- package/src/components/openrouter-mark.tsx +13 -0
- package/src/components/pierre-diff.tsx +41 -16
- package/src/components/pierre-file.tsx +36 -11
- package/src/components/preview-loading.tsx +154 -0
- package/src/components/queue-item-content.ts +14 -0
- package/src/components/queue-surface-implementation.tsx +132 -42
- package/src/components/queue-surface-state.tsx +3 -1
- package/src/components/sandbox-files.tsx +267 -35
- package/src/components/sandbox-terminal.tsx +48 -11
- package/src/components/sandbox-workspace.tsx +337 -135
- package/src/components/session-capability-frame.tsx +192 -0
- package/src/components/session-chrome.tsx +1027 -328
- package/src/components/session-commands-panel.tsx +126 -0
- package/src/components/session-commands.tsx +18 -0
- package/src/components/session-connection-request.tsx +97 -0
- package/src/components/session-conversation.tsx +512 -0
- package/src/components/session-list.tsx +250 -0
- package/src/components/session-mcp-capability-card.tsx +680 -0
- package/src/components/session-status.tsx +1 -1
- package/src/components/timeline-anchor.tsx +119 -0
- package/src/components/timeline-annotation-chrome.tsx +196 -0
- package/src/components/timeline-annotation-layout.ts +268 -0
- package/src/components/timeline-annotation-markers.tsx +185 -0
- package/src/components/timeline-annotation-reveal-context.ts +9 -0
- package/src/components/timeline-annotation-selection.tsx +106 -54
- package/src/components/timeline-annotation-shared.ts +245 -0
- package/src/components/timeline-annotations-dialog.tsx +185 -128
- package/src/components/timeline-annotations.tsx +189 -45
- package/src/components/timeline-reading-progress.ts +80 -0
- package/src/components/timeline-search.tsx +168 -0
- package/src/components/timeline-settlement.ts +60 -0
- package/src/components/tip-follow.ts +70 -7
- package/src/components/tooltip.tsx +38 -5
- package/src/components/usage-limit-notice.tsx +179 -0
- package/src/components/usage-member-list.tsx +792 -0
- package/src/components/usage-meter.tsx +382 -0
- package/src/components/use-viewer-menu-dismiss.ts +33 -0
- package/src/components/user-message-body.tsx +194 -49
- package/src/components/workspace-dock.tsx +141 -175
- package/src/composer.ts +6 -1
- package/src/connect-account-identity.tsx +34 -0
- package/src/connect-accounts.tsx +233 -0
- package/src/connect-chooser.tsx +336 -0
- package/src/connect-panel.tsx +99 -0
- package/src/connect-setup.tsx +307 -0
- package/src/connect.ts +60 -0
- package/src/connection-assets.d.ts +4 -0
- package/src/connection-catalog.tsx +162 -0
- package/src/connection-discovery.tsx +235 -0
- package/src/connection-installed.tsx +51 -0
- package/src/connection-logo.tsx +37 -0
- package/src/connection-service-logo.tsx +55 -0
- package/src/connection-service-presentation.ts +46 -0
- package/src/connection-skeleton.tsx +16 -0
- package/src/connection-type-picker.tsx +36 -0
- package/src/conversation-timeline.ts +92 -0
- package/src/desktop.ts +24 -0
- package/src/device-authorization.tsx +98 -0
- package/src/diffs.ts +16 -0
- package/src/discovery-cache.ts +42 -0
- package/src/editor.ts +13 -0
- package/src/embedded-session-client.ts +104 -0
- package/src/file-node-visibility.ts +66 -0
- package/src/hooks/channel-cache.ts +104 -0
- package/src/hooks/internal.ts +3 -2
- package/src/hooks/latest-question.ts +164 -0
- package/src/hooks/shared-machines-list.ts +239 -0
- package/src/hooks/use-attached-browsers.ts +5 -1
- package/src/hooks/use-available-models.ts +20 -14
- package/src/hooks/use-browser-frame-stream.ts +25 -3
- package/src/hooks/use-browser-session.ts +271 -71
- package/src/hooks/use-browser-sessions.ts +7 -1
- package/src/hooks/use-channels.ts +32 -10
- package/src/hooks/use-codex-accounts.ts +78 -21
- package/src/hooks/use-composer.ts +1034 -320
- package/src/hooks/use-computer-frame-stream.ts +39 -16
- package/src/hooks/use-computer-input-posture.ts +94 -0
- package/src/hooks/use-computer-session.ts +110 -32
- package/src/hooks/use-computer-sessions.ts +8 -1
- package/src/hooks/use-connect.ts +23 -0
- package/src/hooks/use-desktop-stream.ts +19 -28
- package/src/hooks/use-file-attachments.ts +118 -10
- package/src/hooks/use-goal.ts +36 -9
- package/src/hooks/use-human-input.ts +31 -4
- package/src/hooks/use-last-started-turn-policy.ts +15 -13
- package/src/hooks/use-machine-chip.ts +23 -6
- package/src/hooks/use-machines.ts +104 -6
- package/src/hooks/use-sandbox-files.ts +253 -150
- package/src/hooks/use-sandbox-git.ts +58 -29
- package/src/hooks/use-session-background-commands.ts +67 -0
- package/src/hooks/use-session-capabilities.ts +21 -2
- package/src/hooks/use-session-events.ts +759 -433
- package/src/hooks/use-session-lineage.ts +28 -6
- package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
- package/src/hooks/use-session.ts +75 -16
- package/src/hooks/use-slash-commands.ts +6 -11
- package/src/hooks/use-turn-queue.ts +113 -13
- package/src/hooks/use-usage.ts +100 -0
- package/src/hooks/use-voice-input.ts +12 -1
- package/src/hooks/use-workspace-capture.ts +3 -2
- package/src/hooks/use-workspace-edit.ts +23 -5
- package/src/hooks/use-workspace-sessions.ts +99 -11
- package/src/human-input.ts +12 -1
- package/src/identity-link-accounts.tsx +148 -0
- package/src/identity-link-consent.tsx +192 -0
- package/src/index.ts +157 -12
- package/src/interaction.ts +1 -0
- package/src/lib/error-message.ts +37 -0
- package/src/lib/format.ts +150 -14
- package/src/lib/host-theme.ts +511 -0
- package/src/lib/interaction-errors.ts +33 -0
- package/src/lib/menu-styles.ts +44 -0
- package/src/lib/pierre-diffs-loader.ts +53 -0
- package/src/lib/workbench-peers.ts +62 -0
- package/src/lib/xterm-theme.ts +23 -21
- package/src/machines.ts +9 -1
- package/src/mcp-connection-status.ts +35 -0
- package/src/model-policy.ts +223 -69
- package/src/older-history.ts +87 -0
- package/src/plugin-details.tsx +185 -0
- package/src/plugin-discovery.tsx +196 -0
- package/src/provider.tsx +55 -14
- package/src/realtime/dropdown-menu.tsx +19 -12
- package/src/realtime/realtime-control.tsx +274 -60
- package/src/session-auth-recommendation.ts +48 -0
- package/src/session-capability-policy.ts +83 -0
- package/src/session-context.ts +1 -0
- package/src/session-ui.ts +66 -2
- package/src/session.ts +18 -1
- package/src/sites-ui.tsx +402 -0
- package/src/sites.ts +3 -0
- package/src/skill-discovery.tsx +208 -0
- package/src/terminal.ts +26 -0
- package/src/timeline/activity-rail.tsx +171 -80
- package/src/timeline/allowance-exhausted-row.tsx +86 -0
- package/src/timeline/compaction-copy.ts +42 -0
- package/src/timeline/entrance.tsx +28 -3
- package/src/timeline/fleet-decision-projection.ts +2 -1
- package/src/timeline/fleet-decision-row.tsx +1 -0
- package/src/timeline/genie-loading.tsx +136 -0
- package/src/timeline/index.ts +11 -0
- package/src/timeline/knowledge-receipt.tsx +100 -0
- package/src/timeline/parsers.ts +2 -2
- package/src/timeline/platform-activity-row.tsx +216 -0
- package/src/timeline/presented-image.ts +49 -0
- package/src/timeline/projection.ts +1600 -84
- package/src/timeline/registry.ts +15 -3
- package/src/timeline/retained-image.ts +97 -0
- package/src/timeline/rolling-activity.tsx +92 -0
- package/src/timeline/screenshot-lightbox.tsx +115 -17
- package/src/timeline/shared.tsx +47 -15
- package/src/timeline/startup-preference.ts +33 -0
- package/src/timeline/startup-timings.tsx +145 -0
- package/src/timeline/tool-display-name.ts +8 -6
- package/src/timeline/tool-renderers.tsx +497 -128
- package/src/timeline/turn-summary.tsx +208 -44
- package/src/timeline/types.ts +186 -7
- package/src/types/machines.ts +10 -0
- package/src/usage/allowance-copy.ts +64 -0
- package/src/usage/summary.ts +93 -0
- package/src/usage.ts +50 -0
- package/styles/compiled.css +2098 -757
- package/styles/connect.css +284 -0
- package/styles/connect.d.ts +1 -0
- package/styles/effective-tokens.css +1 -0
- package/styles/index.css +201 -9
- package/styles/responsive.css +27 -1
- package/styles/session-capability.css +44 -0
- package/styles/tokens.css +135 -65
- package/dist/chunk-5UQPNLIO.js.map +0 -1
- package/dist/chunk-6KLX2RH5.js.map +0 -1
- package/dist/chunk-7WCLAEFV.js.map +0 -1
- package/dist/chunk-B6WPZSTT.js.map +0 -1
- package/dist/chunk-FK6VG4LL.js +0 -90
- package/dist/chunk-FK6VG4LL.js.map +0 -1
- package/dist/chunk-HA46CYQK.js.map +0 -1
- package/dist/chunk-HUIKIDM5.js.map +0 -1
- package/dist/chunk-IGC6A2ZI.js.map +0 -1
- package/dist/chunk-KCGXPP5V.js.map +0 -1
- package/dist/chunk-KZ73RL76.js.map +0 -1
- package/dist/chunk-LAKLF4PA.js +0 -141
- package/dist/chunk-LAKLF4PA.js.map +0 -1
- package/dist/chunk-LLOLUHVG.js.map +0 -1
- package/dist/chunk-MKPIAGVL.js +0 -465
- package/dist/chunk-MKPIAGVL.js.map +0 -1
- package/dist/chunk-PEI6RANI.js.map +0 -1
- package/dist/chunk-R3AZOAB5.js.map +0 -1
- package/dist/chunk-WSK7G5LE.js +0 -170
- package/dist/chunk-WSK7G5LE.js.map +0 -1
- package/dist/chunk-XBZWOM2K.js +0 -218
- package/dist/chunk-XBZWOM2K.js.map +0 -1
- package/dist/chunk-Y7OEDUJ5.js +0 -8810
- package/dist/chunk-Y7OEDUJ5.js.map +0 -1
- package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
- package/dist/hooks/use-packs.d.ts +0 -32
- package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
- package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
- package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
- package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
- package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
- package/src/hooks/use-packs.ts +0 -157
- /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GTR5XQ7X.js.map} +0 -0
|
@@ -57,7 +57,12 @@ export type UseComputerFrameStreamResult = {
|
|
|
57
57
|
frame: ComputerFrame | null;
|
|
58
58
|
attachment: Pick<
|
|
59
59
|
ComputerSessionAttachment,
|
|
60
|
-
|
|
60
|
+
| "computerSessionId"
|
|
61
|
+
| "controllerGeneration"
|
|
62
|
+
| "targetId"
|
|
63
|
+
| "inputAllowed"
|
|
64
|
+
| "stream"
|
|
65
|
+
| "expiresAt"
|
|
61
66
|
> | null;
|
|
62
67
|
error: Error | null;
|
|
63
68
|
reconnect: () => void;
|
|
@@ -159,9 +164,19 @@ export function useComputerFrameStream(
|
|
|
159
164
|
pendingFrame = null;
|
|
160
165
|
};
|
|
161
166
|
|
|
167
|
+
const clearRecoveryTimers = () => {
|
|
168
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
169
|
+
if (expiryTimer) clearTimeout(expiryTimer);
|
|
170
|
+
reconnectTimer = null;
|
|
171
|
+
expiryTimer = null;
|
|
172
|
+
};
|
|
173
|
+
|
|
162
174
|
const scheduleReconnect = () => {
|
|
163
175
|
if (disposed || reconnectTimer) return;
|
|
164
|
-
if (failures >= MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME)
|
|
176
|
+
if (failures >= MAX_AUTOMATIC_RECONNECTS_WITHOUT_A_FRAME) {
|
|
177
|
+
clearRecoveryTimers();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
165
180
|
const delay = Math.min(5_000, 250 * 2 ** Math.min(failures, 5));
|
|
166
181
|
failures += 1;
|
|
167
182
|
setResult((current) => ({ ...current, state: "reconnecting" }));
|
|
@@ -177,6 +192,7 @@ export function useComputerFrameStream(
|
|
|
177
192
|
setResult((current) => ({ ...current, state: "error", error }));
|
|
178
193
|
clearSocket();
|
|
179
194
|
if (reconnectAutomatically) scheduleReconnect();
|
|
195
|
+
else clearRecoveryTimers();
|
|
180
196
|
};
|
|
181
197
|
|
|
182
198
|
const onOpen = (source: ComputerFrameWebSocket) => {
|
|
@@ -211,10 +227,10 @@ export function useComputerFrameStream(
|
|
|
211
227
|
const frame = await decodeComputerFrameMessage(bytes);
|
|
212
228
|
if (disposed || source !== socket) continue;
|
|
213
229
|
if (frame.computerSessionId !== computerSessionId || frame.targetId !== targetId) {
|
|
214
|
-
throw new Error("
|
|
230
|
+
throw new Error("desktop frame belongs to another resource");
|
|
215
231
|
}
|
|
216
232
|
if (!controllerGeneration || frame.controllerGeneration !== controllerGeneration) {
|
|
217
|
-
throw new Error("
|
|
233
|
+
throw new Error("desktop frame belongs to a stale controller");
|
|
218
234
|
}
|
|
219
235
|
const key = `${computerSessionId}:${targetId}:${frame.controllerGeneration}:${frame.targetGeneration}`;
|
|
220
236
|
if (latestRef.current.key === key && frame.sequence <= latestRef.current.sequence)
|
|
@@ -246,7 +262,7 @@ export function useComputerFrameStream(
|
|
|
246
262
|
if (disposed || source !== socket) return;
|
|
247
263
|
let frameBytes = bytes;
|
|
248
264
|
if (activeStream?.kind === "relay") {
|
|
249
|
-
if (bytes.length < 1) throw new Error("
|
|
265
|
+
if (bytes.length < 1) throw new Error("desktop relay returned an empty message");
|
|
250
266
|
const tag = bytes[0];
|
|
251
267
|
const body = bytes.subarray(1);
|
|
252
268
|
if (tag === RELAY_TAG_OPEN_ACK) {
|
|
@@ -255,7 +271,7 @@ export function useComputerFrameStream(
|
|
|
255
271
|
activeAttachment = null;
|
|
256
272
|
activeStream = null;
|
|
257
273
|
attachmentExpiresAt = 0;
|
|
258
|
-
throw new Error(ack.error?.message ?? "
|
|
274
|
+
throw new Error(ack.error?.message ?? "desktop stream was rejected by the relay");
|
|
259
275
|
}
|
|
260
276
|
relayAccepted = true;
|
|
261
277
|
return;
|
|
@@ -269,7 +285,7 @@ export function useComputerFrameStream(
|
|
|
269
285
|
attachmentExpiresAt = 0;
|
|
270
286
|
lastRelaySequence = null;
|
|
271
287
|
relayAccepted = false;
|
|
272
|
-
fail(new Error("
|
|
288
|
+
fail(new Error("Desktop frame source ended."), false);
|
|
273
289
|
return;
|
|
274
290
|
}
|
|
275
291
|
if (tag !== RELAY_TAG_FRAME || !relayAccepted) return;
|
|
@@ -290,13 +306,12 @@ export function useComputerFrameStream(
|
|
|
290
306
|
|
|
291
307
|
const onError = (source: ComputerFrameWebSocket) => {
|
|
292
308
|
if (source !== socket) return;
|
|
293
|
-
fail(new Error("
|
|
309
|
+
fail(new Error("Desktop view lost connection."));
|
|
294
310
|
};
|
|
295
311
|
|
|
296
312
|
const onClose = (source: ComputerFrameWebSocket) => {
|
|
297
313
|
if (disposed || source !== socket) return;
|
|
298
|
-
|
|
299
|
-
scheduleReconnect();
|
|
314
|
+
fail(new Error("Desktop view lost connection."));
|
|
300
315
|
};
|
|
301
316
|
|
|
302
317
|
const connectSocket = () => {
|
|
@@ -356,16 +371,19 @@ export function useComputerFrameStream(
|
|
|
356
371
|
expiresInSeconds: 120,
|
|
357
372
|
...(streamRef.current ? { stream: streamRef.current } : {}),
|
|
358
373
|
},
|
|
359
|
-
{ signal: attachmentAbort.signal },
|
|
374
|
+
{ signal: attachmentAbort.signal, timeoutMs: 15_000 },
|
|
360
375
|
);
|
|
361
376
|
if (disposed) return;
|
|
362
377
|
if (
|
|
363
378
|
attachment.computerSessionId !== computerSessionId ||
|
|
364
379
|
attachment.targetId !== targetId
|
|
365
380
|
) {
|
|
366
|
-
throw new Error("
|
|
381
|
+
throw new Error("desktop attachment does not match the requested resource");
|
|
367
382
|
}
|
|
368
383
|
controllerGeneration = attachment.controllerGeneration;
|
|
384
|
+
// A fresh attachment owns a new producer whose sequence can restart.
|
|
385
|
+
// Transport reconnects reuse the attachment and retain their sequence fence.
|
|
386
|
+
latestRef.current = { key: "", sequence: -1 };
|
|
369
387
|
activeAttachment = attachment;
|
|
370
388
|
activeStream = attachment.stream;
|
|
371
389
|
attachmentExpiresAt = Date.parse(attachment.expiresAt);
|
|
@@ -378,6 +396,7 @@ export function useComputerFrameStream(
|
|
|
378
396
|
computerSessionId: attachment.computerSessionId,
|
|
379
397
|
controllerGeneration: attachment.controllerGeneration,
|
|
380
398
|
targetId: attachment.targetId,
|
|
399
|
+
inputAllowed: attachment.inputAllowed,
|
|
381
400
|
stream: attachment.stream,
|
|
382
401
|
expiresAt: attachment.expiresAt,
|
|
383
402
|
},
|
|
@@ -397,7 +416,7 @@ export function useComputerFrameStream(
|
|
|
397
416
|
connectSocket();
|
|
398
417
|
} catch (cause) {
|
|
399
418
|
if (attachmentAbort.signal.aborted || disposed) return;
|
|
400
|
-
fail(cause);
|
|
419
|
+
fail(cause, !isPlacementGenerationLossError(cause));
|
|
401
420
|
}
|
|
402
421
|
};
|
|
403
422
|
|
|
@@ -406,8 +425,7 @@ export function useComputerFrameStream(
|
|
|
406
425
|
disposed = true;
|
|
407
426
|
pendingFrame = null;
|
|
408
427
|
attachmentAbort.abort();
|
|
409
|
-
|
|
410
|
-
if (expiryTimer) clearTimeout(expiryTimer);
|
|
428
|
+
clearRecoveryTimers();
|
|
411
429
|
clearSocket(true);
|
|
412
430
|
};
|
|
413
431
|
}, [client, enabled, nonce, options.computerSessionId, options.targetId, workspaceId]);
|
|
@@ -430,5 +448,10 @@ async function messageBytes(value: unknown): Promise<Uint8Array> {
|
|
|
430
448
|
if (typeof Blob !== "undefined" && value instanceof Blob) {
|
|
431
449
|
return new Uint8Array(await value.arrayBuffer());
|
|
432
450
|
}
|
|
433
|
-
throw new Error("
|
|
451
|
+
throw new Error("desktop frame stream returned a non-binary message");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function isPlacementGenerationLossError(cause: unknown): boolean {
|
|
455
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
456
|
+
return /placement instance changed|controller authority changed/i.test(message);
|
|
434
457
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
type EmbeddedComputerInteractionClientOverride,
|
|
4
|
+
useEmbeddedComputerInteraction,
|
|
5
|
+
} from "../session-context";
|
|
6
|
+
|
|
7
|
+
type PostureSource = {
|
|
8
|
+
client: ReturnType<typeof useEmbeddedComputerInteraction>["client"];
|
|
9
|
+
key: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type PostureState = {
|
|
13
|
+
source: PostureSource;
|
|
14
|
+
nonce: number;
|
|
15
|
+
inputAllowed: boolean | null;
|
|
16
|
+
pending: boolean;
|
|
17
|
+
error: Error | null;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Semantic-only targets need caller authority without opening a pixel stream.
|
|
21
|
+
* A source change synchronously discards the previous posture. */
|
|
22
|
+
export function useComputerInputPosture(
|
|
23
|
+
options: EmbeddedComputerInteractionClientOverride & {
|
|
24
|
+
computerSessionId: string | null;
|
|
25
|
+
controllerGeneration: string | null;
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
},
|
|
28
|
+
) {
|
|
29
|
+
const { client, workspaceId } = useEmbeddedComputerInteraction(options);
|
|
30
|
+
const { computerSessionId, controllerGeneration, enabled } = options;
|
|
31
|
+
const [nonce, setNonce] = useState(0);
|
|
32
|
+
const [state, setState] = useState<PostureState | null>(null);
|
|
33
|
+
const key = JSON.stringify([workspaceId, computerSessionId, controllerGeneration, enabled]);
|
|
34
|
+
const sourceRef = useRef<PostureSource>({ client, key });
|
|
35
|
+
if (sourceRef.current.client !== client || sourceRef.current.key !== key) {
|
|
36
|
+
sourceRef.current = { client, key };
|
|
37
|
+
}
|
|
38
|
+
const source = sourceRef.current;
|
|
39
|
+
const visible = state?.source === source && state.nonce === nonce ? state : null;
|
|
40
|
+
const refresh = useCallback(() => setNonce((value) => value + 1), []);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!enabled || !computerSessionId || !controllerGeneration) return;
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
let disposed = false;
|
|
46
|
+
setState({ source, nonce, inputAllowed: null, pending: true, error: null });
|
|
47
|
+
void (async () => {
|
|
48
|
+
try {
|
|
49
|
+
if (!client.getComputerInputPosture) {
|
|
50
|
+
throw new Error("Desktop input availability could not be verified.");
|
|
51
|
+
}
|
|
52
|
+
const posture = await client.getComputerInputPosture(workspaceId, computerSessionId, {
|
|
53
|
+
signal: controller.signal,
|
|
54
|
+
timeoutMs: 15_000,
|
|
55
|
+
});
|
|
56
|
+
if (disposed || sourceRef.current !== source) return;
|
|
57
|
+
if (
|
|
58
|
+
posture.computerSessionId !== computerSessionId ||
|
|
59
|
+
posture.controllerGeneration !== controllerGeneration ||
|
|
60
|
+
typeof posture.inputAllowed !== "boolean"
|
|
61
|
+
) {
|
|
62
|
+
throw new Error("Desktop input availability belongs to a different controller.");
|
|
63
|
+
}
|
|
64
|
+
setState({
|
|
65
|
+
source,
|
|
66
|
+
nonce,
|
|
67
|
+
inputAllowed: posture.inputAllowed,
|
|
68
|
+
pending: false,
|
|
69
|
+
error: null,
|
|
70
|
+
});
|
|
71
|
+
} catch (cause) {
|
|
72
|
+
if (disposed || controller.signal.aborted || sourceRef.current !== source) return;
|
|
73
|
+
setState({
|
|
74
|
+
source,
|
|
75
|
+
nonce,
|
|
76
|
+
inputAllowed: null,
|
|
77
|
+
pending: false,
|
|
78
|
+
error: cause instanceof Error ? cause : new Error(String(cause)),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
return () => {
|
|
83
|
+
disposed = true;
|
|
84
|
+
controller.abort();
|
|
85
|
+
};
|
|
86
|
+
}, [client, computerSessionId, controllerGeneration, enabled, nonce, source, workspaceId]);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
inputAllowed: visible?.inputAllowed ?? null,
|
|
90
|
+
pending: enabled && (visible?.pending ?? true),
|
|
91
|
+
error: visible?.error ?? null,
|
|
92
|
+
refresh,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -8,6 +8,10 @@ import type {
|
|
|
8
8
|
ComputerTarget,
|
|
9
9
|
} from "@opengeni/sdk/interaction";
|
|
10
10
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
|
+
import {
|
|
12
|
+
isInteractionControlUnavailable,
|
|
13
|
+
isNonRetryableInteractionError,
|
|
14
|
+
} from "../lib/interaction-errors";
|
|
11
15
|
import {
|
|
12
16
|
type EmbeddedComputerInteractionClientOverride,
|
|
13
17
|
useEmbeddedComputerInteraction,
|
|
@@ -28,6 +32,8 @@ export type UseComputerSessionResult = {
|
|
|
28
32
|
loading: boolean;
|
|
29
33
|
mutating: boolean;
|
|
30
34
|
error: Error | null;
|
|
35
|
+
/** Control service loss, independent of target accessibility inspection and media. */
|
|
36
|
+
controlError: Error | null;
|
|
31
37
|
refresh: () => Promise<void>;
|
|
32
38
|
readClipboard: () => Promise<ComputerClipboard>;
|
|
33
39
|
/** Changes only this viewer's target cursor; it never takes ownership or
|
|
@@ -55,6 +61,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
55
61
|
);
|
|
56
62
|
const visible =
|
|
57
63
|
state.computerSessionId === computerSessionId ? state : emptyState(computerSessionId, enabled);
|
|
64
|
+
const refreshBlocked = isNonRetryableInteractionError(visible.error);
|
|
58
65
|
const selectedTargetIdRef = useRef<string | null>(visible.selectedTargetId);
|
|
59
66
|
selectedTargetIdRef.current = visible.selectedTargetId;
|
|
60
67
|
const targetsRef = useRef<{
|
|
@@ -103,6 +110,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
103
110
|
requestRef.current.controller?.abort();
|
|
104
111
|
const controller = new AbortController();
|
|
105
112
|
requestRef.current = { id, controller };
|
|
113
|
+
let discoveryCompleted = false;
|
|
106
114
|
try {
|
|
107
115
|
const [session, targetResponse] = await Promise.all([
|
|
108
116
|
client.getComputerSession(workspaceId, computerSessionId, {
|
|
@@ -112,9 +120,38 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
112
120
|
signal: controller.signal,
|
|
113
121
|
}),
|
|
114
122
|
]);
|
|
123
|
+
discoveryCompleted = true;
|
|
115
124
|
if (!mountedRef.current || requestRef.current.id !== id) return;
|
|
116
125
|
const targets = sortComputerTargets(targetResponse.targets);
|
|
117
|
-
const selected = chooseTarget(targets, selectedTargetIdRef.current
|
|
126
|
+
const selected = chooseTarget(targets, selectedTargetIdRef.current);
|
|
127
|
+
// Discovery is useful independently of semantic observation. Publish it
|
|
128
|
+
// now so a slow/unresponsive application cannot block the frame stream
|
|
129
|
+
// or prevent the person from choosing a different window or screen.
|
|
130
|
+
const previous = observationRef.current.observation;
|
|
131
|
+
const retainedObservation =
|
|
132
|
+
selected &&
|
|
133
|
+
previous?.target.id === selected.id &&
|
|
134
|
+
previous.target.controllerGeneration === selected.controllerGeneration &&
|
|
135
|
+
previous.target.targetGeneration === selected.targetGeneration
|
|
136
|
+
? previous
|
|
137
|
+
: null;
|
|
138
|
+
selectedTargetIdRef.current = selected?.id ?? null;
|
|
139
|
+
targetsRef.current = { computerSessionId, targets };
|
|
140
|
+
observationRef.current = { computerSessionId, observation: retainedObservation };
|
|
141
|
+
setState((current) =>
|
|
142
|
+
current.computerSessionId === computerSessionId
|
|
143
|
+
? {
|
|
144
|
+
...current,
|
|
145
|
+
session,
|
|
146
|
+
targets,
|
|
147
|
+
selectedTargetId: selected?.id ?? null,
|
|
148
|
+
observation: retainedObservation,
|
|
149
|
+
loading: false,
|
|
150
|
+
error: null,
|
|
151
|
+
controlError: null,
|
|
152
|
+
}
|
|
153
|
+
: current,
|
|
154
|
+
);
|
|
118
155
|
const observation = selected
|
|
119
156
|
? await client.observeComputerTarget(workspaceId, computerSessionId, selected.id, {
|
|
120
157
|
signal: controller.signal,
|
|
@@ -139,12 +176,19 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
139
176
|
);
|
|
140
177
|
} catch (cause) {
|
|
141
178
|
if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id) return;
|
|
179
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
142
180
|
setState((current) =>
|
|
143
181
|
current.computerSessionId === computerSessionId
|
|
144
182
|
? {
|
|
145
183
|
...current,
|
|
146
184
|
loading: false,
|
|
147
|
-
error
|
|
185
|
+
error,
|
|
186
|
+
controlError: isInteractionControlUnavailable(
|
|
187
|
+
error,
|
|
188
|
+
discoveryCompleted ? "observation" : "control",
|
|
189
|
+
)
|
|
190
|
+
? error
|
|
191
|
+
: current.controlError,
|
|
148
192
|
}
|
|
149
193
|
: current,
|
|
150
194
|
);
|
|
@@ -173,15 +217,15 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
173
217
|
}, [computerSessionId, enabled, invalidateRefresh, refresh]);
|
|
174
218
|
|
|
175
219
|
useEffect(() => {
|
|
176
|
-
if (!enabled || !pageLive || visible.mutating) return;
|
|
220
|
+
if (!enabled || !pageLive || visible.mutating || refreshBlocked) return;
|
|
177
221
|
const timer = setInterval(() => {
|
|
178
222
|
if (!requestRef.current.controller) void refresh();
|
|
179
223
|
}, pollIntervalMs);
|
|
180
224
|
return () => clearInterval(timer);
|
|
181
|
-
}, [enabled, pageLive, pollIntervalMs, refresh, visible.mutating]);
|
|
225
|
+
}, [enabled, pageLive, pollIntervalMs, refresh, refreshBlocked, visible.mutating]);
|
|
182
226
|
|
|
183
227
|
useEffect(() => {
|
|
184
|
-
if (!enabled || !computerSessionId || !pageLive) return;
|
|
228
|
+
if (!enabled || !computerSessionId || !pageLive || refreshBlocked) return;
|
|
185
229
|
let disposed = false;
|
|
186
230
|
const timer = setInterval(() => {
|
|
187
231
|
void client.heartbeatComputerSession(workspaceId, computerSessionId).catch(() => {
|
|
@@ -192,7 +236,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
192
236
|
disposed = true;
|
|
193
237
|
clearInterval(timer);
|
|
194
238
|
};
|
|
195
|
-
}, [client, computerSessionId, enabled, pageLive, refresh, workspaceId]);
|
|
239
|
+
}, [client, computerSessionId, enabled, pageLive, refresh, refreshBlocked, workspaceId]);
|
|
196
240
|
|
|
197
241
|
const runMutation = useCallback(
|
|
198
242
|
async <T>(scopeComputerSessionId: string, operation: () => Promise<T>): Promise<T> => {
|
|
@@ -210,11 +254,23 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
210
254
|
: current,
|
|
211
255
|
);
|
|
212
256
|
try {
|
|
213
|
-
|
|
257
|
+
const result = await operation();
|
|
258
|
+
setState((current) =>
|
|
259
|
+
current.computerSessionId === scopeComputerSessionId
|
|
260
|
+
? { ...current, controlError: null }
|
|
261
|
+
: current,
|
|
262
|
+
);
|
|
263
|
+
return result;
|
|
214
264
|
} catch (cause) {
|
|
215
265
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
216
266
|
setState((current) =>
|
|
217
|
-
current.computerSessionId === scopeComputerSessionId
|
|
267
|
+
current.computerSessionId === scopeComputerSessionId
|
|
268
|
+
? {
|
|
269
|
+
...current,
|
|
270
|
+
error,
|
|
271
|
+
controlError: isInteractionControlUnavailable(error) ? error : current.controlError,
|
|
272
|
+
}
|
|
273
|
+
: current,
|
|
218
274
|
);
|
|
219
275
|
throw error;
|
|
220
276
|
} finally {
|
|
@@ -234,9 +290,9 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
234
290
|
|
|
235
291
|
const selectTarget = useCallback(
|
|
236
292
|
async (targetId: string): Promise<ComputerTarget> => {
|
|
237
|
-
if (!computerSessionId) throw new Error("No
|
|
293
|
+
if (!computerSessionId) throw new Error("No desktop is selected.");
|
|
238
294
|
const target = targetsRef.current.targets.find((candidate) => candidate.id === targetId);
|
|
239
|
-
if (!target) throw new Error("The selected
|
|
295
|
+
if (!target) throw new Error("The selected desktop target is no longer available.");
|
|
240
296
|
invalidateRefresh();
|
|
241
297
|
selectedTargetIdRef.current = target.id;
|
|
242
298
|
observationRef.current = { computerSessionId, observation: null };
|
|
@@ -269,7 +325,14 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
269
325
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
270
326
|
setState((current) =>
|
|
271
327
|
current.computerSessionId === computerSessionId && current.selectedTargetId === target.id
|
|
272
|
-
? {
|
|
328
|
+
? {
|
|
329
|
+
...current,
|
|
330
|
+
loading: false,
|
|
331
|
+
error,
|
|
332
|
+
controlError: isInteractionControlUnavailable(error, "observation")
|
|
333
|
+
? error
|
|
334
|
+
: current.controlError,
|
|
335
|
+
}
|
|
273
336
|
: current,
|
|
274
337
|
);
|
|
275
338
|
throw error;
|
|
@@ -284,9 +347,9 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
284
347
|
operationId: string,
|
|
285
348
|
frame: ComputerFrame | null,
|
|
286
349
|
): Promise<ComputerActionReceipt> => {
|
|
287
|
-
if (!computerSessionId) throw new Error("No
|
|
350
|
+
if (!computerSessionId) throw new Error("No desktop is selected.");
|
|
288
351
|
if (frame && frame.computerSessionId !== computerSessionId) {
|
|
289
|
-
throw new Error("The displayed
|
|
352
|
+
throw new Error("The displayed desktop frame belongs to another desktop session.");
|
|
290
353
|
}
|
|
291
354
|
const currentObservation =
|
|
292
355
|
observationRef.current.computerSessionId === computerSessionId
|
|
@@ -301,19 +364,27 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
301
364
|
? (targetsRef.current.targets.find((candidate) => candidate.id === frame.targetId) ??
|
|
302
365
|
(currentObservation?.target.id === frame.targetId ? currentObservation.target : null))
|
|
303
366
|
: null;
|
|
304
|
-
const
|
|
305
|
-
|
|
367
|
+
const inputTarget =
|
|
368
|
+
(action.type === "keyboard" || action.type === "clipboard") &&
|
|
369
|
+
targetsRef.current.computerSessionId === computerSessionId
|
|
370
|
+
? targetsRef.current.targets.find(
|
|
371
|
+
(candidate) => candidate.id === selectedTargetIdRef.current,
|
|
372
|
+
)
|
|
373
|
+
: null;
|
|
374
|
+
const target =
|
|
375
|
+
frameTarget ?? focusTarget ?? currentObservation?.target ?? inputTarget ?? null;
|
|
376
|
+
if (!target) throw new Error("The desktop target is not ready for input.");
|
|
306
377
|
if (frame && frame.targetId !== selectedTargetIdRef.current) {
|
|
307
|
-
throw new Error("The displayed
|
|
378
|
+
throw new Error("The displayed desktop frame is no longer selected.");
|
|
308
379
|
}
|
|
309
380
|
if (action.type === "pointer") {
|
|
310
381
|
const expectedFrameId = frame?.frameId ?? currentObservation?.frameId ?? null;
|
|
311
382
|
if (!expectedFrameId || action.frameId !== expectedFrameId) {
|
|
312
|
-
throw new Error("Pointer input must reference the exact displayed
|
|
383
|
+
throw new Error("Pointer input must reference the exact displayed desktop frame.");
|
|
313
384
|
}
|
|
314
385
|
}
|
|
315
386
|
if (action.type === "semantic" && !currentObservation) {
|
|
316
|
-
throw new Error("The
|
|
387
|
+
throw new Error("The desktop accessibility tree is not ready for input.");
|
|
317
388
|
}
|
|
318
389
|
|
|
319
390
|
return await runMutation(computerSessionId, async () => {
|
|
@@ -367,8 +438,22 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
367
438
|
);
|
|
368
439
|
|
|
369
440
|
const readClipboard = useCallback(async (): Promise<ComputerClipboard> => {
|
|
370
|
-
if (!computerSessionId) throw new Error("No
|
|
371
|
-
|
|
441
|
+
if (!computerSessionId) throw new Error("No desktop is selected.");
|
|
442
|
+
try {
|
|
443
|
+
return await client.readComputerClipboard(workspaceId, computerSessionId);
|
|
444
|
+
} catch (cause) {
|
|
445
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
446
|
+
setState((current) =>
|
|
447
|
+
current.computerSessionId === computerSessionId
|
|
448
|
+
? {
|
|
449
|
+
...current,
|
|
450
|
+
error,
|
|
451
|
+
controlError: isInteractionControlUnavailable(error) ? error : current.controlError,
|
|
452
|
+
}
|
|
453
|
+
: current,
|
|
454
|
+
);
|
|
455
|
+
throw error;
|
|
456
|
+
}
|
|
372
457
|
}, [client, computerSessionId, workspaceId]);
|
|
373
458
|
|
|
374
459
|
return {
|
|
@@ -380,6 +465,7 @@ export function useComputerSession(options: UseComputerSessionOptions): UseCompu
|
|
|
380
465
|
loading: visible.loading,
|
|
381
466
|
mutating: visible.mutating,
|
|
382
467
|
error: visible.error,
|
|
468
|
+
controlError: visible.controlError,
|
|
383
469
|
refresh,
|
|
384
470
|
readClipboard,
|
|
385
471
|
selectTarget,
|
|
@@ -397,6 +483,7 @@ type ComputerControlState = {
|
|
|
397
483
|
loading: boolean;
|
|
398
484
|
mutating: boolean;
|
|
399
485
|
error: Error | null;
|
|
486
|
+
controlError: Error | null;
|
|
400
487
|
};
|
|
401
488
|
|
|
402
489
|
function emptyState(computerSessionId: string | null, loading: boolean): ComputerControlState {
|
|
@@ -409,32 +496,23 @@ function emptyState(computerSessionId: string | null, loading: boolean): Compute
|
|
|
409
496
|
loading,
|
|
410
497
|
mutating: false,
|
|
411
498
|
error: null,
|
|
499
|
+
controlError: null,
|
|
412
500
|
};
|
|
413
501
|
}
|
|
414
502
|
|
|
415
503
|
function chooseTarget(
|
|
416
504
|
targets: readonly ComputerTarget[],
|
|
417
505
|
preferredId: string | null,
|
|
418
|
-
platform: ComputerSession["platform"],
|
|
419
506
|
): ComputerTarget | null {
|
|
420
507
|
const preferred = targets.find((target) => target.id === preferredId);
|
|
421
508
|
if (preferred) return preferred;
|
|
422
|
-
if (platform === "linux") {
|
|
423
|
-
return (
|
|
424
|
-
targets.find((target) => target.focused && target.kind === "screen") ??
|
|
425
|
-
targets.find((target) => target.kind === "screen") ??
|
|
426
|
-
targets.find((target) => target.focused && target.kind === "window") ??
|
|
427
|
-
targets.find((target) => target.kind === "window") ??
|
|
428
|
-
targets[0] ??
|
|
429
|
-
null
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
509
|
return (
|
|
510
|
+
targets.find((target) => target.focused && target.kind === "screen") ??
|
|
511
|
+
targets.find((target) => target.kind === "screen") ??
|
|
433
512
|
targets.find((target) => target.focused && target.kind === "window") ??
|
|
434
513
|
targets.find((target) => target.kind === "window") ??
|
|
435
514
|
targets.find((target) => target.focused && target.kind === "app") ??
|
|
436
515
|
targets.find((target) => target.kind === "app") ??
|
|
437
|
-
targets.find((target) => target.kind === "screen") ??
|
|
438
516
|
targets[0] ??
|
|
439
517
|
null
|
|
440
518
|
);
|
|
@@ -74,6 +74,7 @@ export function useComputerSessions(
|
|
|
74
74
|
requestRef.current = { id, controller };
|
|
75
75
|
setState((current) => ({
|
|
76
76
|
...(current.workspaceId === workspaceId ? current : emptyState(workspaceId, true)),
|
|
77
|
+
active: true,
|
|
77
78
|
loading: foreground,
|
|
78
79
|
refreshing: !foreground,
|
|
79
80
|
error: foreground || current.workspaceId !== workspaceId ? null : current.error,
|
|
@@ -85,6 +86,7 @@ export function useComputerSessions(
|
|
|
85
86
|
if (!mountedRef.current || requestRef.current.id !== id) return;
|
|
86
87
|
setState({
|
|
87
88
|
workspaceId,
|
|
89
|
+
active: true,
|
|
88
90
|
revision: response.revision,
|
|
89
91
|
sessions: sortComputerSessions(response.sessions),
|
|
90
92
|
loading: false,
|
|
@@ -187,7 +189,10 @@ export function useComputerSessions(
|
|
|
187
189
|
revision: visible.revision,
|
|
188
190
|
sessions: visible.sessions,
|
|
189
191
|
relevantSessions,
|
|
190
|
-
|
|
192
|
+
// A disabled registry is deliberately empty. When its surface becomes
|
|
193
|
+
// visible again, expose that transition as loading in the same render so
|
|
194
|
+
// consumers cannot mistake the stale empty snapshot for a completed list.
|
|
195
|
+
loading: enabled ? !visible.active || visible.loading : false,
|
|
191
196
|
refreshing: visible.refreshing,
|
|
192
197
|
error: visible.error,
|
|
193
198
|
refresh,
|
|
@@ -198,6 +203,7 @@ export function useComputerSessions(
|
|
|
198
203
|
|
|
199
204
|
type ComputerRegistryState = {
|
|
200
205
|
workspaceId: string;
|
|
206
|
+
active: boolean;
|
|
201
207
|
revision: number;
|
|
202
208
|
sessions: ComputerSession[];
|
|
203
209
|
loading: boolean;
|
|
@@ -208,6 +214,7 @@ type ComputerRegistryState = {
|
|
|
208
214
|
function emptyState(workspaceId: string, loading: boolean): ComputerRegistryState {
|
|
209
215
|
return {
|
|
210
216
|
workspaceId,
|
|
217
|
+
active: loading,
|
|
211
218
|
revision: 0,
|
|
212
219
|
sessions: [],
|
|
213
220
|
loading,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ConnectController } from "@opengeni/connect";
|
|
2
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
3
|
+
|
|
4
|
+
/** Internal consumers import the hook directly so setup surfaces stay lazy. */
|
|
5
|
+
export function useConnect(controller: ConnectController) {
|
|
6
|
+
const snapshot = useSyncExternalStore(
|
|
7
|
+
controller.subscribe,
|
|
8
|
+
controller.getSnapshot,
|
|
9
|
+
controller.getSnapshot,
|
|
10
|
+
);
|
|
11
|
+
const actions = useMemo(
|
|
12
|
+
() => ({
|
|
13
|
+
begin: controller.begin.bind(controller),
|
|
14
|
+
recover: controller.recover.bind(controller),
|
|
15
|
+
refresh: controller.refresh.bind(controller),
|
|
16
|
+
waitForAction: controller.waitForAction.bind(controller),
|
|
17
|
+
advance: controller.advance.bind(controller),
|
|
18
|
+
cancel: controller.cancel.bind(controller),
|
|
19
|
+
}),
|
|
20
|
+
[controller],
|
|
21
|
+
);
|
|
22
|
+
return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);
|
|
23
|
+
}
|