@agent-native/core 0.149.1 → 0.149.3
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 +1 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/analytics/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +2 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/analytics/AGENTS.md +25 -32
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +150 -46
- package/corpus/templates/analytics/app/global.css +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +37 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
- package/corpus/templates/analytics/changelog/2026-08-10-dashboard-tables-can-be-copied-and-sorted-by-multiple-column.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/assets/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/assets/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/assets/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/assets/AGENTS.md +6 -9
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/brain/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/brain/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/brain/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/brain/AGENTS.md +5 -12
- package/corpus/templates/brain/app/global.css +1 -1
- package/corpus/templates/brain/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/brain/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/calendar/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/calendar/AGENTS.md +8 -9
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/chat/AGENTS.md +32 -80
- package/corpus/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/clips/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/clips/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/clips/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/clips/AGENTS.md +25 -31
- package/corpus/templates/clips/changelog/2026-08-10-clips-desktop-sign-in-now-starts-with-magic-links-and-google.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.css +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +274 -137
- package/corpus/templates/clips/desktop/src/styles.css +35 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/content/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/content/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/content/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/content/AGENTS.md +5 -9
- package/corpus/templates/content/app/global.css +1 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/crm/AGENTS.md +7 -11
- package/corpus/templates/crm/app/global.css +1 -1
- package/corpus/templates/crm/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/crm/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/design/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/design/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/design/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +70 -3
- package/corpus/templates/design/AGENTS.md +13 -21
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +19 -2
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +115 -7
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +82 -7
- package/corpus/templates/design/app/components/design/design-trace.ts +120 -0
- package/corpus/templates/design/app/components/design/dnd-debug.ts +2 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +40 -26
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -1
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +12 -3
- package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +4 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +7 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -5
- package/corpus/templates/design/app/pages/DesignSystems.tsx +3 -2
- package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +100 -13
- package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +14 -0
- package/corpus/templates/design/changelog/2026-08-10-marquee-selecting-layers-far-down-a-tall-screen-now-selects-.md +6 -0
- package/corpus/templates/design/changelog/2026-08-10-the-frame-tool-draws-a-plain-frame-by-default-with-screen-av.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +27 -32
- package/corpus/templates/design/playwright.config.ts +3 -5
- package/corpus/templates/design/shared/breakpoint-media.ts +9 -2
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/dispatch/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/dispatch/AGENTS.md +9 -16
- package/corpus/templates/dispatch/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/factory/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/factory/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/factory/AGENTS.md +10 -24
- package/corpus/templates/factory/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/forms/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/forms/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/forms/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/forms/AGENTS.md +11 -17
- package/corpus/templates/forms/app/global.css +1 -0
- package/corpus/templates/forms/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/macros/AGENTS.md +8 -8
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/mail/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/mail/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/mail/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/mail/AGENTS.md +5 -6
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/plan/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/plan/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/plan/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/plan/AGENTS.md +5 -14
- package/corpus/templates/plan/app/global.css +1 -0
- package/corpus/templates/plan/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/plan/changelog/2026-08-11-plan-no-longer-reloads-when-runtime-state-changes.md +6 -0
- package/corpus/templates/plan/server/ui-plan-html.ts +4 -1
- package/corpus/templates/plan/vite.config.ts +5 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/slides/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/slides/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -2
- package/corpus/templates/slides/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +6 -3
- package/corpus/templates/slides/.agents/skills/deck-management/SKILL.md +6 -1
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +3 -2
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +3 -0
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +3 -3
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/slides/AGENTS.md +33 -35
- package/corpus/templates/slides/actions/add-deck.ts +2 -0
- package/corpus/templates/slides/actions/add-slide.ts +15 -1
- package/corpus/templates/slides/actions/create-deck.ts +18 -6
- package/corpus/templates/slides/actions/get-deck-reference-context.ts +2 -2
- package/corpus/templates/slides/actions/get-deck.ts +83 -7
- package/corpus/templates/slides/actions/import-file.ts +2 -1
- package/corpus/templates/slides/actions/patch-deck.ts +165 -9
- package/corpus/templates/slides/actions/save-deck.ts +24 -1
- package/corpus/templates/slides/actions/update-slide.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +2 -2
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -23
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +2 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +6 -6
- package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +3 -3
- package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +4 -4
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +432 -668
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +296 -259
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +13 -1
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +56 -174
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +241 -116
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +42 -14
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +6 -12
- package/corpus/templates/slides/app/components/editor/editor-command-model.ts +35 -0
- package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Layout.tsx +34 -35
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +8 -10
- package/corpus/templates/slides/app/components/layout/layout-route-policy.ts +2 -5
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +45 -40
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +63 -16
- package/corpus/templates/slides/app/context/DeckContext.tsx +2 -1
- package/corpus/templates/slides/app/global.css +76 -1
- package/corpus/templates/slides/app/hooks/use-generating-slide-preview.ts +25 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +52 -23
- package/corpus/templates/slides/app/lib/recent-references.ts +23 -1
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +104 -3
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -33
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +2 -2
- package/corpus/templates/slides/app/pages/Index.tsx +315 -151
- package/corpus/templates/slides/app/root.tsx +43 -0
- package/corpus/templates/slides/changelog/2026-08-10-ai-editing-avatar-badge.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-generated-decks-keep-a-clear-human-readable-title.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-new-deck-creation-now-shows-progress-opens-the-editor-direct.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-presentation-reveals-now-follow-valid-targets.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-editing-controls-are-consolidated-into-one-focused-me.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-now-verify-and-restyle-every-imported-slide-in-one-pa.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-only-suggests-a-google-connection-for-relevant-reques.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-the-google-slides-import-option-is-now-labeled-slides.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-faster-slides-chat-deck-reads.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-chat-can-read-one-slide-without-loading-the-full-deck.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-clearly-indicate-when-an-ai-agent-is-editing-alongsid.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/corpus/templates/slides/server/lib/validate-slide-animations.ts +163 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -5
- package/corpus/templates/slides/shared/api.ts +47 -15
- package/corpus/templates/slides/shared/deck-title.ts +135 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/tasks/AGENTS.md +5 -20
- package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +4 -1
- package/dist/agent/engine/ai-sdk-engine.js +1 -1
- package/dist/agent/production-agent.d.ts +21 -1
- package/dist/agent/production-agent.js +505 -355
- package/dist/agent/run-manager.js +156 -14
- package/dist/agent/run-store.d.ts +11 -10
- package/dist/agent/run-store.js +17 -13
- package/dist/agent/tool-approval-store.d.ts +18 -0
- package/dist/agent/tool-approval-store.js +122 -0
- package/dist/agent/types.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +11 -2
- package/dist/client/AgentPanel.js +31 -6
- package/dist/client/AssistantChat.d.ts +9 -4
- package/dist/client/AssistantChat.js +221 -149
- package/dist/client/active-run-state.d.ts +9 -1
- package/dist/client/active-run-state.js +34 -3
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat-adapter.d.ts +8 -0
- package/dist/client/agent-chat-adapter.js +125 -28
- package/dist/client/agent-chat.d.ts +1 -1
- package/dist/client/chat/markdown-renderer.js +14 -2
- package/dist/client/chat/message-components.d.ts +13 -3
- package/dist/client/chat/message-components.js +57 -52
- package/dist/client/chat/run-recovery.d.ts +1 -0
- package/dist/client/chat/run-recovery.js +8 -0
- package/dist/client/chat/tool-call-display.d.ts +5 -5
- package/dist/client/chat/tool-call-display.js +9 -212
- package/dist/client/chat-first/apps-rail.js +3 -3
- package/dist/client/chat-first/browser-pane.js +4 -1
- package/dist/client/chat-first/chat-history.d.ts +3 -1
- package/dist/client/chat-first/chat-history.js +7 -4
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +52 -41
- package/dist/client/chat-first/types.d.ts +3 -0
- package/dist/client/chat-first.d.ts +10 -0
- package/dist/client/chat-first.js +37 -2
- package/dist/client/components/ui/message-scroller.js +4 -1
- package/dist/client/i18n.js +3 -1
- package/dist/client/resources/McpConnectionSuggestion.js +9 -1
- package/dist/client/sse-event-processor.d.ts +4 -2
- package/dist/client/sse-event-processor.js +46 -6
- package/dist/client/use-chat-models.js +156 -80
- package/dist/client/use-run-stuck-detection.d.ts +2 -0
- package/dist/client/use-run-stuck-detection.js +85 -9
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts +0 -4
- package/dist/integrations/adapters/slack.js +6 -30
- package/dist/integrations/catalog.js +1 -1
- package/dist/integrations/pending-tasks-store.d.ts +0 -8
- package/dist/integrations/pending-tasks-store.js +0 -21
- package/dist/integrations/slack-manifest.d.ts +2 -2
- package/dist/integrations/slack-manifest.js +0 -3
- package/dist/integrations/webhook-handler.js +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/scripts/docs/source-search.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js +7 -2
- package/dist/server/agent-chat/prompt-resources.js +2 -2
- package/dist/server/agent-chat/skill-frontmatter.d.ts +31 -2
- package/dist/server/agent-chat/skill-frontmatter.js +41 -15
- package/dist/server/agent-chat-plugin.js +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agents-bundle.d.ts +16 -19
- package/dist/server/agents-bundle.js +19 -35
- package/dist/server/auth.js +262 -31
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/onboarding-html.js +56 -9
- package/dist/server/prompts/framework-core-compact.d.ts +6 -1
- package/dist/server/prompts/framework-core-compact.js +12 -9
- package/dist/server/prompts/framework-core.d.ts +6 -1
- package/dist/server/prompts/framework-core.js +11 -9
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/shared-rules.d.ts +15 -11
- package/dist/server/prompts/shared-rules.js +17 -13
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/reasoning-effort.d.ts +8 -8
- package/dist/shared/reasoning-effort.js +10 -10
- package/dist/shared/streaming-text-smoothing.js +41 -11
- package/dist/styles/agent-native.css +19 -32
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/chat/AGENTS.md +32 -80
- package/dist/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/dist/templates/workspace-core/AGENTS.md +7 -16
- package/docs/content/messaging.mdx +6 -7
- package/docs/content/template-chat.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/chat/AGENTS.md +32 -80
- package/src/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/src/templates/workspace-core/AGENTS.md +7 -16
|
@@ -33,6 +33,10 @@ import {
|
|
|
33
33
|
} from "react-router";
|
|
34
34
|
import type { LinksFunction } from "react-router";
|
|
35
35
|
|
|
36
|
+
import {
|
|
37
|
+
getEditorCommands,
|
|
38
|
+
type EditorCommandGroup,
|
|
39
|
+
} from "@/components/editor/editor-command-model";
|
|
36
40
|
import { Layout as AppLayout } from "@/components/layout/Layout";
|
|
37
41
|
import { FirstDeckOnboardingFlow } from "@/components/onboarding/FirstDeckOnboardingFlow";
|
|
38
42
|
import { AppToolkitProvider } from "@/components/ui/toolkit-provider";
|
|
@@ -202,6 +206,17 @@ function AppContent() {
|
|
|
202
206
|
const navigate = useNavigate();
|
|
203
207
|
useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
|
|
204
208
|
const location = useLocation();
|
|
209
|
+
const editorCommands = getEditorCommands();
|
|
210
|
+
const editorCommandGroups: Array<{
|
|
211
|
+
id: EditorCommandGroup;
|
|
212
|
+
heading: string;
|
|
213
|
+
}> = [
|
|
214
|
+
{ id: "media", heading: t("editorToolbar.media") },
|
|
215
|
+
{ id: "slideTools", heading: t("editorToolbar.slideTools") },
|
|
216
|
+
{ id: "comments", heading: t("editorToolbar.comments") },
|
|
217
|
+
{ id: "deck", heading: t("editorExport.exportAndDuplicate") },
|
|
218
|
+
{ id: "other", heading: t("editorToolbar.more") },
|
|
219
|
+
];
|
|
205
220
|
|
|
206
221
|
const isBare =
|
|
207
222
|
BARE_ROUTES.has(location.pathname) ||
|
|
@@ -236,6 +251,34 @@ function AppContent() {
|
|
|
236
251
|
{t("settings.openAgentSettings")}
|
|
237
252
|
</CommandMenu.Item>
|
|
238
253
|
</CommandMenu.Group>
|
|
254
|
+
{editorCommandGroups.map((group) => {
|
|
255
|
+
const commands = editorCommands.filter(
|
|
256
|
+
(command) => command.group === group.id,
|
|
257
|
+
);
|
|
258
|
+
if (commands.length === 0) return null;
|
|
259
|
+
return (
|
|
260
|
+
<CommandMenu.Group key={group.id} heading={group.heading}>
|
|
261
|
+
{commands.map((command) => {
|
|
262
|
+
const Icon = command.icon;
|
|
263
|
+
return (
|
|
264
|
+
<CommandMenu.Item
|
|
265
|
+
key={command.id}
|
|
266
|
+
onSelect={command.run}
|
|
267
|
+
keywords={command.keywords}
|
|
268
|
+
className={
|
|
269
|
+
command.active
|
|
270
|
+
? "bg-accent text-accent-foreground"
|
|
271
|
+
: undefined
|
|
272
|
+
}
|
|
273
|
+
>
|
|
274
|
+
{Icon ? <Icon size={16} /> : null}
|
|
275
|
+
{command.label}
|
|
276
|
+
</CommandMenu.Item>
|
|
277
|
+
);
|
|
278
|
+
})}
|
|
279
|
+
</CommandMenu.Group>
|
|
280
|
+
);
|
|
281
|
+
})}
|
|
239
282
|
<CommandMenu.Group heading={t("root.commandAppearance")}>
|
|
240
283
|
<CommandMenu.Item
|
|
241
284
|
onSelect={() => setTheme(isDark ? "light" : "dark")}
|
|
@@ -119,7 +119,7 @@ export async function prepareSlidesChatAttachments(args: {
|
|
|
119
119
|
"",
|
|
120
120
|
"File handling rules:",
|
|
121
121
|
"- If the request refers to the current or visible deck, call `view-screen` first to confirm the active deckId, then pass that deckId to import or slide-edit actions.",
|
|
122
|
-
'- PPTX files: when the user wants the visible deck improved, call `import-pptx --filePath "<path>" --deckId <deckId>` first, then
|
|
122
|
+
'- PPTX files: when the user wants the visible deck improved, call `import-pptx --filePath "<path>" --deckId <deckId>` first, then use one patch-deck call with requireAllSourceSlides=true and one content patch per imported slide for a deck-wide restyle. Use update-slide only for a targeted one-slide edit. Do not rebuild the source deck with add-slide.',
|
|
123
123
|
'- PDF and DOCX files: call `import-file --filePath "<path>" --format auto --deckId <deckId>` and use the returned extracted text as source material before creating editable slides. For a visual PDF that the user wants preserved, beautified, or restyled from its original layout, pass `--importIntoDeck true` so each page is imported source-faithfully first; keep the full-page image and style around it, with source text persisted in slide notes for inspection.',
|
|
124
124
|
'- Figma `.fig` files: call `import-file --filePath "<path>" --format fig` to start Builder design-system indexing. Do not create a local design system directly from the upload.',
|
|
125
125
|
"- For deck-generation requests, start mutating promptly: create or update the first slide as soon as source material is extracted, then continue slide-by-slide with add-slide/update-slide.",
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { parseHTML } from "linkedom/worker";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
animationElementKey,
|
|
5
|
+
getElementPath,
|
|
6
|
+
getElementPreview,
|
|
7
|
+
resolveSlideAnimationElement,
|
|
8
|
+
resolveSlideAnimationTargetsWithDiagnostics,
|
|
9
|
+
type AnimationTarget,
|
|
10
|
+
} from "../../app/lib/slide-animation-elements.js";
|
|
11
|
+
|
|
12
|
+
interface SlideAnimation extends AnimationTarget {
|
|
13
|
+
id?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SlideAnimationTargetSummary {
|
|
17
|
+
targetPreview: string | null;
|
|
18
|
+
resolvedPath: string | null;
|
|
19
|
+
targetValid: boolean;
|
|
20
|
+
targetIssue:
|
|
21
|
+
| "missing-slide-root"
|
|
22
|
+
| "target-not-found"
|
|
23
|
+
| "duplicate-target"
|
|
24
|
+
| null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function formatTarget(target: SlideAnimation): string {
|
|
28
|
+
const id = target.id ? ` (${target.id})` : "";
|
|
29
|
+
const path = Array.isArray(target.elementPath)
|
|
30
|
+
? ` path [${target.elementPath.join(", ")}]`
|
|
31
|
+
: "";
|
|
32
|
+
return `step ${target.elementIndex + 1}${id}${path}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function summarizeSlideAnimationTargets(
|
|
36
|
+
content: string,
|
|
37
|
+
animations: readonly SlideAnimation[],
|
|
38
|
+
): SlideAnimationTargetSummary[] {
|
|
39
|
+
if (animations.length === 0) return [];
|
|
40
|
+
|
|
41
|
+
const { document } = parseHTML(
|
|
42
|
+
`<!doctype html><html><head></head><body>${content}</body></html>`,
|
|
43
|
+
);
|
|
44
|
+
const root = document.querySelector(".fmd-slide");
|
|
45
|
+
if (!root) {
|
|
46
|
+
return animations.map(() => ({
|
|
47
|
+
targetPreview: null,
|
|
48
|
+
resolvedPath: null,
|
|
49
|
+
targetValid: false,
|
|
50
|
+
targetIssue: "missing-slide-root",
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const seen = new Set<string>();
|
|
55
|
+
return animations.map((target) => {
|
|
56
|
+
const element = resolveSlideAnimationElement(root, target);
|
|
57
|
+
if (!element) {
|
|
58
|
+
return {
|
|
59
|
+
targetPreview: null,
|
|
60
|
+
resolvedPath: null,
|
|
61
|
+
targetValid: false,
|
|
62
|
+
targetIssue: "target-not-found",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const path = getElementPath(root, element);
|
|
67
|
+
if (!path) {
|
|
68
|
+
return {
|
|
69
|
+
targetPreview: getElementPreview(
|
|
70
|
+
element,
|
|
71
|
+
`Element ${target.elementIndex + 1}`,
|
|
72
|
+
),
|
|
73
|
+
resolvedPath: null,
|
|
74
|
+
targetValid: false,
|
|
75
|
+
targetIssue: "target-not-found",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const key = animationElementKey(path);
|
|
80
|
+
if (seen.has(key)) {
|
|
81
|
+
return {
|
|
82
|
+
targetPreview: getElementPreview(
|
|
83
|
+
element,
|
|
84
|
+
`Element ${target.elementIndex + 1}`,
|
|
85
|
+
),
|
|
86
|
+
resolvedPath: key,
|
|
87
|
+
targetValid: false,
|
|
88
|
+
targetIssue: "duplicate-target",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
seen.add(key);
|
|
93
|
+
return {
|
|
94
|
+
targetPreview: getElementPreview(
|
|
95
|
+
element,
|
|
96
|
+
`Element ${target.elementIndex + 1}`,
|
|
97
|
+
),
|
|
98
|
+
resolvedPath: key,
|
|
99
|
+
targetValid: true,
|
|
100
|
+
targetIssue: null,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Validate animation identity against the exact HTML that is about to be
|
|
107
|
+
* persisted. Playback cannot repair a stale path without risking a different
|
|
108
|
+
* element being revealed, so reject the mutation before the deck is written.
|
|
109
|
+
*/
|
|
110
|
+
export function assertSlideAnimationsResolve({
|
|
111
|
+
slideId,
|
|
112
|
+
content,
|
|
113
|
+
animations,
|
|
114
|
+
requireElementPaths = false,
|
|
115
|
+
}: {
|
|
116
|
+
slideId: string;
|
|
117
|
+
content: string;
|
|
118
|
+
animations: readonly SlideAnimation[];
|
|
119
|
+
requireElementPaths?: boolean;
|
|
120
|
+
}): void {
|
|
121
|
+
if (animations.length === 0) return;
|
|
122
|
+
|
|
123
|
+
if (requireElementPaths) {
|
|
124
|
+
const legacyIndex = animations.findIndex(
|
|
125
|
+
(animation) => !Array.isArray(animation.elementPath),
|
|
126
|
+
);
|
|
127
|
+
if (legacyIndex !== -1) {
|
|
128
|
+
const target = animations[legacyIndex];
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Cannot save animations for slide ${slideId}: ${target ? formatTarget(target) : `step ${legacyIndex + 1}`} is missing elementPath. Agent-created or content-revised animations must use a path from the final HTML; elementIndex-only targets are legacy-only.`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { document } = parseHTML(
|
|
136
|
+
`<!doctype html><html><head></head><body>${content}</body></html>`,
|
|
137
|
+
);
|
|
138
|
+
const root = document.querySelector(".fmd-slide");
|
|
139
|
+
if (!root) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Cannot save animations for slide ${slideId}: the final HTML has no .fmd-slide wrapper. Re-read the slide content, then send the content and complete animation list together.`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const resolution = resolveSlideAnimationTargetsWithDiagnostics(
|
|
146
|
+
root,
|
|
147
|
+
animations,
|
|
148
|
+
);
|
|
149
|
+
const issue = resolution.issue;
|
|
150
|
+
if (!issue) return;
|
|
151
|
+
|
|
152
|
+
const target = animations[issue.animationIndex];
|
|
153
|
+
const targetDescription = target ? formatTarget(target) : "unknown step";
|
|
154
|
+
if (issue.code === "duplicate-target") {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`Cannot save animations for slide ${slideId}: ${targetDescription} duplicates target path ${issue.key ?? "unknown"}${issue.preview ? ` (${issue.preview})` : ""}. Each reveal step must target a different element; re-read the final HTML and send the complete ordered list.`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Cannot save animations for slide ${slideId}: ${targetDescription} does not resolve in the final HTML. Do not fall back to elementIndex; re-read the final HTML and send the content and complete ordered animation list together.`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
@@ -52,23 +52,26 @@ export default createAgentChatPlugin({
|
|
|
52
52
|
prepareRequest: prepareSlidesChatAttachments,
|
|
53
53
|
systemPrompt: `You are an AI deck assistant. You create, edit, import, export, style, share, and navigate decks through actions and shared application state. For a newly created presentation, use create-deck with slides: [] only when you are creating the deck yourself, then add-slide sequentially with full rendered HTML. The legacy generate-slides-ai action returns Markdown drafts and is not part of the persisted presentation workflow.
|
|
54
54
|
|
|
55
|
-
When the user asks to improve, beautify, restyle, or make an uploaded/existing deck on-brand, treat it as an in-place source-preserving edit unless the user explicitly asks to rewrite the story or change slide count. First call view-screen when the active deck is unclear, then get-deck. If get-deck.sourceImport exists, preserve its slide count, order, IDs, factual copy, notes, images, charts, tables, diagrams, freeform objects, and source aspect ratio.
|
|
55
|
+
When the user asks to improve, beautify, restyle, or make an uploaded/existing deck on-brand, treat it as an in-place source-preserving edit unless the user explicitly asks to rewrite the story or change slide count. First call view-screen when the active deck is unclear, then get-deck with compact=true for deck orientation. If you need slide markup, call get-deck with compact=false explicitly and only when the edit requires the full HTML. If get-deck.sourceImport exists, preserve its slide count, order, IDs, factual copy, notes, images, charts, tables, diagrams, freeform objects, and source aspect ratio. For a deck-wide restyle, use one patch-deck call with requireAllSourceSlides=true and one patch-slide operation with fields.content for every source slide ID; the action rejects partial coverage. Do not split a full-deck restyle into arbitrary batches or use one-by-one update-slide calls - reserve update-slide for targeted one-slide edits. After the patch succeeds, verify with get-deck using compact=true so the verification does not retransmit every slide's HTML. Do not claim a partial or initial pass. Do not use add-slide, delete, reorder, or replace source imagery with generic cards for this workflow. If sourceImport.fidelity is partial or imagesSkipped is nonzero, stop and report the exact fidelity warning instead of claiming a reliable improvement.
|
|
56
|
+
For a targeted one-slide edit, prefer get-deck with the stable slideId from view-screen or compact get-deck. It returns only that slide's full HTML by default, so do not load the full deck when one slide is enough. Pass compact=true when you only need a lightweight check of that slide.
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
When the active Slides editor is already showing the deck you just changed, do not include an "Open the updated deck" or similar link in the final response. The deck is already open and the action updated it in place; say that plainly instead. Only provide an open-deck link when the user is elsewhere, the active deck is different, or the user explicitly asks for a link.
|
|
59
|
+
|
|
60
|
+
For source-faithful PDF slides, keep the original full-page image and style around it with restrained design-system chrome such as a frame, edge treatment, caption, or safe overlay that does not obscure source content; never OCR-reconstruct the page from extracted text. For PPTX slides, preserve the imported positioned HTML and every uploaded source image. The patch-deck and update-slide actions enforce these preservation rules by default; pass preserveSource=false only when the user explicitly requests a rewrite of that slide.
|
|
58
61
|
|
|
59
62
|
If the deck has designSystemId, call get-design-system before writing and follow its exact agentContext tokens, assets, and custom instructions. If the user asks for on-brand styling and no design system is linked, call get-workspace-defaults, link its usable design system with patch-deck, then call get-design-system. Do not improvise a generic Builder-like palette when configured Builder.io design-system context is available.
|
|
60
63
|
|
|
61
|
-
Layout-fit workflow is strict. When the user asks to fix overflow, first call view-screen and inspect the deck-wide layout-fit section. If it says measurements are unknown, do not claim the deck fits. Call get-layout-overflows when you need the structured per-slide results. Read
|
|
64
|
+
Layout-fit workflow is strict. When the user asks to fix overflow, first call view-screen and inspect the deck-wide layout-fit section. If it says measurements are unknown, do not claim the deck fits. Call get-layout-overflows when you need the structured per-slide results. Read each affected slide with get-deck slideId=<id> (full HTML is returned for a targeted read), then make one bounded structural repair pass with one patch-slide operation per affected slide in a single patch-deck call. Wait for the action result and verify the persisted HTML with get-deck slideId=<id> compact=true before saying it is fixed. If a fresh measurement still reports overflow, make at most one focused follow-up repair based on that measurement; never loop, repeatedly re-measure, or claim success after a chat response alone.
|
|
62
65
|
|
|
63
66
|
Fit means the main content fits the native content area. A small outer-wrapper spill is tolerated by the measurement, but cards, text, columns, and other visible content must fit. Never use zoom, transform: scale(), overflow: hidden/scroll, clipping, or a smaller-than-16px body font to hide overflow. Preserve manually positioned freeform objects and their data-slide-object-id values; repair normal-flow structure, copy, gaps, or slide padding instead. A successful action result must include the affected slide IDs; if it does not, report that no verified write occurred.
|
|
64
67
|
|
|
65
|
-
Image workflow is strict. For direct insertion, call generate-image-api with insertIntoSlide: true plus deckId and slideId. Claim that an image was added only when that action returns inserted: true; a preview URL or completed generation alone is not a slide edit. For preview-only variations, call generate-image-api without insertIntoSlide, then use update-slide to place the chosen URL and re-read the target with get-deck to confirm its persisted HTML contains that image source before claiming success.
|
|
68
|
+
Image workflow is strict. For direct insertion, call generate-image-api with insertIntoSlide: true plus deckId and slideId. Claim that an image was added only when that action returns inserted: true; a preview URL or completed generation alone is not a slide edit. For preview-only variations, call generate-image-api without insertIntoSlide, then use update-slide to place the chosen URL and re-read the target with get-deck slideId=<id> compact=false to confirm its persisted HTML contains that image source before claiming success.
|
|
66
69
|
|
|
67
70
|
Provider-specific Slides actions are shortcuts, not limits. If a first-class action cannot express the exact Google Drive endpoint, file metadata field, export format, query, request body, pagination mode, payload shape, or API version needed, call provider-api-catalog and provider-api-docs as needed, then call provider-api-request against the real provider API. Use the raw provider API escape hatch instead of weakening the answer or claiming Slides cannot do something the underlying Google Drive API can do.
|
|
68
71
|
|
|
69
72
|
Slides' Google Drive provider API uses the user's connected Google Docs OAuth account. Picker imports keep the per-file drive.file path, while pasted Google Slides links use Drive export access and may ask the user to reconnect Google. For large Drive file lists or metadata sweeps, pass stageAs and pagination options to provider-api-request, then use query-staged-dataset to count, filter, group, or project the staged rows.
|
|
70
73
|
|
|
71
|
-
When a Google Drive or Google Slides request needs authentication, tell the user to use the Connect Google button
|
|
74
|
+
When a Google Drive or Google Slides request needs authentication, tell the user to use the Connect Google button in the Google Slides import step. Do not expose internal routes, API endpoints, OAuth setup instructions, client IDs, or keys in the response, and do not ask the user to configure an API manually.`,
|
|
72
75
|
mentionProviders: async () => {
|
|
73
76
|
const { getDb } = await import("../db/index.js");
|
|
74
77
|
const { decks, deckShares } = await import("../db/schema.js");
|
|
@@ -95,6 +95,18 @@ export type SharedSlideTransition =
|
|
|
95
95
|
|
|
96
96
|
export type SharedAnimationType = "appear" | "fade" | "slide-up" | "zoom";
|
|
97
97
|
|
|
98
|
+
export type SharedAnimationIssueCode =
|
|
99
|
+
| "invalid-shape"
|
|
100
|
+
| "invalid-element-path"
|
|
101
|
+
| "missing-target"
|
|
102
|
+
| "unsupported-type";
|
|
103
|
+
|
|
104
|
+
export interface SharedSlideAnimationIssue {
|
|
105
|
+
index: number;
|
|
106
|
+
id: string | null;
|
|
107
|
+
code: SharedAnimationIssueCode;
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
export interface SharedSlideAnimation {
|
|
99
111
|
id: string;
|
|
100
112
|
elementIndex: number;
|
|
@@ -110,6 +122,7 @@ export interface SharedDeckSlide {
|
|
|
110
122
|
background?: string;
|
|
111
123
|
transition?: SharedSlideTransition;
|
|
112
124
|
animations?: SharedSlideAnimation[];
|
|
125
|
+
animationIssues?: SharedSlideAnimationIssue[];
|
|
113
126
|
splitByParagraph?: boolean;
|
|
114
127
|
}
|
|
115
128
|
|
|
@@ -137,7 +150,7 @@ function normalizeString(value: unknown, fallback: string): string {
|
|
|
137
150
|
}
|
|
138
151
|
|
|
139
152
|
function normalizeElementPath(value: unknown): number[] | undefined {
|
|
140
|
-
if (!Array.isArray(value)) return undefined;
|
|
153
|
+
if (!Array.isArray(value) || value.length === 0) return undefined;
|
|
141
154
|
const path = value.filter(
|
|
142
155
|
(part): part is number =>
|
|
143
156
|
typeof part === "number" &&
|
|
@@ -151,10 +164,18 @@ function normalizeElementPath(value: unknown): number[] | undefined {
|
|
|
151
164
|
function normalizeSlideAnimation(
|
|
152
165
|
value: unknown,
|
|
153
166
|
index: number,
|
|
154
|
-
): SharedSlideAnimation |
|
|
155
|
-
|
|
167
|
+
): { animation: SharedSlideAnimation } | { issue: SharedSlideAnimationIssue } {
|
|
168
|
+
const id = isRecord(value) && typeof value.id === "string" ? value.id : null;
|
|
169
|
+
const issue = (code: SharedAnimationIssueCode) => ({
|
|
170
|
+
issue: { index, id, code },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (!isRecord(value)) return issue("invalid-shape");
|
|
156
174
|
|
|
157
175
|
const elementPath = normalizeElementPath(value.elementPath);
|
|
176
|
+
if (value.elementPath !== undefined && !elementPath) {
|
|
177
|
+
return issue("invalid-element-path");
|
|
178
|
+
}
|
|
158
179
|
const rawElementIndex = value.elementIndex;
|
|
159
180
|
const hasElementIndex =
|
|
160
181
|
typeof rawElementIndex === "number" &&
|
|
@@ -162,12 +183,13 @@ function normalizeSlideAnimation(
|
|
|
162
183
|
Number.isFinite(rawElementIndex) &&
|
|
163
184
|
rawElementIndex >= 0;
|
|
164
185
|
|
|
165
|
-
if (!hasElementIndex && !elementPath) return
|
|
186
|
+
if (!hasElementIndex && !elementPath) return issue("missing-target");
|
|
166
187
|
|
|
167
188
|
const rawType = value.type;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
if (!SHARED_ANIMATION_TYPES.has(rawType as SharedAnimationType)) {
|
|
190
|
+
return issue("unsupported-type");
|
|
191
|
+
}
|
|
192
|
+
const type = rawType as SharedAnimationType;
|
|
171
193
|
|
|
172
194
|
// When an explicit `elementIndex` is present, trust it. Otherwise derive
|
|
173
195
|
// from the last segment of `elementPath` - keeps the index correlated
|
|
@@ -182,10 +204,12 @@ function normalizeSlideAnimation(
|
|
|
182
204
|
: (elementPath![elementPath!.length - 1] ?? 0);
|
|
183
205
|
|
|
184
206
|
return {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
207
|
+
animation: {
|
|
208
|
+
id: normalizeString(value.id, `animation-${index + 1}`),
|
|
209
|
+
elementIndex: resolvedElementIndex,
|
|
210
|
+
...(elementPath ? { elementPath } : {}),
|
|
211
|
+
type,
|
|
212
|
+
},
|
|
189
213
|
};
|
|
190
214
|
}
|
|
191
215
|
|
|
@@ -214,14 +238,22 @@ export function toSharedDeckSlide(
|
|
|
214
238
|
}
|
|
215
239
|
|
|
216
240
|
if (Array.isArray(slide.animations)) {
|
|
217
|
-
const
|
|
218
|
-
|
|
241
|
+
const normalizedAnimations = slide.animations.map(
|
|
242
|
+
(animation, animationIndex) =>
|
|
219
243
|
normalizeSlideAnimation(animation, animationIndex),
|
|
220
|
-
|
|
221
|
-
|
|
244
|
+
);
|
|
245
|
+
const animations = normalizedAnimations.flatMap((result) =>
|
|
246
|
+
"animation" in result ? [result.animation] : [],
|
|
247
|
+
);
|
|
248
|
+
const animationIssues = normalizedAnimations.flatMap((result) =>
|
|
249
|
+
"issue" in result ? [result.issue] : [],
|
|
250
|
+
);
|
|
222
251
|
if (animations.length > 0) {
|
|
223
252
|
shared.animations = animations;
|
|
224
253
|
}
|
|
254
|
+
if (animationIssues.length > 0) {
|
|
255
|
+
shared.animationIssues = animationIssues;
|
|
256
|
+
}
|
|
225
257
|
}
|
|
226
258
|
|
|
227
259
|
return shared;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const GENERATED_TITLE_PLACEHOLDERS = new Set([
|
|
2
|
+
"deck",
|
|
3
|
+
"date",
|
|
4
|
+
"image slide title",
|
|
5
|
+
"presentation title",
|
|
6
|
+
"section",
|
|
7
|
+
"section title",
|
|
8
|
+
"slide title",
|
|
9
|
+
"untitled",
|
|
10
|
+
"untitled deck",
|
|
11
|
+
"your name",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generated deck ids should never become user-facing titles. Keep this
|
|
16
|
+
* deliberately narrow so normal titles with spaces and punctuation remain
|
|
17
|
+
* valid, while catching opaque mixed-case tokens such as H3sVsnns-TEVUOpz9w.
|
|
18
|
+
*/
|
|
19
|
+
const OPAQUE_DECK_TITLE_PATTERN =
|
|
20
|
+
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z0-9_-]{12,64}$/;
|
|
21
|
+
|
|
22
|
+
export const DEFAULT_DECK_TITLE = "Untitled Deck";
|
|
23
|
+
|
|
24
|
+
export function isOpaqueDeckTitle(value: unknown): value is string {
|
|
25
|
+
return (
|
|
26
|
+
typeof value === "string" && OPAQUE_DECK_TITLE_PATTERN.test(value.trim())
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isGeneratedDeckTitle(value: unknown): value is string {
|
|
31
|
+
if (typeof value !== "string") return false;
|
|
32
|
+
const title = value.trim();
|
|
33
|
+
return (
|
|
34
|
+
GENERATED_TITLE_PLACEHOLDERS.has(title.toLowerCase()) ||
|
|
35
|
+
isOpaqueDeckTitle(title)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function decodeHtmlEntities(value: string): string {
|
|
40
|
+
const decodeCodePoint = (raw: string, radix: number): string => {
|
|
41
|
+
const codePoint = Number.parseInt(raw, radix);
|
|
42
|
+
return Number.isNaN(codePoint) || codePoint > 0x10ffff
|
|
43
|
+
? ""
|
|
44
|
+
: String.fromCodePoint(codePoint);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return value
|
|
48
|
+
.replace(/ /gi, " ")
|
|
49
|
+
.replace(/&/gi, "&")
|
|
50
|
+
.replace(/</gi, "<")
|
|
51
|
+
.replace(/>/gi, ">")
|
|
52
|
+
.replace(/"/gi, '"')
|
|
53
|
+
.replace(/(?:'|')/gi, "'")
|
|
54
|
+
.replace(/&#x([0-9a-f]+);?/gi, (_, hex: string) => decodeCodePoint(hex, 16))
|
|
55
|
+
.replace(/&#(\d+);?/g, (_, digits: string) => decodeCodePoint(digits, 10));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function plainText(value: string): string {
|
|
59
|
+
return decodeHtmlEntities(
|
|
60
|
+
value.replace(/<br\s*\/?>/gi, " ").replace(/<[^>]+>/g, " "),
|
|
61
|
+
)
|
|
62
|
+
.replace(/\s+/g, " ")
|
|
63
|
+
.trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function usableCandidate(value: string): string | null {
|
|
67
|
+
const candidate = plainText(value).replace(/^[•●▪‣\-\s]+/, "");
|
|
68
|
+
if (!candidate || candidate.length > 140) return null;
|
|
69
|
+
if (GENERATED_TITLE_PLACEHOLDERS.has(candidate.toLowerCase())) return null;
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Recover a deck title from the largest title-like text in its first slide.
|
|
75
|
+
* This is intentionally HTML-string based because the action runs on the
|
|
76
|
+
* server without a browser DOM.
|
|
77
|
+
*/
|
|
78
|
+
export function deriveDeckTitleFromSlideContent(
|
|
79
|
+
content: unknown,
|
|
80
|
+
): string | null {
|
|
81
|
+
if (typeof content !== "string" || !content.trim()) return null;
|
|
82
|
+
|
|
83
|
+
const candidates: Array<{ score: number; text: string }> = [];
|
|
84
|
+
const headingPattern = /<(h[1-6])\b[^>]*>([\s\S]*?)<\/\1>/gi;
|
|
85
|
+
for (const match of content.matchAll(headingPattern)) {
|
|
86
|
+
const text = usableCandidate(match[2] ?? "");
|
|
87
|
+
if (text) {
|
|
88
|
+
const level = Number.parseInt(match[1].slice(1), 10);
|
|
89
|
+
candidates.push({ score: 1000 - level * 10, text });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const styledTextPattern =
|
|
94
|
+
/<([a-z][\w:-]*)\b[^>]*\bstyle\s*=\s*(["'])([\s\S]*?)\2[^>]*>([\s\S]*?)<\/\1>/gi;
|
|
95
|
+
for (const match of content.matchAll(styledTextPattern)) {
|
|
96
|
+
const fontSize = Number.parseFloat(
|
|
97
|
+
match[3]?.match(/(?:^|;)\s*font-size\s*:\s*([\d.]+)px/i)?.[1] ?? "0",
|
|
98
|
+
);
|
|
99
|
+
if (fontSize < 28) continue;
|
|
100
|
+
const text = usableCandidate(match[4] ?? "");
|
|
101
|
+
if (text) candidates.push({ score: fontSize, text });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return candidates.sort((a, b) => b.score - a.score)[0]?.text ?? null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Return a human-readable replacement only when the requested title is a
|
|
109
|
+
* generated placeholder or opaque id. A meaningful existing title wins when
|
|
110
|
+
* a stale full-payload save tries to replace it with a generated value.
|
|
111
|
+
*/
|
|
112
|
+
export function repairGeneratedDeckTitle(
|
|
113
|
+
requestedTitle: unknown,
|
|
114
|
+
firstSlideContent: unknown,
|
|
115
|
+
existingTitle?: unknown,
|
|
116
|
+
): string | null {
|
|
117
|
+
if (!isGeneratedDeckTitle(requestedTitle)) return null;
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
deriveDeckTitleFromSlideContent(firstSlideContent) ??
|
|
121
|
+
(typeof existingTitle === "string" &&
|
|
122
|
+
existingTitle.trim() &&
|
|
123
|
+
!isGeneratedDeckTitle(existingTitle)
|
|
124
|
+
? existingTitle
|
|
125
|
+
: null)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function assertHumanReadableDeckTitle(title: string): void {
|
|
130
|
+
if (isOpaqueDeckTitle(title)) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
"Deck title must be a concise, human-readable title; generated ids are not valid titles.",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|