@opengeni/react 1.0.1 → 1.0.2-canary.37191796234001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +651 -21
- package/dist/accounts.d.ts +64 -0
- package/dist/accounts.js +822 -0
- package/dist/accounts.js.map +1 -0
- package/dist/approvals.d.ts +2 -1
- package/dist/artifacts-document.js +3 -2
- package/dist/artifacts-presentation.js +3 -2
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.d.ts +4 -1
- package/dist/artifacts.js +518 -42
- package/dist/artifacts.js.map +1 -1
- package/dist/browser-viewer-GTR5XQ7X.js +16 -0
- package/dist/capability-catalog-row.d.ts +20 -0
- package/dist/capability-logo-fallback.d.ts +3 -0
- package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
- package/dist/chat-interactive-block-UGBTNB3L.js.map +1 -0
- package/dist/{chunk-5UQPNLIO.js → chunk-23J2ZNXT.js} +4117 -3896
- package/dist/chunk-23J2ZNXT.js.map +1 -0
- package/dist/chunk-447JLCBU.js +209 -0
- package/dist/chunk-447JLCBU.js.map +1 -0
- package/dist/chunk-4RVYOY4O.js +379 -0
- package/dist/chunk-4RVYOY4O.js.map +1 -0
- package/dist/chunk-5CVXZA3Y.js +292 -0
- package/dist/chunk-5CVXZA3Y.js.map +1 -0
- package/dist/chunk-5J4FOW6Q.js +108 -0
- package/dist/chunk-5J4FOW6Q.js.map +1 -0
- package/dist/chunk-A2PI6UMY.js +41 -0
- package/dist/chunk-A2PI6UMY.js.map +1 -0
- package/dist/{chunk-7WCLAEFV.js → chunk-A4UJB2MM.js} +37 -27
- package/dist/chunk-A4UJB2MM.js.map +1 -0
- package/dist/chunk-B3V6TG77.js +41 -0
- package/dist/chunk-B3V6TG77.js.map +1 -0
- package/dist/chunk-BRM6FVZA.js +302 -0
- package/dist/chunk-BRM6FVZA.js.map +1 -0
- package/dist/chunk-C5X5AJXK.js +182 -0
- package/dist/chunk-C5X5AJXK.js.map +1 -0
- package/dist/chunk-CR7U7HAR.js +453 -0
- package/dist/chunk-CR7U7HAR.js.map +1 -0
- package/dist/{chunk-R3AZOAB5.js → chunk-DYWBUX5Q.js} +29 -123
- package/dist/chunk-DYWBUX5Q.js.map +1 -0
- package/dist/chunk-E3G7SAYZ.js +3124 -0
- package/dist/chunk-E3G7SAYZ.js.map +1 -0
- package/dist/chunk-ELCE5SXV.js +359 -0
- package/dist/chunk-ELCE5SXV.js.map +1 -0
- package/dist/chunk-ERGYJIBB.js +21 -0
- package/dist/chunk-ERGYJIBB.js.map +1 -0
- package/dist/chunk-FFA2OVOV.js +319 -0
- package/dist/chunk-FFA2OVOV.js.map +1 -0
- package/dist/chunk-FZCP527Y.js +116 -0
- package/dist/chunk-FZCP527Y.js.map +1 -0
- package/dist/chunk-GIMRELBW.js +14 -0
- package/dist/chunk-GIMRELBW.js.map +1 -0
- package/dist/{chunk-6KLX2RH5.js → chunk-H2NJQORO.js} +1069 -79
- package/dist/chunk-H2NJQORO.js.map +1 -0
- package/dist/chunk-I7IWRQLN.js +1608 -0
- package/dist/chunk-I7IWRQLN.js.map +1 -0
- package/dist/{chunk-HA46CYQK.js → chunk-IQUCRAT7.js} +792 -537
- package/dist/chunk-IQUCRAT7.js.map +1 -0
- package/dist/chunk-IWIDV7SB.js +1 -0
- package/dist/chunk-IWIDV7SB.js.map +1 -0
- package/dist/chunk-J2QWVSQY.js +312 -0
- package/dist/chunk-J2QWVSQY.js.map +1 -0
- package/dist/chunk-JFNEV4LU.js +2733 -0
- package/dist/chunk-JFNEV4LU.js.map +1 -0
- package/dist/chunk-JT4JW7BC.js +54 -0
- package/dist/chunk-JT4JW7BC.js.map +1 -0
- package/dist/chunk-K3HQAKQX.js +24 -0
- package/dist/chunk-K3HQAKQX.js.map +1 -0
- package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
- package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
- package/dist/chunk-NZUI76EM.js +371 -0
- package/dist/chunk-NZUI76EM.js.map +1 -0
- package/dist/{chunk-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
- package/dist/chunk-PNY3JKBJ.js.map +1 -0
- package/dist/{chunk-IGC6A2ZI.js → chunk-Q5QBEZIQ.js} +777 -246
- package/dist/chunk-Q5QBEZIQ.js.map +1 -0
- package/dist/chunk-RHREZ7BO.js +11 -0
- package/dist/chunk-RHREZ7BO.js.map +1 -0
- package/dist/chunk-SCOTPE2I.js +589 -0
- package/dist/chunk-SCOTPE2I.js.map +1 -0
- package/dist/{chunk-B6WPZSTT.js → chunk-SJZDKVW2.js} +1331 -1163
- package/dist/chunk-SJZDKVW2.js.map +1 -0
- package/dist/chunk-TMJRG4YC.js +12803 -0
- package/dist/chunk-TMJRG4YC.js.map +1 -0
- package/dist/chunk-TMYGL6X5.js +742 -0
- package/dist/chunk-TMYGL6X5.js.map +1 -0
- package/dist/chunk-UGLEYEMP.js +33 -0
- package/dist/chunk-UGLEYEMP.js.map +1 -0
- package/dist/chunk-UK4TINKT.js +27 -0
- package/dist/chunk-UK4TINKT.js.map +1 -0
- package/dist/chunk-UTRTG6LH.js +220 -0
- package/dist/chunk-UTRTG6LH.js.map +1 -0
- package/dist/chunk-WEHMPOXK.js +39 -0
- package/dist/chunk-WEHMPOXK.js.map +1 -0
- package/dist/chunk-WRHIZYZF.js +988 -0
- package/dist/chunk-WRHIZYZF.js.map +1 -0
- package/dist/{chunk-HUIKIDM5.js → chunk-WUISZ3WU.js} +223 -115
- package/dist/chunk-WUISZ3WU.js.map +1 -0
- package/dist/chunk-XCHWDJ22.js +107 -0
- package/dist/chunk-XCHWDJ22.js.map +1 -0
- package/dist/chunk-XOAMRDDK.js +481 -0
- package/dist/chunk-XOAMRDDK.js.map +1 -0
- package/dist/chunk-XUW2UWQM.js +299 -0
- package/dist/chunk-XUW2UWQM.js.map +1 -0
- package/dist/{chunk-KCGXPP5V.js → chunk-Y2PRMYLC.js} +11 -6
- package/dist/chunk-Y2PRMYLC.js.map +1 -0
- package/dist/chunk-YBXQDQFX.js +1772 -0
- package/dist/chunk-YBXQDQFX.js.map +1 -0
- package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
- package/dist/chunk-YQEAA6LT.js.map +1 -0
- package/dist/chunk-YV4L3ILF.js +9 -0
- package/dist/chunk-YV4L3ILF.js.map +1 -0
- package/dist/{chunk-LLOLUHVG.js → chunk-YWFG7ZX7.js} +1358 -2746
- package/dist/chunk-YWFG7ZX7.js.map +1 -0
- package/dist/chunk-ZYRGEKWS.js +216 -0
- package/dist/chunk-ZYRGEKWS.js.map +1 -0
- package/dist/client.d.ts +7 -4
- package/dist/clipboard.js +1 -0
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/anthropic-mark.d.ts +3 -0
- package/dist/components/approval-surface.d.ts +15 -0
- package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
- package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
- package/dist/components/artifacts/artifact-surface.d.ts +3 -1
- package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
- package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
- package/dist/components/artifacts/document-editor.d.ts +4 -2
- package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
- package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
- package/dist/components/artifacts/editable-document.d.ts +1 -1
- package/dist/components/artifacts/editable-presentation.d.ts +2 -2
- package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
- package/dist/components/artifacts/index.d.ts +8 -1
- package/dist/components/artifacts/inline-html-document.d.ts +2 -0
- package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
- package/dist/components/artifacts/presentation-editor.d.ts +6 -2
- package/dist/components/artifacts/published-html-artifact-frame.d.ts +48 -3
- package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
- package/dist/components/artifacts/site-view.d.ts +23 -0
- package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
- package/dist/components/artifacts/visualization-assets.gen.d.ts +2 -0
- package/dist/components/browser-select-control.d.ts +16 -0
- package/dist/components/browser-viewer.d.ts +10 -1
- package/dist/components/chat-composer.d.ts +21 -3
- package/dist/components/child-session-link.d.ts +5 -0
- package/dist/components/claude-mark.d.ts +3 -0
- package/dist/components/code-editor.d.ts +1 -4
- package/dist/components/composer.d.ts +45 -4
- package/dist/components/computer-viewer.d.ts +4 -1
- package/dist/components/copy-button.d.ts +3 -1
- package/dist/components/desktop-viewer.d.ts +1 -1
- package/dist/components/enrollment-consent.d.ts +6 -3
- package/dist/components/file-browser.d.ts +10 -1
- package/dist/components/fleet-tile.d.ts +2 -2
- package/dist/components/grok-mark.d.ts +26 -0
- package/dist/components/human-input-form.d.ts +21 -2
- package/dist/components/human-input-surface.d.ts +6 -3
- package/dist/components/machine-card.d.ts +4 -1
- package/dist/components/machines/machine-detail.d.ts +4 -1
- package/dist/components/machines/machine-operation-policy.d.ts +11 -0
- package/dist/components/machines-dashboard.d.ts +3 -1
- package/dist/components/markdown-table-layout.d.ts +12 -0
- package/dist/components/markdown.d.ts +47 -3
- package/dist/components/message-timeline.d.ts +72 -9
- package/dist/components/model-mark.d.ts +29 -0
- package/dist/components/model-policy-picker-menu.d.ts +9 -0
- package/dist/components/model-policy-picker.d.ts +62 -13
- package/dist/components/open-geni-chat.d.ts +55 -0
- package/dist/components/open-geni-links.d.ts +68 -0
- package/dist/components/openrouter-mark.d.ts +6 -0
- package/dist/components/pierre-file.d.ts +1 -1
- package/dist/components/preview-loading.d.ts +2 -0
- package/dist/components/queue-item-content.d.ts +9 -0
- package/dist/components/sandbox-files.d.ts +13 -2
- package/dist/components/sandbox-workspace.d.ts +43 -3
- package/dist/components/session-capability-frame.d.ts +35 -0
- package/dist/components/session-chrome.d.ts +66 -8
- package/dist/components/session-commands-panel.d.ts +6 -0
- package/dist/components/session-commands.d.ts +6 -0
- package/dist/components/session-connection-request.d.ts +8 -0
- package/dist/components/session-conversation.d.ts +86 -0
- package/dist/components/session-list.d.ts +36 -0
- package/dist/components/session-mcp-capability-card.d.ts +41 -0
- package/dist/components/timeline-anchor.d.ts +24 -0
- package/dist/components/timeline-annotation-chrome.d.ts +25 -0
- package/dist/components/timeline-annotation-layout.d.ts +42 -0
- package/dist/components/timeline-annotation-markers.d.ts +8 -0
- package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
- package/dist/components/timeline-annotation-shared.d.ts +31 -0
- package/dist/components/timeline-annotations-dialog.d.ts +3 -2
- package/dist/components/timeline-annotations.d.ts +13 -3
- package/dist/components/timeline-reading-progress.d.ts +11 -0
- package/dist/components/timeline-search.d.ts +34 -0
- package/dist/components/timeline-settlement.d.ts +16 -0
- package/dist/components/tip-follow.d.ts +16 -0
- package/dist/components/usage-limit-notice.d.ts +49 -0
- package/dist/components/usage-member-list.d.ts +91 -0
- package/dist/components/usage-meter.d.ts +73 -0
- package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
- package/dist/components/user-message-body.d.ts +10 -1
- package/dist/components/workspace-dock.d.ts +6 -2
- package/dist/composer.d.ts +5 -4
- package/dist/composer.js +15 -9
- package/dist/computer-viewer-ENHVAZ2Q.js +19 -0
- package/dist/computer-viewer-ENHVAZ2Q.js.map +1 -0
- package/dist/connect-account-identity.d.ts +8 -0
- package/dist/connect-accounts.d.ts +15 -0
- package/dist/connect-chooser.d.ts +18 -0
- package/dist/connect-panel.d.ts +18 -0
- package/dist/connect-setup.d.ts +16 -0
- package/dist/connect.d.ts +21 -0
- package/dist/connect.js +2129 -0
- package/dist/connect.js.map +1 -0
- package/dist/connection-catalog.d.ts +38 -0
- package/dist/connection-discovery.d.ts +12 -0
- package/dist/connection-installed.d.ts +17 -0
- package/dist/connection-logo.d.ts +9 -0
- package/dist/connection-service-logo.d.ts +8 -0
- package/dist/connection-service-presentation.d.ts +13 -0
- package/dist/connection-skeleton.d.ts +5 -0
- package/dist/connection-type-picker.d.ts +6 -0
- package/dist/conversation-timeline.d.ts +5 -0
- package/dist/desktop.d.ts +7 -0
- package/dist/desktop.js +26 -0
- package/dist/desktop.js.map +1 -0
- package/dist/device-authorization.d.ts +23 -0
- package/dist/diffs.d.ts +8 -0
- package/dist/diffs.js +14 -0
- package/dist/diffs.js.map +1 -0
- package/dist/discovery-cache.d.ts +5 -0
- package/dist/editor.d.ts +7 -0
- package/dist/editor.js +21 -0
- package/dist/editor.js.map +1 -0
- package/dist/embedded-session-client.d.ts +23 -0
- package/dist/file-node-visibility.d.ts +15 -0
- package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
- package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
- package/dist/hooks/channel-cache.d.ts +23 -0
- package/dist/hooks/latest-question.d.ts +25 -0
- package/dist/hooks/shared-machines-list.d.ts +14 -0
- package/dist/hooks/use-attached-browsers.d.ts +2 -1
- package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
- package/dist/hooks/use-browser-session.d.ts +12 -1
- package/dist/hooks/use-channels.d.ts +1 -0
- package/dist/hooks/use-codex-accounts.d.ts +25 -7
- package/dist/hooks/use-composer.d.ts +45 -9
- package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
- package/dist/hooks/use-computer-input-posture.d.ts +13 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-connect.d.ts +22 -0
- package/dist/hooks/use-desktop-stream.d.ts +1 -1
- package/dist/hooks/use-file-attachments.d.ts +21 -2
- package/dist/hooks/use-machine-chip.d.ts +3 -3
- package/dist/hooks/use-machines.d.ts +19 -1
- package/dist/hooks/use-sandbox-files.d.ts +5 -1
- package/dist/hooks/use-session-background-commands.d.ts +14 -0
- package/dist/hooks/use-session-events.d.ts +30 -8
- package/dist/hooks/use-session-lineage.d.ts +4 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
- package/dist/hooks/use-session.d.ts +6 -0
- package/dist/hooks/use-turn-queue.d.ts +12 -0
- package/dist/hooks/use-usage.d.ts +40 -0
- package/dist/hooks/use-workspace-edit.d.ts +4 -0
- package/dist/hooks/use-workspace-sessions.d.ts +27 -5
- package/dist/human-input.d.ts +3 -1
- package/dist/identity-link-accounts.d.ts +11 -0
- package/dist/identity-link-consent.d.ts +18 -0
- package/dist/index.d.ts +60 -17
- package/dist/index.js +2237 -6200
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.js +35 -184
- package/dist/interaction.js.map +1 -1
- package/dist/latest-question-755OW5DS.js +117 -0
- package/dist/latest-question-755OW5DS.js.map +1 -0
- package/dist/lib/error-message.d.ts +7 -0
- package/dist/lib/format.d.ts +36 -2
- package/dist/lib/host-theme.d.ts +70 -0
- package/dist/lib/interaction-errors.d.ts +6 -0
- package/dist/lib/menu-styles.d.ts +22 -0
- package/dist/lib/pierre-diffs-loader.d.ts +20 -0
- package/dist/lib/workbench-peers.d.ts +36 -0
- package/dist/lib/xterm-theme.d.ts +7 -5
- package/dist/machines.d.ts +4 -2
- package/dist/machines.js +14 -4
- package/dist/markdown-table-layout-QXSLK4BY.js +106 -0
- package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
- package/dist/mcp-connection-status.d.ts +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js +14 -0
- package/dist/model-policy-picker-menu-PWRI7R2X.js.map +1 -0
- package/dist/model-policy.d.ts +19 -3
- package/dist/model-policy.js +9 -1
- package/dist/older-history.d.ts +30 -0
- package/dist/platform-activity-row-627BFZ46.js +182 -0
- package/dist/platform-activity-row-627BFZ46.js.map +1 -0
- package/dist/plugin-details.d.ts +14 -0
- package/dist/plugin-discovery.d.ts +25 -0
- package/dist/provider.d.ts +13 -1
- package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-ZHFI5JBP.js} +131 -44
- package/dist/queue-surface-implementation-ZHFI5JBP.js.map +1 -0
- package/dist/realtime/realtime-control.d.ts +6 -3
- package/dist/realtime.js +133 -74
- package/dist/realtime.js.map +1 -1
- package/dist/sandbox-files-BBC47SLD.js +20 -0
- package/dist/sandbox-files-BBC47SLD.js.map +1 -0
- package/dist/session-auth-recommendation.d.ts +5 -0
- package/dist/session-capability-policy.d.ts +12 -0
- package/dist/session-ui.d.ts +30 -2
- package/dist/session-ui.js +85 -7
- package/dist/session-ui.js.map +1 -1
- package/dist/session.d.ts +8 -2
- package/dist/session.js +30 -19
- package/dist/sites-ui.d.ts +34 -0
- package/dist/sites.d.ts +3 -0
- package/dist/sites.js +11 -0
- package/dist/sites.js.map +1 -0
- package/dist/skill-discovery.d.ts +47 -0
- package/dist/terminal.d.ts +8 -0
- package/dist/terminal.js +31 -0
- package/dist/terminal.js.map +1 -0
- package/dist/timeline/activity-rail.d.ts +11 -2
- package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
- package/dist/timeline/compaction-copy.d.ts +10 -0
- package/dist/timeline/entrance.d.ts +13 -1
- package/dist/timeline/genie-loading.d.ts +34 -0
- package/dist/timeline/index.d.ts +6 -2
- package/dist/timeline/knowledge-receipt.d.ts +17 -0
- package/dist/timeline/platform-activity-row.d.ts +14 -0
- package/dist/timeline/presented-image.d.ts +6 -0
- package/dist/timeline/projection.d.ts +31 -2
- package/dist/timeline/registry.d.ts +2 -0
- package/dist/timeline/retained-image.d.ts +18 -0
- package/dist/timeline/rolling-activity.d.ts +11 -0
- package/dist/timeline/screenshot-lightbox.d.ts +16 -1
- package/dist/timeline/shared.d.ts +8 -3
- package/dist/timeline/startup-preference.d.ts +3 -0
- package/dist/timeline/startup-timings.d.ts +4 -0
- package/dist/timeline/tool-display-name.d.ts +2 -1
- package/dist/timeline/turn-summary.d.ts +32 -3
- package/dist/timeline/types.d.ts +141 -7
- package/dist/timeline-annotation-markers-GNDHTGBD.js +165 -0
- package/dist/timeline-annotation-markers-GNDHTGBD.js.map +1 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js +241 -0
- package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js +273 -0
- package/dist/timeline-annotations-dialog-ELRDBHTS.js.map +1 -0
- package/dist/types/machines.d.ts +2 -2
- package/dist/usage/allowance-copy.d.ts +25 -0
- package/dist/usage/summary.d.ts +35 -0
- package/dist/usage.d.ts +13 -0
- package/dist/usage.js +1074 -0
- package/dist/usage.js.map +1 -0
- package/package.json +44 -4
- package/src/accounts.tsx +1072 -0
- package/src/approvals.ts +8 -1
- package/src/artifacts.ts +42 -0
- package/src/assets/README.md +8 -0
- package/src/assets/gmail.ico +0 -0
- package/src/assets/outlook.ico +0 -0
- package/src/capability-catalog-row.tsx +94 -0
- package/src/capability-logo-fallback.ts +22 -0
- package/src/client.ts +22 -13
- package/src/commands/registry.ts +18 -15
- package/src/commands/types.ts +2 -0
- package/src/components/anthropic-mark.tsx +10 -0
- package/src/components/approval-surface.tsx +171 -37
- package/src/components/artifacts/artifact-chrome.tsx +413 -0
- package/src/components/artifacts/artifact-sandbox.tsx +185 -0
- package/src/components/artifacts/artifact-surface.tsx +39 -19
- package/src/components/artifacts/chat-interactive-block.tsx +260 -0
- package/src/components/artifacts/deferred-chat-media.tsx +67 -0
- package/src/components/artifacts/document-editor.tsx +141 -16
- package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
- package/src/components/artifacts/editable-artifact-view.tsx +187 -0
- package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
- package/src/components/artifacts/editable-document.tsx +37 -36
- package/src/components/artifacts/editable-presentation.tsx +36 -18
- package/src/components/artifacts/editable-spreadsheet.tsx +5 -2
- package/src/components/artifacts/index.ts +44 -0
- package/src/components/artifacts/inline-html-document.ts +24 -0
- package/src/components/artifacts/latest-task-runner.ts +49 -0
- package/src/components/artifacts/presentation-editor.tsx +323 -67
- package/src/components/artifacts/published-html-artifact-frame.tsx +338 -5
- package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
- package/src/components/artifacts/site-view.tsx +116 -0
- package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
- package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
- package/src/components/artifacts/spreadsheet-grid.tsx +12 -13
- package/src/components/artifacts/visualization-assets/base.css +1015 -0
- package/src/components/artifacts/visualization-assets/helpers.html +349 -0
- package/src/components/artifacts/visualization-assets.gen.ts +3 -0
- package/src/components/browser-select-control.tsx +312 -0
- package/src/components/browser-viewer.tsx +1054 -314
- package/src/components/chat-composer.tsx +131 -85
- package/src/components/child-session-link.tsx +27 -0
- package/src/components/claude-mark.tsx +10 -0
- package/src/components/code-editor.tsx +13 -16
- package/src/components/composer-transcription-control.tsx +7 -5
- package/src/components/composer.tsx +376 -49
- package/src/components/computer-viewer.tsx +1041 -329
- package/src/components/copy-button.tsx +13 -5
- package/src/components/desktop-viewer.tsx +1 -1
- package/src/components/enrollment-consent.tsx +65 -7
- package/src/components/enrollment-device-flow.tsx +1 -1
- package/src/components/file-browser.tsx +158 -34
- package/src/components/fleet-tile.tsx +8 -16
- package/src/components/generated-video-player.tsx +4 -2
- package/src/components/grok-mark.tsx +33 -0
- package/src/components/human-input-form.tsx +455 -114
- package/src/components/human-input-surface.tsx +18 -7
- package/src/components/interaction-intervention-banner.tsx +2 -2
- package/src/components/machine-card.tsx +119 -4
- package/src/components/machine-dock-bar.tsx +1 -1
- package/src/components/machine-input-display.ts +23 -2
- package/src/components/machines/machine-detail.tsx +52 -2
- package/src/components/machines/machine-operation-policy.tsx +179 -0
- package/src/components/machines-dashboard.tsx +8 -17
- package/src/components/markdown-table-layout.ts +132 -0
- package/src/components/markdown.tsx +473 -44
- package/src/components/message-timeline.tsx +2498 -663
- package/src/components/model-mark.tsx +90 -0
- package/src/components/model-picker.tsx +15 -4
- package/src/components/model-policy-picker-menu.tsx +424 -0
- package/src/components/model-policy-picker.tsx +337 -381
- package/src/components/open-geni-chat.tsx +319 -0
- package/src/components/open-geni-links.tsx +179 -0
- package/src/components/openrouter-mark.tsx +13 -0
- package/src/components/pierre-diff.tsx +41 -16
- package/src/components/pierre-file.tsx +36 -11
- package/src/components/preview-loading.tsx +154 -0
- package/src/components/queue-item-content.ts +14 -0
- package/src/components/queue-surface-implementation.tsx +132 -42
- package/src/components/queue-surface-state.tsx +3 -1
- package/src/components/sandbox-files.tsx +267 -35
- package/src/components/sandbox-terminal.tsx +48 -11
- package/src/components/sandbox-workspace.tsx +337 -135
- package/src/components/session-capability-frame.tsx +192 -0
- package/src/components/session-chrome.tsx +1027 -328
- package/src/components/session-commands-panel.tsx +126 -0
- package/src/components/session-commands.tsx +18 -0
- package/src/components/session-connection-request.tsx +97 -0
- package/src/components/session-conversation.tsx +512 -0
- package/src/components/session-list.tsx +250 -0
- package/src/components/session-mcp-capability-card.tsx +680 -0
- package/src/components/session-status.tsx +1 -1
- package/src/components/timeline-anchor.tsx +119 -0
- package/src/components/timeline-annotation-chrome.tsx +196 -0
- package/src/components/timeline-annotation-layout.ts +268 -0
- package/src/components/timeline-annotation-markers.tsx +185 -0
- package/src/components/timeline-annotation-reveal-context.ts +9 -0
- package/src/components/timeline-annotation-selection.tsx +106 -54
- package/src/components/timeline-annotation-shared.ts +245 -0
- package/src/components/timeline-annotations-dialog.tsx +185 -128
- package/src/components/timeline-annotations.tsx +189 -45
- package/src/components/timeline-reading-progress.ts +80 -0
- package/src/components/timeline-search.tsx +168 -0
- package/src/components/timeline-settlement.ts +60 -0
- package/src/components/tip-follow.ts +70 -7
- package/src/components/tooltip.tsx +38 -5
- package/src/components/usage-limit-notice.tsx +179 -0
- package/src/components/usage-member-list.tsx +792 -0
- package/src/components/usage-meter.tsx +382 -0
- package/src/components/use-viewer-menu-dismiss.ts +33 -0
- package/src/components/user-message-body.tsx +194 -49
- package/src/components/workspace-dock.tsx +141 -175
- package/src/composer.ts +6 -1
- package/src/connect-account-identity.tsx +34 -0
- package/src/connect-accounts.tsx +233 -0
- package/src/connect-chooser.tsx +336 -0
- package/src/connect-panel.tsx +99 -0
- package/src/connect-setup.tsx +307 -0
- package/src/connect.ts +60 -0
- package/src/connection-assets.d.ts +4 -0
- package/src/connection-catalog.tsx +162 -0
- package/src/connection-discovery.tsx +235 -0
- package/src/connection-installed.tsx +51 -0
- package/src/connection-logo.tsx +37 -0
- package/src/connection-service-logo.tsx +55 -0
- package/src/connection-service-presentation.ts +46 -0
- package/src/connection-skeleton.tsx +16 -0
- package/src/connection-type-picker.tsx +36 -0
- package/src/conversation-timeline.ts +92 -0
- package/src/desktop.ts +24 -0
- package/src/device-authorization.tsx +98 -0
- package/src/diffs.ts +16 -0
- package/src/discovery-cache.ts +42 -0
- package/src/editor.ts +13 -0
- package/src/embedded-session-client.ts +104 -0
- package/src/file-node-visibility.ts +66 -0
- package/src/hooks/channel-cache.ts +104 -0
- package/src/hooks/internal.ts +3 -2
- package/src/hooks/latest-question.ts +164 -0
- package/src/hooks/shared-machines-list.ts +239 -0
- package/src/hooks/use-attached-browsers.ts +5 -1
- package/src/hooks/use-available-models.ts +20 -14
- package/src/hooks/use-browser-frame-stream.ts +25 -3
- package/src/hooks/use-browser-session.ts +271 -71
- package/src/hooks/use-browser-sessions.ts +7 -1
- package/src/hooks/use-channels.ts +32 -10
- package/src/hooks/use-codex-accounts.ts +78 -21
- package/src/hooks/use-composer.ts +1034 -320
- package/src/hooks/use-computer-frame-stream.ts +39 -16
- package/src/hooks/use-computer-input-posture.ts +94 -0
- package/src/hooks/use-computer-session.ts +110 -32
- package/src/hooks/use-computer-sessions.ts +8 -1
- package/src/hooks/use-connect.ts +23 -0
- package/src/hooks/use-desktop-stream.ts +19 -28
- package/src/hooks/use-file-attachments.ts +118 -10
- package/src/hooks/use-goal.ts +36 -9
- package/src/hooks/use-human-input.ts +31 -4
- package/src/hooks/use-last-started-turn-policy.ts +15 -13
- package/src/hooks/use-machine-chip.ts +23 -6
- package/src/hooks/use-machines.ts +104 -6
- package/src/hooks/use-sandbox-files.ts +253 -150
- package/src/hooks/use-sandbox-git.ts +58 -29
- package/src/hooks/use-session-background-commands.ts +67 -0
- package/src/hooks/use-session-capabilities.ts +21 -2
- package/src/hooks/use-session-events.ts +759 -433
- package/src/hooks/use-session-lineage.ts +28 -6
- package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
- package/src/hooks/use-session.ts +75 -16
- package/src/hooks/use-slash-commands.ts +6 -11
- package/src/hooks/use-turn-queue.ts +113 -13
- package/src/hooks/use-usage.ts +100 -0
- package/src/hooks/use-voice-input.ts +12 -1
- package/src/hooks/use-workspace-capture.ts +3 -2
- package/src/hooks/use-workspace-edit.ts +23 -5
- package/src/hooks/use-workspace-sessions.ts +99 -11
- package/src/human-input.ts +12 -1
- package/src/identity-link-accounts.tsx +148 -0
- package/src/identity-link-consent.tsx +192 -0
- package/src/index.ts +157 -12
- package/src/interaction.ts +1 -0
- package/src/lib/error-message.ts +37 -0
- package/src/lib/format.ts +150 -14
- package/src/lib/host-theme.ts +511 -0
- package/src/lib/interaction-errors.ts +33 -0
- package/src/lib/menu-styles.ts +44 -0
- package/src/lib/pierre-diffs-loader.ts +53 -0
- package/src/lib/workbench-peers.ts +62 -0
- package/src/lib/xterm-theme.ts +23 -21
- package/src/machines.ts +9 -1
- package/src/mcp-connection-status.ts +35 -0
- package/src/model-policy.ts +223 -69
- package/src/older-history.ts +87 -0
- package/src/plugin-details.tsx +185 -0
- package/src/plugin-discovery.tsx +196 -0
- package/src/provider.tsx +55 -14
- package/src/realtime/dropdown-menu.tsx +19 -12
- package/src/realtime/realtime-control.tsx +133 -46
- package/src/session-auth-recommendation.ts +48 -0
- package/src/session-capability-policy.ts +83 -0
- package/src/session-context.ts +1 -0
- package/src/session-ui.ts +66 -2
- package/src/session.ts +18 -1
- package/src/sites-ui.tsx +402 -0
- package/src/sites.ts +3 -0
- package/src/skill-discovery.tsx +208 -0
- package/src/terminal.ts +26 -0
- package/src/timeline/activity-rail.tsx +171 -80
- package/src/timeline/allowance-exhausted-row.tsx +86 -0
- package/src/timeline/compaction-copy.ts +42 -0
- package/src/timeline/entrance.tsx +28 -3
- package/src/timeline/fleet-decision-projection.ts +2 -1
- package/src/timeline/fleet-decision-row.tsx +1 -0
- package/src/timeline/genie-loading.tsx +136 -0
- package/src/timeline/index.ts +11 -0
- package/src/timeline/knowledge-receipt.tsx +100 -0
- package/src/timeline/parsers.ts +2 -2
- package/src/timeline/platform-activity-row.tsx +216 -0
- package/src/timeline/presented-image.ts +49 -0
- package/src/timeline/projection.ts +1600 -84
- package/src/timeline/registry.ts +15 -3
- package/src/timeline/retained-image.ts +97 -0
- package/src/timeline/rolling-activity.tsx +92 -0
- package/src/timeline/screenshot-lightbox.tsx +115 -17
- package/src/timeline/shared.tsx +47 -15
- package/src/timeline/startup-preference.ts +33 -0
- package/src/timeline/startup-timings.tsx +145 -0
- package/src/timeline/tool-display-name.ts +8 -6
- package/src/timeline/tool-renderers.tsx +497 -128
- package/src/timeline/turn-summary.tsx +208 -44
- package/src/timeline/types.ts +186 -7
- package/src/types/machines.ts +10 -0
- package/src/usage/allowance-copy.ts +64 -0
- package/src/usage/summary.ts +93 -0
- package/src/usage.ts +50 -0
- package/styles/compiled.css +2098 -757
- package/styles/connect.css +284 -0
- package/styles/connect.d.ts +1 -0
- package/styles/effective-tokens.css +1 -0
- package/styles/index.css +201 -9
- package/styles/responsive.css +27 -1
- package/styles/session-capability.css +44 -0
- package/styles/tokens.css +135 -65
- package/dist/chunk-5UQPNLIO.js.map +0 -1
- package/dist/chunk-6KLX2RH5.js.map +0 -1
- package/dist/chunk-7WCLAEFV.js.map +0 -1
- package/dist/chunk-B6WPZSTT.js.map +0 -1
- package/dist/chunk-FK6VG4LL.js +0 -90
- package/dist/chunk-FK6VG4LL.js.map +0 -1
- package/dist/chunk-HA46CYQK.js.map +0 -1
- package/dist/chunk-HUIKIDM5.js.map +0 -1
- package/dist/chunk-IGC6A2ZI.js.map +0 -1
- package/dist/chunk-KCGXPP5V.js.map +0 -1
- package/dist/chunk-KZ73RL76.js.map +0 -1
- package/dist/chunk-LAKLF4PA.js +0 -141
- package/dist/chunk-LAKLF4PA.js.map +0 -1
- package/dist/chunk-LLOLUHVG.js.map +0 -1
- package/dist/chunk-MKPIAGVL.js +0 -465
- package/dist/chunk-MKPIAGVL.js.map +0 -1
- package/dist/chunk-PEI6RANI.js.map +0 -1
- package/dist/chunk-R3AZOAB5.js.map +0 -1
- package/dist/chunk-WSK7G5LE.js +0 -170
- package/dist/chunk-WSK7G5LE.js.map +0 -1
- package/dist/chunk-XBZWOM2K.js +0 -218
- package/dist/chunk-XBZWOM2K.js.map +0 -1
- package/dist/chunk-Y7OEDUJ5.js +0 -8810
- package/dist/chunk-Y7OEDUJ5.js.map +0 -1
- package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
- package/dist/hooks/use-packs.d.ts +0 -32
- package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
- package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
- package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
- package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
- package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
- package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
- package/src/hooks/use-packs.ts +0 -157
- /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GTR5XQ7X.js.map} +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useEffect, useRef, useState, type ReactNode } from "react";
|
|
2
|
+
import { copyTextToClipboard } from "./clipboard";
|
|
3
|
+
|
|
4
|
+
export type DeviceAuthorizationProps = {
|
|
5
|
+
userCode: string;
|
|
6
|
+
verificationUri: string;
|
|
7
|
+
providerLabel?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
codeAttributes?: Record<`data-${string}`, string>;
|
|
11
|
+
loadClipboard?: () => Promise<{ copyTextToClipboard(text: string): Promise<boolean> }>;
|
|
12
|
+
onCopyResult?: (copied: boolean) => void;
|
|
13
|
+
/** Optional host presentation; clipboard state and URL validation remain shared. */
|
|
14
|
+
render?: (state: {
|
|
15
|
+
copied: boolean;
|
|
16
|
+
copyError: boolean;
|
|
17
|
+
copy: () => Promise<void>;
|
|
18
|
+
verificationHref: string | undefined;
|
|
19
|
+
}) => ReactNode;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Optional presentation for the existing model-account device APIs. It neither
|
|
23
|
+
* owns provider state nor assumes that opening a verification page completed it. */
|
|
24
|
+
export function DeviceAuthorization(props: DeviceAuthorizationProps) {
|
|
25
|
+
const [copied, setCopied] = useState(false);
|
|
26
|
+
const [copyError, setCopyError] = useState(false);
|
|
27
|
+
const generation = useRef(0);
|
|
28
|
+
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
generation.current++;
|
|
31
|
+
setCopied(false);
|
|
32
|
+
setCopyError(false);
|
|
33
|
+
return () => {
|
|
34
|
+
// This is a live async-operation counter, not a captured DOM ref.
|
|
35
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
|
+
generation.current++;
|
|
37
|
+
if (timer.current) clearTimeout(timer.current);
|
|
38
|
+
};
|
|
39
|
+
}, [props.userCode]);
|
|
40
|
+
async function copy() {
|
|
41
|
+
const revision = ++generation.current;
|
|
42
|
+
if (timer.current) clearTimeout(timer.current);
|
|
43
|
+
setCopied(false);
|
|
44
|
+
setCopyError(false);
|
|
45
|
+
try {
|
|
46
|
+
const clipboard = props.loadClipboard ? await props.loadClipboard() : { copyTextToClipboard };
|
|
47
|
+
if (revision !== generation.current) return;
|
|
48
|
+
const success = await clipboard.copyTextToClipboard(props.userCode);
|
|
49
|
+
if (revision !== generation.current) return;
|
|
50
|
+
setCopied(success);
|
|
51
|
+
setCopyError(!success);
|
|
52
|
+
props.onCopyResult?.(success);
|
|
53
|
+
if (success)
|
|
54
|
+
timer.current = setTimeout(() => {
|
|
55
|
+
if (revision === generation.current) setCopied(false);
|
|
56
|
+
}, 1600);
|
|
57
|
+
} catch {
|
|
58
|
+
if (revision !== generation.current) return;
|
|
59
|
+
setCopyError(true);
|
|
60
|
+
props.onCopyResult?.(false);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let href: string | undefined;
|
|
64
|
+
try {
|
|
65
|
+
const url = new URL(props.verificationUri);
|
|
66
|
+
if (["https:", "http:"].includes(url.protocol) && !url.username && !url.password)
|
|
67
|
+
href = props.verificationUri;
|
|
68
|
+
} catch {
|
|
69
|
+
/* A malformed provider URL must never become an executable link. */
|
|
70
|
+
}
|
|
71
|
+
if (props.render) return props.render({ copied, copyError, copy, verificationHref: href });
|
|
72
|
+
return (
|
|
73
|
+
<section className={`og-connect ${props.className ?? ""}`} aria-label="Device authorization">
|
|
74
|
+
<p>{props.description ?? `Enter this code at ${props.providerLabel ?? "the provider"}.`}</p>
|
|
75
|
+
<div style={{ display: "flex", flexWrap: "wrap", gap: "0.5rem", alignItems: "center" }}>
|
|
76
|
+
<code {...props.codeAttributes} style={{ overflowWrap: "anywhere" }}>
|
|
77
|
+
{props.userCode}
|
|
78
|
+
</code>
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
aria-label={copied ? "Code copied" : "Copy code"}
|
|
82
|
+
onClick={() => void copy()}
|
|
83
|
+
>
|
|
84
|
+
{copied ? "Copied" : "Copy code"}
|
|
85
|
+
</button>
|
|
86
|
+
{href ? (
|
|
87
|
+
<a href={href} target="_blank" rel="noopener noreferrer">
|
|
88
|
+
Open {props.providerLabel ?? "auth page"}
|
|
89
|
+
</a>
|
|
90
|
+
) : (
|
|
91
|
+
<span role="alert">Authorization address unavailable.</span>
|
|
92
|
+
)}
|
|
93
|
+
</div>
|
|
94
|
+
{copyError ? <p role="alert">Couldn't copy the code. Copy it manually instead.</p> : null}
|
|
95
|
+
<p role="status">Waiting for authorization…</p>
|
|
96
|
+
</section>
|
|
97
|
+
);
|
|
98
|
+
}
|
package/src/diffs.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { registerPierreDiffs } from "./lib/pierre-diffs-loader";
|
|
2
|
+
|
|
3
|
+
export { registerPierreDiffs, type PierreDiffsLoader } from "./lib/pierre-diffs-loader";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Enable Shiki-highlighted diffs and file views from the optional
|
|
7
|
+
* `@pierre/diffs` peer. Call once at startup, only when the host installs it.
|
|
8
|
+
* This is the only module in the package that names the peer, so hosts that
|
|
9
|
+
* skip it build without `@pierre/diffs` and render plain-text diffs.
|
|
10
|
+
*/
|
|
11
|
+
export function enablePierreDiffs(): void {
|
|
12
|
+
registerPierreDiffs(loadPierreDiffsModule);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// One stable loader identity, so repeated enable calls are no-ops.
|
|
16
|
+
const loadPierreDiffsModule = () => import("@pierre/diffs/react");
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Short-lived presentation data only. Never cache installation or authorization state. */
|
|
2
|
+
export function createDiscoveryCache<T>(ttlMs = 60_000, capacity = 64) {
|
|
3
|
+
const clients = new WeakMap<
|
|
4
|
+
object,
|
|
5
|
+
Map<string, { expires: number; value: T | undefined; pending: Promise<T> }>
|
|
6
|
+
>();
|
|
7
|
+
return {
|
|
8
|
+
peek(client: object, key: string): T | undefined {
|
|
9
|
+
const entry = clients.get(client)?.get(key);
|
|
10
|
+
return entry && entry.expires > Date.now() ? entry.value : undefined;
|
|
11
|
+
},
|
|
12
|
+
read(client: object, key: string, fetch: () => Promise<T>): Promise<T> {
|
|
13
|
+
let entries = clients.get(client);
|
|
14
|
+
if (!entries) {
|
|
15
|
+
entries = new Map();
|
|
16
|
+
clients.set(client, entries);
|
|
17
|
+
}
|
|
18
|
+
const existing = entries.get(key);
|
|
19
|
+
if (existing && existing.expires > Date.now()) return existing.pending;
|
|
20
|
+
entries.delete(key);
|
|
21
|
+
while (entries.size >= capacity) entries.delete(entries.keys().next().value!);
|
|
22
|
+
const entry = {
|
|
23
|
+
expires: Date.now() + ttlMs,
|
|
24
|
+
value: undefined as T | undefined,
|
|
25
|
+
pending: Promise.resolve().then(fetch),
|
|
26
|
+
};
|
|
27
|
+
entries.set(key, entry);
|
|
28
|
+
entry.pending = entry.pending.then(
|
|
29
|
+
(value) => {
|
|
30
|
+
entry.value = value;
|
|
31
|
+
entry.expires = Date.now() + ttlMs;
|
|
32
|
+
return value;
|
|
33
|
+
},
|
|
34
|
+
(error) => {
|
|
35
|
+
if (entries.get(key) === entry) entries.delete(key);
|
|
36
|
+
throw error;
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
return entry.pending;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
package/src/editor.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { registerCodeEditor, type CodeEditorLanguages } from "./lib/workbench-peers";
|
|
2
|
+
|
|
3
|
+
export { CodeEditor, languageForPath } from "./components/code-editor";
|
|
4
|
+
export type { CodeEditorProps } from "./components/code-editor";
|
|
5
|
+
export { registerCodeEditor } from "./lib/workbench-peers";
|
|
6
|
+
export type { CodeEditorLanguage, CodeEditorLanguages } from "./lib/workbench-peers";
|
|
7
|
+
|
|
8
|
+
const loadEditor = async () => ({ module: await import("@uiw/react-codemirror") });
|
|
9
|
+
|
|
10
|
+
/** Only name installed grammar peers in host-supplied language loaders. */
|
|
11
|
+
export function enableCodeEditor(languages?: CodeEditorLanguages): void {
|
|
12
|
+
registerCodeEditor(languages ? async () => ({ ...(await loadEditor()), languages }) : loadEditor);
|
|
13
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { ComposerDraft } from "@opengeni/sdk";
|
|
2
|
+
import type { EmbeddedSessionClientLike } from "./client";
|
|
3
|
+
|
|
4
|
+
export type ComposerDraftMapContext = {
|
|
5
|
+
operation: "read" | "save" | "submit";
|
|
6
|
+
workspaceId: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type CreateEmbeddedSessionClientOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* Explicit host-owned method replacements. Methods inherited from `base`
|
|
13
|
+
* retain `base` as their receiver; overrides retain this object as theirs.
|
|
14
|
+
*/
|
|
15
|
+
overrides?: Partial<EmbeddedSessionClientLike> | undefined;
|
|
16
|
+
/** Presentation/policy projection for every draft entering the React layer. */
|
|
17
|
+
mapComposerDraft?:
|
|
18
|
+
| ((draft: ComposerDraft, context: ComposerDraftMapContext) => ComposerDraft)
|
|
19
|
+
| undefined;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const requiredMethods = [
|
|
23
|
+
"getSession",
|
|
24
|
+
"listEvents",
|
|
25
|
+
"streamEvents",
|
|
26
|
+
"getComposerDraft",
|
|
27
|
+
"saveComposerDraft",
|
|
28
|
+
"submitComposerDraft",
|
|
29
|
+
"sendMessage",
|
|
30
|
+
"steerMessage",
|
|
31
|
+
"getQueue",
|
|
32
|
+
"moveQueueItem",
|
|
33
|
+
"editQueueItem",
|
|
34
|
+
"steerQueueItem",
|
|
35
|
+
"deleteQueueItem",
|
|
36
|
+
"pauseSession",
|
|
37
|
+
"resumeSession",
|
|
38
|
+
"sendApprovalDecision",
|
|
39
|
+
] as const satisfies readonly (keyof EmbeddedSessionClientLike)[];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build the exact client required by `@opengeni/react/session` from a full SDK
|
|
43
|
+
* client or host proxy. The constructor binds every delegated method once,
|
|
44
|
+
* supports a host-owned atomic composer-submit override, and fails at creation
|
|
45
|
+
* time instead of waiting for a missing method to be exercised by a hook.
|
|
46
|
+
*/
|
|
47
|
+
export function createEmbeddedSessionClient(
|
|
48
|
+
base: EmbeddedSessionClientLike,
|
|
49
|
+
options: CreateEmbeddedSessionClientOptions = {},
|
|
50
|
+
): EmbeddedSessionClientLike {
|
|
51
|
+
const overrides = options.overrides ?? {};
|
|
52
|
+
const client = {} as EmbeddedSessionClientLike;
|
|
53
|
+
for (const key of requiredMethods) {
|
|
54
|
+
const override = overrides[key];
|
|
55
|
+
const method = override ?? base[key];
|
|
56
|
+
if (typeof method !== "function") {
|
|
57
|
+
throw new TypeError(`Embedded session client method is required: ${key}`);
|
|
58
|
+
}
|
|
59
|
+
client[key] = method.bind(override === undefined ? base : overrides) as never;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const inferenceOverride = overrides.setWorkspaceInferenceState;
|
|
63
|
+
const inferenceBase = base.setWorkspaceInferenceState;
|
|
64
|
+
const inferenceMethod = inferenceOverride ?? inferenceBase;
|
|
65
|
+
if (typeof inferenceMethod === "function") {
|
|
66
|
+
client.setWorkspaceInferenceState = inferenceMethod.bind(
|
|
67
|
+
inferenceOverride === undefined ? base : overrides,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const mapDraft = options.mapComposerDraft;
|
|
72
|
+
if (!mapDraft) return client;
|
|
73
|
+
|
|
74
|
+
const getComposerDraft = client.getComposerDraft;
|
|
75
|
+
client.getComposerDraft = async (workspaceId, sessionId) =>
|
|
76
|
+
mapDraft(await getComposerDraft(workspaceId, sessionId), {
|
|
77
|
+
operation: "read",
|
|
78
|
+
workspaceId,
|
|
79
|
+
sessionId,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const saveComposerDraft = client.saveComposerDraft;
|
|
83
|
+
client.saveComposerDraft = async (workspaceId, sessionId, request) =>
|
|
84
|
+
mapDraft(await saveComposerDraft(workspaceId, sessionId, request), {
|
|
85
|
+
operation: "save",
|
|
86
|
+
workspaceId,
|
|
87
|
+
sessionId,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const submitComposerDraft = client.submitComposerDraft;
|
|
91
|
+
client.submitComposerDraft = async (workspaceId, sessionId, request) => {
|
|
92
|
+
const response = await submitComposerDraft(workspaceId, sessionId, request);
|
|
93
|
+
return {
|
|
94
|
+
...response,
|
|
95
|
+
draft: mapDraft(response.draft, {
|
|
96
|
+
operation: "submit",
|
|
97
|
+
workspaceId,
|
|
98
|
+
sessionId,
|
|
99
|
+
}),
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return client;
|
|
104
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { FileTreeNode } from "./hooks/use-sandbox-files";
|
|
2
|
+
|
|
3
|
+
export type FileNodeVisibilityContext = {
|
|
4
|
+
depth: number;
|
|
5
|
+
parent: FileTreeNode | null;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/** Presentation-only predicate. It never changes filesystem authorization. */
|
|
9
|
+
export type FileNodeVisibilityPredicate = (
|
|
10
|
+
node: FileTreeNode,
|
|
11
|
+
context: FileNodeVisibilityContext,
|
|
12
|
+
) => boolean;
|
|
13
|
+
|
|
14
|
+
export type FilePathVisibility = "visible" | "hidden" | "unknown";
|
|
15
|
+
|
|
16
|
+
function pathIsInsideDirectory(path: string, directory: string): boolean {
|
|
17
|
+
if (!path.startsWith(directory) || path === directory) return false;
|
|
18
|
+
if (directory.endsWith("/") || directory.endsWith("\\")) return true;
|
|
19
|
+
const boundary = path[directory.length];
|
|
20
|
+
return boundary === "/" || boundary === "\\";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Filter an authoritative tree without promoting children of a hidden parent.
|
|
25
|
+
* Undefined children stay undefined so lazy-loading semantics are preserved.
|
|
26
|
+
*/
|
|
27
|
+
export function visibleFileTree(
|
|
28
|
+
nodes: FileTreeNode[],
|
|
29
|
+
predicate?: FileNodeVisibilityPredicate,
|
|
30
|
+
parent: FileTreeNode | null = null,
|
|
31
|
+
depth = 0,
|
|
32
|
+
): FileTreeNode[] {
|
|
33
|
+
if (!predicate) return nodes;
|
|
34
|
+
const visible: FileTreeNode[] = [];
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
if (!predicate(node, { depth, parent })) continue;
|
|
37
|
+
visible.push(
|
|
38
|
+
node.children === undefined
|
|
39
|
+
? node
|
|
40
|
+
: {
|
|
41
|
+
...node,
|
|
42
|
+
children: visibleFileTree(node.children, predicate, node, depth + 1),
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return visible;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Resolve only what the currently loaded tree can prove. */
|
|
50
|
+
export function filePathVisibility(
|
|
51
|
+
nodes: FileTreeNode[],
|
|
52
|
+
path: string,
|
|
53
|
+
predicate?: FileNodeVisibilityPredicate,
|
|
54
|
+
parent: FileTreeNode | null = null,
|
|
55
|
+
depth = 0,
|
|
56
|
+
): FilePathVisibility {
|
|
57
|
+
if (!predicate) return "visible";
|
|
58
|
+
for (const node of nodes) {
|
|
59
|
+
if (node.path !== path && !pathIsInsideDirectory(path, node.path)) continue;
|
|
60
|
+
if (!predicate(node, { depth, parent })) return "hidden";
|
|
61
|
+
if (node.path === path) return "visible";
|
|
62
|
+
if (node.kind !== "dir" || node.children === undefined) return "unknown";
|
|
63
|
+
return filePathVisibility(node.children, path, predicate, node, depth + 1);
|
|
64
|
+
}
|
|
65
|
+
return "unknown";
|
|
66
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Channel } from "@opengeni/sdk";
|
|
2
|
+
import type { SessionClientLike } from "../client";
|
|
3
|
+
|
|
4
|
+
type PendingChannel = { channel: Channel; committedAfterLoad: number };
|
|
5
|
+
|
|
6
|
+
export type ChannelCacheSnapshot = Readonly<{
|
|
7
|
+
channels: readonly Channel[];
|
|
8
|
+
ready: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
|
|
11
|
+
export type ChannelCacheStore = Readonly<{
|
|
12
|
+
getSnapshot: () => ChannelCacheSnapshot;
|
|
13
|
+
subscribe: (listener: () => void) => () => void;
|
|
14
|
+
beginLoad: () => number;
|
|
15
|
+
acceptLoad: (ticket: number, channels: readonly Channel[]) => void;
|
|
16
|
+
publishCreated: (channel: Channel) => void;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
const EMPTY_CHANNELS: readonly Channel[] = [];
|
|
20
|
+
const EMPTY_SNAPSHOT: ChannelCacheSnapshot = {
|
|
21
|
+
channels: EMPTY_CHANNELS,
|
|
22
|
+
ready: false,
|
|
23
|
+
};
|
|
24
|
+
const channelCaches = new WeakMap<object, Map<string, ChannelCacheStore>>();
|
|
25
|
+
|
|
26
|
+
function compareChannels(left: Channel, right: Channel): number {
|
|
27
|
+
return (
|
|
28
|
+
Number(right.pinned) - Number(left.pinned) ||
|
|
29
|
+
left.sortOrder - right.sortOrder ||
|
|
30
|
+
left.id.localeCompare(right.id)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function orderedChannels(channels: readonly Channel[]): Channel[] {
|
|
35
|
+
return [...channels].sort(compareChannels);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function upsertChannel(channels: readonly Channel[], channel: Channel): Channel[] {
|
|
39
|
+
const next = channels.filter((candidate) => candidate.id !== channel.id);
|
|
40
|
+
next.push(channel);
|
|
41
|
+
return orderedChannels(next);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* One client/workspace cache shared by every useChannels consumer.
|
|
46
|
+
*
|
|
47
|
+
* List reads are ticketed so an older request cannot erase a newer result.
|
|
48
|
+
* A successful create remains layered over the latest server snapshot until a
|
|
49
|
+
* list request that started after that success reconciles it. Requests already
|
|
50
|
+
* in flight cannot make the project disappear between create and session start.
|
|
51
|
+
*/
|
|
52
|
+
export function createChannelCacheStore(): ChannelCacheStore {
|
|
53
|
+
let base: readonly Channel[] | null = null;
|
|
54
|
+
let snapshot = EMPTY_SNAPSHOT;
|
|
55
|
+
let nextLoadTicket = 0;
|
|
56
|
+
let acceptedLoadTicket = 0;
|
|
57
|
+
const pending = new Map<string, PendingChannel>();
|
|
58
|
+
const listeners = new Set<() => void>();
|
|
59
|
+
|
|
60
|
+
const publish = () => {
|
|
61
|
+
let channels = base ?? EMPTY_CHANNELS;
|
|
62
|
+
for (const { channel } of pending.values()) {
|
|
63
|
+
channels = upsertChannel(channels, channel);
|
|
64
|
+
}
|
|
65
|
+
snapshot = { channels, ready: base !== null || pending.size > 0 };
|
|
66
|
+
for (const listener of listeners) listener();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
getSnapshot: () => snapshot,
|
|
71
|
+
subscribe: (listener) => {
|
|
72
|
+
listeners.add(listener);
|
|
73
|
+
return () => listeners.delete(listener);
|
|
74
|
+
},
|
|
75
|
+
beginLoad: () => ++nextLoadTicket,
|
|
76
|
+
acceptLoad: (ticket, channels) => {
|
|
77
|
+
if (ticket < acceptedLoadTicket) return;
|
|
78
|
+
acceptedLoadTicket = ticket;
|
|
79
|
+
base = orderedChannels(channels);
|
|
80
|
+
for (const [id, created] of pending) {
|
|
81
|
+
if (ticket > created.committedAfterLoad) pending.delete(id);
|
|
82
|
+
}
|
|
83
|
+
publish();
|
|
84
|
+
},
|
|
85
|
+
publishCreated: (channel) => {
|
|
86
|
+
pending.set(channel.id, { channel, committedAfterLoad: nextLoadTicket });
|
|
87
|
+
publish();
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function channelCacheFor(client: SessionClientLike, workspaceId: string): ChannelCacheStore {
|
|
93
|
+
let byWorkspace = channelCaches.get(client);
|
|
94
|
+
if (!byWorkspace) {
|
|
95
|
+
byWorkspace = new Map();
|
|
96
|
+
channelCaches.set(client, byWorkspace);
|
|
97
|
+
}
|
|
98
|
+
let cache = byWorkspace.get(workspaceId);
|
|
99
|
+
if (!cache) {
|
|
100
|
+
cache = createChannelCacheStore();
|
|
101
|
+
byWorkspace.set(workspaceId, cache);
|
|
102
|
+
}
|
|
103
|
+
return cache;
|
|
104
|
+
}
|
package/src/hooks/internal.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SessionEvent } from "@opengeni/sdk";
|
|
2
2
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
3
|
import type { EmbeddedSessionEventClientLike } from "../client";
|
|
4
|
+
import { normalizeError } from "../lib/error-message";
|
|
4
5
|
|
|
5
6
|
const HIDDEN_STREAM_GRACE_MS = 2_000;
|
|
6
7
|
|
|
@@ -116,7 +117,7 @@ export function usePolledValue<T>(
|
|
|
116
117
|
activeLoadRef.current === load &&
|
|
117
118
|
!requestAbort.signal.aborted
|
|
118
119
|
) {
|
|
119
|
-
setError(
|
|
120
|
+
setError(normalizeError(cause));
|
|
120
121
|
setLoading(false);
|
|
121
122
|
}
|
|
122
123
|
} finally {
|
|
@@ -258,7 +259,7 @@ export function useMutationRunner(identity: unknown = undefined): MutationState
|
|
|
258
259
|
generation.current === ownedGeneration &&
|
|
259
260
|
Object.is(identityRef.current, ownedIdentity)
|
|
260
261
|
) {
|
|
261
|
-
setMutationError(
|
|
262
|
+
setMutationError(normalizeError(cause));
|
|
262
263
|
}
|
|
263
264
|
return null;
|
|
264
265
|
} finally {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { SESSION_EVENT_TYPES, type SessionEvent, type SessionTurn } from "@opengeni/sdk";
|
|
2
|
+
import type { EmbeddedSessionClientLike } from "../client";
|
|
3
|
+
import {
|
|
4
|
+
isTimelineUserQuestion,
|
|
5
|
+
isTurnExecutionEvidence,
|
|
6
|
+
timelineQuestionPlacement,
|
|
7
|
+
} from "../timeline/projection";
|
|
8
|
+
|
|
9
|
+
export type LatestQuestionOptions = {
|
|
10
|
+
/** Check navigation.isCurrent() after awaits and immediately before UI effects. */
|
|
11
|
+
onQueuedQuestion?: (
|
|
12
|
+
turn: SessionTurn,
|
|
13
|
+
navigation: { isCurrent: () => boolean },
|
|
14
|
+
) => void | Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Include every canonical execution fallback, not just turn.started. Derive
|
|
18
|
+
* this optional navigation index only when the user requests Latest question. */
|
|
19
|
+
export const TIMELINE_TURN_ANCHOR_EVENT_TYPES = SESSION_EVENT_TYPES.filter(
|
|
20
|
+
(type) =>
|
|
21
|
+
isTurnExecutionEvidence(type) ||
|
|
22
|
+
type === "turn.queued" ||
|
|
23
|
+
type === "turn.started" ||
|
|
24
|
+
type === "turn.cancelled" ||
|
|
25
|
+
type === "session.queue.changed" ||
|
|
26
|
+
type === "session.control.steer_requested",
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/** Resolve an optional navigation destination without owning the hook's window
|
|
30
|
+
* or React state. The caller guards errors and applies only a current result. */
|
|
31
|
+
export async function resolveLatestQuestion({
|
|
32
|
+
client,
|
|
33
|
+
workspaceId,
|
|
34
|
+
sessionId,
|
|
35
|
+
isCurrent,
|
|
36
|
+
resumeSequence,
|
|
37
|
+
options,
|
|
38
|
+
}: {
|
|
39
|
+
client: EmbeddedSessionClientLike;
|
|
40
|
+
workspaceId: string;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
isCurrent: () => boolean;
|
|
43
|
+
resumeSequence: (events: readonly SessionEvent[]) => number;
|
|
44
|
+
options?: LatestQuestionOptions | undefined;
|
|
45
|
+
}): Promise<{ questionSequence: number; anchor: number; events: SessionEvent[] } | null> {
|
|
46
|
+
let before: number | undefined;
|
|
47
|
+
while (true) {
|
|
48
|
+
const latest = await client.listEvents(workspaceId, sessionId, {
|
|
49
|
+
direction: "before",
|
|
50
|
+
includeTypes: ["user.message"],
|
|
51
|
+
// Historical worker completions also used user.message; page only this
|
|
52
|
+
// filtered index when they occupy the tail.
|
|
53
|
+
limit: before === undefined ? 1 : 64,
|
|
54
|
+
...(before === undefined ? {} : { before }),
|
|
55
|
+
payloadMode: "full",
|
|
56
|
+
mode: "forensic",
|
|
57
|
+
});
|
|
58
|
+
if (!isCurrent()) return null;
|
|
59
|
+
// Keep legacy childCompletion classification aligned with the transcript.
|
|
60
|
+
const question = [...latest]
|
|
61
|
+
.sort((a, b) => b.sequence - a.sequence)
|
|
62
|
+
.find(isTimelineUserQuestion);
|
|
63
|
+
if (question) {
|
|
64
|
+
const queue = await client.getQueue(workspaceId, sessionId);
|
|
65
|
+
if (!isCurrent()) return null;
|
|
66
|
+
const pending = queue.items.find(
|
|
67
|
+
(turn) => turn.triggerEventId === question.id && turn.metadata.delivery !== "steer",
|
|
68
|
+
);
|
|
69
|
+
if (pending) {
|
|
70
|
+
if (!options?.onQueuedQuestion) {
|
|
71
|
+
const reason = new Error("The latest question is in the prompt queue.");
|
|
72
|
+
reason.name = "LatestQuestionQueuedError";
|
|
73
|
+
throw reason;
|
|
74
|
+
}
|
|
75
|
+
await options.onQueuedQuestion(pending, { isCurrent });
|
|
76
|
+
if (!isCurrent()) return null;
|
|
77
|
+
// Queue refresh/focus can race a claim or withdrawal. Resolve that
|
|
78
|
+
// transition below instead of settling on a row that just vanished.
|
|
79
|
+
const refreshedQueue = await client.getQueue(workspaceId, sessionId);
|
|
80
|
+
if (!isCurrent()) return null;
|
|
81
|
+
if (
|
|
82
|
+
refreshedQueue.items.some(
|
|
83
|
+
(turn) => turn.triggerEventId === question.id && turn.metadata.delivery !== "steer",
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const evidence: SessionEvent[] = [];
|
|
89
|
+
const payload =
|
|
90
|
+
question.payload != null && typeof question.payload === "object"
|
|
91
|
+
? (question.payload as Record<string, unknown>)
|
|
92
|
+
: {};
|
|
93
|
+
// Explicit direct admission needs no lifecycle lookup. Older ledgers and
|
|
94
|
+
// queued admission need their durable start/withdrawal witnesses.
|
|
95
|
+
if (
|
|
96
|
+
payload.routing !== "accepted_for_execution" &&
|
|
97
|
+
payload.routing !== "accepted_for_steering" &&
|
|
98
|
+
payload.delivery !== "steer"
|
|
99
|
+
) {
|
|
100
|
+
let lifecycleAfter = question.sequence;
|
|
101
|
+
while (true) {
|
|
102
|
+
const page = await client.listEvents(workspaceId, sessionId, {
|
|
103
|
+
direction: "after",
|
|
104
|
+
after: lifecycleAfter,
|
|
105
|
+
limit: 128,
|
|
106
|
+
compact: true,
|
|
107
|
+
mode: "forensic",
|
|
108
|
+
payloadMode: "full",
|
|
109
|
+
includeTypes: TIMELINE_TURN_ANCHOR_EVENT_TYPES,
|
|
110
|
+
});
|
|
111
|
+
if (!isCurrent()) return null;
|
|
112
|
+
const next = Math.max(lifecycleAfter, resumeSequence(page));
|
|
113
|
+
if (next === lifecycleAfter) break;
|
|
114
|
+
const queued =
|
|
115
|
+
page.find(
|
|
116
|
+
(event) =>
|
|
117
|
+
event.type === "turn.queued" &&
|
|
118
|
+
((event.payload ?? {}) as Record<string, unknown>).triggerEventId === question.id,
|
|
119
|
+
) ?? evidence.find((event) => event.type === "turn.queued");
|
|
120
|
+
const turnId =
|
|
121
|
+
queued && (((queued.payload ?? {}) as Record<string, unknown>).turnId ?? queued.turnId);
|
|
122
|
+
evidence.push(
|
|
123
|
+
...page.filter((event) => {
|
|
124
|
+
const data = (event.payload ?? {}) as Record<string, unknown>;
|
|
125
|
+
return (
|
|
126
|
+
data.triggerEventId === question.id ||
|
|
127
|
+
(turnId != null &&
|
|
128
|
+
(event.turnId === turnId ||
|
|
129
|
+
data.turnId === turnId ||
|
|
130
|
+
data.targetTurnId === turnId))
|
|
131
|
+
);
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
lifecycleAfter = next;
|
|
135
|
+
const placed = timelineQuestionPlacement(question, evidence);
|
|
136
|
+
if (placed.kind === "visible" && placed.sequence !== question.sequence) break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const placement = timelineQuestionPlacement(question, evidence);
|
|
140
|
+
if (placement.kind === "withdrawn") {
|
|
141
|
+
before = question.sequence;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (placement.kind === "pending")
|
|
145
|
+
throw new Error("The latest question is changing queue state. Try again.");
|
|
146
|
+
return {
|
|
147
|
+
questionSequence: question.sequence,
|
|
148
|
+
anchor: placement.sequence,
|
|
149
|
+
events: [
|
|
150
|
+
question,
|
|
151
|
+
...evidence.filter(
|
|
152
|
+
(event) =>
|
|
153
|
+
event.type === "turn.queued" &&
|
|
154
|
+
((event.payload ?? {}) as Record<string, unknown>).triggerEventId === question.id,
|
|
155
|
+
),
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const oldest = Math.min(...latest.map((event) => event.sequence));
|
|
160
|
+
if (!Number.isSafeInteger(oldest) || oldest <= 1 || (before !== undefined && oldest >= before))
|
|
161
|
+
return null;
|
|
162
|
+
before = oldest;
|
|
163
|
+
}
|
|
164
|
+
}
|