@agent-native/core 0.80.7 → 0.80.9
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +18 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +6 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +8 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +10 -2
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +10 -2
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +9 -2
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +6 -0
- package/corpus/core/docs/content/template-design.mdx +9 -2
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/mcp.ts +10 -0
- package/corpus/core/src/cli/skills.ts +58 -12
- package/corpus/core/src/client/AssistantChat.tsx +70 -27
- package/corpus/core/src/client/analytics.ts +3 -1
- package/corpus/core/src/client/error-format.ts +25 -0
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
- package/corpus/core/src/client/guided-questions.tsx +32 -4
- package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
- package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
- package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
- package/corpus/core/src/client/session-replay.ts +34 -0
- package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
- package/corpus/core/src/coding-tools/index.ts +1 -1
- package/corpus/core/src/mcp/index.ts +2 -0
- package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
- package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
- package/corpus/core/src/mcp-client/index.ts +9 -0
- package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
- package/corpus/core/src/onboarding/types.ts +7 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
- package/corpus/core/src/server/agents-bundle.ts +35 -7
- package/corpus/core/src/styles/agent-native.css +5 -0
- package/corpus/core/src/templates/default/app/global.css +35 -35
- package/corpus/templates/analytics/AGENTS.md +6 -0
- package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
- package/corpus/templates/analytics/app/global.css +144 -40
- package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
- package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
- package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
- package/corpus/templates/assets/app/global.css +99 -35
- package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
- package/corpus/templates/assets/app/routes/library.tsx +4 -4
- package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/brain/app/global.css +63 -35
- package/corpus/templates/brain/app/routes/search.tsx +1 -1
- package/corpus/templates/brain/app/routes/settings.tsx +1 -1
- package/corpus/templates/brain/app/routes/sources.tsx +2 -2
- package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
- package/corpus/templates/calendar/app/global.css +69 -35
- package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/global.css +35 -35
- package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/AGENTS.md +13 -0
- package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
- package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
- package/corpus/templates/clips/actions/view-screen.ts +2 -2
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/global.css +47 -35
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
- package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
- package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
- package/corpus/templates/clips/desktop/src/app.tsx +290 -1
- package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
- package/corpus/templates/clips/desktop/src/styles.css +67 -52
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
- package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
- package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +69 -16
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
- package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/content/app/global.css +29 -15
- package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/content/changelog/2026-06-29-read-only-pages-no-longer-try-to-autosave-or-open-editor-onl.md +6 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
- package/corpus/templates/design/AGENTS.md +24 -14
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +24 -4
- package/corpus/templates/design/actions/edit-design.ts +6 -3
- package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
- package/corpus/templates/design/actions/generate-design.ts +6 -21
- package/corpus/templates/design/actions/generate-screens.ts +48 -5
- package/corpus/templates/design/actions/get-design.ts +1 -0
- package/corpus/templates/design/actions/present-design-variants.ts +355 -30
- package/corpus/templates/design/actions/update-design.ts +47 -10
- package/corpus/templates/design/actions/update-file.ts +33 -8
- package/corpus/templates/design/actions/view-screen.ts +89 -31
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +389 -71
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +596 -95
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +428 -221
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1197 -228
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +94 -217
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +28 -14
- package/corpus/templates/design/app/components/design/index.ts +0 -1
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +228 -170
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +140 -13
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +39 -8
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +4 -2
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +75 -5
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
- package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +17 -4
- package/corpus/templates/design/app/components/design/types.ts +9 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +448 -259
- package/corpus/templates/design/app/global.css +77 -49
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +8 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/design/app/i18n-data.ts +55 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2783 -658
- package/corpus/templates/design/app/root.tsx +1 -1
- package/corpus/templates/design/changelog/2026-06-29-agent-edits-to-a-design-are-no-longer-occasionally-dropped-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-box-shadow-and-gradient-colors-keep-named-css-colors-like-re.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-cut-cmd-ctrl-x-now-removes-the-selected-element-to-the-clipb.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-deleting-with-multiple-layers-selected-in-the-layers-panel-n.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
- package/corpus/templates/design/changelog/2026-06-29-duplicating-a-screen-now-gives-the-copy-its-own-layer-ids-so.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-hiding-and-re-showing-a-gradient-fill-now-preserves-each-sto.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-picking-a-design-direction-now-submits-to-the-agent-right-aw.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-style-changes-that-set-several-properties-at-once-fixed-size.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-editor-no-longer-crashes-when-a-screen-ends-up-with-dupl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
- package/corpus/templates/design/e2e/README.md +4 -3
- package/corpus/templates/design/e2e/global-setup.ts +24 -23
- package/corpus/templates/design/e2e/helpers.ts +122 -11
- package/corpus/templates/design/playwright.config.ts +19 -4
- package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
- package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
- package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
- package/corpus/templates/design/shared/code-layer.ts +125 -22
- package/corpus/templates/design/shared/color-utils.ts +159 -0
- package/corpus/templates/design/shared/generation-session.ts +42 -0
- package/corpus/templates/dispatch/app/global.css +79 -35
- package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
- package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
- package/corpus/templates/forms/app/global.css +64 -35
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
- package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/macros/app/global.css +25 -9
- package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
- package/corpus/templates/mail/app/global.css +42 -36
- package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
- package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
- package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
- package/corpus/templates/plan/app/global.css +74 -42
- package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/slides/app/global.css +49 -33
- package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/videos/app/global.css +35 -35
- package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +10 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +58 -12
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +54 -24
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +2 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +17 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +3 -4
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/guided-questions.d.ts +4 -0
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +16 -7
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +26 -1
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
- package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
- package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
- package/dist/client/resources/use-builtin-capabilities.js +2 -1
- package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +31 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +14 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +36 -7
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/coding-tools/index.js +1 -1
- package/dist/coding-tools/index.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +6 -0
- package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
- package/dist/mcp/screen-memory-stdio.js +213 -0
- package/dist/mcp/screen-memory-stdio.js.map +1 -0
- package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
- package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
- package/dist/mcp-client/builtin-capabilities.js +10 -0
- package/dist/mcp-client/builtin-capabilities.js.map +1 -1
- package/dist/mcp-client/index.d.ts +1 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +1 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/screen-memory-local.d.ts +61 -0
- package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
- package/dist/mcp-client/screen-memory-local.js +336 -0
- package/dist/mcp-client/screen-memory-local.js.map +1 -0
- package/dist/onboarding/types.d.ts +7 -0
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +26 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +22 -7
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +5 -0
- package/dist/templates/default/app/global.css +35 -35
- package/docs/content/locales/ar-SA/template-design.mdx +6 -0
- package/docs/content/locales/de-DE/template-design.mdx +8 -0
- package/docs/content/locales/es-ES/template-design.mdx +10 -2
- package/docs/content/locales/fr-FR/template-design.mdx +10 -2
- package/docs/content/locales/hi-IN/template-design.mdx +7 -0
- package/docs/content/locales/ja-JP/template-design.mdx +7 -0
- package/docs/content/locales/ko-KR/template-design.mdx +7 -0
- package/docs/content/locales/pt-BR/template-design.mdx +9 -2
- package/docs/content/locales/zh-CN/template-design.mdx +6 -0
- package/docs/content/locales/zh-TW/template-design.mdx +6 -0
- package/docs/content/template-design.mdx +9 -2
- package/package.json +1 -1
- package/src/templates/default/app/global.css +35 -35
- package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
- package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
- package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -258
|
@@ -8,63 +8,63 @@
|
|
|
8
8
|
|
|
9
9
|
:root {
|
|
10
10
|
--background: 0 0% 100%;
|
|
11
|
-
--foreground:
|
|
11
|
+
--foreground: 0 0% 10%;
|
|
12
12
|
--card: 0 0% 100%;
|
|
13
|
-
--card-foreground:
|
|
13
|
+
--card-foreground: 0 0% 10%;
|
|
14
14
|
--popover: 0 0% 100%;
|
|
15
|
-
--popover-foreground:
|
|
16
|
-
--primary:
|
|
15
|
+
--popover-foreground: 0 0% 10%;
|
|
16
|
+
--primary: 0 0% 15%;
|
|
17
17
|
--primary-foreground: 0 0% 100%;
|
|
18
|
-
--secondary:
|
|
19
|
-
--secondary-foreground:
|
|
20
|
-
--muted:
|
|
21
|
-
--muted-foreground:
|
|
22
|
-
--accent:
|
|
23
|
-
--accent-foreground:
|
|
18
|
+
--secondary: 0 0% 95%;
|
|
19
|
+
--secondary-foreground: 0 0% 15%;
|
|
20
|
+
--muted: 0 0% 95%;
|
|
21
|
+
--muted-foreground: 0 0% 45%;
|
|
22
|
+
--accent: 0 0% 95%;
|
|
23
|
+
--accent-foreground: 0 0% 15%;
|
|
24
24
|
--destructive: 0 84% 60%;
|
|
25
25
|
--destructive-foreground: 0 0% 98%;
|
|
26
|
-
--border:
|
|
27
|
-
--input:
|
|
28
|
-
--ring:
|
|
26
|
+
--border: 0 0% 90%;
|
|
27
|
+
--input: 0 0% 90%;
|
|
28
|
+
--ring: 0 0% 40%;
|
|
29
29
|
--radius: 0.5rem;
|
|
30
|
-
--sidebar-background:
|
|
31
|
-
--sidebar-foreground:
|
|
32
|
-
--sidebar-primary:
|
|
30
|
+
--sidebar-background: 0 0% 97%;
|
|
31
|
+
--sidebar-foreground: 0 0% 45%;
|
|
32
|
+
--sidebar-primary: 0 0% 15%;
|
|
33
33
|
--sidebar-primary-foreground: 0 0% 100%;
|
|
34
|
-
--sidebar-accent:
|
|
35
|
-
--sidebar-accent-foreground:
|
|
36
|
-
--sidebar-border:
|
|
37
|
-
--sidebar-ring:
|
|
34
|
+
--sidebar-accent: 0 0% 95%;
|
|
35
|
+
--sidebar-accent-foreground: 0 0% 15%;
|
|
36
|
+
--sidebar-border: 0 0% 90%;
|
|
37
|
+
--sidebar-ring: 0 0% 40%;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.dark {
|
|
41
|
-
--background:
|
|
41
|
+
--background: 0 0% 13%;
|
|
42
42
|
--foreground: 0 0% 90%;
|
|
43
|
-
--card:
|
|
43
|
+
--card: 0 0% 15%;
|
|
44
44
|
--card-foreground: 0 0% 90%;
|
|
45
|
-
--popover:
|
|
45
|
+
--popover: 0 0% 15%;
|
|
46
46
|
--popover-foreground: 0 0% 90%;
|
|
47
47
|
--primary: 0 0% 75%;
|
|
48
|
-
--primary-foreground:
|
|
49
|
-
--secondary:
|
|
48
|
+
--primary-foreground: 0 0% 10%;
|
|
49
|
+
--secondary: 0 0% 18%;
|
|
50
50
|
--secondary-foreground: 0 0% 90%;
|
|
51
|
-
--muted:
|
|
52
|
-
--muted-foreground:
|
|
53
|
-
--accent:
|
|
51
|
+
--muted: 0 0% 16%;
|
|
52
|
+
--muted-foreground: 0 0% 60%;
|
|
53
|
+
--accent: 0 0% 18%;
|
|
54
54
|
--accent-foreground: 0 0% 90%;
|
|
55
55
|
--destructive: 0 63% 51%;
|
|
56
56
|
--destructive-foreground: 0 0% 98%;
|
|
57
|
-
--border:
|
|
58
|
-
--input:
|
|
57
|
+
--border: 0 0% 24%;
|
|
58
|
+
--input: 0 0% 24%;
|
|
59
59
|
--ring: 0 0% 60%;
|
|
60
60
|
--radius: 0.5rem;
|
|
61
|
-
--sidebar-background:
|
|
62
|
-
--sidebar-foreground:
|
|
61
|
+
--sidebar-background: 0 0% 10%;
|
|
62
|
+
--sidebar-foreground: 0 0% 60%;
|
|
63
63
|
--sidebar-primary: 0 0% 75%;
|
|
64
|
-
--sidebar-primary-foreground:
|
|
65
|
-
--sidebar-accent:
|
|
64
|
+
--sidebar-primary-foreground: 0 0% 10%;
|
|
65
|
+
--sidebar-accent: 0 0% 16%;
|
|
66
66
|
--sidebar-accent-foreground: 0 0% 90%;
|
|
67
|
-
--sidebar-border:
|
|
67
|
+
--sidebar-border: 0 0% 20%;
|
|
68
68
|
--sidebar-ring: 0 0% 60%;
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { useT } from "@agent-native/core/client";
|
|
2
|
-
import { IconCheck } from "@tabler/icons-react";
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
|
|
5
|
-
import { Button } from "@/components/ui/button";
|
|
6
|
-
import { cn } from "@/lib/utils";
|
|
7
|
-
|
|
8
|
-
interface Variant {
|
|
9
|
-
id: string;
|
|
10
|
-
label: string;
|
|
11
|
-
content: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface VariantGridProps {
|
|
15
|
-
variants: Variant[];
|
|
16
|
-
selectedId?: string;
|
|
17
|
-
onSelect: (id: string) => void;
|
|
18
|
-
onUse: (id: string) => void;
|
|
19
|
-
compact?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function VariantGrid({
|
|
23
|
-
variants,
|
|
24
|
-
selectedId,
|
|
25
|
-
onSelect,
|
|
26
|
-
onUse,
|
|
27
|
-
compact = false,
|
|
28
|
-
}: VariantGridProps) {
|
|
29
|
-
const t = useT();
|
|
30
|
-
const [hoveredId, setHoveredId] = useState<string | null>(null);
|
|
31
|
-
const [internalSelectedId, setInternalSelectedId] = useState<
|
|
32
|
-
string | undefined
|
|
33
|
-
>(selectedId);
|
|
34
|
-
const activeSelectedId = selectedId ?? internalSelectedId;
|
|
35
|
-
const previewScale = compact ? 0.36 : 0.5;
|
|
36
|
-
const previewSize = `${100 / previewScale}%`;
|
|
37
|
-
|
|
38
|
-
// The same grid renders both in the full editor and in compact MCP App
|
|
39
|
-
// embeds, so it needs to wrap instead of squeezing previews into slivers.
|
|
40
|
-
const gridClass = compact
|
|
41
|
-
? variants.length <= 1
|
|
42
|
-
? "grid-cols-1"
|
|
43
|
-
: variants.length === 2
|
|
44
|
-
? "grid-cols-1 min-[520px]:grid-cols-2"
|
|
45
|
-
: variants.length === 3
|
|
46
|
-
? "grid-cols-1 min-[520px]:grid-cols-2 min-[820px]:grid-cols-3"
|
|
47
|
-
: "grid-cols-1 min-[520px]:grid-cols-2 min-[880px]:grid-cols-3"
|
|
48
|
-
: variants.length <= 1
|
|
49
|
-
? "grid-cols-1"
|
|
50
|
-
: variants.length === 2
|
|
51
|
-
? "grid-cols-1 sm:grid-cols-2"
|
|
52
|
-
: variants.length === 3
|
|
53
|
-
? "grid-cols-1 sm:grid-cols-2 xl:grid-cols-3"
|
|
54
|
-
: "grid-cols-1 sm:grid-cols-2";
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<div
|
|
58
|
-
className={cn(
|
|
59
|
-
"flex h-full w-full flex-col overflow-y-auto bg-background",
|
|
60
|
-
compact ? "p-3" : "p-3 sm:p-4 lg:p-6",
|
|
61
|
-
)}
|
|
62
|
-
>
|
|
63
|
-
<div
|
|
64
|
-
className={cn(
|
|
65
|
-
"grid min-h-0 flex-1 gap-3 sm:gap-4",
|
|
66
|
-
compact
|
|
67
|
-
? "auto-rows-[minmax(190px,1fr)]"
|
|
68
|
-
: "auto-rows-[minmax(260px,1fr)]",
|
|
69
|
-
gridClass,
|
|
70
|
-
)}
|
|
71
|
-
>
|
|
72
|
-
{variants.map((variant) => {
|
|
73
|
-
const isSelected = activeSelectedId === variant.id;
|
|
74
|
-
const isHovered = hoveredId === variant.id;
|
|
75
|
-
const showAction = isSelected || isHovered;
|
|
76
|
-
const selectVariant = () => {
|
|
77
|
-
setInternalSelectedId(variant.id);
|
|
78
|
-
onSelect(variant.id);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<div
|
|
83
|
-
key={variant.id}
|
|
84
|
-
className="flex flex-col gap-2"
|
|
85
|
-
onMouseEnter={() => setHoveredId(variant.id)}
|
|
86
|
-
onMouseLeave={() => setHoveredId(null)}
|
|
87
|
-
>
|
|
88
|
-
{/* Preview frame */}
|
|
89
|
-
<div
|
|
90
|
-
onClick={selectVariant}
|
|
91
|
-
onKeyDown={(event) => {
|
|
92
|
-
if (event.key !== "Enter" && event.key !== " ") return;
|
|
93
|
-
event.preventDefault();
|
|
94
|
-
selectVariant();
|
|
95
|
-
}}
|
|
96
|
-
role="button"
|
|
97
|
-
tabIndex={0}
|
|
98
|
-
aria-label={t("home.designPreview")}
|
|
99
|
-
className={cn(
|
|
100
|
-
"relative flex-1 cursor-pointer overflow-hidden rounded-lg border-2 bg-muted/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
101
|
-
isSelected
|
|
102
|
-
? "border-primary"
|
|
103
|
-
: "border-transparent hover:border-muted-foreground/30",
|
|
104
|
-
)}
|
|
105
|
-
>
|
|
106
|
-
{/* Scaled iframe preview */}
|
|
107
|
-
<iframe
|
|
108
|
-
srcDoc={wrapContent(variant.content)}
|
|
109
|
-
className="pointer-events-none h-full w-full origin-top-left"
|
|
110
|
-
style={{
|
|
111
|
-
width: previewSize,
|
|
112
|
-
height: previewSize,
|
|
113
|
-
transform: `scale(${previewScale})`,
|
|
114
|
-
}}
|
|
115
|
-
sandbox="allow-scripts"
|
|
116
|
-
title={variant.label}
|
|
117
|
-
/>
|
|
118
|
-
|
|
119
|
-
{/* Selection indicator */}
|
|
120
|
-
{isSelected && (
|
|
121
|
-
<div className="absolute top-2 right-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary">
|
|
122
|
-
<IconCheck className="h-3 w-3 text-primary-foreground" />
|
|
123
|
-
</div>
|
|
124
|
-
)}
|
|
125
|
-
|
|
126
|
-
{/* Commit action appears after hover or selection, including touch. */}
|
|
127
|
-
{showAction && (
|
|
128
|
-
<div className="absolute inset-0 flex items-center justify-center bg-black/40">
|
|
129
|
-
<Button
|
|
130
|
-
size="sm"
|
|
131
|
-
onClick={(e) => {
|
|
132
|
-
e.stopPropagation();
|
|
133
|
-
onUse(variant.id);
|
|
134
|
-
}}
|
|
135
|
-
aria-label={t("designEditor.useThisDirection")}
|
|
136
|
-
>
|
|
137
|
-
{t("designEditor.useThisDirection")}
|
|
138
|
-
</Button>
|
|
139
|
-
</div>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
{/* Label */}
|
|
144
|
-
<span
|
|
145
|
-
className={cn(
|
|
146
|
-
"text-center text-xs",
|
|
147
|
-
isSelected
|
|
148
|
-
? "font-medium text-foreground"
|
|
149
|
-
: "text-muted-foreground",
|
|
150
|
-
)}
|
|
151
|
-
>
|
|
152
|
-
{variant.label}
|
|
153
|
-
</span>
|
|
154
|
-
</div>
|
|
155
|
-
);
|
|
156
|
-
})}
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** Prepare generated HTML for the iframe preview without changing full docs. */
|
|
163
|
-
function wrapContent(content: string): string {
|
|
164
|
-
const previewStyle = `<style data-agent-native-preview>
|
|
165
|
-
*, *::before, *::after { box-sizing: border-box; }
|
|
166
|
-
html, body { width: 100%; height: 100%; overflow: hidden; }
|
|
167
|
-
body { margin: 0; background: #fff; }
|
|
168
|
-
</style>`;
|
|
169
|
-
const trimmed = content.trim();
|
|
170
|
-
|
|
171
|
-
if (/<!doctype\s+html|<html[\s>]/i.test(trimmed)) {
|
|
172
|
-
if (/<\/head>/i.test(trimmed)) {
|
|
173
|
-
return trimmed.replace(/<\/head>/i, `${previewStyle}</head>`);
|
|
174
|
-
}
|
|
175
|
-
return trimmed.replace(
|
|
176
|
-
/<html([^>]*)>/i, // i18n-ignore HTML parser regex, not UI copy
|
|
177
|
-
`<html$1><head>${previewStyle}</head>`,
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return `<!DOCTYPE html>
|
|
182
|
-
<html>
|
|
183
|
-
<head>
|
|
184
|
-
<meta charset="utf-8" />
|
|
185
|
-
${previewStyle}
|
|
186
|
-
</head>
|
|
187
|
-
<body>${trimmed}</body>
|
|
188
|
-
</html>`;
|
|
189
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { useT } from "@agent-native/core/client";
|
|
2
|
-
import { IconCheck, IconCopy } from "@tabler/icons-react";
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
4
|
-
import { toast } from "sonner";
|
|
5
|
-
|
|
6
|
-
import { Button } from "@/components/ui/button";
|
|
7
|
-
import { Textarea } from "@/components/ui/textarea";
|
|
8
|
-
import type { StandalonePick } from "@/hooks/use-variant-flow";
|
|
9
|
-
|
|
10
|
-
interface VariantHandoffCardProps {
|
|
11
|
-
pick: StandalonePick;
|
|
12
|
-
onDismiss: () => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Shown after a pick (or dismiss) when the editor was opened from a link-only
|
|
17
|
-
* host (CLI / Codex / Claude Code) that can't relay the choice over a chat
|
|
18
|
-
* bridge. The card owns the clipboard write so its "Copied" state stays
|
|
19
|
-
* truthful even when the browser blocks programmatic copy.
|
|
20
|
-
*/
|
|
21
|
-
export function VariantHandoffCard({
|
|
22
|
-
pick,
|
|
23
|
-
onDismiss,
|
|
24
|
-
}: VariantHandoffCardProps) {
|
|
25
|
-
const t = useT();
|
|
26
|
-
const [copied, setCopied] = useState(false);
|
|
27
|
-
|
|
28
|
-
const writeClipboard = useCallback(async () => {
|
|
29
|
-
try {
|
|
30
|
-
await navigator.clipboard.writeText(pick.text);
|
|
31
|
-
return true;
|
|
32
|
-
} catch {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
}, [pick.text]);
|
|
36
|
-
|
|
37
|
-
// Auto-copy on mount, but reflect what actually happened: if the browser
|
|
38
|
-
// blocks the write, leave the button on "Copy summary" so the user knows to
|
|
39
|
-
// copy (or select) it themselves.
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
let active = true;
|
|
42
|
-
void writeClipboard().then((ok) => {
|
|
43
|
-
if (active) setCopied(ok);
|
|
44
|
-
});
|
|
45
|
-
return () => {
|
|
46
|
-
active = false;
|
|
47
|
-
};
|
|
48
|
-
}, [writeClipboard]);
|
|
49
|
-
|
|
50
|
-
const onCopyClick = async () => {
|
|
51
|
-
const ok = await writeClipboard();
|
|
52
|
-
setCopied(ok);
|
|
53
|
-
toast[ok ? "success" : "info"](
|
|
54
|
-
ok
|
|
55
|
-
? t("designEditor.summaryCopied")
|
|
56
|
-
: t("designEditor.selectSummaryToCopy"),
|
|
57
|
-
);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div className="absolute inset-0 z-40 grid place-items-center bg-background/80 p-4 backdrop-blur-sm">
|
|
62
|
-
<div className="w-full max-w-md rounded-xl border border-border bg-card p-5 shadow-lg">
|
|
63
|
-
<div className="flex items-center gap-2.5">
|
|
64
|
-
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary">
|
|
65
|
-
<IconCheck className="h-3.5 w-3.5 text-primary-foreground" />
|
|
66
|
-
</span>
|
|
67
|
-
<div className="min-w-0">
|
|
68
|
-
<div className="text-sm font-medium leading-tight">
|
|
69
|
-
{pick.heading}
|
|
70
|
-
</div>
|
|
71
|
-
{pick.label && (
|
|
72
|
-
<div className="truncate text-xs text-muted-foreground">
|
|
73
|
-
“{pick.label}”
|
|
74
|
-
</div>
|
|
75
|
-
)}
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
<p className="mt-3 text-sm text-muted-foreground">
|
|
80
|
-
{t("designEditor.variantHandoffHelp")}
|
|
81
|
-
</p>
|
|
82
|
-
|
|
83
|
-
<Textarea
|
|
84
|
-
readOnly
|
|
85
|
-
value={pick.text}
|
|
86
|
-
className="mt-3 h-28 resize-none border-border/70 bg-muted/40 font-mono text-[11px] leading-relaxed"
|
|
87
|
-
onFocus={(event) => event.currentTarget.select()}
|
|
88
|
-
/>
|
|
89
|
-
|
|
90
|
-
<div className="mt-3 flex justify-end gap-2">
|
|
91
|
-
<Button
|
|
92
|
-
variant="ghost"
|
|
93
|
-
size="sm"
|
|
94
|
-
className="cursor-pointer"
|
|
95
|
-
onClick={onDismiss}
|
|
96
|
-
>
|
|
97
|
-
{t("designEditor.dismiss")}
|
|
98
|
-
</Button>
|
|
99
|
-
<Button
|
|
100
|
-
size="sm"
|
|
101
|
-
className="cursor-pointer gap-1.5"
|
|
102
|
-
onClick={onCopyClick}
|
|
103
|
-
>
|
|
104
|
-
{copied ? (
|
|
105
|
-
<IconCheck className="h-3.5 w-3.5" />
|
|
106
|
-
) : (
|
|
107
|
-
<IconCopy className="h-3.5 w-3.5" />
|
|
108
|
-
)}
|
|
109
|
-
{copied ? t("designEditor.copied") : t("designEditor.copySummary")}
|
|
110
|
-
</Button>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
sendToAgentChat,
|
|
3
|
-
agentNativePath,
|
|
4
|
-
callAction,
|
|
5
|
-
isEmbedAuthActive,
|
|
6
|
-
} from "@agent-native/core/client";
|
|
7
|
-
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
8
|
-
import { useEffect, useCallback, useState } from "react";
|
|
9
|
-
|
|
10
|
-
export const DESIGN_VARIANT_PICKED_EVENT = "agent-native-design-variant-picked";
|
|
11
|
-
|
|
12
|
-
export interface VariantCandidate {
|
|
13
|
-
id: string;
|
|
14
|
-
label: string;
|
|
15
|
-
content: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface VariantState {
|
|
19
|
-
designId: string;
|
|
20
|
-
variants: VariantCandidate[];
|
|
21
|
-
/** Optional caption above the grid, e.g. "Pick a direction". */
|
|
22
|
-
prompt?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** A pick/dismiss surfaced as a copyable handoff for link-only hosts. */
|
|
26
|
-
export interface StandalonePick {
|
|
27
|
-
/** Card heading, e.g. "Direction selected" or "Closed without picking". */
|
|
28
|
-
heading: string;
|
|
29
|
-
/** Chosen variant name, when a direction was picked. */
|
|
30
|
-
label?: string;
|
|
31
|
-
/** Paste-back text the user copies into their coding agent's chat. */
|
|
32
|
-
text: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* True when this editor was opened from a link-only host (CLI / Codex / Claude
|
|
37
|
-
* Code) that can't render the inline MCP app — the deep link carries
|
|
38
|
-
* `handoff=chat`. There's no host chat bridge to receive the pick, so after the
|
|
39
|
-
* user chooses we show a copyable summary to paste back into their agent.
|
|
40
|
-
*/
|
|
41
|
-
function isLinkOnlyHandoff(): boolean {
|
|
42
|
-
if (typeof window === "undefined") return false;
|
|
43
|
-
try {
|
|
44
|
-
return (
|
|
45
|
-
new URLSearchParams(window.location.search).get("handoff") === "chat"
|
|
46
|
-
);
|
|
47
|
-
} catch {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function variantHandoffText(
|
|
53
|
-
designId: string,
|
|
54
|
-
variant: VariantCandidate,
|
|
55
|
-
persisted: boolean,
|
|
56
|
-
): string {
|
|
57
|
-
const context = {
|
|
58
|
-
selectedDesign: {
|
|
59
|
-
designId,
|
|
60
|
-
variantId: variant.id,
|
|
61
|
-
label: variant.label,
|
|
62
|
-
file: "index.html",
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
return [
|
|
66
|
-
"Paste this back into your chat so your agent continues from the chosen design.",
|
|
67
|
-
"",
|
|
68
|
-
`I picked the "${variant.label}" design direction.`,
|
|
69
|
-
persisted
|
|
70
|
-
? `It's saved as index.html in design ${designId}. Refine from here with get-design-snapshot + generate-design, or export-coding-handoff to bring it into code. Don't show new variants unless I ask.`
|
|
71
|
-
: `Saving didn't finish — re-run present-design-variants or generate-design for design ${designId} before refining.`,
|
|
72
|
-
"",
|
|
73
|
-
"Design selection context:",
|
|
74
|
-
JSON.stringify(context, null, 2),
|
|
75
|
-
].join("\n");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function variantDismissText(): string {
|
|
79
|
-
return [
|
|
80
|
-
"Paste this back into your chat to keep going.",
|
|
81
|
-
"",
|
|
82
|
-
"I closed the design directions without picking one. Show me a different direction.",
|
|
83
|
-
].join("\n");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Polls `application-state/design-variants`. When the agent generates 2-5
|
|
88
|
-
* candidate variations, it writes them here; the editor surfaces a
|
|
89
|
-
* full-canvas grid (Claude Design-style: pick a direction before refining).
|
|
90
|
-
*
|
|
91
|
-
* On "Use this one", the chosen variant's HTML is persisted to the design as
|
|
92
|
-
* `index.html` via `generate-design`, and the pick is reported back through the
|
|
93
|
-
* right channel for the host: an embedded MCP host gets a chat message over the
|
|
94
|
-
* bridge; the first-party app posts to its own sidebar; a link-only host (CLI)
|
|
95
|
-
* gets a copyable summary to paste back. The variant state is then cleared.
|
|
96
|
-
*/
|
|
97
|
-
export function useVariantFlow(designId: string | undefined) {
|
|
98
|
-
const qc = useQueryClient();
|
|
99
|
-
const [state, setState] = useState<VariantState | null>(null);
|
|
100
|
-
const [standalonePick, setStandalonePick] = useState<StandalonePick | null>(
|
|
101
|
-
null,
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
const { data } = useQuery({
|
|
105
|
-
queryKey: ["design-variants"],
|
|
106
|
-
queryFn: async () => {
|
|
107
|
-
const res = await fetch(
|
|
108
|
-
agentNativePath("/_agent-native/application-state/design-variants"),
|
|
109
|
-
);
|
|
110
|
-
if (!res.ok) return null;
|
|
111
|
-
const text = await res.text();
|
|
112
|
-
if (!text) return null;
|
|
113
|
-
try {
|
|
114
|
-
return JSON.parse(text) as VariantState;
|
|
115
|
-
} catch {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
refetchInterval: 2_000,
|
|
120
|
-
structuralSharing: false,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
if (
|
|
125
|
-
data?.variants &&
|
|
126
|
-
data.variants.length > 0 &&
|
|
127
|
-
data.designId === designId
|
|
128
|
-
) {
|
|
129
|
-
setState(data);
|
|
130
|
-
} else {
|
|
131
|
-
setState(null);
|
|
132
|
-
}
|
|
133
|
-
}, [data, designId]);
|
|
134
|
-
|
|
135
|
-
const clear = useCallback(() => {
|
|
136
|
-
setState(null);
|
|
137
|
-
qc.setQueryData(["design-variants"], null);
|
|
138
|
-
fetch(agentNativePath("/_agent-native/application-state/design-variants"), {
|
|
139
|
-
method: "DELETE",
|
|
140
|
-
}).catch(() => {});
|
|
141
|
-
}, [qc]);
|
|
142
|
-
|
|
143
|
-
const dismissStandalonePick = useCallback(() => setStandalonePick(null), []);
|
|
144
|
-
|
|
145
|
-
const useVariant = useCallback(
|
|
146
|
-
async (variantId: string) => {
|
|
147
|
-
if (!state || !designId) return;
|
|
148
|
-
const chosen = state.variants.find((v) => v.id === variantId);
|
|
149
|
-
if (!chosen) return;
|
|
150
|
-
|
|
151
|
-
// Persist the chosen variant as the design's primary file via the
|
|
152
|
-
// agent's own action endpoint so every host lands on the same design.
|
|
153
|
-
let persisted = false;
|
|
154
|
-
try {
|
|
155
|
-
await callAction(
|
|
156
|
-
"generate-design" as any,
|
|
157
|
-
{
|
|
158
|
-
designId,
|
|
159
|
-
prompt: `User picked variant "${chosen.label}"`,
|
|
160
|
-
files: [
|
|
161
|
-
{
|
|
162
|
-
filename: "index.html",
|
|
163
|
-
content: chosen.content,
|
|
164
|
-
fileType: "html",
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
} as any,
|
|
168
|
-
);
|
|
169
|
-
await Promise.all([
|
|
170
|
-
qc.invalidateQueries({
|
|
171
|
-
queryKey: ["action", "get-design", { id: designId }],
|
|
172
|
-
}),
|
|
173
|
-
qc.invalidateQueries({ queryKey: ["action", "get-design"] }),
|
|
174
|
-
qc.invalidateQueries({ queryKey: ["action", "list-designs"] }),
|
|
175
|
-
]);
|
|
176
|
-
persisted = true;
|
|
177
|
-
if (typeof window !== "undefined") {
|
|
178
|
-
window.dispatchEvent(
|
|
179
|
-
new CustomEvent(DESIGN_VARIANT_PICKED_EVENT, {
|
|
180
|
-
detail: { designId, content: chosen.content },
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
} catch {
|
|
185
|
-
// Network error: report the choice below so the agent still records it;
|
|
186
|
-
// the grid still clears so the user isn't stuck.
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const refineHint = persisted
|
|
190
|
-
? `Its content has been saved as index.html. Continue refining from there if the user asks.`
|
|
191
|
-
: `Saving the chosen variant did not complete. Ask the user whether to retry before refining it.`;
|
|
192
|
-
const guardHint = persisted
|
|
193
|
-
? `Do not show further variants unless the user explicitly asks for "more options" or "alternatives".`
|
|
194
|
-
: `Do not claim the design file was updated until generate-design succeeds.`;
|
|
195
|
-
|
|
196
|
-
if (isEmbedAuthActive()) {
|
|
197
|
-
// Embedded MCP host (ChatGPT / Claude): the pick rides the host chat
|
|
198
|
-
// bridge straight into the conversation.
|
|
199
|
-
sendToAgentChat({
|
|
200
|
-
message: `I picked "${chosen.label}".`,
|
|
201
|
-
context: [
|
|
202
|
-
`The user chose variant "${chosen.label}" (id: ${chosen.id}) for design ${designId} inside the embedded Design app.`,
|
|
203
|
-
refineHint,
|
|
204
|
-
guardHint,
|
|
205
|
-
].join("\n"),
|
|
206
|
-
submit: true,
|
|
207
|
-
openSidebar: false,
|
|
208
|
-
});
|
|
209
|
-
} else if (isLinkOnlyHandoff()) {
|
|
210
|
-
// Link-only host (CLI / Codex / Claude Code): no chat bridge — show a
|
|
211
|
-
// copyable summary the user pastes back into their coding agent. The
|
|
212
|
-
// card owns the clipboard write so its "Copied" state stays truthful.
|
|
213
|
-
setStandalonePick({
|
|
214
|
-
heading: "Direction selected",
|
|
215
|
-
label: chosen.label,
|
|
216
|
-
text: variantHandoffText(designId, chosen, persisted),
|
|
217
|
-
});
|
|
218
|
-
} else {
|
|
219
|
-
// First-party app: post the pick to its own agent sidebar composer.
|
|
220
|
-
sendToAgentChat({
|
|
221
|
-
message: `I picked "${chosen.label}".`,
|
|
222
|
-
context: [
|
|
223
|
-
`The user chose variant "${chosen.label}" (id: ${chosen.id}) for design ${designId}.`,
|
|
224
|
-
refineHint,
|
|
225
|
-
guardHint,
|
|
226
|
-
].join("\n"),
|
|
227
|
-
submit: false,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
clear();
|
|
232
|
-
},
|
|
233
|
-
[state, designId, qc, clear],
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
const dismiss = useCallback(() => {
|
|
237
|
-
const embedded = isEmbedAuthActive();
|
|
238
|
-
clear();
|
|
239
|
-
if (isLinkOnlyHandoff() && !isEmbedAuthActive()) {
|
|
240
|
-
// No chat bridge to relay the dismissal — give the user a copyable note
|
|
241
|
-
// so their coding agent doesn't wait on a pick that isn't coming.
|
|
242
|
-
setStandalonePick({
|
|
243
|
-
heading: "Closed without picking",
|
|
244
|
-
text: variantDismissText(),
|
|
245
|
-
});
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
sendToAgentChat({
|
|
249
|
-
message: "Close the variants — none of these.",
|
|
250
|
-
context:
|
|
251
|
-
"User dismissed the variant grid without picking. Ask what direction they want instead.",
|
|
252
|
-
submit: embedded,
|
|
253
|
-
...(embedded ? { openSidebar: false } : {}),
|
|
254
|
-
});
|
|
255
|
-
}, [clear]);
|
|
256
|
-
|
|
257
|
-
return { state, useVariant, dismiss, standalonePick, dismissStandalonePick };
|
|
258
|
-
}
|