@opengeni/react 1.0.1 → 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 +651 -21
- 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 +6 -3
- package/dist/realtime.js +133 -74
- 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 +133 -46
- 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
|
@@ -2,6 +2,7 @@ import { FileCode2Icon, FileWarningIcon, LoaderCircleIcon } from "lucide-react";
|
|
|
2
2
|
import { type ReactNode, useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Group, Panel, Separator } from "react-resizable-panels";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { prefersReducedMotion } from "../lib/motion";
|
|
5
6
|
import { useThemeType } from "../lib/use-theme-type";
|
|
6
7
|
import {
|
|
7
8
|
CapturedFileUnavailableError,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
type UseSandboxFilesResult,
|
|
10
11
|
} from "../hooks/use-sandbox-files";
|
|
11
12
|
import type { UseSandboxGitResult } from "../hooks/use-sandbox-git";
|
|
13
|
+
import { filePathVisibility, type FileNodeVisibilityPredicate } from "../file-node-visibility";
|
|
12
14
|
import { CodeEditor } from "./code-editor";
|
|
13
15
|
import { FileBrowser } from "./file-browser";
|
|
14
16
|
import { PierreFile } from "./pierre-file";
|
|
@@ -32,8 +34,16 @@ export type SandboxFilesProps = {
|
|
|
32
34
|
* dock warms the box on this so the save lands fast; opening/reading never fires
|
|
33
35
|
* it. Browsing the tree/diff must not warm a box. */
|
|
34
36
|
onEditIntent?: (() => void) | undefined;
|
|
35
|
-
/**
|
|
37
|
+
/** Restore the file last viewed in this task. Invalid/missing paths still
|
|
38
|
+
* surface the ordinary file-view error instead of changing files silently. */
|
|
39
|
+
initialSelectedPath?: string | null | undefined;
|
|
40
|
+
onSelectedPathChange?: ((path: string | null) => void) | undefined;
|
|
41
|
+
/** Presentation-only node filter shared with the tree and selected-file view. */
|
|
42
|
+
isNodeVisible?: FileNodeVisibilityPredicate | undefined;
|
|
43
|
+
/** A deliberate file-open path routed here by the parent workspace. */
|
|
36
44
|
requestedPath?: string | undefined;
|
|
45
|
+
/** 1-based line to reveal after `requestedPath` opens. */
|
|
46
|
+
requestedLine?: number | null | undefined;
|
|
37
47
|
/** Identity for one guarded-file request. Increment this when the same path is
|
|
38
48
|
* deliberately requested again; it also lets a pending request be consumed
|
|
39
49
|
* without overriding later manual tree navigation. Defaults to the path. */
|
|
@@ -47,6 +57,8 @@ export type SandboxFilesProps = {
|
|
|
47
57
|
workspaceWaking?: boolean | undefined;
|
|
48
58
|
/** Whether live reads are currently authoritative. */
|
|
49
59
|
liveWorkspaceReady?: boolean | undefined;
|
|
60
|
+
/** Failed live negotiation; never present a failure as an ongoing wake. */
|
|
61
|
+
workspaceError?: Error | null | undefined;
|
|
50
62
|
/** Deliberately wake the machine to read content absent from the capture. */
|
|
51
63
|
onWakeWorkspace?: (() => void) | undefined;
|
|
52
64
|
themeType?: "dark" | "light" | undefined;
|
|
@@ -67,22 +79,33 @@ export function SandboxFiles({
|
|
|
67
79
|
usePierre = true,
|
|
68
80
|
editable = true,
|
|
69
81
|
onEditIntent,
|
|
82
|
+
initialSelectedPath,
|
|
83
|
+
onSelectedPathChange,
|
|
84
|
+
isNodeVisible,
|
|
70
85
|
requestedPath,
|
|
86
|
+
requestedLine,
|
|
71
87
|
requestedPathRequestId,
|
|
72
88
|
requestedPathReady = true,
|
|
73
89
|
workspaceResting = false,
|
|
74
90
|
workspaceWaking = false,
|
|
75
91
|
liveWorkspaceReady = true,
|
|
92
|
+
workspaceError = null,
|
|
76
93
|
onWakeWorkspace,
|
|
77
94
|
themeType,
|
|
78
95
|
className,
|
|
79
96
|
}: SandboxFilesProps) {
|
|
80
|
-
const [selected, setSelected] = useState<string | null>(null);
|
|
97
|
+
const [selected, setSelected] = useState<string | null>(() => initialSelectedPath ?? null);
|
|
81
98
|
// View vs Edit for the selected file. Resets to View on every new selection so
|
|
82
99
|
// opening a file never lands you in a stale dirty editor for a different path.
|
|
83
100
|
const [editMode, setEditMode] = useState(false);
|
|
101
|
+
const [focusLine, setFocusLine] = useState<number | null>(null);
|
|
102
|
+
const [treeRevealRequest, setTreeRevealRequest] = useState<{
|
|
103
|
+
path: string;
|
|
104
|
+
requestId: string | number;
|
|
105
|
+
} | null>(null);
|
|
84
106
|
const [liveRequestedPath, setLiveRequestedPath] = useState<string | null>(null);
|
|
85
107
|
const [viewReloadRevision, setViewReloadRevision] = useState(0);
|
|
108
|
+
const viewerScrollRef = useRef<HTMLDivElement | null>(null);
|
|
86
109
|
const pendingRequestRef = useRef<string | number | null>(null);
|
|
87
110
|
const handledRequestRef = useRef<string | number | null>(null);
|
|
88
111
|
const requestKey = requestedPath ? (requestedPathRequestId ?? requestedPath) : null;
|
|
@@ -91,6 +114,7 @@ export function SandboxFiles({
|
|
|
91
114
|
if (!requestedPath || requestKey === null) {
|
|
92
115
|
pendingRequestRef.current = null;
|
|
93
116
|
handledRequestRef.current = null;
|
|
117
|
+
setTreeRevealRequest(null);
|
|
94
118
|
return;
|
|
95
119
|
}
|
|
96
120
|
if (handledRequestRef.current === requestKey) {
|
|
@@ -98,13 +122,40 @@ export function SandboxFiles({
|
|
|
98
122
|
}
|
|
99
123
|
if (!requestedPathReady) {
|
|
100
124
|
pendingRequestRef.current = requestKey;
|
|
125
|
+
setTreeRevealRequest(null);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (isNodeVisible && files.loading && files.tree.length === 0) return;
|
|
129
|
+
if (isNodeVisible && !files.loading && files.tree.length === 0) {
|
|
130
|
+
handledRequestRef.current = requestKey;
|
|
131
|
+
pendingRequestRef.current = null;
|
|
132
|
+
setTreeRevealRequest(null);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (filePathVisibility(files.tree, requestedPath, isNodeVisible) === "hidden") {
|
|
136
|
+
handledRequestRef.current = requestKey;
|
|
137
|
+
pendingRequestRef.current = null;
|
|
138
|
+
setTreeRevealRequest(null);
|
|
101
139
|
return;
|
|
102
140
|
}
|
|
103
141
|
handledRequestRef.current = requestKey;
|
|
104
142
|
pendingRequestRef.current = null;
|
|
105
143
|
setSelected(requestedPath);
|
|
144
|
+
onSelectedPathChange?.(requestedPath);
|
|
106
145
|
setEditMode(false);
|
|
107
|
-
|
|
146
|
+
setFocusLine(requestedLine != null && requestedLine > 0 ? requestedLine : null);
|
|
147
|
+
setTreeRevealRequest({ path: requestedPath, requestId: requestKey });
|
|
148
|
+
setViewReloadRevision((revision) => revision + 1);
|
|
149
|
+
}, [
|
|
150
|
+
files.loading,
|
|
151
|
+
files.tree,
|
|
152
|
+
isNodeVisible,
|
|
153
|
+
onSelectedPathChange,
|
|
154
|
+
requestKey,
|
|
155
|
+
requestedLine,
|
|
156
|
+
requestedPath,
|
|
157
|
+
requestedPathReady,
|
|
158
|
+
]);
|
|
108
159
|
|
|
109
160
|
// Side-by-side (tree left, viewer right) once the surface is wide enough;
|
|
110
161
|
// stacked (tree over viewer) on a narrow dock. Tracked off the container so it
|
|
@@ -143,27 +194,52 @@ export function SandboxFiles({
|
|
|
143
194
|
// The selected tree file opens in the viewer (read-only) or the editor (when
|
|
144
195
|
// writable). Nothing is auto-selected — the pane waits for a tree click, so the
|
|
145
196
|
// Files tab opens as a calm browser, not a diff.
|
|
146
|
-
const
|
|
197
|
+
const selectedVisibility = selected
|
|
198
|
+
? filePathVisibility(files.tree, selected, isNodeVisible)
|
|
199
|
+
: "unknown";
|
|
200
|
+
const visibilityPending = Boolean(isNodeVisible && files.loading && files.tree.length === 0);
|
|
201
|
+
const viewPath = selectedVisibility === "hidden" || visibilityPending ? null : selected;
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (selected === null || selectedVisibility !== "hidden") return;
|
|
204
|
+
setSelected(null);
|
|
205
|
+
onSelectedPathChange?.(null);
|
|
206
|
+
setEditMode(false);
|
|
207
|
+
setFocusLine(null);
|
|
208
|
+
setTreeRevealRequest(null);
|
|
209
|
+
setLiveRequestedPath(null);
|
|
210
|
+
}, [onSelectedPathChange, selected, selectedVisibility]);
|
|
147
211
|
const fileView = useFileView(
|
|
148
212
|
viewPath,
|
|
149
213
|
files.readFile,
|
|
150
|
-
|
|
214
|
+
`${files.contentRevision ?? 0}:${viewReloadRevision}`,
|
|
151
215
|
);
|
|
152
216
|
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (focusLine === null && viewReloadRevision > 0 && viewerScrollRef.current) {
|
|
219
|
+
viewerScrollRef.current.scrollTop = 0;
|
|
220
|
+
}
|
|
221
|
+
}, [focusLine, viewReloadRevision]);
|
|
222
|
+
|
|
153
223
|
// Selecting a (different) file always returns to View — never drop the user into
|
|
154
224
|
// an editor whose buffer belongs to the previously-selected path. Manual
|
|
155
225
|
// navigation also consumes a pending guarded-file request: a late cold→warm
|
|
156
226
|
// transition must never pull the user away from the file they chose meanwhile.
|
|
157
|
-
const selectFile = useCallback(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
227
|
+
const selectFile = useCallback(
|
|
228
|
+
(path: string) => {
|
|
229
|
+
if (pendingRequestRef.current !== null) {
|
|
230
|
+
handledRequestRef.current = pendingRequestRef.current;
|
|
231
|
+
pendingRequestRef.current = null;
|
|
232
|
+
}
|
|
233
|
+
setSelected(path);
|
|
234
|
+
onSelectedPathChange?.(path);
|
|
235
|
+
setEditMode(false);
|
|
236
|
+
setFocusLine(null);
|
|
237
|
+
setTreeRevealRequest(null);
|
|
238
|
+
setLiveRequestedPath(null);
|
|
239
|
+
setViewReloadRevision(0);
|
|
240
|
+
},
|
|
241
|
+
[onSelectedPathChange],
|
|
242
|
+
);
|
|
167
243
|
|
|
168
244
|
// A tree file is editable only when it is a real, fully-loaded text file: not
|
|
169
245
|
// binary (would corrupt on save) and not truncated (we only hold a PREFIX). The
|
|
@@ -181,10 +257,22 @@ export function SandboxFiles({
|
|
|
181
257
|
const captureFileUnavailable =
|
|
182
258
|
fileView.error instanceof CapturedFileUnavailableError ? fileView.error : null;
|
|
183
259
|
const waitingForSelectedFile =
|
|
260
|
+
!workspaceError &&
|
|
184
261
|
liveRequestedPath === viewPath &&
|
|
185
262
|
(!liveWorkspaceReady || files.loading) &&
|
|
186
263
|
captureFileUnavailable !== null;
|
|
187
264
|
|
|
265
|
+
if (workspaceError && !liveWorkspaceReady && files.source !== "capture") {
|
|
266
|
+
return (
|
|
267
|
+
<Notice className={className} title="Could not open live workspace" announce="alert">
|
|
268
|
+
<p>{workspaceError.message}</p>
|
|
269
|
+
{onWakeWorkspace ? (
|
|
270
|
+
<WakeButton onClick={onWakeWorkspace}>Retry live workspace</WakeButton>
|
|
271
|
+
) : null}
|
|
272
|
+
</Notice>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
188
276
|
if (workspaceResting || workspaceWaking) {
|
|
189
277
|
return (
|
|
190
278
|
<div className={cn("h-full", className)} data-opengeni-workspace-resting>
|
|
@@ -263,7 +351,14 @@ export function SandboxFiles({
|
|
|
263
351
|
>
|
|
264
352
|
<FileBrowser
|
|
265
353
|
result={files}
|
|
354
|
+
isNodeVisible={isNodeVisible}
|
|
266
355
|
selectedPath={selected ?? undefined}
|
|
356
|
+
{...(treeRevealRequest
|
|
357
|
+
? {
|
|
358
|
+
revealPath: treeRevealRequest.path,
|
|
359
|
+
revealPathRequestId: treeRevealRequest.requestId,
|
|
360
|
+
}
|
|
361
|
+
: {})}
|
|
267
362
|
onSelectFile={selectFile}
|
|
268
363
|
editable={editable}
|
|
269
364
|
emptyState="This directory is empty"
|
|
@@ -295,7 +390,11 @@ export function SandboxFiles({
|
|
|
295
390
|
data-opengeni-selected-file
|
|
296
391
|
className="min-w-0 truncate font-og-mono text-og-xs text-og-fg-muted"
|
|
297
392
|
>
|
|
298
|
-
{selected
|
|
393
|
+
{selected
|
|
394
|
+
? focusLine !== null
|
|
395
|
+
? `${selected}:${focusLine}`
|
|
396
|
+
: selected
|
|
397
|
+
: "No file selected"}
|
|
299
398
|
</span>
|
|
300
399
|
{/* View/Edit toggle — only for a real, fully-loaded text file the editor
|
|
301
400
|
can safely round-trip. Binary/truncated/read-only files never get an
|
|
@@ -311,7 +410,11 @@ export function SandboxFiles({
|
|
|
311
410
|
/>
|
|
312
411
|
)}
|
|
313
412
|
</div>
|
|
314
|
-
<div
|
|
413
|
+
<div
|
|
414
|
+
ref={viewerScrollRef}
|
|
415
|
+
className="min-h-0 flex-1 overflow-auto"
|
|
416
|
+
data-opengeni-file-viewer-scroll
|
|
417
|
+
>
|
|
315
418
|
{viewPath ? (
|
|
316
419
|
showEditor && fileView.content !== null ? (
|
|
317
420
|
<CodeEditor
|
|
@@ -327,6 +430,15 @@ export function SandboxFiles({
|
|
|
327
430
|
{...(onEditIntent ? { onEditIntent } : {})}
|
|
328
431
|
className="h-full"
|
|
329
432
|
/>
|
|
433
|
+
) : workspaceError &&
|
|
434
|
+
(liveRequestedPath === viewPath || requestedPath === viewPath) &&
|
|
435
|
+
!liveWorkspaceReady ? (
|
|
436
|
+
<Notice title="Could not open live file" announce="alert">
|
|
437
|
+
<p>{workspaceError.message}</p>
|
|
438
|
+
{onWakeWorkspace ? (
|
|
439
|
+
<WakeButton onClick={onWakeWorkspace}>Retry live file</WakeButton>
|
|
440
|
+
) : null}
|
|
441
|
+
</Notice>
|
|
330
442
|
) : waitingForSelectedFile ? (
|
|
331
443
|
<Notice
|
|
332
444
|
icon={
|
|
@@ -367,6 +479,12 @@ export function SandboxFiles({
|
|
|
367
479
|
</Notice>
|
|
368
480
|
) : fileView.loading ? (
|
|
369
481
|
<Notice announce="status">Loading {viewPath}…</Notice>
|
|
482
|
+
) : fileView.imageUrl ? (
|
|
483
|
+
<RasterFilePreview
|
|
484
|
+
key={fileView.imageUrl}
|
|
485
|
+
src={fileView.imageUrl}
|
|
486
|
+
path={viewPath}
|
|
487
|
+
/>
|
|
370
488
|
) : fileView.isBinary ? (
|
|
371
489
|
<Notice>
|
|
372
490
|
{viewPath} is a binary file ({fileView.sizeBytes ?? 0} bytes).
|
|
@@ -379,8 +497,9 @@ export function SandboxFiles({
|
|
|
379
497
|
loaded). Editing is disabled to avoid corrupting the file.
|
|
380
498
|
</div>
|
|
381
499
|
)}
|
|
382
|
-
{usePierre ? (
|
|
500
|
+
{usePierre && focusLine === null ? (
|
|
383
501
|
<PierreFile
|
|
502
|
+
key={`${viewPath}:${viewReloadRevision}`}
|
|
384
503
|
path={viewPath}
|
|
385
504
|
contents={fileView.content}
|
|
386
505
|
themeType={resolvedTheme}
|
|
@@ -391,6 +510,12 @@ export function SandboxFiles({
|
|
|
391
510
|
}
|
|
392
511
|
className="p-1"
|
|
393
512
|
/>
|
|
513
|
+
) : focusLine !== null ? (
|
|
514
|
+
<LineNumberedFile
|
|
515
|
+
path={viewPath}
|
|
516
|
+
contents={fileView.content}
|
|
517
|
+
focusLine={focusLine}
|
|
518
|
+
/>
|
|
394
519
|
) : (
|
|
395
520
|
<pre className="overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg">
|
|
396
521
|
{fileView.content}
|
|
@@ -402,18 +527,27 @@ export function SandboxFiles({
|
|
|
402
527
|
)
|
|
403
528
|
) : // Nothing selected — the tree shows the whole workspace; pick a file.
|
|
404
529
|
requestedPath && !requestedPathReady ? (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
<
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
530
|
+
workspaceError ? (
|
|
531
|
+
<Notice title="Could not open live file" announce="alert">
|
|
532
|
+
<p>{workspaceError.message}</p>
|
|
533
|
+
{onWakeWorkspace ? (
|
|
534
|
+
<WakeButton onClick={onWakeWorkspace}>Retry live file</WakeButton>
|
|
535
|
+
) : null}
|
|
536
|
+
</Notice>
|
|
537
|
+
) : (
|
|
538
|
+
<Notice
|
|
539
|
+
icon={
|
|
540
|
+
<LoaderCircleIcon
|
|
541
|
+
className="size-5 animate-spin motion-reduce:animate-none"
|
|
542
|
+
aria-hidden
|
|
543
|
+
/>
|
|
544
|
+
}
|
|
545
|
+
title="Waking sandbox"
|
|
546
|
+
announce="status"
|
|
547
|
+
>
|
|
548
|
+
Opening {requestedPath} when the live workspace is ready…
|
|
549
|
+
</Notice>
|
|
550
|
+
)
|
|
417
551
|
) : (
|
|
418
552
|
<Notice icon={<FileCode2Icon className="size-5" aria-hidden />} title="Choose a file">
|
|
419
553
|
Select a file in the tree to preview it.
|
|
@@ -431,13 +565,72 @@ function WakeButton({ children, onClick }: { children: ReactNode; onClick: () =>
|
|
|
431
565
|
<button
|
|
432
566
|
type="button"
|
|
433
567
|
onClick={onClick}
|
|
434
|
-
className="mt-1 inline-flex min-h-11 items-center justify-center rounded-og-md bg-og-
|
|
568
|
+
className="mt-1 inline-flex min-h-11 items-center justify-center rounded-og-md border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-2 text-og-sm font-medium transition-colors hover:bg-og-primary-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg"
|
|
435
569
|
>
|
|
436
570
|
{children}
|
|
437
571
|
</button>
|
|
438
572
|
);
|
|
439
573
|
}
|
|
440
574
|
|
|
575
|
+
function LineNumberedFile({
|
|
576
|
+
path,
|
|
577
|
+
contents,
|
|
578
|
+
focusLine,
|
|
579
|
+
}: {
|
|
580
|
+
path: string;
|
|
581
|
+
contents: string;
|
|
582
|
+
focusLine: number;
|
|
583
|
+
}) {
|
|
584
|
+
const lines = contents.split("\n");
|
|
585
|
+
const inRange = focusLine >= 1 && focusLine <= lines.length;
|
|
586
|
+
const targetRef = useRef<HTMLDivElement | null>(null);
|
|
587
|
+
|
|
588
|
+
useEffect(() => {
|
|
589
|
+
targetRef.current?.scrollIntoView({
|
|
590
|
+
block: "center",
|
|
591
|
+
behavior: prefersReducedMotion() ? "auto" : "smooth",
|
|
592
|
+
});
|
|
593
|
+
}, [path, focusLine, contents]);
|
|
594
|
+
|
|
595
|
+
return (
|
|
596
|
+
<div
|
|
597
|
+
className="h-full min-h-0 overflow-auto font-og-mono text-og-sm text-og-fg"
|
|
598
|
+
role="region"
|
|
599
|
+
aria-label={inRange ? `${path} at line ${focusLine}` : path}
|
|
600
|
+
>
|
|
601
|
+
{!inRange ? (
|
|
602
|
+
<p
|
|
603
|
+
className="border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-fg-muted"
|
|
604
|
+
role="status"
|
|
605
|
+
>
|
|
606
|
+
Line {focusLine} is past the end of this file.
|
|
607
|
+
</p>
|
|
608
|
+
) : null}
|
|
609
|
+
<div>
|
|
610
|
+
{lines.map((text, index) => {
|
|
611
|
+
const lineNumber = index + 1;
|
|
612
|
+
const focused = inRange && lineNumber === focusLine;
|
|
613
|
+
return (
|
|
614
|
+
<div
|
|
615
|
+
key={lineNumber}
|
|
616
|
+
ref={focused ? targetRef : undefined}
|
|
617
|
+
data-opengeni-file-line={lineNumber}
|
|
618
|
+
{...(focused ? { "data-opengeni-focus-line": "" } : {})}
|
|
619
|
+
aria-current={focused ? "location" : undefined}
|
|
620
|
+
className={cn("flex gap-3 px-2 py-0.5 leading-6", focused && "bg-og-accent-soft")}
|
|
621
|
+
>
|
|
622
|
+
<span className="w-11 shrink-0 select-none text-right tabular-nums text-og-fg-subtle">
|
|
623
|
+
{lineNumber}
|
|
624
|
+
</span>
|
|
625
|
+
<pre className="min-w-0 flex-1 whitespace-pre-wrap break-words">{text || " "}</pre>
|
|
626
|
+
</div>
|
|
627
|
+
);
|
|
628
|
+
})}
|
|
629
|
+
</div>
|
|
630
|
+
</div>
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
|
|
441
634
|
function GitHeader({ git, loading }: { git: SandboxFilesGitSummary; loading: boolean }) {
|
|
442
635
|
if (loading) {
|
|
443
636
|
return (
|
|
@@ -474,8 +667,10 @@ function GitHeader({ git, loading }: { git: SandboxFilesGitSummary; loading: boo
|
|
|
474
667
|
</span>
|
|
475
668
|
{(git.ahead > 0 || git.behind > 0) && (
|
|
476
669
|
<span className="flex shrink-0 items-center gap-1.5 text-og-xs text-og-fg-subtle">
|
|
477
|
-
{
|
|
478
|
-
|
|
670
|
+
{/* Small arrow glyphs can make axe's pixel overlap heuristic inconclusive.
|
|
671
|
+
Keep both counters in the same computed-contrast audit as the dirty count. */}
|
|
672
|
+
{git.ahead > 0 && <span data-contrast-audited>↑{git.ahead}</span>}
|
|
673
|
+
{git.behind > 0 && <span data-contrast-audited>↓{git.behind}</span>}
|
|
479
674
|
</span>
|
|
480
675
|
)}
|
|
481
676
|
{dirty && (
|
|
@@ -523,6 +718,7 @@ function Segmented({
|
|
|
523
718
|
|
|
524
719
|
type FileViewState = {
|
|
525
720
|
content: string | null;
|
|
721
|
+
imageUrl?: string | null;
|
|
526
722
|
isBinary: boolean;
|
|
527
723
|
/** The backend truncated the read (size cap hit) — content is a PREFIX only.
|
|
528
724
|
* Editing+saving such a file would write the prefix back and corrupt it, so
|
|
@@ -542,7 +738,7 @@ type FileViewState = {
|
|
|
542
738
|
function useFileView(
|
|
543
739
|
path: string | null,
|
|
544
740
|
readFile: UseSandboxFilesResult["readFile"],
|
|
545
|
-
reloadRevision = 0,
|
|
741
|
+
reloadRevision: string | number = 0,
|
|
546
742
|
): FileViewState {
|
|
547
743
|
const previousPathRef = useRef<string | null>(null);
|
|
548
744
|
const [state, setState] = useState<FileViewState>({
|
|
@@ -595,6 +791,8 @@ function useFileView(
|
|
|
595
791
|
: res.content;
|
|
596
792
|
setState({
|
|
597
793
|
content,
|
|
794
|
+
imageUrl:
|
|
795
|
+
!res.truncated && res.encoding === "base64" ? rasterImageUrl(path, res.content) : null,
|
|
598
796
|
isBinary: res.isBinary,
|
|
599
797
|
truncated: res.truncated,
|
|
600
798
|
sizeBytes: res.sizeBytes,
|
|
@@ -626,6 +824,38 @@ function useFileView(
|
|
|
626
824
|
return state;
|
|
627
825
|
}
|
|
628
826
|
|
|
827
|
+
/** Only raster formats belong in this preview; never interpret SVG/HTML as a document. */
|
|
828
|
+
function rasterImageUrl(path: string, content: string): string | null {
|
|
829
|
+
const extension = path.split(".").pop()?.toLowerCase();
|
|
830
|
+
const mime =
|
|
831
|
+
extension === "png"
|
|
832
|
+
? "image/png"
|
|
833
|
+
: extension === "jpg" || extension === "jpeg"
|
|
834
|
+
? "image/jpeg"
|
|
835
|
+
: extension === "gif"
|
|
836
|
+
? "image/gif"
|
|
837
|
+
: extension === "webp"
|
|
838
|
+
? "image/webp"
|
|
839
|
+
: null;
|
|
840
|
+
return mime ? `data:${mime};base64,${content}` : null;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
function RasterFilePreview({ src, path }: { src: string; path: string }) {
|
|
844
|
+
const [failed, setFailed] = useState(false);
|
|
845
|
+
return failed ? (
|
|
846
|
+
<Notice title="Image preview unavailable" announce="alert">
|
|
847
|
+
Could not decode {path} as an image.
|
|
848
|
+
</Notice>
|
|
849
|
+
) : (
|
|
850
|
+
<img
|
|
851
|
+
src={src}
|
|
852
|
+
alt={path}
|
|
853
|
+
onError={() => setFailed(true)}
|
|
854
|
+
className="max-w-full object-contain"
|
|
855
|
+
/>
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
|
|
629
859
|
/** Decode a base64 payload to a UTF-8 string (browser `atob` + TextDecoder). */
|
|
630
860
|
function decodeBase64Utf8(b64: string): string {
|
|
631
861
|
try {
|
|
@@ -671,7 +901,9 @@ function Notice({
|
|
|
671
901
|
</span>
|
|
672
902
|
) : null}
|
|
673
903
|
{title ? <p className="font-medium text-og-fg">{title}</p> : null}
|
|
674
|
-
<div className="leading-5">
|
|
904
|
+
<div data-contrast-audited className="leading-5">
|
|
905
|
+
{children}
|
|
906
|
+
</div>
|
|
675
907
|
</div>
|
|
676
908
|
</div>
|
|
677
909
|
);
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { TerminalCapability } from "@opengeni/sdk";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type ReactNode,
|
|
4
|
+
useEffect,
|
|
5
|
+
useLayoutEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
useSyncExternalStore,
|
|
9
|
+
} from "react";
|
|
3
10
|
import { cn } from "../lib/cn";
|
|
4
11
|
import { type TerminalStreamStatus, useTerminalStream } from "../hooks/use-terminal-stream";
|
|
5
12
|
import type { UseSandboxTerminalResult } from "../hooks/use-sandbox-terminal";
|
|
@@ -7,6 +14,7 @@ import { resolveTerminalFont, xtermThemeFromTokens } from "../lib/xterm-theme";
|
|
|
7
14
|
import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
|
|
8
15
|
import { terminalCanAcquirePty } from "../lib/terminal-capability";
|
|
9
16
|
import { attachRenderer, type RendererLoaders, type RendererTier } from "../lib/xterm-renderer";
|
|
17
|
+
import { sandboxTerminalPeers } from "../lib/workbench-peers";
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
20
|
* A COMPLETE xterm `ITheme` (subset by intent, but every field xterm colors a
|
|
@@ -114,6 +122,19 @@ type XtermLike = {
|
|
|
114
122
|
};
|
|
115
123
|
};
|
|
116
124
|
type FitAddonLike = { fit: () => void };
|
|
125
|
+
type TerminalPeerBundle = {
|
|
126
|
+
Terminal: new (options: Record<string, unknown>) => XtermLike;
|
|
127
|
+
FitAddon: new () => FitAddonLike;
|
|
128
|
+
WebLinksAddon: new (handler: (event: MouseEvent, uri: string) => void) => unknown;
|
|
129
|
+
loadWebgl?:
|
|
130
|
+
| (() => Promise<{
|
|
131
|
+
WebglAddon: new () => {
|
|
132
|
+
dispose: () => void;
|
|
133
|
+
onContextLoss?: (callback: () => void) => void;
|
|
134
|
+
};
|
|
135
|
+
}>)
|
|
136
|
+
| undefined;
|
|
137
|
+
};
|
|
117
138
|
|
|
118
139
|
export type TerminalSurfaceState =
|
|
119
140
|
| "loading"
|
|
@@ -237,6 +258,12 @@ export function SandboxTerminal({
|
|
|
237
258
|
const wroteFirehoseRef = useRef(false);
|
|
238
259
|
const bootActiveRef = useRef(false);
|
|
239
260
|
const [ready, setReady] = useState(false);
|
|
261
|
+
const [loadError, setLoadError] = useState<Error | null>(null);
|
|
262
|
+
const peerRevision = useSyncExternalStore(
|
|
263
|
+
sandboxTerminalPeers.subscribe,
|
|
264
|
+
sandboxTerminalPeers.revision,
|
|
265
|
+
sandboxTerminalPeers.revision,
|
|
266
|
+
);
|
|
240
267
|
const [inputReady, setInputReady] = useState(false);
|
|
241
268
|
const [activated, setActivated] = useState(false);
|
|
242
269
|
|
|
@@ -353,12 +380,10 @@ export function SandboxTerminal({
|
|
|
353
380
|
|
|
354
381
|
ensureXtermBaseCss();
|
|
355
382
|
|
|
383
|
+
setLoadError(null);
|
|
356
384
|
void (async () => {
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
import("@xterm/addon-fit"),
|
|
360
|
-
import("@xterm/addon-web-links"),
|
|
361
|
-
]);
|
|
385
|
+
const { Terminal, FitAddon, WebLinksAddon, loadWebgl } =
|
|
386
|
+
(await sandboxTerminalPeers.load()) as TerminalPeerBundle;
|
|
362
387
|
if (disposed) return;
|
|
363
388
|
await waitForSize(el);
|
|
364
389
|
if (disposed) return;
|
|
@@ -397,13 +422,17 @@ export function SandboxTerminal({
|
|
|
397
422
|
const failSet = forcedRendererFailures();
|
|
398
423
|
const loaders: RendererLoaders = {
|
|
399
424
|
webgl: async (onLoss) => {
|
|
425
|
+
if (disposed) throw new Error("Terminal was disposed");
|
|
400
426
|
if (failSet.has("webgl")) throw new Error("forced webgl failure");
|
|
401
|
-
|
|
427
|
+
if (!loadWebgl) throw new Error("WebGL terminal renderer is not enabled");
|
|
428
|
+
const { WebglAddon } = await loadWebgl();
|
|
429
|
+
if (disposed) throw new Error("Terminal was disposed");
|
|
402
430
|
const addon = new WebglAddon() as unknown as {
|
|
403
431
|
dispose: () => void;
|
|
404
432
|
onContextLoss?: (cb: () => void) => void;
|
|
405
433
|
};
|
|
406
434
|
addon.onContextLoss?.(() => {
|
|
435
|
+
if (disposed) return;
|
|
407
436
|
try {
|
|
408
437
|
addon.dispose();
|
|
409
438
|
} catch {
|
|
@@ -416,6 +445,7 @@ export function SandboxTerminal({
|
|
|
416
445
|
},
|
|
417
446
|
};
|
|
418
447
|
await attachRenderer("webgl", loaders, (tier) => {
|
|
448
|
+
if (disposed) return;
|
|
419
449
|
rendererRef.current = tier;
|
|
420
450
|
el.setAttribute("data-og-term-renderer", tier);
|
|
421
451
|
});
|
|
@@ -448,7 +478,9 @@ export function SandboxTerminal({
|
|
|
448
478
|
}
|
|
449
479
|
setReady(true);
|
|
450
480
|
});
|
|
451
|
-
})()
|
|
481
|
+
})().catch((cause: unknown) => {
|
|
482
|
+
if (!disposed) setLoadError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
483
|
+
});
|
|
452
484
|
|
|
453
485
|
return () => {
|
|
454
486
|
disposed = true;
|
|
@@ -461,9 +493,9 @@ export function SandboxTerminal({
|
|
|
461
493
|
bootActiveRef.current = false;
|
|
462
494
|
setReady(false);
|
|
463
495
|
};
|
|
464
|
-
// Mount
|
|
496
|
+
// Mount once per peer registration; runtime options sync without a remount.
|
|
465
497
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
466
|
-
}, []);
|
|
498
|
+
}, [peerRevision]);
|
|
467
499
|
|
|
468
500
|
// Sync stdin/cursor at runtime (NOT a remount) when interactivity flips, so the
|
|
469
501
|
// projection→PTY handoff keeps the single Terminal instance + its scrollback.
|
|
@@ -621,7 +653,12 @@ export function SandboxTerminal({
|
|
|
621
653
|
onPointerDownCapture={handleActivate}
|
|
622
654
|
onFocusCapture={handleActivate}
|
|
623
655
|
>
|
|
624
|
-
{!ready &&
|
|
656
|
+
{!ready &&
|
|
657
|
+
(loadError ? (
|
|
658
|
+
<p role="alert">{loadError.message}</p>
|
|
659
|
+
) : (
|
|
660
|
+
(placeholder ?? <TerminalPlaceholder />)
|
|
661
|
+
))}
|
|
625
662
|
{/* Kept `visibility:hidden` until the first successful fit so the first
|
|
626
663
|
VISIBLE frame is already correctly sized (no 80×24 flash — E4). */}
|
|
627
664
|
<div
|