@opengeni/react 1.0.1 → 1.0.2-canary.37202341988001
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 +660 -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-SHYKQRNX.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-26ZNDDLZ.js +453 -0
- package/dist/chunk-26ZNDDLZ.js.map +1 -0
- package/dist/chunk-3CTRFMAK.js +359 -0
- package/dist/chunk-3CTRFMAK.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-742CZ3L3.js +481 -0
- package/dist/chunk-742CZ3L3.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-6KLX2RH5.js → chunk-DO544OSV.js} +1075 -79
- package/dist/chunk-DO544OSV.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-HA46CYQK.js → chunk-EESD3PY3.js} +792 -537
- package/dist/chunk-EESD3PY3.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-EN3YTHKR.js} +4117 -3896
- package/dist/chunk-EN3YTHKR.js.map +1 -0
- package/dist/chunk-ERGYJIBB.js +21 -0
- package/dist/chunk-ERGYJIBB.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-GYVRFZDY.js +2733 -0
- package/dist/chunk-GYVRFZDY.js.map +1 -0
- package/dist/{chunk-LLOLUHVG.js → chunk-HDJWDK7W.js} +1358 -2746
- package/dist/chunk-HDJWDK7W.js.map +1 -0
- package/dist/chunk-I7IWRQLN.js +1608 -0
- package/dist/chunk-I7IWRQLN.js.map +1 -0
- package/dist/chunk-IT4BJUGF.js +13055 -0
- package/dist/chunk-IT4BJUGF.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-J6DBS4T3.js +371 -0
- package/dist/chunk-J6DBS4T3.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-JIQYUGVL.js} +1331 -1163
- package/dist/chunk-JIQYUGVL.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-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
- package/dist/chunk-PNY3JKBJ.js.map +1 -0
- package/dist/chunk-RHREZ7BO.js +11 -0
- package/dist/chunk-RHREZ7BO.js.map +1 -0
- package/dist/chunk-RLUSC2WA.js +299 -0
- package/dist/chunk-RLUSC2WA.js.map +1 -0
- package/dist/{chunk-IGC6A2ZI.js → chunk-RSI7XYXL.js} +777 -246
- package/dist/chunk-RSI7XYXL.js.map +1 -0
- package/dist/chunk-SCOTPE2I.js +589 -0
- package/dist/chunk-SCOTPE2I.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-TKOTKRWY.js} +5 -4
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-TKOTKRWY.js.map} +1 -1
- 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-WGXVEJO5.js +319 -0
- package/dist/chunk-WGXVEJO5.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-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-YM2DE7BQ.js +3124 -0
- package/dist/chunk-YM2DE7BQ.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-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 +58 -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 +89 -0
- package/dist/components/session-list.d.ts +36 -0
- package/dist/components/session-mcp-capability-card.d.ts +41 -0
- package/dist/components/session-proxy-scope.d.ts +21 -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-6SRGWRUX.js +19 -0
- package/dist/computer-viewer-6SRGWRUX.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 +2238 -6201
- 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-HTRIS4KJ.js +117 -0
- package/dist/latest-question-HTRIS4KJ.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-M54ISBMN.js +14 -0
- package/dist/model-policy-picker-menu-M54ISBMN.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-GORZOUUJ.js +20 -0
- package/dist/sandbox-files-GORZOUUJ.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 +34 -3
- package/dist/timeline/types.d.ts +147 -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 +2754 -665
- 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 +338 -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 +526 -0
- package/src/components/session-list.tsx +250 -0
- package/src/components/session-mcp-capability-card.tsx +680 -0
- package/src/components/session-proxy-scope.tsx +92 -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-video-artifact-playback.ts +1 -1
- 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 +4 -3
- 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 +1609 -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 +218 -44
- package/src/timeline/types.ts +192 -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-SHYKQRNX.js.map} +0 -0
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
PauseIcon,
|
|
10
10
|
PlayIcon,
|
|
11
11
|
RotateCwIcon,
|
|
12
|
+
SquareIcon,
|
|
12
13
|
XIcon,
|
|
13
14
|
} from "lucide-react";
|
|
14
15
|
import { AnimatePresence, motion } from "motion/react";
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
useContext,
|
|
21
22
|
useEffect,
|
|
22
23
|
useId,
|
|
24
|
+
useLayoutEffect,
|
|
23
25
|
useMemo,
|
|
24
26
|
useRef,
|
|
25
27
|
useState,
|
|
@@ -35,6 +37,7 @@ import {
|
|
|
35
37
|
type RefObject,
|
|
36
38
|
} from "react";
|
|
37
39
|
import { argHint, defaultCommands } from "../commands/registry";
|
|
40
|
+
import { useErrorMessage } from "../lib/error-message";
|
|
38
41
|
import type { Notice, SlashCommand } from "../commands/types";
|
|
39
42
|
import type { ComposerState } from "../hooks/use-composer";
|
|
40
43
|
import { shouldSteerOnKey, shouldSubmitOnKey } from "../hooks/use-composer";
|
|
@@ -51,6 +54,7 @@ import {
|
|
|
51
54
|
} from "../lib/composer-responsive-context";
|
|
52
55
|
import { composerSubmissionErrorMessage, formatBytes, formatRelativeTime } from "../lib/format";
|
|
53
56
|
import type { PickerModelRow } from "../model-policy";
|
|
57
|
+
import { useLightboxOptional } from "../timeline/screenshot-lightbox";
|
|
54
58
|
import { OPEN_WORKSTREAM_CONTROL_EVENT } from "../workstream-control-event";
|
|
55
59
|
import { CommandPalette as CommandPaletteView } from "./command-palette";
|
|
56
60
|
import { ModelPicker as ModelPickerView } from "./model-picker";
|
|
@@ -72,7 +76,16 @@ function ComposerTip({
|
|
|
72
76
|
|
|
73
77
|
export type ComposerDelivery = Pick<
|
|
74
78
|
ComposerState,
|
|
75
|
-
|
|
79
|
+
| "value"
|
|
80
|
+
| "setValue"
|
|
81
|
+
| "send"
|
|
82
|
+
| "steer"
|
|
83
|
+
| "sending"
|
|
84
|
+
| "canSend"
|
|
85
|
+
| "error"
|
|
86
|
+
| "clearError"
|
|
87
|
+
| "annotations"
|
|
88
|
+
| "requestAnnotationReview"
|
|
76
89
|
>;
|
|
77
90
|
|
|
78
91
|
export type ComposerDraftState = Pick<
|
|
@@ -106,10 +119,14 @@ export type ChatComposerMessages = {
|
|
|
106
119
|
attachFiles: string;
|
|
107
120
|
pauseAriaLabel: string;
|
|
108
121
|
pauseTitle: string;
|
|
122
|
+
/** Stop control shown while a response runs (`runControl="stop"`). */
|
|
123
|
+
stopAriaLabel?: string | undefined;
|
|
124
|
+
stopTitle?: string | undefined;
|
|
109
125
|
sendMessageAriaLabel: string;
|
|
110
126
|
sendAndResumeAriaLabel: string;
|
|
111
127
|
sendTitle: string;
|
|
112
128
|
sendAndResumeTitle: string;
|
|
129
|
+
annotationNotesRequired: string;
|
|
113
130
|
workspacePaused: string;
|
|
114
131
|
pausedHere: string;
|
|
115
132
|
parentBlocker: string;
|
|
@@ -134,6 +151,11 @@ export type ChatComposerMessages = {
|
|
|
134
151
|
removeRestoredResource: (index: number) => string;
|
|
135
152
|
uploading: string;
|
|
136
153
|
uploadFailed: string;
|
|
154
|
+
previewAttachment: (name: string) => string;
|
|
155
|
+
previewUnavailable?: string | undefined;
|
|
156
|
+
attachmentPreviewLabel: string;
|
|
157
|
+
downloadAttachment: (name: string) => string;
|
|
158
|
+
closeAttachmentPreview: string;
|
|
137
159
|
retryAttachment: (name: string) => string;
|
|
138
160
|
retryUpload: string;
|
|
139
161
|
removeAttachment: (name: string) => string;
|
|
@@ -156,9 +178,11 @@ export type ChatComposerMessages = {
|
|
|
156
178
|
|
|
157
179
|
export const defaultChatComposerMessages: ChatComposerMessages = {
|
|
158
180
|
messagePlaceholder: "Message the agent…",
|
|
159
|
-
pausedPlaceholder: "
|
|
181
|
+
pausedPlaceholder: "Message the agent — it will wait in the queue…",
|
|
160
182
|
inputLabel: "Message the agent",
|
|
161
|
-
|
|
183
|
+
// Shortcuts live in the send button's title; the footer stays quiet unless
|
|
184
|
+
// the host supplies its own hint.
|
|
185
|
+
keyboardHint: "",
|
|
162
186
|
slashCommandBlocked:
|
|
163
187
|
"That's a slash command — press Enter in the command list to run it, or edit the line to send a message.",
|
|
164
188
|
controlChangedError:
|
|
@@ -168,19 +192,22 @@ export const defaultChatComposerMessages: ChatComposerMessages = {
|
|
|
168
192
|
attachFiles: "Attach files",
|
|
169
193
|
pauseAriaLabel: "Pause this workstream",
|
|
170
194
|
pauseTitle: "Pause this workstream; queued prompts and approvals are preserved",
|
|
195
|
+
stopAriaLabel: "Stop",
|
|
196
|
+
stopTitle: "Stop the response",
|
|
171
197
|
sendMessageAriaLabel: "Send message",
|
|
172
|
-
sendAndResumeAriaLabel: "
|
|
198
|
+
sendAndResumeAriaLabel: "Add message to queue",
|
|
173
199
|
sendTitle: "Queue message (Enter); steer with Cmd/Ctrl+Enter",
|
|
174
|
-
sendAndResumeTitle: "
|
|
200
|
+
sendAndResumeTitle: "Add to queue (Enter); steer now with Cmd/Ctrl+Enter",
|
|
201
|
+
annotationNotesRequired: "Add a note to each quote before sending.",
|
|
175
202
|
workspacePaused: "Workspace paused",
|
|
176
203
|
pausedHere: "Paused here",
|
|
177
204
|
parentBlocker: "parent",
|
|
178
205
|
narrowerPause: "a narrower pause",
|
|
179
206
|
pausedBy: (displayName) => `Paused by ${displayName}`,
|
|
180
207
|
queuedAhead: (count) =>
|
|
181
|
-
|
|
182
|
-
resumingAndSending: "
|
|
183
|
-
nextMessageResumes: "
|
|
208
|
+
`${count} waiting prompt${count === 1 ? "" : "s"}; your message joins the queue.`,
|
|
209
|
+
resumingAndSending: "Sending…",
|
|
210
|
+
nextMessageResumes: "Messages wait in the queue until you resume.",
|
|
184
211
|
resumeThisWorkstream: "Resume this workstream",
|
|
185
212
|
resumeShort: "Resume",
|
|
186
213
|
hidePauseDetails: "Hide pause details",
|
|
@@ -197,6 +224,11 @@ export const defaultChatComposerMessages: ChatComposerMessages = {
|
|
|
197
224
|
removeRestoredResource: (index) => `Remove restored resource ${index + 1}`,
|
|
198
225
|
uploading: "Uploading",
|
|
199
226
|
uploadFailed: "Upload failed",
|
|
227
|
+
previewAttachment: (name) => `Preview ${name}`,
|
|
228
|
+
previewUnavailable: "Preview unavailable",
|
|
229
|
+
attachmentPreviewLabel: "Attachment preview",
|
|
230
|
+
downloadAttachment: (name) => `Download ${name}`,
|
|
231
|
+
closeAttachmentPreview: "Close",
|
|
200
232
|
retryAttachment: (name) => `Retry ${name}`,
|
|
201
233
|
retryUpload: "Retry upload",
|
|
202
234
|
removeAttachment: (name) => `Remove ${name}`,
|
|
@@ -225,9 +257,21 @@ export type ComposerSubmitBlocker =
|
|
|
225
257
|
| "attachment"
|
|
226
258
|
| "sending"
|
|
227
259
|
| "command"
|
|
260
|
+
| "annotations"
|
|
228
261
|
| "empty"
|
|
229
262
|
| null;
|
|
230
263
|
|
|
264
|
+
/**
|
|
265
|
+
* How the composer offers run control.
|
|
266
|
+
* - `pause`: the workstream Pause control and paused-state strip (default; the
|
|
267
|
+
* OpenGeni console).
|
|
268
|
+
* - `stop`: a Stop control only while a response runs. Stopping pauses this
|
|
269
|
+
* conversation; the next message continues it, so people never see a paused
|
|
270
|
+
* state they have to resume. Pauses applied elsewhere still show.
|
|
271
|
+
* - `none`: no run control.
|
|
272
|
+
*/
|
|
273
|
+
export type ComposerRunControl = "pause" | "stop" | "none";
|
|
274
|
+
|
|
231
275
|
export type UseChatComposerControllerOptions = {
|
|
232
276
|
delivery: ComposerDelivery;
|
|
233
277
|
draft?: ComposerDraftState | undefined;
|
|
@@ -243,6 +287,10 @@ export type UseChatComposerControllerOptions = {
|
|
|
243
287
|
onClearView?: (() => void) | undefined;
|
|
244
288
|
onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;
|
|
245
289
|
messages?: Partial<ChatComposerMessages> | undefined;
|
|
290
|
+
/** Run control presentation. Defaults to `pause`. */
|
|
291
|
+
runControl?: ComposerRunControl | undefined;
|
|
292
|
+
/** A response is in progress; shows the Stop control under `runControl="stop"`. */
|
|
293
|
+
running?: boolean | undefined;
|
|
246
294
|
};
|
|
247
295
|
|
|
248
296
|
/**
|
|
@@ -269,7 +317,7 @@ function measureComposerContentHeight(textarea: HTMLTextAreaElement): number {
|
|
|
269
317
|
mirror.tabIndex = -1;
|
|
270
318
|
mirror.rows = 1;
|
|
271
319
|
mirror.style.cssText =
|
|
272
|
-
"position:
|
|
320
|
+
"position:fixed;top:0;left:-100000px;visibility:hidden;pointer-events:none;height:auto;min-height:0;max-height:none;overflow:hidden;z-index:-1;";
|
|
273
321
|
composerHeightMirror = mirror;
|
|
274
322
|
}
|
|
275
323
|
|
|
@@ -349,7 +397,10 @@ export function useChatComposerController({
|
|
|
349
397
|
onClearView,
|
|
350
398
|
onPaste,
|
|
351
399
|
messages: messageOverrides,
|
|
400
|
+
runControl = "pause",
|
|
401
|
+
running = false,
|
|
352
402
|
}: UseChatComposerControllerOptions) {
|
|
403
|
+
const formatError = useErrorMessage();
|
|
353
404
|
const messages = useMemo(
|
|
354
405
|
() => ({ ...defaultChatComposerMessages, ...messageOverrides }),
|
|
355
406
|
[messageOverrides],
|
|
@@ -360,13 +411,55 @@ export function useChatComposerController({
|
|
|
360
411
|
const pauseButtonRef = useRef<HTMLButtonElement | null>(null);
|
|
361
412
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
|
362
413
|
const listboxId = useId();
|
|
363
|
-
const
|
|
414
|
+
const controlPaused = effectiveControl?.state === "paused";
|
|
415
|
+
// Set when this composer's Stop paused the conversation; cleared once it runs
|
|
416
|
+
// again. Pauses from anyone or anywhere else are never reinterpreted.
|
|
417
|
+
const [stoppedHere, setStoppedHere] = useState(false);
|
|
418
|
+
useEffect(() => {
|
|
419
|
+
if (!controlPaused) setStoppedHere(false);
|
|
420
|
+
}, [controlPaused]);
|
|
421
|
+
// Under Stop, the stopped response is not a state to manage: hide it and let
|
|
422
|
+
// the next message continue (a Steer resumes a paused branch). It applies
|
|
423
|
+
// only to this conversation's own pause with nothing queued behind it.
|
|
424
|
+
const resumesOnSend =
|
|
425
|
+
runControl === "stop" &&
|
|
426
|
+
stoppedHere &&
|
|
427
|
+
controlPaused &&
|
|
428
|
+
effectiveControl?.directState === "paused" &&
|
|
429
|
+
effectiveControl.additionalBlockerCount === 0 &&
|
|
430
|
+
queuedAheadCount === 0;
|
|
431
|
+
const paused = controlPaused && !resumesOnSend;
|
|
364
432
|
const [controlDetailsOpen, setControlDetailsOpen] = useState(false);
|
|
365
433
|
const [paletteMounted, setPaletteMounted] = useState(false);
|
|
366
434
|
const [submitting, setSubmitting] = useState(false);
|
|
367
435
|
const submittingRef = useRef(false);
|
|
368
436
|
const controlOperationRef = useRef(false);
|
|
437
|
+
const deliveryValue = delivery.value;
|
|
438
|
+
const setDeliveryValue = delivery.setValue;
|
|
369
439
|
const mountedRef = useRef(true);
|
|
440
|
+
const deliveredValueRef = useRef(deliveryValue);
|
|
441
|
+
const liveValueRef = useRef(deliveryValue);
|
|
442
|
+
const [renderedValue, setRenderedValue] = useState(deliveryValue);
|
|
443
|
+
const deliveryChanged = deliveryValue !== deliveredValueRef.current;
|
|
444
|
+
if (deliveryChanged) {
|
|
445
|
+
deliveredValueRef.current = deliveryValue;
|
|
446
|
+
liveValueRef.current = deliveryValue;
|
|
447
|
+
}
|
|
448
|
+
const setComposerValue = useCallback(
|
|
449
|
+
(next: string) => {
|
|
450
|
+
liveValueRef.current = next;
|
|
451
|
+
setRenderedValue(next);
|
|
452
|
+
setDeliveryValue(next);
|
|
453
|
+
},
|
|
454
|
+
[setDeliveryValue],
|
|
455
|
+
);
|
|
456
|
+
const visibleValue = deliveryChanged ? deliveryValue : renderedValue;
|
|
457
|
+
|
|
458
|
+
useLayoutEffect(() => {
|
|
459
|
+
if (renderedValue !== liveValueRef.current) {
|
|
460
|
+
setRenderedValue(liveValueRef.current);
|
|
461
|
+
}
|
|
462
|
+
}, [deliveryValue, renderedValue]);
|
|
370
463
|
|
|
371
464
|
useEffect(() => {
|
|
372
465
|
mountedRef.current = true;
|
|
@@ -400,7 +493,6 @@ export function useChatComposerController({
|
|
|
400
493
|
}, [id, paused]);
|
|
401
494
|
|
|
402
495
|
const blockedByAttachment = attachments?.hasUnresolved === true;
|
|
403
|
-
const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;
|
|
404
496
|
|
|
405
497
|
const [dragging, setDragging] = useState(false);
|
|
406
498
|
const dragCarriesFiles = (event: { dataTransfer: DataTransfer | null }): boolean =>
|
|
@@ -409,9 +501,9 @@ export function useChatComposerController({
|
|
|
409
501
|
(event: DragEvent<HTMLDivElement>) => {
|
|
410
502
|
if (!attachments || !dragCarriesFiles(event)) return;
|
|
411
503
|
event.preventDefault();
|
|
412
|
-
setDragging(true);
|
|
504
|
+
if (!disabled) setDragging(true);
|
|
413
505
|
},
|
|
414
|
-
[attachments],
|
|
506
|
+
[attachments, disabled],
|
|
415
507
|
);
|
|
416
508
|
const handleDragLeave = useCallback(
|
|
417
509
|
(event: DragEvent<HTMLDivElement>) => {
|
|
@@ -426,11 +518,16 @@ export function useChatComposerController({
|
|
|
426
518
|
if (!attachments || !dragCarriesFiles(event)) return;
|
|
427
519
|
event.preventDefault();
|
|
428
520
|
setDragging(false);
|
|
429
|
-
if (event.dataTransfer.files.length > 0)
|
|
521
|
+
if (!disabled && event.dataTransfer.files.length > 0)
|
|
522
|
+
attachments.addFiles(event.dataTransfer.files);
|
|
430
523
|
},
|
|
431
|
-
[attachments],
|
|
524
|
+
[attachments, disabled],
|
|
432
525
|
);
|
|
433
526
|
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
if (disabled) setDragging(false);
|
|
529
|
+
}, [disabled]);
|
|
530
|
+
|
|
434
531
|
const [notice, setNotice] = useState<Notice | null>(null);
|
|
435
532
|
const [helpOpen, setHelpOpen] = useState(false);
|
|
436
533
|
const [confirmState, setConfirmState] = useState<ConfirmState>(null);
|
|
@@ -468,7 +565,7 @@ export function useChatComposerController({
|
|
|
468
565
|
applyComposerTextareaHeight(textarea, 220);
|
|
469
566
|
});
|
|
470
567
|
}, []);
|
|
471
|
-
useEffect(() => resizeInput(), [
|
|
568
|
+
useEffect(() => resizeInput(), [resizeInput, visibleValue]);
|
|
472
569
|
useEffect(
|
|
473
570
|
() => () => {
|
|
474
571
|
if (resizeInputRafRef.current !== null) {
|
|
@@ -505,11 +602,14 @@ export function useChatComposerController({
|
|
|
505
602
|
commands,
|
|
506
603
|
context: commandContext,
|
|
507
604
|
handlers,
|
|
508
|
-
value:
|
|
509
|
-
setValue:
|
|
605
|
+
value: visibleValue,
|
|
606
|
+
setValue: setComposerValue,
|
|
510
607
|
});
|
|
511
608
|
const paletteEnabled = commandContext !== undefined;
|
|
512
609
|
const commandDraftBlocked = paletteEnabled && palette.isCommandDraft;
|
|
610
|
+
const annotationsIncomplete = (delivery.annotations ?? []).some(
|
|
611
|
+
(annotation) => annotation.note.trim().length === 0,
|
|
612
|
+
);
|
|
513
613
|
|
|
514
614
|
const submitBlocker: ComposerSubmitBlocker = disabled
|
|
515
615
|
? "disabled"
|
|
@@ -519,9 +619,11 @@ export function useChatComposerController({
|
|
|
519
619
|
? "sending"
|
|
520
620
|
: commandDraftBlocked
|
|
521
621
|
? "command"
|
|
522
|
-
:
|
|
523
|
-
?
|
|
524
|
-
:
|
|
622
|
+
: annotationsIncomplete
|
|
623
|
+
? "annotations"
|
|
624
|
+
: delivery.canSend
|
|
625
|
+
? null
|
|
626
|
+
: "empty";
|
|
525
627
|
const canSubmit = submitBlocker === null;
|
|
526
628
|
|
|
527
629
|
const submit = useCallback(
|
|
@@ -533,23 +635,31 @@ export function useChatComposerController({
|
|
|
533
635
|
}
|
|
534
636
|
if (disabled || blockedByAttachment || delivery.sending || submittingRef.current)
|
|
535
637
|
return false;
|
|
536
|
-
if (
|
|
638
|
+
if (annotationsIncomplete) {
|
|
639
|
+
setNotice({ tone: "error", message: messages.annotationNotesRequired });
|
|
640
|
+
delivery.clearError();
|
|
641
|
+
delivery.requestAnnotationReview?.();
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
if (!delivery.canSend) return false;
|
|
537
645
|
submittingRef.current = true;
|
|
538
646
|
setSubmitting(true);
|
|
539
647
|
try {
|
|
540
|
-
return mode === "steer" ? await delivery.steer() : await delivery.send();
|
|
648
|
+
return mode === "steer" || resumesOnSend ? await delivery.steer() : await delivery.send();
|
|
541
649
|
} finally {
|
|
542
650
|
submittingRef.current = false;
|
|
543
651
|
if (mountedRef.current) setSubmitting(false);
|
|
544
652
|
}
|
|
545
653
|
},
|
|
546
654
|
[
|
|
655
|
+
annotationsIncomplete,
|
|
547
656
|
blockedByAttachment,
|
|
548
657
|
commandDraftBlocked,
|
|
549
658
|
delivery,
|
|
550
659
|
disabled,
|
|
551
|
-
|
|
660
|
+
messages.annotationNotesRequired,
|
|
552
661
|
messages.slashCommandBlocked,
|
|
662
|
+
resumesOnSend,
|
|
553
663
|
],
|
|
554
664
|
);
|
|
555
665
|
|
|
@@ -564,17 +674,18 @@ export function useChatComposerController({
|
|
|
564
674
|
);
|
|
565
675
|
const handlePaste = useCallback(
|
|
566
676
|
(event: ClipboardEvent<HTMLTextAreaElement>) => {
|
|
677
|
+
if (disabled) return;
|
|
567
678
|
onPaste?.(event);
|
|
568
679
|
attachments?.addFromPaste(event);
|
|
569
680
|
},
|
|
570
|
-
[attachments, onPaste],
|
|
681
|
+
[attachments, disabled, onPaste],
|
|
571
682
|
);
|
|
572
683
|
const handleFileChange = useCallback(
|
|
573
684
|
(event: ChangeEvent<HTMLInputElement>) => {
|
|
574
|
-
if (event.target.files) attachments?.addFiles(event.target.files);
|
|
685
|
+
if (!disabled && event.target.files) attachments?.addFiles(event.target.files);
|
|
575
686
|
event.target.value = "";
|
|
576
687
|
},
|
|
577
|
-
[attachments],
|
|
688
|
+
[attachments, disabled],
|
|
578
689
|
);
|
|
579
690
|
|
|
580
691
|
const helpCommands = useMemo(
|
|
@@ -597,7 +708,10 @@ export function useChatComposerController({
|
|
|
597
708
|
tone: "error" as const,
|
|
598
709
|
message: /control changed|paused while/i.test(delivery.error.message)
|
|
599
710
|
? messages.controlChangedError
|
|
600
|
-
:
|
|
711
|
+
: formatError(
|
|
712
|
+
delivery.error,
|
|
713
|
+
composerSubmissionErrorMessage(delivery.error) || messages.sendFailedError,
|
|
714
|
+
),
|
|
601
715
|
}
|
|
602
716
|
: null);
|
|
603
717
|
useEffect(() => {
|
|
@@ -608,6 +722,12 @@ export function useChatComposerController({
|
|
|
608
722
|
);
|
|
609
723
|
return () => window.clearTimeout(timer);
|
|
610
724
|
}, [notice]);
|
|
725
|
+
useEffect(() => {
|
|
726
|
+
if (annotationsIncomplete) return;
|
|
727
|
+
setNotice((current) =>
|
|
728
|
+
current?.message === messages.annotationNotesRequired ? null : current,
|
|
729
|
+
);
|
|
730
|
+
}, [annotationsIncomplete, messages.annotationNotesRequired]);
|
|
611
731
|
|
|
612
732
|
const runControlOperation = useCallback(async (operation: () => Promise<void>) => {
|
|
613
733
|
if (controlOperationRef.current) return false;
|
|
@@ -642,6 +762,12 @@ export function useChatComposerController({
|
|
|
642
762
|
[control, runControlOperation],
|
|
643
763
|
);
|
|
644
764
|
|
|
765
|
+
const stop = useCallback(async (): Promise<boolean> => {
|
|
766
|
+
const stopped = await pause();
|
|
767
|
+
if (stopped && mountedRef.current) setStoppedHere(true);
|
|
768
|
+
return stopped;
|
|
769
|
+
}, [pause]);
|
|
770
|
+
|
|
645
771
|
return {
|
|
646
772
|
id,
|
|
647
773
|
rootRef,
|
|
@@ -666,9 +792,12 @@ export function useChatComposerController({
|
|
|
666
792
|
removeRestoredResource: draft?.removeRestoredResource,
|
|
667
793
|
resolveDraftConflict: draft?.resolveDraftConflict,
|
|
668
794
|
hasControl: control !== undefined,
|
|
795
|
+
runControl,
|
|
796
|
+
running,
|
|
669
797
|
pausing: control?.pausing ?? false,
|
|
670
798
|
resuming: control?.resuming ?? false,
|
|
671
799
|
pause,
|
|
800
|
+
stop,
|
|
672
801
|
resume,
|
|
673
802
|
resumeScope,
|
|
674
803
|
paused,
|
|
@@ -696,8 +825,8 @@ export function useChatComposerController({
|
|
|
696
825
|
handlePaste,
|
|
697
826
|
handleFileChange,
|
|
698
827
|
focusInput: () => textareaRef.current?.focus(),
|
|
699
|
-
setValue:
|
|
700
|
-
value:
|
|
828
|
+
setValue: setComposerValue,
|
|
829
|
+
value: visibleValue,
|
|
701
830
|
};
|
|
702
831
|
}
|
|
703
832
|
|
|
@@ -909,8 +1038,11 @@ export function Attachments() {
|
|
|
909
1038
|
<AttachmentChips
|
|
910
1039
|
attachments={controller.attachments.attachments}
|
|
911
1040
|
messages={controller.messages}
|
|
1041
|
+
disabled={controller.disabled}
|
|
912
1042
|
onRemove={controller.attachments.remove}
|
|
913
1043
|
onRetry={controller.attachments.retry}
|
|
1044
|
+
onRetainPreview={controller.attachments.retainPreview}
|
|
1045
|
+
onLoadPreview={controller.attachments.loadPreview}
|
|
914
1046
|
/>
|
|
915
1047
|
);
|
|
916
1048
|
}
|
|
@@ -928,6 +1060,26 @@ type OwnedInputProps =
|
|
|
928
1060
|
| "aria-keyshortcuts";
|
|
929
1061
|
export type ComposerInputProps = Omit<ComponentPropsWithoutRef<"textarea">, OwnedInputProps>;
|
|
930
1062
|
|
|
1063
|
+
const EDITING_FOCUS_SELECTOR =
|
|
1064
|
+
'input, textarea, select, [contenteditable="true"], [role="textbox"]';
|
|
1065
|
+
const POPUP_FOCUS_SELECTOR =
|
|
1066
|
+
'[role="menu"], [role="menubar"], [role="listbox"], [role="dialog"], [role="alertdialog"]';
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Initial focus is a convenience, not authority to move focus the person has
|
|
1070
|
+
* placed elsewhere. It yields to a field they started editing and to an open
|
|
1071
|
+
* menu, listbox, or dialog that does not contain the composer: moving focus
|
|
1072
|
+
* behind a non-modal popup dismisses it, and a modal surface owns focus until
|
|
1073
|
+
* it closes.
|
|
1074
|
+
*/
|
|
1075
|
+
function focusBelongsElsewhere(textarea: HTMLTextAreaElement): boolean {
|
|
1076
|
+
const active = textarea.ownerDocument.activeElement;
|
|
1077
|
+
if (!active || active === textarea) return false;
|
|
1078
|
+
if (active.closest(EDITING_FOCUS_SELECTOR)) return true;
|
|
1079
|
+
const popup = active.closest(POPUP_FOCUS_SELECTOR);
|
|
1080
|
+
return popup !== null && !popup.contains(textarea);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
931
1083
|
export const Input = forwardRef<HTMLTextAreaElement, ComposerInputProps>(function ComposerInput(
|
|
932
1084
|
{ rows = 1, placeholder, className, "aria-label": ariaLabel, autoFocus = false, ...props },
|
|
933
1085
|
forwardedRef,
|
|
@@ -937,14 +1089,17 @@ export const Input = forwardRef<HTMLTextAreaElement, ComposerInputProps>(functio
|
|
|
937
1089
|
const paletteOpen =
|
|
938
1090
|
controller.paletteEnabled && controller.paletteMounted && controller.palette.open;
|
|
939
1091
|
|
|
940
|
-
//
|
|
941
|
-
// hydrate)
|
|
1092
|
+
// Focus once the controller is interactive. The textarea can mount disabled
|
|
1093
|
+
// (create-session draft hydrate), and the route can finish loading after the
|
|
1094
|
+
// person has already moved on, so this deliberately does not use the native
|
|
1095
|
+
// autoFocus attribute: that would take focus at mount without the guard.
|
|
942
1096
|
useEffect(() => {
|
|
943
1097
|
if (!autoFocus || controller.disabled || autoFocusedRef.current) return;
|
|
944
1098
|
const frame = window.requestAnimationFrame(() => {
|
|
945
1099
|
const textarea = controller.textareaRef.current;
|
|
946
1100
|
if (!textarea || textarea.disabled) return;
|
|
947
1101
|
autoFocusedRef.current = true;
|
|
1102
|
+
if (focusBelongsElsewhere(textarea)) return;
|
|
948
1103
|
textarea.focus();
|
|
949
1104
|
});
|
|
950
1105
|
return () => window.cancelAnimationFrame(frame);
|
|
@@ -965,7 +1120,6 @@ export const Input = forwardRef<HTMLTextAreaElement, ComposerInputProps>(functio
|
|
|
965
1120
|
: (placeholder ?? controller.messages.messagePlaceholder)
|
|
966
1121
|
}
|
|
967
1122
|
disabled={controller.disabled}
|
|
968
|
-
autoFocus={autoFocus && !controller.disabled}
|
|
969
1123
|
aria-label={ariaLabel ?? controller.messages.inputLabel}
|
|
970
1124
|
aria-keyshortcuts="Enter Meta+Enter Control+Enter Shift+Enter"
|
|
971
1125
|
aria-autocomplete={
|
|
@@ -1176,12 +1330,19 @@ export const PauseButton = forwardRef<HTMLButtonElement, ComposerPauseButtonProp
|
|
|
1176
1330
|
ref,
|
|
1177
1331
|
) {
|
|
1178
1332
|
const controller = useComposerController();
|
|
1179
|
-
if (
|
|
1333
|
+
if (
|
|
1334
|
+
controller.runControl !== "pause" ||
|
|
1335
|
+
!controller.effectiveControl ||
|
|
1336
|
+
controller.paused ||
|
|
1337
|
+
!controller.hasControl
|
|
1338
|
+
)
|
|
1339
|
+
return null;
|
|
1180
1340
|
const busy = controller.pausing || controller.resuming;
|
|
1181
1341
|
const tip = title ?? controller.messages.pauseTitle;
|
|
1182
1342
|
return (
|
|
1183
1343
|
<ComposerTip tip={tip}>
|
|
1184
1344
|
<button
|
|
1345
|
+
data-analytics-action="pause"
|
|
1185
1346
|
{...props}
|
|
1186
1347
|
ref={mergeRefs(controller.pauseButtonRef, ref)}
|
|
1187
1348
|
type="button"
|
|
@@ -1208,6 +1369,62 @@ export const PauseButton = forwardRef<HTMLButtonElement, ComposerPauseButtonProp
|
|
|
1208
1369
|
},
|
|
1209
1370
|
);
|
|
1210
1371
|
|
|
1372
|
+
export type ComposerStopButtonProps = Omit<
|
|
1373
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
1374
|
+
OwnedButtonProps
|
|
1375
|
+
>;
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* Stop the running response. Rendered only under `runControl="stop"` while a
|
|
1379
|
+
* response runs; stopping pauses this conversation and the next message
|
|
1380
|
+
* continues it.
|
|
1381
|
+
*/
|
|
1382
|
+
export const StopButton = forwardRef<HTMLButtonElement, ComposerStopButtonProps>(
|
|
1383
|
+
function ComposerStopButton(
|
|
1384
|
+
{ className, "aria-label": ariaLabel, title, children, ...props },
|
|
1385
|
+
ref,
|
|
1386
|
+
) {
|
|
1387
|
+
const controller = useComposerController();
|
|
1388
|
+
if (
|
|
1389
|
+
controller.runControl !== "stop" ||
|
|
1390
|
+
!controller.running ||
|
|
1391
|
+
!controller.hasControl ||
|
|
1392
|
+
controller.effectiveControl?.state === "paused"
|
|
1393
|
+
)
|
|
1394
|
+
return null;
|
|
1395
|
+
const busy = controller.pausing;
|
|
1396
|
+
const label = ariaLabel ?? controller.messages.stopAriaLabel ?? "Stop";
|
|
1397
|
+
const tip = title ?? controller.messages.stopTitle ?? label;
|
|
1398
|
+
return (
|
|
1399
|
+
<ComposerTip tip={tip}>
|
|
1400
|
+
<button
|
|
1401
|
+
data-analytics-action="stop"
|
|
1402
|
+
data-og-composer-stop=""
|
|
1403
|
+
{...props}
|
|
1404
|
+
ref={ref}
|
|
1405
|
+
type="button"
|
|
1406
|
+
onClick={() => void controller.stop()}
|
|
1407
|
+
disabled={busy}
|
|
1408
|
+
aria-label={label}
|
|
1409
|
+
className={cn(
|
|
1410
|
+
"inline-flex size-8 items-center justify-center rounded-og-md border border-og-border pointer-coarse:size-11",
|
|
1411
|
+
"bg-og-surface-1 text-og-fg transition-colors duration-150",
|
|
1412
|
+
"hover:bg-og-surface-2 disabled:opacity-50",
|
|
1413
|
+
className,
|
|
1414
|
+
)}
|
|
1415
|
+
>
|
|
1416
|
+
{children ??
|
|
1417
|
+
(busy ? (
|
|
1418
|
+
<LoaderCircleIcon className="size-3.5 animate-og-spin" />
|
|
1419
|
+
) : (
|
|
1420
|
+
<SquareIcon className="size-3 fill-current" />
|
|
1421
|
+
))}
|
|
1422
|
+
</button>
|
|
1423
|
+
</ComposerTip>
|
|
1424
|
+
);
|
|
1425
|
+
},
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1211
1428
|
export type ComposerSendButtonProps = Omit<
|
|
1212
1429
|
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
1213
1430
|
OwnedButtonProps
|
|
@@ -1221,10 +1438,15 @@ export const SendButton = forwardRef<HTMLButtonElement, ComposerSendButtonProps>
|
|
|
1221
1438
|
const controller = useComposerController();
|
|
1222
1439
|
const tip =
|
|
1223
1440
|
title ??
|
|
1224
|
-
(controller.
|
|
1441
|
+
(controller.submitBlocker === "annotations"
|
|
1442
|
+
? controller.messages.annotationNotesRequired
|
|
1443
|
+
: controller.paused
|
|
1444
|
+
? controller.messages.sendAndResumeTitle
|
|
1445
|
+
: controller.messages.sendTitle);
|
|
1225
1446
|
return (
|
|
1226
1447
|
<ComposerTip tip={tip}>
|
|
1227
1448
|
<button
|
|
1449
|
+
data-analytics-action="send"
|
|
1228
1450
|
{...props}
|
|
1229
1451
|
ref={ref}
|
|
1230
1452
|
type="button"
|
|
@@ -1239,10 +1461,10 @@ export const SendButton = forwardRef<HTMLButtonElement, ComposerSendButtonProps>
|
|
|
1239
1461
|
}
|
|
1240
1462
|
className={cn(
|
|
1241
1463
|
"inline-flex size-8 items-center justify-center rounded-og-md pointer-coarse:size-11",
|
|
1242
|
-
"bg-og-
|
|
1464
|
+
"border border-og-primary-border bg-og-primary text-og-primary-fg",
|
|
1243
1465
|
"transition-[background-color,transform,opacity] duration-150 ease-og-spring",
|
|
1244
|
-
"hover:bg-og-
|
|
1245
|
-
"disabled:cursor-not-allowed disabled:
|
|
1466
|
+
"hover:bg-og-primary-hover active:scale-95",
|
|
1467
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1246
1468
|
className,
|
|
1247
1469
|
)}
|
|
1248
1470
|
>
|
|
@@ -1399,7 +1621,7 @@ function WorkstreamPausedStrip({
|
|
|
1399
1621
|
<button
|
|
1400
1622
|
type="button"
|
|
1401
1623
|
aria-label={messages.resumeThisWorkstream}
|
|
1402
|
-
className="inline-flex min-h-8 shrink-0 items-center gap-1.5 rounded-og-md border border-og-
|
|
1624
|
+
className="inline-flex min-h-8 shrink-0 items-center gap-1.5 rounded-og-md border border-og-primary-border bg-og-primary px-2.5 text-og-xs font-medium text-og-primary-fg hover:bg-og-primary-hover disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11"
|
|
1403
1625
|
disabled={busy}
|
|
1404
1626
|
onClick={onResume}
|
|
1405
1627
|
>
|
|
@@ -1599,20 +1821,88 @@ function ConfirmBar({
|
|
|
1599
1821
|
function AttachmentChips({
|
|
1600
1822
|
attachments,
|
|
1601
1823
|
messages,
|
|
1824
|
+
disabled,
|
|
1602
1825
|
onRemove,
|
|
1603
1826
|
onRetry,
|
|
1827
|
+
onRetainPreview,
|
|
1828
|
+
onLoadPreview,
|
|
1604
1829
|
}: {
|
|
1605
1830
|
attachments: UseFileAttachmentsResult["attachments"];
|
|
1606
1831
|
messages: ChatComposerMessages;
|
|
1832
|
+
disabled: boolean;
|
|
1607
1833
|
onRemove: (id: string) => void;
|
|
1608
1834
|
onRetry?: ((id: string) => void) | undefined;
|
|
1835
|
+
onRetainPreview: UseFileAttachmentsResult["retainPreview"];
|
|
1836
|
+
onLoadPreview: UseFileAttachmentsResult["loadPreview"];
|
|
1609
1837
|
}) {
|
|
1838
|
+
const lightbox = useLightboxOptional();
|
|
1839
|
+
const previewRequest = useRef<AbortController | null>(null);
|
|
1840
|
+
const [previewLoadingId, setPreviewLoadingId] = useState<string | null>(null);
|
|
1841
|
+
const [previewErrorId, setPreviewErrorId] = useState<string | null>(null);
|
|
1842
|
+
|
|
1843
|
+
useEffect(() => () => previewRequest.current?.abort(), [onLoadPreview]);
|
|
1844
|
+
|
|
1845
|
+
async function openPreview(
|
|
1846
|
+
attachment: UseFileAttachmentsResult["attachments"][number],
|
|
1847
|
+
source: HTMLButtonElement,
|
|
1848
|
+
canLoadPreview: boolean,
|
|
1849
|
+
) {
|
|
1850
|
+
previewRequest.current?.abort();
|
|
1851
|
+
const attachmentId = attachment.id;
|
|
1852
|
+
const releaseSource = onRetainPreview(attachmentId);
|
|
1853
|
+
let src = attachment.previewUrl;
|
|
1854
|
+
if (!releaseSource && canLoadPreview) {
|
|
1855
|
+
const controller = new AbortController();
|
|
1856
|
+
previewRequest.current = controller;
|
|
1857
|
+
setPreviewLoadingId(attachmentId);
|
|
1858
|
+
setPreviewErrorId(null);
|
|
1859
|
+
try {
|
|
1860
|
+
src = await onLoadPreview!(attachmentId, controller.signal);
|
|
1861
|
+
if (controller.signal.aborted) return;
|
|
1862
|
+
if (!src) {
|
|
1863
|
+
setPreviewErrorId(attachmentId);
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
} catch {
|
|
1867
|
+
if (!controller.signal.aborted) setPreviewErrorId(attachmentId);
|
|
1868
|
+
return;
|
|
1869
|
+
} finally {
|
|
1870
|
+
if (previewRequest.current === controller) {
|
|
1871
|
+
setPreviewLoadingId(null);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
lightbox!.open(
|
|
1876
|
+
src!,
|
|
1877
|
+
attachment.name,
|
|
1878
|
+
source,
|
|
1879
|
+
messages.attachmentPreviewLabel,
|
|
1880
|
+
attachment.name,
|
|
1881
|
+
{
|
|
1882
|
+
download: messages.downloadAttachment(attachment.name),
|
|
1883
|
+
close: messages.closeAttachmentPreview,
|
|
1884
|
+
},
|
|
1885
|
+
releaseSource,
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1610
1889
|
return (
|
|
1611
1890
|
<div className="flex flex-wrap gap-2 px-3 py-2">
|
|
1612
1891
|
{attachments.map((attachment) => {
|
|
1613
1892
|
const failed = attachment.status === "failed";
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1893
|
+
const secureContextRequired = attachment.errorCode === "secure_context_required";
|
|
1894
|
+
const previewFailed = previewErrorId === attachment.id;
|
|
1895
|
+
const previewLoading = previewLoadingId === attachment.id;
|
|
1896
|
+
const canLoadPreview = Boolean(
|
|
1897
|
+
lightbox &&
|
|
1898
|
+
onLoadPreview &&
|
|
1899
|
+
attachment.status === "ready" &&
|
|
1900
|
+
attachment.file &&
|
|
1901
|
+
attachment.contentType.startsWith("image/"),
|
|
1902
|
+
);
|
|
1903
|
+
const statusText = previewFailed
|
|
1904
|
+
? (messages.previewUnavailable ?? "Preview unavailable")
|
|
1905
|
+
: attachment.status === "uploading"
|
|
1616
1906
|
? messages.uploading
|
|
1617
1907
|
: failed
|
|
1618
1908
|
? attachment.error || messages.uploadFailed
|
|
@@ -1621,13 +1911,44 @@ function AttachmentChips({
|
|
|
1621
1911
|
<div
|
|
1622
1912
|
key={attachment.id}
|
|
1623
1913
|
className={cn(
|
|
1624
|
-
"flex min-w-0
|
|
1914
|
+
"flex min-w-0 items-center gap-2 rounded-og-md border px-2 py-1.5 text-og-sm",
|
|
1625
1915
|
failed
|
|
1626
|
-
?
|
|
1627
|
-
|
|
1916
|
+
? cn(
|
|
1917
|
+
"border-og-status-failed/40 bg-og-status-failed/10",
|
|
1918
|
+
secureContextRequired
|
|
1919
|
+
? "max-w-full items-start sm:max-w-[32rem]"
|
|
1920
|
+
: "max-w-[240px]",
|
|
1921
|
+
)
|
|
1922
|
+
: "max-w-[240px] border-og-border bg-og-surface-2",
|
|
1628
1923
|
)}
|
|
1629
1924
|
>
|
|
1630
|
-
{attachment.previewUrl ? (
|
|
1925
|
+
{lightbox && (attachment.previewUrl || canLoadPreview) ? (
|
|
1926
|
+
<button
|
|
1927
|
+
type="button"
|
|
1928
|
+
className={cn(
|
|
1929
|
+
"size-8 shrink-0 overflow-hidden rounded outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent",
|
|
1930
|
+
!attachment.previewUrl && "flex items-center justify-center disabled:cursor-wait",
|
|
1931
|
+
)}
|
|
1932
|
+
aria-label={messages.previewAttachment(attachment.name)}
|
|
1933
|
+
aria-busy={previewLoading || undefined}
|
|
1934
|
+
disabled={previewLoading}
|
|
1935
|
+
onClick={(event) =>
|
|
1936
|
+
void openPreview(attachment, event.currentTarget, canLoadPreview)
|
|
1937
|
+
}
|
|
1938
|
+
>
|
|
1939
|
+
{attachment.previewUrl ? (
|
|
1940
|
+
<img
|
|
1941
|
+
src={attachment.previewUrl}
|
|
1942
|
+
alt=""
|
|
1943
|
+
className="h-full w-full object-cover transition-opacity hover:opacity-80"
|
|
1944
|
+
/>
|
|
1945
|
+
) : previewLoading ? (
|
|
1946
|
+
<LoaderCircleIcon className="size-4 animate-og-spin text-og-fg-muted" />
|
|
1947
|
+
) : (
|
|
1948
|
+
<ImageIcon className="size-4 text-og-fg-muted" />
|
|
1949
|
+
)}
|
|
1950
|
+
</button>
|
|
1951
|
+
) : attachment.previewUrl ? (
|
|
1631
1952
|
<img
|
|
1632
1953
|
src={attachment.previewUrl}
|
|
1633
1954
|
alt=""
|
|
@@ -1640,7 +1961,11 @@ function AttachmentChips({
|
|
|
1640
1961
|
)}
|
|
1641
1962
|
<div className="min-w-0 flex-1">
|
|
1642
1963
|
<div className="truncate font-medium text-og-fg">{attachment.name}</div>
|
|
1643
|
-
{
|
|
1964
|
+
{secureContextRequired ? (
|
|
1965
|
+
<div className="break-words text-og-xs leading-4 text-og-status-failed">
|
|
1966
|
+
{statusText}
|
|
1967
|
+
</div>
|
|
1968
|
+
) : failed || previewFailed ? (
|
|
1644
1969
|
<ComposerTip tip={statusText}>
|
|
1645
1970
|
<div className="truncate text-og-xs text-og-status-failed">{statusText}</div>
|
|
1646
1971
|
</ComposerTip>
|
|
@@ -1651,12 +1976,13 @@ function AttachmentChips({
|
|
|
1651
1976
|
{attachment.status === "uploading" ? (
|
|
1652
1977
|
<LoaderCircleIcon className="size-3.5 shrink-0 animate-og-spin" />
|
|
1653
1978
|
) : null}
|
|
1654
|
-
{failed && onRetry ? (
|
|
1979
|
+
{failed && !secureContextRequired && onRetry ? (
|
|
1655
1980
|
<ComposerTip tip={messages.retryUpload}>
|
|
1656
1981
|
<button
|
|
1657
1982
|
type="button"
|
|
1658
1983
|
onClick={() => onRetry(attachment.id)}
|
|
1659
|
-
|
|
1984
|
+
disabled={disabled}
|
|
1985
|
+
className="shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:size-10"
|
|
1660
1986
|
aria-label={messages.retryAttachment(attachment.name)}
|
|
1661
1987
|
>
|
|
1662
1988
|
<RotateCwIcon className="size-3.5" />
|
|
@@ -1666,7 +1992,8 @@ function AttachmentChips({
|
|
|
1666
1992
|
<button
|
|
1667
1993
|
type="button"
|
|
1668
1994
|
onClick={() => onRemove(attachment.id)}
|
|
1669
|
-
|
|
1995
|
+
disabled={disabled}
|
|
1996
|
+
className="shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:size-10"
|
|
1670
1997
|
aria-label={messages.removeAttachment(attachment.name)}
|
|
1671
1998
|
>
|
|
1672
1999
|
<XIcon className="size-3.5" />
|