@agent-native/core 0.7.13 → 0.7.15
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 +56 -6
- package/dist/a2a/client.d.ts +44 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +88 -11
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts +10 -0
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +417 -67
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +212 -19
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +20 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +72 -2
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/default-model.d.ts +21 -0
- package/dist/agent/default-model.d.ts.map +1 -0
- package/dist/agent/default-model.js +21 -0
- package/dist/agent/default-model.js.map +1 -0
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +7 -4
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +10 -4
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +11 -26
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/builtin.js +1 -1
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +27 -7
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +101 -20
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +25 -3
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +227 -36
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/handlers.js +10 -6
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/application-state/script-helpers.d.ts +1 -1
- package/dist/application-state/script-helpers.d.ts.map +1 -1
- package/dist/application-state/script-helpers.js +12 -8
- package/dist/application-state/script-helpers.js.map +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +19 -10
- package/dist/application-state/store.js.map +1 -1
- package/dist/chat-threads/store.d.ts +3 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +36 -1
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +79 -13
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +97 -39
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/templates-meta.d.ts +4 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +67 -12
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspacify.d.ts +2 -0
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +5 -4
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +7 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +81 -32
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AgentTaskCard.d.ts.map +1 -1
- package/dist/client/AgentTaskCard.js +5 -2
- package/dist/client/AgentTaskCard.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +183 -84
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +2 -1
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/DefaultSpinner.d.ts +1 -1
- package/dist/client/DefaultSpinner.d.ts.map +1 -1
- package/dist/client/DefaultSpinner.js +2 -9
- package/dist/client/DefaultSpinner.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts +1 -3
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +37 -9
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +4 -3
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +165 -68
- 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 +2 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts +11 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +4 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +70 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/api-path.d.ts +5 -0
- package/dist/client/api-path.d.ts.map +1 -0
- package/dist/client/api-path.js +48 -0
- package/dist/client/api-path.js.map +1 -0
- package/dist/client/components/AgentPresenceChip.d.ts +12 -0
- package/dist/client/components/AgentPresenceChip.d.ts.map +1 -0
- package/dist/client/components/AgentPresenceChip.js +42 -0
- package/dist/client/components/AgentPresenceChip.js.map +1 -0
- package/dist/client/components/ApiKeySettings.d.ts.map +1 -1
- package/dist/client/components/ApiKeySettings.js +3 -2
- package/dist/client/components/ApiKeySettings.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +3 -2
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts +17 -0
- package/dist/client/components/PresenceBar.d.ts.map +1 -0
- package/dist/client/components/PresenceBar.js +118 -0
- package/dist/client/components/PresenceBar.js.map +1 -0
- package/dist/client/composer/ComposerPlusMenu.d.ts +6 -1
- package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.js +22 -83
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +3 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +245 -23
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/draft-key.d.ts +2 -0
- package/dist/client/composer/draft-key.d.ts.map +1 -0
- package/dist/client/composer/draft-key.js +8 -0
- package/dist/client/composer/draft-key.js.map +1 -0
- package/dist/client/composer/types.d.ts +1 -0
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/use-file-search.d.ts.map +1 -1
- package/dist/client/composer/use-file-search.js +2 -1
- package/dist/client/composer/use-file-search.js.map +1 -1
- package/dist/client/composer/use-mention-search.d.ts.map +1 -1
- package/dist/client/composer/use-mention-search.js +2 -1
- package/dist/client/composer/use-mention-search.js.map +1 -1
- package/dist/client/composer/use-skills.d.ts.map +1 -1
- package/dist/client/composer/use-skills.js +2 -1
- package/dist/client/composer/use-skills.js.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts +3 -1
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +101 -18
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/dev-mode.d.ts +14 -0
- package/dist/client/dev-mode.d.ts.map +1 -0
- package/dist/client/dev-mode.js +14 -0
- package/dist/client/dev-mode.js.map +1 -0
- package/dist/client/dev-overlay/DevOverlay.d.ts +26 -0
- package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -0
- package/dist/client/dev-overlay/DevOverlay.js +315 -0
- package/dist/client/dev-overlay/DevOverlay.js.map +1 -0
- package/dist/client/dev-overlay/builtins.d.ts +6 -0
- package/dist/client/dev-overlay/builtins.d.ts.map +1 -0
- package/dist/client/dev-overlay/builtins.js +35 -0
- package/dist/client/dev-overlay/builtins.js.map +1 -0
- package/dist/client/dev-overlay/index.d.ts +6 -0
- package/dist/client/dev-overlay/index.d.ts.map +1 -0
- package/dist/client/dev-overlay/index.js +5 -0
- package/dist/client/dev-overlay/index.js.map +1 -0
- package/dist/client/dev-overlay/registry.d.ts +13 -0
- package/dist/client/dev-overlay/registry.d.ts.map +1 -0
- package/dist/client/dev-overlay/registry.js +63 -0
- package/dist/client/dev-overlay/registry.js.map +1 -0
- package/dist/client/dev-overlay/types.d.ts +56 -0
- package/dist/client/dev-overlay/types.d.ts.map +1 -0
- package/dist/client/dev-overlay/types.js +9 -0
- package/dist/client/dev-overlay/types.js.map +1 -0
- package/dist/client/dev-overlay/use-dev-option.d.ts +12 -0
- package/dist/client/dev-overlay/use-dev-option.d.ts.map +1 -0
- package/dist/client/dev-overlay/use-dev-option.js +73 -0
- package/dist/client/dev-overlay/use-dev-option.js.map +1 -0
- package/dist/client/dev-overlay/use-dev-overlay-shortcut.d.ts +6 -0
- package/dist/client/dev-overlay/use-dev-overlay-shortcut.d.ts.map +1 -0
- package/dist/client/dev-overlay/use-dev-overlay-shortcut.js +29 -0
- package/dist/client/dev-overlay/use-dev-overlay-shortcut.js.map +1 -0
- package/dist/client/frame.d.ts +1 -0
- package/dist/client/frame.d.ts.map +1 -1
- package/dist/client/frame.js +32 -11
- package/dist/client/frame.js.map +1 -1
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/integrations/IntegrationCard.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationCard.js +3 -2
- package/dist/client/integrations/IntegrationCard.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -2
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/integrations/useIntegrationStatus.d.ts.map +1 -1
- package/dist/client/integrations/useIntegrationStatus.js +2 -1
- package/dist/client/integrations/useIntegrationStatus.js.map +1 -1
- package/dist/client/notifications/NotificationsBell.d.ts.map +1 -1
- package/dist/client/notifications/NotificationsBell.js +26 -8
- package/dist/client/notifications/NotificationsBell.js.map +1 -1
- package/dist/client/observability/ThumbsFeedback.d.ts.map +1 -1
- package/dist/client/observability/ThumbsFeedback.js +2 -1
- package/dist/client/observability/ThumbsFeedback.js.map +1 -1
- package/dist/client/observability/useObservability.d.ts.map +1 -1
- package/dist/client/observability/useObservability.js +2 -1
- package/dist/client/observability/useObservability.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.d.ts +0 -7
- package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +20 -10
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/onboarding/index.d.ts +1 -0
- package/dist/client/onboarding/index.d.ts.map +1 -1
- package/dist/client/onboarding/index.js +1 -0
- package/dist/client/onboarding/index.js.map +1 -1
- package/dist/client/onboarding/use-onboarding.d.ts +1 -7
- package/dist/client/onboarding/use-onboarding.d.ts.map +1 -1
- package/dist/client/onboarding/use-onboarding.js +27 -13
- package/dist/client/onboarding/use-onboarding.js.map +1 -1
- package/dist/client/onboarding/use-preview-mode.d.ts +10 -0
- package/dist/client/onboarding/use-preview-mode.d.ts.map +1 -0
- package/dist/client/onboarding/use-preview-mode.js +35 -0
- package/dist/client/onboarding/use-preview-mode.js.map +1 -0
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +2 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
- package/dist/client/org/RequireActiveOrg.js +15 -10
- package/dist/client/org/RequireActiveOrg.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +132 -9
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +30 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +67 -1
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +2 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +2 -1
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/resources/McpServerDetail.d.ts +0 -8
- package/dist/client/resources/McpServerDetail.d.ts.map +1 -1
- package/dist/client/resources/McpServerDetail.js +6 -1
- package/dist/client/resources/McpServerDetail.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/client/resources/ResourceEditor.js +2 -1
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +7 -2
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/use-mcp-servers.d.ts.map +1 -1
- package/dist/client/resources/use-mcp-servers.js +7 -2
- package/dist/client/resources/use-mcp-servers.js.map +1 -1
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +9 -7
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/settings/AgentsSection.d.ts.map +1 -1
- package/dist/client/settings/AgentsSection.js +7 -5
- package/dist/client/settings/AgentsSection.js.map +1 -1
- package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
- package/dist/client/settings/AutomationsSection.js +10 -5
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.js +2 -1
- package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +12 -4
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +38 -33
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/UsageSection.d.ts.map +1 -1
- package/dist/client/settings/UsageSection.js +2 -1
- package/dist/client/settings/UsageSection.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +2 -4
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +66 -23
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +9 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +31 -3
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +7 -2
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +4 -3
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts +1 -0
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +12 -8
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/tools/EmbeddedTool.d.ts +20 -0
- package/dist/client/tools/EmbeddedTool.d.ts.map +1 -0
- package/dist/client/tools/EmbeddedTool.js +113 -0
- package/dist/client/tools/EmbeddedTool.js.map +1 -0
- package/dist/client/tools/ExtensionSlot.d.ts +27 -0
- package/dist/client/tools/ExtensionSlot.d.ts.map +1 -0
- package/dist/client/tools/ExtensionSlot.js +96 -0
- package/dist/client/tools/ExtensionSlot.js.map +1 -0
- package/dist/client/tools/ToolEditor.d.ts +5 -0
- package/dist/client/tools/ToolEditor.d.ts.map +1 -0
- package/dist/client/tools/ToolEditor.js +99 -0
- package/dist/client/tools/ToolEditor.js.map +1 -0
- package/dist/client/tools/ToolViewer.d.ts +5 -0
- package/dist/client/tools/ToolViewer.d.ts.map +1 -0
- package/dist/client/tools/ToolViewer.js +275 -0
- package/dist/client/tools/ToolViewer.js.map +1 -0
- package/dist/client/tools/ToolViewerPage.d.ts +2 -0
- package/dist/client/tools/ToolViewerPage.d.ts.map +1 -0
- package/dist/client/tools/ToolViewerPage.js +24 -0
- package/dist/client/tools/ToolViewerPage.js.map +1 -0
- package/dist/client/tools/ToolsListPage.d.ts +2 -0
- package/dist/client/tools/ToolsListPage.d.ts.map +1 -0
- package/dist/client/tools/ToolsListPage.js +73 -0
- package/dist/client/tools/ToolsListPage.js.map +1 -0
- package/dist/client/tools/ToolsSidebarSection.d.ts +2 -0
- package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -0
- package/dist/client/tools/ToolsSidebarSection.js +189 -0
- package/dist/client/tools/ToolsSidebarSection.js.map +1 -0
- package/dist/client/tools/iframe-bridge.d.ts +16 -0
- package/dist/client/tools/iframe-bridge.d.ts.map +1 -0
- package/dist/client/tools/iframe-bridge.js +118 -0
- package/dist/client/tools/iframe-bridge.js.map +1 -0
- package/dist/client/tools/index.d.ts +8 -0
- package/dist/client/tools/index.d.ts.map +1 -0
- package/dist/client/tools/index.js +8 -0
- package/dist/client/tools/index.js.map +1 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +2 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-avatar.d.ts.map +1 -1
- package/dist/client/use-avatar.js +3 -2
- package/dist/client/use-avatar.js.map +1 -1
- package/dist/client/use-builder-enabled.d.ts.map +1 -1
- package/dist/client/use-builder-enabled.js +2 -1
- package/dist/client/use-builder-enabled.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +1 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +31 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +9 -8
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-dev-mode.d.ts.map +1 -1
- package/dist/client/use-dev-mode.js +2 -1
- package/dist/client/use-dev-mode.js.map +1 -1
- package/dist/client/use-send-to-agent-chat.d.ts.map +1 -1
- package/dist/client/use-send-to-agent-chat.js +3 -1
- package/dist/client/use-send-to-agent-chat.js.map +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +2 -1
- package/dist/client/use-session.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +2 -1
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/collab/agent-identity.d.ts +15 -0
- package/dist/collab/agent-identity.d.ts.map +1 -0
- package/dist/collab/agent-identity.js +14 -0
- package/dist/collab/agent-identity.js.map +1 -0
- package/dist/collab/agent-presence.d.ts +59 -0
- package/dist/collab/agent-presence.d.ts.map +1 -0
- package/dist/collab/agent-presence.js +165 -0
- package/dist/collab/agent-presence.js.map +1 -0
- package/dist/collab/awareness.d.ts +7 -0
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +2 -2
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client-struct.d.ts +43 -0
- package/dist/collab/client-struct.d.ts.map +1 -0
- package/dist/collab/client-struct.js +272 -0
- package/dist/collab/client-struct.js.map +1 -0
- package/dist/collab/client.d.ts +2 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +18 -3
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +6 -1
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +11 -1
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/json-to-yjs.d.ts +72 -0
- package/dist/collab/json-to-yjs.d.ts.map +1 -0
- package/dist/collab/json-to-yjs.js +456 -0
- package/dist/collab/json-to-yjs.js.map +1 -0
- package/dist/collab/struct-routes.d.ts +52 -0
- package/dist/collab/struct-routes.d.ts.map +1 -0
- package/dist/collab/struct-routes.js +74 -0
- package/dist/collab/struct-routes.js.map +1 -0
- package/dist/collab/ydoc-manager.d.ts +19 -0
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +49 -0
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/credentials/index.d.ts +27 -10
- package/dist/credentials/index.d.ts.map +1 -1
- package/dist/credentials/index.js +61 -19
- package/dist/credentials/index.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +10 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations.d.ts +13 -5
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +9 -2
- package/dist/db/migrations.js.map +1 -1
- package/dist/deploy/build.d.ts +12 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +196 -24
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +2 -1
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +25 -1
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts +17 -0
- package/dist/integrations/adapters/email.d.ts.map +1 -0
- package/dist/integrations/adapters/email.js +740 -0
- package/dist/integrations/adapters/email.js.map +1 -0
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +190 -32
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +56 -5
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +91 -12
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +5 -2
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +1 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/internal-token.d.ts +18 -0
- package/dist/integrations/internal-token.d.ts.map +1 -0
- package/dist/integrations/internal-token.js +102 -0
- package/dist/integrations/internal-token.js.map +1 -0
- package/dist/integrations/pending-tasks-retry-job.d.ts +15 -0
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -0
- package/dist/integrations/pending-tasks-retry-job.js +210 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -0
- package/dist/integrations/pending-tasks-store.d.ts +56 -0
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -0
- package/dist/integrations/pending-tasks-store.js +204 -0
- package/dist/integrations/pending-tasks-store.js.map +1 -0
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +340 -15
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/task-queue-stats.d.ts +22 -0
- package/dist/integrations/task-queue-stats.d.ts.map +1 -0
- package/dist/integrations/task-queue-stats.js +117 -0
- package/dist/integrations/task-queue-stats.js.map +1 -0
- package/dist/integrations/types.d.ts +35 -2
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +29 -4
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +323 -85
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/cron.d.ts.map +1 -1
- package/dist/jobs/cron.js +12 -4
- package/dist/jobs/cron.js.map +1 -1
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +141 -16
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +94 -3
- package/dist/jobs/tools.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +128 -62
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp-client/hub-routes.d.ts +14 -0
- package/dist/mcp-client/hub-routes.d.ts.map +1 -1
- package/dist/mcp-client/hub-routes.js +42 -2
- package/dist/mcp-client/hub-routes.js.map +1 -1
- package/dist/mcp-client/index.d.ts +1 -1
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +1 -1
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/manager.d.ts +3 -0
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +33 -3
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/remote-store.d.ts +49 -1
- package/dist/mcp-client/remote-store.d.ts.map +1 -1
- package/dist/mcp-client/remote-store.js +253 -6
- package/dist/mcp-client/remote-store.js.map +1 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +11 -9
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/mcp-client/visibility.d.ts +7 -3
- package/dist/mcp-client/visibility.d.ts.map +1 -1
- package/dist/mcp-client/visibility.js +16 -7
- package/dist/mcp-client/visibility.js.map +1 -1
- package/dist/notifications/actions.d.ts.map +1 -1
- package/dist/notifications/actions.js +7 -1
- package/dist/notifications/actions.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts.map +1 -1
- package/dist/notifications/routes.js +20 -3
- package/dist/notifications/routes.js.map +1 -1
- package/dist/notifications/store.d.ts.map +1 -1
- package/dist/notifications/store.js +6 -1
- package/dist/notifications/store.js.map +1 -1
- package/dist/oauth-tokens/google-refresh.d.ts.map +1 -1
- package/dist/oauth-tokens/google-refresh.js +6 -0
- package/dist/oauth-tokens/google-refresh.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts +43 -2
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +83 -14
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/observability/experiments.js +5 -5
- package/dist/observability/experiments.js.map +1 -1
- package/dist/observability/routes.d.ts.map +1 -1
- package/dist/observability/routes.js +37 -8
- package/dist/observability/routes.js.map +1 -1
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +19 -3
- package/dist/observability/store.js.map +1 -1
- package/dist/observability/types.d.ts +7 -0
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +10 -4
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/plugin.d.ts.map +1 -1
- package/dist/onboarding/plugin.js +63 -32
- package/dist/onboarding/plugin.js.map +1 -1
- package/dist/onboarding/types.d.ts +6 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/org/accept-pending.d.ts.map +1 -1
- package/dist/org/accept-pending.js +2 -1
- package/dist/org/accept-pending.js.map +1 -1
- package/dist/org/context.d.ts +35 -0
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +136 -0
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts +76 -0
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +411 -2
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/index.d.ts +2 -2
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +2 -2
- package/dist/org/index.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +8 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +6 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +71 -7
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +38 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +2 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/org/types.d.ts +7 -0
- package/dist/org/types.d.ts.map +1 -1
- package/dist/progress/actions.d.ts.map +1 -1
- package/dist/progress/actions.js +10 -1
- package/dist/progress/actions.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts.map +1 -1
- package/dist/progress/routes.js +20 -3
- package/dist/progress/routes.js.map +1 -1
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +6 -1
- package/dist/progress/store.js.map +1 -1
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +35 -7
- package/dist/resources/handlers.js.map +1 -1
- package/dist/resources/script-helpers.d.ts.map +1 -1
- package/dist/resources/script-helpers.js +15 -3
- package/dist/resources/script-helpers.js.map +1 -1
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +12 -4
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/call-agent.d.ts +1 -0
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +146 -36
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/chat/search-chats.d.ts.map +1 -1
- package/dist/scripts/chat/search-chats.js +3 -2
- package/dist/scripts/chat/search-chats.js.map +1 -1
- package/dist/scripts/db/exec.d.ts +1 -1
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +22 -3
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/index.d.ts.map +1 -1
- package/dist/scripts/db/index.js +2 -0
- package/dist/scripts/db/index.js.map +1 -1
- package/dist/scripts/db/migrate-user-api-keys.d.ts +24 -0
- package/dist/scripts/db/migrate-user-api-keys.d.ts.map +1 -0
- package/dist/scripts/db/migrate-user-api-keys.js +234 -0
- package/dist/scripts/db/migrate-user-api-keys.js.map +1 -0
- package/dist/scripts/db/query.d.ts +1 -1
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +22 -3
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/scoping.d.ts.map +1 -1
- package/dist/scripts/db/scoping.js +15 -9
- package/dist/scripts/db/scoping.js.map +1 -1
- package/dist/scripts/db/wipe-leaked-builder-keys.d.ts +27 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.d.ts.map +1 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.js +163 -0
- package/dist/scripts/db/wipe-leaked-builder-keys.js.map +1 -0
- package/dist/scripts/dev/shell.d.ts.map +1 -1
- package/dist/scripts/dev/shell.js +3 -1
- package/dist/scripts/dev/shell.js.map +1 -1
- package/dist/scripts/resources/delete-memory.d.ts.map +1 -1
- package/dist/scripts/resources/delete-memory.js +2 -1
- package/dist/scripts/resources/delete-memory.js.map +1 -1
- package/dist/scripts/resources/delete.d.ts.map +1 -1
- package/dist/scripts/resources/delete.js +2 -1
- package/dist/scripts/resources/delete.js.map +1 -1
- package/dist/scripts/resources/list.d.ts.map +1 -1
- package/dist/scripts/resources/list.js +2 -1
- package/dist/scripts/resources/list.js.map +1 -1
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -1
- package/dist/scripts/resources/migrate-learnings.js +2 -1
- package/dist/scripts/resources/migrate-learnings.js.map +1 -1
- package/dist/scripts/resources/read.d.ts.map +1 -1
- package/dist/scripts/resources/read.js +2 -1
- package/dist/scripts/resources/read.js.map +1 -1
- package/dist/scripts/resources/save-memory.d.ts.map +1 -1
- package/dist/scripts/resources/save-memory.js +2 -1
- package/dist/scripts/resources/save-memory.js.map +1 -1
- package/dist/scripts/resources/write.d.ts.map +1 -1
- package/dist/scripts/resources/write.js +2 -1
- package/dist/scripts/resources/write.js.map +1 -1
- package/dist/secrets/onboarding.d.ts.map +1 -1
- package/dist/secrets/onboarding.js +24 -16
- package/dist/secrets/onboarding.js.map +1 -1
- package/dist/secrets/register-framework-secrets.d.ts +5 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +7 -44
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/secrets/routes.d.ts.map +1 -1
- package/dist/secrets/routes.js +139 -37
- package/dist/secrets/routes.js.map +1 -1
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +23 -12
- package/dist/secrets/storage.js.map +1 -1
- package/dist/secrets/substitution.d.ts +24 -2
- package/dist/secrets/substitution.d.ts.map +1 -1
- package/dist/secrets/substitution.js +58 -8
- package/dist/secrets/substitution.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +54 -51
- 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 +42 -15
- 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 +632 -373
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +8 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +39 -12
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +4 -1
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/analytics.d.ts +0 -1
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +0 -1
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/app-base-path.d.ts +4 -0
- package/dist/server/app-base-path.d.ts.map +1 -0
- package/dist/server/app-base-path.js +33 -0
- package/dist/server/app-base-path.js.map +1 -0
- package/dist/server/auth.d.ts +29 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +629 -82
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +67 -15
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts +16 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +102 -16
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/cli-capture.d.ts +31 -0
- package/dist/server/cli-capture.d.ts.map +1 -0
- package/dist/server/cli-capture.js +120 -0
- package/dist/server/cli-capture.js.map +1 -0
- package/dist/server/collab-plugin.d.ts +16 -0
- package/dist/server/collab-plugin.d.ts.map +1 -1
- package/dist/server/collab-plugin.js +87 -19
- package/dist/server/collab-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +499 -164
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts +2 -0
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +82 -11
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/credential-provider.d.ts +54 -2
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +164 -2
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/csrf.d.ts +58 -0
- package/dist/server/csrf.d.ts.map +1 -0
- package/dist/server/csrf.js +165 -0
- package/dist/server/csrf.js.map +1 -0
- package/dist/server/design-token-utils.d.ts +132 -0
- package/dist/server/design-token-utils.d.ts.map +1 -0
- package/dist/server/design-token-utils.js +714 -0
- package/dist/server/design-token-utils.js.map +1 -0
- package/dist/server/email.d.ts +10 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +63 -16
- package/dist/server/email.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts +20 -0
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +140 -24
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-auth-plugin.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +10 -2
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts +102 -3
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +263 -43
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/index.d.ts +5 -5
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/oauth-helpers.d.ts +8 -3
- package/dist/server/oauth-helpers.d.ts.map +1 -1
- package/dist/server/oauth-helpers.js +12 -8
- package/dist/server/oauth-helpers.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +50 -9
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll.d.ts +33 -0
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +43 -2
- package/dist/server/poll.js.map +1 -1
- package/dist/server/request-context.d.ts +102 -3
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +100 -7
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/security-headers.d.ts +51 -0
- package/dist/server/security-headers.d.ts.map +1 -0
- package/dist/server/security-headers.js +90 -0
- package/dist/server/security-headers.js.map +1 -0
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +96 -2
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +376 -60
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/server/voice-providers-status.d.ts +12 -0
- package/dist/server/voice-providers-status.d.ts.map +1 -0
- package/dist/server/voice-providers-status.js +71 -0
- package/dist/server/voice-providers-status.js.map +1 -0
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +16 -13
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts +1 -0
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +45 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/schema.d.ts +1 -1
- package/dist/styles/agent-native.css +5 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +54 -0
- package/dist/templates/default/app/root.tsx +51 -14
- package/dist/templates/default/app/routes/_index.tsx +6 -1
- package/dist/templates/default/public/favicon.svg +13 -0
- package/dist/templates/default/public/icon-180.svg +12 -3
- package/dist/templates/default/public/icon-192.svg +12 -3
- package/dist/templates/default/public/icon-512.svg +12 -3
- package/dist/templates/default/react-router.config.ts +3 -0
- package/dist/templates/workspace-core/package.json +22 -4
- package/dist/templates/workspace-core/src/credentials.ts +32 -5
- package/dist/templates/workspace-core/tsconfig.json +4 -1
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +7 -1
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +26 -6
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/dist/tools/actions.d.ts +3 -0
- package/dist/tools/actions.d.ts.map +1 -0
- package/dist/tools/actions.js +270 -0
- package/dist/tools/actions.js.map +1 -0
- package/dist/tools/fetch-tool.d.ts +1 -0
- package/dist/tools/fetch-tool.d.ts.map +1 -1
- package/dist/tools/fetch-tool.js +39 -17
- package/dist/tools/fetch-tool.js.map +1 -1
- package/dist/tools/html-shell.d.ts +44 -0
- package/dist/tools/html-shell.d.ts.map +1 -0
- package/dist/tools/html-shell.js +485 -0
- package/dist/tools/html-shell.js.map +1 -0
- package/dist/tools/proxy-security.d.ts +12 -0
- package/dist/tools/proxy-security.d.ts.map +1 -0
- package/dist/tools/proxy-security.js +158 -0
- package/dist/tools/proxy-security.js.map +1 -0
- package/dist/tools/routes.d.ts +2 -0
- package/dist/tools/routes.d.ts.map +1 -0
- package/dist/tools/routes.js +629 -0
- package/dist/tools/routes.js.map +1 -0
- package/dist/tools/schema.d.ts +578 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +115 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/tools/slots/routes.d.ts +15 -0
- package/dist/tools/slots/routes.d.ts.map +1 -0
- package/dist/tools/slots/routes.js +94 -0
- package/dist/tools/slots/routes.js.map +1 -0
- package/dist/tools/slots/schema.d.ts +303 -0
- package/dist/tools/slots/schema.d.ts.map +1 -0
- package/dist/tools/slots/schema.js +76 -0
- package/dist/tools/slots/schema.js.map +1 -0
- package/dist/tools/slots/store.d.ts +66 -0
- package/dist/tools/slots/store.d.ts.map +1 -0
- package/dist/tools/slots/store.js +227 -0
- package/dist/tools/slots/store.js.map +1 -0
- package/dist/tools/store.d.ts +40 -0
- package/dist/tools/store.d.ts.map +1 -0
- package/dist/tools/store.js +181 -0
- package/dist/tools/store.js.map +1 -0
- package/dist/tools/theme.d.ts +2 -0
- package/dist/tools/theme.d.ts.map +1 -0
- package/dist/tools/theme.js +67 -0
- package/dist/tools/theme.js.map +1 -0
- package/dist/tools/url-safety.d.ts +24 -0
- package/dist/tools/url-safety.d.ts.map +1 -0
- package/dist/tools/url-safety.js +224 -0
- package/dist/tools/url-safety.js.map +1 -0
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +28 -11
- package/dist/tracking/providers.js.map +1 -1
- package/dist/tracking/registry.d.ts.map +1 -1
- package/dist/tracking/registry.js +7 -3
- package/dist/tracking/registry.js.map +1 -1
- package/dist/transcription/builder-transcription.d.ts.map +1 -1
- package/dist/transcription/builder-transcription.js +26 -14
- package/dist/transcription/builder-transcription.js.map +1 -1
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +11 -6
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/condition-evaluator.d.ts +8 -0
- package/dist/triggers/condition-evaluator.d.ts.map +1 -1
- package/dist/triggers/condition-evaluator.js +39 -4
- package/dist/triggers/condition-evaluator.js.map +1 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +67 -4
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +18 -7
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/dist/vite/client.d.ts +2 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +240 -8
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.md +2 -2
- package/docs/content/authentication.md +78 -12
- package/docs/content/cloneable-saas.md +59 -62
- package/docs/content/drop-in-agent.md +2 -2
- package/docs/content/faq.md +73 -43
- package/docs/content/getting-started.md +37 -61
- package/docs/content/mcp-clients.md +14 -1
- package/docs/content/messaging.md +324 -0
- package/docs/content/onboarding.md +82 -12
- package/docs/content/pure-agent-apps.md +55 -28
- package/docs/content/template-analytics.md +65 -59
- package/docs/content/template-calendar.md +61 -56
- package/docs/content/template-clips.md +25 -23
- package/docs/content/template-content.md +36 -26
- package/docs/content/template-design.md +55 -0
- package/docs/content/template-dispatch.md +15 -1
- package/docs/content/template-forms.md +19 -16
- package/docs/content/template-mail.md +78 -80
- package/docs/content/template-slides.md +43 -31
- package/docs/content/template-video.md +49 -22
- package/docs/content/tools.md +107 -0
- package/docs/content/what-is-agent-native.md +89 -105
- package/package.json +5 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +54 -0
- package/src/templates/default/app/root.tsx +51 -14
- package/src/templates/default/app/routes/_index.tsx +6 -1
- package/src/templates/default/public/favicon.svg +13 -0
- package/src/templates/default/public/icon-180.svg +12 -3
- package/src/templates/default/public/icon-192.svg +12 -3
- package/src/templates/default/public/icon-512.svg +12 -3
- package/src/templates/default/react-router.config.ts +3 -0
- package/src/templates/workspace-core/package.json +22 -4
- package/src/templates/workspace-core/src/credentials.ts +32 -5
- package/src/templates/workspace-core/tsconfig.json +4 -1
- package/docs/content/integrations.md +0 -198
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
import { getHeader, readRawBody as h3ReadRawBody } from "h3";
|
|
2
|
+
import { timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { getIntegrationConfig } from "../config-store.js";
|
|
4
|
+
import { getDbExec } from "../../db/client.js";
|
|
5
|
+
import { sendEmail, isEmailConfigured, getEmailProvider, } from "../../server/email.js";
|
|
6
|
+
/** Max body length before truncation */
|
|
7
|
+
const EMAIL_MAX_BODY_LENGTH = 15000;
|
|
8
|
+
/** Rate limit: max emails per sender within the window */
|
|
9
|
+
const RATE_LIMIT_MAX = 20;
|
|
10
|
+
/** Rate limit window in ms (1 hour) */
|
|
11
|
+
const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000;
|
|
12
|
+
/**
|
|
13
|
+
* One-shot warning flags so we don't spam logs on every webhook.
|
|
14
|
+
* Cleared per process — one warning per cold start is enough to surface
|
|
15
|
+
* a misconfiguration without leaking config status to anyone with log access
|
|
16
|
+
* (M6 in the webhook security audit).
|
|
17
|
+
*/
|
|
18
|
+
let _resendUnverifiedWarned = false;
|
|
19
|
+
let _sendgridUnverifiedWarned = false;
|
|
20
|
+
/**
|
|
21
|
+
* Returns true when the deployment is running in production mode and the
|
|
22
|
+
* operator has NOT explicitly opted into accepting unverified webhooks for
|
|
23
|
+
* local testing. In production we MUST refuse webhooks whose signature can't
|
|
24
|
+
* be verified — accepting them with attacker-controlled `from:` addresses
|
|
25
|
+
* lets the dispatch owner-resolution path run as the victim (C1 in the
|
|
26
|
+
* webhook security audit).
|
|
27
|
+
*/
|
|
28
|
+
function shouldRefuseWhenSecretMissing() {
|
|
29
|
+
if (process.env.AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS === "1")
|
|
30
|
+
return false;
|
|
31
|
+
return process.env.NODE_ENV === "production";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create an Email platform adapter for inbound/outbound email via
|
|
35
|
+
* Resend or SendGrid webhooks.
|
|
36
|
+
*
|
|
37
|
+
* Required env vars:
|
|
38
|
+
* - EMAIL_AGENT_ADDRESS — The email address the agent receives mail at
|
|
39
|
+
*
|
|
40
|
+
* One of these must also be set (checked via isEmailConfigured()):
|
|
41
|
+
* - RESEND_API_KEY — For sending/receiving via Resend
|
|
42
|
+
* - SENDGRID_API_KEY — For sending/receiving via SendGrid
|
|
43
|
+
*
|
|
44
|
+
* Optional:
|
|
45
|
+
* - EMAIL_INBOUND_WEBHOOK_SECRET — Webhook signature verification secret
|
|
46
|
+
*/
|
|
47
|
+
export function emailAdapter() {
|
|
48
|
+
return {
|
|
49
|
+
platform: "email",
|
|
50
|
+
label: "Email",
|
|
51
|
+
getRequiredEnvKeys() {
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
key: "EMAIL_AGENT_ADDRESS",
|
|
55
|
+
label: "Agent Email Address",
|
|
56
|
+
required: true,
|
|
57
|
+
helpText: "The email address people will use to message your agent (e.g. `agent@yourcompany.com`, or pick from your `<slug>.resend.app` sandbox).",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "RESEND_API_KEY",
|
|
61
|
+
label: "Resend API Key",
|
|
62
|
+
required: false,
|
|
63
|
+
helpText: "From resend.com → API keys (starts with `re_`). Either Resend or SendGrid is required for sending and receiving mail.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: "SENDGRID_API_KEY",
|
|
67
|
+
label: "SendGrid API Key",
|
|
68
|
+
required: false,
|
|
69
|
+
helpText: "From sendgrid.com → Settings → API Keys (starts with `SG.`). Either Resend or SendGrid is required.",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "EMAIL_INBOUND_WEBHOOK_SECRET",
|
|
73
|
+
label: "Inbound Webhook Secret",
|
|
74
|
+
required: false,
|
|
75
|
+
helpText: "Optional. From Resend (Webhooks → Signing Secret, starts with `whsec_`) or your SendGrid Inbound Parse basic-auth password. Used to verify inbound webhooks are real.",
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
},
|
|
79
|
+
async handleVerification(_event) {
|
|
80
|
+
// Email webhooks don't need challenge handshakes
|
|
81
|
+
return { handled: false };
|
|
82
|
+
},
|
|
83
|
+
async verifyWebhook(event) {
|
|
84
|
+
const secret = process.env.EMAIL_INBOUND_WEBHOOK_SECRET;
|
|
85
|
+
const provider = getEmailProvider();
|
|
86
|
+
if (provider === "resend") {
|
|
87
|
+
return verifyResendWebhook(event, secret);
|
|
88
|
+
}
|
|
89
|
+
if (provider === "sendgrid") {
|
|
90
|
+
return verifySendGridWebhook(event, secret);
|
|
91
|
+
}
|
|
92
|
+
// No provider configured — reject
|
|
93
|
+
console.warn("[email] No email provider configured, rejecting webhook");
|
|
94
|
+
return false;
|
|
95
|
+
},
|
|
96
|
+
async parseIncomingMessage(event) {
|
|
97
|
+
const provider = getEmailProvider();
|
|
98
|
+
const agentAddress = process.env.EMAIL_AGENT_ADDRESS?.toLowerCase();
|
|
99
|
+
if (!agentAddress) {
|
|
100
|
+
console.warn("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
let parsed = null;
|
|
104
|
+
if (provider === "resend") {
|
|
105
|
+
parsed = await parseResendWebhook(event);
|
|
106
|
+
}
|
|
107
|
+
else if (provider === "sendgrid") {
|
|
108
|
+
parsed = await parseSendGridWebhook(event);
|
|
109
|
+
}
|
|
110
|
+
if (!parsed)
|
|
111
|
+
return null;
|
|
112
|
+
// Rate limiting (SQL-backed heuristic — counts the sender's already-queued
|
|
113
|
+
// tasks within the last hour). The previous in-memory map reset on every
|
|
114
|
+
// serverless cold start, so the actual ceiling per attacker was
|
|
115
|
+
// RATE_LIMIT_MAX × number_of_active_instances. SQL-backed counting holds
|
|
116
|
+
// across instances. See H4 in the webhook security audit.
|
|
117
|
+
const senderEmail = parsed.from.email.toLowerCase();
|
|
118
|
+
if (await isRateLimited(senderEmail)) {
|
|
119
|
+
console.warn(`[email] Rate limited sender: ${senderEmail} (>${RATE_LIMIT_MAX}/hr)`);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
// Check allowed domains
|
|
123
|
+
const config = await getIntegrationConfig("email");
|
|
124
|
+
if (config?.configData?.allowedDomains) {
|
|
125
|
+
const allowed = config.configData.allowedDomains;
|
|
126
|
+
if (allowed.length > 0) {
|
|
127
|
+
const senderDomain = senderEmail.split("@")[1];
|
|
128
|
+
if (!senderDomain || !allowed.includes(senderDomain)) {
|
|
129
|
+
console.warn(`[email] Rejected email from ${senderEmail}: domain not in allowedDomains`);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Determine if agent was CC'd (not in To, but in CC)
|
|
135
|
+
const toAddresses = parsed.to.map((a) => a.toLowerCase());
|
|
136
|
+
const ccAddresses = (parsed.cc ?? []).map((a) => a.toLowerCase());
|
|
137
|
+
const isCC = !toAddresses.includes(agentAddress) &&
|
|
138
|
+
ccAddresses.includes(agentAddress);
|
|
139
|
+
// Build thread ID from References chain (Gmail-style: oldest Message-ID is thread root).
|
|
140
|
+
// Scope the thread root by sender so an attacker who can forge a `References:`
|
|
141
|
+
// header pointing at someone else's thread root can't graft into that thread.
|
|
142
|
+
// Without this scoping, a third party could craft an inbound email whose
|
|
143
|
+
// References chain matches a known victim's Message-ID and inject messages into
|
|
144
|
+
// the victim's existing conversation — leaking prior content via the agent's
|
|
145
|
+
// reply (M1 in the webhooks security audit).
|
|
146
|
+
const threadRootId = scopeThreadIdToSender(getThreadRootId(parsed.messageId, parsed.references), senderEmail);
|
|
147
|
+
// Build body text
|
|
148
|
+
let bodyText = parsed.text || stripHtmlForPlainText(parsed.html || "");
|
|
149
|
+
// Truncate if needed
|
|
150
|
+
if (bodyText.length > EMAIL_MAX_BODY_LENGTH) {
|
|
151
|
+
bodyText =
|
|
152
|
+
bodyText.slice(0, EMAIL_MAX_BODY_LENGTH) + "\n[Message truncated]";
|
|
153
|
+
}
|
|
154
|
+
// Prefix CC'd emails with context
|
|
155
|
+
if (isCC) {
|
|
156
|
+
const otherRecipients = toAddresses
|
|
157
|
+
.filter((a) => a !== agentAddress)
|
|
158
|
+
.join(", ");
|
|
159
|
+
bodyText =
|
|
160
|
+
`[CC'd on email between ${senderEmail} and ${otherRecipients || "others"}]\n` +
|
|
161
|
+
`Subject: ${parsed.subject}\n\n` +
|
|
162
|
+
bodyText;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
platform: "email",
|
|
166
|
+
externalThreadId: threadRootId,
|
|
167
|
+
text: bodyText,
|
|
168
|
+
senderName: parsed.from.name,
|
|
169
|
+
senderId: senderEmail,
|
|
170
|
+
platformContext: {
|
|
171
|
+
messageId: parsed.messageId,
|
|
172
|
+
subject: parsed.subject,
|
|
173
|
+
from: senderEmail,
|
|
174
|
+
to: parsed.to,
|
|
175
|
+
cc: parsed.cc,
|
|
176
|
+
inReplyTo: parsed.inReplyTo,
|
|
177
|
+
references: parsed.references,
|
|
178
|
+
isCC,
|
|
179
|
+
},
|
|
180
|
+
timestamp: parsed.date ? new Date(parsed.date).getTime() : Date.now(),
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
async sendResponse(message, context) {
|
|
184
|
+
const agentAddress = process.env.EMAIL_AGENT_ADDRESS;
|
|
185
|
+
if (!agentAddress) {
|
|
186
|
+
console.error("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const config = await getIntegrationConfig("email");
|
|
190
|
+
const displayName = config?.configData?.displayName || "Dispatch Agent";
|
|
191
|
+
// EMAIL_FROM overrides the from-address — required when the receiving
|
|
192
|
+
// address is on a sub-domain that can't be a verified sender (e.g.
|
|
193
|
+
// *.resend.app). Inbound and outbound addresses can differ.
|
|
194
|
+
const fromAddress = process.env.EMAIL_FROM
|
|
195
|
+
? process.env.EMAIL_FROM
|
|
196
|
+
: `${displayName} <${agentAddress}>`;
|
|
197
|
+
const subject = context.platformContext.subject;
|
|
198
|
+
const reSubject = subject.startsWith("Re: ") ? subject : `Re: ${subject}`;
|
|
199
|
+
try {
|
|
200
|
+
await sendEmail({
|
|
201
|
+
to: context.senderId,
|
|
202
|
+
from: fromAddress,
|
|
203
|
+
subject: reSubject,
|
|
204
|
+
html: message.text,
|
|
205
|
+
text: stripHtmlForPlainText(message.text),
|
|
206
|
+
inReplyTo: context.platformContext.messageId,
|
|
207
|
+
references: buildReferencesHeader(context.platformContext),
|
|
208
|
+
cc: context.platformContext.isCC
|
|
209
|
+
? buildReplyAllCc(context)
|
|
210
|
+
: undefined,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.error("[email] Failed to send response:", err);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
async sendMessageToTarget(message, target) {
|
|
218
|
+
const agentAddress = process.env.EMAIL_AGENT_ADDRESS;
|
|
219
|
+
if (!agentAddress) {
|
|
220
|
+
console.error("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const config = await getIntegrationConfig("email");
|
|
224
|
+
const displayName = config?.configData?.displayName || "Dispatch Agent";
|
|
225
|
+
try {
|
|
226
|
+
await sendEmail({
|
|
227
|
+
to: target.destination,
|
|
228
|
+
from: `${displayName} <${agentAddress}>`,
|
|
229
|
+
subject: target.label || "Message from Dispatch Agent",
|
|
230
|
+
html: message.text,
|
|
231
|
+
text: stripHtmlForPlainText(message.text),
|
|
232
|
+
...(target.threadRef
|
|
233
|
+
? {
|
|
234
|
+
inReplyTo: target.threadRef,
|
|
235
|
+
references: target.threadRef,
|
|
236
|
+
}
|
|
237
|
+
: {}),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
console.error("[email] Failed to send proactive message:", err);
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
formatAgentResponse(text) {
|
|
246
|
+
const bodyHtml = markdownToHtml(text);
|
|
247
|
+
const html = wrapInEmailTemplate(bodyHtml);
|
|
248
|
+
return { text: html, platformContext: {} };
|
|
249
|
+
},
|
|
250
|
+
async getStatus(_baseUrl) {
|
|
251
|
+
const hasAgentAddress = !!process.env.EMAIL_AGENT_ADDRESS;
|
|
252
|
+
const hasEmailProvider = isEmailConfigured();
|
|
253
|
+
const hasWebhookSecret = !!process.env.EMAIL_INBOUND_WEBHOOK_SECRET;
|
|
254
|
+
const configured = hasAgentAddress && hasEmailProvider;
|
|
255
|
+
return {
|
|
256
|
+
platform: "email",
|
|
257
|
+
label: "Email",
|
|
258
|
+
enabled: false, // overridden by plugin
|
|
259
|
+
configured,
|
|
260
|
+
details: {
|
|
261
|
+
hasAgentAddress,
|
|
262
|
+
hasEmailProvider,
|
|
263
|
+
hasWebhookSecret,
|
|
264
|
+
provider: getEmailProvider(),
|
|
265
|
+
},
|
|
266
|
+
error: !configured
|
|
267
|
+
? "Set EMAIL_AGENT_ADDRESS and either RESEND_API_KEY or SENDGRID_API_KEY"
|
|
268
|
+
: undefined,
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Webhook verification
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
async function verifyResendWebhook(event, secret) {
|
|
277
|
+
if (!secret) {
|
|
278
|
+
if (shouldRefuseWhenSecretMissing()) {
|
|
279
|
+
if (!_resendUnverifiedWarned) {
|
|
280
|
+
_resendUnverifiedWarned = true;
|
|
281
|
+
console.error("[email] EMAIL_INBOUND_WEBHOOK_SECRET not set — refusing Resend webhook in production. " +
|
|
282
|
+
"Set EMAIL_INBOUND_WEBHOOK_SECRET, or set AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS=1 for local testing only.");
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
if (!_resendUnverifiedWarned) {
|
|
287
|
+
_resendUnverifiedWarned = true;
|
|
288
|
+
console.warn("[email] EMAIL_INBOUND_WEBHOOK_SECRET not set — accepting Resend webhook without verification (dev mode)");
|
|
289
|
+
}
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
const svixId = getHeader(event, "svix-id");
|
|
293
|
+
const svixTimestamp = getHeader(event, "svix-timestamp");
|
|
294
|
+
const svixSignature = getHeader(event, "svix-signature");
|
|
295
|
+
if (!svixId || !svixTimestamp || !svixSignature) {
|
|
296
|
+
console.warn("[email] Missing Svix signature headers");
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
// Reject requests older than 5 minutes (replay protection)
|
|
300
|
+
const ts = parseInt(svixTimestamp, 10);
|
|
301
|
+
if (Math.abs(Date.now() / 1000 - ts) > 300) {
|
|
302
|
+
console.warn("[email] Svix timestamp too old, rejecting");
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
const body = await readRawBody(event);
|
|
306
|
+
const crypto = await import("node:crypto");
|
|
307
|
+
// Svix signing secret may be prefixed with "whsec_"
|
|
308
|
+
const rawSecret = secret.startsWith("whsec_") ? secret.slice(6) : secret;
|
|
309
|
+
const secretBytes = Buffer.from(rawSecret, "base64");
|
|
310
|
+
const signedContent = `${svixId}.${svixTimestamp}.${body}`;
|
|
311
|
+
const expectedSignature = crypto
|
|
312
|
+
.createHmac("sha256", secretBytes)
|
|
313
|
+
.update(signedContent)
|
|
314
|
+
.digest("base64");
|
|
315
|
+
// Svix sends multiple signatures separated by spaces, each prefixed with "v1,"
|
|
316
|
+
const signatures = svixSignature.split(" ");
|
|
317
|
+
for (const sig of signatures) {
|
|
318
|
+
const sigValue = sig.startsWith("v1,") ? sig.slice(3) : sig;
|
|
319
|
+
try {
|
|
320
|
+
if (crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(sigValue))) {
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// Length mismatch — try next signature
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
console.warn("[email] Svix signature verification failed");
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
function safeEq(a, b) {
|
|
332
|
+
const aBuf = Buffer.from(a);
|
|
333
|
+
const bBuf = Buffer.from(b);
|
|
334
|
+
if (aBuf.length !== bBuf.length)
|
|
335
|
+
return false;
|
|
336
|
+
return timingSafeEqual(aBuf, bBuf);
|
|
337
|
+
}
|
|
338
|
+
async function verifySendGridWebhook(event, secret) {
|
|
339
|
+
if (!secret) {
|
|
340
|
+
if (shouldRefuseWhenSecretMissing()) {
|
|
341
|
+
if (!_sendgridUnverifiedWarned) {
|
|
342
|
+
_sendgridUnverifiedWarned = true;
|
|
343
|
+
console.error("[email] EMAIL_INBOUND_WEBHOOK_SECRET not set — refusing SendGrid webhook in production. " +
|
|
344
|
+
"Set EMAIL_INBOUND_WEBHOOK_SECRET, or set AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS=1 for local testing only.");
|
|
345
|
+
}
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
if (!_sendgridUnverifiedWarned) {
|
|
349
|
+
_sendgridUnverifiedWarned = true;
|
|
350
|
+
console.warn("[email] EMAIL_INBOUND_WEBHOOK_SECRET not set — accepting SendGrid webhook without verification (dev mode)");
|
|
351
|
+
}
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
// Check for the secret in a custom header or basic auth
|
|
355
|
+
const authHeader = getHeader(event, "authorization");
|
|
356
|
+
if (authHeader) {
|
|
357
|
+
// Basic auth: "Basic base64(user:pass)" — secret is the password
|
|
358
|
+
if (authHeader.startsWith("Basic ")) {
|
|
359
|
+
const decoded = Buffer.from(authHeader.slice(6), "base64").toString();
|
|
360
|
+
const password = decoded.split(":")[1];
|
|
361
|
+
if (password !== undefined && safeEq(password, secret))
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Also check a custom header (common SendGrid Inbound Parse pattern)
|
|
366
|
+
const customSecret = getHeader(event, "x-webhook-secret");
|
|
367
|
+
if (customSecret !== undefined && safeEq(customSecret, secret))
|
|
368
|
+
return true;
|
|
369
|
+
console.warn("[email] SendGrid webhook secret verification failed");
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
// Inbound email parsing
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
async function parseResendWebhook(event) {
|
|
376
|
+
const raw = await readRawBody(event);
|
|
377
|
+
const body = JSON.parse(raw);
|
|
378
|
+
if (!body || body.type !== "email.received")
|
|
379
|
+
return null;
|
|
380
|
+
const data = body.data;
|
|
381
|
+
if (!data)
|
|
382
|
+
return null;
|
|
383
|
+
// Resend webhook payload provides email metadata directly in data
|
|
384
|
+
// Fields: from, to, cc, subject, text, html, headers, created_at
|
|
385
|
+
const fromRaw = data.from;
|
|
386
|
+
const from = fromRaw ? parseEmailAddress(fromRaw) : null;
|
|
387
|
+
if (!from)
|
|
388
|
+
return null;
|
|
389
|
+
const toRaw = data.to;
|
|
390
|
+
const to = normalizeAddressList(toRaw);
|
|
391
|
+
const ccRaw = data.cc;
|
|
392
|
+
const cc = normalizeAddressList(ccRaw);
|
|
393
|
+
// Parse headers for Message-ID, In-Reply-To, References
|
|
394
|
+
const headers = parseHeadersObject(data.headers);
|
|
395
|
+
const messageId = headers["message-id"] || data.email_id || `resend-${Date.now()}`;
|
|
396
|
+
return {
|
|
397
|
+
messageId,
|
|
398
|
+
subject: data.subject || "(no subject)",
|
|
399
|
+
from,
|
|
400
|
+
to,
|
|
401
|
+
cc: cc.length > 0 ? cc : undefined,
|
|
402
|
+
text: data.text,
|
|
403
|
+
html: data.html,
|
|
404
|
+
inReplyTo: headers["in-reply-to"] || undefined,
|
|
405
|
+
references: parseReferencesHeader(headers["references"]),
|
|
406
|
+
date: data.created_at || undefined,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
async function parseSendGridWebhook(event) {
|
|
410
|
+
const raw = await readRawBody(event);
|
|
411
|
+
const body = JSON.parse(raw);
|
|
412
|
+
if (!body)
|
|
413
|
+
return null;
|
|
414
|
+
// SendGrid Inbound Parse sends form data with fields:
|
|
415
|
+
// from, to, cc, subject, text, html, headers, envelope
|
|
416
|
+
const fromRaw = body.from;
|
|
417
|
+
const from = fromRaw ? parseEmailAddress(fromRaw) : null;
|
|
418
|
+
if (!from)
|
|
419
|
+
return null;
|
|
420
|
+
const toRaw = body.to;
|
|
421
|
+
const to = toRaw ? toRaw.split(",").map((a) => a.trim()) : [];
|
|
422
|
+
const ccRaw = body.cc;
|
|
423
|
+
const cc = ccRaw ? ccRaw.split(",").map((a) => a.trim()) : [];
|
|
424
|
+
// Parse raw headers string
|
|
425
|
+
const headersStr = body.headers;
|
|
426
|
+
const headers = parseHeadersString(headersStr);
|
|
427
|
+
const messageId = headers["message-id"] || `sendgrid-${Date.now()}`;
|
|
428
|
+
return {
|
|
429
|
+
messageId,
|
|
430
|
+
subject: body.subject || "(no subject)",
|
|
431
|
+
from,
|
|
432
|
+
to,
|
|
433
|
+
cc: cc.length > 0 ? cc : undefined,
|
|
434
|
+
text: body.text,
|
|
435
|
+
html: body.html,
|
|
436
|
+
inReplyTo: headers["in-reply-to"] || undefined,
|
|
437
|
+
references: parseReferencesHeader(headers["references"]),
|
|
438
|
+
date: headers["date"] || undefined,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
// Rate limiting
|
|
443
|
+
// ---------------------------------------------------------------------------
|
|
444
|
+
/**
|
|
445
|
+
* Rate-limit heuristic backed by the `integration_pending_tasks` queue.
|
|
446
|
+
*
|
|
447
|
+
* Counts how many tasks this sender has produced in the last hour. The count
|
|
448
|
+
* INCLUDES tasks already processed (status = completed/failed) because the
|
|
449
|
+
* rows aren't deleted on completion — that's enough signal to throttle a
|
|
450
|
+
* single noisy/abusive sender without needing a dedicated counter table.
|
|
451
|
+
*
|
|
452
|
+
* Two trade-offs worth knowing:
|
|
453
|
+
* - This is a coarse heuristic, not exact metering. Within one hour the
|
|
454
|
+
* count is correct; rows produced more than an hour ago naturally drop
|
|
455
|
+
* off. We don't try to be precise, only to raise the bar past the
|
|
456
|
+
* "send 10K emails through one Lambda burst" failure mode.
|
|
457
|
+
* - The query relies on the `idx_pending_tasks_status_created` index plus
|
|
458
|
+
* a sender substring match. A targeted attacker could amortise the cost
|
|
459
|
+
* by reusing one sender address — that's fine, the goal here is to bound
|
|
460
|
+
* the attack within a single attacker identity, not to detect spoofing.
|
|
461
|
+
*
|
|
462
|
+
* If the table doesn't yet exist on this deployment (no inbound webhook has
|
|
463
|
+
* been processed before), we silently allow the message — the schema is
|
|
464
|
+
* provisioned on first task insert. See H4 in the webhook security audit.
|
|
465
|
+
*/
|
|
466
|
+
async function isRateLimited(senderEmail) {
|
|
467
|
+
const cutoff = Date.now() - RATE_LIMIT_WINDOW_MS;
|
|
468
|
+
try {
|
|
469
|
+
const client = getDbExec();
|
|
470
|
+
const { rows } = await client.execute({
|
|
471
|
+
sql: `
|
|
472
|
+
SELECT COUNT(*) AS c
|
|
473
|
+
FROM integration_pending_tasks
|
|
474
|
+
WHERE platform = ?
|
|
475
|
+
AND created_at >= ?
|
|
476
|
+
AND payload LIKE ?
|
|
477
|
+
`,
|
|
478
|
+
args: ["email", cutoff, `%"senderId":"${senderEmail}"%`],
|
|
479
|
+
});
|
|
480
|
+
const count = Number(rows[0]?.c ?? 0);
|
|
481
|
+
return count >= RATE_LIMIT_MAX;
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
// Table doesn't exist yet (first webhook on a fresh deployment) — allow.
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// ---------------------------------------------------------------------------
|
|
489
|
+
// Helpers — email address parsing
|
|
490
|
+
// ---------------------------------------------------------------------------
|
|
491
|
+
/** Parse "Name <addr@example.com>" or plain "addr@example.com" */
|
|
492
|
+
function parseEmailAddress(raw) {
|
|
493
|
+
const match = raw.match(/^\s*(.*?)\s*<([^>]+)>\s*$/);
|
|
494
|
+
if (match && match[2]) {
|
|
495
|
+
return {
|
|
496
|
+
name: match[1].replace(/^["']|["']$/g, "").trim() || undefined,
|
|
497
|
+
email: match[2].trim(),
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
return { email: raw.trim() };
|
|
501
|
+
}
|
|
502
|
+
/** Normalize a to/cc field that may be a string, array, or undefined into a string[] of addresses */
|
|
503
|
+
function normalizeAddressList(raw) {
|
|
504
|
+
if (!raw)
|
|
505
|
+
return [];
|
|
506
|
+
if (Array.isArray(raw))
|
|
507
|
+
return raw.map((a) => a.trim());
|
|
508
|
+
return raw.split(",").map((a) => a.trim());
|
|
509
|
+
}
|
|
510
|
+
// ---------------------------------------------------------------------------
|
|
511
|
+
// Helpers — header parsing
|
|
512
|
+
// ---------------------------------------------------------------------------
|
|
513
|
+
/** Parse a headers object (Resend format: array of {name, value} or Record) */
|
|
514
|
+
function parseHeadersObject(headers) {
|
|
515
|
+
const result = {};
|
|
516
|
+
if (!headers)
|
|
517
|
+
return result;
|
|
518
|
+
if (Array.isArray(headers)) {
|
|
519
|
+
for (const h of headers) {
|
|
520
|
+
if (h && typeof h === "object" && "name" in h && "value" in h) {
|
|
521
|
+
result[h.name.toLowerCase()] = h.value;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
else if (typeof headers === "object") {
|
|
526
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
527
|
+
result[key.toLowerCase()] = String(value);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return result;
|
|
531
|
+
}
|
|
532
|
+
/** Parse a raw headers string (SendGrid format: "Key: Value\nKey: Value\n...") */
|
|
533
|
+
function parseHeadersString(raw) {
|
|
534
|
+
const result = {};
|
|
535
|
+
if (!raw)
|
|
536
|
+
return result;
|
|
537
|
+
const lines = raw.split(/\r?\n/);
|
|
538
|
+
let currentKey = "";
|
|
539
|
+
let currentValue = "";
|
|
540
|
+
for (const line of lines) {
|
|
541
|
+
// Continuation line (starts with whitespace)
|
|
542
|
+
if (/^\s/.test(line) && currentKey) {
|
|
543
|
+
currentValue += " " + line.trim();
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
// Save previous header
|
|
547
|
+
if (currentKey) {
|
|
548
|
+
result[currentKey.toLowerCase()] = currentValue;
|
|
549
|
+
}
|
|
550
|
+
const colonIdx = line.indexOf(":");
|
|
551
|
+
if (colonIdx > 0) {
|
|
552
|
+
currentKey = line.slice(0, colonIdx).trim();
|
|
553
|
+
currentValue = line.slice(colonIdx + 1).trim();
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
currentKey = "";
|
|
557
|
+
currentValue = "";
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Save last header
|
|
561
|
+
if (currentKey) {
|
|
562
|
+
result[currentKey.toLowerCase()] = currentValue;
|
|
563
|
+
}
|
|
564
|
+
return result;
|
|
565
|
+
}
|
|
566
|
+
/** Parse a References header value into an array of Message-IDs */
|
|
567
|
+
function parseReferencesHeader(references) {
|
|
568
|
+
if (!references)
|
|
569
|
+
return undefined;
|
|
570
|
+
const ids = references.match(/<[^>]+>/g);
|
|
571
|
+
return ids && ids.length > 0 ? ids : undefined;
|
|
572
|
+
}
|
|
573
|
+
// ---------------------------------------------------------------------------
|
|
574
|
+
// Helpers — threading
|
|
575
|
+
// ---------------------------------------------------------------------------
|
|
576
|
+
/**
|
|
577
|
+
* Get the thread root ID using a Gmail-style approach:
|
|
578
|
+
* the oldest Message-ID from the References chain is the thread root.
|
|
579
|
+
* If no References, use the current Message-ID.
|
|
580
|
+
*/
|
|
581
|
+
function getThreadRootId(messageId, references) {
|
|
582
|
+
if (references && references.length > 0) {
|
|
583
|
+
return references[0];
|
|
584
|
+
}
|
|
585
|
+
return messageId;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Scope a raw thread root id by the sender's email address. Two different
|
|
589
|
+
* senders crafting the same `References:` header value should NOT collide
|
|
590
|
+
* onto the same internal thread mapping — that's the email-side fix for the
|
|
591
|
+
* thread-injection finding (M1 in the webhook security audit).
|
|
592
|
+
*
|
|
593
|
+
* The returned id is opaque to callers and stays stable across messages
|
|
594
|
+
* from the same sender on the same conversation thread, so reply behaviour
|
|
595
|
+
* is unchanged.
|
|
596
|
+
*/
|
|
597
|
+
function scopeThreadIdToSender(rawThreadId, senderEmail) {
|
|
598
|
+
return `${senderEmail.toLowerCase()}::${rawThreadId}`;
|
|
599
|
+
}
|
|
600
|
+
// ---------------------------------------------------------------------------
|
|
601
|
+
// Helpers — reply building
|
|
602
|
+
// ---------------------------------------------------------------------------
|
|
603
|
+
/** Build a References header from the platform context */
|
|
604
|
+
function buildReferencesHeader(ctx) {
|
|
605
|
+
const parts = [];
|
|
606
|
+
// Include existing references
|
|
607
|
+
const refs = ctx.references;
|
|
608
|
+
if (refs) {
|
|
609
|
+
parts.push(...refs);
|
|
610
|
+
}
|
|
611
|
+
// Append the current message ID
|
|
612
|
+
const messageId = ctx.messageId;
|
|
613
|
+
if (messageId) {
|
|
614
|
+
// Avoid duplicates
|
|
615
|
+
if (!parts.includes(messageId)) {
|
|
616
|
+
parts.push(messageId);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return parts.join(" ");
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Build CC list for reply-all when agent was CC'd.
|
|
623
|
+
* Include original To addresses and other CC addresses, excluding the agent and the original sender.
|
|
624
|
+
*/
|
|
625
|
+
function buildReplyAllCc(context) {
|
|
626
|
+
const agentAddress = process.env.EMAIL_AGENT_ADDRESS?.toLowerCase();
|
|
627
|
+
const senderEmail = context.senderId?.toLowerCase();
|
|
628
|
+
const toAddresses = context.platformContext.to || [];
|
|
629
|
+
const ccAddresses = context.platformContext.cc || [];
|
|
630
|
+
const allRecipients = new Set();
|
|
631
|
+
for (const addr of [...toAddresses, ...ccAddresses]) {
|
|
632
|
+
const normalized = addr.toLowerCase().trim();
|
|
633
|
+
// Exclude agent address and original sender (sender goes in To)
|
|
634
|
+
if (normalized !== agentAddress && normalized !== senderEmail) {
|
|
635
|
+
allRecipients.add(normalized);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return allRecipients.size > 0 ? Array.from(allRecipients) : undefined;
|
|
639
|
+
}
|
|
640
|
+
// ---------------------------------------------------------------------------
|
|
641
|
+
// Helpers — text conversion
|
|
642
|
+
// ---------------------------------------------------------------------------
|
|
643
|
+
/** Strip HTML tags for a plain-text version of the email */
|
|
644
|
+
function stripHtmlForPlainText(html) {
|
|
645
|
+
return html
|
|
646
|
+
.replace(/<br\s*\/?>/gi, "\n")
|
|
647
|
+
.replace(/<\/p>/gi, "\n\n")
|
|
648
|
+
.replace(/<\/div>/gi, "\n")
|
|
649
|
+
.replace(/<\/li>/gi, "\n")
|
|
650
|
+
.replace(/<li[^>]*>/gi, "- ")
|
|
651
|
+
.replace(/<\/h[1-6]>/gi, "\n\n")
|
|
652
|
+
.replace(/<[^>]+>/g, "")
|
|
653
|
+
.replace(/ /g, " ")
|
|
654
|
+
.replace(/&/g, "&")
|
|
655
|
+
.replace(/</g, "<")
|
|
656
|
+
.replace(/>/g, ">")
|
|
657
|
+
.replace(/"/g, '"')
|
|
658
|
+
.replace(/'/g, "'")
|
|
659
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
660
|
+
.trim();
|
|
661
|
+
}
|
|
662
|
+
/** Convert basic markdown to HTML for email rendering */
|
|
663
|
+
function markdownToHtml(md) {
|
|
664
|
+
let html = md;
|
|
665
|
+
// Escape HTML entities in the source (but not our generated tags)
|
|
666
|
+
html = html
|
|
667
|
+
.replace(/&/g, "&")
|
|
668
|
+
.replace(/</g, "<")
|
|
669
|
+
.replace(/>/g, ">");
|
|
670
|
+
// Bold: **text** or __text__
|
|
671
|
+
html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
672
|
+
html = html.replace(/__(.+?)__/g, "<strong>$1</strong>");
|
|
673
|
+
// Italic: *text* or _text_ (but not inside words with underscores)
|
|
674
|
+
html = html.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g, "<em>$1</em>");
|
|
675
|
+
html = html.replace(/(?<!\w)_([^_]+?)_(?!\w)/g, "<em>$1</em>");
|
|
676
|
+
// Links: [text](url)
|
|
677
|
+
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#2563eb;text-decoration:underline;">$1</a>');
|
|
678
|
+
// Inline code: `code`
|
|
679
|
+
html = html.replace(/`([^`]+)`/g, '<code style="background:#f1f5f9;padding:1px 4px;border-radius:3px;font-size:0.9em;">$1</code>');
|
|
680
|
+
// Unordered lists: lines starting with "- " or "* "
|
|
681
|
+
html = html.replace(/^([*-]) (.+)$/gm, "<li>$2</li>");
|
|
682
|
+
// Wrap consecutive <li> in <ul>
|
|
683
|
+
html = html.replace(/(<li>.*?<\/li>\n?)+/g, '<ul style="margin:8px 0;padding-left:20px;">$&</ul>');
|
|
684
|
+
// Ordered lists: lines starting with "1. ", "2. " etc.
|
|
685
|
+
html = html.replace(/^\d+\. (.+)$/gm, "<li>$1</li>");
|
|
686
|
+
// Wrap consecutive <li> that aren't in <ul> in <ol>
|
|
687
|
+
html = html.replace(/(?<!<\/ul>)(<li>.*?<\/li>\n?)+/g, (match) => {
|
|
688
|
+
if (match.includes("<ul"))
|
|
689
|
+
return match;
|
|
690
|
+
return `<ol style="margin:8px 0;padding-left:20px;">${match}</ol>`;
|
|
691
|
+
});
|
|
692
|
+
// Headings: # through ###
|
|
693
|
+
html = html.replace(/^### (.+)$/gm, '<h3 style="margin:16px 0 8px;font-size:1.1em;">$1</h3>');
|
|
694
|
+
html = html.replace(/^## (.+)$/gm, '<h2 style="margin:16px 0 8px;font-size:1.25em;">$1</h2>');
|
|
695
|
+
html = html.replace(/^# (.+)$/gm, '<h1 style="margin:16px 0 8px;font-size:1.4em;">$1</h1>');
|
|
696
|
+
// Horizontal rules: --- or ***
|
|
697
|
+
html = html.replace(/^(-{3,}|\*{3,})$/gm, '<hr style="border:none;border-top:1px solid #e2e8f0;margin:16px 0;">');
|
|
698
|
+
// Paragraphs: double newlines
|
|
699
|
+
html = html.replace(/\n\n/g, "</p><p>");
|
|
700
|
+
// Single newlines → <br>
|
|
701
|
+
html = html.replace(/\n/g, "<br>");
|
|
702
|
+
// Wrap in paragraph tags
|
|
703
|
+
html = `<p>${html}</p>`;
|
|
704
|
+
// Clean up empty paragraphs
|
|
705
|
+
html = html.replace(/<p>\s*<\/p>/g, "");
|
|
706
|
+
return html;
|
|
707
|
+
}
|
|
708
|
+
/** Wrap body HTML in a minimal email template with inline styles */
|
|
709
|
+
function wrapInEmailTemplate(bodyHtml) {
|
|
710
|
+
return `<!DOCTYPE html>
|
|
711
|
+
<html>
|
|
712
|
+
<head>
|
|
713
|
+
<meta charset="utf-8">
|
|
714
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
715
|
+
</head>
|
|
716
|
+
<body style="margin:0;padding:0;background-color:#ffffff;">
|
|
717
|
+
<div style="max-width:600px;margin:0 auto;padding:20px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.6;color:#1a1a1a;">
|
|
718
|
+
${bodyHtml}
|
|
719
|
+
</div>
|
|
720
|
+
</body>
|
|
721
|
+
</html>`;
|
|
722
|
+
}
|
|
723
|
+
// ---------------------------------------------------------------------------
|
|
724
|
+
// Raw body reader (matches Slack adapter pattern)
|
|
725
|
+
// ---------------------------------------------------------------------------
|
|
726
|
+
/**
|
|
727
|
+
* Read the raw request body as a string and cache on the event context.
|
|
728
|
+
* Reads raw bytes from the request stream — never re-stringifies a parsed
|
|
729
|
+
* body, since the Resend / Svix HMAC is computed over the exact bytes sent
|
|
730
|
+
* (M2 in the webhook security audit).
|
|
731
|
+
*/
|
|
732
|
+
async function readRawBody(event) {
|
|
733
|
+
const cached = event.context.__rawBody;
|
|
734
|
+
if (typeof cached === "string")
|
|
735
|
+
return cached;
|
|
736
|
+
const raw = (await h3ReadRawBody(event)) ?? "";
|
|
737
|
+
event.context.__rawBody = raw;
|
|
738
|
+
return raw;
|
|
739
|
+
}
|
|
740
|
+
//# sourceMappingURL=email.js.map
|