@agent-native/core 0.169.1 → 0.170.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +4 -1
- package/bin/agent-native.js +23 -5
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- package/corpus/templates/analytics/app/routes/$.tsx +10 -0
- package/corpus/templates/analytics/app/routes.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
- package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
- package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
- package/corpus/templates/analytics/server/lib/slack.ts +4 -2
- package/corpus/templates/analytics/vitest.config.ts +6 -1
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/assets/app/routes/library.tsx +5 -3
- package/corpus/templates/assets/app/routes.ts +3 -1
- package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
- package/corpus/templates/assets/vitest.config.ts +6 -1
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/brain/app/routes/sources.tsx +8 -3
- package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
- package/corpus/templates/brain/vitest.config.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
- package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
- package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
- package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
- package/corpus/templates/calendar/app/routes.ts +3 -1
- package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
- package/corpus/templates/calendar/server/onboarding.ts +85 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/calendar/shared/api.ts +9 -1
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/chat/app/routes.ts +3 -1
- package/corpus/templates/chat/vitest.config.ts +8 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/clips/actions/get-meeting.ts +9 -4
- package/corpus/templates/clips/actions/list-recordings.ts +16 -3
- package/corpus/templates/clips/actions/search-meetings.ts +1 -0
- package/corpus/templates/clips/actions/view-screen.ts +8 -1
- package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
- package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
- package/corpus/templates/clips/desktop/src/app.tsx +53 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
- package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
- package/corpus/templates/clips/server/lib/emails.ts +17 -33
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
- package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
- package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
- package/corpus/templates/content/app/i18n-data.ts +25 -0
- package/corpus/templates/content/app/routes.ts +3 -1
- package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
- package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
- package/corpus/templates/content/vitest.config.ts +7 -1
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
- package/corpus/templates/design/actions/generate-design.ts +98 -47
- package/corpus/templates/design/actions/get-design-system.ts +6 -1
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
- package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
- package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
- package/corpus/templates/design/app/pages/Index.tsx +2 -0
- package/corpus/templates/design/app/pages/Templates.tsx +0 -10
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
- package/corpus/templates/design/app/routes.ts +3 -1
- package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
- package/corpus/templates/design/shared/canvas-math.ts +612 -206
- package/corpus/templates/design/shared/pen-path.ts +37 -0
- package/corpus/templates/design/vitest.config.ts +7 -1
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
- package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
- package/corpus/templates/dispatch/app/routes.ts +3 -1
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/factory/.env.example +2 -7
- package/corpus/templates/factory/AGENTS.md +3 -0
- package/corpus/templates/factory/README.md +5 -3
- package/corpus/templates/factory/actions/create-factory.ts +16 -3
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
- package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
- package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
- package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
- package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
- package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
- package/corpus/templates/factory/app/routes/factory.tsx +84 -11
- package/corpus/templates/factory/app/routes.ts +3 -1
- package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
- package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
- package/corpus/templates/factory/vitest.config.ts +17 -2
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
- package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
- package/corpus/templates/forms/vitest.config.ts +1 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/macros/app/routes.ts +3 -1
- package/corpus/templates/macros/vitest.config.ts +6 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
- package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
- package/corpus/templates/mail/app/routes/$.tsx +9 -0
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
- package/corpus/templates/mail/app/routes/$view.tsx +47 -1
- package/corpus/templates/mail/app/routes.ts +3 -1
- package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
- package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
- package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
- package/corpus/templates/mail/server/onboarding.ts +66 -18
- package/corpus/templates/mail/vitest.config.ts +6 -1
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/plan/app/routes/settings.tsx +4 -1
- package/corpus/templates/plan/app/routes.ts +3 -1
- package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/plan/netlify.toml +1 -1
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/slides/actions/patch-deck.ts +79 -10
- package/corpus/templates/slides/actions/update-slide.ts +11 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
- package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/slides/app/routes.ts +3 -1
- package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
- package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/slides/tsconfig.json +5 -0
- package/corpus/templates/slides/vitest.config.ts +6 -1
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
- package/corpus/templates/tasks/app/routes.ts +3 -1
- package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/tasks/vitest.config.ts +7 -1
- package/dist/action.d.ts +91 -0
- package/dist/action.js +50 -0
- package/dist/agent/abort-reasons.d.ts +38 -0
- package/dist/agent/abort-reasons.js +49 -0
- package/dist/agent/engine/ai-sdk-engine.js +8 -5
- package/dist/agent/engine/anthropic-engine.js +7 -5
- package/dist/agent/engine/first-event-timeout.d.ts +42 -17
- package/dist/agent/engine/first-event-timeout.js +67 -25
- package/dist/agent/production-agent.d.ts +23 -0
- package/dist/agent/production-agent.js +107 -102
- package/dist/agent/run-loop-with-resume.d.ts +2 -28
- package/dist/agent/run-loop-with-resume.js +25 -40
- package/dist/agent/run-manager.js +5 -4
- package/dist/agent/run-store.d.ts +55 -0
- package/dist/agent/run-store.js +124 -1
- package/dist/agent/tool-search.js +2 -1
- package/dist/agent/types.d.ts +9 -4
- package/dist/app-config/configuration-error.d.ts +11 -0
- package/dist/app-config/configuration-error.js +14 -0
- package/dist/app-config/index.d.ts +1 -0
- package/dist/app-config/index.js +1 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +10 -0
- package/dist/app-config/plugins.d.ts +34 -0
- package/dist/app-config/plugins.js +39 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
- package/dist/app-config/run-lifecycle-invariants.js +18 -25
- package/dist/app-config/schema.d.ts +16 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/chat-threads/schema-migrations.js +20 -0
- package/dist/chat-threads/store.js +21 -4
- package/dist/cli/native-dependencies.d.ts +4 -0
- package/dist/cli/native-dependencies.js +15 -0
- package/dist/client/EnvironmentBadge.d.ts +1 -1
- package/dist/client/EnvironmentBadge.js +40 -5
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -14
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +2 -1
- package/dist/client/agent-page/use-jobs.js +3 -5
- package/dist/client/agent-sidebar-state.js +3 -1
- package/dist/client/blocks/library/code-tabs.js +5 -0
- package/dist/client/blocks/library/code.js +1 -0
- package/dist/client/chat-first/apps-rail.js +2 -2
- package/dist/client/chat-model-groups.d.ts +12 -0
- package/dist/client/chat-model-groups.js +3 -2
- package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
- package/dist/client/integrations/GoogleProductLogo.js +45 -0
- package/dist/client/integrations/index.d.ts +2 -0
- package/dist/client/integrations/index.js +2 -0
- package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
- package/dist/client/integrations/workspace-provider-oauth.js +13 -0
- package/dist/client/resources/mcp-integration-catalog.js +0 -29
- package/dist/client/settings/SettingsTabsPage.js +10 -6
- package/dist/client/sharing/ShareButton.js +11 -2
- package/dist/client/use-chat-models.d.ts +6 -0
- package/dist/client/use-chat-models.js +10 -0
- package/dist/client/use-db-sync.js +27 -9
- package/dist/connections/catalog.d.ts +111 -9
- package/dist/connections/catalog.js +86 -30
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/ddl-guard.d.ts +0 -4
- package/dist/db/ddl-guard.js +46 -0
- package/dist/deploy/build.d.ts +19 -0
- package/dist/deploy/build.js +190 -16
- package/dist/deploy/function-bundle.d.ts +45 -0
- package/dist/deploy/function-bundle.js +337 -0
- package/dist/deploy/workspace-deploy.js +19 -1
- package/dist/eject/workspace-connections.js +4 -0
- package/dist/email-catalog/registry.d.ts +4 -0
- package/dist/email-catalog/registry.js +79 -14
- package/dist/extensions/content-patch.js +14 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/plugin.d.ts +10 -0
- package/dist/integrations/plugin.js +40 -6
- package/dist/jobs/actions/run-automation-now.d.ts +2 -1
- package/dist/jobs/actions/run-automation-now.js +11 -5
- package/dist/jobs/frontmatter.js +53 -2
- package/dist/jobs/run-now.d.ts +11 -1
- package/dist/jobs/run-now.js +42 -7
- package/dist/jobs/scheduler.d.ts +1 -0
- package/dist/jobs/scheduler.js +2 -1
- package/dist/localization/core-messages/ar-SA.js +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts +2 -5
- package/dist/localization/default-messages.js +2 -5
- package/dist/mcp/build-server.d.ts +9 -0
- package/dist/mcp/build-server.js +37 -8
- package/dist/mcp-client/oauth-client.d.ts +7 -0
- package/dist/mcp-client/oauth-client.js +12 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/lifecycle.d.ts +11 -0
- package/dist/oauth-tokens/lifecycle.js +17 -0
- package/dist/oauth-tokens/store.js +7 -0
- package/dist/observability/posthog-ai.d.ts +15 -1
- package/dist/observability/posthog-ai.js +24 -12
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.js +158 -28
- package/dist/onboarding/app-profile.js +2 -2
- package/dist/onboarding/plugin.js +10 -2
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
- package/dist/server/agent-chat/action-filters-a2a.js +48 -9
- package/dist/server/agent-chat-plugin.js +36 -9
- package/dist/server/agent-discovery.js +43 -20
- package/dist/server/auth.js +18 -16
- package/dist/server/beta-opt-out-html.js +45 -4
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +23 -7
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.js +87 -6
- package/dist/server/builder-oauth.d.ts +1 -7
- package/dist/server/builder-oauth.js +80 -163
- package/dist/server/core-routes-plugin.d.ts +29 -0
- package/dist/server/core-routes-plugin.js +100 -20
- package/dist/server/default-plugins.d.ts +18 -0
- package/dist/server/default-plugins.js +22 -0
- package/dist/server/edge.d.ts +1 -0
- package/dist/server/edge.js +1 -0
- package/dist/server/framework-request-handler.js +31 -3
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.js +3 -0
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/onboarding-html.js +37 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.js +72 -20
- package/dist/shared/agent-sidebar-url.d.ts +1 -0
- package/dist/shared/agent-sidebar-url.js +1 -0
- package/dist/shared/environment-lanes.d.ts +2 -0
- package/dist/shared/environment-lanes.js +3 -1
- package/dist/shared/index.d.ts +3 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/surface-visibility.d.ts +31 -0
- package/dist/shared/surface-visibility.js +57 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/chat/app/routes.ts +3 -1
- package/dist/templates/chat/vitest.config.ts +8 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/default/app/routes.ts +3 -1
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/tracking/registry.d.ts +11 -0
- package/dist/tracking/registry.js +5 -2
- package/dist/triggers/actions.js +10 -3
- package/dist/usage/store.js +23 -3
- package/dist/user-profile/actions/get-auth-methods.js +18 -5
- package/dist/vite/client.js +24 -5
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/template-clips-capture-everywhere.mdx +29 -30
- package/docs/content/template-clips-developers.mdx +4 -4
- package/docs/content/template-clips.mdx +3 -1
- package/package.json +2 -2
- package/src/eject/workspace-connections.ts +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/chat/app/routes.ts +3 -1
- package/src/templates/chat/vitest.config.ts +8 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/default/app/routes.ts +3 -1
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
|
@@ -31,6 +31,7 @@ import { getDb, schema } from "../server/db/index.js";
|
|
|
31
31
|
import { mutateDesignData } from "../server/lib/design-data-mutation.js";
|
|
32
32
|
import {
|
|
33
33
|
readLiveSourceFile,
|
|
34
|
+
SourceWorkspaceEditConflictError,
|
|
34
35
|
writeInlineSourceFile,
|
|
35
36
|
type SourceWorkspaceFile,
|
|
36
37
|
} from "../server/source-workspace.js";
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
assertDesignHtmlCreateIntegrity,
|
|
49
50
|
describeDesignHtmlIntegrityIssue,
|
|
50
51
|
inspectDesignHtmlDocumentIntegrity,
|
|
52
|
+
isDesignHtmlIntegrityError,
|
|
51
53
|
} from "../shared/html-integrity.js";
|
|
52
54
|
import { assertLockedLayersPreserved } from "../shared/locked-layers.js";
|
|
53
55
|
import { widthToPrefix } from "../shared/responsive-classes.js";
|
|
@@ -488,6 +490,9 @@ const generateDesignAction = defineAction({
|
|
|
488
490
|
"The agent calls this after generating HTML/CSS/JSX content to persist it " +
|
|
489
491
|
"as files in the design project. Creates or updates files as needed. " +
|
|
490
492
|
"Returns the saved files and design URL path for iframe rendering. " +
|
|
493
|
+
"A file rejected by a concurrent edit or an HTML-integrity check does not " +
|
|
494
|
+
"fail the whole call — it is listed in `fileErrors` instead, while every " +
|
|
495
|
+
"other file in the same call still saves; resend just the named file(s). " +
|
|
491
496
|
"Keep the first save compact and working; for large designs, persist a minimal " +
|
|
492
497
|
"version then refine individual files with `edit-design` (search/replace) rather " +
|
|
493
498
|
"than resending a big multi-file payload — a single oversized payload can get cut " +
|
|
@@ -793,14 +798,23 @@ const generateDesignAction = defineAction({
|
|
|
793
798
|
// takes the lenient edit transition instead, so a legacy-malformed screen
|
|
794
799
|
// stays repairable — but its advisories are still reported, or the same
|
|
795
800
|
// content would warn as a new file and save silently as a regeneration.
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
801
|
+
let advisory: ReturnType<typeof assertDesignHtmlCreateIntegrity>;
|
|
802
|
+
if (!existing || becomesHtml) {
|
|
803
|
+
advisory = assertDesignHtmlCreateIntegrity({
|
|
804
|
+
content: file.content,
|
|
805
|
+
fileType: "html",
|
|
806
|
+
filename: file.filename,
|
|
807
|
+
});
|
|
808
|
+
} else {
|
|
809
|
+
// `inspectDesignHtmlDocumentIntegrity` only sets `.advisory` when
|
|
810
|
+
// valid:true; an invalid existing file's issues live in `.detail`
|
|
811
|
+
// instead, so `.advisory ?? []` was silently dropping them — the
|
|
812
|
+
// opposite of the comment above promising they are still reported.
|
|
813
|
+
const inspected = inspectDesignHtmlDocumentIntegrity(file.content);
|
|
814
|
+
advisory = inspected.valid
|
|
815
|
+
? (inspected.advisory ?? [])
|
|
816
|
+
: (inspected.detail ?? []);
|
|
817
|
+
}
|
|
804
818
|
for (const entry of advisory) {
|
|
805
819
|
integrityWarnings.push({
|
|
806
820
|
filename: file.filename,
|
|
@@ -809,6 +823,10 @@ const generateDesignAction = defineAction({
|
|
|
809
823
|
}
|
|
810
824
|
}
|
|
811
825
|
|
|
826
|
+
// Populated when a per-file write is rejected below (conflict or
|
|
827
|
+
// integrity failure); surfaced in the return payload so a partial batch
|
|
828
|
+
// is reported as partial, never silently read back as complete.
|
|
829
|
+
const fileErrors: Array<{ filename: string; message: string }> = [];
|
|
812
830
|
for (const file of annotatedFiles) {
|
|
813
831
|
const existing = existingByName.get(file.filename);
|
|
814
832
|
if (existing) {
|
|
@@ -820,49 +838,79 @@ const generateDesignAction = defineAction({
|
|
|
820
838
|
});
|
|
821
839
|
|
|
822
840
|
try {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
841
|
+
try {
|
|
842
|
+
// `file.content` here is LLM-generated content produced upstream of
|
|
843
|
+
// this action call, so there can be a large async window (the full
|
|
844
|
+
// generation time) between whenever this file's content was last
|
|
845
|
+
// known and this write. Read the LIVE base (collab text when
|
|
846
|
+
// present, else the SQL row) right before persisting and carry its
|
|
847
|
+
// versionHash through to writeInlineSourceFile, which re-reads the
|
|
848
|
+
// live text immediately before its own applyText/DB write and
|
|
849
|
+
// rejects if it no longer matches — closing the race window where a
|
|
850
|
+
// concurrent editor/agent write lands mid-generation. See
|
|
851
|
+
// insert-design-native-asset.ts and insert-asset.ts for the
|
|
852
|
+
// identical pattern.
|
|
853
|
+
const workspaceFile: SourceWorkspaceFile = {
|
|
854
|
+
id: existing.id,
|
|
855
|
+
designId: existing.designId,
|
|
856
|
+
filename: existing.filename ?? "",
|
|
857
|
+
fileType: existing.fileType ?? "html",
|
|
858
|
+
content: existing.content,
|
|
859
|
+
createdAt: null,
|
|
860
|
+
updatedAt: null,
|
|
861
|
+
};
|
|
862
|
+
const live = await readLiveSourceFile(workspaceFile);
|
|
844
863
|
|
|
845
|
-
|
|
864
|
+
assertLockedLayersPreserved(live.content, file.content);
|
|
846
865
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
866
|
+
await writeInlineSourceFile({
|
|
867
|
+
designId: existing.designId,
|
|
868
|
+
file: workspaceFile,
|
|
869
|
+
content: file.content,
|
|
870
|
+
expectedVersionHash: live.versionHash,
|
|
871
|
+
});
|
|
853
872
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
873
|
+
// writeInlineSourceFile only persists content/updatedAt; keep
|
|
874
|
+
// fileType in sync separately when the caller changed it (e.g.
|
|
875
|
+
// html -> jsx), matching the original update behavior.
|
|
876
|
+
const nextFileType = file.fileType ?? "html";
|
|
877
|
+
if (nextFileType !== (existing.fileType ?? "html")) {
|
|
878
|
+
await db
|
|
879
|
+
.update(schema.designFiles)
|
|
880
|
+
.set({ fileType: nextFileType, updatedAt: now })
|
|
881
|
+
.where(eq(schema.designFiles.id, existing.id));
|
|
882
|
+
}
|
|
883
|
+
} finally {
|
|
884
|
+
agentLeaveDocument(existing.id);
|
|
863
885
|
}
|
|
864
|
-
}
|
|
865
|
-
|
|
886
|
+
} catch (error) {
|
|
887
|
+
// Only the two rejection reasons the tool description above
|
|
888
|
+
// promises — a version-hash conflict and an HTML-integrity
|
|
889
|
+
// rejection — are reported per-file. Anything else (a DB/provider
|
|
890
|
+
// failure from the read, the write, or the follow-up fileType
|
|
891
|
+
// update) is not a caller-diagnosable rejection of THIS file's
|
|
892
|
+
// content; swallowing it here would report a transient
|
|
893
|
+
// infrastructure failure as an ordinary "resend this file"
|
|
894
|
+
// outcome, or hide that the content write actually succeeded and
|
|
895
|
+
// only the fileType update failed. Rethrow so it fails the whole
|
|
896
|
+
// call loud instead.
|
|
897
|
+
if (
|
|
898
|
+
!(error instanceof SourceWorkspaceEditConflictError) &&
|
|
899
|
+
!isDesignHtmlIntegrityError(error)
|
|
900
|
+
) {
|
|
901
|
+
throw error;
|
|
902
|
+
}
|
|
903
|
+
// A legitimate optimistic-concurrency conflict or an HTML-integrity
|
|
904
|
+
// rejection on THIS file must not discard files earlier in this
|
|
905
|
+
// batch that already committed durably, and must not disappear
|
|
906
|
+
// either — record it as a distinct, loud failure so the caller can
|
|
907
|
+
// tell "saved" from "failed" and retry just this file, instead of a
|
|
908
|
+
// later read seeing a mixed batch with no marker explaining why.
|
|
909
|
+
fileErrors.push({
|
|
910
|
+
filename: file.filename,
|
|
911
|
+
message: error instanceof Error ? error.message : String(error),
|
|
912
|
+
});
|
|
913
|
+
continue;
|
|
866
914
|
}
|
|
867
915
|
|
|
868
916
|
savedFiles.push({
|
|
@@ -1241,6 +1289,9 @@ const generateDesignAction = defineAction({
|
|
|
1241
1289
|
// Non-blocking: a well-formed screen with no Tailwind runtime renders
|
|
1242
1290
|
// unstyled, which reads as a layout bug rather than a missing runtime.
|
|
1243
1291
|
...(integrityWarnings.length > 0 ? { warnings: integrityWarnings } : {}),
|
|
1292
|
+
// Per-file conflicts/rejections caught above: these files were NOT
|
|
1293
|
+
// saved and still need a retry, unlike everything in `savedFiles`.
|
|
1294
|
+
...(fileErrors.length > 0 ? { fileErrors } : {}),
|
|
1244
1295
|
...creativeContextProvenance,
|
|
1245
1296
|
};
|
|
1246
1297
|
},
|
|
@@ -114,6 +114,7 @@ function buildDesignSystemAgentContext({
|
|
|
114
114
|
assets,
|
|
115
115
|
customInstructions,
|
|
116
116
|
builder,
|
|
117
|
+
canRefreshBuilder,
|
|
117
118
|
}: {
|
|
118
119
|
id: string;
|
|
119
120
|
title: string;
|
|
@@ -122,6 +123,7 @@ function buildDesignSystemAgentContext({
|
|
|
122
123
|
assets?: string | null;
|
|
123
124
|
customInstructions?: string | null;
|
|
124
125
|
builder: BuilderGenerationContext | null;
|
|
126
|
+
canRefreshBuilder: boolean;
|
|
125
127
|
}): string {
|
|
126
128
|
const lines: string[] = [
|
|
127
129
|
"## Selected Design System Context",
|
|
@@ -154,7 +156,9 @@ function buildDesignSystemAgentContext({
|
|
|
154
156
|
builder.builderUrl ? `- URL: ${builder.builderUrl}` : "",
|
|
155
157
|
builder.builderStatus ? `- Status: ${builder.builderStatus}` : "",
|
|
156
158
|
"- Builder DSI docs and token values override local proxy placeholders.",
|
|
157
|
-
|
|
159
|
+
canRefreshBuilder
|
|
160
|
+
? "- If no usable DSI docs or tokens are returned, call refresh-design-system-with-builder once, then call get-design-system again before generating; if it is still empty, tell the user Builder indexing is not ready."
|
|
161
|
+
: "- If no usable DSI docs or tokens are returned, tell the user Builder indexing is not ready; refreshing the shared system requires editor access.",
|
|
158
162
|
);
|
|
159
163
|
|
|
160
164
|
if (builder.warning) {
|
|
@@ -297,6 +301,7 @@ export default defineAction({
|
|
|
297
301
|
data: row.data,
|
|
298
302
|
assets: row.assets,
|
|
299
303
|
customInstructions: row.customInstructions,
|
|
304
|
+
canRefreshBuilder: ["owner", "admin", "editor"].includes(access.role),
|
|
300
305
|
builder,
|
|
301
306
|
}),
|
|
302
307
|
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import {
|
|
3
|
+
hydrateBuilderDesignSystemReference,
|
|
4
|
+
parseBuilderDesignSystemProxyReference,
|
|
5
|
+
} from "@agent-native/core/server";
|
|
6
|
+
import { assertAccess, resolveAccess } from "@agent-native/core/sharing";
|
|
7
|
+
import { and, eq } from "drizzle-orm";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
11
|
+
import { reconcileBuilderProxyData } from "../server/lib/builder-design-system-proxy.js";
|
|
12
|
+
|
|
13
|
+
function persistedBuilderSyncMatches(data: unknown, syncedAt: string): boolean {
|
|
14
|
+
if (typeof data !== "string") return false;
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(data) as Record<string, unknown>;
|
|
17
|
+
return (
|
|
18
|
+
parsed.builderStatus === "ready" && parsed.builderSyncedAt === syncedAt
|
|
19
|
+
);
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"The design system data became invalid while Builder DSI was syncing.",
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default defineAction({
|
|
28
|
+
description:
|
|
29
|
+
"Refresh a Builder-backed design-system proxy after DSI indexing finishes. " +
|
|
30
|
+
"Requires editor access. If Builder is still processing, returns synced=false " +
|
|
31
|
+
"without replacing the local proxy with partial data.",
|
|
32
|
+
schema: z.object({
|
|
33
|
+
id: z.string().min(1).describe("Local design system id"),
|
|
34
|
+
}),
|
|
35
|
+
run: async ({ id }) => {
|
|
36
|
+
await assertAccess("design-system", id, "editor");
|
|
37
|
+
const access = await resolveAccess("design-system", id);
|
|
38
|
+
if (!access) throw new Error("Design system not found");
|
|
39
|
+
|
|
40
|
+
const reference = parseBuilderDesignSystemProxyReference(
|
|
41
|
+
access.resource.data,
|
|
42
|
+
);
|
|
43
|
+
if (!reference) {
|
|
44
|
+
throw new Error("This design system is not a Builder-backed proxy.");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const hydrated = await hydrateBuilderDesignSystemReference(reference);
|
|
48
|
+
const syncedAt = new Date().toISOString();
|
|
49
|
+
const reconciliation = reconcileBuilderProxyData(
|
|
50
|
+
access.resource.data,
|
|
51
|
+
hydrated,
|
|
52
|
+
syncedAt,
|
|
53
|
+
);
|
|
54
|
+
if (!reconciliation) {
|
|
55
|
+
return {
|
|
56
|
+
id,
|
|
57
|
+
synced: false,
|
|
58
|
+
status:
|
|
59
|
+
hydrated.builderStatus ?? reference.builderStatus ?? "in-progress",
|
|
60
|
+
docCount: hydrated.docCount,
|
|
61
|
+
tokenCount: 0,
|
|
62
|
+
message: "Builder DSI has not returned usable token values yet.",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (reconciliation.rejectedTokenCount > 0) {
|
|
67
|
+
return {
|
|
68
|
+
id,
|
|
69
|
+
synced: false,
|
|
70
|
+
status: "incomplete",
|
|
71
|
+
docCount: hydrated.docCount,
|
|
72
|
+
tokenCount: reconciliation.tokenCount,
|
|
73
|
+
rejectedTokenCount: reconciliation.rejectedTokenCount,
|
|
74
|
+
message: `Builder DSI returned ${reconciliation.rejectedTokenCount} token(s) that could not be safely imported.`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!reconciliation.completionConfirmed) {
|
|
79
|
+
return {
|
|
80
|
+
id,
|
|
81
|
+
synced: false,
|
|
82
|
+
status:
|
|
83
|
+
hydrated.builderStatus ?? reference.builderStatus ?? "in-progress",
|
|
84
|
+
docCount: hydrated.docCount,
|
|
85
|
+
tokenCount: reconciliation.tokenCount,
|
|
86
|
+
rejectedTokenCount: 0,
|
|
87
|
+
message:
|
|
88
|
+
"Builder DSI returned token values without confirming that indexing is complete. Retry after Builder reports completion.",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
await assertAccess("design-system", id, "editor");
|
|
93
|
+
const latestAccess = await resolveAccess("design-system", id);
|
|
94
|
+
if (!latestAccess) throw new Error("Design system not found");
|
|
95
|
+
if (
|
|
96
|
+
latestAccess.resource.id !== access.resource.id ||
|
|
97
|
+
latestAccess.resource.data !== access.resource.data
|
|
98
|
+
) {
|
|
99
|
+
return {
|
|
100
|
+
id,
|
|
101
|
+
synced: false,
|
|
102
|
+
status: "conflict",
|
|
103
|
+
docCount: hydrated.docCount,
|
|
104
|
+
tokenCount: reconciliation.tokenCount,
|
|
105
|
+
rejectedTokenCount: 0,
|
|
106
|
+
message:
|
|
107
|
+
"The design system changed while Builder DSI was syncing. Retry the refresh.",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const db = getDb();
|
|
112
|
+
await db
|
|
113
|
+
.update(schema.designSystems)
|
|
114
|
+
.set({ data: reconciliation.data, updatedAt: syncedAt })
|
|
115
|
+
.where(
|
|
116
|
+
and(
|
|
117
|
+
eq(schema.designSystems.id, latestAccess.resource.id),
|
|
118
|
+
eq(schema.designSystems.data, latestAccess.resource.data),
|
|
119
|
+
),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const persisted = await resolveAccess("design-system", id);
|
|
123
|
+
if (!persistedBuilderSyncMatches(persisted?.resource?.data, syncedAt)) {
|
|
124
|
+
return {
|
|
125
|
+
id,
|
|
126
|
+
synced: false,
|
|
127
|
+
status: "conflict",
|
|
128
|
+
docCount: hydrated.docCount,
|
|
129
|
+
tokenCount: reconciliation.tokenCount,
|
|
130
|
+
rejectedTokenCount: 0,
|
|
131
|
+
message:
|
|
132
|
+
"The design system changed while Builder DSI was syncing. Retry the refresh.",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
id,
|
|
138
|
+
synced: true,
|
|
139
|
+
status: "ready",
|
|
140
|
+
docCount: hydrated.docCount,
|
|
141
|
+
tokenCount: reconciliation.tokenCount,
|
|
142
|
+
rejectedTokenCount: reconciliation.rejectedTokenCount,
|
|
143
|
+
syncedAt,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
});
|
|
@@ -20,10 +20,12 @@ import {
|
|
|
20
20
|
closePenPath,
|
|
21
21
|
constrainPointTo45Degrees,
|
|
22
22
|
createCornerNode,
|
|
23
|
-
|
|
23
|
+
createPenCuspLatch,
|
|
24
|
+
createPenDragNode,
|
|
24
25
|
isPenCloseTarget,
|
|
25
26
|
serializePenPath,
|
|
26
27
|
translatePenPath,
|
|
28
|
+
type PenCuspLatch,
|
|
27
29
|
type PenPath,
|
|
28
30
|
type PenPoint,
|
|
29
31
|
} from "@shared/pen-path";
|
|
@@ -494,7 +496,10 @@ interface DesignCanvasProps {
|
|
|
494
496
|
selector: string,
|
|
495
497
|
styles: Record<string, string>,
|
|
496
498
|
info?: ElementInfo,
|
|
497
|
-
metadata?: {
|
|
499
|
+
metadata?: {
|
|
500
|
+
originalStyles?: Record<string, string>;
|
|
501
|
+
preserveSelection?: boolean;
|
|
502
|
+
},
|
|
498
503
|
) => void;
|
|
499
504
|
onTextContentChange?: (
|
|
500
505
|
selector: string,
|
|
@@ -956,6 +961,16 @@ function originFromUrl(value: string | undefined): string | null {
|
|
|
956
961
|
}
|
|
957
962
|
}
|
|
958
963
|
|
|
964
|
+
/**
|
|
965
|
+
* JSON for embedding inside an inline `<script>`. A bare `JSON.stringify` keeps
|
|
966
|
+
* `</script>` verbatim, and the HTML parser closes the surrounding script the
|
|
967
|
+
* moment it sees that sequence — truncating the bridge for any design whose
|
|
968
|
+
* head legitimately contains one (JSON-LD, a templating snippet).
|
|
969
|
+
*/
|
|
970
|
+
function inlineScriptJson(value: string): string {
|
|
971
|
+
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
972
|
+
}
|
|
973
|
+
|
|
959
974
|
function buildEditorChromeBridgeScript(args: {
|
|
960
975
|
readOnly: boolean;
|
|
961
976
|
editMode: boolean;
|
|
@@ -966,6 +981,7 @@ function buildEditorChromeBridgeScript(args: {
|
|
|
966
981
|
contentOffsetX: number;
|
|
967
982
|
contentOffsetY: number;
|
|
968
983
|
runtimeLayerSnapshotEnabled: boolean;
|
|
984
|
+
initialSourceHead: string;
|
|
969
985
|
}) {
|
|
970
986
|
return (
|
|
971
987
|
createEditorBridgeThemeScript(readEditorBridgeThemeVars()) +
|
|
@@ -1001,9 +1017,18 @@ function buildEditorChromeBridgeScript(args: {
|
|
|
1001
1017
|
"__SELECTED_LAYER_DRAG_PRIORITY__",
|
|
1002
1018
|
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
1003
1019
|
)
|
|
1020
|
+
.replace(/__INITIAL_SOURCE_HEAD__/g, () =>
|
|
1021
|
+
inlineScriptJson(args.initialSourceHead),
|
|
1022
|
+
)
|
|
1004
1023
|
);
|
|
1005
1024
|
}
|
|
1006
1025
|
|
|
1026
|
+
/** The `<head>` the bridge's own srcdoc will render, so its first in-place
|
|
1027
|
+
* patch diffs against what is actually in the document. */
|
|
1028
|
+
function sourceHeadInnerHtml(html: string): string {
|
|
1029
|
+
return /<head\b[^>]*>([\s\S]*?)<\/head\s*>/i.exec(html)?.[1] ?? "";
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1007
1032
|
function contentHash(value: string): string {
|
|
1008
1033
|
let hash = 0;
|
|
1009
1034
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -1015,27 +1040,30 @@ function contentHash(value: string): string {
|
|
|
1015
1040
|
const SCRIPT_ELEMENT_RE = /<script\b[^>]*>[\s\S]*?<\/script\s*>/gi; // i18n-ignore non-UI regex
|
|
1016
1041
|
|
|
1017
1042
|
/**
|
|
1018
|
-
* Runtime document replacement
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1043
|
+
* Runtime document replacement morphs the live DOM, which preserves the iframe
|
|
1044
|
+
* browsing context but cannot execute newly inserted or changed scripts.
|
|
1045
|
+
* Reload only when source script elements change.
|
|
1046
|
+
*
|
|
1047
|
+
* A changed `<head>` is NOT a reload trigger: the bridge swaps only the nodes
|
|
1048
|
+
* the previous source head contributed (replaceSourceHeadNodes), leaving what
|
|
1049
|
+
* the page's own runtime injected in place. Treating any head edit as a reload
|
|
1050
|
+
* meant every breakpoint override, motion track and token write — all of which
|
|
1051
|
+
* persist into a managed `<style>` in the head — reloaded the whole frame.
|
|
1022
1052
|
*/
|
|
1023
1053
|
function runtimeDocumentNeedsReload(
|
|
1024
1054
|
previousContent: string,
|
|
1025
1055
|
nextContent: string,
|
|
1026
1056
|
): boolean {
|
|
1027
|
-
const scriptSignature = (html: string) =>
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
headSignature(previousContent) !== headSignature(nextContent)
|
|
1038
|
-
);
|
|
1057
|
+
const scriptSignature = (html: string) => {
|
|
1058
|
+
const headEnd = html.search(/<\/head\s*>/i);
|
|
1059
|
+
const boundary = headEnd === -1 ? 0 : headEnd;
|
|
1060
|
+
return Array.from(
|
|
1061
|
+
html.matchAll(SCRIPT_ELEMENT_RE),
|
|
1062
|
+
(match) =>
|
|
1063
|
+
`${(match.index ?? 0) < boundary ? "head" : "body"}:${match[0]}`,
|
|
1064
|
+
).join("\n");
|
|
1065
|
+
};
|
|
1066
|
+
return scriptSignature(previousContent) !== scriptSignature(nextContent);
|
|
1039
1067
|
}
|
|
1040
1068
|
|
|
1041
1069
|
/**
|
|
@@ -1465,6 +1493,9 @@ export function DesignCanvas({
|
|
|
1465
1493
|
contentOffsetX: embeddedFrame?.contentOffsetX ?? 0,
|
|
1466
1494
|
contentOffsetY: embeddedFrame?.contentOffsetY ?? 0,
|
|
1467
1495
|
runtimeLayerSnapshotEnabled,
|
|
1496
|
+
// A live/localhost screen's document is the running app, not content
|
|
1497
|
+
// this canvas rendered, so there is no source head to diff against.
|
|
1498
|
+
initialSourceHead: "",
|
|
1468
1499
|
}),
|
|
1469
1500
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1470
1501
|
[boardSurface, contentKey, runtimeLayerSnapshotEnabled, screenId],
|
|
@@ -2329,6 +2360,7 @@ export function DesignCanvas({
|
|
|
2329
2360
|
// keyed bridge registration is pending. The loading surface waits without
|
|
2330
2361
|
// mounting an iframe, then mounts the real `src` exactly once.
|
|
2331
2362
|
if (rawExternalPreviewUrl) return undefined;
|
|
2363
|
+
const localizedContent = withLocalRuntimes(iframeRenderContent);
|
|
2332
2364
|
const editorChromeBridge = interactMode
|
|
2333
2365
|
? ""
|
|
2334
2366
|
: createEditorBridgeThemeScript(readEditorBridgeThemeVars()) +
|
|
@@ -2369,6 +2401,9 @@ export function DesignCanvas({
|
|
|
2369
2401
|
.replace(
|
|
2370
2402
|
"__SELECTED_LAYER_DRAG_PRIORITY__",
|
|
2371
2403
|
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
2404
|
+
)
|
|
2405
|
+
.replace(/__INITIAL_SOURCE_HEAD__/g, () =>
|
|
2406
|
+
inlineScriptJson(sourceHeadInnerHtml(localizedContent)),
|
|
2372
2407
|
);
|
|
2373
2408
|
// ALWAYS injected (like the other always-on bridges above) so
|
|
2374
2409
|
// MultiScreenCanvas's cross-screen drag hit-testing
|
|
@@ -2389,7 +2424,7 @@ export function DesignCanvas({
|
|
|
2389
2424
|
editorChromeBridge +
|
|
2390
2425
|
imageDiagBridge;
|
|
2391
2426
|
const frameContent = getEmbeddedFrameDocumentContent({
|
|
2392
|
-
content:
|
|
2427
|
+
content: localizedContent,
|
|
2393
2428
|
embeddedFrameBackground,
|
|
2394
2429
|
transparentBackground,
|
|
2395
2430
|
contentOffsetX: embeddedFrame?.contentOffsetX ?? 0,
|
|
@@ -2410,7 +2445,7 @@ export function DesignCanvas({
|
|
|
2410
2445
|
embeddedFrame?.contentOffsetY ?? 0,
|
|
2411
2446
|
),
|
|
2412
2447
|
].join("");
|
|
2413
|
-
frameDocument = `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">${frameStyle}</head><body>${
|
|
2448
|
+
frameDocument = `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">${frameStyle}</head><body>${localizedContent}${bridgeToInject}</body></html>`;
|
|
2414
2449
|
}
|
|
2415
2450
|
// Overview frames report their own content height so the canvas can
|
|
2416
2451
|
// content-fit them (Framer-style). Embedded (overview) frames only — a
|
|
@@ -2730,6 +2765,7 @@ export function DesignCanvas({
|
|
|
2730
2765
|
isElementInfoPayload(e.data.payload) ? e.data.payload : undefined,
|
|
2731
2766
|
{
|
|
2732
2767
|
originalStyles,
|
|
2768
|
+
preserveSelection: e.data.preserveSelection === true,
|
|
2733
2769
|
},
|
|
2734
2770
|
);
|
|
2735
2771
|
}
|
|
@@ -5110,6 +5146,7 @@ interface SingleScreenPenGestureState {
|
|
|
5110
5146
|
pathBefore: PenPath | null;
|
|
5111
5147
|
moved: boolean;
|
|
5112
5148
|
closing: boolean;
|
|
5149
|
+
cuspLatch: PenCuspLatch;
|
|
5113
5150
|
}
|
|
5114
5151
|
|
|
5115
5152
|
const SINGLE_SCREEN_PEN_HIT_RADIUS_PX = 10;
|
|
@@ -5342,6 +5379,7 @@ function SingleScreenCreationOverlay({
|
|
|
5342
5379
|
pathBefore,
|
|
5343
5380
|
moved: false,
|
|
5344
5381
|
closing,
|
|
5382
|
+
cuspLatch: createPenCuspLatch(),
|
|
5345
5383
|
};
|
|
5346
5384
|
const initialPath = closing
|
|
5347
5385
|
? closePenPath(pathBefore!)
|
|
@@ -5400,9 +5438,12 @@ function SingleScreenCreationOverlay({
|
|
|
5400
5438
|
: appendPenNode(
|
|
5401
5439
|
gesture.pathBefore,
|
|
5402
5440
|
moved
|
|
5403
|
-
?
|
|
5404
|
-
|
|
5405
|
-
|
|
5441
|
+
? createPenDragNode(
|
|
5442
|
+
gesture.anchor,
|
|
5443
|
+
handleOut,
|
|
5444
|
+
gesture.cuspLatch,
|
|
5445
|
+
e.altKey,
|
|
5446
|
+
)
|
|
5406
5447
|
: createCornerNode(gesture.anchor),
|
|
5407
5448
|
);
|
|
5408
5449
|
updatePenPath(nextPath);
|
|
@@ -5454,9 +5495,12 @@ function SingleScreenCreationOverlay({
|
|
|
5454
5495
|
: appendPenNode(
|
|
5455
5496
|
gesture.pathBefore,
|
|
5456
5497
|
moved
|
|
5457
|
-
?
|
|
5458
|
-
|
|
5459
|
-
|
|
5498
|
+
? createPenDragNode(
|
|
5499
|
+
gesture.anchor,
|
|
5500
|
+
handleOut,
|
|
5501
|
+
gesture.cuspLatch,
|
|
5502
|
+
e.altKey,
|
|
5503
|
+
)
|
|
5460
5504
|
: createCornerNode(gesture.anchor),
|
|
5461
5505
|
);
|
|
5462
5506
|
penGestureRef.current = null;
|