@agent-native/core 0.79.27 → 0.80.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +26 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +41 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +51 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +50 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +49 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +44 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +46 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +44 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +48 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +36 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +38 -0
- package/corpus/core/docs/content/template-design.mdx +45 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/agent/engine/index.ts +1 -0
- package/corpus/core/src/agent/engine/registry.ts +40 -0
- package/corpus/core/src/agent/production-agent.ts +6 -2
- package/corpus/core/src/cli/design-connect.ts +490 -0
- package/corpus/core/src/cli/index.ts +16 -0
- package/corpus/core/src/cli/skills.ts +126 -3
- package/corpus/core/src/client/AssistantChat.tsx +43 -7
- package/corpus/core/src/client/agent-chat.ts +27 -3
- package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +1 -1
- package/corpus/core/src/client/blocks/library/diagram.tsx +2 -2
- package/corpus/core/src/client/blocks/library/wireframe.tsx +1 -1
- package/corpus/core/src/client/chat/message-components.tsx +1 -1
- package/corpus/core/src/client/chat-model-groups.ts +1 -2
- package/corpus/core/src/client/components/LiveCursorOverlay.tsx +33 -66
- package/corpus/core/src/client/composer/TiptapComposer.tsx +99 -24
- package/corpus/core/src/client/composer/useVoiceDictation.ts +429 -260
- package/corpus/core/src/client/frame-protocol.ts +17 -2
- package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +2 -2
- package/corpus/core/src/client/sharing/ShareButton.tsx +20 -15
- package/corpus/core/src/client/use-agent-engine-configured.ts +80 -28
- package/corpus/core/src/server/transcribe-voice.ts +57 -22
- package/corpus/core/src/shared/mcp-embed-headers.ts +23 -1
- package/corpus/core/src/styles/agent-native.css +56 -7
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
- package/corpus/core/src/vite/client.ts +2 -0
- package/corpus/core/src/voice/index.ts +18 -0
- package/corpus/core/src/voice/voice-cleanup-prompt.ts +38 -0
- package/corpus/core/src/voice/voice-context.ts +217 -0
- package/corpus/core/src/voice/voice-replacements.ts +75 -0
- package/corpus/templates/analytics/AGENTS.md +4 -3
- package/corpus/templates/analytics/actions/list-session-recordings.ts +6 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +557 -400
- package/corpus/templates/analytics/app/global.css +0 -4
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +20 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +33 -8
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +7 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +7 -0
- package/corpus/templates/analytics/changelog/2026-06-28-ask-tab-now-matches-the-darker-app-background.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-28-dashboard-email-reports-now-use-cleaner-light-mode-snapshots.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-28-sessions-now-show-only-signed-in-recordings-with-playable-re.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +29 -7
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +5 -2
- package/corpus/templates/analytics/server/lib/session-replay.ts +24 -4
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -4
- package/corpus/templates/assets/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +29 -2
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +131 -42
- package/corpus/templates/brain/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/brain/app/i18n-data.ts +20 -0
- package/corpus/templates/brain/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +29 -1
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +417 -299
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +6 -19
- package/corpus/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/cleanup-transcript.ts +39 -9
- package/corpus/templates/clips/actions/finalize-meeting.ts +81 -12
- package/corpus/templates/clips/actions/lib/agents-md-context.ts +4 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +1 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +2 -2
- package/corpus/templates/clips/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/personal-vocabulary.ts +13 -8
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +60 -1
- package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -5
- package/corpus/templates/content/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +137 -0
- package/corpus/templates/design/AGENTS.md +95 -5
- package/corpus/templates/design/DESIGN.md +82 -0
- package/corpus/templates/design/DEVELOPING.md +43 -0
- package/corpus/templates/design/actions/add-localhost-screens.ts +426 -0
- package/corpus/templates/design/actions/apply-shader.ts +277 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +303 -0
- package/corpus/templates/design/actions/connect-localhost.ts +183 -0
- package/corpus/templates/design/actions/edit-design.ts +195 -42
- package/corpus/templates/design/actions/generate-design.ts +71 -1
- package/corpus/templates/design/actions/generate-screens.ts +193 -0
- package/corpus/templates/design/actions/get-code-layer-projection.ts +191 -0
- package/corpus/templates/design/actions/get-shader.ts +119 -0
- package/corpus/templates/design/actions/list-localhost-connections.ts +95 -0
- package/corpus/templates/design/actions/navigate.ts +55 -2
- package/corpus/templates/design/actions/view-screen.ts +68 -1
- package/corpus/templates/design/agent-native.app-skill.json +10 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +761 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +2057 -103
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +74 -38
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +399 -0
- package/corpus/templates/design/app/components/design/EditPanel.tsx +3185 -439
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +1124 -0
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +3116 -147
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +700 -13
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +107 -63
- package/corpus/templates/design/app/components/design/index.ts +0 -5
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +286 -0
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +699 -0
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +461 -0
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +166 -0
- package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +1420 -0
- package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +420 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +215 -0
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +71 -0
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +518 -0
- package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +106 -0
- package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +361 -0
- package/corpus/templates/design/app/components/design/inspector/index.ts +60 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +201 -0
- package/corpus/templates/design/app/components/design/types.ts +23 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +24 -13
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +4 -4
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +474 -36
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +22 -5
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +24 -11
- package/corpus/templates/design/app/global.css +121 -3
- package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +130 -8
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +329 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +264 -0
- package/corpus/templates/design/app/i18n-data.ts +2790 -1
- package/corpus/templates/design/app/pages/DesignEditor.tsx +5108 -851
- package/corpus/templates/design/changelog/2026-06-28-annotate-mode-now-combines-drawing-and-comment-pins-in-one-c.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-design-editor-panel-borders-are-cleaner-so-the-canvas-edge-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-drawing-prompts-now-reliably-open-and-submit-to-the-design-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-editor-app-menus-now-use-an-outline-agent-native-mark-with-b.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-layer-selection-now-updates-chat-context-without-opening-the.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-layer-selections-now-preserve-hidden-and-locked-canvas-state.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-handles-zooming-drawing-opening-and-dele.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-selects-screens-on-click-and-opens-them-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-screen-overview-zooms-into-the-active-screen-with-smoother-e.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-selected-element-chips-in-chat-are-shorter-and-easier-to-sca.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-the-design-editor-toolbar-is-more-compact-and-the-app-menu-m.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-at-the-top-of-the-design-sidebar-instead-of-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-in-the-right-inspector-beside-the-design-tab.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-active-sidebar-rows-use-soft-highlights.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-agents-can-now-open-screen-overview-focus-screens-and-add.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-agents-now-edit-broad-copy-changes-more-reliably.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-editor-extensions-now-run-inline-beside-the-artboard.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-sidebars-use-darker-chrome-and-chat-warns-immediately.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-visual-edit-can-open-localhost-routes-as-url-backed-screens.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/db/schema.ts +26 -0
- package/corpus/templates/design/server/lib/design-snapshot.ts +1 -1
- package/corpus/templates/design/server/plugins/agent-chat.ts +3 -0
- package/corpus/templates/design/shared/api.ts +27 -0
- package/corpus/templates/design/shared/canvas-frames.ts +103 -0
- package/corpus/templates/design/shared/canvas-math.ts +1058 -0
- package/corpus/templates/design/shared/code-layer.ts +2212 -0
- package/corpus/templates/design/shared/color-utils.ts +180 -0
- package/corpus/templates/design/shared/generation-session.ts +61 -0
- package/corpus/templates/design/shared/shader-presets.ts +782 -0
- package/corpus/templates/design/shared/shader-safety.ts +137 -0
- package/corpus/templates/design/shared/source-mode.ts +237 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +149 -6
- package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/forms/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
- package/corpus/templates/macros/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +408 -247
- package/corpus/templates/mail/app/i18n/ar-SA.ts +4 -0
- package/corpus/templates/mail/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/mail/app/i18n/en-US.ts +4 -0
- package/corpus/templates/mail/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/mail/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/mail/app/i18n/hi-IN.ts +4 -0
- package/corpus/templates/mail/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/mail/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/mail/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/mail/app/i18n/zh-CN.ts +4 -0
- package/corpus/templates/mail/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/mail/changelog/2026-06-28-pinned-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +6 -8
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
- package/corpus/templates/plan/app/global.css +61 -78
- package/corpus/templates/plan/app/pages/PlansPage.tsx +8 -0
- package/corpus/templates/plan/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-28-plans-use-the-shared-neutral-light-and-dark-theme.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-28-sending-open-feedback-from-a-plan-now-opens-the-inline-plan-.md +6 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
- package/corpus/templates/slides/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/videos/app/components/Sidebar.tsx +2 -2
- package/corpus/templates/videos/app/components/layout/Layout.tsx +29 -2
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +113 -30
- package/corpus/templates/videos/app/i18n/ar-SA.ts +2 -0
- package/corpus/templates/videos/app/i18n/de-DE.ts +2 -0
- package/corpus/templates/videos/app/i18n/en-US.ts +2 -0
- package/corpus/templates/videos/app/i18n/es-ES.ts +2 -0
- package/corpus/templates/videos/app/i18n/fr-FR.ts +2 -0
- package/corpus/templates/videos/app/i18n/hi-IN.ts +2 -0
- package/corpus/templates/videos/app/i18n/ja-JP.ts +2 -0
- package/corpus/templates/videos/app/i18n/ko-KR.ts +2 -0
- package/corpus/templates/videos/app/i18n/pt-BR.ts +2 -0
- package/corpus/templates/videos/app/i18n/zh-CN.ts +2 -0
- package/corpus/templates/videos/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +9 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +37 -0
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/design-connect.d.ts +52 -0
- package/dist/cli/design-connect.d.ts.map +1 -0
- package/dist/cli/design-connect.js +409 -0
- package/dist/cli/design-connect.js.map +1 -0
- package/dist/cli/index.js +15 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +121 -3
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +38 -8
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +6 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +17 -3
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +1 -1
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.js +1 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/chat/message-components.js +1 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +1 -2
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/components/LiveCursorOverlay.d.ts +1 -2
- package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.js +19 -40
- package/dist/client/components/LiveCursorOverlay.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +3 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +86 -24
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts +9 -0
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +154 -32
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/frame-protocol.d.ts +17 -2
- package/dist/client/frame-protocol.d.ts.map +1 -1
- package/dist/client/frame-protocol.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +2 -2
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +2 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +7 -6
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts +5 -0
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +51 -25
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +8 -8
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +40 -24
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -0
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +20 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/styles/agent-native.css +56 -7
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/dist/voice/index.d.ts +5 -0
- package/dist/voice/index.d.ts.map +1 -0
- package/dist/voice/index.js +4 -0
- package/dist/voice/index.js.map +1 -0
- package/dist/voice/voice-cleanup-prompt.d.ts +6 -0
- package/dist/voice/voice-cleanup-prompt.d.ts.map +1 -0
- package/dist/voice/voice-cleanup-prompt.js +26 -0
- package/dist/voice/voice-cleanup-prompt.js.map +1 -0
- package/dist/voice/voice-context.d.ts +25 -0
- package/dist/voice/voice-context.d.ts.map +1 -0
- package/dist/voice/voice-context.js +156 -0
- package/dist/voice/voice-context.js.map +1 -0
- package/dist/voice/voice-replacements.d.ts +4 -0
- package/dist/voice/voice-replacements.d.ts.map +1 -0
- package/dist/voice/voice-replacements.js +52 -0
- package/dist/voice/voice-replacements.js.map +1 -0
- package/docs/content/locales/ar-SA/template-design.mdx +41 -0
- package/docs/content/locales/de-DE/template-design.mdx +51 -0
- package/docs/content/locales/es-ES/template-design.mdx +50 -0
- package/docs/content/locales/fr-FR/template-design.mdx +49 -0
- package/docs/content/locales/hi-IN/template-design.mdx +44 -0
- package/docs/content/locales/ja-JP/template-design.mdx +46 -0
- package/docs/content/locales/ko-KR/template-design.mdx +44 -0
- package/docs/content/locales/pt-BR/template-design.mdx +48 -0
- package/docs/content/locales/zh-CN/template-design.mdx +36 -0
- package/docs/content/locales/zh-TW/template-design.mdx +38 -0
- package/docs/content/template-design.mdx +45 -0
- package/package.json +2 -1
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
- package/corpus/templates/design/app/components/design/DesignToolbar.tsx +0 -339
- package/corpus/templates/design/app/components/design/PresentMode.tsx +0 -68
- package/corpus/templates/design/app/components/design/ViewportTabs.tsx +0 -149
- package/corpus/templates/design/app/components/design/ZoomControls.tsx +0 -157
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { sendToAgentChat, useT } from "@agent-native/core/client";
|
|
2
2
|
import {
|
|
3
|
+
IconAlertTriangle,
|
|
4
|
+
IconBolt,
|
|
5
|
+
IconCircleCheck,
|
|
3
6
|
IconMessage,
|
|
4
7
|
IconMessageCheck,
|
|
5
8
|
IconSend,
|
|
6
9
|
IconX,
|
|
7
10
|
} from "@tabler/icons-react";
|
|
8
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
9
12
|
|
|
10
13
|
import { Button } from "@/components/ui/button";
|
|
11
14
|
import { Textarea } from "@/components/ui/textarea";
|
|
@@ -23,10 +26,14 @@ export interface CanvasPin {
|
|
|
23
26
|
yPct: number;
|
|
24
27
|
/** Optional CSS selector of the element under the click, for context */
|
|
25
28
|
targetSelector?: string;
|
|
29
|
+
/** Best-effort stable canvas/code-layer id when the clicked layer exposes one. */
|
|
30
|
+
targetAnchorId?: string;
|
|
26
31
|
/** Optional snippet of text content the user clicked near */
|
|
27
32
|
targetText?: string;
|
|
28
33
|
/** Pending comment text the user is composing */
|
|
29
34
|
draft?: string;
|
|
35
|
+
/** Held locally until the user batch-applies queued comments. */
|
|
36
|
+
queued?: boolean;
|
|
30
37
|
/** Submitted state — the marker stays visible as confirmation. */
|
|
31
38
|
submitted?: boolean;
|
|
32
39
|
}
|
|
@@ -34,8 +41,16 @@ export interface CanvasPin {
|
|
|
34
41
|
interface CanvasCommentPinsProps {
|
|
35
42
|
/** Whether the pin tool is active. When true, clicks drop pins. */
|
|
36
43
|
active: boolean;
|
|
44
|
+
/** In queue mode, pin Send adds to the shared annotation batch. */
|
|
45
|
+
submitMode?: "direct" | "queue";
|
|
37
46
|
/** Disable / exit the pin mode (called on Escape, after submit, etc.) */
|
|
38
47
|
onClose: () => void;
|
|
48
|
+
/** Mirrors local pins to a parent that can submit them with other annotations. */
|
|
49
|
+
onPinsChange?: (pins: CanvasPin[]) => void;
|
|
50
|
+
/** Increment to mark queued pins as submitted by a parent action. */
|
|
51
|
+
submitQueuedSignal?: number;
|
|
52
|
+
/** Keep the click plane below a sibling draw toolbar in combined annotate mode. */
|
|
53
|
+
clickPlaneUnderToolbar?: boolean;
|
|
39
54
|
/**
|
|
40
55
|
* Selector for the canvas surface (e.g. `.slide-content`). Pins are anchored
|
|
41
56
|
* to this element's bounding rect; clicks outside are ignored.
|
|
@@ -49,6 +64,210 @@ interface CanvasCommentPinsProps {
|
|
|
49
64
|
contextLabel?: string;
|
|
50
65
|
}
|
|
51
66
|
|
|
67
|
+
type PinCapabilityStatus =
|
|
68
|
+
| "deterministic"
|
|
69
|
+
| "needs-agent"
|
|
70
|
+
| "conflict"
|
|
71
|
+
| "unsupported";
|
|
72
|
+
|
|
73
|
+
interface PinStatusMeta {
|
|
74
|
+
status: PinCapabilityStatus;
|
|
75
|
+
label: string;
|
|
76
|
+
shortLabel: string;
|
|
77
|
+
detail: string;
|
|
78
|
+
markerClassName: string;
|
|
79
|
+
badgeClassName: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const STATUS_META: Record<PinCapabilityStatus, PinStatusMeta> = {
|
|
83
|
+
deterministic: {
|
|
84
|
+
status: "deterministic",
|
|
85
|
+
label: "",
|
|
86
|
+
shortLabel: "",
|
|
87
|
+
detail: "",
|
|
88
|
+
markerClassName: "bg-emerald-500 text-white ring-emerald-200",
|
|
89
|
+
badgeClassName:
|
|
90
|
+
"border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
|
|
91
|
+
},
|
|
92
|
+
"needs-agent": {
|
|
93
|
+
status: "needs-agent",
|
|
94
|
+
label: "",
|
|
95
|
+
shortLabel: "",
|
|
96
|
+
detail: "",
|
|
97
|
+
markerClassName: "bg-amber-400 text-amber-950 ring-amber-200",
|
|
98
|
+
badgeClassName:
|
|
99
|
+
"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",
|
|
100
|
+
},
|
|
101
|
+
conflict: {
|
|
102
|
+
status: "conflict",
|
|
103
|
+
label: "",
|
|
104
|
+
shortLabel: "",
|
|
105
|
+
detail: "",
|
|
106
|
+
markerClassName:
|
|
107
|
+
"bg-destructive text-destructive-foreground ring-destructive/30",
|
|
108
|
+
badgeClassName: "border-destructive/30 bg-destructive/10 text-destructive",
|
|
109
|
+
},
|
|
110
|
+
unsupported: {
|
|
111
|
+
status: "unsupported",
|
|
112
|
+
label: "",
|
|
113
|
+
shortLabel: "",
|
|
114
|
+
detail: "",
|
|
115
|
+
markerClassName: "bg-muted text-muted-foreground ring-border",
|
|
116
|
+
badgeClassName: "border-border bg-muted text-muted-foreground",
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
function localizePinStatus(
|
|
121
|
+
status: PinStatusMeta,
|
|
122
|
+
t: (key: string, options?: Record<string, unknown>) => string,
|
|
123
|
+
): PinStatusMeta {
|
|
124
|
+
return {
|
|
125
|
+
...status,
|
|
126
|
+
label: t(`visualEditor.pinStatus.${status.status}.label`),
|
|
127
|
+
shortLabel: t(`visualEditor.pinStatus.${status.status}.shortLabel`),
|
|
128
|
+
detail: t(`visualEditor.pinStatus.${status.status}.detail`),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function escapeAttributeValue(value: string): string {
|
|
133
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function escapeCssIdentifier(value: string): string {
|
|
137
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
138
|
+
return CSS.escape(value);
|
|
139
|
+
}
|
|
140
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "\\$&");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getTargetAnchor(target?: HTMLElement | null): {
|
|
144
|
+
targetSelector?: string;
|
|
145
|
+
targetAnchorId?: string;
|
|
146
|
+
} {
|
|
147
|
+
const anchor = target?.closest(
|
|
148
|
+
"[data-agent-native-node-id], [data-builder-id], [data-loc], [id]",
|
|
149
|
+
);
|
|
150
|
+
if (!(anchor instanceof HTMLElement)) return {};
|
|
151
|
+
|
|
152
|
+
for (const attribute of [
|
|
153
|
+
"data-agent-native-node-id",
|
|
154
|
+
"data-builder-id",
|
|
155
|
+
"data-loc",
|
|
156
|
+
]) {
|
|
157
|
+
const value = anchor.getAttribute(attribute);
|
|
158
|
+
if (value) {
|
|
159
|
+
return {
|
|
160
|
+
targetSelector: `[${attribute}="${escapeAttributeValue(value)}"]`,
|
|
161
|
+
targetAnchorId: value,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (anchor.id) {
|
|
167
|
+
return {
|
|
168
|
+
targetSelector: `#${escapeCssIdentifier(anchor.id)}`,
|
|
169
|
+
targetAnchorId: anchor.id,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function wordsIncludePair(
|
|
177
|
+
text: string,
|
|
178
|
+
first: string,
|
|
179
|
+
second: string,
|
|
180
|
+
): boolean {
|
|
181
|
+
return (
|
|
182
|
+
new RegExp(`\\b${first}\\b`, "i").test(text) &&
|
|
183
|
+
new RegExp(`\\b${second}\\b`, "i").test(text)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function hasContradictoryLanguage(text: string): boolean {
|
|
188
|
+
return [
|
|
189
|
+
["bigger", "smaller"],
|
|
190
|
+
["larger", "smaller"],
|
|
191
|
+
["hide", "show"],
|
|
192
|
+
["remove", "keep"],
|
|
193
|
+
["delete", "keep"],
|
|
194
|
+
["left", "right"],
|
|
195
|
+
["top", "bottom"],
|
|
196
|
+
["dark", "light"],
|
|
197
|
+
].some(([first, second]) => wordsIncludePair(text, first, second));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function pinsLikelyOverlap(pin: CanvasPin, other: CanvasPin): boolean {
|
|
201
|
+
if (pin.id === other.id || other.submitted) return false;
|
|
202
|
+
if (pin.targetSelector && pin.targetSelector === other.targetSelector)
|
|
203
|
+
return true;
|
|
204
|
+
const xDelta = Math.abs(pin.xPct - other.xPct);
|
|
205
|
+
const yDelta = Math.abs(pin.yPct - other.yPct);
|
|
206
|
+
return xDelta <= 4 && yDelta <= 4;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function derivePinStatus(pin: CanvasPin, pins: CanvasPin[]): PinStatusMeta {
|
|
210
|
+
const text = (pin.draft || "").toLowerCase();
|
|
211
|
+
const anchored = Boolean(pin.targetSelector || pin.targetAnchorId);
|
|
212
|
+
const unsupported =
|
|
213
|
+
/\b(api|backend|database|server|auth|login|oauth|stripe|payment|email|webhook|permission|role|roles|deploy|domain|routing|route|video|audio|3d|three\.js|pdf|spreadsheet)\b/i.test(
|
|
214
|
+
text,
|
|
215
|
+
);
|
|
216
|
+
if (unsupported) return STATUS_META.unsupported;
|
|
217
|
+
|
|
218
|
+
const overlaps = pins.some(
|
|
219
|
+
(other) =>
|
|
220
|
+
pinsLikelyOverlap(pin, other) &&
|
|
221
|
+
(pin.draft || "").trim() &&
|
|
222
|
+
(other.draft || "").trim() &&
|
|
223
|
+
(pin.draft || "").trim() !== (other.draft || "").trim(),
|
|
224
|
+
);
|
|
225
|
+
if (overlaps || hasContradictoryLanguage(text)) {
|
|
226
|
+
return STATUS_META.conflict;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const directEdit =
|
|
230
|
+
/\b(color|font|copy|text|label|spacing|gap|margin|padding|radius|rounded|border|align|center|move|resize|width|height|background|image|button|headline|section|swap|replace)\b/i.test(
|
|
231
|
+
text,
|
|
232
|
+
);
|
|
233
|
+
const vagueInstruction =
|
|
234
|
+
/\b(polish|improve|better|nice|clean up|fix it|make it work|decide|surprise me)\b/i.test(
|
|
235
|
+
text,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (anchored && directEdit && !vagueInstruction) {
|
|
239
|
+
return STATUS_META.deterministic;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return STATUS_META["needs-agent"];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function PinStatusBadge({ status }: { status: PinStatusMeta }) {
|
|
246
|
+
const Icon =
|
|
247
|
+
status.status === "deterministic"
|
|
248
|
+
? IconCircleCheck
|
|
249
|
+
: status.status === "unsupported" || status.status === "conflict"
|
|
250
|
+
? IconAlertTriangle
|
|
251
|
+
: IconBolt;
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<Tooltip>
|
|
255
|
+
<TooltipTrigger asChild>
|
|
256
|
+
<span
|
|
257
|
+
className={cn(
|
|
258
|
+
"inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none",
|
|
259
|
+
status.badgeClassName,
|
|
260
|
+
)}
|
|
261
|
+
>
|
|
262
|
+
<Icon className="size-3" />
|
|
263
|
+
{status.label}
|
|
264
|
+
</span>
|
|
265
|
+
</TooltipTrigger>
|
|
266
|
+
<TooltipContent>{status.detail}</TooltipContent>
|
|
267
|
+
</Tooltip>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
52
271
|
/**
|
|
53
272
|
* Click-to-comment pins anchored to the canvas.
|
|
54
273
|
*
|
|
@@ -67,7 +286,11 @@ interface CanvasCommentPinsProps {
|
|
|
67
286
|
*/
|
|
68
287
|
export function CanvasCommentPins({
|
|
69
288
|
active,
|
|
289
|
+
submitMode = "direct",
|
|
70
290
|
onClose,
|
|
291
|
+
onPinsChange,
|
|
292
|
+
submitQueuedSignal,
|
|
293
|
+
clickPlaneUnderToolbar = false,
|
|
71
294
|
canvasSelector,
|
|
72
295
|
contextId,
|
|
73
296
|
contextLabel,
|
|
@@ -76,6 +299,7 @@ export function CanvasCommentPins({
|
|
|
76
299
|
const [pins, setPins] = useState<CanvasPin[]>([]);
|
|
77
300
|
const [activePinId, setActivePinId] = useState<string | null>(null);
|
|
78
301
|
const containerRef = useRef<HTMLElement | null>(null);
|
|
302
|
+
const lastSubmitQueuedSignalRef = useRef(submitQueuedSignal);
|
|
79
303
|
const [canvasEl, setCanvasEl] = useState<HTMLElement | null>(null);
|
|
80
304
|
|
|
81
305
|
// Reset pins when the context (slide) changes — they're scoped to one view.
|
|
@@ -113,12 +337,7 @@ export function CanvasCommentPins({
|
|
|
113
337
|
// Build a best-effort selector for parent-DOM canvases. For iframe
|
|
114
338
|
// canvases the transparent overlay captures the click, so target details
|
|
115
339
|
// are intentionally omitted but the precise position is preserved.
|
|
116
|
-
|
|
117
|
-
const builderId = target
|
|
118
|
-
?.closest("[data-builder-id]")
|
|
119
|
-
?.getAttribute("data-builder-id");
|
|
120
|
-
if (builderId) targetSelector = `[data-builder-id="${builderId}"]`;
|
|
121
|
-
|
|
340
|
+
const { targetSelector, targetAnchorId } = getTargetAnchor(target);
|
|
122
341
|
const targetText = target?.textContent?.trim().slice(0, 80) || undefined;
|
|
123
342
|
|
|
124
343
|
const newPin: CanvasPin = {
|
|
@@ -126,6 +345,7 @@ export function CanvasCommentPins({
|
|
|
126
345
|
xPct,
|
|
127
346
|
yPct,
|
|
128
347
|
targetSelector,
|
|
348
|
+
targetAnchorId,
|
|
129
349
|
targetText,
|
|
130
350
|
draft: "",
|
|
131
351
|
};
|
|
@@ -181,34 +401,140 @@ export function CanvasCommentPins({
|
|
|
181
401
|
if (activePinId === id) setActivePinId(null);
|
|
182
402
|
};
|
|
183
403
|
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
404
|
+
const queuedPins = useMemo(
|
|
405
|
+
() =>
|
|
406
|
+
pins.filter(
|
|
407
|
+
(pin) => pin.queued && !pin.submitted && (pin.draft || "").trim(),
|
|
408
|
+
),
|
|
409
|
+
[pins],
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
useEffect(() => {
|
|
413
|
+
onPinsChange?.(pins);
|
|
414
|
+
}, [onPinsChange, pins]);
|
|
415
|
+
|
|
416
|
+
useEffect(() => {
|
|
417
|
+
if (
|
|
418
|
+
submitQueuedSignal === undefined ||
|
|
419
|
+
submitQueuedSignal === lastSubmitQueuedSignalRef.current
|
|
420
|
+
) {
|
|
188
421
|
return;
|
|
189
422
|
}
|
|
423
|
+
lastSubmitQueuedSignalRef.current = submitQueuedSignal;
|
|
424
|
+
if (queuedPins.length === 0) return;
|
|
425
|
+
const submittedIds = new Set(queuedPins.map((pin) => pin.id));
|
|
426
|
+
setPins((prev) =>
|
|
427
|
+
prev.map((pin) =>
|
|
428
|
+
submittedIds.has(pin.id)
|
|
429
|
+
? { ...pin, queued: false, submitted: true }
|
|
430
|
+
: pin,
|
|
431
|
+
),
|
|
432
|
+
);
|
|
433
|
+
setActivePinId(null);
|
|
434
|
+
}, [queuedPins, submitQueuedSignal]);
|
|
435
|
+
|
|
436
|
+
const submittedCount = pins.filter((pin) => pin.submitted).length;
|
|
437
|
+
const statusCounts = useMemo(
|
|
438
|
+
() =>
|
|
439
|
+
pins.reduce<Record<PinCapabilityStatus, number>>(
|
|
440
|
+
(counts, pin) => {
|
|
441
|
+
const status = derivePinStatus(pin, pins).status;
|
|
442
|
+
counts[status] += 1;
|
|
443
|
+
return counts;
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
deterministic: 0,
|
|
447
|
+
"needs-agent": 0,
|
|
448
|
+
conflict: 0,
|
|
449
|
+
unsupported: 0,
|
|
450
|
+
},
|
|
451
|
+
),
|
|
452
|
+
[pins],
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
const buildPinLines = (pin: CanvasPin, index?: number) => {
|
|
456
|
+
const status = localizePinStatus(derivePinStatus(pin, pins), t);
|
|
190
457
|
const lines = [
|
|
191
|
-
|
|
458
|
+
index === undefined
|
|
459
|
+
? `[Comment pin on ${contextLabel || contextId}]`
|
|
460
|
+
: `[${index + 1}] Comment pin on ${contextLabel || contextId}`,
|
|
192
461
|
`Position: ${pin.xPct.toFixed(1)}% from left, ${pin.yPct.toFixed(1)}% from top`,
|
|
462
|
+
`Capability: ${status.label} - ${status.detail}`,
|
|
193
463
|
];
|
|
464
|
+
if (pin.targetAnchorId) lines.push(`Anchor id: ${pin.targetAnchorId}`);
|
|
194
465
|
if (pin.targetSelector) lines.push(`Element: ${pin.targetSelector}`);
|
|
195
466
|
if (pin.targetText) lines.push(`Nearby text: "${pin.targetText}"`);
|
|
196
467
|
lines.push("");
|
|
197
|
-
lines.push(
|
|
468
|
+
lines.push((pin.draft || "").trim());
|
|
469
|
+
return lines;
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const sendPinsToAgent = (targetPins: CanvasPin[], batch = false) => {
|
|
473
|
+
const message = batch
|
|
474
|
+
? [
|
|
475
|
+
`[Comment batch on ${contextLabel || contextId}]`,
|
|
476
|
+
`Annotations: ${targetPins.length}`,
|
|
477
|
+
"",
|
|
478
|
+
...targetPins.flatMap((pin, index) => [
|
|
479
|
+
...buildPinLines(pin, index),
|
|
480
|
+
"",
|
|
481
|
+
]),
|
|
482
|
+
].join("\n")
|
|
483
|
+
: buildPinLines(targetPins[0]!).join("\n");
|
|
484
|
+
|
|
198
485
|
try {
|
|
199
486
|
// Use `sendToAgentChat` (not the shared `agentChat.submit`) so the
|
|
200
487
|
// request routes correctly when design is embedded in Builder/Frame
|
|
201
488
|
// and so the agent sidebar is reliably opened via the `agent-panel:open`
|
|
202
489
|
// custom event even if the user has it collapsed.
|
|
203
490
|
sendToAgentChat({
|
|
204
|
-
message
|
|
491
|
+
message,
|
|
205
492
|
submit: true,
|
|
206
493
|
openSidebar: true,
|
|
207
494
|
});
|
|
208
495
|
} catch (err) {
|
|
209
496
|
console.error("[CanvasCommentPins] failed to send to agent:", err);
|
|
210
497
|
}
|
|
211
|
-
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
const queuePin = (pin: CanvasPin) => {
|
|
501
|
+
const text = (pin.draft || "").trim();
|
|
502
|
+
if (!text) {
|
|
503
|
+
removePin(pin.id);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
updatePin(pin.id, { draft: text, queued: true });
|
|
507
|
+
setActivePinId(null);
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
const submitPin = (pin: CanvasPin) => {
|
|
511
|
+
const text = (pin.draft || "").trim();
|
|
512
|
+
if (!text) {
|
|
513
|
+
removePin(pin.id);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (submitMode === "queue") {
|
|
517
|
+
queuePin(pin);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const nextPin = { ...pin, draft: text };
|
|
521
|
+
sendPinsToAgent([nextPin]);
|
|
522
|
+
updatePin(pin.id, { draft: text, queued: false, submitted: true });
|
|
523
|
+
setActivePinId(null);
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
const submitQueuedPins = () => {
|
|
527
|
+
if (queuedPins.length === 0) return;
|
|
528
|
+
if (submitMode === "queue") return;
|
|
529
|
+
sendPinsToAgent(queuedPins, true);
|
|
530
|
+
const submittedIds = new Set(queuedPins.map((pin) => pin.id));
|
|
531
|
+
setPins((prev) =>
|
|
532
|
+
prev.map((pin) =>
|
|
533
|
+
submittedIds.has(pin.id)
|
|
534
|
+
? { ...pin, queued: false, submitted: true }
|
|
535
|
+
: pin,
|
|
536
|
+
),
|
|
537
|
+
);
|
|
212
538
|
setActivePinId(null);
|
|
213
539
|
};
|
|
214
540
|
|
|
@@ -218,6 +544,8 @@ export function CanvasCommentPins({
|
|
|
218
544
|
const canvas = containerRef.current ?? canvasEl;
|
|
219
545
|
if (!canvas) return null;
|
|
220
546
|
const rect = canvas.getBoundingClientRect();
|
|
547
|
+
const summaryLeft = Math.min(rect.right - 8, window.innerWidth - 8);
|
|
548
|
+
const summaryTop = Math.max(rect.top + 8, 72);
|
|
221
549
|
|
|
222
550
|
return (
|
|
223
551
|
<>
|
|
@@ -226,7 +554,10 @@ export function CanvasCommentPins({
|
|
|
226
554
|
{active && (
|
|
227
555
|
<div
|
|
228
556
|
data-pin-click-overlay
|
|
229
|
-
className=
|
|
557
|
+
className={cn(
|
|
558
|
+
"fixed cursor-crosshair",
|
|
559
|
+
clickPlaneUnderToolbar ? "z-[20]" : "z-[54]",
|
|
560
|
+
)}
|
|
230
561
|
style={{
|
|
231
562
|
left: rect.left,
|
|
232
563
|
top: rect.top,
|
|
@@ -261,12 +592,73 @@ export function CanvasCommentPins({
|
|
|
261
592
|
</div>
|
|
262
593
|
)}
|
|
263
594
|
|
|
595
|
+
{/* Compact queue/result summary for local annotation batching. */}
|
|
596
|
+
{pins.length > 0 && (
|
|
597
|
+
<div
|
|
598
|
+
data-pin-popover
|
|
599
|
+
className="fixed z-[56] w-64 -translate-x-full rounded-lg border border-border bg-popover p-3 shadow-xl"
|
|
600
|
+
style={{ left: summaryLeft, top: summaryTop }}
|
|
601
|
+
>
|
|
602
|
+
<div className="mb-2 flex items-center justify-between gap-2">
|
|
603
|
+
<div className="min-w-0">
|
|
604
|
+
<p className="truncate text-xs font-semibold text-foreground">
|
|
605
|
+
{t("visualEditor.annotationQueue")}
|
|
606
|
+
</p>
|
|
607
|
+
<p className="text-[10px] text-muted-foreground">
|
|
608
|
+
{t("visualEditor.annotationQueueCounts", {
|
|
609
|
+
queued: queuedPins.length,
|
|
610
|
+
sent: submittedCount,
|
|
611
|
+
})}
|
|
612
|
+
</p>
|
|
613
|
+
</div>
|
|
614
|
+
{submitMode === "direct" ? (
|
|
615
|
+
<Button
|
|
616
|
+
size="sm"
|
|
617
|
+
className="h-7 gap-1 px-2 text-[10px]"
|
|
618
|
+
onClick={submitQueuedPins}
|
|
619
|
+
disabled={queuedPins.length === 0}
|
|
620
|
+
>
|
|
621
|
+
<IconBolt className="size-3" />
|
|
622
|
+
{t("visualEditor.batchApply")}
|
|
623
|
+
</Button>
|
|
624
|
+
) : (
|
|
625
|
+
<span className="rounded-md bg-muted px-2 py-1 text-[10px] font-medium text-muted-foreground">
|
|
626
|
+
{t("visualEditor.queued")}
|
|
627
|
+
</span>
|
|
628
|
+
)}
|
|
629
|
+
</div>
|
|
630
|
+
<div className="grid grid-cols-2 gap-1 text-[10px]">
|
|
631
|
+
<span className="rounded-md bg-muted/45 px-2 py-1 text-muted-foreground">
|
|
632
|
+
{t("visualEditor.pinStatusCount.direct", {
|
|
633
|
+
count: statusCounts.deterministic,
|
|
634
|
+
})}
|
|
635
|
+
</span>
|
|
636
|
+
<span className="rounded-md bg-muted/45 px-2 py-1 text-muted-foreground">
|
|
637
|
+
{t("visualEditor.pinStatusCount.agent", {
|
|
638
|
+
count: statusCounts["needs-agent"],
|
|
639
|
+
})}
|
|
640
|
+
</span>
|
|
641
|
+
<span className="rounded-md bg-muted/45 px-2 py-1 text-muted-foreground">
|
|
642
|
+
{t("visualEditor.pinStatusCount.conflict", {
|
|
643
|
+
count: statusCounts.conflict,
|
|
644
|
+
})}
|
|
645
|
+
</span>
|
|
646
|
+
<span className="rounded-md bg-muted/45 px-2 py-1 text-muted-foreground">
|
|
647
|
+
{t("visualEditor.pinStatusCount.blocked", {
|
|
648
|
+
count: statusCounts.unsupported,
|
|
649
|
+
})}
|
|
650
|
+
</span>
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
)}
|
|
654
|
+
|
|
264
655
|
{/* Pin overlays */}
|
|
265
656
|
{pins.map((pin) => {
|
|
266
657
|
const left = rect.left + (pin.xPct / 100) * rect.width;
|
|
267
658
|
const top = rect.top + (pin.yPct / 100) * rect.height;
|
|
268
659
|
const isActive = activePinId === pin.id;
|
|
269
660
|
const PinIcon = pin.submitted ? IconMessageCheck : IconMessage;
|
|
661
|
+
const status = localizePinStatus(derivePinStatus(pin, pins), t);
|
|
270
662
|
return (
|
|
271
663
|
<div
|
|
272
664
|
key={pin.id}
|
|
@@ -288,23 +680,37 @@ export function CanvasCommentPins({
|
|
|
288
680
|
if (!pin.submitted) setActivePinId(pin.id);
|
|
289
681
|
}}
|
|
290
682
|
className={cn(
|
|
291
|
-
"absolute -translate-x-1/2 -translate-y-full -
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
: "bg-[#609FF8] text-black",
|
|
295
|
-
"hover:scale-110 transition-transform",
|
|
683
|
+
"absolute -mt-1 flex size-7 -translate-x-1/2 -translate-y-full cursor-pointer items-center justify-center rounded-full rounded-bl-none shadow-lg ring-2 transition-transform hover:scale-110",
|
|
684
|
+
status.markerClassName,
|
|
685
|
+
pin.submitted && "opacity-95",
|
|
296
686
|
)}
|
|
297
687
|
>
|
|
298
|
-
<PinIcon className="
|
|
688
|
+
<PinIcon className="size-3.5" />
|
|
299
689
|
</button>
|
|
300
690
|
</TooltipTrigger>
|
|
301
691
|
<TooltipContent className="pointer-events-none">
|
|
302
|
-
{pin.
|
|
303
|
-
(
|
|
304
|
-
|
|
305
|
-
|
|
692
|
+
{pin.queued
|
|
693
|
+
? t("visualEditor.queuedStatus", { status: status.label })
|
|
694
|
+
: pin.draft ||
|
|
695
|
+
(pin.submitted
|
|
696
|
+
? t("visualEditor.commentSentStatus", {
|
|
697
|
+
status: status.label,
|
|
698
|
+
})
|
|
699
|
+
: t("visualEditor.commentStatus", {
|
|
700
|
+
status: status.label,
|
|
701
|
+
}))}
|
|
306
702
|
</TooltipContent>
|
|
307
703
|
</Tooltip>
|
|
704
|
+
<span
|
|
705
|
+
className={cn(
|
|
706
|
+
"pointer-events-none absolute left-3 -top-10 rounded-full border px-1.5 py-0.5 text-[9px] font-medium leading-none shadow-sm",
|
|
707
|
+
status.badgeClassName,
|
|
708
|
+
)}
|
|
709
|
+
>
|
|
710
|
+
{pin.queued && !pin.submitted
|
|
711
|
+
? t("visualEditor.queued")
|
|
712
|
+
: status.shortLabel}
|
|
713
|
+
</span>
|
|
308
714
|
|
|
309
715
|
{/* Inline composer. z-[260] keeps it above the shadcn floating-UI
|
|
310
716
|
* tier (z-[250] — Tooltip, Popover, Dialog overlay, etc.) so a
|
|
@@ -314,13 +720,21 @@ export function CanvasCommentPins({
|
|
|
314
720
|
data-pin-popover
|
|
315
721
|
className="absolute z-[260] left-3 top-1 w-72 rounded-lg border border-border bg-popover shadow-xl p-2"
|
|
316
722
|
>
|
|
317
|
-
<
|
|
318
|
-
|
|
319
|
-
|
|
723
|
+
<div className="mb-2 flex items-center justify-between gap-2">
|
|
724
|
+
<p className="text-xs font-semibold text-foreground">
|
|
725
|
+
{t("visualEditor.editDesign")}
|
|
726
|
+
</p>
|
|
727
|
+
<PinStatusBadge status={status} />
|
|
728
|
+
</div>
|
|
320
729
|
<Textarea
|
|
321
730
|
autoFocus
|
|
322
731
|
value={pin.draft || ""}
|
|
323
|
-
onChange={(e) =>
|
|
732
|
+
onChange={(e) =>
|
|
733
|
+
updatePin(pin.id, {
|
|
734
|
+
draft: e.target.value,
|
|
735
|
+
queued: false,
|
|
736
|
+
})
|
|
737
|
+
}
|
|
324
738
|
onKeyDown={(e) => {
|
|
325
739
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
326
740
|
e.preventDefault();
|
|
@@ -334,15 +748,28 @@ export function CanvasCommentPins({
|
|
|
334
748
|
placeholder={t("visualEditor.tellAgentWhatToChange")}
|
|
335
749
|
className="resize-none text-xs min-h-[60px]"
|
|
336
750
|
/>
|
|
751
|
+
<p className="mt-1 text-[10px] leading-4 text-muted-foreground">
|
|
752
|
+
{status.detail}
|
|
753
|
+
</p>
|
|
754
|
+
{pin.targetAnchorId && (
|
|
755
|
+
<div className="mt-1 truncate rounded-md bg-muted/45 px-2 py-1 text-[10px] text-muted-foreground">
|
|
756
|
+
{t("visualEditor.anchorLabel", {
|
|
757
|
+
id: pin.targetAnchorId,
|
|
758
|
+
})}
|
|
759
|
+
</div>
|
|
760
|
+
)}
|
|
337
761
|
{pin.targetText && (
|
|
338
762
|
<div className="text-[10px] text-muted-foreground mt-1 italic line-clamp-1">
|
|
339
|
-
|
|
763
|
+
{t("visualEditor.nearText", { text: pin.targetText })}
|
|
340
764
|
</div>
|
|
341
765
|
)}
|
|
342
766
|
<div className="flex items-center justify-between mt-2">
|
|
343
767
|
<span className="text-[10px] text-muted-foreground">
|
|
344
|
-
{
|
|
345
|
-
|
|
768
|
+
{t("visualEditor.submitShortcut", {
|
|
769
|
+
mod: /Mac|iPhone|iPad/.test(navigator.userAgent)
|
|
770
|
+
? "⌘"
|
|
771
|
+
: "Ctrl",
|
|
772
|
+
})}
|
|
346
773
|
</span>
|
|
347
774
|
<div className="flex gap-1">
|
|
348
775
|
<Button
|
|
@@ -355,13 +782,24 @@ export function CanvasCommentPins({
|
|
|
355
782
|
</Button>
|
|
356
783
|
<Button
|
|
357
784
|
size="sm"
|
|
785
|
+
variant="outline"
|
|
358
786
|
className="h-6 gap-1 px-2 text-[10px] cursor-pointer"
|
|
359
|
-
onClick={() =>
|
|
787
|
+
onClick={() => queuePin(pin)}
|
|
360
788
|
disabled={!(pin.draft || "").trim()}
|
|
361
789
|
>
|
|
362
|
-
|
|
363
|
-
{t("visualEditor.send")}
|
|
790
|
+
{t("visualEditor.queue")}
|
|
364
791
|
</Button>
|
|
792
|
+
{submitMode === "direct" && (
|
|
793
|
+
<Button
|
|
794
|
+
size="sm"
|
|
795
|
+
className="h-6 gap-1 px-2 text-[10px] cursor-pointer"
|
|
796
|
+
onClick={() => submitPin(pin)}
|
|
797
|
+
disabled={!(pin.draft || "").trim()}
|
|
798
|
+
>
|
|
799
|
+
<IconSend className="w-3 h-3" />
|
|
800
|
+
{t("visualEditor.send")}
|
|
801
|
+
</Button>
|
|
802
|
+
)}
|
|
365
803
|
</div>
|
|
366
804
|
</div>
|
|
367
805
|
</div>
|