@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
|
@@ -58,6 +58,10 @@ type GranularOp =
|
|
|
58
58
|
| { op: "full-replace"; deck: Deck };
|
|
59
59
|
|
|
60
60
|
export type PatchDeckOp = Exclude<GranularOp, { op: "full-replace" }>;
|
|
61
|
+
export type DeckReloadStatus = "loaded" | "failed" | "stale";
|
|
62
|
+
export interface UpdateSlideOptions {
|
|
63
|
+
persistence?: "debounced" | "immediate";
|
|
64
|
+
}
|
|
61
65
|
|
|
62
66
|
// ---------------------------------------------------------------------------
|
|
63
67
|
// Inverse-op undo
|
|
@@ -164,6 +168,7 @@ interface DeckContextType {
|
|
|
164
168
|
updates: Partial<Omit<Deck, "id" | "createdAt">>,
|
|
165
169
|
) => void;
|
|
166
170
|
reloadDecks: () => Promise<void>;
|
|
171
|
+
reloadDecksWithStatus: () => Promise<DeckReloadStatus>;
|
|
167
172
|
getDeck: (id: string) => Deck | undefined;
|
|
168
173
|
addSlide: (
|
|
169
174
|
deckId: string,
|
|
@@ -174,6 +179,7 @@ interface DeckContextType {
|
|
|
174
179
|
deckId: string,
|
|
175
180
|
slideId: string,
|
|
176
181
|
updates: Partial<Omit<Slide, "id">>,
|
|
182
|
+
options?: UpdateSlideOptions,
|
|
177
183
|
) => void;
|
|
178
184
|
deleteSlide: (deckId: string, slideId: string) => void;
|
|
179
185
|
duplicateSlide: (deckId: string, slideId: string) => void;
|
|
@@ -260,7 +266,13 @@ function normalizeActionDeck(value: unknown): Deck | null {
|
|
|
260
266
|
// uncommitted?" for the indicator.
|
|
261
267
|
const pendingSaves = new Map<string, ReturnType<typeof setTimeout>>();
|
|
262
268
|
const inFlightSaves = new Set<string>();
|
|
269
|
+
const inFlightSaveChains = new Map<string, Promise<void>>();
|
|
270
|
+
const immediateFlushRequests = new Set<string>();
|
|
271
|
+
const deckSaveRetryAttempts = new Map<string, number>();
|
|
272
|
+
const failedSaveDecks = new Set<string>();
|
|
263
273
|
const saveStateListeners = new Set<() => void>();
|
|
274
|
+
const MAX_DECK_SAVE_RETRIES = 2;
|
|
275
|
+
const DECK_SAVE_RETRY_BASE_MS = 250;
|
|
264
276
|
|
|
265
277
|
// Per-deck queue of granular ops waiting to be flushed. Keys are deck IDs.
|
|
266
278
|
// Ops are appended by enqueueDeckOp and drained when the debounce fires.
|
|
@@ -273,7 +285,8 @@ const pendingOpsQueue = new Map<string, GranularOp[]>();
|
|
|
273
285
|
let cachedSnapshot: { saving: boolean } = { saving: false };
|
|
274
286
|
|
|
275
287
|
function recomputeSnapshot() {
|
|
276
|
-
const saving =
|
|
288
|
+
const saving =
|
|
289
|
+
pendingSaves.size > 0 || inFlightSaves.size > 0 || pendingOpsQueue.size > 0;
|
|
277
290
|
if (saving !== cachedSnapshot.saving) {
|
|
278
291
|
cachedSnapshot = { saving };
|
|
279
292
|
}
|
|
@@ -322,10 +335,118 @@ function deckPayload(deck: Deck): Record<string, unknown> {
|
|
|
322
335
|
* the `save-deck` action is called first, then any trailing granular ops are
|
|
323
336
|
* sent through `patch-deck`.
|
|
324
337
|
*/
|
|
325
|
-
function
|
|
326
|
-
|
|
338
|
+
async function persistDeckOps(deckId: string, ops: GranularOp[]) {
|
|
339
|
+
if (ops[0].op === "full-replace") {
|
|
340
|
+
// Legacy full-deck write — used by undo/redo and setDeckSlides.
|
|
341
|
+
// `callAction` bounds it so a stalled save can't wedge `inFlightSaves`
|
|
342
|
+
// forever (its `finally` cleanup below only runs once this await
|
|
343
|
+
// settles; an AbortError from the timeout still reaches it).
|
|
344
|
+
const deck = ops[0].deck;
|
|
345
|
+
await callAction(
|
|
346
|
+
"save-deck",
|
|
347
|
+
{ deckId, deck: deckPayload(deck) },
|
|
348
|
+
{ method: "PUT" },
|
|
349
|
+
);
|
|
350
|
+
const trailingOps = ops.slice(1) as PatchDeckOp[];
|
|
351
|
+
if (trailingOps.length > 0) {
|
|
352
|
+
await callAction("patch-deck", {
|
|
353
|
+
deckId,
|
|
354
|
+
operations: trailingOps,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
await callAction("patch-deck", {
|
|
359
|
+
deckId,
|
|
360
|
+
operations: ops as PatchDeckOp[],
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Drain the current operation batch behind every earlier batch for this deck.
|
|
367
|
+
* Slide content patches replace the full HTML field, so overlapping requests
|
|
368
|
+
* could otherwise complete out of order and let a stale drag overwrite a
|
|
369
|
+
* newer resize.
|
|
370
|
+
*/
|
|
371
|
+
function drainPendingDeckOps(deckId: string): Promise<void> {
|
|
372
|
+
const timer = pendingSaves.get(deckId);
|
|
373
|
+
if (timer) clearTimeout(timer);
|
|
374
|
+
pendingSaves.delete(deckId);
|
|
375
|
+
|
|
376
|
+
const active = inFlightSaveChains.get(deckId);
|
|
377
|
+
if (active) {
|
|
378
|
+
immediateFlushRequests.add(deckId);
|
|
379
|
+
notifySaveListeners();
|
|
380
|
+
return active;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const ops = pendingOpsQueue.get(deckId) ?? [];
|
|
384
|
+
pendingOpsQueue.delete(deckId);
|
|
385
|
+
if (ops.length === 0) {
|
|
386
|
+
notifySaveListeners();
|
|
387
|
+
return Promise.resolve();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
inFlightSaves.add(deckId);
|
|
391
|
+
let succeeded = false;
|
|
392
|
+
const next = persistDeckOps(deckId, ops)
|
|
393
|
+
.then(() => {
|
|
394
|
+
succeeded = true;
|
|
395
|
+
deckSaveRetryAttempts.delete(deckId);
|
|
396
|
+
failedSaveDecks.delete(deckId);
|
|
397
|
+
})
|
|
398
|
+
.catch((err) => {
|
|
399
|
+
console.error(`Failed to save deck ${deckId}:`, err);
|
|
400
|
+
const pending = pendingOpsQueue.get(deckId) ?? [];
|
|
401
|
+
pendingOpsQueue.set(deckId, [...ops, ...pending]);
|
|
402
|
+
const attempt = (deckSaveRetryAttempts.get(deckId) ?? 0) + 1;
|
|
403
|
+
deckSaveRetryAttempts.set(deckId, attempt);
|
|
404
|
+
immediateFlushRequests.delete(deckId);
|
|
405
|
+
const pendingTimer = pendingSaves.get(deckId);
|
|
406
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
407
|
+
pendingSaves.delete(deckId);
|
|
408
|
+
if (attempt <= MAX_DECK_SAVE_RETRIES) {
|
|
409
|
+
const retryTimer = setTimeout(
|
|
410
|
+
() => {
|
|
411
|
+
void drainPendingDeckOps(deckId);
|
|
412
|
+
},
|
|
413
|
+
DECK_SAVE_RETRY_BASE_MS * 2 ** (attempt - 1),
|
|
414
|
+
);
|
|
415
|
+
pendingSaves.set(deckId, retryTimer);
|
|
416
|
+
} else {
|
|
417
|
+
failedSaveDecks.add(deckId);
|
|
418
|
+
}
|
|
419
|
+
})
|
|
420
|
+
.finally(() => {
|
|
421
|
+
if (inFlightSaveChains.get(deckId) === next) {
|
|
422
|
+
inFlightSaveChains.delete(deckId);
|
|
423
|
+
inFlightSaves.delete(deckId);
|
|
424
|
+
const flushImmediately = immediateFlushRequests.delete(deckId);
|
|
425
|
+
notifySaveListeners();
|
|
426
|
+
if (succeeded && flushImmediately) {
|
|
427
|
+
void drainPendingDeckOps(deckId);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
inFlightSaveChains.set(deckId, next);
|
|
432
|
+
notifySaveListeners();
|
|
433
|
+
return next;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function enqueueDeckOp(
|
|
437
|
+
deckId: string,
|
|
438
|
+
op: GranularOp,
|
|
439
|
+
options?: { persistence?: "debounced" | "immediate" },
|
|
440
|
+
) {
|
|
327
441
|
const existing = pendingSaves.get(deckId);
|
|
328
442
|
if (existing) clearTimeout(existing);
|
|
443
|
+
if (
|
|
444
|
+
(deckSaveRetryAttempts.get(deckId) ?? 0) > MAX_DECK_SAVE_RETRIES &&
|
|
445
|
+
!inFlightSaveChains.has(deckId)
|
|
446
|
+
) {
|
|
447
|
+
deckSaveRetryAttempts.delete(deckId);
|
|
448
|
+
failedSaveDecks.delete(deckId);
|
|
449
|
+
}
|
|
329
450
|
|
|
330
451
|
if (op.op === "full-replace") {
|
|
331
452
|
// Discard any accumulated granular ops — this is a wholesale replacement
|
|
@@ -336,53 +457,15 @@ function enqueueDeckOp(deckId: string, op: GranularOp) {
|
|
|
336
457
|
pendingOpsQueue.set(deckId, queue);
|
|
337
458
|
}
|
|
338
459
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
460
|
+
if (options?.persistence === "immediate") {
|
|
461
|
+
void drainPendingDeckOps(deckId);
|
|
462
|
+
} else {
|
|
463
|
+
const timer = setTimeout(() => {
|
|
464
|
+
void drainPendingDeckOps(deckId);
|
|
465
|
+
}, 500);
|
|
466
|
+
pendingSaves.set(deckId, timer);
|
|
343
467
|
notifySaveListeners();
|
|
344
|
-
|
|
345
|
-
const ops = pendingOpsQueue.get(deckId) ?? [];
|
|
346
|
-
pendingOpsQueue.delete(deckId);
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
if (ops.length === 0) return;
|
|
350
|
-
|
|
351
|
-
if (ops[0].op === "full-replace") {
|
|
352
|
-
// Legacy full-deck write — used by undo/redo and setDeckSlides.
|
|
353
|
-
// `callAction` bounds it so a stalled save can't wedge `inFlightSaves`
|
|
354
|
-
// forever (its `finally` cleanup below only runs once this await
|
|
355
|
-
// settles; an AbortError from the timeout still reaches it).
|
|
356
|
-
const deck = ops[0].deck;
|
|
357
|
-
await callAction(
|
|
358
|
-
"save-deck",
|
|
359
|
-
{ deckId, deck: deckPayload(deck) },
|
|
360
|
-
{ method: "PUT" },
|
|
361
|
-
);
|
|
362
|
-
const trailingOps = ops.slice(1) as PatchDeckOp[];
|
|
363
|
-
if (trailingOps.length > 0) {
|
|
364
|
-
await callAction("patch-deck", {
|
|
365
|
-
deckId,
|
|
366
|
-
operations: trailingOps,
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
} else {
|
|
370
|
-
// Granular patch — concurrent-safe
|
|
371
|
-
await callAction("patch-deck", {
|
|
372
|
-
deckId,
|
|
373
|
-
operations: ops as PatchDeckOp[],
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
} catch (err) {
|
|
377
|
-
console.error(`Failed to save deck ${deckId}:`, err);
|
|
378
|
-
} finally {
|
|
379
|
-
inFlightSaves.delete(deckId);
|
|
380
|
-
notifySaveListeners();
|
|
381
|
-
}
|
|
382
|
-
}, 500);
|
|
383
|
-
|
|
384
|
-
pendingSaves.set(deckId, timer);
|
|
385
|
-
notifySaveListeners();
|
|
468
|
+
}
|
|
386
469
|
}
|
|
387
470
|
|
|
388
471
|
/**
|
|
@@ -468,6 +551,9 @@ function discardPendingDeckOps(deckId: string) {
|
|
|
468
551
|
if (timer) clearTimeout(timer);
|
|
469
552
|
pendingSaves.delete(deckId);
|
|
470
553
|
pendingOpsQueue.delete(deckId);
|
|
554
|
+
deckSaveRetryAttempts.delete(deckId);
|
|
555
|
+
failedSaveDecks.delete(deckId);
|
|
556
|
+
immediateFlushRequests.delete(deckId);
|
|
471
557
|
notifySaveListeners();
|
|
472
558
|
}
|
|
473
559
|
|
|
@@ -837,7 +923,8 @@ export function hasUncommittedDeckChanges(
|
|
|
837
923
|
return (
|
|
838
924
|
dirtyDeckIds.has(deckId) ||
|
|
839
925
|
pendingSaves.has(deckId) ||
|
|
840
|
-
inFlightSaves.has(deckId)
|
|
926
|
+
inFlightSaves.has(deckId) ||
|
|
927
|
+
failedSaveDecks.has(deckId)
|
|
841
928
|
);
|
|
842
929
|
}
|
|
843
930
|
|
|
@@ -1270,25 +1357,31 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1270
1357
|
[isNewerThanSnapshot],
|
|
1271
1358
|
);
|
|
1272
1359
|
|
|
1273
|
-
const
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
setLoadError(loaded === null);
|
|
1360
|
+
const reloadDecksWithStatus =
|
|
1361
|
+
useCallback(async (): Promise<DeckReloadStatus> => {
|
|
1362
|
+
const requestId = ++deckBaselineRequestIdRef.current;
|
|
1363
|
+
const createSeqAtRequest = localCreateSeqRef.current;
|
|
1364
|
+
const requestedOpenDeckId = currentOpenDeckIdFromWindow();
|
|
1365
|
+
const loaded = await fetchDecksForCurrentRoute();
|
|
1366
|
+
if (
|
|
1367
|
+
requestId !== deckBaselineRequestIdRef.current ||
|
|
1368
|
+
requestedOpenDeckId !== currentOpenDeckIdFromWindow()
|
|
1369
|
+
) {
|
|
1370
|
+
return "stale";
|
|
1285
1371
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1372
|
+
if (loaded === null) {
|
|
1373
|
+
setLoadError(true);
|
|
1374
|
+
return "failed";
|
|
1375
|
+
}
|
|
1376
|
+
lastExternalUpdateRef.current = Date.now();
|
|
1377
|
+
resetDeckBaseline(loaded, createSeqAtRequest);
|
|
1378
|
+
setLoadError(false);
|
|
1379
|
+
return "loaded";
|
|
1380
|
+
}, [resetDeckBaseline]);
|
|
1381
|
+
|
|
1382
|
+
const reloadDecks = useCallback(async () => {
|
|
1383
|
+
await reloadDecksWithStatus();
|
|
1384
|
+
}, [reloadDecksWithStatus]);
|
|
1292
1385
|
|
|
1293
1386
|
// Load decks from API on mount
|
|
1294
1387
|
useEffect(() => {
|
|
@@ -1435,7 +1528,11 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1435
1528
|
dirtyDeckIdsRef.current.delete(id);
|
|
1436
1529
|
// Only fall back to full-replace if no granular ops were enqueued
|
|
1437
1530
|
// for this deck (they handle the actual save).
|
|
1438
|
-
if (
|
|
1531
|
+
if (
|
|
1532
|
+
!pendingOpsQueue.has(id) &&
|
|
1533
|
+
!pendingSaves.has(id) &&
|
|
1534
|
+
!inFlightSaves.has(id)
|
|
1535
|
+
) {
|
|
1439
1536
|
const deck = decks.find((d) => d.id === id);
|
|
1440
1537
|
if (!deck) continue;
|
|
1441
1538
|
saveDeckToAPI(deck);
|
|
@@ -1750,7 +1847,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1750
1847
|
};
|
|
1751
1848
|
optimistic.slides = optimistic.slides.map((s) => ({
|
|
1752
1849
|
...s,
|
|
1753
|
-
id: nanoid(8)
|
|
1850
|
+
id: `slide-${nanoid(8)}`,
|
|
1754
1851
|
}));
|
|
1755
1852
|
|
|
1756
1853
|
// Track as pending so the poll doesn't wipe the optimistic deck before
|
|
@@ -1766,6 +1863,10 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1766
1863
|
deckId: sourceDeckId,
|
|
1767
1864
|
newId,
|
|
1768
1865
|
title,
|
|
1866
|
+
// The user can start editing the copy before this resolves, so the
|
|
1867
|
+
// persisted slides must carry the ids the optimistic ones already
|
|
1868
|
+
// have — otherwise those edits address slides the server never had.
|
|
1869
|
+
slideIds: optimistic.slides.map((s) => s.id),
|
|
1769
1870
|
},
|
|
1770
1871
|
).then(() => undefined);
|
|
1771
1872
|
pendingCreatePromisesRef.current.set(newId, duplicatePromise);
|
|
@@ -1941,7 +2042,12 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1941
2042
|
);
|
|
1942
2043
|
|
|
1943
2044
|
const updateSlide = useCallback(
|
|
1944
|
-
(
|
|
2045
|
+
(
|
|
2046
|
+
deckId: string,
|
|
2047
|
+
slideId: string,
|
|
2048
|
+
updates: Partial<Omit<Slide, "id">>,
|
|
2049
|
+
options?: UpdateSlideOptions,
|
|
2050
|
+
) => {
|
|
1945
2051
|
markDeckDirty(deckId);
|
|
1946
2052
|
const label = updates.layout
|
|
1947
2053
|
? "Change layout"
|
|
@@ -1965,7 +2071,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1965
2071
|
);
|
|
1966
2072
|
// Granular op — only this slide's changed fields reach the server.
|
|
1967
2073
|
const op: PatchDeckOp = { op: "patch-slide", slideId, fields: updates };
|
|
1968
|
-
enqueueDeckOp(deckId, op);
|
|
2074
|
+
enqueueDeckOp(deckId, op, options);
|
|
1969
2075
|
if (before) {
|
|
1970
2076
|
// Coalesce a burst of edits to the SAME slide's SAME field-set into one
|
|
1971
2077
|
// undo step (e.g. typing characters into inline text). Distinct
|
|
@@ -2121,6 +2227,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
2121
2227
|
deleteDeck,
|
|
2122
2228
|
updateDeck,
|
|
2123
2229
|
reloadDecks,
|
|
2230
|
+
reloadDecksWithStatus,
|
|
2124
2231
|
getDeck,
|
|
2125
2232
|
addSlide,
|
|
2126
2233
|
updateSlide,
|
|
@@ -61,6 +61,8 @@ button[title="Open agent sidebar"] {
|
|
|
61
61
|
--sidebar-accent-foreground: 0 0% 93%;
|
|
62
62
|
--sidebar-border: 0 0% 20%;
|
|
63
63
|
--sidebar-ring: 0 0% 50%;
|
|
64
|
+
|
|
65
|
+
--accent-cyan: 187 100% 50%;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
.light {
|
|
@@ -102,6 +104,9 @@ button[title="Open agent sidebar"] {
|
|
|
102
104
|
--sidebar-accent-foreground: 0 0% 10%;
|
|
103
105
|
--sidebar-border: 0 0% 90%;
|
|
104
106
|
--sidebar-ring: 0 0% 65%;
|
|
107
|
+
|
|
108
|
+
/* Darker than the dark-theme #00E5FF so text stays >= 4.5:1 against a white popover. */
|
|
109
|
+
--accent-cyan: 193 82% 31%;
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
/* Slides keeps the shared visual inspector behavior, but the dock needs the
|
|
@@ -109,6 +114,9 @@ button[title="Open agent sidebar"] {
|
|
|
109
114
|
.slide-style-inspector {
|
|
110
115
|
--slides-inspector-control-background: hsl(var(--muted) / 0.82);
|
|
111
116
|
--slides-inspector-divider: hsl(var(--border) / 0.7);
|
|
117
|
+
--design-editor-control-bg: var(--slides-inspector-control-background);
|
|
118
|
+
--design-editor-control-border: transparent;
|
|
119
|
+
--design-editor-accent-color: #609ff8;
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
.slide-style-inspector > div:first-child {
|
|
@@ -1142,6 +1150,103 @@ button[title="Open agent sidebar"] {
|
|
|
1142
1150
|
background: rgba(96, 159, 248, 0.35);
|
|
1143
1151
|
}
|
|
1144
1152
|
|
|
1153
|
+
/* Google Slides-style object selection chrome. The edge hit targets are wider
|
|
1154
|
+
than their visible bars, but both centers sit on the 1px outline rather than
|
|
1155
|
+
drifting into the selected object through the outline's border box. */
|
|
1156
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle] {
|
|
1157
|
+
box-sizing: border-box;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="nw"],
|
|
1161
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="ne"],
|
|
1162
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="sw"],
|
|
1163
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="se"],
|
|
1164
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle-bar="true"] {
|
|
1165
|
+
border: 1px solid #609ff8;
|
|
1166
|
+
background: #fff;
|
|
1167
|
+
box-shadow: none;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="nw"],
|
|
1171
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="ne"],
|
|
1172
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="sw"],
|
|
1173
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="se"] {
|
|
1174
|
+
width: 7px;
|
|
1175
|
+
height: 7px;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="nw"] {
|
|
1179
|
+
top: -4px;
|
|
1180
|
+
left: -4px;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="ne"] {
|
|
1184
|
+
top: -4px;
|
|
1185
|
+
right: -4px;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="sw"] {
|
|
1189
|
+
bottom: -4px;
|
|
1190
|
+
left: -4px;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="se"] {
|
|
1194
|
+
right: -4px;
|
|
1195
|
+
bottom: -4px;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="n"],
|
|
1199
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="s"] {
|
|
1200
|
+
width: 22px;
|
|
1201
|
+
height: 12px;
|
|
1202
|
+
left: 50%;
|
|
1203
|
+
transform: translateX(-50%);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="n"] {
|
|
1207
|
+
top: -6.5px;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="s"] {
|
|
1211
|
+
bottom: -6.5px;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="e"],
|
|
1215
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="w"] {
|
|
1216
|
+
width: 12px;
|
|
1217
|
+
height: 22px;
|
|
1218
|
+
top: 50%;
|
|
1219
|
+
transform: translateY(-50%);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="e"] {
|
|
1223
|
+
right: -6.5px;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
[data-slide-selection-chrome="true"] [data-slide-resize-handle="w"] {
|
|
1227
|
+
left: -6.5px;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
[data-slide-selection-chrome="true"]
|
|
1231
|
+
[data-slide-resize-handle="n"]
|
|
1232
|
+
[data-slide-resize-handle-bar="true"],
|
|
1233
|
+
[data-slide-selection-chrome="true"]
|
|
1234
|
+
[data-slide-resize-handle="s"]
|
|
1235
|
+
[data-slide-resize-handle-bar="true"] {
|
|
1236
|
+
width: 14px;
|
|
1237
|
+
height: 4px;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
[data-slide-selection-chrome="true"]
|
|
1241
|
+
[data-slide-resize-handle="e"]
|
|
1242
|
+
[data-slide-resize-handle-bar="true"],
|
|
1243
|
+
[data-slide-selection-chrome="true"]
|
|
1244
|
+
[data-slide-resize-handle="w"]
|
|
1245
|
+
[data-slide-resize-handle-bar="true"] {
|
|
1246
|
+
width: 4px;
|
|
1247
|
+
height: 14px;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1145
1250
|
/* ─── Slide Transition Keyframes ─── */
|
|
1146
1251
|
|
|
1147
1252
|
@keyframes slide-fade-in {
|
|
@@ -356,6 +356,8 @@ const messages = {
|
|
|
356
356
|
styleInspector: {
|
|
357
357
|
title: "Style",
|
|
358
358
|
close: "Close style inspector",
|
|
359
|
+
slideBackground: "Slide background",
|
|
360
|
+
slide: "Slide",
|
|
359
361
|
deckStyle: "Deck style",
|
|
360
362
|
designSystemTweaks: "Design system tweaks",
|
|
361
363
|
closeTweaks: "Close tweaks",
|
|
@@ -415,6 +417,10 @@ const messages = {
|
|
|
415
417
|
emerald: "Emerald",
|
|
416
418
|
amber: "Amber",
|
|
417
419
|
rose: "Rose",
|
|
420
|
+
arrange: "Arrange",
|
|
421
|
+
order: "Order",
|
|
422
|
+
bringToFront: "Bring to front",
|
|
423
|
+
sendToBack: "Send to back",
|
|
418
424
|
},
|
|
419
425
|
animations: {
|
|
420
426
|
appear: "Appear",
|
|
@@ -531,6 +537,7 @@ const messages = {
|
|
|
531
537
|
deckHasNoSlides: "Deck has no slides.",
|
|
532
538
|
pdfRenderFailed: "Could not render PDF.",
|
|
533
539
|
buildingDeck: "Building deck",
|
|
540
|
+
dismissLayoutWarning: "Dismiss layout warning",
|
|
534
541
|
slidesAdded_one: "{{count}} slide added",
|
|
535
542
|
slidesAdded_other: "{{count}} slides added",
|
|
536
543
|
},
|
|
@@ -632,6 +639,7 @@ const messages = {
|
|
|
632
639
|
clearWorkspaceDefault: "Clear workspace default",
|
|
633
640
|
workspaceDefaultSet: "Set as the workspace default",
|
|
634
641
|
workspaceDefaultCleared: "Workspace default cleared",
|
|
642
|
+
duplicateFailed: "Couldn't duplicate that deck",
|
|
635
643
|
workspaceDefaultFailed: "Couldn't update the workspace default",
|
|
636
644
|
workspaceDefaultConfirmTitle: "Set as workspace default?",
|
|
637
645
|
workspaceDefaultDeckShareBody:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function deckAccessCheckKey(
|
|
2
|
+
deckId: string | undefined,
|
|
3
|
+
orgId: string | null | undefined,
|
|
4
|
+
): string | null {
|
|
5
|
+
return deckId ? JSON.stringify([deckId, orgId ?? null]) : null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function shouldShowDeckEditorSkeleton({
|
|
9
|
+
deckFound,
|
|
10
|
+
decksLoading,
|
|
11
|
+
orgLoading,
|
|
12
|
+
accessCheckKey,
|
|
13
|
+
checkedAccessKey,
|
|
14
|
+
retrying,
|
|
15
|
+
}: {
|
|
16
|
+
deckFound: boolean;
|
|
17
|
+
decksLoading: boolean;
|
|
18
|
+
orgLoading: boolean;
|
|
19
|
+
accessCheckKey: string | null;
|
|
20
|
+
checkedAccessKey: string | null;
|
|
21
|
+
retrying: boolean;
|
|
22
|
+
}): boolean {
|
|
23
|
+
if (decksLoading) return true;
|
|
24
|
+
if (deckFound || !accessCheckKey) return false;
|
|
25
|
+
return orgLoading || checkedAccessKey !== accessCheckKey || retrying;
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts `<div class="mermaid">...</div>` blocks from raw slide HTML and
|
|
3
|
+
* replaces them with `data-mermaid-index="N"` placeholders, BEFORE any
|
|
4
|
+
* sanitization. The sanitizer round-trips HTML through DOMParser +
|
|
5
|
+
* innerHTML, which HTML-escapes `>` in text nodes to `>` — that mangles
|
|
6
|
+
* diagram arrows like `A --> B` into `A --> B` and breaks the mermaid
|
|
7
|
+
* parser. The extracted definitions are the untouched source of truth for
|
|
8
|
+
* re-rendering (SlideRenderer) and for restoring the original markup when
|
|
9
|
+
* saving edits made elsewhere on the same slide (SlideEditor) — the live DOM
|
|
10
|
+
* replaces each placeholder with a rendered SVG, which must never be
|
|
11
|
+
* serialized back into slide.content or the diagram becomes permanently
|
|
12
|
+
* inert raw SVG with no way to edit or regenerate it.
|
|
13
|
+
*/
|
|
14
|
+
export function extractMermaidBlocks(content: string): {
|
|
15
|
+
blocks: string[];
|
|
16
|
+
contentWithPlaceholders: string;
|
|
17
|
+
} {
|
|
18
|
+
const blocks: string[] = [];
|
|
19
|
+
const contentWithPlaceholders = content.replace(
|
|
20
|
+
/<div\s+class="mermaid"[^>]*>([\s\S]*?)<\/div>/gi,
|
|
21
|
+
(_, definition) => {
|
|
22
|
+
blocks.push(String(definition).trim());
|
|
23
|
+
return `<div data-mermaid-index="${blocks.length - 1}"></div>`;
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
return { blocks, contentWithPlaceholders };
|
|
27
|
+
}
|