@agent-native/core 0.37.3 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -6
- package/dist/action.d.ts +60 -2
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +6 -2
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +12 -6
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +161 -11
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +2 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/catalog.json +2 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +15 -0
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/index.js +10 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-publish-store.d.ts +52 -0
- package/dist/cli/plan-publish-store.d.ts.map +1 -0
- package/dist/cli/plan-publish-store.js +103 -0
- package/dist/cli/plan-publish-store.js.map +1 -0
- package/dist/cli/skills.d.ts +29 -4
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +851 -275
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/templates-meta.js +12 -12
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +3 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +65 -15
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +20 -2
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-engine-key.d.ts +24 -0
- package/dist/client/agent-engine-key.d.ts.map +1 -0
- package/dist/client/agent-engine-key.js +49 -0
- package/dist/client/agent-engine-key.js.map +1 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +34 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/blocks/BlockView.d.ts +26 -0
- package/dist/client/blocks/BlockView.d.ts.map +1 -0
- package/dist/client/blocks/BlockView.js +24 -0
- package/dist/client/blocks/BlockView.js.map +1 -0
- package/dist/client/blocks/SchemaBlockEditor.d.ts +25 -0
- package/dist/client/blocks/SchemaBlockEditor.d.ts.map +1 -0
- package/dist/client/blocks/SchemaBlockEditor.js +72 -0
- package/dist/client/blocks/SchemaBlockEditor.js.map +1 -0
- package/dist/client/blocks/agent.d.ts +30 -0
- package/dist/client/blocks/agent.d.ts.map +1 -0
- package/dist/client/blocks/agent.js +61 -0
- package/dist/client/blocks/agent.js.map +1 -0
- package/dist/client/blocks/index.d.ts +34 -0
- package/dist/client/blocks/index.d.ts.map +1 -0
- package/dist/client/blocks/index.js +42 -0
- package/dist/client/blocks/index.js.map +1 -0
- package/dist/client/blocks/library/checklist.config.d.ts +36 -0
- package/dist/client/blocks/library/checklist.config.d.ts.map +1 -0
- package/dist/client/blocks/library/checklist.config.js +25 -0
- package/dist/client/blocks/library/checklist.config.js.map +1 -0
- package/dist/client/blocks/library/checklist.d.ts +26 -0
- package/dist/client/blocks/library/checklist.d.ts.map +1 -0
- package/dist/client/blocks/library/checklist.js +76 -0
- package/dist/client/blocks/library/checklist.js.map +1 -0
- package/dist/client/blocks/library/code-tabs.config.d.ts +36 -0
- package/dist/client/blocks/library/code-tabs.config.d.ts.map +1 -0
- package/dist/client/blocks/library/code-tabs.config.js +30 -0
- package/dist/client/blocks/library/code-tabs.config.js.map +1 -0
- package/dist/client/blocks/library/code-tabs.d.ts +3 -0
- package/dist/client/blocks/library/code-tabs.d.ts.map +1 -0
- package/dist/client/blocks/library/code-tabs.js +165 -0
- package/dist/client/blocks/library/code-tabs.js.map +1 -0
- package/dist/client/blocks/library/html.config.d.ts +37 -0
- package/dist/client/blocks/library/html.config.d.ts.map +1 -0
- package/dist/client/blocks/library/html.config.js +46 -0
- package/dist/client/blocks/library/html.config.js.map +1 -0
- package/dist/client/blocks/library/html.d.ts +21 -0
- package/dist/client/blocks/library/html.d.ts.map +1 -0
- package/dist/client/blocks/library/html.js +69 -0
- package/dist/client/blocks/library/html.js.map +1 -0
- package/dist/client/blocks/library/table.config.d.ts +30 -0
- package/dist/client/blocks/library/table.config.d.ts.map +1 -0
- package/dist/client/blocks/library/table.config.js +22 -0
- package/dist/client/blocks/library/table.config.js.map +1 -0
- package/dist/client/blocks/library/table.d.ts +8 -0
- package/dist/client/blocks/library/table.d.ts.map +1 -0
- package/dist/client/blocks/library/table.js +107 -0
- package/dist/client/blocks/library/table.js.map +1 -0
- package/dist/client/blocks/library/tabs.config.d.ts +56 -0
- package/dist/client/blocks/library/tabs.config.d.ts.map +1 -0
- package/dist/client/blocks/library/tabs.config.js +36 -0
- package/dist/client/blocks/library/tabs.config.js.map +1 -0
- package/dist/client/blocks/library/tabs.d.ts +20 -0
- package/dist/client/blocks/library/tabs.d.ts.map +1 -0
- package/dist/client/blocks/library/tabs.js +123 -0
- package/dist/client/blocks/library/tabs.js.map +1 -0
- package/dist/client/blocks/mdx.d.ts +74 -0
- package/dist/client/blocks/mdx.d.ts.map +1 -0
- package/dist/client/blocks/mdx.js +205 -0
- package/dist/client/blocks/mdx.js.map +1 -0
- package/dist/client/blocks/provider.d.ts +25 -0
- package/dist/client/blocks/provider.d.ts.map +1 -0
- package/dist/client/blocks/provider.js +19 -0
- package/dist/client/blocks/provider.js.map +1 -0
- package/dist/client/blocks/registry.d.ts +24 -0
- package/dist/client/blocks/registry.d.ts.map +1 -0
- package/dist/client/blocks/registry.js +50 -0
- package/dist/client/blocks/registry.js.map +1 -0
- package/dist/client/blocks/schema-form/introspect.d.ts +31 -0
- package/dist/client/blocks/schema-form/introspect.d.ts.map +1 -0
- package/dist/client/blocks/schema-form/introspect.js +164 -0
- package/dist/client/blocks/schema-form/introspect.js.map +1 -0
- package/dist/client/blocks/server.d.ts +22 -0
- package/dist/client/blocks/server.d.ts.map +1 -0
- package/dist/client/blocks/server.js +25 -0
- package/dist/client/blocks/server.js.map +1 -0
- package/dist/client/blocks/types.d.ts +212 -0
- package/dist/client/blocks/types.d.ts.map +1 -0
- package/dist/client/blocks/types.js +5 -0
- package/dist/client/blocks/types.js.map +1 -0
- package/dist/client/composer/ComposerPlusMenu.js +10 -1
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/guided-questions.d.ts +68 -0
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +158 -3
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +15 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts +37 -0
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/BubbleToolbar.js +161 -0
- package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +1 -0
- package/dist/client/rich-markdown-editor/ImageExtension.d.ts +63 -0
- package/dist/client/rich-markdown-editor/ImageExtension.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/ImageExtension.js +242 -0
- package/dist/client/rich-markdown-editor/ImageExtension.js.map +1 -0
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +51 -0
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.js +37 -0
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.js.map +1 -0
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +61 -0
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +121 -0
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +36 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js +193 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +1 -0
- package/dist/client/rich-markdown-editor/extensions.d.ts +166 -0
- package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/extensions.js +222 -0
- package/dist/client/rich-markdown-editor/extensions.js.map +1 -0
- package/dist/client/rich-markdown-editor/index.d.ts +9 -0
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/index.js +9 -0
- package/dist/client/rich-markdown-editor/index.js.map +1 -0
- package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts +18 -0
- package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/uploadEditorImage.js +57 -0
- package/dist/client/rich-markdown-editor/uploadEditorImage.js.map +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +91 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +342 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -0
- package/dist/client/track.d.ts +25 -0
- package/dist/client/track.d.ts.map +1 -0
- package/dist/client/track.js +53 -0
- package/dist/client/track.js.map +1 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +6 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-session.d.ts +3 -2
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +3 -2
- package/dist/client/use-session.js.map +1 -1
- package/dist/deploy/build.d.ts +5 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +67 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/schema.d.ts +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +9 -2
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +35 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/provider-api/index.d.ts +1 -1
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +5 -2
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +16 -3
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +2 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +30 -4
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +65 -19
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +8 -1
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/agents-bundle.d.ts +27 -1
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +41 -3
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +76 -3
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +60 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +160 -22
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/sentry.d.ts.map +1 -1
- package/dist/server/sentry.js +6 -0
- package/dist/server/sentry.js.map +1 -1
- package/dist/server/social-og-image.d.ts +2 -1
- package/dist/server/social-og-image.d.ts.map +1 -1
- package/dist/server/social-og-image.js +24 -4
- package/dist/server/social-og-image.js.map +1 -1
- package/dist/sharing/schema.d.ts +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/rich-markdown-editor.css +439 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +4 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +13 -4
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
- package/dist/templates/default/AGENTS.md +1 -0
- package/dist/templates/default/DEVELOPING.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
- package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
- package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
- package/dist/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
- package/dist/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
- package/dist/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
- package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
- package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
- package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
- package/dist/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
- package/dist/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
- package/dist/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
- package/dist/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
- package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
- package/dist/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
- package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
- package/dist/templates/workspace-core/AGENTS.md +5 -1
- package/dist/templates/workspace-root/AGENTS.md +5 -2
- package/dist/tracking/route.d.ts +43 -0
- package/dist/tracking/route.d.ts.map +1 -0
- package/dist/tracking/route.js +85 -0
- package/dist/tracking/route.js.map +1 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +15 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.md +18 -4
- package/docs/content/actions.md +87 -0
- package/docs/content/agent-mentions.md +2 -1
- package/docs/content/authentication.md +2 -1
- package/docs/content/client.md +64 -13
- package/docs/content/cloneable-saas.md +1 -1
- package/docs/content/code-agents-ui.md +17 -11
- package/docs/content/context-awareness.md +23 -28
- package/docs/content/creating-templates.md +1 -1
- package/docs/content/drop-in-agent.md +2 -0
- package/docs/content/getting-started.md +2 -2
- package/docs/content/key-concepts.md +2 -2
- package/docs/content/messaging.md +57 -15
- package/docs/content/migration-workbench.md +1 -1
- package/docs/content/multi-app-workspace.md +1 -1
- package/docs/content/multi-tenancy.md +17 -15
- package/docs/content/real-time-collaboration.md +1 -1
- package/docs/content/recurring-jobs.md +1 -1
- package/docs/content/security.md +2 -2
- package/docs/content/server.md +4 -4
- package/docs/content/skills-guide.md +30 -0
- package/docs/content/template-analytics.md +2 -2
- package/docs/content/template-assets.md +17 -1
- package/docs/content/template-brain.md +2 -2
- package/docs/content/template-calendar.md +1 -1
- package/docs/content/template-clips.md +3 -3
- package/docs/content/template-content.md +2 -2
- package/docs/content/template-design.md +2 -2
- package/docs/content/template-dispatch.md +3 -3
- package/docs/content/template-forms.md +14 -2
- package/docs/content/template-mail.md +1 -3
- package/docs/content/template-plan.md +118 -0
- package/docs/content/template-slides.md +5 -4
- package/docs/content/template-starter.md +4 -4
- package/docs/content/template-videos.md +6 -11
- package/docs/content/tracking.md +21 -1
- package/docs/content/visual-plans.md +72 -0
- package/docs/content/workspace.md +9 -9
- package/package.json +26 -11
- package/src/templates/default/.agents/skills/actions/SKILL.md +4 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +13 -4
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
- package/src/templates/default/AGENTS.md +1 -0
- package/src/templates/default/DEVELOPING.md +2 -0
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
- package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
- package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
- package/src/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
- package/src/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
- package/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
- package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
- package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
- package/src/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
- package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
- package/src/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
- package/src/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
- package/src/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
- package/src/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
- package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
- package/src/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
- package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
- package/src/templates/workspace-core/AGENTS.md +5 -1
- package/src/templates/workspace-root/AGENTS.md +5 -2
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
3
|
+
import { cn } from "../utils.js";
|
|
4
|
+
import { pickAndInsertImage } from "./ImageExtension.js";
|
|
5
|
+
/**
|
|
6
|
+
* The default block commands — Plan's current set. Apps pass their own `items`
|
|
7
|
+
* (typically `[...DEFAULT_SLASH_COMMANDS, ...extra]`) to extend it.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_SLASH_COMMANDS = [
|
|
10
|
+
{
|
|
11
|
+
title: "Text",
|
|
12
|
+
description: "Plain text block",
|
|
13
|
+
icon: "T",
|
|
14
|
+
action: (editor) => editor.chain().focus().setParagraph().run(),
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
title: "Heading 1",
|
|
18
|
+
description: "Large heading",
|
|
19
|
+
icon: "H1",
|
|
20
|
+
action: (editor) => editor.chain().focus().toggleHeading({ level: 1 }).run(),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: "Heading 2",
|
|
24
|
+
description: "Section heading",
|
|
25
|
+
icon: "H2",
|
|
26
|
+
action: (editor) => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
title: "Heading 3",
|
|
30
|
+
description: "Subheading",
|
|
31
|
+
icon: "H3",
|
|
32
|
+
action: (editor) => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: "Bulleted list",
|
|
36
|
+
description: "Unordered list",
|
|
37
|
+
icon: "-",
|
|
38
|
+
action: (editor) => editor.chain().focus().toggleBulletList().run(),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
title: "Numbered list",
|
|
42
|
+
description: "Ordered list",
|
|
43
|
+
icon: "1.",
|
|
44
|
+
action: (editor) => editor.chain().focus().toggleOrderedList().run(),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "To-do list",
|
|
48
|
+
description: "Checklist items",
|
|
49
|
+
icon: "[]",
|
|
50
|
+
action: (editor) => editor.chain().focus().toggleTaskList().run(),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: "Quote",
|
|
54
|
+
description: "Block quote",
|
|
55
|
+
icon: '"',
|
|
56
|
+
action: (editor) => editor.chain().focus().toggleBlockquote().run(),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
title: "Code block",
|
|
60
|
+
description: "Code snippet",
|
|
61
|
+
icon: "<>",
|
|
62
|
+
action: (editor) => editor.chain().focus().toggleCodeBlock().run(),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: "Divider",
|
|
66
|
+
description: "Horizontal rule",
|
|
67
|
+
icon: "-",
|
|
68
|
+
action: (editor) => editor.chain().focus().setHorizontalRule().run(),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
title: "Table",
|
|
72
|
+
description: "Three by three table",
|
|
73
|
+
icon: "tbl",
|
|
74
|
+
action: (editor) => editor
|
|
75
|
+
.chain()
|
|
76
|
+
.focus()
|
|
77
|
+
.insertTable({ rows: 3, cols: 3, withHeaderRow: true })
|
|
78
|
+
.run(),
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
/**
|
|
82
|
+
* Build the `/image` slash command for the shared image block. Requires the
|
|
83
|
+
* editor to mount the shared image extension (`features.image`) and an
|
|
84
|
+
* {@link ImageUploadFn}; the command opens a native file picker and uploads +
|
|
85
|
+
* inserts the chosen image(s). Add it to the list an app passes to
|
|
86
|
+
* {@link SlashCommandMenu} (e.g. `[...DEFAULT_SLASH_COMMANDS, createImageSlashCommand(upload)]`).
|
|
87
|
+
*/
|
|
88
|
+
export function createImageSlashCommand(upload) {
|
|
89
|
+
return {
|
|
90
|
+
title: "Image",
|
|
91
|
+
description: "Upload an image",
|
|
92
|
+
icon: "img",
|
|
93
|
+
action: (editor) => pickAndInsertImage(editor.view, upload),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The shared "/" block-insert menu. Detects a `/query` at the caret, filters the
|
|
98
|
+
* provided command list, and renders a fixed-position picker with keyboard
|
|
99
|
+
* navigation. Extracted from the inline plan menu so apps share one
|
|
100
|
+
* implementation and only swap the command list.
|
|
101
|
+
*/
|
|
102
|
+
export function SlashCommandMenu({ editor, items = DEFAULT_SLASH_COMMANDS, }) {
|
|
103
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
104
|
+
const [query, setQuery] = useState("");
|
|
105
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
106
|
+
const [position, setPosition] = useState(null);
|
|
107
|
+
const slashPosRef = useRef(null);
|
|
108
|
+
const filteredCommands = useMemo(() => items.filter((cmd) => cmd.title.toLowerCase().includes(query.toLowerCase()) ||
|
|
109
|
+
cmd.description.toLowerCase().includes(query.toLowerCase())), [items, query]);
|
|
110
|
+
const close = useCallback(() => {
|
|
111
|
+
setIsOpen(false);
|
|
112
|
+
setQuery("");
|
|
113
|
+
slashPosRef.current = null;
|
|
114
|
+
}, []);
|
|
115
|
+
const executeCommand = useCallback((command) => {
|
|
116
|
+
if (slashPosRef.current !== null) {
|
|
117
|
+
const { from } = editor.state.selection;
|
|
118
|
+
editor
|
|
119
|
+
.chain()
|
|
120
|
+
.focus()
|
|
121
|
+
.deleteRange({ from: slashPosRef.current, to: from })
|
|
122
|
+
.run();
|
|
123
|
+
}
|
|
124
|
+
command.action(editor);
|
|
125
|
+
close();
|
|
126
|
+
}, [close, editor]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
const handleKeyDown = (event) => {
|
|
129
|
+
if (!isOpen)
|
|
130
|
+
return;
|
|
131
|
+
if (event.key === "ArrowDown") {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
setSelectedIndex((index) => (index + 1) % filteredCommands.length);
|
|
134
|
+
}
|
|
135
|
+
else if (event.key === "ArrowUp") {
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
setSelectedIndex((index) => (index - 1 + filteredCommands.length) % filteredCommands.length);
|
|
138
|
+
}
|
|
139
|
+
else if (event.key === "Enter") {
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
const command = filteredCommands[selectedIndex];
|
|
142
|
+
if (command)
|
|
143
|
+
executeCommand(command);
|
|
144
|
+
}
|
|
145
|
+
else if (event.key === "Escape") {
|
|
146
|
+
close();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
document.addEventListener("keydown", handleKeyDown, true);
|
|
150
|
+
return () => document.removeEventListener("keydown", handleKeyDown, true);
|
|
151
|
+
}, [close, executeCommand, filteredCommands, isOpen, selectedIndex]);
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const handleTransaction = () => {
|
|
154
|
+
const { state } = editor;
|
|
155
|
+
const { from } = state.selection;
|
|
156
|
+
const textBefore = state.doc.textBetween(Math.max(0, from - 32), from, "\n");
|
|
157
|
+
const slashMatch = textBefore.match(/\/([a-zA-Z0-9]*)$/);
|
|
158
|
+
if (!slashMatch) {
|
|
159
|
+
if (isOpen)
|
|
160
|
+
close();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const slashStart = from - slashMatch[0].length;
|
|
164
|
+
slashPosRef.current = slashStart;
|
|
165
|
+
setQuery(slashMatch[1]);
|
|
166
|
+
setSelectedIndex(0);
|
|
167
|
+
const coords = editor.view.coordsAtPos(from);
|
|
168
|
+
const menuHeight = 320;
|
|
169
|
+
const spaceBelow = window.innerHeight - coords.bottom;
|
|
170
|
+
const flipUp = spaceBelow < menuHeight && coords.top > menuHeight;
|
|
171
|
+
setPosition({
|
|
172
|
+
top: flipUp ? coords.top : coords.bottom + 4,
|
|
173
|
+
left: Math.min(coords.left, window.innerWidth - 250),
|
|
174
|
+
flipUp,
|
|
175
|
+
});
|
|
176
|
+
setIsOpen(true);
|
|
177
|
+
};
|
|
178
|
+
editor.on("transaction", handleTransaction);
|
|
179
|
+
return () => {
|
|
180
|
+
editor.off("transaction", handleTransaction);
|
|
181
|
+
};
|
|
182
|
+
}, [close, editor, isOpen]);
|
|
183
|
+
if (!isOpen || !position || filteredCommands.length === 0)
|
|
184
|
+
return null;
|
|
185
|
+
return (_jsxs("div", { className: "an-rich-md-slash-menu", style: {
|
|
186
|
+
position: "fixed",
|
|
187
|
+
...(position.flipUp
|
|
188
|
+
? { bottom: window.innerHeight - position.top + 4 }
|
|
189
|
+
: { top: position.top }),
|
|
190
|
+
left: position.left,
|
|
191
|
+
}, "data-plan-interactive": true, children: [_jsx("div", { className: "an-rich-md-slash-heading", children: "Blocks" }), filteredCommands.map((command, index) => (_jsxs("button", { type: "button", className: cn("an-rich-md-slash-item", index === selectedIndex && "an-rich-md-slash-item--active"), onMouseEnter: () => setSelectedIndex(index), onMouseDown: (event) => event.preventDefault(), onClick: () => executeCommand(command), children: [_jsx("span", { className: "an-rich-md-slash-icon", children: command.icon }), _jsxs("span", { children: [_jsx("span", { className: "an-rich-md-slash-title", children: command.title }), _jsx("span", { className: "an-rich-md-slash-description", children: command.description })] })] }, command.title)))] }));
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=SlashCommandMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlashCommandMenu.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/SlashCommandMenu.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport type { Editor } from \"@tiptap/react\";\nimport { cn } from \"../utils.js\";\nimport { pickAndInsertImage, type ImageUploadFn } from \"./ImageExtension.js\";\n\n/** A single slash-menu block command. Apps can extend the default list. */\nexport interface SlashCommandItem {\n title: string;\n description: string;\n /** Short text glyph shown in the menu (T, H1, tbl, …). */\n icon: string;\n action: (editor: Editor) => void;\n}\n\n/**\n * The default block commands — Plan's current set. Apps pass their own `items`\n * (typically `[...DEFAULT_SLASH_COMMANDS, ...extra]`) to extend it.\n */\nexport const DEFAULT_SLASH_COMMANDS: SlashCommandItem[] = [\n {\n title: \"Text\",\n description: \"Plain text block\",\n icon: \"T\",\n action: (editor) => editor.chain().focus().setParagraph().run(),\n },\n {\n title: \"Heading 1\",\n description: \"Large heading\",\n icon: \"H1\",\n action: (editor) =>\n editor.chain().focus().toggleHeading({ level: 1 }).run(),\n },\n {\n title: \"Heading 2\",\n description: \"Section heading\",\n icon: \"H2\",\n action: (editor) =>\n editor.chain().focus().toggleHeading({ level: 2 }).run(),\n },\n {\n title: \"Heading 3\",\n description: \"Subheading\",\n icon: \"H3\",\n action: (editor) =>\n editor.chain().focus().toggleHeading({ level: 3 }).run(),\n },\n {\n title: \"Bulleted list\",\n description: \"Unordered list\",\n icon: \"-\",\n action: (editor) => editor.chain().focus().toggleBulletList().run(),\n },\n {\n title: \"Numbered list\",\n description: \"Ordered list\",\n icon: \"1.\",\n action: (editor) => editor.chain().focus().toggleOrderedList().run(),\n },\n {\n title: \"To-do list\",\n description: \"Checklist items\",\n icon: \"[]\",\n action: (editor) => editor.chain().focus().toggleTaskList().run(),\n },\n {\n title: \"Quote\",\n description: \"Block quote\",\n icon: '\"',\n action: (editor) => editor.chain().focus().toggleBlockquote().run(),\n },\n {\n title: \"Code block\",\n description: \"Code snippet\",\n icon: \"<>\",\n action: (editor) => editor.chain().focus().toggleCodeBlock().run(),\n },\n {\n title: \"Divider\",\n description: \"Horizontal rule\",\n icon: \"-\",\n action: (editor) => editor.chain().focus().setHorizontalRule().run(),\n },\n {\n title: \"Table\",\n description: \"Three by three table\",\n icon: \"tbl\",\n action: (editor) =>\n editor\n .chain()\n .focus()\n .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n .run(),\n },\n];\n\n/**\n * Build the `/image` slash command for the shared image block. Requires the\n * editor to mount the shared image extension (`features.image`) and an\n * {@link ImageUploadFn}; the command opens a native file picker and uploads +\n * inserts the chosen image(s). Add it to the list an app passes to\n * {@link SlashCommandMenu} (e.g. `[...DEFAULT_SLASH_COMMANDS, createImageSlashCommand(upload)]`).\n */\nexport function createImageSlashCommand(\n upload: ImageUploadFn,\n): SlashCommandItem {\n return {\n title: \"Image\",\n description: \"Upload an image\",\n icon: \"img\",\n action: (editor) => pickAndInsertImage(editor.view, upload),\n };\n}\n\nexport interface SlashCommandMenuProps {\n editor: Editor;\n /** Block command list. Defaults to {@link DEFAULT_SLASH_COMMANDS}. */\n items?: SlashCommandItem[];\n}\n\n/**\n * The shared \"/\" block-insert menu. Detects a `/query` at the caret, filters the\n * provided command list, and renders a fixed-position picker with keyboard\n * navigation. Extracted from the inline plan menu so apps share one\n * implementation and only swap the command list.\n */\nexport function SlashCommandMenu({\n editor,\n items = DEFAULT_SLASH_COMMANDS,\n}: SlashCommandMenuProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [position, setPosition] = useState<{\n top: number;\n left: number;\n flipUp: boolean;\n } | null>(null);\n const slashPosRef = useRef<number | null>(null);\n\n const filteredCommands = useMemo(\n () =>\n items.filter(\n (cmd) =>\n cmd.title.toLowerCase().includes(query.toLowerCase()) ||\n cmd.description.toLowerCase().includes(query.toLowerCase()),\n ),\n [items, query],\n );\n\n const close = useCallback(() => {\n setIsOpen(false);\n setQuery(\"\");\n slashPosRef.current = null;\n }, []);\n\n const executeCommand = useCallback(\n (command: SlashCommandItem) => {\n if (slashPosRef.current !== null) {\n const { from } = editor.state.selection;\n editor\n .chain()\n .focus()\n .deleteRange({ from: slashPosRef.current, to: from })\n .run();\n }\n command.action(editor);\n close();\n },\n [close, editor],\n );\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!isOpen) return;\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setSelectedIndex((index) => (index + 1) % filteredCommands.length);\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setSelectedIndex(\n (index) =>\n (index - 1 + filteredCommands.length) % filteredCommands.length,\n );\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n const command = filteredCommands[selectedIndex];\n if (command) executeCommand(command);\n } else if (event.key === \"Escape\") {\n close();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown, true);\n return () => document.removeEventListener(\"keydown\", handleKeyDown, true);\n }, [close, executeCommand, filteredCommands, isOpen, selectedIndex]);\n\n useEffect(() => {\n const handleTransaction = () => {\n const { state } = editor;\n const { from } = state.selection;\n const textBefore = state.doc.textBetween(\n Math.max(0, from - 32),\n from,\n \"\\n\",\n );\n const slashMatch = textBefore.match(/\\/([a-zA-Z0-9]*)$/);\n if (!slashMatch) {\n if (isOpen) close();\n return;\n }\n\n const slashStart = from - slashMatch[0].length;\n slashPosRef.current = slashStart;\n setQuery(slashMatch[1]);\n setSelectedIndex(0);\n const coords = editor.view.coordsAtPos(from);\n const menuHeight = 320;\n const spaceBelow = window.innerHeight - coords.bottom;\n const flipUp = spaceBelow < menuHeight && coords.top > menuHeight;\n setPosition({\n top: flipUp ? coords.top : coords.bottom + 4,\n left: Math.min(coords.left, window.innerWidth - 250),\n flipUp,\n });\n setIsOpen(true);\n };\n\n editor.on(\"transaction\", handleTransaction);\n return () => {\n editor.off(\"transaction\", handleTransaction);\n };\n }, [close, editor, isOpen]);\n\n if (!isOpen || !position || filteredCommands.length === 0) return null;\n\n return (\n <div\n className=\"an-rich-md-slash-menu\"\n style={\n {\n position: \"fixed\",\n ...(position.flipUp\n ? { bottom: window.innerHeight - position.top + 4 }\n : { top: position.top }),\n left: position.left,\n } as CSSProperties\n }\n data-plan-interactive\n >\n <div className=\"an-rich-md-slash-heading\">Blocks</div>\n {filteredCommands.map((command, index) => (\n <button\n key={command.title}\n type=\"button\"\n className={cn(\n \"an-rich-md-slash-item\",\n index === selectedIndex && \"an-rich-md-slash-item--active\",\n )}\n onMouseEnter={() => setSelectedIndex(index)}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => executeCommand(command)}\n >\n <span className=\"an-rich-md-slash-icon\">{command.icon}</span>\n <span>\n <span className=\"an-rich-md-slash-title\">{command.title}</span>\n <span className=\"an-rich-md-slash-description\">\n {command.description}\n </span>\n </span>\n </button>\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { Extension, Node, Mark } from "@tiptap/core";
|
|
2
|
+
import type { StarterKitOptions } from "@tiptap/starter-kit";
|
|
3
|
+
import { Markdown } from "tiptap-markdown";
|
|
4
|
+
import type { Doc as YDoc } from "yjs";
|
|
5
|
+
import type { Awareness } from "y-protocols/awareness";
|
|
6
|
+
import { type ImageUploadFn } from "./ImageExtension.js";
|
|
7
|
+
/**
|
|
8
|
+
* Markdown dialect the editor parses/serializes.
|
|
9
|
+
*
|
|
10
|
+
* - `gfm` — GitHub-Flavored Markdown. No raw HTML passthrough. The byte-stable
|
|
11
|
+
* serialization used by Plans (see RichMarkdownEditor.roundtrip.spec.ts).
|
|
12
|
+
* - `nfm` — the Notion-Flavored Markdown superset used by the Content editor,
|
|
13
|
+
* which opts into inline HTML so Notion-specific blocks round-trip.
|
|
14
|
+
*/
|
|
15
|
+
export type RichMarkdownDialect = "gfm" | "nfm";
|
|
16
|
+
/**
|
|
17
|
+
* Editor preset. Schema-neutral today (both presets share the base schema),
|
|
18
|
+
* but threaded through so an app can branch schema/behavior per preset without
|
|
19
|
+
* a new factory. The collab/markdown wiring is preset-independent.
|
|
20
|
+
*/
|
|
21
|
+
export type RichMarkdownEditorPreset = "plan" | "content";
|
|
22
|
+
/** User info used to label this client's collaborative cursor. */
|
|
23
|
+
export interface RichMarkdownCollabUser {
|
|
24
|
+
name: string;
|
|
25
|
+
color: string;
|
|
26
|
+
email?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Optional collaborative-editing inputs for the shared editor. */
|
|
29
|
+
export interface SharedEditorCollab {
|
|
30
|
+
/**
|
|
31
|
+
* Yjs document for collaborative editing. When present the editor binds the
|
|
32
|
+
* shared {@link Collaboration} (+ {@link CollaborationCaret} when awareness
|
|
33
|
+
* is set) extensions and StarterKit's built-in undo/redo is disabled (Yjs
|
|
34
|
+
* owns history). When absent the editor is a controlled `value`/`onChange`
|
|
35
|
+
* editor.
|
|
36
|
+
*/
|
|
37
|
+
ydoc?: YDoc | null;
|
|
38
|
+
/** Shared awareness instance for live multi-user cursors. */
|
|
39
|
+
awareness?: Awareness | null;
|
|
40
|
+
/** Current user info for the collaborative cursor label. */
|
|
41
|
+
user?: RichMarkdownCollabUser | null;
|
|
42
|
+
}
|
|
43
|
+
/** Toggle the optional base extensions on/off per app. All default to `true`. */
|
|
44
|
+
export interface SharedEditorFeatures {
|
|
45
|
+
/** GFM pipe tables (Table + TableRow + TableHeader + TableCell). */
|
|
46
|
+
tables?: boolean;
|
|
47
|
+
/** Task / checklist lists (TaskList + TaskItem). */
|
|
48
|
+
tasks?: boolean;
|
|
49
|
+
/** Inline links (the `Link` mark). When off, links fall back to plain text. */
|
|
50
|
+
link?: boolean;
|
|
51
|
+
/** Fenced code blocks. Disabling lets an app inject its own code-block node. */
|
|
52
|
+
codeBlock?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The built-in {@link Placeholder} extension. Default `true`. Apps that need a
|
|
55
|
+
* bespoke placeholder resolver (per-node-type labels, ancestor-aware text)
|
|
56
|
+
* disable this and supply their own Placeholder via `extraExtensions`.
|
|
57
|
+
*/
|
|
58
|
+
placeholder?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* The built-in dialect-keyed {@link Markdown} serializer. Default `true`.
|
|
61
|
+
* Apps with a custom serializer (e.g. Content's NFM converter, which does NOT
|
|
62
|
+
* round-trip through tiptap-markdown's storage) disable this and own the
|
|
63
|
+
* serialize/parse pipeline themselves. The Markdown extension is still added
|
|
64
|
+
* so paste/clipboard transforms work — disable it only when supplying your own
|
|
65
|
+
* Markdown configuration via the {@link CreateSharedEditorExtensionsOptions.markdown}
|
|
66
|
+
* option instead.
|
|
67
|
+
*/
|
|
68
|
+
markdown?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* The shared block-level image node (`@tiptap/extension-image`). Default
|
|
71
|
+
* `false` so existing embedders are unchanged. When `true`, images
|
|
72
|
+
* serialize to GFM `` (source-syncable) and — when an
|
|
73
|
+
* {@link CreateSharedEditorExtensionsOptions.onImageUpload} function is
|
|
74
|
+
* supplied — paste / drop of local image files uploads through it. Content
|
|
75
|
+
* leaves this off and injects its own richer image node via
|
|
76
|
+
* `extraExtensions`, so the two never collide.
|
|
77
|
+
*/
|
|
78
|
+
image?: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface CreateSharedEditorExtensionsOptions {
|
|
81
|
+
/** Markdown dialect; selects the keyed {@link Markdown} config. */
|
|
82
|
+
dialect?: RichMarkdownDialect;
|
|
83
|
+
/** Preset hook (schema-neutral today). */
|
|
84
|
+
preset?: RichMarkdownEditorPreset;
|
|
85
|
+
/** Empty-block placeholder text (headings get their own labels). */
|
|
86
|
+
placeholder?: string;
|
|
87
|
+
/** Toggle individual base extensions. */
|
|
88
|
+
features?: SharedEditorFeatures;
|
|
89
|
+
/**
|
|
90
|
+
* Extra StarterKit options merged over the shared defaults. Lets an app turn
|
|
91
|
+
* off StarterKit nodes it replaces (Content swaps in its own paragraph /
|
|
92
|
+
* blockquote / code block) or pass a custom dropcursor, while still sharing
|
|
93
|
+
* the rest of the StarterKit base + the collab undo/redo gating. The shared
|
|
94
|
+
* defaults (`heading` levels 1-4, `link: false`, the default dropcursor, and
|
|
95
|
+
* `undoRedo: false` in collab mode) are applied first and can be overridden
|
|
96
|
+
* key-by-key here.
|
|
97
|
+
*/
|
|
98
|
+
starterKit?: Partial<StarterKitOptions>;
|
|
99
|
+
/**
|
|
100
|
+
* Custom {@link Markdown} configuration. Replaces the dialect-keyed config from
|
|
101
|
+
* {@link MARKDOWN_DIALECT_CONFIG} when provided. Only used when
|
|
102
|
+
* `features.markdown !== false`; apps that own the whole markdown pipeline (no
|
|
103
|
+
* tiptap-markdown serialization at all) should set `features.markdown: false`
|
|
104
|
+
* and add their own configured Markdown extension via `extraExtensions`.
|
|
105
|
+
*/
|
|
106
|
+
markdown?: Parameters<typeof Markdown.configure>[0];
|
|
107
|
+
/**
|
|
108
|
+
* App-specific extensions (Notion nodes, media, drag handles, comment
|
|
109
|
+
* anchors, etc.) appended LAST so they bind over the shared base schema and
|
|
110
|
+
* the optional Collaboration extensions still mount after them.
|
|
111
|
+
*/
|
|
112
|
+
extraExtensions?: Array<Extension | Node | Mark>;
|
|
113
|
+
/** Optional collaborative-editing wiring. */
|
|
114
|
+
collab?: SharedEditorCollab | null;
|
|
115
|
+
/**
|
|
116
|
+
* Injectable image uploader for the shared image block. Only used when
|
|
117
|
+
* `features.image` is on. Turns a picked / pasted / dropped image File into a
|
|
118
|
+
* hosted `{ src, alt? }`. Plans pass `uploadEditorImage` (the framework
|
|
119
|
+
* `upload-image` action). When omitted, the image block still renders and
|
|
120
|
+
* round-trips `` markdown but cannot ingest local files.
|
|
121
|
+
*/
|
|
122
|
+
onImageUpload?: ImageUploadFn | null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* tiptap-markdown configuration, keyed by dialect. This is the single source of
|
|
126
|
+
* truth for how each dialect parses/serializes markdown so the editor component
|
|
127
|
+
* and the round-trip fidelity test can never drift apart.
|
|
128
|
+
*
|
|
129
|
+
* tiptap-markdown re-serializes the whole document on every edit, so the goal
|
|
130
|
+
* for GFM is `serialize(parse(markdown)) === markdown` for the markdown plans
|
|
131
|
+
* actually contain. We deliberately keep tiptap-markdown's own defaults
|
|
132
|
+
* (`bulletListMarker: "-"`, `tightLists: true`, `linkify: false`,
|
|
133
|
+
* `breaks: false`) because those produce the most byte-stable GFM. See
|
|
134
|
+
* RichMarkdownEditor.roundtrip.spec.ts for the pinned corpus.
|
|
135
|
+
*
|
|
136
|
+
* NFM (Content) opts into inline HTML passthrough (`html: true`) so
|
|
137
|
+
* Notion-specific blocks survive a markdown round-trip; the rest mirrors the
|
|
138
|
+
* Content editor's existing `Markdown.configure` call.
|
|
139
|
+
*/
|
|
140
|
+
export declare const MARKDOWN_DIALECT_CONFIG: Record<RichMarkdownDialect, Parameters<typeof Markdown.configure>[0]>;
|
|
141
|
+
/**
|
|
142
|
+
* The ONE editor extension factory shared by every embedder (Plans today,
|
|
143
|
+
* Content next). It assembles the base Tiptap schema (StarterKit + Placeholder
|
|
144
|
+
* + Link + tasks + tables + code block), the dialect-keyed {@link Markdown}
|
|
145
|
+
* serializer, the optional Collaboration stack, and finally any app-specific
|
|
146
|
+
* `extraExtensions`.
|
|
147
|
+
*
|
|
148
|
+
* Ordering matters:
|
|
149
|
+
* 1. Base schema (StarterKit first so its nodes/marks register; `starterKit`
|
|
150
|
+
* overrides let an app disable replaced nodes / swap the dropcursor).
|
|
151
|
+
* 2. dialect-keyed Markdown serializer (suppressible via `features.markdown`
|
|
152
|
+
* for apps that own the whole serialize/parse pipeline, e.g. Content's NFM).
|
|
153
|
+
* 3. `extraExtensions` (Notion/media/etc.) — appended before Collaboration so
|
|
154
|
+
* apps can extend the schema and Collaboration still binds over the full
|
|
155
|
+
* schema.
|
|
156
|
+
* 4. Collaboration (+ CollaborationCaret) LAST so they bind over everything.
|
|
157
|
+
*
|
|
158
|
+
* Content (the NFM editor) drives this factory with `features.placeholder` and
|
|
159
|
+
* `features.markdown` off, `features.tasks/tables/link` off where it ships its
|
|
160
|
+
* own, a `starterKit` override disabling paragraph/blockquote/codeBlock, and all
|
|
161
|
+
* Notion/media/fidelity nodes + its own Markdown(NFM)/Placeholder via
|
|
162
|
+
* `extraExtensions` — so it shares the StarterKit base + the collab wiring while
|
|
163
|
+
* owning its byte-identical NFM serializer.
|
|
164
|
+
*/
|
|
165
|
+
export declare function createSharedEditorExtensions({ dialect, preset: _preset, placeholder, features, starterKit, markdown, extraExtensions, collab, onImageUpload, }?: CreateSharedEditorExtensionsOptions): Array<Extension | Node | Mark>;
|
|
166
|
+
//# sourceMappingURL=extensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/extensions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
2
|
+
import Placeholder from "@tiptap/extension-placeholder";
|
|
3
|
+
import Link from "@tiptap/extension-link";
|
|
4
|
+
import TaskList from "@tiptap/extension-task-list";
|
|
5
|
+
import TaskItem from "@tiptap/extension-task-item";
|
|
6
|
+
import { Table } from "@tiptap/extension-table";
|
|
7
|
+
import { TableRow } from "@tiptap/extension-table-row";
|
|
8
|
+
import { TableCell } from "@tiptap/extension-table-cell";
|
|
9
|
+
import { TableHeader } from "@tiptap/extension-table-header";
|
|
10
|
+
import { Markdown } from "tiptap-markdown";
|
|
11
|
+
import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
|
|
12
|
+
import { createLowlight } from "lowlight";
|
|
13
|
+
import bash from "highlight.js/lib/languages/bash";
|
|
14
|
+
import css from "highlight.js/lib/languages/css";
|
|
15
|
+
import javascript from "highlight.js/lib/languages/javascript";
|
|
16
|
+
import json from "highlight.js/lib/languages/json";
|
|
17
|
+
import markdown from "highlight.js/lib/languages/markdown";
|
|
18
|
+
import python from "highlight.js/lib/languages/python";
|
|
19
|
+
import sql from "highlight.js/lib/languages/sql";
|
|
20
|
+
import typescript from "highlight.js/lib/languages/typescript";
|
|
21
|
+
import xml from "highlight.js/lib/languages/xml";
|
|
22
|
+
import yaml from "highlight.js/lib/languages/yaml";
|
|
23
|
+
import Collaboration from "@tiptap/extension-collaboration";
|
|
24
|
+
import CollaborationCaret from "@tiptap/extension-collaboration-caret";
|
|
25
|
+
/**
|
|
26
|
+
* Shared lowlight instance for the editor's syntax-highlighted code blocks. A
|
|
27
|
+
* curated grammar set (aliases like ts/tsx, js/jsx, html, sh, py, yml, md come
|
|
28
|
+
* for free from each grammar) keeps the editor bundle lean while matching the
|
|
29
|
+
* languages the read-side Shiki surfaces (`code-tabs`) support. highlight.js is
|
|
30
|
+
* synchronous, which is what a live ProseMirror editor needs — Shiki is async
|
|
31
|
+
* and only used for read-only render paths.
|
|
32
|
+
*/
|
|
33
|
+
const codeLowlight = createLowlight({
|
|
34
|
+
bash,
|
|
35
|
+
css,
|
|
36
|
+
javascript,
|
|
37
|
+
json,
|
|
38
|
+
markdown,
|
|
39
|
+
python,
|
|
40
|
+
sql,
|
|
41
|
+
typescript,
|
|
42
|
+
xml,
|
|
43
|
+
yaml,
|
|
44
|
+
});
|
|
45
|
+
import { createImageExtension } from "./ImageExtension.js";
|
|
46
|
+
/**
|
|
47
|
+
* tiptap-markdown configuration, keyed by dialect. This is the single source of
|
|
48
|
+
* truth for how each dialect parses/serializes markdown so the editor component
|
|
49
|
+
* and the round-trip fidelity test can never drift apart.
|
|
50
|
+
*
|
|
51
|
+
* tiptap-markdown re-serializes the whole document on every edit, so the goal
|
|
52
|
+
* for GFM is `serialize(parse(markdown)) === markdown` for the markdown plans
|
|
53
|
+
* actually contain. We deliberately keep tiptap-markdown's own defaults
|
|
54
|
+
* (`bulletListMarker: "-"`, `tightLists: true`, `linkify: false`,
|
|
55
|
+
* `breaks: false`) because those produce the most byte-stable GFM. See
|
|
56
|
+
* RichMarkdownEditor.roundtrip.spec.ts for the pinned corpus.
|
|
57
|
+
*
|
|
58
|
+
* NFM (Content) opts into inline HTML passthrough (`html: true`) so
|
|
59
|
+
* Notion-specific blocks survive a markdown round-trip; the rest mirrors the
|
|
60
|
+
* Content editor's existing `Markdown.configure` call.
|
|
61
|
+
*/
|
|
62
|
+
export const MARKDOWN_DIALECT_CONFIG = {
|
|
63
|
+
gfm: {
|
|
64
|
+
// GFM plans are the common case and must never gain raw HTML as a second
|
|
65
|
+
// representation.
|
|
66
|
+
html: false,
|
|
67
|
+
// Keep tiptap-markdown's defaults that minimise first-edit normalisation
|
|
68
|
+
// churn (see roundtrip spec). Listed explicitly so the contract is
|
|
69
|
+
// self-documenting rather than relying on the package defaults.
|
|
70
|
+
bulletListMarker: "-",
|
|
71
|
+
tightLists: true,
|
|
72
|
+
linkify: false,
|
|
73
|
+
breaks: false,
|
|
74
|
+
transformPastedText: true,
|
|
75
|
+
transformCopiedText: true,
|
|
76
|
+
},
|
|
77
|
+
nfm: {
|
|
78
|
+
// NFM is a superset that allows inline HTML so Notion blocks round-trip.
|
|
79
|
+
html: true,
|
|
80
|
+
transformPastedText: true,
|
|
81
|
+
transformCopiedText: true,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const DEFAULT_FEATURES = {
|
|
85
|
+
tables: true,
|
|
86
|
+
tasks: true,
|
|
87
|
+
link: true,
|
|
88
|
+
codeBlock: true,
|
|
89
|
+
placeholder: true,
|
|
90
|
+
markdown: true,
|
|
91
|
+
// Off by default: only Plans opt in today. Content injects its own richer
|
|
92
|
+
// image node via `extraExtensions` and must not get a second `image` node.
|
|
93
|
+
image: false,
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The ONE editor extension factory shared by every embedder (Plans today,
|
|
97
|
+
* Content next). It assembles the base Tiptap schema (StarterKit + Placeholder
|
|
98
|
+
* + Link + tasks + tables + code block), the dialect-keyed {@link Markdown}
|
|
99
|
+
* serializer, the optional Collaboration stack, and finally any app-specific
|
|
100
|
+
* `extraExtensions`.
|
|
101
|
+
*
|
|
102
|
+
* Ordering matters:
|
|
103
|
+
* 1. Base schema (StarterKit first so its nodes/marks register; `starterKit`
|
|
104
|
+
* overrides let an app disable replaced nodes / swap the dropcursor).
|
|
105
|
+
* 2. dialect-keyed Markdown serializer (suppressible via `features.markdown`
|
|
106
|
+
* for apps that own the whole serialize/parse pipeline, e.g. Content's NFM).
|
|
107
|
+
* 3. `extraExtensions` (Notion/media/etc.) — appended before Collaboration so
|
|
108
|
+
* apps can extend the schema and Collaboration still binds over the full
|
|
109
|
+
* schema.
|
|
110
|
+
* 4. Collaboration (+ CollaborationCaret) LAST so they bind over everything.
|
|
111
|
+
*
|
|
112
|
+
* Content (the NFM editor) drives this factory with `features.placeholder` and
|
|
113
|
+
* `features.markdown` off, `features.tasks/tables/link` off where it ships its
|
|
114
|
+
* own, a `starterKit` override disabling paragraph/blockquote/codeBlock, and all
|
|
115
|
+
* Notion/media/fidelity nodes + its own Markdown(NFM)/Placeholder via
|
|
116
|
+
* `extraExtensions` — so it shares the StarterKit base + the collab wiring while
|
|
117
|
+
* owning its byte-identical NFM serializer.
|
|
118
|
+
*/
|
|
119
|
+
export function createSharedEditorExtensions({ dialect = "gfm",
|
|
120
|
+
// `preset` is accepted and forwarded for future preset-specific schema
|
|
121
|
+
// branches; it is currently schema-neutral.
|
|
122
|
+
preset: _preset = "plan", placeholder = "Type '/' for commands...", features, starterKit, markdown, extraExtensions = [], collab = null, onImageUpload = null, } = {}) {
|
|
123
|
+
const feat = { ...DEFAULT_FEATURES, ...(features ?? {}) };
|
|
124
|
+
const ydoc = collab?.ydoc ?? null;
|
|
125
|
+
const awareness = collab?.awareness ?? null;
|
|
126
|
+
const user = collab?.user ?? null;
|
|
127
|
+
const exts = [
|
|
128
|
+
StarterKit.configure({
|
|
129
|
+
heading: { levels: [1, 2, 3, 4] },
|
|
130
|
+
link: false,
|
|
131
|
+
// StarterKit's plain code block is always disabled; when enabled we add the
|
|
132
|
+
// syntax-highlighting `CodeBlockLowlight` (same `codeBlock` node) below.
|
|
133
|
+
codeBlock: false,
|
|
134
|
+
dropcursor: { color: "hsl(var(--ring))", width: 2 },
|
|
135
|
+
// Yjs owns undo/redo when Collaboration is active; the StarterKit history
|
|
136
|
+
// plugin and the CRDT cannot both track undo without corrupting state.
|
|
137
|
+
...(ydoc ? { undoRedo: false } : {}),
|
|
138
|
+
// App overrides last so embedders can disable replaced nodes (paragraph,
|
|
139
|
+
// blockquote, code block) or swap the dropcursor while keeping the shared
|
|
140
|
+
// base + the collab undo/redo gating above.
|
|
141
|
+
...(starterKit ?? {}),
|
|
142
|
+
}),
|
|
143
|
+
];
|
|
144
|
+
// Syntax-highlighted code block (replaces StarterKit's plain one) only when the
|
|
145
|
+
// embedder opts in via `features.codeBlock`. Content disables it and ships its
|
|
146
|
+
// own code node, so this affects Plans (and future opt-in apps) alone.
|
|
147
|
+
if (feat.codeBlock) {
|
|
148
|
+
exts.push(CodeBlockLowlight.configure({
|
|
149
|
+
lowlight: codeLowlight,
|
|
150
|
+
defaultLanguage: null,
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
if (feat.placeholder) {
|
|
154
|
+
exts.push(Placeholder.configure({
|
|
155
|
+
placeholder: ({ node }) => {
|
|
156
|
+
if (node.type.name === "heading") {
|
|
157
|
+
const level = node.attrs.level;
|
|
158
|
+
if (level === 1)
|
|
159
|
+
return "Heading 1";
|
|
160
|
+
if (level === 2)
|
|
161
|
+
return "Heading 2";
|
|
162
|
+
if (level === 3)
|
|
163
|
+
return "Heading 3";
|
|
164
|
+
return "Heading 4";
|
|
165
|
+
}
|
|
166
|
+
return placeholder;
|
|
167
|
+
},
|
|
168
|
+
showOnlyWhenEditable: true,
|
|
169
|
+
showOnlyCurrent: true,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
if (feat.link) {
|
|
173
|
+
exts.push(Link.configure({
|
|
174
|
+
openOnClick: false,
|
|
175
|
+
HTMLAttributes: { class: "an-rich-md-link" },
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
if (feat.tasks) {
|
|
179
|
+
exts.push(TaskList.configure({
|
|
180
|
+
HTMLAttributes: { class: "an-rich-md-task-list" },
|
|
181
|
+
}), TaskItem.configure({ nested: true }));
|
|
182
|
+
}
|
|
183
|
+
if (feat.tables) {
|
|
184
|
+
exts.push(Table.configure({
|
|
185
|
+
resizable: false,
|
|
186
|
+
HTMLAttributes: { class: "an-rich-md-table" },
|
|
187
|
+
}), TableRow, TableHeader, TableCell);
|
|
188
|
+
}
|
|
189
|
+
if (feat.markdown) {
|
|
190
|
+
exts.push(Markdown.configure(markdown ?? MARKDOWN_DIALECT_CONFIG[dialect]));
|
|
191
|
+
}
|
|
192
|
+
// Shared block-level image node. The node is named `image`, so when
|
|
193
|
+
// `features.markdown` is on, tiptap-markdown serializes it through its
|
|
194
|
+
// built-in `defaultMarkdownSerializer.nodes.image` fallback → ``
|
|
195
|
+
// (no width-as-HTML override here, so GFM stays byte-stable and
|
|
196
|
+
// source-syncable). With an `onImageUpload` it accepts paste/drop uploads.
|
|
197
|
+
if (feat.image) {
|
|
198
|
+
exts.push(createImageExtension({ onImageUpload }));
|
|
199
|
+
}
|
|
200
|
+
// App-specific extensions (Notion/media/drag handles/comments). Appended
|
|
201
|
+
// before Collaboration so they can extend the schema and Collaboration binds
|
|
202
|
+
// over the full set.
|
|
203
|
+
if (extraExtensions.length > 0) {
|
|
204
|
+
exts.push(...extraExtensions);
|
|
205
|
+
}
|
|
206
|
+
// Collaborative editing via the shared Y.Doc. Markdown stays the canonical
|
|
207
|
+
// saved representation (onChange serializes it); the Y.Doc is transient live
|
|
208
|
+
// state only. Appended last so it binds over the configured schema above.
|
|
209
|
+
if (ydoc) {
|
|
210
|
+
exts.push(Collaboration.configure({ document: ydoc }));
|
|
211
|
+
// Live multi-user cursors. Only mounted alongside a Y.Doc so the standalone
|
|
212
|
+
// controlled editor (today's plan/content behavior) is untouched.
|
|
213
|
+
if (awareness) {
|
|
214
|
+
exts.push(CollaborationCaret.configure({
|
|
215
|
+
provider: { awareness },
|
|
216
|
+
user: user ?? { name: "Anonymous", color: "#999" },
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return exts;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=extensions.js.map
|