@agent-native/toolkit 0.228.0-nightly-20261111212500 → 0.228.0
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/agent-native.eject.json +2 -0
- package/dist/app/agentkit/react/approval-card.d.ts.map +1 -1
- package/dist/app/agentkit/react/approval-card.js +5 -3
- package/dist/app/agentkit/react/approval-card.js.map +1 -1
- package/dist/app/agentkit/react/code-block.d.ts +32 -0
- package/dist/app/agentkit/react/code-block.d.ts.map +1 -0
- package/dist/app/agentkit/react/code-block.js +125 -0
- package/dist/app/agentkit/react/code-block.js.map +1 -0
- package/dist/app/agentkit/react/components.d.ts +33 -14
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +843 -168
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context-usage.d.ts +45 -0
- package/dist/app/agentkit/react/context-usage.d.ts.map +1 -0
- package/dist/app/agentkit/react/context-usage.js +93 -0
- package/dist/app/agentkit/react/context-usage.js.map +1 -0
- package/dist/app/agentkit/react/context.d.ts +42 -3
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +46 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/disclosure-content.d.ts +12 -0
- package/dist/app/agentkit/react/disclosure-content.d.ts.map +1 -0
- package/dist/app/agentkit/react/disclosure-content.js +33 -0
- package/dist/app/agentkit/react/disclosure-content.js.map +1 -0
- package/dist/app/agentkit/react/duration.d.ts +6 -0
- package/dist/app/agentkit/react/duration.d.ts.map +1 -0
- package/dist/app/agentkit/react/duration.js +21 -0
- package/dist/app/agentkit/react/duration.js.map +1 -0
- package/dist/app/agentkit/react/file-change.d.ts +33 -0
- package/dist/app/agentkit/react/file-change.d.ts.map +1 -0
- package/dist/app/agentkit/react/file-change.js +83 -0
- package/dist/app/agentkit/react/file-change.js.map +1 -0
- package/dist/app/agentkit/react/file-diff.d.ts +17 -0
- package/dist/app/agentkit/react/file-diff.d.ts.map +1 -0
- package/dist/app/agentkit/react/file-diff.js +94 -0
- package/dist/app/agentkit/react/file-diff.js.map +1 -0
- package/dist/app/agentkit/react/index.d.ts +7 -0
- package/dist/app/agentkit/react/index.d.ts.map +1 -1
- package/dist/app/agentkit/react/index.js +7 -0
- package/dist/app/agentkit/react/index.js.map +1 -1
- package/dist/app/agentkit/react/question-card.d.ts +67 -0
- package/dist/app/agentkit/react/question-card.d.ts.map +1 -0
- package/dist/app/agentkit/react/question-card.js +198 -0
- package/dist/app/agentkit/react/question-card.js.map +1 -0
- package/dist/app/agentkit/react/root.d.ts +3 -2
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/roving-focus.d.ts +4 -0
- package/dist/app/agentkit/react/roving-focus.d.ts.map +1 -0
- package/dist/app/agentkit/react/roving-focus.js +75 -0
- package/dist/app/agentkit/react/roving-focus.js.map +1 -0
- package/dist/app/agentkit/react/stack-trace.d.ts +34 -0
- package/dist/app/agentkit/react/stack-trace.d.ts.map +1 -0
- package/dist/app/agentkit/react/stack-trace.js +121 -0
- package/dist/app/agentkit/react/stack-trace.js.map +1 -0
- package/dist/app/agentkit/react/stop-button.d.ts.map +1 -1
- package/dist/app/agentkit/react/stop-button.js +22 -6
- package/dist/app/agentkit/react/stop-button.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +1306 -395
- package/dist/app/agentkit/react/terminal.d.ts +28 -0
- package/dist/app/agentkit/react/terminal.d.ts.map +1 -0
- package/dist/app/agentkit/react/terminal.js +84 -0
- package/dist/app/agentkit/react/terminal.js.map +1 -0
- package/dist/app/agentkit/react/trace.d.ts +31 -0
- package/dist/app/agentkit/react/trace.d.ts.map +1 -0
- package/dist/app/agentkit/react/trace.js +73 -0
- package/dist/app/agentkit/react/trace.js.map +1 -0
- package/dist/app/blocks/library/HighlightedCode.d.ts +2 -1
- package/dist/app/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/app/blocks/library/HighlightedCode.js +8 -111
- package/dist/app/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +23 -245
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.d.ts +15 -1
- package/dist/app/chat/agentkit-chat/guided-questions.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.js +142 -2
- package/dist/app/chat/agentkit-chat/guided-questions.js.map +1 -1
- package/dist/app/chat/agentkit-chat/history.js +1 -1
- package/dist/app/chat/agentkit-chat/history.js.map +1 -1
- package/dist/app/chat/agentkit-chat/index.d.ts +1 -1
- package/dist/app/chat/agentkit-chat/index.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/index.js +1 -1
- package/dist/app/chat/agentkit-chat/index.js.map +1 -1
- package/dist/app/chat/agentkit-chat/labels.d.ts +5 -0
- package/dist/app/chat/agentkit-chat/labels.d.ts.map +1 -0
- package/dist/app/chat/agentkit-chat/labels.js +245 -0
- package/dist/app/chat/agentkit-chat/labels.js.map +1 -0
- package/dist/app/chat/agentkit-chat/questions.d.ts +1 -1
- package/dist/app/chat/agentkit-chat/questions.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/questions.js +1 -1
- package/dist/app/chat/agentkit-chat/questions.js.map +1 -1
- package/dist/app/chat/agentkit-chat/root.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/root.js +5 -64
- package/dist/app/chat/agentkit-chat/root.js.map +1 -1
- package/dist/app/chat/agentkit-chat/work-step-labels.d.ts +2 -0
- package/dist/app/chat/agentkit-chat/work-step-labels.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/work-step-labels.js +31 -0
- package/dist/app/chat/agentkit-chat/work-step-labels.js.map +1 -1
- package/dist/app/chat/chat/markdown-renderer.d.ts +2 -12
- package/dist/app/chat/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/app/chat/chat/markdown-renderer.js +2 -41
- package/dist/app/chat/chat/markdown-renderer.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +2 -2
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.js +2 -37
- package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
- package/dist/app/chat/tool-cells/BashCell.d.ts +3 -1
- package/dist/app/chat/tool-cells/BashCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/BashCell.js +4 -40
- package/dist/app/chat/tool-cells/BashCell.js.map +1 -1
- package/dist/app/chat/tool-cells/EditCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/EditCell.js +5 -108
- package/dist/app/chat/tool-cells/EditCell.js.map +1 -1
- package/dist/app/chat/tool-cells/FilesChangedSummary.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/FilesChangedSummary.js +23 -81
- package/dist/app/chat/tool-cells/FilesChangedSummary.js.map +1 -1
- package/dist/app/chat/tool-cells/WriteCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/WriteCell.js +5 -24
- package/dist/app/chat/tool-cells/WriteCell.js.map +1 -1
- package/dist/app/code-highlighter.d.ts +11 -0
- package/dist/app/code-highlighter.d.ts.map +1 -0
- package/dist/app/code-highlighter.js +122 -0
- package/dist/app/code-highlighter.js.map +1 -0
- package/dist/app/context-xray/ThreadContextRing.js +3 -3
- package/dist/app/context-xray/ThreadContextRing.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +22 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +22 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +22 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +22 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +22 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +22 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +22 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +22 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +22 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +22 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +22 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +22 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/first-run-first-paint.d.ts +10 -0
- package/dist/app/onboarding/first-run-first-paint.d.ts.map +1 -0
- package/dist/app/onboarding/first-run-first-paint.js +22 -0
- package/dist/app/onboarding/first-run-first-paint.js.map +1 -0
- package/dist/app/onboarding/first-run-startup-gate.d.ts +3 -1
- package/dist/app/onboarding/first-run-startup-gate.d.ts.map +1 -1
- package/dist/app/onboarding/first-run-startup-gate.js +30 -6
- package/dist/app/onboarding/first-run-startup-gate.js.map +1 -1
- package/dist/app/providers/AppProviders.d.ts.map +1 -1
- package/dist/app/providers/AppProviders.js +9 -2
- package/dist/app/providers/AppProviders.js.map +1 -1
- package/dist/app/providers/BuilderSignupActivation.d.ts +2 -1
- package/dist/app/providers/BuilderSignupActivation.d.ts.map +1 -1
- package/dist/app/providers/BuilderSignupActivation.js +6 -3
- package/dist/app/providers/BuilderSignupActivation.js.map +1 -1
- package/dist/app/shared/AppShellSkeleton.d.ts.map +1 -1
- package/dist/app/shared/AppShellSkeleton.js +11 -1
- package/dist/app/shared/AppShellSkeleton.js.map +1 -1
- package/dist/app/styles/agent-native.css +2 -2
- package/dist/app/styles/tokens/agent-kit.css +20 -3
- package/dist/composer/AgentSuggestionBar.d.ts.map +1 -1
- package/dist/composer/AgentSuggestionBar.js +2 -2
- package/dist/composer/AgentSuggestionBar.js.map +1 -1
- package/dist/composer/ComposerContextMenu.js +4 -4
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/ComposerContextPicker.d.ts.map +1 -1
- package/dist/composer/ComposerContextPicker.js +2 -2
- package/dist/composer/ComposerContextPicker.js.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.d.ts.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.js +2 -2
- package/dist/composer/ComposerContextPickerDialog.js.map +1 -1
- package/dist/composer/ComposerModePicker.d.ts.map +1 -1
- package/dist/composer/ComposerModePicker.js +2 -1
- package/dist/composer/ComposerModePicker.js.map +1 -1
- package/dist/composer/ComposerPlusMenu.js +1 -1
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/MentionChip.js +1 -1
- package/dist/composer/MentionChip.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts +3 -0
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +34 -15
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/MessageQueueDrawer.d.ts.map +1 -1
- package/dist/composer/MessageQueueDrawer.js +14 -9
- package/dist/composer/MessageQueueDrawer.js.map +1 -1
- package/dist/composer/PastedTextChip.d.ts.map +1 -1
- package/dist/composer/PastedTextChip.js +14 -18
- package/dist/composer/PastedTextChip.js.map +1 -1
- package/dist/composer/PromptBar.js +1 -1
- package/dist/composer/PromptBar.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +11 -9
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/RealtimeVoiceMode.js +2 -2
- package/dist/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +52 -89
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/VoiceButton.d.ts +3 -1
- package/dist/composer/VoiceButton.d.ts.map +1 -1
- package/dist/composer/VoiceButton.js +10 -8
- package/dist/composer/VoiceButton.js.map +1 -1
- package/dist/composer/composer-notice.js +3 -3
- package/dist/composer/composer-notice.js.map +1 -1
- package/dist/composer/extensions/FileReference.js +1 -1
- package/dist/composer/extensions/FileReference.js.map +1 -1
- package/dist/composer/extensions/SkillReference.js +1 -1
- package/dist/composer/extensions/SkillReference.js.map +1 -1
- package/dist/composer/popover-surface.d.ts +1 -1
- package/dist/composer/popover-surface.d.ts.map +1 -1
- package/dist/composer/popover-surface.js +1 -1
- package/dist/composer/popover-surface.js.map +1 -1
- package/dist/context-ui/ContextUsageRing.d.ts +1 -45
- package/dist/context-ui/ContextUsageRing.d.ts.map +1 -1
- package/dist/context-ui/ContextUsageRing.js +2 -87
- package/dist/context-ui/ContextUsageRing.js.map +1 -1
- package/dist/context-ui/index.d.ts +2 -2
- package/dist/context-ui/index.d.ts.map +1 -1
- package/dist/context-ui/index.js +2 -2
- package/dist/context-ui/index.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/approval-card.tsx +14 -2
- package/src/app/agentkit/react/code-block.spec.tsx +154 -0
- package/src/app/agentkit/react/code-block.tsx +317 -0
- package/src/app/agentkit/react/components.interaction.spec.tsx +7 -0
- package/src/app/agentkit/react/components.papercuts.spec.tsx +143 -2
- package/src/app/agentkit/react/components.spec.tsx +40 -47
- package/src/app/agentkit/react/components.tsx +1533 -413
- package/src/app/agentkit/react/composer-context.spec.tsx +35 -0
- package/src/app/agentkit/react/context-usage.tsx +353 -0
- package/src/app/agentkit/react/context.tsx +93 -1
- package/src/app/agentkit/react/disclosure-content.ts +42 -0
- package/src/app/agentkit/react/disclosures.spec.tsx +62 -4
- package/src/app/agentkit/react/duration.ts +22 -0
- package/src/app/agentkit/react/file-change.spec.tsx +124 -0
- package/src/app/agentkit/react/file-change.tsx +228 -0
- package/src/app/agentkit/react/file-diff.ts +110 -0
- package/src/app/agentkit/react/index.ts +7 -0
- package/src/app/agentkit/react/lifecycle.spec.tsx +565 -20
- package/src/app/agentkit/react/markdown.spec.tsx +18 -8
- package/src/app/agentkit/react/message-actions.spec.tsx +55 -1
- package/src/app/agentkit/react/notices.spec.tsx +4 -4
- package/src/app/agentkit/react/optimistic-send.spec.tsx +43 -0
- package/src/app/agentkit/react/question-card.spec.tsx +276 -0
- package/src/app/agentkit/react/question-card.tsx +533 -0
- package/src/app/agentkit/react/root.tsx +4 -0
- package/src/app/agentkit/react/roving-focus.spec.tsx +114 -0
- package/src/app/agentkit/react/roving-focus.ts +82 -0
- package/src/app/agentkit/react/stack-trace.spec.tsx +177 -0
- package/src/app/agentkit/react/stack-trace.tsx +281 -0
- package/src/app/agentkit/react/stop-button.spec.tsx +40 -0
- package/src/app/agentkit/react/stop-button.tsx +22 -5
- package/src/app/agentkit/react/styles.css +1306 -395
- package/src/app/agentkit/react/subagent-step.spec.tsx +554 -0
- package/src/app/agentkit/react/terminal.spec.tsx +228 -0
- package/src/app/agentkit/react/terminal.tsx +228 -0
- package/src/app/agentkit/react/trace.spec.tsx +120 -0
- package/src/app/agentkit/react/trace.tsx +239 -0
- package/src/app/blocks/library/HighlightedCode.tsx +14 -126
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +28 -12
- package/src/app/chat/AgentKitAssistantChat.tsx +27 -253
- package/src/app/chat/agentkit-chat/approval-card.spec.tsx +1 -0
- package/src/app/chat/agentkit-chat/guided-questions.flow.spec.tsx +381 -0
- package/src/app/chat/agentkit-chat/guided-questions.tsx +236 -3
- package/src/app/chat/agentkit-chat/history.tsx +1 -1
- package/src/app/chat/agentkit-chat/index.ts +2 -0
- package/src/app/chat/agentkit-chat/labels.ts +259 -0
- package/src/app/chat/agentkit-chat/questions.ts +2 -0
- package/src/app/chat/agentkit-chat/root.spec.tsx +18 -0
- package/src/app/chat/agentkit-chat/root.tsx +5 -64
- package/src/app/chat/agentkit-chat/work-step-labels.ts +42 -0
- package/src/app/chat/chat/markdown-renderer.tsx +2 -59
- package/src/app/chat/chat/tool-call-display.spec.tsx +26 -14
- package/src/app/chat/chat/tool-call-display.tsx +2 -1
- package/src/app/chat/conversation/AgentConversation.tsx +2 -50
- package/src/app/chat/tool-cells/BashCell.tsx +14 -136
- package/src/app/chat/tool-cells/EditCell.tsx +11 -248
- package/src/app/chat/tool-cells/FilesChangedSummary.spec.tsx +62 -5
- package/src/app/chat/tool-cells/FilesChangedSummary.tsx +31 -162
- package/src/app/chat/tool-cells/WriteCell.tsx +11 -121
- package/src/app/code-highlighter.ts +131 -0
- package/src/app/context-xray/ThreadContextRing.tsx +7 -7
- package/src/app/i18n/catalogs/ar-SA.ts +22 -0
- package/src/app/i18n/catalogs/de-DE.ts +22 -0
- package/src/app/i18n/catalogs/en-US.ts +22 -0
- package/src/app/i18n/catalogs/es-ES.ts +22 -0
- package/src/app/i18n/catalogs/fr-FR.ts +22 -0
- package/src/app/i18n/catalogs/hi-IN.ts +22 -0
- package/src/app/i18n/catalogs/ja-JP.ts +22 -0
- package/src/app/i18n/catalogs/ko-KR.ts +22 -0
- package/src/app/i18n/catalogs/pt-BR.ts +22 -0
- package/src/app/i18n/catalogs/zh-CN.ts +22 -0
- package/src/app/i18n/catalogs/zh-TW.ts +22 -0
- package/src/app/onboarding/first-run-first-paint.spec.ts +39 -0
- package/src/app/onboarding/first-run-first-paint.ts +24 -0
- package/src/app/onboarding/first-run-startup-gate.spec.tsx +125 -13
- package/src/app/onboarding/first-run-startup-gate.tsx +48 -5
- package/src/app/providers/AppProviders.tsx +18 -0
- package/src/app/providers/BuilderSignupActivation.tsx +8 -2
- package/src/app/shared/AppShellSkeleton.spec.tsx +60 -1
- package/src/app/shared/AppShellSkeleton.tsx +31 -1
- package/src/app/styles/agent-native.css +2 -2
- package/src/app/styles/agent-native.spec.ts +2 -2
- package/src/app/styles/tokens/agent-kit.css +20 -3
- package/src/composer/AgentSuggestionBar.spec.tsx +3 -1
- package/src/composer/AgentSuggestionBar.tsx +5 -2
- package/src/composer/ComposerContextMenu.tsx +4 -4
- package/src/composer/ComposerContextPicker.tsx +8 -2
- package/src/composer/ComposerContextPickerDialog.tsx +5 -2
- package/src/composer/ComposerModePicker.tsx +2 -1
- package/src/composer/ComposerPlusMenu.tsx +1 -1
- package/src/composer/MentionChip.tsx +1 -1
- package/src/composer/MentionPopover.spec.tsx +108 -2
- package/src/composer/MentionPopover.tsx +93 -17
- package/src/composer/MessageQueueDrawer.spec.tsx +5 -5
- package/src/composer/MessageQueueDrawer.tsx +19 -12
- package/src/composer/PastedTextChip.spec.tsx +36 -0
- package/src/composer/PastedTextChip.tsx +52 -58
- package/src/composer/PromptBar.tsx +1 -1
- package/src/composer/PromptComposer.context.spec.tsx +2 -2
- package/src/composer/PromptComposer.submission.spec.tsx +27 -0
- package/src/composer/PromptComposer.tsx +17 -9
- package/src/composer/RealtimeVoiceMode.tsx +2 -2
- package/src/composer/TiptapComposer.model-picker.spec.tsx +23 -82
- package/src/composer/TiptapComposer.tsx +68 -145
- package/src/composer/VoiceButton.tsx +12 -7
- package/src/composer/composer-notice.tsx +3 -3
- package/src/composer/extensions/FileReference.tsx +1 -1
- package/src/composer/extensions/SkillReference.tsx +1 -1
- package/src/composer/popover-surface.ts +1 -1
- package/src/context-ui/ContextUsageRing.spec.tsx +33 -8
- package/src/context-ui/ContextUsageRing.tsx +13 -348
- package/src/context-ui/index.ts +7 -1
- package/dist/composer/ModelPickerParts.d.ts +0 -20
- package/dist/composer/ModelPickerParts.d.ts.map +0 -1
- package/dist/composer/ModelPickerParts.js +0 -77
- package/dist/composer/ModelPickerParts.js.map +0 -1
- package/src/composer/ModelPickerParts.tsx +0 -188
|
@@ -45,10 +45,13 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
45
45
|
"activity.groupLabel": "智能体活动",
|
|
46
46
|
"activity.agents": "智能体协作",
|
|
47
47
|
"activity.tasks": "智能体任务",
|
|
48
|
+
"activity.tasksProgress": "{{total}} 项中已完成 {{completed}} 项",
|
|
48
49
|
"agent.started": "开始工作了",
|
|
49
50
|
"agent.resumed": "恢复了工作",
|
|
50
51
|
"agent.messaged": "发送了消息",
|
|
51
52
|
"agent.delegated": "委派了工作",
|
|
53
|
+
"agent.working": "正在工作",
|
|
54
|
+
"agent.workedFor": "工作了 {{duration}}",
|
|
52
55
|
"agent.paused": "暂停了工作",
|
|
53
56
|
"agent.queued": "排队中",
|
|
54
57
|
"agent.completed": "已完成",
|
|
@@ -422,6 +425,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
422
425
|
"composer.attachmentTooLarge": "文件超过 8 MB",
|
|
423
426
|
"composer.attachmentNotUtf8": "文件不是 UTF-8 文本",
|
|
424
427
|
"composer.scrollToBottom": "滚动到底部",
|
|
428
|
+
"composer.skipToMessageBox": "跳到消息输入框",
|
|
425
429
|
"composer.suggestedPrompts": "推荐提示",
|
|
426
430
|
"composer.stopResponse": "停止响应",
|
|
427
431
|
"composer.subAgentReadOnly":
|
|
@@ -577,6 +581,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
577
581
|
"pastedText.remove": "移除粘贴的文本",
|
|
578
582
|
"pastedText.title": "粘贴的文本",
|
|
579
583
|
"voice.dictation.start": "听写({{shortcut}})",
|
|
584
|
+
"voice.dictation.startPlain": "听写",
|
|
580
585
|
"voice.dictation.stopRecording": "停止录音",
|
|
581
586
|
"voice.dictation.transcribing": "正在转写…",
|
|
582
587
|
"voiceMode.errors.channelDisconnected": "实时语音控制通道已断开。",
|
|
@@ -3137,6 +3142,14 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3137
3142
|
"guided.other": "其他…",
|
|
3138
3143
|
"guided.otherDescription": "准确告诉智能体你的意思。",
|
|
3139
3144
|
"guided.recommended": "推荐",
|
|
3145
|
+
"guided.question": "问题",
|
|
3146
|
+
"guided.questionProgress": "{{current}}/{{total}}",
|
|
3147
|
+
"guided.questionProgressLabel": "第 {{current}} 个,共 {{total}} 个",
|
|
3148
|
+
"guided.ownResponse": "或者输入你自己的回答",
|
|
3149
|
+
"guided.next": "下一个",
|
|
3150
|
+
"guided.send": "发送",
|
|
3151
|
+
"guided.dismiss": "关闭问题",
|
|
3152
|
+
"guided.chooseFiles": "选择文件…",
|
|
3140
3153
|
"guided.typeAnswer": "输入你的回答…",
|
|
3141
3154
|
"guided.typeCustomAnswer": "输入自定义回答…",
|
|
3142
3155
|
"guided.dropFiles": "将文件拖到此处,或",
|
|
@@ -3174,6 +3187,10 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3174
3187
|
"toolCells.showMoreLines": "再显示 {{count}} 行",
|
|
3175
3188
|
"toolCells.partial": "部分",
|
|
3176
3189
|
"toolCells.timedOut": "已超时",
|
|
3190
|
+
"toolCells.exitCode": "退出码 {{code}}",
|
|
3191
|
+
"toolCells.copyOutput": "复制输出",
|
|
3192
|
+
"toolCells.lineAdded": "已添加",
|
|
3193
|
+
"toolCells.lineRemoved": "已删除",
|
|
3177
3194
|
"codeRequired.requestFailed": "请求失败({{status}})",
|
|
3178
3195
|
"chatFirst.chats": "聊天",
|
|
3179
3196
|
"chatFirst.noChats": "还没有聊天。",
|
|
@@ -3287,6 +3304,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3287
3304
|
"mentions.noCommands": "没有命令",
|
|
3288
3305
|
"mentions.noMatches": "没有匹配项",
|
|
3289
3306
|
"queue.dragToReorder": "拖动以重新排序",
|
|
3307
|
+
"queue.attachedImage": "附加的图片",
|
|
3290
3308
|
"queue.moveUp": "上移",
|
|
3291
3309
|
"queue.moveDown": "下移",
|
|
3292
3310
|
"queue.movedToPosition": "已移到第 {{position}} 位,共 {{count}} 位",
|
|
@@ -3340,6 +3358,10 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3340
3358
|
"workSteps.readPagesOther": "阅读了 {{count}} 个网页",
|
|
3341
3359
|
"workSteps.fetchedOne": "获取了 1 个 URL",
|
|
3342
3360
|
"workSteps.fetchedOther": "获取了 {{count}} 个 URL",
|
|
3361
|
+
"workSteps.sourcesOne": "使用了 1 个来源",
|
|
3362
|
+
"workSteps.sourcesOther": "使用了 {{count}} 个来源",
|
|
3363
|
+
"workSteps.frameworkFrames": "{{count}} 个框架帧",
|
|
3364
|
+
"workSteps.copyStackTrace": "复制堆栈跟踪",
|
|
3343
3365
|
"workSteps.readFilesOne": "读取了 1 个文件",
|
|
3344
3366
|
"workSteps.readFilesOther": "读取了 {{count}} 个文件",
|
|
3345
3367
|
"workSteps.editedOne": "编辑了 1 个文件",
|
|
@@ -46,10 +46,13 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
46
46
|
"activity.groupLabel": "代理活動",
|
|
47
47
|
"activity.agents": "代理協作",
|
|
48
48
|
"activity.tasks": "代理任務",
|
|
49
|
+
"activity.tasksProgress": "{{total}} 項中已完成 {{completed}} 項",
|
|
49
50
|
"agent.started": "開始工作",
|
|
50
51
|
"agent.resumed": "恢復工作",
|
|
51
52
|
"agent.messaged": "傳送了訊息",
|
|
52
53
|
"agent.delegated": "已委派工作",
|
|
54
|
+
"agent.working": "正在工作",
|
|
55
|
+
"agent.workedFor": "工作了 {{duration}}",
|
|
53
56
|
"agent.paused": "已暫停工作",
|
|
54
57
|
"agent.queued": "排隊中",
|
|
55
58
|
"agent.completed": "已完成",
|
|
@@ -423,6 +426,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
423
426
|
"composer.attachmentTooLarge": "檔案超過 8 MB",
|
|
424
427
|
"composer.attachmentNotUtf8": "檔案不是 UTF-8 文字",
|
|
425
428
|
"composer.scrollToBottom": "捲動到底部",
|
|
429
|
+
"composer.skipToMessageBox": "跳至訊息輸入框",
|
|
426
430
|
"composer.suggestedPrompts": "建議提示",
|
|
427
431
|
"composer.stopResponse": "停止回應",
|
|
428
432
|
"composer.subAgentReadOnly":
|
|
@@ -578,6 +582,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
578
582
|
"pastedText.remove": "移除貼上的文字",
|
|
579
583
|
"pastedText.title": "貼上的文字",
|
|
580
584
|
"voice.dictation.start": "聽寫({{shortcut}})",
|
|
585
|
+
"voice.dictation.startPlain": "聽寫",
|
|
581
586
|
"voice.dictation.stopRecording": "停止錄音",
|
|
582
587
|
"voice.dictation.transcribing": "正在轉錄…",
|
|
583
588
|
"voiceMode.errors.channelDisconnected": "即時語音控制頻道已中斷連線。",
|
|
@@ -3154,6 +3159,14 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3154
3159
|
"guided.other": "其他…",
|
|
3155
3160
|
"guided.otherDescription": "明確告訴代理你的意思。",
|
|
3156
3161
|
"guided.recommended": "推薦",
|
|
3162
|
+
"guided.question": "問題",
|
|
3163
|
+
"guided.questionProgress": "{{current}}/{{total}}",
|
|
3164
|
+
"guided.questionProgressLabel": "第 {{current}} 個,共 {{total}} 個",
|
|
3165
|
+
"guided.ownResponse": "或輸入你自己的回答",
|
|
3166
|
+
"guided.next": "下一個",
|
|
3167
|
+
"guided.send": "傳送",
|
|
3168
|
+
"guided.dismiss": "關閉問題",
|
|
3169
|
+
"guided.chooseFiles": "選擇檔案…",
|
|
3157
3170
|
"guided.typeAnswer": "輸入你的回答…",
|
|
3158
3171
|
"guided.typeCustomAnswer": "輸入自訂回答…",
|
|
3159
3172
|
"guided.dropFiles": "將檔案拖曳到這裡,或",
|
|
@@ -3191,6 +3204,10 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3191
3204
|
"toolCells.showMoreLines": "再顯示 {{count}} 行",
|
|
3192
3205
|
"toolCells.partial": "部分",
|
|
3193
3206
|
"toolCells.timedOut": "已逾時",
|
|
3207
|
+
"toolCells.exitCode": "結束代碼 {{code}}",
|
|
3208
|
+
"toolCells.copyOutput": "複製輸出",
|
|
3209
|
+
"toolCells.lineAdded": "已新增",
|
|
3210
|
+
"toolCells.lineRemoved": "已刪除",
|
|
3194
3211
|
"codeRequired.requestFailed": "要求失敗({{status}})",
|
|
3195
3212
|
"chatFirst.chats": "聊天",
|
|
3196
3213
|
"chatFirst.noChats": "還沒有聊天。",
|
|
@@ -3304,6 +3321,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3304
3321
|
"mentions.noCommands": "沒有指令",
|
|
3305
3322
|
"mentions.noMatches": "沒有相符項目",
|
|
3306
3323
|
"queue.dragToReorder": "拖曳以重新排序",
|
|
3324
|
+
"queue.attachedImage": "附加的圖片",
|
|
3307
3325
|
"queue.moveUp": "上移",
|
|
3308
3326
|
"queue.moveDown": "下移",
|
|
3309
3327
|
"queue.movedToPosition": "已移到第 {{position}} 位,共 {{count}} 位",
|
|
@@ -3358,6 +3376,10 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
3358
3376
|
"workSteps.readPagesOther": "閱讀了 {{count}} 個網頁",
|
|
3359
3377
|
"workSteps.fetchedOne": "擷取了 1 個 URL",
|
|
3360
3378
|
"workSteps.fetchedOther": "擷取了 {{count}} 個 URL",
|
|
3379
|
+
"workSteps.sourcesOne": "使用了 1 個來源",
|
|
3380
|
+
"workSteps.sourcesOther": "使用了 {{count}} 個來源",
|
|
3381
|
+
"workSteps.frameworkFrames": "{{count}} 個框架堆疊框",
|
|
3382
|
+
"workSteps.copyStackTrace": "複製堆疊追蹤",
|
|
3361
3383
|
"workSteps.readFilesOne": "讀取了 1 個檔案",
|
|
3362
3384
|
"workSteps.readFilesOther": "讀取了 {{count}} 個檔案",
|
|
3363
3385
|
"workSteps.editedOne": "編輯了 1 個檔案",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { FIRST_RUN_ONBOARDING_COOKIE } from "@agent-native/core/shared/first-run-onboarding";
|
|
4
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
FIRST_RUN_PENDING_ATTRIBUTE,
|
|
8
|
+
getFirstRunFirstPaintScriptBody,
|
|
9
|
+
} from "./first-run-first-paint.js";
|
|
10
|
+
|
|
11
|
+
function runBootScript() {
|
|
12
|
+
// The body is inlined into the SSR shell as a classic script.
|
|
13
|
+
new Function(getFirstRunFirstPaintScriptBody())();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("first-run first-paint boot script", () => {
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
document.documentElement.removeAttribute(FIRST_RUN_PENDING_ATTRIBUTE);
|
|
19
|
+
document.cookie = `${FIRST_RUN_ONBOARDING_COOKIE}=; Max-Age=0; path=/`;
|
|
20
|
+
document.cookie = "other=; Max-Age=0; path=/";
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("marks the document while the first-run cookie is present", () => {
|
|
24
|
+
document.cookie = "other=1; path=/";
|
|
25
|
+
document.cookie = `${FIRST_RUN_ONBOARDING_COOKIE}=1; path=/`;
|
|
26
|
+
runBootScript();
|
|
27
|
+
expect(
|
|
28
|
+
document.documentElement.hasAttribute(FIRST_RUN_PENDING_ATTRIBUTE),
|
|
29
|
+
).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("leaves the document unmarked without the cookie", () => {
|
|
33
|
+
document.cookie = "other=1; path=/";
|
|
34
|
+
runBootScript();
|
|
35
|
+
expect(
|
|
36
|
+
document.documentElement.hasAttribute(FIRST_RUN_PENDING_ATTRIBUTE),
|
|
37
|
+
).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FIRST_RUN_ONBOARDING_COOKIE } from "@agent-native/core/shared/first-run-onboarding";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Set on <html> before the first paint while the first-run cookie says
|
|
5
|
+
* onboarding may start. The SSR shell is shared by every visitor, so a
|
|
6
|
+
* first-paint home is swapped for a plain skeleton by CSS keyed to this
|
|
7
|
+
* attribute, never by rendering a different tree.
|
|
8
|
+
*/
|
|
9
|
+
export const FIRST_RUN_PENDING_ATTRIBUTE =
|
|
10
|
+
"data-agent-native-first-run-pending";
|
|
11
|
+
|
|
12
|
+
export function getFirstRunFirstPaintScriptBody(): string {
|
|
13
|
+
const entry = JSON.stringify(`${FIRST_RUN_ONBOARDING_COOKIE}=1`);
|
|
14
|
+
const attribute = JSON.stringify(FIRST_RUN_PENDING_ATTRIBUTE);
|
|
15
|
+
// An unreadable cookie leaves the attribute unset, which is what the startup
|
|
16
|
+
// gate does with one too: it skips first run (and logs why).
|
|
17
|
+
// coercion-ok: an inline pre-paint script has no caller to report to.
|
|
18
|
+
return `(function(){try{if(document.cookie.split(";").some(function(c){return c.trim()===${entry}}))document.documentElement.setAttribute(${attribute},"")}catch(_){}})();`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function clearFirstRunFirstPaint(): void {
|
|
22
|
+
if (typeof document === "undefined") return;
|
|
23
|
+
document.documentElement.removeAttribute(FIRST_RUN_PENDING_ATTRIBUTE);
|
|
24
|
+
}
|
|
@@ -29,17 +29,24 @@ vi.mock("@agent-native/core/client/onboarding/use-preview-mode", () => ({
|
|
|
29
29
|
}));
|
|
30
30
|
|
|
31
31
|
vi.mock("./FirstRunOnboarding.js", () => ({
|
|
32
|
-
FirstRunOnboarding: ({ initialFirstRun }: { initialFirstRun?: boolean }) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
FirstRunOnboarding: ({ initialFirstRun }: { initialFirstRun?: boolean }) => {
|
|
33
|
+
const [mountId] = React.useState(() => ++nextOnboardingMountId);
|
|
34
|
+
return (
|
|
35
|
+
<div
|
|
36
|
+
data-testid="first-run-onboarding"
|
|
37
|
+
data-initial-first-run={String(initialFirstRun === true)}
|
|
38
|
+
data-mount-id={mountId}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
},
|
|
38
42
|
}));
|
|
39
43
|
|
|
44
|
+
let nextOnboardingMountId = 0;
|
|
45
|
+
|
|
40
46
|
import { SessionPreloadContext } from "@agent-native/core/client/use-session";
|
|
41
47
|
import { FIRST_RUN_ONBOARDING_COOKIE } from "@agent-native/core/shared/first-run-onboarding";
|
|
42
48
|
|
|
49
|
+
import { FIRST_RUN_PENDING_ATTRIBUTE } from "./first-run-first-paint.js";
|
|
43
50
|
import {
|
|
44
51
|
FirstRunOnboardingStartupGate,
|
|
45
52
|
useFirstRunOnboardingGateOwnsSurface,
|
|
@@ -97,13 +104,17 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
97
104
|
container.remove();
|
|
98
105
|
vi.unstubAllGlobals();
|
|
99
106
|
document.cookie = `${FIRST_RUN_ONBOARDING_COOKIE}=; Max-Age=0; path=/`;
|
|
107
|
+
document.documentElement.removeAttribute(FIRST_RUN_PENDING_ATTRIBUTE);
|
|
100
108
|
});
|
|
101
109
|
|
|
102
|
-
it("
|
|
110
|
+
it("covers the app while Builder setup defers an eligible first run, without mounting the onboarding surface", async () => {
|
|
103
111
|
mocks.fetchStatus.mockResolvedValue(true);
|
|
104
112
|
await act(async () => {
|
|
105
113
|
root.render(
|
|
106
|
-
<FirstRunOnboardingStartupGate
|
|
114
|
+
<FirstRunOnboardingStartupGate
|
|
115
|
+
deferSurface
|
|
116
|
+
cover={<div data-testid="startup-skeleton" />}
|
|
117
|
+
>
|
|
107
118
|
<GateOwnershipProbe />
|
|
108
119
|
</FirstRunOnboardingStartupGate>,
|
|
109
120
|
);
|
|
@@ -111,20 +122,118 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
111
122
|
expect(
|
|
112
123
|
container.querySelector('[data-testid="gate-ownership"]')?.textContent,
|
|
113
124
|
).toBe("true");
|
|
125
|
+
// oracle-change: an eligible first run under deferral used to leave the
|
|
126
|
+
// home painted and usable, so it flashed before the role question.
|
|
127
|
+
expect(
|
|
128
|
+
container.querySelector(
|
|
129
|
+
"[data-first-run-cover] [data-testid='startup-skeleton']",
|
|
130
|
+
),
|
|
131
|
+
).not.toBeNull();
|
|
114
132
|
expect(
|
|
115
133
|
container.querySelector('[data-first-run-app-inert="true"]'),
|
|
116
|
-
).toBeNull();
|
|
117
|
-
expect(container.querySelector("[aria-hidden='true']")).toBeNull();
|
|
134
|
+
).not.toBeNull();
|
|
118
135
|
expect(
|
|
119
136
|
container
|
|
120
137
|
.querySelector("[data-testid='gate-ownership']")
|
|
121
138
|
?.getAttribute("data-blocked"),
|
|
122
|
-
).toBe("
|
|
139
|
+
).toBe("true");
|
|
123
140
|
expect(
|
|
124
141
|
container.querySelector('[data-testid="first-run-onboarding"]'),
|
|
125
142
|
).toBeNull();
|
|
126
143
|
});
|
|
127
144
|
|
|
145
|
+
it("lifts the first-paint stand-in once first run is ruled out", async () => {
|
|
146
|
+
const status = deferred<boolean>();
|
|
147
|
+
mocks.fetchStatus.mockReturnValue(status.promise);
|
|
148
|
+
document.documentElement.setAttribute(FIRST_RUN_PENDING_ATTRIBUTE, "");
|
|
149
|
+
|
|
150
|
+
act(() => {
|
|
151
|
+
root.render(
|
|
152
|
+
<FirstRunOnboardingStartupGate>
|
|
153
|
+
<div data-testid="app-content">app</div>
|
|
154
|
+
</FirstRunOnboardingStartupGate>,
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
expect(
|
|
158
|
+
document.documentElement.hasAttribute(FIRST_RUN_PENDING_ATTRIBUTE),
|
|
159
|
+
).toBe(true);
|
|
160
|
+
|
|
161
|
+
await act(async () => {
|
|
162
|
+
status.resolve(false);
|
|
163
|
+
await status.promise;
|
|
164
|
+
});
|
|
165
|
+
expect(
|
|
166
|
+
document.documentElement.hasAttribute(FIRST_RUN_PENDING_ATTRIBUTE),
|
|
167
|
+
).toBe(false);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("keeps an ineligible user's app usable while Builder setup defers onboarding", async () => {
|
|
171
|
+
mocks.fetchStatus.mockResolvedValue(false);
|
|
172
|
+
await act(async () => {
|
|
173
|
+
root.render(
|
|
174
|
+
<FirstRunOnboardingStartupGate deferSurface>
|
|
175
|
+
<GateOwnershipProbe />
|
|
176
|
+
</FirstRunOnboardingStartupGate>,
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
expect(container.querySelector("[data-first-run-cover]")).toBeNull();
|
|
180
|
+
expect(container.querySelector("[data-first-run-app-inert]")).toBeNull();
|
|
181
|
+
expect(
|
|
182
|
+
container
|
|
183
|
+
.querySelector("[data-testid='gate-ownership']")
|
|
184
|
+
?.getAttribute("data-blocked"),
|
|
185
|
+
).toBe("false");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("keeps onboarding on screen when a deferral starts after it appears", async () => {
|
|
189
|
+
mocks.fetchStatus.mockResolvedValue(true);
|
|
190
|
+
const renderGate = (deferSurface: boolean) =>
|
|
191
|
+
act(async () => {
|
|
192
|
+
root.render(
|
|
193
|
+
<FirstRunOnboardingStartupGate deferSurface={deferSurface}>
|
|
194
|
+
<div data-testid="app-content">app</div>
|
|
195
|
+
</FirstRunOnboardingStartupGate>,
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
await renderGate(false);
|
|
199
|
+
await vi.waitFor(() => {
|
|
200
|
+
expect(
|
|
201
|
+
container.querySelector("[data-testid='first-run-onboarding']"),
|
|
202
|
+
).not.toBeNull();
|
|
203
|
+
});
|
|
204
|
+
const mountId = container
|
|
205
|
+
.querySelector("[data-testid='first-run-onboarding']")
|
|
206
|
+
?.getAttribute("data-mount-id");
|
|
207
|
+
|
|
208
|
+
await renderGate(true);
|
|
209
|
+
|
|
210
|
+
expect(
|
|
211
|
+
container
|
|
212
|
+
.querySelector("[data-testid='first-run-onboarding']")
|
|
213
|
+
?.getAttribute("data-mount-id"),
|
|
214
|
+
).toBe(mountId);
|
|
215
|
+
expect(container.querySelector("[data-first-run-cover]")).toBeNull();
|
|
216
|
+
expect(
|
|
217
|
+
container
|
|
218
|
+
.querySelector("[data-testid='app-content']")
|
|
219
|
+
?.closest("[inert]"),
|
|
220
|
+
).not.toBeNull();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("paints a skeleton, not a blank screen, when the caller passes no cover", async () => {
|
|
224
|
+
mocks.fetchStatus.mockReturnValue(new Promise(() => {}));
|
|
225
|
+
await act(async () => {
|
|
226
|
+
root.render(
|
|
227
|
+
<FirstRunOnboardingStartupGate>
|
|
228
|
+
<div data-testid="app-content">app</div>
|
|
229
|
+
</FirstRunOnboardingStartupGate>,
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
expect(
|
|
233
|
+
container.querySelector("[data-first-run-cover] .skeleton-shimmer"),
|
|
234
|
+
).not.toBeNull();
|
|
235
|
+
});
|
|
236
|
+
|
|
128
237
|
it("holds the status read while the session preloads, then reads once it resolves", async () => {
|
|
129
238
|
mocks.fetchStatus.mockResolvedValue(false);
|
|
130
239
|
const renderGate = (preloading: boolean) =>
|
|
@@ -201,7 +310,7 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
201
310
|
).not.toBeNull();
|
|
202
311
|
});
|
|
203
312
|
|
|
204
|
-
it("keeps the app
|
|
313
|
+
it("keeps the app mounted, inert and covered while eligibility is unresolved", async () => {
|
|
205
314
|
const status = deferred<boolean>();
|
|
206
315
|
mocks.fetchStatus.mockReturnValue(status.promise);
|
|
207
316
|
|
|
@@ -218,7 +327,7 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
218
327
|
expect(
|
|
219
328
|
container.querySelector("[data-first-run-startup-loading]"),
|
|
220
329
|
).toBeNull();
|
|
221
|
-
// oracle-change: the app
|
|
330
|
+
// oracle-change: the app stays mounted under the startup cover while first-run eligibility resolves.
|
|
222
331
|
expect(
|
|
223
332
|
container.querySelector("[data-testid='app-content']"),
|
|
224
333
|
).not.toBeNull();
|
|
@@ -226,6 +335,7 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
226
335
|
expect(
|
|
227
336
|
container.querySelector("[data-first-run-app-inert]"),
|
|
228
337
|
).not.toBeNull();
|
|
338
|
+
expect(container.querySelector("[data-first-run-cover]")).not.toBeNull();
|
|
229
339
|
expect(
|
|
230
340
|
container.querySelector("[data-testid='gate-ownership']")?.textContent,
|
|
231
341
|
).toBe("true");
|
|
@@ -235,6 +345,7 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
235
345
|
await status.promise;
|
|
236
346
|
});
|
|
237
347
|
expect(container.querySelector("[data-first-run-app-inert]")).toBeNull();
|
|
348
|
+
expect(container.querySelector("[data-first-run-cover]")).toBeNull();
|
|
238
349
|
});
|
|
239
350
|
|
|
240
351
|
it("retries a failed status read before revealing a first-run app", async () => {
|
|
@@ -538,6 +649,7 @@ describe("FirstRunOnboardingStartupGate", () => {
|
|
|
538
649
|
container.querySelector("[data-testid='first-run-onboarding']"),
|
|
539
650
|
).not.toBeNull();
|
|
540
651
|
});
|
|
652
|
+
expect(container.querySelector("[data-first-run-cover]")).toBeNull();
|
|
541
653
|
expect(container.querySelector("[data-first-run-app-hidden]")).toBeNull();
|
|
542
654
|
expect(
|
|
543
655
|
container.querySelector("[data-testid='app-content']"),
|
|
@@ -6,8 +6,10 @@ import { useOnboardingPreviewMode } from "@agent-native/core/client/onboarding/u
|
|
|
6
6
|
import { useSessionPreloading } from "@agent-native/core/client/use-session";
|
|
7
7
|
import { FIRST_RUN_ONBOARDING_COOKIE } from "@agent-native/core/shared/first-run-onboarding";
|
|
8
8
|
import { Button } from "@agent-native/toolkit/ui/button";
|
|
9
|
+
import { Skeleton } from "@agent-native/toolkit/ui/skeleton";
|
|
9
10
|
import React, { Suspense, lazy, useEffect, useState } from "react";
|
|
10
11
|
|
|
12
|
+
import { clearFirstRunFirstPaint } from "./first-run-first-paint.js";
|
|
11
13
|
import {
|
|
12
14
|
FirstRunOnboardingGateContext,
|
|
13
15
|
StartupInteractionContext,
|
|
@@ -53,15 +55,27 @@ function readFirstRunOnboardingCookieState(): FirstRunCookieState {
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
function DefaultStartupCover() {
|
|
59
|
+
return (
|
|
60
|
+
<div className="flex h-full gap-4 p-4">
|
|
61
|
+
<Skeleton className="h-full w-60" />
|
|
62
|
+
<Skeleton className="h-full flex-1" />
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
56
67
|
export function FirstRunOnboardingStartupGate({
|
|
57
68
|
children,
|
|
58
69
|
suppressSurface = false,
|
|
59
70
|
deferSurface = false,
|
|
71
|
+
cover = <DefaultStartupCover />,
|
|
60
72
|
}: {
|
|
61
73
|
children: React.ReactNode;
|
|
62
74
|
suppressSurface?: boolean;
|
|
63
75
|
/** Another startup operation owns onboarding until it settles. */
|
|
64
76
|
deferSurface?: boolean;
|
|
77
|
+
/** Fills the screen while first run is possible but not yet on screen. */
|
|
78
|
+
cover?: React.ReactNode;
|
|
65
79
|
}) {
|
|
66
80
|
const t = useT();
|
|
67
81
|
const inheritedInteractionBlock = useStartupInteractionBlocked();
|
|
@@ -138,14 +152,42 @@ export function FirstRunOnboardingStartupGate({
|
|
|
138
152
|
};
|
|
139
153
|
}, [retryNumber, shouldResolve, preloading]);
|
|
140
154
|
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (decision === "ineligible") clearFirstRunFirstPaint();
|
|
157
|
+
}, [decision]);
|
|
158
|
+
|
|
159
|
+
// A deferral that starts once onboarding is on screen must not unmount it:
|
|
160
|
+
// that drops the user's answers and shows the app between two dialogs.
|
|
161
|
+
const [surfaceShown, setSurfaceShown] = useState(false);
|
|
141
162
|
const ownsSurface =
|
|
142
|
-
!suppressSurface &&
|
|
163
|
+
!suppressSurface &&
|
|
164
|
+
decision === "eligible" &&
|
|
165
|
+
(!deferSurface || surfaceShown);
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (ownsSurface) setSurfaceShown(true);
|
|
168
|
+
}, [ownsSurface]);
|
|
143
169
|
const gateOwnsSurface =
|
|
144
170
|
deferSurface || (!suppressSurface && decision !== "ineligible");
|
|
171
|
+
// Until first run is ruled out, the app must not paint: a frame of it
|
|
172
|
+
// before (or between) onboarding screens reads as a flash of the home.
|
|
173
|
+
const coversApp =
|
|
174
|
+
!suppressSurface &&
|
|
175
|
+
!ownsSurface &&
|
|
176
|
+
(decision === "pending" || decision === "eligible");
|
|
145
177
|
|
|
146
|
-
// Deferral
|
|
147
|
-
//
|
|
148
|
-
const appIsInert =
|
|
178
|
+
// Deferral alone does not block the app: an ineligible user keeps using it
|
|
179
|
+
// while another startup operation settles.
|
|
180
|
+
const appIsInert =
|
|
181
|
+
coversApp || ownsSurface || (gateOwnsSurface && !deferSurface);
|
|
182
|
+
const coverElement = (
|
|
183
|
+
<div
|
|
184
|
+
aria-busy="true"
|
|
185
|
+
data-first-run-cover="true"
|
|
186
|
+
className="fixed inset-0 z-[100] bg-background"
|
|
187
|
+
>
|
|
188
|
+
{cover}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
149
191
|
|
|
150
192
|
return (
|
|
151
193
|
<FirstRunOnboardingGateContext.Provider value={gateOwnsSurface}>
|
|
@@ -179,8 +221,9 @@ export function FirstRunOnboardingStartupGate({
|
|
|
179
221
|
</Button>
|
|
180
222
|
</div>
|
|
181
223
|
)}
|
|
224
|
+
{coversApp && coverElement}
|
|
182
225
|
{ownsSurface && (
|
|
183
|
-
<Suspense fallback={
|
|
226
|
+
<Suspense fallback={coverElement}>
|
|
184
227
|
<FirstRunOnboarding initialFirstRun />
|
|
185
228
|
</Suspense>
|
|
186
229
|
)}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
AgentNativeI18nProvider,
|
|
10
10
|
type AgentNativeI18nProviderProps,
|
|
11
11
|
} from "@agent-native/core/client/i18n";
|
|
12
|
+
import { isFirstRunOnboardingEnabled } from "@agent-native/core/client/onboarding/first-run-enabled";
|
|
12
13
|
import { AgentNativeRouteWarmup } from "@agent-native/core/client/route-warmup";
|
|
13
14
|
import {
|
|
14
15
|
EMBEDDED_THEME_CHANGE_EVENT,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
McpApprovalReviewGate,
|
|
40
41
|
McpApprovalReviewSkeleton,
|
|
41
42
|
} from "../mcp-approval/McpApprovalReview.js";
|
|
43
|
+
import { getFirstRunFirstPaintScriptBody } from "../onboarding/first-run-first-paint.js";
|
|
42
44
|
import { FirstRunOnboardingStartupGate } from "../onboarding/first-run-startup-gate.js";
|
|
43
45
|
import {
|
|
44
46
|
AppShellSkeleton,
|
|
@@ -158,6 +160,17 @@ function McpAppWidgetBootScript() {
|
|
|
158
160
|
);
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
// Before the server-rendered skeleton paints, so a first-paint home never
|
|
164
|
+
// shows to someone about to see the role question.
|
|
165
|
+
function FirstRunFirstPaintScript() {
|
|
166
|
+
return (
|
|
167
|
+
<script
|
|
168
|
+
data-agent-native-first-run-first-paint="1"
|
|
169
|
+
dangerouslySetInnerHTML={{ __html: getFirstRunFirstPaintScriptBody() }}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
161
174
|
function EarlySessionBootstrapScript() {
|
|
162
175
|
const sessionPath = agentNativePath("/_agent-native/auth/session");
|
|
163
176
|
// The document handler starts this read again from the top of <head>, where
|
|
@@ -653,12 +666,14 @@ export function AppProviders({
|
|
|
653
666
|
<BuilderSignupStartupGate
|
|
654
667
|
experimentId={builderSignupExperiment}
|
|
655
668
|
suppressSurface={skipFirstRunOnboarding}
|
|
669
|
+
cover={fallback}
|
|
656
670
|
>
|
|
657
671
|
{children}
|
|
658
672
|
</BuilderSignupStartupGate>
|
|
659
673
|
) : (
|
|
660
674
|
<FirstRunOnboardingStartupGate
|
|
661
675
|
suppressSurface={skipFirstRunOnboarding}
|
|
676
|
+
cover={fallback}
|
|
662
677
|
>
|
|
663
678
|
{children}
|
|
664
679
|
</FirstRunOnboardingStartupGate>
|
|
@@ -697,6 +712,9 @@ export function AppProviders({
|
|
|
697
712
|
<>
|
|
698
713
|
<EarlySessionBootstrapScript />
|
|
699
714
|
<EarlyBetaRedirectScript />
|
|
715
|
+
{isFirstRunOnboardingEnabled() && !skipFirstRunOnboarding ? (
|
|
716
|
+
<FirstRunFirstPaintScript />
|
|
717
|
+
) : null}
|
|
700
718
|
</>
|
|
701
719
|
)}
|
|
702
720
|
<ClientOnly fallback={fallback}>
|
|
@@ -218,7 +218,8 @@ export function BuilderSignupActivationCover({
|
|
|
218
218
|
{children}
|
|
219
219
|
</div>
|
|
220
220
|
{activating ? (
|
|
221
|
-
|
|
221
|
+
// Above the first-run gate's cover, which waits under this one.
|
|
222
|
+
<div className="fixed inset-0 z-[110] flex gap-4 bg-background p-4">
|
|
222
223
|
<span role="status" className="sr-only">
|
|
223
224
|
{t("agentChat.common.loading")}
|
|
224
225
|
</span>
|
|
@@ -239,7 +240,9 @@ export function BuilderSignupActivationCover({
|
|
|
239
240
|
) : statusError ? (
|
|
240
241
|
<div
|
|
241
242
|
role="alert"
|
|
242
|
-
|
|
243
|
+
// Above the first-run gate's cover, which stays up while an unknown
|
|
244
|
+
// eligibility defers onboarding.
|
|
245
|
+
className="fixed bottom-4 right-4 z-[110] flex max-w-sm flex-col items-start gap-3 rounded-lg border bg-background p-4 shadow-lg"
|
|
243
246
|
>
|
|
244
247
|
{retryContent}
|
|
245
248
|
</div>
|
|
@@ -251,10 +254,12 @@ export function BuilderSignupActivationCover({
|
|
|
251
254
|
export function BuilderSignupStartupGate({
|
|
252
255
|
experimentId,
|
|
253
256
|
suppressSurface,
|
|
257
|
+
cover,
|
|
254
258
|
children,
|
|
255
259
|
}: {
|
|
256
260
|
experimentId?: string;
|
|
257
261
|
suppressSurface: boolean;
|
|
262
|
+
cover?: ReactNode;
|
|
258
263
|
children: ReactNode;
|
|
259
264
|
}) {
|
|
260
265
|
const { session } = useSession();
|
|
@@ -274,6 +279,7 @@ export function BuilderSignupStartupGate({
|
|
|
274
279
|
<FirstRunOnboardingStartupGate
|
|
275
280
|
suppressSurface={suppressSurface}
|
|
276
281
|
deferSurface={resolving || activating}
|
|
282
|
+
cover={cover}
|
|
277
283
|
>
|
|
278
284
|
{children}
|
|
279
285
|
</FirstRunOnboardingStartupGate>
|