@opengeni/react 0.57.0 → 1.0.2-canary.37191796234001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +654 -22
- package/dist/accounts.d.ts +64 -0
- package/dist/accounts.js +822 -0
- package/dist/accounts.js.map +1 -0
- package/dist/approvals.d.ts +2 -1
- package/dist/artifacts-document.js +3 -2
- package/dist/artifacts-presentation.js +3 -2
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.d.ts +4 -1
- package/dist/artifacts.js +518 -42
- package/dist/artifacts.js.map +1 -1
- package/dist/browser-viewer-GTR5XQ7X.js +16 -0
- package/dist/capability-catalog-row.d.ts +20 -0
- package/dist/capability-logo-fallback.d.ts +3 -0
- package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
- package/dist/chat-interactive-block-UGBTNB3L.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-23J2ZNXT.js} +4117 -3896
- package/dist/chunk-23J2ZNXT.js.map +1 -0
- package/dist/chunk-447JLCBU.js +209 -0
- package/dist/chunk-447JLCBU.js.map +1 -0
- package/dist/chunk-4RVYOY4O.js +379 -0
- package/dist/chunk-4RVYOY4O.js.map +1 -0
- package/dist/chunk-5CVXZA3Y.js +292 -0
- package/dist/chunk-5CVXZA3Y.js.map +1 -0
- package/dist/chunk-5J4FOW6Q.js +108 -0
- package/dist/chunk-5J4FOW6Q.js.map +1 -0
- package/dist/chunk-A2PI6UMY.js +41 -0
- package/dist/chunk-A2PI6UMY.js.map +1 -0
- package/dist/{chunk-7WCLAEFV.js → chunk-A4UJB2MM.js} +37 -27
- package/dist/chunk-A4UJB2MM.js.map +1 -0
- package/dist/chunk-B3V6TG77.js +41 -0
- package/dist/chunk-B3V6TG77.js.map +1 -0
- package/dist/chunk-BRM6FVZA.js +302 -0
- package/dist/chunk-BRM6FVZA.js.map +1 -0
- package/dist/chunk-C5X5AJXK.js +182 -0
- package/dist/chunk-C5X5AJXK.js.map +1 -0
- package/dist/chunk-CR7U7HAR.js +453 -0
- package/dist/chunk-CR7U7HAR.js.map +1 -0
- package/dist/{chunk-R3AZOAB5.js → chunk-DYWBUX5Q.js} +29 -123
- package/dist/chunk-DYWBUX5Q.js.map +1 -0
- package/dist/chunk-E3G7SAYZ.js +3124 -0
- package/dist/chunk-E3G7SAYZ.js.map +1 -0
- package/dist/chunk-ELCE5SXV.js +359 -0
- package/dist/chunk-ELCE5SXV.js.map +1 -0
- package/dist/chunk-ERGYJIBB.js +21 -0
- package/dist/chunk-ERGYJIBB.js.map +1 -0
- package/dist/chunk-FFA2OVOV.js +319 -0
- package/dist/chunk-FFA2OVOV.js.map +1 -0
- package/dist/chunk-FZCP527Y.js +116 -0
- package/dist/chunk-FZCP527Y.js.map +1 -0
- package/dist/chunk-GIMRELBW.js +14 -0
- package/dist/chunk-GIMRELBW.js.map +1 -0
- package/dist/{chunk-6KLX2RH5.js → chunk-H2NJQORO.js} +1069 -79
- package/dist/chunk-H2NJQORO.js.map +1 -0
- package/dist/chunk-I7IWRQLN.js +1608 -0
- package/dist/chunk-I7IWRQLN.js.map +1 -0
- package/dist/{chunk-HA46CYQK.js → chunk-IQUCRAT7.js} +792 -537
- package/dist/chunk-IQUCRAT7.js.map +1 -0
- package/dist/chunk-IWIDV7SB.js +1 -0
- package/dist/chunk-IWIDV7SB.js.map +1 -0
- package/dist/chunk-J2QWVSQY.js +312 -0
- package/dist/chunk-J2QWVSQY.js.map +1 -0
- package/dist/chunk-JFNEV4LU.js +2733 -0
- package/dist/chunk-JFNEV4LU.js.map +1 -0
- package/dist/chunk-JT4JW7BC.js +54 -0
- package/dist/chunk-JT4JW7BC.js.map +1 -0
- package/dist/chunk-K3HQAKQX.js +24 -0
- package/dist/chunk-K3HQAKQX.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
- package/dist/chunk-NZUI76EM.js +371 -0
- package/dist/chunk-NZUI76EM.js.map +1 -0
- package/dist/{chunk-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
- package/dist/chunk-PNY3JKBJ.js.map +1 -0
- package/dist/{chunk-IGC6A2ZI.js → chunk-Q5QBEZIQ.js} +777 -246
- package/dist/chunk-Q5QBEZIQ.js.map +1 -0
- package/dist/chunk-RHREZ7BO.js +11 -0
- package/dist/chunk-RHREZ7BO.js.map +1 -0
- package/dist/chunk-SCOTPE2I.js +589 -0
- package/dist/chunk-SCOTPE2I.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-SJZDKVW2.js} +1331 -1163
- package/dist/chunk-SJZDKVW2.js.map +1 -0
- package/dist/chunk-TMJRG4YC.js +12803 -0
- package/dist/chunk-TMJRG4YC.js.map +1 -0
- package/dist/chunk-TMYGL6X5.js +742 -0
- package/dist/chunk-TMYGL6X5.js.map +1 -0
- package/dist/chunk-UGLEYEMP.js +33 -0
- package/dist/chunk-UGLEYEMP.js.map +1 -0
- package/dist/chunk-UK4TINKT.js +27 -0
- package/dist/chunk-UK4TINKT.js.map +1 -0
- package/dist/chunk-UTRTG6LH.js +220 -0
- package/dist/chunk-UTRTG6LH.js.map +1 -0
- package/dist/chunk-WEHMPOXK.js +39 -0
- package/dist/chunk-WEHMPOXK.js.map +1 -0
- package/dist/chunk-WRHIZYZF.js +988 -0
- package/dist/chunk-WRHIZYZF.js.map +1 -0
- package/dist/{chunk-HUIKIDM5.js → chunk-WUISZ3WU.js} +223 -115
- package/dist/chunk-WUISZ3WU.js.map +1 -0
- package/dist/chunk-XCHWDJ22.js +107 -0
- package/dist/chunk-XCHWDJ22.js.map +1 -0
- package/dist/chunk-XOAMRDDK.js +481 -0
- package/dist/chunk-XOAMRDDK.js.map +1 -0
- package/dist/chunk-XUW2UWQM.js +299 -0
- package/dist/chunk-XUW2UWQM.js.map +1 -0
- package/dist/{chunk-KCGXPP5V.js → chunk-Y2PRMYLC.js} +11 -6
- package/dist/chunk-Y2PRMYLC.js.map +1 -0
- package/dist/chunk-YBXQDQFX.js +1772 -0
- package/dist/chunk-YBXQDQFX.js.map +1 -0
- package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
- package/dist/chunk-YQEAA6LT.js.map +1 -0
- package/dist/chunk-YV4L3ILF.js +9 -0
- package/dist/chunk-YV4L3ILF.js.map +1 -0
- package/dist/{chunk-LLOLUHVG.js → chunk-YWFG7ZX7.js} +1358 -2746
- package/dist/chunk-YWFG7ZX7.js.map +1 -0
- package/dist/chunk-ZYRGEKWS.js +216 -0
- package/dist/chunk-ZYRGEKWS.js.map +1 -0
- package/dist/client.d.ts +7 -4
- package/dist/clipboard.js +1 -0
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/anthropic-mark.d.ts +3 -0
- package/dist/components/approval-surface.d.ts +15 -0
- package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
- package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
- package/dist/components/artifacts/artifact-surface.d.ts +3 -1
- package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
- package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
- package/dist/components/artifacts/document-editor.d.ts +4 -2
- package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
- package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
- package/dist/components/artifacts/editable-document.d.ts +1 -1
- package/dist/components/artifacts/editable-presentation.d.ts +2 -2
- package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
- package/dist/components/artifacts/index.d.ts +8 -1
- package/dist/components/artifacts/inline-html-document.d.ts +2 -0
- package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
- package/dist/components/artifacts/presentation-editor.d.ts +6 -2
- package/dist/components/artifacts/published-html-artifact-frame.d.ts +48 -3
- package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
- package/dist/components/artifacts/site-view.d.ts +23 -0
- package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
- package/dist/components/artifacts/visualization-assets.gen.d.ts +2 -0
- package/dist/components/browser-select-control.d.ts +16 -0
- package/dist/components/browser-viewer.d.ts +10 -1
- package/dist/components/chat-composer.d.ts +21 -3
- package/dist/components/child-session-link.d.ts +5 -0
- package/dist/components/claude-mark.d.ts +3 -0
- package/dist/components/code-editor.d.ts +1 -4
- package/dist/components/composer.d.ts +45 -4
- package/dist/components/computer-viewer.d.ts +4 -1
- package/dist/components/copy-button.d.ts +3 -1
- package/dist/components/desktop-viewer.d.ts +1 -1
- package/dist/components/enrollment-consent.d.ts +6 -3
- package/dist/components/file-browser.d.ts +10 -1
- package/dist/components/fleet-tile.d.ts +2 -2
- package/dist/components/grok-mark.d.ts +26 -0
- package/dist/components/human-input-form.d.ts +21 -2
- package/dist/components/human-input-surface.d.ts +6 -3
- package/dist/components/machine-card.d.ts +4 -1
- package/dist/components/machines/machine-detail.d.ts +4 -1
- package/dist/components/machines/machine-operation-policy.d.ts +11 -0
- package/dist/components/machines-dashboard.d.ts +3 -1
- package/dist/components/markdown-table-layout.d.ts +12 -0
- package/dist/components/markdown.d.ts +47 -3
- package/dist/components/message-timeline.d.ts +72 -9
- package/dist/components/model-mark.d.ts +29 -0
- package/dist/components/model-policy-picker-menu.d.ts +9 -0
- package/dist/components/model-policy-picker.d.ts +62 -13
- package/dist/components/open-geni-chat.d.ts +55 -0
- package/dist/components/open-geni-links.d.ts +68 -0
- package/dist/components/openrouter-mark.d.ts +6 -0
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/preview-loading.d.ts +2 -0
- package/dist/components/queue-item-content.d.ts +9 -0
- package/dist/components/sandbox-files.d.ts +13 -2
- package/dist/components/sandbox-workspace.d.ts +43 -3
- package/dist/components/session-capability-frame.d.ts +35 -0
- package/dist/components/session-chrome.d.ts +66 -8
- package/dist/components/session-commands-panel.d.ts +6 -0
- package/dist/components/session-commands.d.ts +6 -0
- package/dist/components/session-connection-request.d.ts +8 -0
- package/dist/components/session-conversation.d.ts +86 -0
- package/dist/components/session-list.d.ts +36 -0
- package/dist/components/session-mcp-capability-card.d.ts +41 -0
- package/dist/components/timeline-anchor.d.ts +24 -0
- package/dist/components/timeline-annotation-chrome.d.ts +25 -0
- package/dist/components/timeline-annotation-layout.d.ts +42 -0
- package/dist/components/timeline-annotation-markers.d.ts +8 -0
- package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
- package/dist/components/timeline-annotation-shared.d.ts +31 -0
- package/dist/components/timeline-annotations-dialog.d.ts +3 -2
- package/dist/components/timeline-annotations.d.ts +13 -3
- package/dist/components/timeline-reading-progress.d.ts +11 -0
- package/dist/components/timeline-search.d.ts +34 -0
- package/dist/components/timeline-settlement.d.ts +16 -0
- package/dist/components/tip-follow.d.ts +16 -0
- package/dist/components/usage-limit-notice.d.ts +49 -0
- package/dist/components/usage-member-list.d.ts +91 -0
- package/dist/components/usage-meter.d.ts +73 -0
- package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
- package/dist/components/user-message-body.d.ts +10 -1
- package/dist/components/workspace-dock.d.ts +6 -2
- package/dist/composer.d.ts +5 -4
- package/dist/composer.js +15 -9
- package/dist/computer-viewer-ENHVAZ2Q.js +19 -0
- package/dist/computer-viewer-ENHVAZ2Q.js.map +1 -0
- package/dist/connect-account-identity.d.ts +8 -0
- package/dist/connect-accounts.d.ts +15 -0
- package/dist/connect-chooser.d.ts +18 -0
- package/dist/connect-panel.d.ts +18 -0
- package/dist/connect-setup.d.ts +16 -0
- package/dist/connect.d.ts +21 -0
- package/dist/connect.js +2129 -0
- package/dist/connect.js.map +1 -0
- package/dist/connection-catalog.d.ts +38 -0
- package/dist/connection-discovery.d.ts +12 -0
- package/dist/connection-installed.d.ts +17 -0
- package/dist/connection-logo.d.ts +9 -0
- package/dist/connection-service-logo.d.ts +8 -0
- package/dist/connection-service-presentation.d.ts +13 -0
- package/dist/connection-skeleton.d.ts +5 -0
- package/dist/connection-type-picker.d.ts +6 -0
- package/dist/conversation-timeline.d.ts +5 -0
- package/dist/desktop.d.ts +7 -0
- package/dist/desktop.js +26 -0
- package/dist/desktop.js.map +1 -0
- package/dist/device-authorization.d.ts +23 -0
- package/dist/diffs.d.ts +8 -0
- package/dist/diffs.js +14 -0
- package/dist/diffs.js.map +1 -0
- package/dist/discovery-cache.d.ts +5 -0
- package/dist/editor.d.ts +7 -0
- package/dist/editor.js +21 -0
- package/dist/editor.js.map +1 -0
- package/dist/embedded-session-client.d.ts +23 -0
- package/dist/file-node-visibility.d.ts +15 -0
- package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
- package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
- package/dist/hooks/channel-cache.d.ts +23 -0
- package/dist/hooks/latest-question.d.ts +25 -0
- package/dist/hooks/shared-machines-list.d.ts +14 -0
- package/dist/hooks/use-attached-browsers.d.ts +2 -1
- package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
- package/dist/hooks/use-browser-session.d.ts +12 -1
- package/dist/hooks/use-channels.d.ts +1 -0
- package/dist/hooks/use-codex-accounts.d.ts +25 -7
- package/dist/hooks/use-composer.d.ts +45 -9
- package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
- package/dist/hooks/use-computer-input-posture.d.ts +13 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-connect.d.ts +22 -0
- package/dist/hooks/use-desktop-stream.d.ts +1 -1
- package/dist/hooks/use-file-attachments.d.ts +21 -2
- package/dist/hooks/use-machine-chip.d.ts +3 -3
- package/dist/hooks/use-machines.d.ts +19 -1
- package/dist/hooks/use-sandbox-files.d.ts +5 -1
- package/dist/hooks/use-session-background-commands.d.ts +14 -0
- package/dist/hooks/use-session-events.d.ts +30 -8
- package/dist/hooks/use-session-lineage.d.ts +4 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-session.d.ts +6 -0
- package/dist/hooks/use-turn-queue.d.ts +12 -0
- package/dist/hooks/use-usage.d.ts +40 -0
- package/dist/hooks/use-workspace-edit.d.ts +4 -0
- package/dist/hooks/use-workspace-sessions.d.ts +27 -5
- package/dist/human-input.d.ts +3 -1
- package/dist/identity-link-accounts.d.ts +11 -0
- package/dist/identity-link-consent.d.ts +18 -0
- package/dist/index.d.ts +60 -17
- package/dist/index.js +2237 -6200
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.js +35 -184
- package/dist/interaction.js.map +1 -1
- package/dist/latest-question-755OW5DS.js +117 -0
- package/dist/latest-question-755OW5DS.js.map +1 -0
- package/dist/lib/error-message.d.ts +7 -0
- package/dist/lib/format.d.ts +36 -2
- package/dist/lib/host-theme.d.ts +70 -0
- package/dist/lib/interaction-errors.d.ts +6 -0
- package/dist/lib/menu-styles.d.ts +22 -0
- package/dist/lib/pierre-diffs-loader.d.ts +20 -0
- package/dist/lib/workbench-peers.d.ts +36 -0
- package/dist/lib/xterm-theme.d.ts +7 -5
- package/dist/machines.d.ts +4 -2
- package/dist/machines.js +14 -4
- package/dist/markdown-table-layout-QXSLK4BY.js +106 -0
- package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
- package/dist/mcp-connection-status.d.ts +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js.map +1 -0
- package/dist/model-policy.d.ts +19 -3
- package/dist/model-policy.js +9 -1
- package/dist/older-history.d.ts +30 -0
- package/dist/platform-activity-row-627BFZ46.js +182 -0
- package/dist/platform-activity-row-627BFZ46.js.map +1 -0
- package/dist/plugin-details.d.ts +14 -0
- package/dist/plugin-discovery.d.ts +25 -0
- package/dist/provider.d.ts +13 -1
- package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-ZHFI5JBP.js} +131 -44
- package/dist/queue-surface-implementation-ZHFI5JBP.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +10 -3
- package/dist/realtime.js +229 -83
- package/dist/realtime.js.map +1 -1
- package/dist/sandbox-files-BBC47SLD.js +20 -0
- package/dist/sandbox-files-BBC47SLD.js.map +1 -0
- package/dist/session-auth-recommendation.d.ts +5 -0
- package/dist/session-capability-policy.d.ts +12 -0
- package/dist/session-ui.d.ts +30 -2
- package/dist/session-ui.js +85 -7
- package/dist/session-ui.js.map +1 -1
- package/dist/session.d.ts +8 -2
- package/dist/session.js +30 -19
- package/dist/sites-ui.d.ts +34 -0
- package/dist/sites.d.ts +3 -0
- package/dist/sites.js +11 -0
- package/dist/sites.js.map +1 -0
- package/dist/skill-discovery.d.ts +47 -0
- package/dist/terminal.d.ts +8 -0
- package/dist/terminal.js +31 -0
- package/dist/terminal.js.map +1 -0
- package/dist/timeline/activity-rail.d.ts +11 -2
- package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
- package/dist/timeline/compaction-copy.d.ts +10 -0
- package/dist/timeline/entrance.d.ts +13 -1
- package/dist/timeline/genie-loading.d.ts +34 -0
- package/dist/timeline/index.d.ts +6 -2
- package/dist/timeline/knowledge-receipt.d.ts +17 -0
- package/dist/timeline/platform-activity-row.d.ts +14 -0
- package/dist/timeline/presented-image.d.ts +6 -0
- package/dist/timeline/projection.d.ts +31 -2
- package/dist/timeline/registry.d.ts +2 -0
- package/dist/timeline/retained-image.d.ts +18 -0
- package/dist/timeline/rolling-activity.d.ts +11 -0
- package/dist/timeline/screenshot-lightbox.d.ts +16 -1
- package/dist/timeline/shared.d.ts +8 -3
- package/dist/timeline/startup-preference.d.ts +3 -0
- package/dist/timeline/startup-timings.d.ts +4 -0
- package/dist/timeline/tool-display-name.d.ts +2 -1
- package/dist/timeline/turn-summary.d.ts +32 -3
- package/dist/timeline/types.d.ts +141 -7
- package/dist/timeline-annotation-markers-GNDHTGBD.js +165 -0
- package/dist/timeline-annotation-markers-GNDHTGBD.js.map +1 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js +241 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js +273 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js.map +1 -0
- package/dist/types/machines.d.ts +2 -2
- package/dist/usage/allowance-copy.d.ts +25 -0
- package/dist/usage/summary.d.ts +35 -0
- package/dist/usage.d.ts +13 -0
- package/dist/usage.js +1074 -0
- package/dist/usage.js.map +1 -0
- package/package.json +44 -4
- package/src/accounts.tsx +1072 -0
- package/src/approvals.ts +8 -1
- package/src/artifacts.ts +42 -0
- package/src/assets/README.md +8 -0
- package/src/assets/gmail.ico +0 -0
- package/src/assets/outlook.ico +0 -0
- package/src/capability-catalog-row.tsx +94 -0
- package/src/capability-logo-fallback.ts +22 -0
- package/src/client.ts +22 -13
- package/src/commands/registry.ts +18 -15
- package/src/commands/types.ts +2 -0
- package/src/components/anthropic-mark.tsx +10 -0
- package/src/components/approval-surface.tsx +171 -37
- package/src/components/artifacts/artifact-chrome.tsx +413 -0
- package/src/components/artifacts/artifact-sandbox.tsx +185 -0
- package/src/components/artifacts/artifact-surface.tsx +39 -19
- package/src/components/artifacts/chat-interactive-block.tsx +260 -0
- package/src/components/artifacts/deferred-chat-media.tsx +67 -0
- package/src/components/artifacts/document-editor.tsx +141 -16
- package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
- package/src/components/artifacts/editable-artifact-view.tsx +187 -0
- package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
- package/src/components/artifacts/editable-document.tsx +37 -36
- package/src/components/artifacts/editable-presentation.tsx +36 -18
- package/src/components/artifacts/editable-spreadsheet.tsx +5 -2
- package/src/components/artifacts/index.ts +44 -0
- package/src/components/artifacts/inline-html-document.ts +24 -0
- package/src/components/artifacts/latest-task-runner.ts +49 -0
- package/src/components/artifacts/presentation-editor.tsx +323 -67
- package/src/components/artifacts/published-html-artifact-frame.tsx +338 -5
- package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
- package/src/components/artifacts/site-view.tsx +116 -0
- package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
- package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +12 -13
- package/src/components/artifacts/visualization-assets/base.css +1015 -0
- package/src/components/artifacts/visualization-assets/helpers.html +349 -0
- package/src/components/artifacts/visualization-assets.gen.ts +3 -0
- package/src/components/browser-select-control.tsx +312 -0
- package/src/components/browser-viewer.tsx +1054 -314
- package/src/components/chat-composer.tsx +131 -85
- package/src/components/child-session-link.tsx +27 -0
- package/src/components/claude-mark.tsx +10 -0
- package/src/components/code-editor.tsx +13 -16
- package/src/components/composer-transcription-control.tsx +7 -5
- package/src/components/composer.tsx +376 -49
- package/src/components/computer-viewer.tsx +1041 -329
- package/src/components/copy-button.tsx +13 -5
- package/src/components/desktop-viewer.tsx +1 -1
- package/src/components/enrollment-consent.tsx +65 -7
- package/src/components/enrollment-device-flow.tsx +1 -1
- package/src/components/file-browser.tsx +158 -34
- package/src/components/fleet-tile.tsx +8 -16
- package/src/components/generated-video-player.tsx +4 -2
- package/src/components/grok-mark.tsx +33 -0
- package/src/components/human-input-form.tsx +455 -114
- package/src/components/human-input-surface.tsx +18 -7
- package/src/components/interaction-intervention-banner.tsx +2 -2
- package/src/components/machine-card.tsx +119 -4
- package/src/components/machine-dock-bar.tsx +1 -1
- package/src/components/machine-input-display.ts +23 -2
- package/src/components/machines/machine-detail.tsx +52 -2
- package/src/components/machines/machine-operation-policy.tsx +179 -0
- package/src/components/machines-dashboard.tsx +8 -17
- package/src/components/markdown-table-layout.ts +132 -0
- package/src/components/markdown.tsx +473 -44
- package/src/components/message-timeline.tsx +2498 -663
- package/src/components/model-mark.tsx +90 -0
- package/src/components/model-picker.tsx +15 -4
- package/src/components/model-policy-picker-menu.tsx +424 -0
- package/src/components/model-policy-picker.tsx +337 -381
- package/src/components/open-geni-chat.tsx +319 -0
- package/src/components/open-geni-links.tsx +179 -0
- package/src/components/openrouter-mark.tsx +13 -0
- package/src/components/pierre-diff.tsx +41 -16
- package/src/components/pierre-file.tsx +36 -11
- package/src/components/preview-loading.tsx +154 -0
- package/src/components/queue-item-content.ts +14 -0
- package/src/components/queue-surface-implementation.tsx +132 -42
- package/src/components/queue-surface-state.tsx +3 -1
- package/src/components/sandbox-files.tsx +267 -35
- package/src/components/sandbox-terminal.tsx +48 -11
- package/src/components/sandbox-workspace.tsx +337 -135
- package/src/components/session-capability-frame.tsx +192 -0
- package/src/components/session-chrome.tsx +1027 -328
- package/src/components/session-commands-panel.tsx +126 -0
- package/src/components/session-commands.tsx +18 -0
- package/src/components/session-connection-request.tsx +97 -0
- package/src/components/session-conversation.tsx +512 -0
- package/src/components/session-list.tsx +250 -0
- package/src/components/session-mcp-capability-card.tsx +680 -0
- package/src/components/session-status.tsx +1 -1
- package/src/components/timeline-anchor.tsx +119 -0
- package/src/components/timeline-annotation-chrome.tsx +196 -0
- package/src/components/timeline-annotation-layout.ts +268 -0
- package/src/components/timeline-annotation-markers.tsx +185 -0
- package/src/components/timeline-annotation-reveal-context.ts +9 -0
- package/src/components/timeline-annotation-selection.tsx +106 -54
- package/src/components/timeline-annotation-shared.ts +245 -0
- package/src/components/timeline-annotations-dialog.tsx +185 -128
- package/src/components/timeline-annotations.tsx +189 -45
- package/src/components/timeline-reading-progress.ts +80 -0
- package/src/components/timeline-search.tsx +168 -0
- package/src/components/timeline-settlement.ts +60 -0
- package/src/components/tip-follow.ts +70 -7
- package/src/components/tooltip.tsx +38 -5
- package/src/components/usage-limit-notice.tsx +179 -0
- package/src/components/usage-member-list.tsx +792 -0
- package/src/components/usage-meter.tsx +382 -0
- package/src/components/use-viewer-menu-dismiss.ts +33 -0
- package/src/components/user-message-body.tsx +194 -49
- package/src/components/workspace-dock.tsx +141 -175
- package/src/composer.ts +6 -1
- package/src/connect-account-identity.tsx +34 -0
- package/src/connect-accounts.tsx +233 -0
- package/src/connect-chooser.tsx +336 -0
- package/src/connect-panel.tsx +99 -0
- package/src/connect-setup.tsx +307 -0
- package/src/connect.ts +60 -0
- package/src/connection-assets.d.ts +4 -0
- package/src/connection-catalog.tsx +162 -0
- package/src/connection-discovery.tsx +235 -0
- package/src/connection-installed.tsx +51 -0
- package/src/connection-logo.tsx +37 -0
- package/src/connection-service-logo.tsx +55 -0
- package/src/connection-service-presentation.ts +46 -0
- package/src/connection-skeleton.tsx +16 -0
- package/src/connection-type-picker.tsx +36 -0
- package/src/conversation-timeline.ts +92 -0
- package/src/desktop.ts +24 -0
- package/src/device-authorization.tsx +98 -0
- package/src/diffs.ts +16 -0
- package/src/discovery-cache.ts +42 -0
- package/src/editor.ts +13 -0
- package/src/embedded-session-client.ts +104 -0
- package/src/file-node-visibility.ts +66 -0
- package/src/hooks/channel-cache.ts +104 -0
- package/src/hooks/internal.ts +3 -2
- package/src/hooks/latest-question.ts +164 -0
- package/src/hooks/shared-machines-list.ts +239 -0
- package/src/hooks/use-attached-browsers.ts +5 -1
- package/src/hooks/use-available-models.ts +20 -14
- package/src/hooks/use-browser-frame-stream.ts +25 -3
- package/src/hooks/use-browser-session.ts +271 -71
- package/src/hooks/use-browser-sessions.ts +7 -1
- package/src/hooks/use-channels.ts +32 -10
- package/src/hooks/use-codex-accounts.ts +78 -21
- package/src/hooks/use-composer.ts +1034 -320
- package/src/hooks/use-computer-frame-stream.ts +39 -16
- package/src/hooks/use-computer-input-posture.ts +94 -0
- package/src/hooks/use-computer-session.ts +110 -32
- package/src/hooks/use-computer-sessions.ts +8 -1
- package/src/hooks/use-connect.ts +23 -0
- package/src/hooks/use-desktop-stream.ts +19 -28
- package/src/hooks/use-file-attachments.ts +118 -10
- package/src/hooks/use-goal.ts +36 -9
- package/src/hooks/use-human-input.ts +31 -4
- package/src/hooks/use-last-started-turn-policy.ts +15 -13
- package/src/hooks/use-machine-chip.ts +23 -6
- package/src/hooks/use-machines.ts +104 -6
- package/src/hooks/use-sandbox-files.ts +253 -150
- package/src/hooks/use-sandbox-git.ts +58 -29
- package/src/hooks/use-session-background-commands.ts +67 -0
- package/src/hooks/use-session-capabilities.ts +21 -2
- package/src/hooks/use-session-events.ts +759 -433
- package/src/hooks/use-session-lineage.ts +28 -6
- package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
- package/src/hooks/use-session.ts +75 -16
- package/src/hooks/use-slash-commands.ts +6 -11
- package/src/hooks/use-turn-queue.ts +113 -13
- package/src/hooks/use-usage.ts +100 -0
- package/src/hooks/use-voice-input.ts +12 -1
- package/src/hooks/use-workspace-capture.ts +3 -2
- package/src/hooks/use-workspace-edit.ts +23 -5
- package/src/hooks/use-workspace-sessions.ts +99 -11
- package/src/human-input.ts +12 -1
- package/src/identity-link-accounts.tsx +148 -0
- package/src/identity-link-consent.tsx +192 -0
- package/src/index.ts +157 -12
- package/src/interaction.ts +1 -0
- package/src/lib/error-message.ts +37 -0
- package/src/lib/format.ts +150 -14
- package/src/lib/host-theme.ts +511 -0
- package/src/lib/interaction-errors.ts +33 -0
- package/src/lib/menu-styles.ts +44 -0
- package/src/lib/pierre-diffs-loader.ts +53 -0
- package/src/lib/workbench-peers.ts +62 -0
- package/src/lib/xterm-theme.ts +23 -21
- package/src/machines.ts +9 -1
- package/src/mcp-connection-status.ts +35 -0
- package/src/model-policy.ts +223 -69
- package/src/older-history.ts +87 -0
- package/src/plugin-details.tsx +185 -0
- package/src/plugin-discovery.tsx +196 -0
- package/src/provider.tsx +55 -14
- package/src/realtime/dropdown-menu.tsx +19 -12
- package/src/realtime/realtime-control.tsx +274 -60
- package/src/session-auth-recommendation.ts +48 -0
- package/src/session-capability-policy.ts +83 -0
- package/src/session-context.ts +1 -0
- package/src/session-ui.ts +66 -2
- package/src/session.ts +18 -1
- package/src/sites-ui.tsx +402 -0
- package/src/sites.ts +3 -0
- package/src/skill-discovery.tsx +208 -0
- package/src/terminal.ts +26 -0
- package/src/timeline/activity-rail.tsx +171 -80
- package/src/timeline/allowance-exhausted-row.tsx +86 -0
- package/src/timeline/compaction-copy.ts +42 -0
- package/src/timeline/entrance.tsx +28 -3
- package/src/timeline/fleet-decision-projection.ts +2 -1
- package/src/timeline/fleet-decision-row.tsx +1 -0
- package/src/timeline/genie-loading.tsx +136 -0
- package/src/timeline/index.ts +11 -0
- package/src/timeline/knowledge-receipt.tsx +100 -0
- package/src/timeline/parsers.ts +2 -2
- package/src/timeline/platform-activity-row.tsx +216 -0
- package/src/timeline/presented-image.ts +49 -0
- package/src/timeline/projection.ts +1600 -84
- package/src/timeline/registry.ts +15 -3
- package/src/timeline/retained-image.ts +97 -0
- package/src/timeline/rolling-activity.tsx +92 -0
- package/src/timeline/screenshot-lightbox.tsx +115 -17
- package/src/timeline/shared.tsx +47 -15
- package/src/timeline/startup-preference.ts +33 -0
- package/src/timeline/startup-timings.tsx +145 -0
- package/src/timeline/tool-display-name.ts +8 -6
- package/src/timeline/tool-renderers.tsx +497 -128
- package/src/timeline/turn-summary.tsx +208 -44
- package/src/timeline/types.ts +186 -7
- package/src/types/machines.ts +10 -0
- package/src/usage/allowance-copy.ts +64 -0
- package/src/usage/summary.ts +93 -0
- package/src/usage.ts +50 -0
- package/styles/compiled.css +2098 -757
- package/styles/connect.css +284 -0
- package/styles/connect.d.ts +1 -0
- package/styles/effective-tokens.css +1 -0
- package/styles/index.css +201 -9
- package/styles/responsive.css +27 -1
- package/styles/session-capability.css +44 -0
- package/styles/tokens.css +135 -65
- package/dist/chunk-5UQPNLIO.js.map +0 -1
- package/dist/chunk-6KLX2RH5.js.map +0 -1
- package/dist/chunk-7WCLAEFV.js.map +0 -1
- package/dist/chunk-B6WPZSTT.js.map +0 -1
- package/dist/chunk-FK6VG4LL.js +0 -90
- package/dist/chunk-FK6VG4LL.js.map +0 -1
- package/dist/chunk-HA46CYQK.js.map +0 -1
- package/dist/chunk-HUIKIDM5.js.map +0 -1
- package/dist/chunk-IGC6A2ZI.js.map +0 -1
- package/dist/chunk-KCGXPP5V.js.map +0 -1
- package/dist/chunk-KZ73RL76.js.map +0 -1
- package/dist/chunk-LAKLF4PA.js +0 -141
- package/dist/chunk-LAKLF4PA.js.map +0 -1
- package/dist/chunk-LLOLUHVG.js.map +0 -1
- package/dist/chunk-MKPIAGVL.js +0 -465
- package/dist/chunk-MKPIAGVL.js.map +0 -1
- package/dist/chunk-PEI6RANI.js.map +0 -1
- package/dist/chunk-R3AZOAB5.js.map +0 -1
- package/dist/chunk-WSK7G5LE.js +0 -170
- package/dist/chunk-WSK7G5LE.js.map +0 -1
- package/dist/chunk-XBZWOM2K.js +0 -218
- package/dist/chunk-XBZWOM2K.js.map +0 -1
- package/dist/chunk-Y7OEDUJ5.js +0 -8810
- package/dist/chunk-Y7OEDUJ5.js.map +0 -1
- package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
- package/dist/hooks/use-packs.d.ts +0 -32
- package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
- package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
- package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
- package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
- package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
- package/src/hooks/use-packs.ts +0 -157
- /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GTR5XQ7X.js.map} +0 -0
package/README.md
CHANGED
|
@@ -19,11 +19,225 @@ island for back-compat, deprecated per #144.)
|
|
|
19
19
|
|
|
20
20
|
Design-system-first: every visual decision routes through CSS-variable tokens
|
|
21
21
|
(`styles/tokens.css`) — color, typography, radius, shadow, motion. Dark mode is
|
|
22
|
-
the first-class default; light is an opt-in via `data-og-theme="light"` on
|
|
23
|
-
ancestor.
|
|
22
|
+
the first-class token default; light is an opt-in via `data-og-theme="light"` on
|
|
23
|
+
any ancestor. The embedded chat roots (`OpenGeniChat`, `SessionConversation`)
|
|
24
|
+
resolve light or dark from the host page instead; see
|
|
25
|
+
[Conversation UI](#conversation-ui). Components are styled with Tailwind v4 utilities mapped onto the
|
|
24
26
|
tokens, Radix primitives for behavior, and Motion for state-communicating
|
|
25
27
|
animation. Override the tokens to rebrand everything.
|
|
26
28
|
|
|
29
|
+
## Embedded connections and Sites
|
|
30
|
+
|
|
31
|
+
Optional `@opengeni/react/connect` exports `useConnect`, `ConnectChooser`,
|
|
32
|
+
`ConnectSetup`, `ConnectAccounts`, and the composed `ConnectPanel`. Inject one
|
|
33
|
+
`@opengeni/connect` controller per authenticated actor/workspace and dispose it
|
|
34
|
+
when that scope changes. The controller uses your authenticated backend proxy;
|
|
35
|
+
never place an organization key in browser props. Import
|
|
36
|
+
`@opengeni/react/connect.css` for opt-in, scoped styles without Tailwind.
|
|
37
|
+
`DeviceAuthorization` also accepts an optional `render` callback for host presentation;
|
|
38
|
+
it receives shared copy state, the copy action, and the validated verification URL.
|
|
39
|
+
Omitting it preserves the default embedded presentation.
|
|
40
|
+
|
|
41
|
+
`CapabilityCatalogRow` gives connections, skills, and plugins one consistent
|
|
42
|
+
icon/name/description button with a decorative plus/check and visible exception
|
|
43
|
+
states. Supply `onOpen` and an explicit `status`; the host owns setup and
|
|
44
|
+
installation. `ConnectionCatalog` accepts the same states through each option's
|
|
45
|
+
`state`. Older callers that omit `state` keep their visible status labels, so
|
|
46
|
+
provider warnings are not hidden during migration.
|
|
47
|
+
|
|
48
|
+
`PluginDiscovery` accepts `defaultProvider="openai"` or `"anthropic"` to choose
|
|
49
|
+
the initial registry. Omitting it starts with All. Users can still switch among
|
|
50
|
+
All, OpenAI, and Anthropic; changing the search preserves their selection. The
|
|
51
|
+
OpenGeni Plugins page starts with OpenAI.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { ConnectPanel } from "@opengeni/react/connect";
|
|
55
|
+
import "@opengeni/react/connect.css";
|
|
56
|
+
|
|
57
|
+
<ConnectPanel
|
|
58
|
+
controller={controller}
|
|
59
|
+
returnUrl={hostSelectedReturnUrl}
|
|
60
|
+
onAuthorize={hostAuthorizeFromClick}
|
|
61
|
+
/>;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The host owns synchronous popup/full-redirect navigation and pending-attempt
|
|
65
|
+
recovery. Backend state, not a popup message or URL query, proves completion.
|
|
66
|
+
Operation installation uses explicit selection; OAuth success alone is not
|
|
67
|
+
installation. Account disconnect requires an observed version and confirmation,
|
|
68
|
+
revokes local OpenGeni access only, and never silently retries an unknown outcome.
|
|
69
|
+
Provider readiness is deployment-dependent; use the server catalog rather than
|
|
70
|
+
assuming every OAuth application or operator-managed provider is configured.
|
|
71
|
+
|
|
72
|
+
Optional `@opengeni/react/sites` exports `SiteList`, `SiteDetail`, and `SiteClient`.
|
|
73
|
+
Pass the public SDK client through your host proxy. `onOpen` owns list
|
|
74
|
+
navigation. Authoring buttons and prompts belong to the host and use the ordinary
|
|
75
|
+
session SDK; they are not part of the Site component API. `SiteDetail` reuses `PublishedHtmlArtifactFrame`, accepts
|
|
76
|
+
an optional authenticated/filtered tool bridge, and removes the frame after
|
|
77
|
+
read-authority refresh failure. Loaded Sites revalidate every 15 seconds;
|
|
78
|
+
downloaded HTML cannot be recalled and every tool call still needs live authority.
|
|
79
|
+
|
|
80
|
+
`canPublish` is only a presentation hint. Version-checked rollback/archive/restore
|
|
81
|
+
remain subject to backend `artifacts:publish` permission. Sites stay workspace
|
|
82
|
+
shared, even if a source session is private. See
|
|
83
|
+
[`examples/embedded-product`](../../examples/embedded-product/README.md) for the
|
|
84
|
+
runnable loopback host reference. Native route reuse and full visual acceptance
|
|
85
|
+
are not implied by these optional package surfaces.
|
|
86
|
+
## Conversation UI
|
|
87
|
+
|
|
88
|
+
`SessionConversation` is the default product integration for an existing
|
|
89
|
+
session. Back it with `createSessionProxyHandler` from `@opengeni/sdk`, mounted
|
|
90
|
+
on your server, and point an unmodified browser
|
|
91
|
+
`new OpenGeniClient({ baseUrl: "/api/opengeni" })` at it:
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import "@opengeni/react/compiled.css";
|
|
95
|
+
|
|
96
|
+
<OpenGeniProvider client={client} workspaceId={workspaceId}>
|
|
97
|
+
<SessionConversation sessionId={sessionId} />
|
|
98
|
+
</OpenGeniProvider>;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Compose `MessageTimeline` and `ChatComposer` with the session hooks only when
|
|
102
|
+
the product needs a materially different interaction model. These components do
|
|
103
|
+
not consume the text-only `@opengeni/sdk/chat` fallback protocol.
|
|
104
|
+
|
|
105
|
+
`OpenGeniChat` adds the user's chat list to the conversation: a sidebar when
|
|
106
|
+
the component is wide and a drawer behind a menu button when narrow (measured on
|
|
107
|
+
its own container, so it works inside panels), a new-chat composer that creates
|
|
108
|
+
the session from its first message, and inline rename and archive. It is
|
|
109
|
+
composed from `SessionList` and `SessionConversation`, which you can also mount
|
|
110
|
+
separately. Pass `conversationProps` for message rendering and tool renderers,
|
|
111
|
+
`createSession` to create chats through your own endpoint, or `sessionId` /
|
|
112
|
+
`onSessionChange` to control the selection (for example from the URL).
|
|
113
|
+
|
|
114
|
+
`SessionConversation` and `OpenGeniChat` are built to look native inside
|
|
115
|
+
someone else's product with zero styling:
|
|
116
|
+
|
|
117
|
+
- **Theme follows the host**, not the OS: an enclosing `data-og-theme`, then
|
|
118
|
+
`class="dark"`/`data-theme` (and similar) on `<html>`/`<body>`, the host's
|
|
119
|
+
`color-scheme`, then the luminance of the background the chat sits on. Pass
|
|
120
|
+
`theme="light" | "dark"` to force one.
|
|
121
|
+
- **Surfaces blend into the host** (`surface="host"`, default): backgrounds and
|
|
122
|
+
cards are opaque mixes of the host background, so a navy app gets navy cards.
|
|
123
|
+
Host-customized `--og-color-*` tokens are kept; `surface="theme"` uses the
|
|
124
|
+
token surfaces as they are.
|
|
125
|
+
- **Run control is Stop, not Pause**: a Stop control appears only while a
|
|
126
|
+
response runs, and the next message continues a stopped conversation. Opt
|
|
127
|
+
into the console's workstream Pause with `composerProps={{ runControl: "pause" }}`
|
|
128
|
+
(`"none"` hides both).
|
|
129
|
+
- **No model picker by default**: end users rarely choose models. Pass
|
|
130
|
+
`modelPicker`, or report `modelSelection: true` from the proxy
|
|
131
|
+
(`createSessionProxyHandler({ modelSelection: true })`); `modelSelection: false`
|
|
132
|
+
also fixes the policy server-side.
|
|
133
|
+
|
|
134
|
+
Attachments appear when the deployment enables uploads (`attachments={false}`
|
|
135
|
+
opts out), pending tool approvals render Approve/Reject, a yes/no question
|
|
136
|
+
renders as two buttons, a failed load offers Try again, and `toolRegistry`
|
|
137
|
+
customizes tool rendering.
|
|
138
|
+
|
|
139
|
+
The root keeps all existing exports, including workbench components, but never
|
|
140
|
+
imports their optional peers. Conversation-only Next.js/Vite hosts do not need
|
|
141
|
+
terminal, desktop, editor, or diff packages. Hosts mounting those surfaces opt
|
|
142
|
+
in through the [per-surface setup entries](#optional-peer-dependencies).
|
|
143
|
+
|
|
144
|
+
Highlighted diffs use the optional `@pierre/diffs` peer only after an explicit
|
|
145
|
+
opt-in, so a host without it still builds with any bundler (Turbopack resolves
|
|
146
|
+
every reachable `import()`). Hosts that install it call `enablePierreDiffs()`
|
|
147
|
+
once; call it from the lazily loaded route that renders diffs to keep the peer
|
|
148
|
+
out of your initial bundle. Views already on screen upgrade when it registers:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import { enablePierreDiffs } from "@opengeni/react/diffs";
|
|
152
|
+
enablePierreDiffs();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Without it, diffs and file views render as plain text.
|
|
156
|
+
|
|
157
|
+
`OpenGeniProvider` never blocks or reloads the host page when OpenGeni deploys
|
|
158
|
+
a new API contract revision. The stock OpenGeni console opts into that
|
|
159
|
+
stale-tab protection with `reloadOnApiContractChange`; embedded products
|
|
160
|
+
should leave it off.
|
|
161
|
+
|
|
162
|
+
### Exact conversation search navigation
|
|
163
|
+
|
|
164
|
+
`useSessionEvents().initialHistoryReady` becomes true when a history window has
|
|
165
|
+
loaded successfully, including an empty tail. It stays true through later stream
|
|
166
|
+
errors, history navigation, and tip reloads, and resets for a new session/replay
|
|
167
|
+
identity. Use it rather than inferring initial success from `initialLoading` or
|
|
168
|
+
the combined `error`. A failed first load stays unready until recovery;
|
|
169
|
+
`jumpToLatest()` clears its stale error and retries. Full replay has no history
|
|
170
|
+
snapshot-completion watermark, so SSE alone does not set this flag.
|
|
171
|
+
|
|
172
|
+
`useSessionEvents(sessionId).jumpToSequence(sequence)` replaces the current
|
|
173
|
+
window with at most two bounded cursor reads around an exact durable event.
|
|
174
|
+
It resolves `true` only when that event is retained, `false` for a missing or
|
|
175
|
+
superseded target, and rejects current request errors. `loadingTarget` exposes
|
|
176
|
+
the pending state. New targets supersede older targets/pages; session/client
|
|
177
|
+
changes fence stale results. Search enters history mode; use the existing
|
|
178
|
+
`loadOlder`, `loadNewer`, and `jumpToLatest` controls to navigate onward. It does
|
|
179
|
+
not download the intervening session history.
|
|
180
|
+
Pass `jumpToSequence(sequence, { signal })` to cancel one navigation: an
|
|
181
|
+
aborted signal fences the pending jump before its fetched window is applied
|
|
182
|
+
(the underlying reads may still complete), resolves `false`, and settles
|
|
183
|
+
`loadingTarget` without disturbing any newer navigation that superseded it.
|
|
184
|
+
|
|
185
|
+
Pass the selected hit to `MessageTimeline` independently of loading:
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
const history = useSessionEvents(sessionId);
|
|
189
|
+
const [target, setTarget] = useState<TimelineSearchTarget | null>(null);
|
|
190
|
+
|
|
191
|
+
function selectHit(hit: { sequence: number; eventId: string }, query: string, occurrence = 0) {
|
|
192
|
+
setTarget({ ...hit, query, occurrence });
|
|
193
|
+
void history.jumpToSequence(hit.sequence);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
<MessageTimeline events={history.events} items={history.timeline} searchTarget={target} />;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The host owns search results, error handling, next/previous controls and query
|
|
200
|
+
state. `TimelineSearchTarget` is exported from the root and `session-ui` entry:
|
|
201
|
+
`{ sequence: number; eventId?: string; query: string; occurrence?: number; offset?: number }`.
|
|
202
|
+
Matching is literal, case-insensitive, non-overlapping; `occurrence` is zero-based
|
|
203
|
+
within the message, defaulting to zero. When the backend all-occurrence search
|
|
204
|
+
returns `messageMatchOffset`, pass it as `offset`: the zero-based UTF-16 position
|
|
205
|
+
of the match in the original message text. An explicit `offset` takes precedence
|
|
206
|
+
over `occurrence` and is validated against the query, so a stale offset simply
|
|
207
|
+
produces no highlight. `buildTimeline` supplies `sourceEvents`
|
|
208
|
+
identities so completed assistant events remain addressable when the renderer
|
|
209
|
+
keeps a first-delta ID. Hosts supplying their own items should preserve those
|
|
210
|
+
identities (or the canonical `annotationSource`).
|
|
211
|
+
|
|
212
|
+
The active message's group and long-user disclosure open persistently. Setting
|
|
213
|
+
`searchTarget={null}` removes the active highlight without collapsing content or
|
|
214
|
+
restoring a former scroll position. The package mounts its complete bounded
|
|
215
|
+
window. The default Markdown renderer shows a labeled, bounded **message source**
|
|
216
|
+
excerpt for the active match, including Markdown syntax and link destinations;
|
|
217
|
+
closing find removes the highlight but retains that excerpt and its layout.
|
|
218
|
+
An explicit **Show formatted message** action restores the full body; this can
|
|
219
|
+
expand a huge message, so it is never done automatically on closing Find.
|
|
220
|
+
Raw UTF-16 offsets are never applied
|
|
221
|
+
to rendered Markdown text. Custom hosts can use
|
|
222
|
+
`<Markdown searchTarget={searchTarget}>{text}</Markdown>` for the same behavior.
|
|
223
|
+
A custom virtualized renderer receives
|
|
224
|
+
`renderMessageText(text, item, { searchTarget })` and must materialize the exact
|
|
225
|
+
occurrence when that context is non-null. Existing two-argument renderers remain
|
|
226
|
+
compatible. If previous occurrences are omitted from the virtualized DOM, wrap
|
|
227
|
+
the materialized match in an element with `data-og-search-occurrence` (zero-based
|
|
228
|
+
index), `data-og-search-sequence` and `data-og-search-query`, each set from the
|
|
229
|
+
target; when the target carries an `offset`, set `data-og-search-offset` to it
|
|
230
|
+
alongside `data-og-search-occurrence` (which can be zero). This lets navigation
|
|
231
|
+
identify that exact occurrence without recounting an incomplete DOM. Keep the
|
|
232
|
+
materialized window when the context clears to
|
|
233
|
+
preserve position. Navigation waits for the mounted text and highlights the active
|
|
234
|
+
DOM range using the CSS Custom Highlight API, without rewriting React-owned
|
|
235
|
+
text. Explicit source-offset targets require this marker: matching characters
|
|
236
|
+
at the same rendered offset are not proof of source identity. A custom renderer
|
|
237
|
+
that omits source text or puts it in an opaque iframe must reveal that text
|
|
238
|
+
itself. Existing renderers without this mapping remain render-compatible but
|
|
239
|
+
cannot provide exact source-offset navigation.
|
|
240
|
+
|
|
27
241
|
## Editable Office artifacts
|
|
28
242
|
|
|
29
243
|
The optional artifact workbench is isolated from the ordinary session and
|
|
@@ -135,6 +349,21 @@ can therefore implement only the methods used by each hook. A shared event feed
|
|
|
135
349
|
also avoids requiring a client-owned event stream at runtime. Workspace-level
|
|
136
350
|
Resume is an optional authority.
|
|
137
351
|
|
|
352
|
+
Use `createEmbeddedSessionClient(base, options)` to bind that narrow surface
|
|
353
|
+
from a full SDK client or host proxy. Delegated methods preserve their SDK
|
|
354
|
+
receiver, `options.overrides.submitComposerDraft` can route atomic submission
|
|
355
|
+
through a host-authenticated endpoint, and `mapComposerDraft` can project every
|
|
356
|
+
read/save/submit draft before React adopts it. Construction fails immediately
|
|
357
|
+
when a required method is missing, and submit returns the host/native
|
|
358
|
+
`SubmitComposerDraftResponse` unchanged apart from an explicitly configured
|
|
359
|
+
draft projection.
|
|
360
|
+
|
|
361
|
+
The styled file surfaces accept a presentation-only node predicate:
|
|
362
|
+
`FileBrowser.isNodeVisible`, `SandboxFiles.isNodeVisible`, and
|
|
363
|
+
`SandboxWorkspace.isFileNodeVisible`. Hidden parents never expose orphaned
|
|
364
|
+
children, hidden selections/reveal requests are ignored, and omitting the prop
|
|
365
|
+
preserves the complete authoritative tree. This is not an authorization seam.
|
|
366
|
+
|
|
138
367
|
The styled root surface ships with ready-to-use CSS. Import it once; the host
|
|
139
368
|
does not need Tailwind:
|
|
140
369
|
|
|
@@ -272,7 +501,7 @@ function OpsChannel({ sessionId }: { sessionId: string }) {
|
|
|
272
501
|
status={sessionStatus}
|
|
273
502
|
hasOlder={hasOlder}
|
|
274
503
|
loadingOlder={loadingOlder}
|
|
275
|
-
onLoadOlder={
|
|
504
|
+
onLoadOlder={loadOlder}
|
|
276
505
|
className="min-h-0 flex-1"
|
|
277
506
|
/>
|
|
278
507
|
<QueueSurface queue={queue} composer={composer} />
|
|
@@ -353,7 +582,9 @@ exported `EmbeddedRealtimeSessionClientLike` requires only catalog, begin,
|
|
|
353
582
|
Codex/Gateway negotiation, activation, heartbeat, ledger sync, and end. For
|
|
354
583
|
custom layouts, use `useSessionRealtime`, `useRealtimeModelSelection`,
|
|
355
584
|
`RealtimeVoiceControl`, and `RealtimeModelPickerMenu`; the batteries-included
|
|
356
|
-
wrappers remain the recommended path.
|
|
585
|
+
wrappers remain the recommended path. Concurrent catalog reads are deduplicated
|
|
586
|
+
per client and workspace, and successful results are reused for a short bounded
|
|
587
|
+
window so embedded controls can remount without refetching.
|
|
357
588
|
|
|
358
589
|
The reference consumer is `demo/realtime.html`. Run `bun run demo` from
|
|
359
590
|
`packages/react`, then open `http://localhost:3100/realtime.html?mode=mock` for
|
|
@@ -389,6 +620,41 @@ workspace discovery, peer switching, tabs/windows, live frames, human input,
|
|
|
389
620
|
identity versions, interventions, diagnostics, reconnect, and lifecycle state do
|
|
390
621
|
not require app-private controller glue.
|
|
391
622
|
|
|
623
|
+
Managed browser actions keep the foreground tab in place. Target-local Chromium
|
|
624
|
+
focus emulation keeps animation callbacks running without an open preview;
|
|
625
|
+
explicit activation brings a tab forward. The override ends when its controller
|
|
626
|
+
detaches. Native **App controls** also work in the background where supported.
|
|
627
|
+
Physical desktop mouse/keyboard input shares the foreground seat; **Bring to front**
|
|
628
|
+
makes that change explicit.
|
|
629
|
+
Computer frames fit the dock while preserving their proportions. Resizing or
|
|
630
|
+
reopening the dock refits the visible image without changing capture resolution
|
|
631
|
+
or the coordinates sent to the computer.
|
|
632
|
+
Desktop opens a whole screen by default. Multiple screens use a compact screen
|
|
633
|
+
selector; app controls and window views are available from **Advanced**. Explicit
|
|
634
|
+
view choices survive refreshes while the target remains available.
|
|
635
|
+
|
|
636
|
+
Desktop IME candidates and their selection keys stay local; only committed text is sent.
|
|
637
|
+
|
|
638
|
+
A managed browser's attachment authority error keeps a same-browser **Reconnect**
|
|
639
|
+
action available. It obtains a fresh server-authorized attachment without creating
|
|
640
|
+
a replacement browser or replaying input. The fresh Connected Chrome instruction
|
|
641
|
+
is reserved for the selected extension-attached browser's generation loss; a
|
|
642
|
+
different lost browser in the workspace cannot change that recovery path.
|
|
643
|
+
|
|
644
|
+
The browser viewer negotiates bounded typing batches from the active controller's
|
|
645
|
+
short-lived attachment. Supporting helpers recheck the original controller,
|
|
646
|
+
target, document and frame fence before every action; old helpers retain one
|
|
647
|
+
request per action. Only queued text actions share a request (at most 16), with
|
|
648
|
+
each text/input event preserved. Keys, pointer input and clipboard operations
|
|
649
|
+
remain ordering barriers. A failed or uncertain action discards the queued suffix
|
|
650
|
+
without replay.
|
|
651
|
+
IME candidate-selection keys stay local to the viewer; only committed text is
|
|
652
|
+
sent to the remote page. A later ordinary Enter remains a remote key action.
|
|
653
|
+
Live image props use opaque byte buffers so React development timing diagnostics
|
|
654
|
+
cannot expand and retain every screenshot byte. Normal timing diagnostics remain enabled.
|
|
655
|
+
Queued inputs retain only immutable frame fences, not screenshot bytes or prior
|
|
656
|
+
render callbacks. Replacing the selected viewer invalidates its queued suffix.
|
|
657
|
+
|
|
392
658
|
```tsx
|
|
393
659
|
import { OpenGeniProvider } from "@opengeni/react";
|
|
394
660
|
import { BrowserViewer, ComputerViewer } from "@opengeni/react/interaction";
|
|
@@ -414,6 +680,33 @@ returned ComputerSession must be the exact placement/window the browser uses.
|
|
|
414
680
|
`onOpenComputer` then changes the host layout to that resource—it must not open a
|
|
415
681
|
lookalike desktop. Closing either viewer never ends its durable resource.
|
|
416
682
|
|
|
683
|
+
`ComputerViewer` disables input when its control service is unavailable, even if
|
|
684
|
+
frames keep arriving. Reconnect refreshes the selected desktop's controls and
|
|
685
|
+
frames. App accessibility inspection failures leave independent live input
|
|
686
|
+
available; `useComputerSession().controlError` reports service loss separately
|
|
687
|
+
from the hook's general `error`.
|
|
688
|
+
|
|
689
|
+
If the chat's latest browser was lost or failed, the viewer names it and explains
|
|
690
|
+
why it is unavailable instead of showing the ordinary empty state. It offers the
|
|
691
|
+
existing new-browser controls without reopening the lost controller or selecting
|
|
692
|
+
another chat's browser. Explicitly closed browsers still use the empty state;
|
|
693
|
+
older failures do not replace a newer closed browser. This loss notice also takes
|
|
694
|
+
precedence over `renderEmpty`. Preview the deadline-loss case with
|
|
695
|
+
`browser.html?mode=mock&lost=1` (add `width=360&theme=light` for a narrow light dock).
|
|
696
|
+
|
|
697
|
+
Native dropdown popups may not appear in page frames. With a controller that
|
|
698
|
+
advertises focused input observations, clicking one opens its choices beside
|
|
699
|
+
the click. Ordinary clicks use a bounded focus probe instead of a full page
|
|
700
|
+
snapshot; only a focused native dropdown (or a child-frame focus hint) requests
|
|
701
|
+
semantic options. Current controllers show no permanent **Choose option** button
|
|
702
|
+
over the page; older controllers retain that explicit fallback. **Alt+Down** opens
|
|
703
|
+
the focused dropdown and reads its options on either controller generation.
|
|
704
|
+
Selection uses the normal browser action API. The viewer retains that
|
|
705
|
+
observation's target/document/frame fence. Private, oversized, or ambiguous
|
|
706
|
+
choices remain unavailable; the page's keyboard controls still work. This
|
|
707
|
+
fallback requires a controller with focused native-select metadata support and
|
|
708
|
+
does not rewrite the page or capture the desktop.
|
|
709
|
+
|
|
417
710
|
The provider opens one shared workspace interaction-revision stream and every
|
|
418
711
|
catalog refreshes only when its revision advances; hidden or disconnected pages
|
|
419
712
|
fall back to bounded polling and reconcile from the retained cursor. Hosts that
|
|
@@ -426,6 +719,18 @@ same-origin `/demo-api` proxy and the exact published SDK/React entrypoints.
|
|
|
426
719
|
|
|
427
720
|
## Composer customization (`@opengeni/react/composer`)
|
|
428
721
|
|
|
722
|
+
`SessionChrome` accepts `onComposerFocus` for queue editing. Connect it to
|
|
723
|
+
`controller.focusInput` from `useChatComposerController`, or focus a custom
|
|
724
|
+
input through its ref. Chrome calls it after a successful checkout and
|
|
725
|
+
`composer.applyDraft`, including confirmed draft replacement; failed checkout
|
|
726
|
+
and pending/cancelled replacement do not request focus. The host retains
|
|
727
|
+
ownership of the input and no DOM selector or global focus event is needed.
|
|
728
|
+
|
|
729
|
+
When sharing `useSessionEvents().events` with `useGoal`, the hook still fetches
|
|
730
|
+
the authoritative goal on mount and target changes, even when the supplied log
|
|
731
|
+
already contains goal events. The shared log drives subsequent invalidations
|
|
732
|
+
without opening another event stream. A 404 remains a normal goal-less state.
|
|
733
|
+
|
|
429
734
|
Use `ChatComposer` for the standard layout and its `controlsStart`, `header`,
|
|
430
735
|
and `messages` props for small additions. For a different layout, import the
|
|
431
736
|
headless controller and compound primitives as a namespace. The controller is
|
|
@@ -504,20 +809,53 @@ state remains application-owned; durable draft and session state remain in
|
|
|
504
809
|
|
|
505
810
|
- `useSessionEvents(sessionId)` — loads a compact, bounded tail window by
|
|
506
811
|
default, then live-streams on the SDK's exactly-once/ordered event delivery.
|
|
507
|
-
Initial replay
|
|
812
|
+
Initial replay reads one 1000-row raw page, with at most one extra page to
|
|
813
|
+
recover a dense turn's boundary; `loadOlder` is capped at two such pages;
|
|
508
814
|
timeline group density is only an early stop. It returns the raw windowed
|
|
509
815
|
`events`, projected `timeline`, latest `sessionStatus`, connection state, and
|
|
510
816
|
older-history controls (`hasOlder`, `loadingOlder`, `loadOlder`). Pass
|
|
511
817
|
`replay: "full"` to opt back into full replay; a nonzero `after` keeps the
|
|
512
|
-
previous resume semantics.
|
|
818
|
+
previous resume semantics. `loadOlder()` remains await-compatible and resolves
|
|
819
|
+
to the existing `boolean`, while its promise also carries the causal
|
|
820
|
+
`committed` receipt used by `MessageTimeline`. Pass it directly or through an
|
|
821
|
+
existing wrapper, including `onLoadOlder={() => void loadOlder()}`; synchronous
|
|
822
|
+
receipt capture preserves the commit signal without narrowing the historical
|
|
823
|
+
callback return type. Custom loaders can use `createOlderHistoryLoadReceipt`
|
|
824
|
+
and call `markCommitted` immediately before publishing their accepted older
|
|
825
|
+
window.
|
|
826
|
+
- Browser retention limits are exported as `SESSION_EVENT_BROWSER_MAX_BYTES`
|
|
827
|
+
and `SESSION_EVENT_BROWSER_MAX_COUNT`; they do not change fetch page sizes.
|
|
828
|
+
The live working set is at most 16 MiB or 20,000 events. One event larger than
|
|
829
|
+
the byte target stays complete in a window of its own.
|
|
830
|
+
Live appends reuse the retained window's byte total, measuring only incoming
|
|
831
|
+
and evicted events. History still pages when either retention limit is reached.
|
|
832
|
+
- Newer history uses `hasNewer`, `loadingNewer`, and `loadNewer`. A failed
|
|
833
|
+
`loadNewer()` preserves the retained events and cursors, exposes the original
|
|
834
|
+
failure through `error`, and still rejects for the caller to handle. Pass
|
|
835
|
+
`onLoadNewer={loadNewer}` (or return its promise from your wrapper) to
|
|
836
|
+
`MessageTimeline`: it catches the request failure, shows the error and an
|
|
837
|
+
explicit **Retry later activity** action, and does not automatically retry
|
|
838
|
+
the failed boundary. A successful retry, jump to the start/latest window,
|
|
839
|
+
or session change clears that failure. Loading older rows alone does not
|
|
840
|
+
resolve a failed newer read. Late failures from a previous session are ignored.
|
|
841
|
+
A host that discards the promise must handle its own rejected request.
|
|
513
842
|
- `useComposer(sessionId, { sendExtras, effectiveControl })` — revisioned private
|
|
514
843
|
draft, Send, Steer, and workstream Pause/Resume state. `send()` appends in
|
|
515
|
-
visible queue order; `steer()`
|
|
844
|
+
visible queue order (including while paused); `steer()` puts the new direction
|
|
845
|
+
directly in chat and supersedes the current direction. Resume is always an
|
|
846
|
+
explicit control action and never an implicit side effect of Send. Drafts
|
|
516
847
|
autosave with optimistic concurrency, survive failed sends, and reuse one
|
|
517
|
-
`clientEventId` across retries so the server dedupes.
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
848
|
+
`clientEventId` across retries so the server dedupes. Draft reads retry transient
|
|
849
|
+
failures, including request timeouts, with backoff. Successful refreshes clear
|
|
850
|
+
draft-read errors without dismissing Send, Steer, or control errors; a draft
|
|
851
|
+
sync timeout does not mean the agent turn has stopped. `composer.policy` and
|
|
852
|
+
`setModel` / `setReasoningEffort` / `setLatencyMode` expose the exact policy
|
|
853
|
+
owned by that actor/session draft; policy is `null` until hydration completes.
|
|
854
|
+
`sendExtras` (object or function evaluated at send time) is only for
|
|
855
|
+
non-policy per-message fields such as live attachment resources and connection
|
|
856
|
+
authority. Disabling durable draft persistence requires an explicit
|
|
857
|
+
`initialPolicy`; no session or workspace fallback is invented. All human input
|
|
858
|
+
is plain chat text by design; approvals flow as control events
|
|
521
859
|
(`useSessionControl`), not bespoke widgets.
|
|
522
860
|
- `useTurnQueue(sessionId, { events })` — the one server-authoritative human
|
|
523
861
|
prompt queue with `moveTurn`, crash-safe `editTurn`, identity-preserving
|
|
@@ -545,13 +883,14 @@ state remains application-owned; durable draft and session state remain in
|
|
|
545
883
|
- `useSlashCommands(...)` — the slash-command palette state (registry + parsing +
|
|
546
884
|
handlers) behind `CommandPalette`.
|
|
547
885
|
- `useWorkspaceSessions()` / `useScheduledTasks()` — workspace lists for
|
|
548
|
-
fleet/manager views (optional polling).
|
|
886
|
+
fleet/manager views (optional polling). `useWorkspaceSessions({ projection:
|
|
887
|
+
"summary" })` returns compact list entries; omit the option for full sessions.
|
|
888
|
+
Scripted clients can omit the summary method and the hook projects full pages
|
|
889
|
+
locally while retaining cancellation and causal read revisions.
|
|
549
890
|
- `useVariableSets()` — workspace variable sets with metadata-only generic
|
|
550
891
|
reads and create/update/remove/set/delete operations. Dedicated permissioned
|
|
551
892
|
exact-value reveal is part of the held React/UI train rather than an
|
|
552
893
|
implicit field on ordinary reads.
|
|
553
|
-
- `usePacks()` — capability packs + installations with
|
|
554
|
-
register/enable/remove and `installationFor(packId)`.
|
|
555
894
|
- `useWorkspaces()` — the caller's workspaces with create/update (client-only;
|
|
556
895
|
not bound to the provider's workspace).
|
|
557
896
|
- `useBillingUsage({ accountId?, workspaceId? })` — credit balance + recent
|
|
@@ -589,8 +928,9 @@ intentional changes should regenerate those snapshots and review the diff.
|
|
|
589
928
|
|
|
590
929
|
## Components
|
|
591
930
|
|
|
592
|
-
- `ChatComposer` — auto-growing textarea, Enter-to-send (IME-safe),
|
|
593
|
-
|
|
931
|
+
- `ChatComposer` — auto-growing textarea, Enter-to-send (IME-safe), direct
|
|
932
|
+
Cmd/Ctrl+Enter steering, pause/resume controls, and inline finite error
|
|
933
|
+
recovery. Paused sends visibly join the queue without resuming. Slots for app chrome:
|
|
594
934
|
`controlsStart` (footer controls like model pickers / attach buttons),
|
|
595
935
|
`header` (e.g. attachment chips above the field), and `onPaste`
|
|
596
936
|
(paste-image-to-attach). Its advanced controller and compound primitives are
|
|
@@ -605,6 +945,15 @@ intentional changes should regenerate those snapshots and review the diff.
|
|
|
605
945
|
- `UserMessageBody` — the shared lossless rendered-height disclosure for
|
|
606
946
|
already-sent user text. Use it inside a custom `renderMessageText` user branch
|
|
607
947
|
so attachments and voice identity remain outside the clipped Markdown region.
|
|
948
|
+
Pass `disclosureLabels={{ showMore: "Afficher davantage", showLess: "Réduire" }}`
|
|
949
|
+
to localize a direct instance. For the default timeline, pass the same object
|
|
950
|
+
as `MessageTimeline.userMessageDisclosureLabels` or
|
|
951
|
+
`SessionConversation.userMessageDisclosureLabels`; custom `UserMessageBody`
|
|
952
|
+
renderers inside that timeline inherit these labels too. Each direct label
|
|
953
|
+
overrides its timeline label independently, then falls back to `Show more`
|
|
954
|
+
or `Show less`. Changing labels does not reset a message's expanded state.
|
|
955
|
+
`UserMessageDisclosureLabels` is exported from both `@opengeni/react` and
|
|
956
|
+
`@opengeni/react/session-ui`.
|
|
608
957
|
- `SessionStatus` / `StatusDot` — status badges; live states breathe.
|
|
609
958
|
- `FleetTile` — one session in a fleet grid: title, status, model, recency.
|
|
610
959
|
- `ModelPicker` — a compact model dropdown for a composer slot, grouping the
|
|
@@ -614,8 +963,26 @@ intentional changes should regenerate those snapshots and review the diff.
|
|
|
614
963
|
runnable latency modes such as Fast. It accepts either `ClientModel[]` or
|
|
615
964
|
catalog-backed `PickerModelRow[]`, and supports host-supplied labels.
|
|
616
965
|
- `Markdown` — the timeline's markdown renderer (GFM), also usable standalone.
|
|
966
|
+
Top-level assistant tables in `MessageTimeline` can expand beyond the prose
|
|
967
|
+
column into the actual conversation panel's available space. Small tables,
|
|
968
|
+
paragraphs, user bubbles, and nested or standalone Markdown keep their normal
|
|
969
|
+
width; oversized tables retain table-only horizontal scrolling. No host prop
|
|
970
|
+
or viewport-wide layout override is required.
|
|
971
|
+
Remeasurement during host rerenders or tail streaming does not temporarily
|
|
972
|
+
resize the live table or displace an unpinned history reader.
|
|
973
|
+
With `onSandboxFile`, a valid `sandbox:<path>[:line]` application link becomes
|
|
974
|
+
an in-session Open action. The callback receives the decoded path unchanged;
|
|
975
|
+
the optional line is positive and 1-based. Invalid sandbox references render
|
|
976
|
+
as disabled text, never as empty or browser-navigation links.
|
|
617
977
|
- `CommandPalette` — the slash-command palette UI over `useSlashCommands`.
|
|
618
978
|
|
|
979
|
+
`SandboxWorkspace.openFileRequest` is the host seam for that callback. Each new
|
|
980
|
+
`requestId` selects Files, opens the exact path on the already selected session
|
|
981
|
+
target, reveals its loaded/lazy ancestors in the file tree, selects and scrolls
|
|
982
|
+
to the file, and optionally focuses the requested line. A request without a line
|
|
983
|
+
opens the top of the file; file publication/download remains a separate explicit
|
|
984
|
+
artifact action.
|
|
985
|
+
|
|
619
986
|
The timeline is extensible: `createToolRegistry` / `defaultToolRegistry` plug
|
|
620
987
|
per-tool renderers, and the rendering primitives (`ActivityDisclosure`,
|
|
621
988
|
`ScreenshotFigure`, `TermBlock`, `LightboxProvider`, …) compose custom rows with
|
|
@@ -653,6 +1020,97 @@ remaining built-ins in supplied order. Duplicate IDs keep their first
|
|
|
653
1020
|
definition; remove a built-in before adding a custom facet with the same ID.
|
|
654
1021
|
`replace` is type-exclusive with `add` and `remove`.
|
|
655
1022
|
|
|
1023
|
+
`turnSummary={{ rolling: true }}` selects the readable per-turn presentation:
|
|
1024
|
+
startup shows the preparation orb outside any disclosure, then hands over to
|
|
1025
|
+
Working without resetting the startup-inclusive elapsed clock. While work is
|
|
1026
|
+
live, assistant progress messages stay fully formatted and visible,
|
|
1027
|
+
followed by one Working or Waiting disclosure with the rolling latest step.
|
|
1028
|
+
When the turn finishes, earlier assistant messages and tools share the Worked
|
|
1029
|
+
disclosure; the final response remains visible. Expanding reveals that turn's
|
|
1030
|
+
earlier prose and activity in chronological order, not a fold of multiple turns.
|
|
1031
|
+
An already expanded or actively read view is preserved through settlement.
|
|
1032
|
+
Routine machine inputs get one compact reason per resumed turn. Normal tip-follow
|
|
1033
|
+
continues through long answers, and manual scrolling never auto-repins on new work.
|
|
1034
|
+
Expanded outer work headers stay reachable at the top of the timeline until
|
|
1035
|
+
their own details end; nested headers never stick. The contextual navigation
|
|
1036
|
+
pill stays below the sticky-header strip and avoids interactive controls. If
|
|
1037
|
+
no horizontal slot fits beside a toolbar, only the pill moves below it; the
|
|
1038
|
+
timeline's size and scroll position do not change.
|
|
1039
|
+
|
|
1040
|
+
The single **Back to your message** button returns to the loaded user prompt
|
|
1041
|
+
associated with the response or work being read: the latest prompt preceding
|
|
1042
|
+
the viewport midpoint. It appears only when that prompt's start is more than
|
|
1043
|
+
24 px above the viewport and its entire body and attachments are out of view.
|
|
1044
|
+
Clicking synchronously scrolls and focuses that exact
|
|
1045
|
+
mounted prompt near the top and leaves tip-follow. Later messages and queued
|
|
1046
|
+
prompts do not change the destination while the reader remains in older work.
|
|
1047
|
+
An older bounded window uses its own loaded context; a window with no associated
|
|
1048
|
+
prompt shows no action. Navigation never replaces the history window or looks up
|
|
1049
|
+
the globally newest message. There are no previous/next arrows.
|
|
1050
|
+
|
|
1051
|
+
`SessionConversation` includes this behavior automatically. Custom timelines
|
|
1052
|
+
need no prompt-navigation callback:
|
|
1053
|
+
|
|
1054
|
+
```tsx
|
|
1055
|
+
const events = useSessionEvents(sessionId);
|
|
1056
|
+
<MessageTimeline
|
|
1057
|
+
events={events.events}
|
|
1058
|
+
items={events.timeline}
|
|
1059
|
+
turnSummary={{ rolling: true }}
|
|
1060
|
+
hasNewer={events.hasNewer}
|
|
1061
|
+
onJumpToLatest={events.jumpToLatest}
|
|
1062
|
+
/>;
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
`onJumpToLatest` retains its separate live-bottom behavior. The deprecated
|
|
1066
|
+
`MessageTimeline.onJumpToLatestQuestion` prop remains source-compatible but is
|
|
1067
|
+
not invoked by contextual navigation.
|
|
1068
|
+
|
|
1069
|
+
### Optional global newest-message lookup
|
|
1070
|
+
|
|
1071
|
+
The public `useSessionEvents().jumpToLatestQuestion()` hook remains available for
|
|
1072
|
+
hosts that deliberately build a **separate** global lookup action. It is not wired
|
|
1073
|
+
to `MessageTimeline` or the first-party conversation's contextual button.
|
|
1074
|
+
The hook checks the authoritative queue and normally uses one filtered forensic
|
|
1075
|
+
lookup plus, if needed, two bounded context reads. It pages past legacy worker
|
|
1076
|
+
completions and withdrawn/cancelled-before-start prompts, never substituting an
|
|
1077
|
+
arbitrary question from a loaded old page. Queued/legacy admission uses filtered
|
|
1078
|
+
lifecycle evidence to locate its real turn start. A distant prompt is retained as
|
|
1079
|
+
one projection-only witness in `events.timeline`; `events.events` remains the
|
|
1080
|
+
bounded contiguous raw window, so pass `items` as above.
|
|
1081
|
+
The optional resolver loads on its first invocation, not when opening a session.
|
|
1082
|
+
Identity and navigation guards also cover that module-loading delay.
|
|
1083
|
+
|
|
1084
|
+
Custom hosts can provide their own queue destination when invoking this hook:
|
|
1085
|
+
|
|
1086
|
+
```tsx
|
|
1087
|
+
const navigateToNewest = () => events.jumpToLatestQuestion({
|
|
1088
|
+
onQueuedQuestion: async (turn, navigation) => {
|
|
1089
|
+
await queue.refresh();
|
|
1090
|
+
if (!navigation.isCurrent()) return;
|
|
1091
|
+
// Check the host's latest queue/error state before applying its focus request.
|
|
1092
|
+
setQueueFocusTarget((previous) => ({
|
|
1093
|
+
turnId: turn.id,
|
|
1094
|
+
requestId: (previous?.requestId ?? 0) + 1,
|
|
1095
|
+
}));
|
|
1096
|
+
},
|
|
1097
|
+
});
|
|
1098
|
+
// Pass queueFocusTarget to SessionChrome; each new request opens/focuses once.
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
A queue destination returns `null`, not an invisible transcript sequence. Without
|
|
1102
|
+
`onQueuedQuestion`, a pending prompt rejects with `LatestQuestionQueuedError`;
|
|
1103
|
+
the custom host can show guidance. Transitional queue state can be retried.
|
|
1104
|
+
Check `navigation.isCurrent()` after awaits and immediately before queue UI effects:
|
|
1105
|
+
an explicit history jump can supersede a queued lookup without changing the session.
|
|
1106
|
+
The shared projection predicate supplies execution evidence for older queued turns
|
|
1107
|
+
without `turn.started`, including tools, agent/sandbox activity, startup, recovery,
|
|
1108
|
+
and capacity events. Compact cursor coverage skips coalesced delta runs.
|
|
1109
|
+
`groupTimeline(items)` retains classic
|
|
1110
|
+
grouping; `{ readableTurns: true }` selects the new projection. The deprecated
|
|
1111
|
+
`foldExchanges` option aliases readable turns, not the removed cross-turn fold. See
|
|
1112
|
+
[`docs/design/genie-loading.md`](../../docs/design/genie-loading.md).
|
|
1113
|
+
|
|
656
1114
|
## Sandbox surfacing
|
|
657
1115
|
|
|
658
1116
|
An opt-in workbench that surfaces a session's live sandbox — files, terminal,
|
|
@@ -672,13 +1130,24 @@ capability document so every surface degrades to a reason instead of crashing.
|
|
|
672
1130
|
firehose and the real interactive PTY over the minted `pty-ws` cell.
|
|
673
1131
|
- `useDesktopStream` — the noVNC socket, hot-swapped on box rollover via
|
|
674
1132
|
`stream.url.rotated`.
|
|
675
|
-
- Components: `WorkspaceDock` (the resizable/collapsible right-hand dock
|
|
1133
|
+
- Components: `WorkspaceDock` (the resizable/collapsible right-hand dock with a
|
|
1134
|
+
vertical activity rail, persistent visited panels, and a panel-local Hide action),
|
|
676
1135
|
`FileBrowser` / `SandboxFiles`, `DiffView` / `PierreDiff` / `PierreFile`,
|
|
677
1136
|
`CodeEditor`, `SandboxTerminal`, and `DesktopViewer`.
|
|
678
1137
|
|
|
679
1138
|
These surfaces pull in [optional peer dependencies](#optional-peer-dependencies)
|
|
680
1139
|
— install only the ones for surfaces you actually mount.
|
|
681
1140
|
|
|
1141
|
+
`SandboxWorkspace` keeps capture-backed file browsing passive, but an explicit
|
|
1142
|
+
live-file open acquires a viewer. Failed opens show the connection error and a
|
|
1143
|
+
retry that renegotiates the viewer instead of leaving a waking spinner running.
|
|
1144
|
+
When composing `SandboxFiles` directly, pass `workspaceError` alongside
|
|
1145
|
+
`liveWorkspaceReady` and supply an `onWakeWorkspace` callback that can retry a
|
|
1146
|
+
failed negotiation. Complete PNG, JPEG, GIF, and WebP reads render as read-only
|
|
1147
|
+
image previews; truncated reads and other binary formats remain non-editable
|
|
1148
|
+
notices. Image previews use the existing bounded file-read path and do not
|
|
1149
|
+
publish or retain additional files.
|
|
1150
|
+
|
|
682
1151
|
## Connected Machines (`@opengeni/react/machines`)
|
|
683
1152
|
|
|
684
1153
|
Bring-your-own-compute UI: the Machines dashboard, per-machine metrics, the
|
|
@@ -700,11 +1169,15 @@ never pull it in.
|
|
|
700
1169
|
plus the `MachineView` / `MachineState` / `MetricSample` view-model types.
|
|
701
1170
|
|
|
702
1171
|
```tsx
|
|
703
|
-
import {
|
|
1172
|
+
import {
|
|
1173
|
+
MACHINES_SESSION_POLL_MS,
|
|
1174
|
+
MachinesDashboard,
|
|
1175
|
+
useMachines,
|
|
1176
|
+
} from "@opengeni/react/machines";
|
|
704
1177
|
|
|
705
1178
|
function Fleet({ sessionId }: { sessionId: string }) {
|
|
706
1179
|
const { machines, activeSandboxId, attach, attachingSandboxId, refresh } =
|
|
707
|
-
useMachines({ sessionId, pollIntervalMs:
|
|
1180
|
+
useMachines({ sessionId, pollIntervalMs: MACHINES_SESSION_POLL_MS });
|
|
708
1181
|
return (
|
|
709
1182
|
<MachinesDashboard
|
|
710
1183
|
machines={machines}
|
|
@@ -720,11 +1193,46 @@ function Fleet({ sessionId }: { sessionId: string }) {
|
|
|
720
1193
|
See the [Connected Machines guide](../../docs/connected-machines.md) for the
|
|
721
1194
|
end-to-end embedder story (create-on-machine, discover, swap, enroll, revoke).
|
|
722
1195
|
|
|
1196
|
+
## Usage allowances (`@opengeni/react/usage`)
|
|
1197
|
+
|
|
1198
|
+
Show people where they stand against a workspace or member usage allowance.
|
|
1199
|
+
A separate subpath, so hosts that don't meter usage never load it.
|
|
1200
|
+
|
|
1201
|
+
- `useUsage({ workspaceId? })` — the signed-in person's own `/usage/me`
|
|
1202
|
+
(through `getMyUsage` or any client with `requestJson`) plus a summary of
|
|
1203
|
+
which limit binds first. `refreshKey` re-reads when work settles.
|
|
1204
|
+
- `UsageMeter` — "38% left · Resets Nov 1". Shares only; pass `formatAmount`
|
|
1205
|
+
for money, credits or plan multiples. `density="compact"` for menus,
|
|
1206
|
+
`"hero"` to lead a page.
|
|
1207
|
+
- `UsageLimitNotice` — the calm composer line: nothing while comfortable, a
|
|
1208
|
+
dismissible heads-up near the limit, then who can raise it and when it
|
|
1209
|
+
resets. `labels` rewords it; `action` adds your own "Upgrade" button.
|
|
1210
|
+
- `UsageMemberList` — the admin roster with a share-of-budget slider,
|
|
1211
|
+
optional fixed amounts, and a visible note when shares add up to more than
|
|
1212
|
+
the pool. Save rules through your backend in `onChangeRule`.
|
|
1213
|
+
|
|
1214
|
+
```tsx
|
|
1215
|
+
import { UsageLimitNotice, UsageMeter } from "@opengeni/react/usage";
|
|
1216
|
+
|
|
1217
|
+
<UsageMeter workspaceId={workspaceId} />
|
|
1218
|
+
<SessionConversation
|
|
1219
|
+
sessionId={sessionId}
|
|
1220
|
+
composerProps={{ header: <UsageLimitNotice workspaceId={workspaceId} /> }}
|
|
1221
|
+
allowanceExhaustedLabels={{ memberRemedy: "Ask your team admin for more." }}
|
|
1222
|
+
/>
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
The conversation's "usage limit reached" row is customized on
|
|
1226
|
+
`MessageTimeline`/`SessionConversation` with `allowanceExhaustedLabels` or
|
|
1227
|
+
replaced with `renderAllowanceExhausted`. See
|
|
1228
|
+
[usage allowances](../../docs/usage-allowances.md#react-components-and-the-console).
|
|
1229
|
+
|
|
723
1230
|
## Optional peer dependencies
|
|
724
1231
|
|
|
725
|
-
The chat/timeline surface
|
|
726
|
-
|
|
727
|
-
|
|
1232
|
+
The chat/timeline surface needs only the required React/React DOM peers. All
|
|
1233
|
+
existing root exports remain available without optional workbench peers, even
|
|
1234
|
+
when a bundler resolves every reachable dynamic import. Install and enable
|
|
1235
|
+
only the surfaces you mount, once in their client route or bootstrap:
|
|
728
1236
|
|
|
729
1237
|
- Terminal (`SandboxTerminal`): `@xterm/xterm`, `@xterm/addon-fit`,
|
|
730
1238
|
`@xterm/addon-web-links`.
|
|
@@ -734,6 +1242,37 @@ what the surfaces you mount need:
|
|
|
734
1242
|
language packs you need (`css`, `html`, `javascript`, `json`, `markdown`,
|
|
735
1243
|
`python`).
|
|
736
1244
|
|
|
1245
|
+
```ts
|
|
1246
|
+
import { enableSandboxTerminal } from "@opengeni/react/terminal";
|
|
1247
|
+
import { enableDesktopViewer } from "@opengeni/react/desktop";
|
|
1248
|
+
import { enableCodeEditor } from "@opengeni/react/editor";
|
|
1249
|
+
|
|
1250
|
+
enableSandboxTerminal();
|
|
1251
|
+
enableDesktopViewer();
|
|
1252
|
+
enableCodeEditor({
|
|
1253
|
+
javascript: async () =>
|
|
1254
|
+
(await import("@codemirror/lang-javascript")).javascript({ jsx: true, typescript: true }),
|
|
1255
|
+
});
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
Omit imports and calls for surfaces you do not use. These entries also re-export
|
|
1259
|
+
their components; root component imports continue to work after setup. The
|
|
1260
|
+
libraries load on mount, not during setup or SSR. Import the setup from a lazy
|
|
1261
|
+
route to keep its peer chunks outside the initial conversation graph.
|
|
1262
|
+
|
|
1263
|
+
For optional terminal WebGL acceleration, install `@xterm/addon-webgl` and call
|
|
1264
|
+
`enableSandboxTerminal({ webgl: () => import("@xterm/addon-webgl") })`. Without
|
|
1265
|
+
it, or if it fails, the terminal uses its DOM renderer. Only supply editor
|
|
1266
|
+
grammar loaders for packages you installed; absent/failed grammars use plain
|
|
1267
|
+
CodeMirror. Without editor setup, the existing textarea fallback remains usable.
|
|
1268
|
+
Without terminal/VNC setup, those surfaces show a setup error; relay-frame
|
|
1269
|
+
desktops and a custom `rfbFactory` need no noVNC setup.
|
|
1270
|
+
|
|
1271
|
+
Custom hosts may supply `registerSandboxTerminal`, `registerCodeEditor`, or
|
|
1272
|
+
`registerDesktopViewer` loaders from the root instead. Mounted fallbacks retry
|
|
1273
|
+
when registration changes. Do not hide peer imports behind runtime bare strings
|
|
1274
|
+
or `@vite-ignore`: browsers cannot resolve those without an import map.
|
|
1275
|
+
|
|
737
1276
|
## Demo harness
|
|
738
1277
|
|
|
739
1278
|
`bun run demo` (from this package) serves a harness that drives the real hooks
|
|
@@ -742,3 +1281,96 @@ with streaming, tool calls, and a worker spawn, plus fleet and scheduled-task
|
|
|
742
1281
|
views and a dark/light toggle. `realtime.html` is the public-package reference
|
|
743
1282
|
consumer described above, with deterministic mock and same-origin live modes.
|
|
744
1283
|
`bun run demo:build` is part of the repo gate.
|
|
1284
|
+
|
|
1285
|
+
### Model selection
|
|
1286
|
+
|
|
1287
|
+
`ModelPolicyPicker` opens a flat, searchable list grouped by payment source, with
|
|
1288
|
+
the selected model checked in its provider group. Choosing a model applies it and closes the popover.
|
|
1289
|
+
Thinking and supported speed controls remain in a fixed footer instead of a
|
|
1290
|
+
nested page. Model changes preserve supported reasoning effort and latency;
|
|
1291
|
+
unsupported effort falls back to the new model's default, and unsupported speed
|
|
1292
|
+
returns to Standard. Thinking uses inline radio choices and is hidden when the
|
|
1293
|
+
model has no adjustable reasoning levels. Availability and Codex-only session restrictions still disable choices.
|
|
1294
|
+
|
|
1295
|
+
The trigger renders immediately; the searchable popover loads when opened. Hosts
|
|
1296
|
+
can translate its search, current-selection, empty-result, attachment-warning, and
|
|
1297
|
+
thinking labels through `messages`, and override payment descriptions through
|
|
1298
|
+
`messages.billingHints`.
|
|
1299
|
+
|
|
1300
|
+
The stock deployment-provided group is labeled **Models**, with a generic model
|
|
1301
|
+
icon. It can contain both credit-backed and free models; the **Free** badge
|
|
1302
|
+
depends on the model's explicit cost, not its group. Genuine external-provider
|
|
1303
|
+
and subscription identities retain their own labels and marks.
|
|
1304
|
+
|
|
1305
|
+
Hosts can rebrand the full picker without replacing its interaction logic:
|
|
1306
|
+
|
|
1307
|
+
```tsx
|
|
1308
|
+
<ModelPolicyPicker
|
|
1309
|
+
{...pickerProps}
|
|
1310
|
+
groupPresentation={{
|
|
1311
|
+
opengeni_credits: {
|
|
1312
|
+
label: "Acme Assist",
|
|
1313
|
+
icon: <AcmeMark aria-hidden="true" />,
|
|
1314
|
+
description: "Provided by your workspace",
|
|
1315
|
+
},
|
|
1316
|
+
codex_subscription: { description: null },
|
|
1317
|
+
}}
|
|
1318
|
+
/>
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
`groupPresentation` is a partial map keyed by `PickerBillingClass`. Labels apply
|
|
1322
|
+
to group headings, search, and trigger-icon accessibility. Icons apply to both
|
|
1323
|
+
the menu and trigger; supply decorative, non-interactive content (SVG or image)
|
|
1324
|
+
that fits the existing 14px slot. Explicit `null` hides an icon or description;
|
|
1325
|
+
omitted fields retain defaults. Descriptions override `messages.billingHints`,
|
|
1326
|
+
can also be shown for the deployment-provided group, and are searchable. Existing
|
|
1327
|
+
`rows[].billingClassLabel` remains the fallback when no label override is supplied.
|
|
1328
|
+
This is presentation only: model IDs, billing, ordering, availability and callbacks
|
|
1329
|
+
are unchanged. The type `ModelPolicyPickerGroupPresentation` is exported from
|
|
1330
|
+
both `@opengeni/react` and `@opengeni/react/composer`. The native `ModelPicker`
|
|
1331
|
+
is a separate control; this API targets the full `ModelPolicyPicker` shown above.
|
|
1332
|
+
|
|
1333
|
+
The complete conversation uses this same neutral picker. Customize its appearance
|
|
1334
|
+
without replacing composer controls through `SessionConversation.modelPickerProps`,
|
|
1335
|
+
or through `OpenGeniChat.conversationProps`:
|
|
1336
|
+
|
|
1337
|
+
```tsx
|
|
1338
|
+
<OpenGeniChat
|
|
1339
|
+
client={client}
|
|
1340
|
+
workspaceId={workspaceId}
|
|
1341
|
+
conversationProps={{
|
|
1342
|
+
modelPickerProps: {
|
|
1343
|
+
groupPresentation: {
|
|
1344
|
+
opengeni_credits: { label: "Acme Assist", icon: <AcmeMark aria-hidden="true" /> },
|
|
1345
|
+
},
|
|
1346
|
+
messages: { label: "Choose a model" },
|
|
1347
|
+
},
|
|
1348
|
+
}}
|
|
1349
|
+
/>
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
`modelPickerProps` accepts only `groupPresentation` and `messages`; it does not
|
|
1353
|
+
enable a hidden picker or change policy, model availability or callbacks. Keep
|
|
1354
|
+
model-picker visibility controlled by `modelPicker` and the client configuration.
|
|
1355
|
+
|
|
1356
|
+
For a rendered example, open the composer-responsive demo with `?branding=host`.
|
|
1357
|
+
|
|
1358
|
+
Models always show their clean name and maker logo: picker rows carry
|
|
1359
|
+
`modelDisplayName(model)` (`claude-opus-4-8` and
|
|
1360
|
+
`organization-claude-subscription/claude-opus-5-5` read `Claude Opus 4.8` and
|
|
1361
|
+
`Claude Opus 5.5`) and a `ModelMark`. Organization- and workspace-connected API
|
|
1362
|
+
keys share one "API keys" group, and identical copies of one model in a
|
|
1363
|
+
connection group show once. Render a model anywhere else with
|
|
1364
|
+
`<ModelName model={id} />`, or `modelDisplayName` / `modelVendor` from
|
|
1365
|
+
`@opengeni/react` or `@opengeni/sdk/model-display`. The trigger keeps a host's
|
|
1366
|
+
explicit group icon; otherwise API-key models show the maker's logo.
|
|
1367
|
+
|
|
1368
|
+
Subscription descriptions appear once per provider group. Free models carry a
|
|
1369
|
+
Free badge. Pass `hasImageAttachments` for the current draft to show an image
|
|
1370
|
+
compatibility warning only when the selected model cannot view those images.
|
|
1371
|
+
|
|
1372
|
+
`MessageTimeline.renderMessageActions(item)` places host-owned controls beside
|
|
1373
|
+
Copy and the timestamp for user messages and completed assistant messages.
|
|
1374
|
+
The host owns feedback, fork authorization, and mutations; streaming assistant
|
|
1375
|
+
messages omit this slot. Use the `group/copy` hover/focus state and preserve
|
|
1376
|
+
visible touch targets when styling actions.
|