@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
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.80.0",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
"./embedding/react": "./dist/embedding/react.js",
|
|
90
90
|
"./onboarding": "./dist/onboarding/index.js",
|
|
91
91
|
"./shared": "./dist/shared/index.js",
|
|
92
|
+
"./voice": "./dist/voice/index.js",
|
|
92
93
|
"./scripts": "./dist/scripts/index.js",
|
|
93
94
|
"./application-state": "./dist/application-state/index.js",
|
|
94
95
|
"./settings": "./dist/settings/index.js",
|
|
@@ -412,6 +412,46 @@ export async function isStoredEngineUsableForRequest(
|
|
|
412
412
|
return true;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
/**
|
|
416
|
+
* Request-aware credential preflight for an already-resolved engine instance.
|
|
417
|
+
* `resolveEngine()` may still return a default or explicitly requested engine
|
|
418
|
+
* object before credentials are actually usable; call this before starting a
|
|
419
|
+
* user-visible run so missing providers fail immediately.
|
|
420
|
+
*/
|
|
421
|
+
export async function isResolvedEngineUsableForRequest(
|
|
422
|
+
engine: AgentEngine,
|
|
423
|
+
options: { apiKey?: string } = {},
|
|
424
|
+
): Promise<boolean> {
|
|
425
|
+
const entry = _registry.get(engine.name);
|
|
426
|
+
// Custom engines may have their own credential contract outside the core
|
|
427
|
+
// registry metadata, so do not block them speculatively.
|
|
428
|
+
if (!entry) return true;
|
|
429
|
+
if (!isAgentEnginePackageInstalled(entry)) return false;
|
|
430
|
+
if (entry.requiredEnvVars.length === 0) return true;
|
|
431
|
+
|
|
432
|
+
if (entry.name === "builder") {
|
|
433
|
+
const creds = await resolveBuilderCredentials();
|
|
434
|
+
return Boolean(creds.privateKey && creds.publicKey);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (options.apiKey?.trim()) return true;
|
|
438
|
+
|
|
439
|
+
for (const key of entry.requiredEnvVars) {
|
|
440
|
+
try {
|
|
441
|
+
if (await resolveSecret(key)) continue;
|
|
442
|
+
} catch {
|
|
443
|
+
// Fall through to deployment-level fallback when allowed.
|
|
444
|
+
}
|
|
445
|
+
if (
|
|
446
|
+
!canUseDeployCredentialFallbackForRequest() ||
|
|
447
|
+
!readDeployCredentialEnv(key)
|
|
448
|
+
) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
|
|
415
455
|
export interface ResolveEngineConfig {
|
|
416
456
|
/** Explicit engine name or instance from createAgentChatPlugin options */
|
|
417
457
|
engineOption?:
|
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
registerBuiltinEngines,
|
|
68
68
|
getStoredModelForEngine,
|
|
69
69
|
normalizeModelForEngine,
|
|
70
|
+
isResolvedEngineUsableForRequest,
|
|
70
71
|
} from "./engine/index.js";
|
|
71
72
|
import { resolveMaxOutputTokensForEngine } from "./engine/output-tokens.js";
|
|
72
73
|
import { PROVIDER_TO_ENV } from "./engine/provider-env-vars.js";
|
|
@@ -4206,8 +4207,11 @@ export function createProductionAgentHandler(
|
|
|
4206
4207
|
`[agent-chat] resolved engine=${engine.name} model=${model} requestEngine=${requestEngine ?? "(none)"}`,
|
|
4207
4208
|
);
|
|
4208
4209
|
|
|
4209
|
-
|
|
4210
|
-
|
|
4210
|
+
if (
|
|
4211
|
+
!(await isResolvedEngineUsableForRequest(engine, {
|
|
4212
|
+
apiKey: effectiveApiKey,
|
|
4213
|
+
}))
|
|
4214
|
+
) {
|
|
4211
4215
|
setResponseHeader(event, "Content-Type", "text/event-stream");
|
|
4212
4216
|
setResponseHeader(event, "Cache-Control", "no-cache");
|
|
4213
4217
|
setResponseHeader(event, "Connection", "keep-alive");
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import fsSync from "node:fs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import http, {
|
|
4
|
+
type IncomingMessage,
|
|
5
|
+
type Server,
|
|
6
|
+
type ServerResponse,
|
|
7
|
+
} from "node:http";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
|
|
10
|
+
const DEFAULT_BRIDGE_PORT = 7331;
|
|
11
|
+
const ROUTE_MANIFEST_FILE = path.join(".agent-native", "design-routes.json");
|
|
12
|
+
const DEFAULT_DEV_SERVER_CANDIDATES = [
|
|
13
|
+
"http://127.0.0.1:5173",
|
|
14
|
+
"http://localhost:5173",
|
|
15
|
+
"http://127.0.0.1:3000",
|
|
16
|
+
"http://localhost:3000",
|
|
17
|
+
"http://127.0.0.1:8080",
|
|
18
|
+
"http://localhost:8080",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const BRIDGE_OPERATIONS = [
|
|
22
|
+
"select",
|
|
23
|
+
"resolveNodeToFile",
|
|
24
|
+
"readFile",
|
|
25
|
+
"applyEdit",
|
|
26
|
+
"writeFile",
|
|
27
|
+
"captureSnapshot",
|
|
28
|
+
"captureState",
|
|
29
|
+
] as const;
|
|
30
|
+
|
|
31
|
+
type BridgeOperation = (typeof BRIDGE_OPERATIONS)[number];
|
|
32
|
+
|
|
33
|
+
export interface DesignConnectArgs {
|
|
34
|
+
url?: string;
|
|
35
|
+
port: number;
|
|
36
|
+
root: string;
|
|
37
|
+
routeManifest?: string;
|
|
38
|
+
json: boolean;
|
|
39
|
+
once: boolean;
|
|
40
|
+
dryRun: boolean;
|
|
41
|
+
help: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface DesignConnectRoute {
|
|
45
|
+
id: string;
|
|
46
|
+
path: string;
|
|
47
|
+
title: string;
|
|
48
|
+
sourceFile?: string;
|
|
49
|
+
sourceKind: "react-router" | "html" | "manual";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface DesignConnectManifest {
|
|
53
|
+
version: 1;
|
|
54
|
+
source: "agent-native-design-connect";
|
|
55
|
+
sourceType: "localhost";
|
|
56
|
+
localOnly: true;
|
|
57
|
+
devServerUrl: string;
|
|
58
|
+
bridgeUrl: string;
|
|
59
|
+
rootPath: string;
|
|
60
|
+
routeManifestPath: string;
|
|
61
|
+
routeManifestCreated: boolean;
|
|
62
|
+
routes: DesignConnectRoute[];
|
|
63
|
+
routeCount: number;
|
|
64
|
+
generatedAt: string;
|
|
65
|
+
capabilities: Array<{
|
|
66
|
+
operation: BridgeOperation;
|
|
67
|
+
status: "available" | "planned" | "disabled";
|
|
68
|
+
reason?: string;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface DesignConnectBridge {
|
|
73
|
+
server: Server;
|
|
74
|
+
manifest: DesignConnectManifest;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function stringFlagValue(argv: string[], index: number, flag: string) {
|
|
78
|
+
const value = argv[index + 1];
|
|
79
|
+
if (!value || value.startsWith("-")) {
|
|
80
|
+
throw new Error(`${flag} requires a value`);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function normalizeSlash(value: string) {
|
|
86
|
+
return value.replace(/\\/g, "/");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function normalizeHttpUrl(value: string): string {
|
|
90
|
+
const raw = value.trim();
|
|
91
|
+
const withProtocol = /^[a-z]+:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
92
|
+
const parsed = new URL(withProtocol);
|
|
93
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
94
|
+
throw new Error("--url must be an http(s) URL");
|
|
95
|
+
}
|
|
96
|
+
parsed.hash = "";
|
|
97
|
+
return parsed.toString().replace(/\/$/, "");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function parseDesignConnectArgs(argv: string[]): DesignConnectArgs {
|
|
101
|
+
const args = argv[0] === "connect" ? argv.slice(1) : argv;
|
|
102
|
+
const parsed: DesignConnectArgs = {
|
|
103
|
+
port: DEFAULT_BRIDGE_PORT,
|
|
104
|
+
root: process.cwd(),
|
|
105
|
+
json: false,
|
|
106
|
+
once: false,
|
|
107
|
+
dryRun: false,
|
|
108
|
+
help: false,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
112
|
+
const arg = args[index]!;
|
|
113
|
+
if (arg === "help" || arg === "--help" || arg === "-h") {
|
|
114
|
+
parsed.help = true;
|
|
115
|
+
} else if (arg === "--url") {
|
|
116
|
+
parsed.url = stringFlagValue(args, index, arg);
|
|
117
|
+
index += 1;
|
|
118
|
+
} else if (arg.startsWith("--url=")) {
|
|
119
|
+
parsed.url = arg.slice("--url=".length);
|
|
120
|
+
} else if (arg === "--port") {
|
|
121
|
+
parsed.port = Number.parseInt(stringFlagValue(args, index, arg), 10);
|
|
122
|
+
index += 1;
|
|
123
|
+
} else if (arg.startsWith("--port=")) {
|
|
124
|
+
parsed.port = Number.parseInt(arg.slice("--port=".length), 10);
|
|
125
|
+
} else if (arg === "--root") {
|
|
126
|
+
parsed.root = stringFlagValue(args, index, arg);
|
|
127
|
+
index += 1;
|
|
128
|
+
} else if (arg.startsWith("--root=")) {
|
|
129
|
+
parsed.root = arg.slice("--root=".length);
|
|
130
|
+
} else if (arg === "--route-manifest") {
|
|
131
|
+
parsed.routeManifest = stringFlagValue(args, index, arg);
|
|
132
|
+
index += 1;
|
|
133
|
+
} else if (arg.startsWith("--route-manifest=")) {
|
|
134
|
+
parsed.routeManifest = arg.slice("--route-manifest=".length);
|
|
135
|
+
} else if (arg === "--json") {
|
|
136
|
+
parsed.json = true;
|
|
137
|
+
parsed.once = true;
|
|
138
|
+
} else if (arg === "--once") {
|
|
139
|
+
parsed.once = true;
|
|
140
|
+
} else if (arg === "--dry-run") {
|
|
141
|
+
parsed.dryRun = true;
|
|
142
|
+
parsed.once = true;
|
|
143
|
+
} else if (arg.startsWith("-")) {
|
|
144
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!Number.isInteger(parsed.port) || parsed.port <= 0) {
|
|
151
|
+
throw new Error("--port must be a positive integer");
|
|
152
|
+
}
|
|
153
|
+
parsed.root = path.resolve(parsed.root);
|
|
154
|
+
parsed.url = parsed.url ? normalizeHttpUrl(parsed.url) : undefined;
|
|
155
|
+
return parsed;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function routeId(routePath: string): string {
|
|
159
|
+
if (routePath === "/") return "route-root";
|
|
160
|
+
const slug = routePath
|
|
161
|
+
.replace(/^\/+/, "")
|
|
162
|
+
.replace(/[^a-zA-Z0-9]+/g, "-")
|
|
163
|
+
.replace(/^-+|-+$/g, "")
|
|
164
|
+
.toLowerCase();
|
|
165
|
+
return slug ? `route-${slug}` : "route-wildcard";
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function titleFromRoutePath(routePath: string): string {
|
|
169
|
+
if (routePath === "/") return "Home";
|
|
170
|
+
if (routePath === "/*" || routePath === "*") return "Wildcard";
|
|
171
|
+
return (
|
|
172
|
+
routePath
|
|
173
|
+
.replace(/^\/+/, "")
|
|
174
|
+
.replace(/[:$]/g, "")
|
|
175
|
+
.replace(/[-_/]+/g, " ")
|
|
176
|
+
.replace(/\s+/g, " ")
|
|
177
|
+
.trim()
|
|
178
|
+
.replace(/\b\w/g, (char) => char.toUpperCase()) || "Screen"
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function walkFiles(dir: string, files: string[] = []): string[] {
|
|
183
|
+
if (!fsSync.existsSync(dir)) return files;
|
|
184
|
+
for (const entry of fsSync.readdirSync(dir, { withFileTypes: true })) {
|
|
185
|
+
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
186
|
+
const absolute = path.join(dir, entry.name);
|
|
187
|
+
if (entry.isDirectory()) {
|
|
188
|
+
walkFiles(absolute, files);
|
|
189
|
+
} else {
|
|
190
|
+
files.push(absolute);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return files;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function routePathFromReactRouterFile(filePath: string, routesDir: string) {
|
|
197
|
+
const withoutExt = normalizeSlash(path.relative(routesDir, filePath)).replace(
|
|
198
|
+
/\.[cm]?[jt]sx?$/,
|
|
199
|
+
"",
|
|
200
|
+
);
|
|
201
|
+
const parts: string[] = [];
|
|
202
|
+
for (const segment of withoutExt.split("/")) {
|
|
203
|
+
for (const token of segment.split(".")) {
|
|
204
|
+
if (!token || token === "route" || token === "index") continue;
|
|
205
|
+
if (token === "_index") continue;
|
|
206
|
+
if (token.startsWith("_")) continue;
|
|
207
|
+
const pathToken = token.endsWith("_") ? token.slice(0, -1) : token;
|
|
208
|
+
if (pathToken === "$") {
|
|
209
|
+
parts.push("*");
|
|
210
|
+
} else if (pathToken.startsWith("$")) {
|
|
211
|
+
const param = pathToken.slice(1) || "param";
|
|
212
|
+
parts.push(`:${param}`);
|
|
213
|
+
} else {
|
|
214
|
+
parts.push(pathToken);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return `/${parts.join("/")}`.replace(/\/+/g, "/");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function discoverDesignRoutes(root: string): DesignConnectRoute[] {
|
|
222
|
+
const absoluteRoot = path.resolve(root);
|
|
223
|
+
const routeDirs = [
|
|
224
|
+
path.join(absoluteRoot, "app", "routes"),
|
|
225
|
+
path.join(absoluteRoot, "src", "routes"),
|
|
226
|
+
path.join(absoluteRoot, "pages"),
|
|
227
|
+
].filter((dir) => fsSync.existsSync(dir));
|
|
228
|
+
const routes = new Map<string, DesignConnectRoute>();
|
|
229
|
+
|
|
230
|
+
for (const routeDir of routeDirs) {
|
|
231
|
+
for (const file of walkFiles(routeDir)) {
|
|
232
|
+
if (!/\.[cm]?[jt]sx?$/.test(file)) continue;
|
|
233
|
+
if (/\.test\.|\.spec\./.test(file)) continue;
|
|
234
|
+
const pathName = routePathFromReactRouterFile(file, routeDir);
|
|
235
|
+
routes.set(pathName, {
|
|
236
|
+
id: routeId(pathName),
|
|
237
|
+
path: pathName,
|
|
238
|
+
title: titleFromRoutePath(pathName),
|
|
239
|
+
sourceFile: normalizeSlash(path.relative(absoluteRoot, file)),
|
|
240
|
+
sourceKind: "react-router",
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (routes.size === 0) {
|
|
246
|
+
for (const dir of [absoluteRoot, path.join(absoluteRoot, "public")]) {
|
|
247
|
+
for (const file of walkFiles(dir)) {
|
|
248
|
+
if (!file.endsWith(".html")) continue;
|
|
249
|
+
const rel = normalizeSlash(path.relative(dir, file));
|
|
250
|
+
const pathName =
|
|
251
|
+
rel === "index.html" ? "/" : `/${rel.replace(/\.html$/, "")}`;
|
|
252
|
+
routes.set(pathName, {
|
|
253
|
+
id: routeId(pathName),
|
|
254
|
+
path: pathName,
|
|
255
|
+
title: titleFromRoutePath(pathName),
|
|
256
|
+
sourceFile: normalizeSlash(path.relative(absoluteRoot, file)),
|
|
257
|
+
sourceKind: "html",
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return [...routes.values()].sort((a, b) => {
|
|
264
|
+
if (a.path === "/") return -1;
|
|
265
|
+
if (b.path === "/") return 1;
|
|
266
|
+
return a.path.localeCompare(b.path);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function probeDevServer(url: string): Promise<boolean> {
|
|
271
|
+
const controller = new AbortController();
|
|
272
|
+
const timeout = setTimeout(() => controller.abort(), 800);
|
|
273
|
+
try {
|
|
274
|
+
const response = await fetch(url, {
|
|
275
|
+
method: "GET",
|
|
276
|
+
signal: controller.signal,
|
|
277
|
+
});
|
|
278
|
+
return response.status < 500;
|
|
279
|
+
} catch {
|
|
280
|
+
return false;
|
|
281
|
+
} finally {
|
|
282
|
+
clearTimeout(timeout);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function resolveDevServerUrl(url?: string): Promise<string> {
|
|
287
|
+
if (url) return normalizeHttpUrl(url);
|
|
288
|
+
for (const candidate of DEFAULT_DEV_SERVER_CANDIDATES) {
|
|
289
|
+
if (await probeDevServer(candidate)) return candidate;
|
|
290
|
+
}
|
|
291
|
+
return DEFAULT_DEV_SERVER_CANDIDATES[0]!;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function ensureRouteManifest(options: {
|
|
295
|
+
root: string;
|
|
296
|
+
routeManifestPath: string;
|
|
297
|
+
routes: DesignConnectRoute[];
|
|
298
|
+
devServerUrl: string;
|
|
299
|
+
dryRun: boolean;
|
|
300
|
+
}): Promise<{ path: string; created: boolean }> {
|
|
301
|
+
const manifestPath = path.isAbsolute(options.routeManifestPath)
|
|
302
|
+
? options.routeManifestPath
|
|
303
|
+
: path.join(options.root, options.routeManifestPath);
|
|
304
|
+
if (fsSync.existsSync(manifestPath)) {
|
|
305
|
+
return { path: manifestPath, created: false };
|
|
306
|
+
}
|
|
307
|
+
if (!options.dryRun) {
|
|
308
|
+
await fs.mkdir(path.dirname(manifestPath), { recursive: true });
|
|
309
|
+
await fs.writeFile(
|
|
310
|
+
manifestPath,
|
|
311
|
+
`${JSON.stringify(
|
|
312
|
+
{
|
|
313
|
+
version: 1,
|
|
314
|
+
sourceType: "localhost",
|
|
315
|
+
devServerUrl: options.devServerUrl,
|
|
316
|
+
rootPath: options.root,
|
|
317
|
+
routes: options.routes,
|
|
318
|
+
generatedAt: new Date().toISOString(),
|
|
319
|
+
},
|
|
320
|
+
null,
|
|
321
|
+
2,
|
|
322
|
+
)}\n`,
|
|
323
|
+
"utf8",
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return { path: manifestPath, created: !options.dryRun };
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export async function prepareDesignConnectManifest(
|
|
330
|
+
options: Partial<DesignConnectArgs> & { root?: string } = {},
|
|
331
|
+
): Promise<DesignConnectManifest> {
|
|
332
|
+
const root = path.resolve(options.root ?? process.cwd());
|
|
333
|
+
const port = options.port ?? DEFAULT_BRIDGE_PORT;
|
|
334
|
+
const devServerUrl = await resolveDevServerUrl(options.url);
|
|
335
|
+
const bridgeUrl = `http://127.0.0.1:${port}`;
|
|
336
|
+
const routes = discoverDesignRoutes(root);
|
|
337
|
+
const routeManifest = await ensureRouteManifest({
|
|
338
|
+
root,
|
|
339
|
+
routeManifestPath: options.routeManifest ?? ROUTE_MANIFEST_FILE,
|
|
340
|
+
routes,
|
|
341
|
+
devServerUrl,
|
|
342
|
+
dryRun: Boolean(options.dryRun),
|
|
343
|
+
});
|
|
344
|
+
const generatedAt = new Date().toISOString();
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
version: 1,
|
|
348
|
+
source: "agent-native-design-connect",
|
|
349
|
+
sourceType: "localhost",
|
|
350
|
+
localOnly: true,
|
|
351
|
+
devServerUrl,
|
|
352
|
+
bridgeUrl,
|
|
353
|
+
rootPath: root,
|
|
354
|
+
routeManifestPath: routeManifest.path,
|
|
355
|
+
routeManifestCreated: routeManifest.created,
|
|
356
|
+
routes,
|
|
357
|
+
routeCount: routes.length,
|
|
358
|
+
generatedAt,
|
|
359
|
+
capabilities: BRIDGE_OPERATIONS.map((operation) => ({
|
|
360
|
+
operation,
|
|
361
|
+
status:
|
|
362
|
+
operation === "readFile" ||
|
|
363
|
+
operation === "applyEdit" ||
|
|
364
|
+
operation === "writeFile"
|
|
365
|
+
? "planned"
|
|
366
|
+
: "available",
|
|
367
|
+
reason:
|
|
368
|
+
operation === "writeFile"
|
|
369
|
+
? "The bridge advertises the contract before enabling local file writes."
|
|
370
|
+
: undefined,
|
|
371
|
+
})),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function sendJson(
|
|
376
|
+
res: ServerResponse,
|
|
377
|
+
statusCode: number,
|
|
378
|
+
body: Record<string, unknown>,
|
|
379
|
+
) {
|
|
380
|
+
res.writeHead(statusCode, {
|
|
381
|
+
"content-type": "application/json; charset=utf-8",
|
|
382
|
+
"access-control-allow-origin": "*",
|
|
383
|
+
"access-control-allow-methods": "GET, OPTIONS",
|
|
384
|
+
"access-control-allow-headers": "content-type",
|
|
385
|
+
"access-control-allow-private-network": "true",
|
|
386
|
+
});
|
|
387
|
+
res.end(`${JSON.stringify(body, null, 2)}\n`);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export async function startDesignConnectBridge(
|
|
391
|
+
manifest: DesignConnectManifest,
|
|
392
|
+
): Promise<DesignConnectBridge> {
|
|
393
|
+
const server = http.createServer(
|
|
394
|
+
(req: IncomingMessage, res: ServerResponse) => {
|
|
395
|
+
if (req.method === "OPTIONS") {
|
|
396
|
+
sendJson(res, 204, {});
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const pathname = new URL(req.url ?? "/", manifest.bridgeUrl).pathname;
|
|
400
|
+
if (pathname === "/" || pathname === "/manifest.json") {
|
|
401
|
+
sendJson(res, 200, manifest as unknown as Record<string, unknown>);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (pathname === "/routes.json") {
|
|
405
|
+
sendJson(res, 200, {
|
|
406
|
+
version: 1,
|
|
407
|
+
sourceType: "localhost",
|
|
408
|
+
devServerUrl: manifest.devServerUrl,
|
|
409
|
+
rootPath: manifest.rootPath,
|
|
410
|
+
routes: manifest.routes,
|
|
411
|
+
generatedAt: manifest.generatedAt,
|
|
412
|
+
});
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (pathname === "/health") {
|
|
416
|
+
sendJson(res, 200, { ok: true, source: manifest.source });
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
sendJson(res, 404, { ok: false, error: "not found" });
|
|
420
|
+
},
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
await new Promise<void>((resolve, reject) => {
|
|
424
|
+
server.once("error", reject);
|
|
425
|
+
server.listen(new URL(manifest.bridgeUrl).port, "127.0.0.1", () => {
|
|
426
|
+
server.off("error", reject);
|
|
427
|
+
resolve();
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
return { server, manifest };
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function printHelp() {
|
|
435
|
+
console.log(`Usage:
|
|
436
|
+
agent-native design connect [options]
|
|
437
|
+
|
|
438
|
+
Options:
|
|
439
|
+
--url <url> Dev server URL to inspect (auto-detected if omitted)
|
|
440
|
+
--port <number> Local bridge port (default ${DEFAULT_BRIDGE_PORT})
|
|
441
|
+
--root <path> App/repo root for route discovery (default cwd)
|
|
442
|
+
--route-manifest <path> Non-destructive route manifest output path
|
|
443
|
+
--json Print the manifest JSON and exit
|
|
444
|
+
--once Prepare/scaffold the manifest and exit
|
|
445
|
+
--dry-run Print what would be exposed without writing files`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export async function runDesign(argv: string[]) {
|
|
449
|
+
const subcommand = argv[0];
|
|
450
|
+
if (subcommand !== "connect") {
|
|
451
|
+
if (
|
|
452
|
+
subcommand === "help" ||
|
|
453
|
+
subcommand === "--help" ||
|
|
454
|
+
subcommand === "-h"
|
|
455
|
+
) {
|
|
456
|
+
printHelp();
|
|
457
|
+
return 0;
|
|
458
|
+
}
|
|
459
|
+
console.error("Usage: agent-native design connect [options]");
|
|
460
|
+
return 1;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const parsed = parseDesignConnectArgs(argv);
|
|
464
|
+
if (parsed.help) {
|
|
465
|
+
printHelp();
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const manifest = await prepareDesignConnectManifest(parsed);
|
|
470
|
+
if (parsed.json || parsed.once || parsed.dryRun) {
|
|
471
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
472
|
+
return 0;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const bridge = await startDesignConnectBridge(manifest);
|
|
476
|
+
console.error("Design localhost bridge running");
|
|
477
|
+
console.error(`Bridge: ${manifest.bridgeUrl}`);
|
|
478
|
+
console.error(`Manifest: ${manifest.bridgeUrl}/manifest.json`);
|
|
479
|
+
console.error(`Routes: ${manifest.routeCount}`);
|
|
480
|
+
console.error(`Dev URL: ${manifest.devServerUrl}`);
|
|
481
|
+
|
|
482
|
+
return await new Promise<number>((resolve) => {
|
|
483
|
+
const stop = () => {
|
|
484
|
+
bridge.server.close(() => resolve(0));
|
|
485
|
+
};
|
|
486
|
+
for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"] as const) {
|
|
487
|
+
process.once(signal, stop);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
@@ -737,6 +737,19 @@ switch (command) {
|
|
|
737
737
|
break;
|
|
738
738
|
}
|
|
739
739
|
|
|
740
|
+
case "design": {
|
|
741
|
+
import("./design-connect.js")
|
|
742
|
+
.then(async (m) => {
|
|
743
|
+
const code = await m.runDesign(args);
|
|
744
|
+
process.exit(code);
|
|
745
|
+
})
|
|
746
|
+
.catch((err) => {
|
|
747
|
+
console.error(err?.message ?? err);
|
|
748
|
+
process.exit(1);
|
|
749
|
+
});
|
|
750
|
+
break;
|
|
751
|
+
}
|
|
752
|
+
|
|
740
753
|
case "recap": {
|
|
741
754
|
// PR visual recap helpers used by the GitHub Action. Promoted to the CLI
|
|
742
755
|
// so an installed repo's workflow can call `agent-native recap …` instead
|
|
@@ -925,6 +938,9 @@ Usage:
|
|
|
925
938
|
Launch Content in local-file mode for a local
|
|
926
939
|
docs/content folder. Use --no-open, --port N,
|
|
927
940
|
or --profile docs/no-bookkeeping as needed.
|
|
941
|
+
agent-native design connect Start a localhost Design bridge for a running
|
|
942
|
+
dev server. Use --url, --port, --root, or
|
|
943
|
+
--json to print the route/source manifest.
|
|
928
944
|
agent-native recap <cmd> PR visual recap setup and GitHub Action helpers.
|
|
929
945
|
Run 'agent-native recap help' for subcommands.
|
|
930
946
|
agent-native plan <cmd> Plan helpers for block catalogs and local files.
|