@agent-native/core 0.131.5 → 0.131.7
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 +3 -3
- package/corpus/core/CHANGELOG.md +70 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +13 -6
- package/corpus/core/docs/content/cloneable-saas.mdx +5 -5
- package/corpus/core/docs/content/creating-templates.mdx +9 -0
- package/corpus/core/docs/content/deployment.mdx +18 -12
- package/corpus/core/docs/content/doctor.mdx +8 -1
- package/corpus/core/docs/content/drop-in-agent.mdx +1 -1
- package/corpus/core/docs/content/extensions.mdx +18 -18
- package/corpus/core/docs/content/faq.mdx +4 -4
- package/corpus/core/docs/content/key-concepts.mdx +30 -21
- package/corpus/core/docs/content/security.mdx +2 -2
- package/corpus/core/docs/content/template-brain-developers.mdx +4 -1
- package/corpus/core/docs/content/template-mail-developers.mdx +4 -1
- package/corpus/core/docs/content/what-is-agent-native.mdx +6 -6
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/client.ts +449 -66
- package/corpus/core/src/a2a/correlation.ts +31 -0
- package/corpus/core/src/a2a/invoke.ts +4 -2
- package/corpus/core/src/a2a/types.ts +4 -0
- package/corpus/core/src/action.ts +3 -0
- package/corpus/core/src/agent/action-continuation-guidance.ts +2 -1
- package/corpus/core/src/agent/engine/registry.ts +98 -6
- package/corpus/core/src/agent/production-agent.ts +151 -18
- package/corpus/core/src/agent/run-loop-with-resume.ts +190 -3
- package/corpus/core/src/agent/run-manager.ts +117 -41
- package/corpus/core/src/agent/thread-debug-history.ts +86 -0
- package/corpus/core/src/agent/types.ts +3 -1
- package/corpus/core/src/cli/create.ts +11 -1
- package/corpus/core/src/cli/templates-meta.ts +2 -2
- package/corpus/core/src/client/agent-chat-adapter.ts +91 -13
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +11 -9
- package/corpus/core/src/client/sse-event-processor.ts +17 -3
- package/corpus/core/src/db/client.ts +57 -17
- package/corpus/core/src/guards/no-env-credentials.ts +2 -0
- package/corpus/core/src/integrations/adapters/slack.ts +8 -3
- package/corpus/core/src/localization/default-messages.ts +44 -0
- package/corpus/core/src/observability/traces.ts +78 -5
- package/corpus/core/src/scripts/call-agent.ts +294 -11
- package/corpus/core/src/scripts/describe-workspace-apps.ts +2 -2
- package/corpus/core/src/secrets/crypto.ts +156 -35
- package/corpus/core/src/secrets/storage.ts +64 -26
- package/corpus/core/src/server/agent-capabilities.ts +1 -1
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +113 -7
- package/corpus/core/src/server/agent-chat/context-tools.ts +2 -0
- package/corpus/core/src/server/agent-chat/plugin-options.ts +34 -1
- package/corpus/core/src/server/agent-chat/prompt-resources.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +91 -59
- package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
- package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
- package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
- package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
- package/corpus/core/src/vite/client.ts +1 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +5 -4
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +6 -4
- package/corpus/templates/analytics/AGENTS.md +7 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -3
- package/corpus/templates/analytics/changelog/2026-07-30-delegated-analytics-questions-now-return-a-useful-current-me.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-30-scheduled-dashboard-emails-complete-every-panel-without-pool.md +6 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +28 -1
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +18 -11
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +4 -4
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +9 -5
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +6 -2
- package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +11 -4
- package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +49 -31
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +16 -8
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +9 -3
- package/corpus/templates/analytics/server/lib/production-serverless-runtime.ts +11 -0
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +10 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -2
- package/corpus/templates/analytics/server/plugins/analytics-alert-jobs.ts +2 -1
- package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +2 -1
- package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +1 -12
- package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +54 -6
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +20 -9
- package/corpus/templates/brain/.agents/skills/ingestion-and-connectors/SKILL.md +33 -1
- package/corpus/templates/brain/AGENTS.md +3 -1
- package/corpus/templates/brain/README.md +4 -1
- package/corpus/templates/brain/actions/_schemas.ts +30 -8
- package/corpus/templates/brain/actions/ask-brain.ts +124 -14
- package/corpus/templates/brain/actions/create-source.ts +18 -2
- package/corpus/templates/brain/actions/enqueue-captures-distillation.ts +8 -123
- package/corpus/templates/brain/actions/enqueue-distillation.ts +6 -127
- package/corpus/templates/brain/actions/import-capture.ts +17 -5
- package/corpus/templates/brain/actions/import-transcript.ts +17 -5
- package/corpus/templates/brain/actions/update-source.ts +25 -5
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/brain/changelog/2026-07-30-blessed-resources-can-feed-cited-company-answers.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-30-the-left-sidebar-no-longer-shows-a-blank-organization-placeh.md +6 -0
- package/corpus/templates/brain/server/lib/brain.ts +49 -19
- package/corpus/templates/brain/server/lib/distillation-queue.ts +147 -0
- package/corpus/templates/brain/server/lib/source-policy.ts +264 -0
- package/corpus/templates/brain/server/plugins/agent-chat.ts +3 -2
- package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +116 -19
- package/corpus/templates/clips/app/components/meetings/google-oauth-identity-notice.tsx +51 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +3 -1
- package/corpus/templates/clips/changelog/2026-07-30-google-calendar-warning.md +6 -0
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +72 -8
- package/corpus/templates/content/changelog/2026-07-30-the-slash-command-hint-now-stays-on-only-the-active-empty-li.md +6 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +506 -11
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +148 -17
- package/corpus/templates/design/app/components/design/canvas-interactions/design-canvas-interactions.ts +357 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +7 -466
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +15 -311
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +19 -997
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +8 -1216
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +31 -38
- package/corpus/templates/design/package.json +0 -1
- package/corpus/templates/dispatch/AGENTS.md +8 -0
- package/corpus/templates/dispatch/DEVELOPING.md +29 -0
- package/corpus/templates/dispatch/actions/view-screen.ts +34 -2
- package/corpus/templates/dispatch/app/i18n-data.ts +457 -0
- package/corpus/templates/dispatch/changelog/2026-07-30-delegated-dispatch-work-continues-reliably-in-the-background.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-30-find-failed-runs-across-apps.md +6 -0
- package/corpus/templates/dispatch/netlify.toml +3 -0
- package/corpus/templates/plan/actions/get-visual-plan.ts +10 -6
- package/corpus/templates/plan/actions/patch-visual-plan-source.ts +117 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +56 -14
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
- package/corpus/templates/plan/changelog/2026-07-30-plan-agents-recover-with-targeted-writes.md +6 -0
- package/corpus/templates/plan/shared/plan-content.ts +35 -0
- package/corpus/templates/slides/.agents/skills/analytics-data-for-decks/SKILL.md +8 -12
- package/corpus/templates/slides/AGENTS.md +4 -4
- package/corpus/templates/slides/actions/create-deck.ts +1 -1
- package/corpus/templates/slides/actions/duplicate-deck.ts +19 -4
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -10
- package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +12 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +30 -13
- package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +35 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +63 -56
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -76
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1110 -292
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +53 -0
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +235 -18
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +4 -1
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +11 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +129 -0
- package/corpus/templates/slides/app/components/editor/selection-overlay-measurement.ts +70 -0
- package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +519 -65
- package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +36 -426
- package/corpus/templates/slides/app/components/visual-editor/DrawOverlay.tsx +19 -458
- package/corpus/templates/slides/app/context/DeckContext.tsx +179 -72
- package/corpus/templates/slides/app/global.css +105 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -0
- package/corpus/templates/slides/app/lib/deck-editor-loading.ts +26 -0
- package/corpus/templates/slides/app/lib/mermaid-blocks.ts +27 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +71 -38
- package/corpus/templates/slides/app/pages/Index.tsx +98 -41
- package/corpus/templates/slides/changelog/2026-07-30-deck-loading-no-longer-flashes-an-unavailable-message.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-duplicating-a-deck-from-the-deck-list-now-opens-the-copy-imm.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-layout-overflow-warning-is-readable-and-dismissible.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-new-decks-now-start-with-an-empty-slide-list-when-no-slides-.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-shared-canvas-annotations.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-slide-objects-can-be-moved-as-a-group-copied-and-pasted-with.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-slide-text-editing-and-object-controls-now-match-google-slides.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-style-panel-now-scrolls-with-speaker-notes-open-shows-the-sl.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-top-toolbar-controls-now-use-consistent-sizing-with-undo-and.md +6 -0
- package/corpus/templates/slides/netlify.toml +3 -1
- package/corpus/templates/slides/package.json +0 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +18 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/slides/vite.config.ts +0 -1
- package/corpus/toolkit/CHANGELOG.md +13 -0
- package/corpus/toolkit/README.md +19 -0
- package/corpus/toolkit/agent-native.eject.json +38 -0
- package/corpus/toolkit/package.json +29 -1
- package/corpus/toolkit/src/canvas-annotations/CanvasCommentPins.tsx +861 -0
- package/corpus/toolkit/src/canvas-annotations/DrawOverlay.tsx +1233 -0
- package/corpus/toolkit/src/canvas-annotations/index.ts +15 -0
- package/corpus/toolkit/src/canvas-annotations/types.ts +14 -0
- package/corpus/toolkit/src/canvas-interactions/canvas-interactions.ts +933 -0
- package/corpus/toolkit/src/canvas-interactions/index.ts +67 -0
- package/corpus/toolkit/src/design-tweaks/scrub-input-utils.ts +311 -0
- package/corpus/toolkit/src/design-tweaks/scrub-input.tsx +491 -0
- package/corpus/toolkit/src/design-tweaks/visual-style-controls.tsx +26 -171
- package/corpus/toolkit/src/index.ts +1 -0
- package/dist/a2a/client.d.ts +23 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +309 -44
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/correlation.d.ts +1 -0
- package/dist/a2a/correlation.d.ts.map +1 -1
- package/dist/a2a/correlation.js +27 -0
- package/dist/a2a/correlation.js.map +1 -1
- package/dist/a2a/invoke.d.ts.map +1 -1
- package/dist/a2a/invoke.js +4 -2
- package/dist/a2a/invoke.js.map +1 -1
- package/dist/a2a/types.d.ts +4 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/action.d.ts +3 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/action-continuation-guidance.d.ts.map +1 -1
- package/dist/agent/action-continuation-guidance.js +2 -1
- package/dist/agent/action-continuation-guidance.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +82 -8
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts +40 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +113 -15
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +21 -0
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +163 -4
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-manager.d.ts +16 -9
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +93 -42
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/thread-debug-history.d.ts +10 -0
- package/dist/agent/thread-debug-history.d.ts.map +1 -0
- package/dist/agent/thread-debug-history.js +68 -0
- package/dist/agent/thread-debug-history.js.map +1 -0
- package/dist/agent/types.d.ts +3 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +6 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/templates-meta.js +2 -2
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +76 -13
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +1 -1
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +12 -3
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +48 -17
- package/dist/db/client.js.map +1 -1
- package/dist/guards/no-env-credentials.d.ts.map +1 -1
- package/dist/guards/no-env-credentials.js +2 -0
- package/dist/guards/no-env-credentials.js.map +1 -1
- package/dist/integrations/adapters/slack.js +7 -3
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/localization/default-messages.d.ts +43 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +43 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/observability/traces.d.ts +3 -1
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +73 -4
- package/dist/observability/traces.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +237 -12
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/describe-workspace-apps.js +2 -2
- package/dist/scripts/describe-workspace-apps.js.map +1 -1
- package/dist/secrets/crypto.d.ts +36 -21
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +134 -33
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/secrets/storage.d.ts +6 -6
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +43 -26
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/agent-capabilities.js +1 -1
- package/dist/server/agent-capabilities.js.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +17 -3
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +94 -3
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
- package/dist/server/agent-chat/context-tools.js +2 -0
- package/dist/server/agent-chat/context-tools.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +23 -0
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js +4 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat/prompt-resources.js +1 -1
- package/dist/server/agent-chat/prompt-resources.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +2 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +79 -56
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +19 -7
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
- package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +13 -6
- package/docs/content/cloneable-saas.mdx +5 -5
- package/docs/content/creating-templates.mdx +9 -0
- package/docs/content/deployment.mdx +18 -12
- package/docs/content/doctor.mdx +8 -1
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/extensions.mdx +18 -18
- package/docs/content/faq.mdx +4 -4
- package/docs/content/key-concepts.mdx +30 -21
- package/docs/content/security.mdx +2 -2
- package/docs/content/template-brain-developers.mdx +4 -1
- package/docs/content/template-mail-developers.mdx +4 -1
- package/docs/content/what-is-agent-native.mdx +6 -6
- package/package.json +3 -3
- package/src/a2a/client.ts +449 -66
- package/src/a2a/correlation.ts +31 -0
- package/src/a2a/invoke.ts +4 -2
- package/src/a2a/types.ts +4 -0
- package/src/action.ts +3 -0
- package/src/agent/action-continuation-guidance.ts +2 -1
- package/src/agent/engine/registry.ts +98 -6
- package/src/agent/production-agent.ts +151 -18
- package/src/agent/run-loop-with-resume.ts +190 -3
- package/src/agent/run-manager.ts +117 -41
- package/src/agent/thread-debug-history.ts +86 -0
- package/src/agent/types.ts +3 -1
- package/src/cli/create.ts +11 -1
- package/src/cli/templates-meta.ts +2 -2
- package/src/client/agent-chat-adapter.ts +91 -13
- package/src/client/resources/McpIntegrationDialog.tsx +11 -9
- package/src/client/sse-event-processor.ts +17 -3
- package/src/db/client.ts +57 -17
- package/src/guards/no-env-credentials.ts +2 -0
- package/src/integrations/adapters/slack.ts +8 -3
- package/src/localization/default-messages.ts +44 -0
- package/src/observability/traces.ts +78 -5
- package/src/scripts/call-agent.ts +294 -11
- package/src/scripts/describe-workspace-apps.ts +2 -2
- package/src/secrets/crypto.ts +156 -35
- package/src/secrets/storage.ts +64 -26
- package/src/server/agent-capabilities.ts +1 -1
- package/src/server/agent-chat/action-filters-a2a.ts +113 -7
- package/src/server/agent-chat/context-tools.ts +2 -0
- package/src/server/agent-chat/plugin-options.ts +34 -1
- package/src/server/agent-chat/prompt-resources.ts +1 -1
- package/src/server/agent-chat-plugin.ts +91 -59
- package/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
- package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
- package/src/vite/client.ts +1 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { IconAlertTriangle, IconX } from "@tabler/icons-react";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
|
|
5
|
+
interface SlideOverflowWarningProps {
|
|
6
|
+
verticalOverflow: number;
|
|
7
|
+
isAskingAgentToFix: boolean;
|
|
8
|
+
dismissLabel: string;
|
|
9
|
+
onFix: () => void;
|
|
10
|
+
onDismiss: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function SlideOverflowWarning({
|
|
14
|
+
verticalOverflow,
|
|
15
|
+
isAskingAgentToFix,
|
|
16
|
+
dismissLabel,
|
|
17
|
+
onFix,
|
|
18
|
+
onDismiss,
|
|
19
|
+
}: SlideOverflowWarningProps) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
role="status"
|
|
23
|
+
aria-live="polite"
|
|
24
|
+
className="absolute top-3 left-3 z-20 flex items-center gap-2 rounded-md border border-amber-400/70 bg-amber-950/95 px-2.5 py-1.5 text-xs text-amber-50 shadow-lg"
|
|
25
|
+
onPointerDown={(event) => event.stopPropagation()}
|
|
26
|
+
onClick={(event) => event.stopPropagation()}
|
|
27
|
+
>
|
|
28
|
+
<IconAlertTriangle className="h-3.5 w-3.5 flex-shrink-0" stroke={2} />
|
|
29
|
+
<span className="leading-tight">
|
|
30
|
+
Layout overflows by {verticalOverflow}px
|
|
31
|
+
</span>
|
|
32
|
+
<Button
|
|
33
|
+
size="sm"
|
|
34
|
+
variant="ghost"
|
|
35
|
+
className="ml-1 h-6 cursor-pointer px-2 text-[11px] font-medium text-amber-50 hover:bg-amber-400/20 hover:text-white"
|
|
36
|
+
onClick={onFix}
|
|
37
|
+
disabled={isAskingAgentToFix}
|
|
38
|
+
>
|
|
39
|
+
{isAskingAgentToFix ? "Asking…" : "Fix with AI"}
|
|
40
|
+
</Button>
|
|
41
|
+
<Button
|
|
42
|
+
size="icon"
|
|
43
|
+
variant="ghost"
|
|
44
|
+
className="size-6 cursor-pointer text-amber-50 hover:bg-amber-400/20 hover:text-white"
|
|
45
|
+
onClick={onDismiss}
|
|
46
|
+
aria-label={dismissLabel}
|
|
47
|
+
title={dismissLabel}
|
|
48
|
+
>
|
|
49
|
+
<IconX className="size-3.5" />
|
|
50
|
+
</Button>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -9,12 +9,20 @@ import {
|
|
|
9
9
|
} from "@agent-native/toolkit/design-tweaks";
|
|
10
10
|
import type { DesignSystemData } from "@shared/api";
|
|
11
11
|
import {
|
|
12
|
+
IconAngle,
|
|
13
|
+
IconArrowAutofitHeight,
|
|
14
|
+
IconArrowAutofitWidth,
|
|
12
15
|
IconBorderRadius,
|
|
16
|
+
IconBorderStyle,
|
|
13
17
|
IconBoxPadding,
|
|
14
18
|
IconDroplet,
|
|
19
|
+
IconGridDots,
|
|
15
20
|
IconLetterCase,
|
|
16
21
|
IconRuler2,
|
|
17
22
|
IconSpacingHorizontal,
|
|
23
|
+
IconSpacingVertical,
|
|
24
|
+
IconStackBack,
|
|
25
|
+
IconStackFront,
|
|
18
26
|
IconX,
|
|
19
27
|
} from "@tabler/icons-react";
|
|
20
28
|
|
|
@@ -24,6 +32,8 @@ import { cn } from "@/lib/utils";
|
|
|
24
32
|
import type { InlineTextStyleKey } from "./rich-text-selection";
|
|
25
33
|
|
|
26
34
|
export interface SlideStyleSnapshot {
|
|
35
|
+
/** Omitted snapshots are existing object snapshots for backward compatibility. */
|
|
36
|
+
mode?: "object";
|
|
27
37
|
selector: string;
|
|
28
38
|
label: string;
|
|
29
39
|
tagName: string;
|
|
@@ -50,10 +60,25 @@ export interface SlideStyleSnapshot {
|
|
|
50
60
|
borderColor: string;
|
|
51
61
|
paddingX: number;
|
|
52
62
|
paddingY: number;
|
|
63
|
+
zIndex: number;
|
|
53
64
|
textStyleScope?: "block" | "selection";
|
|
54
65
|
mixedTextStyles?: InlineTextStyleKey[];
|
|
55
66
|
}
|
|
56
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Slide backgrounds are a surface, rather than selectable canvas objects.
|
|
70
|
+
* The editor passes this mode while its Style panel is open without an object
|
|
71
|
+
* selection, so the inspector exposes only background-safe controls.
|
|
72
|
+
*/
|
|
73
|
+
export interface SlideBackgroundStyleSnapshot {
|
|
74
|
+
mode: "background";
|
|
75
|
+
backgroundColor: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type SlideStyleInspectorSnapshot =
|
|
79
|
+
| SlideStyleSnapshot
|
|
80
|
+
| SlideBackgroundStyleSnapshot;
|
|
81
|
+
|
|
57
82
|
export type SlideStylePatch = Partial<{
|
|
58
83
|
color: string;
|
|
59
84
|
backgroundColor: string;
|
|
@@ -74,8 +99,13 @@ export type SlideStylePatch = Partial<{
|
|
|
74
99
|
width: string;
|
|
75
100
|
height: string;
|
|
76
101
|
transform: string;
|
|
102
|
+
zIndex: string;
|
|
77
103
|
}>;
|
|
78
104
|
|
|
105
|
+
export type SlideBackgroundStylePatch = Required<
|
|
106
|
+
Pick<SlideStylePatch, "backgroundColor">
|
|
107
|
+
>;
|
|
108
|
+
|
|
79
109
|
function tokenPalette(
|
|
80
110
|
designSystem: DesignSystemData | undefined,
|
|
81
111
|
t: (key: string) => string,
|
|
@@ -138,6 +168,85 @@ function tokenPalette(
|
|
|
138
168
|
];
|
|
139
169
|
}
|
|
140
170
|
|
|
171
|
+
// `slide.background` holds either a raw CSS value or a Tailwind arbitrary
|
|
172
|
+
// class (`bg-[#000000]`), which SlideRenderer applies as a class rather than
|
|
173
|
+
// an inline style. The picker only speaks CSS colors, so unwrap the arbitrary
|
|
174
|
+
// form and report anything else (named utilities, gradients) as unreadable
|
|
175
|
+
// rather than guessing a hex the slide is not actually using.
|
|
176
|
+
function backgroundCssValue(background: string | undefined): string | null {
|
|
177
|
+
// SlideRenderer's own fallback when the field is unset.
|
|
178
|
+
if (!background) return "#000000";
|
|
179
|
+
const arbitrary = background.match(/^bg-\[(.+)\]$/);
|
|
180
|
+
if (arbitrary) return arbitrary[1].replace(/_/g, " ");
|
|
181
|
+
return background.startsWith("bg-") ? null : background;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Rendered in the style dock when no element is selected — otherwise the
|
|
186
|
+
* slide's own background is unreachable from the editor UI.
|
|
187
|
+
*/
|
|
188
|
+
export function SlideBackgroundInspector({
|
|
189
|
+
background,
|
|
190
|
+
designSystem,
|
|
191
|
+
className,
|
|
192
|
+
onChange,
|
|
193
|
+
onClose,
|
|
194
|
+
}: {
|
|
195
|
+
background: string | undefined;
|
|
196
|
+
designSystem?: DesignSystemData;
|
|
197
|
+
className?: string;
|
|
198
|
+
onChange: (background: string) => void;
|
|
199
|
+
onClose?: () => void;
|
|
200
|
+
}) {
|
|
201
|
+
const t = useT();
|
|
202
|
+
const documentColors = tokenPalette(designSystem, t).map(
|
|
203
|
+
(option) => option.value,
|
|
204
|
+
);
|
|
205
|
+
const solid = backgroundCssValue(background);
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<VisualInspectorPanel
|
|
209
|
+
title={t("styleInspector.title")}
|
|
210
|
+
subtitle={t("styleInspector.slide")}
|
|
211
|
+
className={className}
|
|
212
|
+
headerAction={
|
|
213
|
+
onClose ? (
|
|
214
|
+
<Button
|
|
215
|
+
type="button"
|
|
216
|
+
variant="ghost"
|
|
217
|
+
size="icon"
|
|
218
|
+
className="size-7 cursor-pointer text-muted-foreground hover:text-foreground"
|
|
219
|
+
onClick={onClose}
|
|
220
|
+
aria-label={t("styleInspector.close")}
|
|
221
|
+
>
|
|
222
|
+
<IconX className="size-3.5" />
|
|
223
|
+
</Button>
|
|
224
|
+
) : undefined
|
|
225
|
+
}
|
|
226
|
+
>
|
|
227
|
+
<VisualInspectorSection
|
|
228
|
+
title={
|
|
229
|
+
<span className="inline-flex items-center gap-1.5">
|
|
230
|
+
<IconDroplet className="size-3" />
|
|
231
|
+
{t("styleInspector.slideBackground")}
|
|
232
|
+
</span>
|
|
233
|
+
}
|
|
234
|
+
>
|
|
235
|
+
<VisualControlRow label={t("styleInspector.background")}>
|
|
236
|
+
<VisualColorPicker
|
|
237
|
+
label={t("styleInspector.slideBackground")}
|
|
238
|
+
value={solid ?? "#000000"}
|
|
239
|
+
mixed={solid === null}
|
|
240
|
+
mixedLabel={t("styleInspector.mixed")}
|
|
241
|
+
documentColors={documentColors}
|
|
242
|
+
onChange={onChange}
|
|
243
|
+
/>
|
|
244
|
+
</VisualControlRow>
|
|
245
|
+
</VisualInspectorSection>
|
|
246
|
+
</VisualInspectorPanel>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
141
250
|
function formatValue(value: number) {
|
|
142
251
|
return Number.isInteger(value)
|
|
143
252
|
? String(value)
|
|
@@ -153,21 +262,79 @@ export function SlideStyleInspector({
|
|
|
153
262
|
designSystem,
|
|
154
263
|
className,
|
|
155
264
|
onChange,
|
|
265
|
+
onArrange,
|
|
156
266
|
onClose,
|
|
157
267
|
}: {
|
|
158
|
-
snapshot:
|
|
268
|
+
snapshot: SlideStyleInspectorSnapshot;
|
|
159
269
|
designSystem?: DesignSystemData;
|
|
160
270
|
className?: string;
|
|
161
271
|
onChange: (patch: SlideStylePatch) => void;
|
|
272
|
+
/** Bring-to-front / send-to-back for the selected freeform object. Omitted
|
|
273
|
+
* (or the snapshot not being a freeform object) hides the Arrange row. */
|
|
274
|
+
onArrange?: (target: "front" | "back") => void;
|
|
162
275
|
onClose: () => void;
|
|
163
276
|
}) {
|
|
164
277
|
const t = useT();
|
|
165
278
|
const palette = tokenPalette(designSystem, t);
|
|
166
279
|
const documentColors = palette.map((option) => option.value);
|
|
167
|
-
const mixedTextStyles = snapshot.mixedTextStyles ?? [];
|
|
168
280
|
const inlineEditSurfaceProps = {
|
|
169
281
|
"data-slide-inline-edit-surface": "true",
|
|
170
282
|
};
|
|
283
|
+
const inspectorClassName = cn(
|
|
284
|
+
"slide-style-inspector h-full w-full rounded-none border-0 bg-transparent text-foreground shadow-none backdrop-blur-none",
|
|
285
|
+
className,
|
|
286
|
+
);
|
|
287
|
+
const headerAction = (
|
|
288
|
+
<Button
|
|
289
|
+
type="button"
|
|
290
|
+
variant="ghost"
|
|
291
|
+
size="icon"
|
|
292
|
+
className="size-7 shrink-0 text-muted-foreground hover:text-foreground"
|
|
293
|
+
onClick={onClose}
|
|
294
|
+
aria-label={t("styleInspector.close")}
|
|
295
|
+
>
|
|
296
|
+
<IconX className="size-3.5" />
|
|
297
|
+
</Button>
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
if (snapshot.mode === "background") {
|
|
301
|
+
return (
|
|
302
|
+
<VisualInspectorPanel
|
|
303
|
+
title={t("styleInspector.title")}
|
|
304
|
+
subtitle={t("styleInspector.background")}
|
|
305
|
+
className={inspectorClassName}
|
|
306
|
+
headerAction={headerAction}
|
|
307
|
+
>
|
|
308
|
+
<VisualInspectorSection
|
|
309
|
+
title={
|
|
310
|
+
<span className="inline-flex items-center gap-1.5">
|
|
311
|
+
<IconDroplet className="size-3.5" />
|
|
312
|
+
{t("styleInspector.fill")}
|
|
313
|
+
</span>
|
|
314
|
+
}
|
|
315
|
+
className="slides-inspector-section"
|
|
316
|
+
>
|
|
317
|
+
<VisualControlRow
|
|
318
|
+
label={t("styleInspector.color")}
|
|
319
|
+
className="slides-inspector-control"
|
|
320
|
+
>
|
|
321
|
+
<VisualColorPicker
|
|
322
|
+
label={t("styleInspector.fill")}
|
|
323
|
+
value={snapshot.backgroundColor}
|
|
324
|
+
documentColors={documentColors}
|
|
325
|
+
allowTransparent
|
|
326
|
+
variant="filled"
|
|
327
|
+
className="rounded-sm bg-[var(--slides-inspector-control-background)] hover:bg-[var(--slides-inspector-control-background)]"
|
|
328
|
+
contentProps={inlineEditSurfaceProps}
|
|
329
|
+
onChange={(value) => onChange({ backgroundColor: value })}
|
|
330
|
+
/>
|
|
331
|
+
</VisualControlRow>
|
|
332
|
+
</VisualInspectorSection>
|
|
333
|
+
</VisualInspectorPanel>
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const mixedTextStyles = snapshot.mixedTextStyles ?? [];
|
|
171
338
|
const targetLabel =
|
|
172
339
|
snapshot.textPreview || snapshot.label || snapshot.tagName.toUpperCase();
|
|
173
340
|
const horizontalAlignment =
|
|
@@ -208,22 +375,8 @@ export function SlideStyleInspector({
|
|
|
208
375
|
<VisualInspectorPanel
|
|
209
376
|
title={t("styleInspector.title")}
|
|
210
377
|
subtitle={targetLabel}
|
|
211
|
-
className={
|
|
212
|
-
|
|
213
|
-
className,
|
|
214
|
-
)}
|
|
215
|
-
headerAction={
|
|
216
|
-
<Button
|
|
217
|
-
type="button"
|
|
218
|
-
variant="ghost"
|
|
219
|
-
size="icon"
|
|
220
|
-
className="size-7 shrink-0 text-muted-foreground hover:text-foreground"
|
|
221
|
-
onClick={onClose}
|
|
222
|
-
aria-label={t("styleInspector.close")}
|
|
223
|
-
>
|
|
224
|
-
<IconX className="size-3.5" />
|
|
225
|
-
</Button>
|
|
226
|
-
}
|
|
378
|
+
className={inspectorClassName}
|
|
379
|
+
headerAction={headerAction}
|
|
227
380
|
>
|
|
228
381
|
{snapshot.isAbsolute ? (
|
|
229
382
|
<VisualInspectorSection
|
|
@@ -268,12 +421,16 @@ export function SlideStyleInspector({
|
|
|
268
421
|
<div className="grid grid-cols-2 gap-2">
|
|
269
422
|
<VisualScrubInput
|
|
270
423
|
label={t("styleInspector.x")}
|
|
424
|
+
icon={null}
|
|
425
|
+
labelClassName="w-8 justify-center"
|
|
271
426
|
value={snapshot.x}
|
|
272
427
|
unit="px"
|
|
273
428
|
onChange={(x) => onChange({ left: `${formatValue(x)}px` })}
|
|
274
429
|
/>
|
|
275
430
|
<VisualScrubInput
|
|
276
431
|
label={t("styleInspector.y")}
|
|
432
|
+
icon={null}
|
|
433
|
+
labelClassName="w-8 justify-center"
|
|
277
434
|
value={snapshot.y}
|
|
278
435
|
unit="px"
|
|
279
436
|
onChange={(y) => onChange({ top: `${formatValue(y)}px` })}
|
|
@@ -281,6 +438,8 @@ export function SlideStyleInspector({
|
|
|
281
438
|
</div>
|
|
282
439
|
<VisualScrubInput
|
|
283
440
|
label={t("styleInspector.rotation")}
|
|
441
|
+
icon={IconAngle}
|
|
442
|
+
prefix="icon"
|
|
284
443
|
value={snapshot.rotation}
|
|
285
444
|
min={-360}
|
|
286
445
|
max={360}
|
|
@@ -292,6 +451,46 @@ export function SlideStyleInspector({
|
|
|
292
451
|
</VisualInspectorSection>
|
|
293
452
|
) : null}
|
|
294
453
|
|
|
454
|
+
{snapshot.isAbsolute && onArrange ? (
|
|
455
|
+
<VisualInspectorSection
|
|
456
|
+
title={
|
|
457
|
+
<span className="inline-flex items-center gap-1.5">
|
|
458
|
+
<IconStackFront className="size-3.5" />
|
|
459
|
+
{t("styleInspector.arrange")}
|
|
460
|
+
</span>
|
|
461
|
+
}
|
|
462
|
+
className="slides-inspector-section"
|
|
463
|
+
>
|
|
464
|
+
<VisualControlRow
|
|
465
|
+
label={t("styleInspector.order")}
|
|
466
|
+
className="slides-inspector-control"
|
|
467
|
+
>
|
|
468
|
+
<div className="flex items-center gap-1">
|
|
469
|
+
<Button
|
|
470
|
+
type="button"
|
|
471
|
+
variant="ghost"
|
|
472
|
+
size="icon"
|
|
473
|
+
className="size-7 cursor-pointer rounded-sm bg-[var(--slides-inspector-control-background)] text-muted-foreground hover:bg-[var(--slides-inspector-control-background)] hover:text-foreground"
|
|
474
|
+
onClick={() => onArrange("back")}
|
|
475
|
+
aria-label={t("styleInspector.sendToBack")}
|
|
476
|
+
>
|
|
477
|
+
<IconStackBack className="size-3.5" />
|
|
478
|
+
</Button>
|
|
479
|
+
<Button
|
|
480
|
+
type="button"
|
|
481
|
+
variant="ghost"
|
|
482
|
+
size="icon"
|
|
483
|
+
className="size-7 cursor-pointer rounded-sm bg-[var(--slides-inspector-control-background)] text-muted-foreground hover:bg-[var(--slides-inspector-control-background)] hover:text-foreground"
|
|
484
|
+
onClick={() => onArrange("front")}
|
|
485
|
+
aria-label={t("styleInspector.bringToFront")}
|
|
486
|
+
>
|
|
487
|
+
<IconStackFront className="size-3.5" />
|
|
488
|
+
</Button>
|
|
489
|
+
</div>
|
|
490
|
+
</VisualControlRow>
|
|
491
|
+
</VisualInspectorSection>
|
|
492
|
+
) : null}
|
|
493
|
+
|
|
295
494
|
<VisualInspectorSection
|
|
296
495
|
title={
|
|
297
496
|
<span className="inline-flex items-center gap-1.5">
|
|
@@ -304,6 +503,8 @@ export function SlideStyleInspector({
|
|
|
304
503
|
<div className="grid grid-cols-2 gap-2">
|
|
305
504
|
<VisualScrubInput
|
|
306
505
|
label={t("styleInspector.width")}
|
|
506
|
+
icon={IconArrowAutofitWidth}
|
|
507
|
+
prefix="icon"
|
|
307
508
|
value={snapshot.width}
|
|
308
509
|
min={0}
|
|
309
510
|
unit="px"
|
|
@@ -311,6 +512,8 @@ export function SlideStyleInspector({
|
|
|
311
512
|
/>
|
|
312
513
|
<VisualScrubInput
|
|
313
514
|
label={t("styleInspector.height")}
|
|
515
|
+
icon={IconArrowAutofitHeight}
|
|
516
|
+
prefix="icon"
|
|
314
517
|
value={snapshot.height}
|
|
315
518
|
min={0}
|
|
316
519
|
unit="px"
|
|
@@ -333,6 +536,8 @@ export function SlideStyleInspector({
|
|
|
333
536
|
<div className="grid grid-cols-2 gap-2">
|
|
334
537
|
<VisualScrubInput
|
|
335
538
|
label={t("styleInspector.opacity")}
|
|
539
|
+
icon={IconGridDots}
|
|
540
|
+
prefix="icon"
|
|
336
541
|
value={snapshot.opacity}
|
|
337
542
|
min={0}
|
|
338
543
|
max={100}
|
|
@@ -342,6 +547,8 @@ export function SlideStyleInspector({
|
|
|
342
547
|
/>
|
|
343
548
|
<VisualScrubInput
|
|
344
549
|
label={t("styleInspector.cornerRadius")}
|
|
550
|
+
icon={IconBorderRadius}
|
|
551
|
+
prefix="icon"
|
|
345
552
|
value={snapshot.borderRadius}
|
|
346
553
|
min={0}
|
|
347
554
|
max={96}
|
|
@@ -396,6 +603,8 @@ export function SlideStyleInspector({
|
|
|
396
603
|
>
|
|
397
604
|
<VisualScrubInput
|
|
398
605
|
label={t("styleInspector.strokeWeight")}
|
|
606
|
+
icon={IconBorderStyle}
|
|
607
|
+
prefix="icon"
|
|
399
608
|
value={snapshot.borderWidth}
|
|
400
609
|
min={0}
|
|
401
610
|
max={16}
|
|
@@ -449,6 +658,8 @@ export function SlideStyleInspector({
|
|
|
449
658
|
<div className="grid grid-cols-2 gap-2">
|
|
450
659
|
<VisualScrubInput
|
|
451
660
|
label={t("styleInspector.size")}
|
|
661
|
+
icon={IconLetterCase}
|
|
662
|
+
prefix="icon"
|
|
452
663
|
value={snapshot.fontSize}
|
|
453
664
|
min={8}
|
|
454
665
|
max={160}
|
|
@@ -461,6 +672,8 @@ export function SlideStyleInspector({
|
|
|
461
672
|
/>
|
|
462
673
|
<VisualScrubInput
|
|
463
674
|
label={t("styleInspector.line")}
|
|
675
|
+
icon={IconArrowAutofitHeight}
|
|
676
|
+
prefix="icon"
|
|
464
677
|
value={snapshot.lineHeight}
|
|
465
678
|
min={0.8}
|
|
466
679
|
max={3}
|
|
@@ -512,6 +725,8 @@ export function SlideStyleInspector({
|
|
|
512
725
|
<div className="grid grid-cols-2 gap-2">
|
|
513
726
|
<VisualScrubInput
|
|
514
727
|
label={t("styleInspector.horizontal")}
|
|
728
|
+
icon={IconSpacingHorizontal}
|
|
729
|
+
prefix="icon"
|
|
515
730
|
value={snapshot.paddingX}
|
|
516
731
|
min={0}
|
|
517
732
|
max={120}
|
|
@@ -526,6 +741,8 @@ export function SlideStyleInspector({
|
|
|
526
741
|
/>
|
|
527
742
|
<VisualScrubInput
|
|
528
743
|
label={t("styleInspector.vertical")}
|
|
744
|
+
icon={IconSpacingVertical}
|
|
745
|
+
prefix="icon"
|
|
529
746
|
value={snapshot.paddingY}
|
|
530
747
|
min={0}
|
|
531
748
|
max={120}
|
|
@@ -7,6 +7,7 @@ interface SpeakerNotesPanelProps {
|
|
|
7
7
|
onChange: (notes: string) => void;
|
|
8
8
|
slideIndex: number;
|
|
9
9
|
slideCount: number;
|
|
10
|
+
readOnly?: boolean;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const MIN_NOTES_HEIGHT = 72;
|
|
@@ -22,6 +23,7 @@ export function SpeakerNotesPanel({
|
|
|
22
23
|
onChange,
|
|
23
24
|
slideIndex,
|
|
24
25
|
slideCount,
|
|
26
|
+
readOnly = false,
|
|
25
27
|
}: SpeakerNotesPanelProps) {
|
|
26
28
|
const t = useT();
|
|
27
29
|
const [expanded, setExpanded] = useState(() => {
|
|
@@ -105,7 +107,8 @@ export function SpeakerNotesPanel({
|
|
|
105
107
|
<textarea
|
|
106
108
|
value={notes || ""}
|
|
107
109
|
onChange={(e) => onChange(e.target.value)}
|
|
108
|
-
|
|
110
|
+
readOnly={readOnly}
|
|
111
|
+
placeholder={readOnly ? undefined : t("raw.addSpeakerNotes")}
|
|
109
112
|
className="h-full w-full resize-none bg-transparent font-mono text-xs text-muted-foreground outline-none placeholder:text-muted-foreground/70"
|
|
110
113
|
/>
|
|
111
114
|
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createSlidesCanvasGestureController,
|
|
3
|
+
createSlidesCanvasInteractionCore,
|
|
4
|
+
isWithinSlidesCanvasEdgeMoveBand,
|
|
5
|
+
resolveSlidesCanvasPointerIntent,
|
|
6
|
+
slidesCanvasInteractionCore,
|
|
7
|
+
SLIDES_CANVAS_EDGE_MOVE_BAND,
|
|
8
|
+
type SlidesCanvasHtmlMutationAdapter,
|
|
9
|
+
type SlidesCanvasGestureAdapter,
|
|
10
|
+
type SlidesCanvasPointerIntent,
|
|
11
|
+
} from "./slides-canvas-adapter";
|
package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCanvasGestureController,
|
|
3
|
+
createCanvasInteractionCore,
|
|
4
|
+
type CanvasGestureAdapter,
|
|
5
|
+
type CanvasInteractionAdapter,
|
|
6
|
+
} from "@agent-native/toolkit/canvas-interactions";
|
|
7
|
+
|
|
8
|
+
import { MIN_SLIDE_OBJECT_SIZE } from "../slide-object-interactions";
|
|
9
|
+
|
|
10
|
+
export const SLIDES_CANVAS_EDGE_MOVE_BAND = 8;
|
|
11
|
+
|
|
12
|
+
export function isWithinSlidesCanvasEdgeMoveBand(
|
|
13
|
+
rect: Pick<DOMRect, "left" | "right" | "top" | "bottom" | "width" | "height">,
|
|
14
|
+
clientX: number,
|
|
15
|
+
clientY: number,
|
|
16
|
+
): boolean {
|
|
17
|
+
// Tiny labels still need a usable center click target. Cap the move band at
|
|
18
|
+
// one quarter of either dimension so its opposite edges never consume it.
|
|
19
|
+
const edgeBand = Math.min(
|
|
20
|
+
SLIDES_CANVAS_EDGE_MOVE_BAND,
|
|
21
|
+
rect.width / 4,
|
|
22
|
+
rect.height / 4,
|
|
23
|
+
);
|
|
24
|
+
const outerBand = edgeBand / 2;
|
|
25
|
+
const withinExpandedBounds =
|
|
26
|
+
clientX >= rect.left - outerBand &&
|
|
27
|
+
clientX <= rect.right + outerBand &&
|
|
28
|
+
clientY >= rect.top - outerBand &&
|
|
29
|
+
clientY <= rect.bottom + outerBand;
|
|
30
|
+
if (!withinExpandedBounds) return false;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
Math.abs(clientX - rect.left) <= edgeBand ||
|
|
34
|
+
Math.abs(clientX - rect.right) <= edgeBand ||
|
|
35
|
+
Math.abs(clientY - rect.top) <= edgeBand ||
|
|
36
|
+
Math.abs(clientY - rect.bottom) <= edgeBand
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Slides owns its persistence adapter: it translates shared semantic commands
|
|
42
|
+
* into mutations of the selected slide's HTML. Toolkit remains unaware of the
|
|
43
|
+
* DOM, coordinate containers, and the one-write-per-gesture boundary.
|
|
44
|
+
*/
|
|
45
|
+
export type SlidesCanvasHtmlMutationAdapter = CanvasInteractionAdapter<string>;
|
|
46
|
+
export type SlidesCanvasGestureAdapter = CanvasGestureAdapter<string>;
|
|
47
|
+
|
|
48
|
+
const slidesCanvasInteractionConfig = {
|
|
49
|
+
textEditing: {
|
|
50
|
+
activation: "single-click" as const,
|
|
51
|
+
escapeBehavior: "select-object" as const,
|
|
52
|
+
},
|
|
53
|
+
drag: {
|
|
54
|
+
threshold: 2,
|
|
55
|
+
duplicateModifier: "alt" as const,
|
|
56
|
+
},
|
|
57
|
+
nudge: {
|
|
58
|
+
amount: 1,
|
|
59
|
+
acceleratedAmount: 10,
|
|
60
|
+
},
|
|
61
|
+
minSize: MIN_SLIDE_OBJECT_SIZE,
|
|
62
|
+
capabilities: {
|
|
63
|
+
multiSelection: true,
|
|
64
|
+
snapping: false,
|
|
65
|
+
alignment: false,
|
|
66
|
+
distribution: false,
|
|
67
|
+
grouping: false,
|
|
68
|
+
rotation: false,
|
|
69
|
+
marquee: true,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export function createSlidesCanvasInteractionCore(
|
|
74
|
+
adapter?: SlidesCanvasHtmlMutationAdapter,
|
|
75
|
+
) {
|
|
76
|
+
return createCanvasInteractionCore(slidesCanvasInteractionConfig, adapter);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Creates one shared controller per live Slides pointer gesture. */
|
|
80
|
+
export function createSlidesCanvasGestureController(
|
|
81
|
+
adapter: SlidesCanvasGestureAdapter,
|
|
82
|
+
) {
|
|
83
|
+
return createCanvasGestureController({
|
|
84
|
+
...slidesCanvasInteractionConfig,
|
|
85
|
+
adapter,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Shared Slides policy for callers that do not need an HTML command adapter. */
|
|
90
|
+
export const slidesCanvasInteractionCore = createSlidesCanvasInteractionCore();
|
|
91
|
+
|
|
92
|
+
export type SlidesCanvasPointerIntent =
|
|
93
|
+
| "edit-text"
|
|
94
|
+
| "move-object-body"
|
|
95
|
+
| "move-object-perimeter"
|
|
96
|
+
| "none";
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Slides supplies hit testing and this policy decision, while the shared
|
|
100
|
+
* gesture controller owns threshold, coordinate, modifier, and resize math.
|
|
101
|
+
* A selected object's body begins a thresholded move candidate. An unmoved
|
|
102
|
+
* press still falls through to the click handler for text editing, while a
|
|
103
|
+
* real drag consumes that trailing click.
|
|
104
|
+
*/
|
|
105
|
+
export function resolveSlidesCanvasPointerIntent({
|
|
106
|
+
hasSelectedObject,
|
|
107
|
+
targetWithinSelectedObject,
|
|
108
|
+
targetContainsSelectedObject,
|
|
109
|
+
pointerWithinMoveBand,
|
|
110
|
+
targetIsEditableText,
|
|
111
|
+
}: {
|
|
112
|
+
hasSelectedObject: boolean;
|
|
113
|
+
targetWithinSelectedObject: boolean;
|
|
114
|
+
targetContainsSelectedObject: boolean;
|
|
115
|
+
pointerWithinMoveBand: boolean;
|
|
116
|
+
targetIsEditableText: boolean;
|
|
117
|
+
}): SlidesCanvasPointerIntent {
|
|
118
|
+
if (
|
|
119
|
+
hasSelectedObject &&
|
|
120
|
+
(targetWithinSelectedObject || targetContainsSelectedObject) &&
|
|
121
|
+
pointerWithinMoveBand
|
|
122
|
+
) {
|
|
123
|
+
return "move-object-perimeter";
|
|
124
|
+
}
|
|
125
|
+
if (hasSelectedObject && targetWithinSelectedObject) {
|
|
126
|
+
return "move-object-body";
|
|
127
|
+
}
|
|
128
|
+
return targetIsEditableText ? "edit-text" : "none";
|
|
129
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export interface SelectionOverlayMeasurement {
|
|
2
|
+
key: string;
|
|
3
|
+
rect: DOMRect;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface SelectionOverlayMeasurementIdentity {
|
|
7
|
+
slideId: string;
|
|
8
|
+
content: string;
|
|
9
|
+
objectId: string | null;
|
|
10
|
+
selector: string | null;
|
|
11
|
+
path: number[] | null;
|
|
12
|
+
canvasZoom: number;
|
|
13
|
+
stylePanelOpen: boolean;
|
|
14
|
+
revision: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The portal paints in viewport coordinates. Its measurement is only valid
|
|
19
|
+
* for this exact rendered selection and canvas geometry.
|
|
20
|
+
*/
|
|
21
|
+
export function createSelectionOverlayMeasurementKey({
|
|
22
|
+
slideId,
|
|
23
|
+
content,
|
|
24
|
+
objectId,
|
|
25
|
+
selector,
|
|
26
|
+
path,
|
|
27
|
+
canvasZoom,
|
|
28
|
+
stylePanelOpen,
|
|
29
|
+
revision,
|
|
30
|
+
}: SelectionOverlayMeasurementIdentity): string {
|
|
31
|
+
return JSON.stringify([
|
|
32
|
+
slideId,
|
|
33
|
+
content,
|
|
34
|
+
objectId,
|
|
35
|
+
selector,
|
|
36
|
+
path,
|
|
37
|
+
canvasZoom,
|
|
38
|
+
stylePanelOpen,
|
|
39
|
+
revision,
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** AutoFit only depends on the rendered slide, not editor-only canvas chrome. */
|
|
44
|
+
export function createSelectionOverlayAutofitKey(
|
|
45
|
+
slideId: string,
|
|
46
|
+
content: string,
|
|
47
|
+
): string {
|
|
48
|
+
return JSON.stringify([slideId, content]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function currentSelectionOverlayRect(
|
|
52
|
+
measurement: SelectionOverlayMeasurement | null,
|
|
53
|
+
currentKey: string,
|
|
54
|
+
): DOMRect | null {
|
|
55
|
+
return measurement?.key === currentKey ? measurement.rect : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isSelectionOverlayAutofitSettled(
|
|
59
|
+
settledAutofitKey: string | null,
|
|
60
|
+
canvasAutofitKey: string,
|
|
61
|
+
): boolean {
|
|
62
|
+
return settledAutofitKey === canvasAutofitKey;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function isSelectionOverlayOnActiveSlide(
|
|
66
|
+
selectedSlideId: string | null,
|
|
67
|
+
activeSlideId: string,
|
|
68
|
+
): boolean {
|
|
69
|
+
return selectedSlideId === activeSlideId;
|
|
70
|
+
}
|