@agent-native/core 0.92.12 → 0.93.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +39 -0
- package/corpus/core/docs/content/automation-connectors.mdx +80 -0
- package/corpus/core/docs/content/extensions.mdx +8 -0
- package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +8 -0
- package/corpus/core/docs/content/locales/ar-SA/messaging.mdx +84 -15
- package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/de-DE/extensions.mdx +10 -0
- package/corpus/core/docs/content/locales/de-DE/messaging.mdx +92 -15
- package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/es-ES/extensions.mdx +10 -0
- package/corpus/core/docs/content/locales/es-ES/messaging.mdx +91 -15
- package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +10 -0
- package/corpus/core/docs/content/locales/fr-FR/messaging.mdx +91 -15
- package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +8 -0
- package/corpus/core/docs/content/locales/hi-IN/messaging.mdx +81 -15
- package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +9 -0
- package/corpus/core/docs/content/locales/ja-JP/messaging.mdx +81 -15
- package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +8 -0
- package/corpus/core/docs/content/locales/ko-KR/messaging.mdx +80 -15
- package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +9 -0
- package/corpus/core/docs/content/locales/pt-BR/messaging.mdx +88 -15
- package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-CN/messaging.mdx +78 -15
- package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -0
- package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-TW/messaging.mdx +78 -15
- package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +1 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -0
- package/corpus/core/docs/content/messaging.mdx +227 -45
- package/corpus/core/docs/content/template-clips.mdx +3 -0
- package/corpus/core/docs/content/template-design.mdx +4 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/a2a/artifact-response.ts +131 -2
- package/corpus/core/src/a2a/client.ts +10 -0
- package/corpus/core/src/a2a/handlers.ts +40 -76
- package/corpus/core/src/a2a/types.ts +2 -0
- package/corpus/core/src/agent/durable-background.ts +24 -0
- package/corpus/core/src/agent/production-agent.ts +15 -3
- package/corpus/core/src/agent/run-manager.ts +130 -10
- package/corpus/core/src/agent/run-store.ts +225 -15
- package/corpus/core/src/agent/types.ts +23 -0
- package/corpus/core/src/audit/record.ts +31 -0
- package/corpus/core/src/audit/store.ts +69 -3
- package/corpus/core/src/audit/types.ts +13 -0
- package/corpus/core/src/automation/index.ts +802 -0
- package/corpus/core/src/cli/create.ts +12 -5
- package/corpus/core/src/cli/design-connect.ts +596 -36
- package/corpus/core/src/client/AgentPanel.tsx +51 -6
- package/corpus/core/src/client/AssistantChat.tsx +274 -147
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
- package/corpus/core/src/client/RunStuckBanner.tsx +69 -20
- package/corpus/core/src/client/agent-chat-adapter.ts +54 -5
- package/corpus/core/src/client/automation.ts +22 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +67 -50
- package/corpus/core/src/client/composer/TiptapComposer.tsx +8 -0
- package/corpus/core/src/client/index.ts +30 -0
- package/corpus/core/src/client/integrations/api.ts +295 -0
- package/corpus/core/src/client/integrations/index.ts +26 -0
- package/corpus/core/src/client/transcription/use-live-transcription.ts +68 -5
- package/corpus/core/src/client/use-run-stuck-detection.ts +41 -3
- package/corpus/core/src/deploy/build.ts +59 -3
- package/corpus/core/src/deploy/workspace-deploy.ts +37 -2
- package/corpus/core/src/file-upload/types.ts +2 -0
- package/corpus/core/src/index.ts +37 -0
- package/corpus/core/src/integrations/a2a-continuations-store.ts +6 -4
- package/corpus/core/src/integrations/adapters/discord.ts +362 -0
- package/corpus/core/src/integrations/adapters/index.ts +29 -0
- package/corpus/core/src/integrations/adapters/microsoft-teams.ts +411 -0
- package/corpus/core/src/integrations/adapters/slack.ts +861 -27
- package/corpus/core/src/integrations/adapters/telegram.ts +54 -15
- package/corpus/core/src/integrations/adapters/whatsapp.ts +41 -17
- package/corpus/core/src/integrations/catalog.ts +571 -0
- package/corpus/core/src/integrations/controls-store.ts +187 -0
- package/corpus/core/src/integrations/index.ts +100 -0
- package/corpus/core/src/integrations/installations-store.ts +677 -0
- package/corpus/core/src/integrations/integration-memory.ts +187 -0
- package/corpus/core/src/integrations/pending-tasks-retry-job.ts +6 -6
- package/corpus/core/src/integrations/pending-tasks-store.ts +83 -5
- package/corpus/core/src/integrations/plugin.ts +685 -47
- package/corpus/core/src/integrations/scope-store.ts +498 -0
- package/corpus/core/src/integrations/slack-manifest.ts +78 -0
- package/corpus/core/src/integrations/slack-oauth.ts +343 -0
- package/corpus/core/src/integrations/types.ts +179 -0
- package/corpus/core/src/integrations/usage-budget-store.ts +906 -0
- package/corpus/core/src/integrations/webhook-handler.ts +562 -51
- package/corpus/core/src/jobs/scheduler.ts +100 -2
- package/corpus/core/src/jobs/tools.ts +45 -9
- package/corpus/core/src/provider-api/index.ts +72 -1
- package/corpus/core/src/resources/handlers.ts +88 -14
- package/corpus/core/src/resources/script-helpers.ts +36 -7
- package/corpus/core/src/resources/store.ts +59 -52
- package/corpus/core/src/scripts/call-agent.ts +107 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +294 -119
- package/corpus/core/src/server/auth.ts +10 -14
- package/corpus/core/src/server/builder-design-systems.ts +16 -1
- package/corpus/core/src/server/edge.ts +18 -0
- package/corpus/core/src/server/index.ts +26 -0
- package/corpus/core/src/server/request-context.ts +18 -0
- package/corpus/core/src/server/social-og-image.ts +3 -2
- package/corpus/core/src/styles/agent-native.css +62 -44
- package/corpus/core/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/core/src/templates/default/AGENTS.md +7 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/core/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
- package/corpus/core/src/templates/workspace-core/AGENTS.md +3 -2
- package/corpus/core/src/usage/store.ts +37 -2
- package/corpus/templates/analytics/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +23 -0
- package/corpus/templates/analytics/.builder/skills/provider-api/SKILL.md +15 -0
- package/corpus/templates/analytics/actions/save-monitor.ts +25 -2
- package/corpus/templates/analytics/app/lib/data-sources.ts +28 -0
- package/corpus/templates/analytics/changelog/2026-07-10-agent-created-uptime-monitors-now-return-a-direct-link-to-th.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-10-dashboard-email-reports-still-arrive-when-screenshot-capture-temporarily-fails.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +3 -7
- package/corpus/templates/analytics/server/lib/credential-keys.ts +12 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +5 -1
- package/corpus/templates/analytics/server/lib/provider-credentials.ts +2 -0
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +16 -0
- package/corpus/templates/assets/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/brain/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/calendar/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +98 -108
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +97 -90
- package/corpus/templates/calendar/changelog/2026-07-10-event-guest-details-and-option-menus-now-use-valid-accessibl.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-10-natural-language-event-phrases-stay-available-as-quick-creat.md +6 -0
- package/corpus/templates/chat/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
- package/corpus/templates/clips/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +8 -0
- package/corpus/templates/clips/AGENTS.md +8 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +63 -23
- package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -2
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +72 -9
- package/corpus/templates/clips/actions/list-recordings.ts +19 -3
- package/corpus/templates/clips/actions/navigate.ts +2 -0
- package/corpus/templates/clips/actions/reprocess-recording.ts +20 -6
- package/corpus/templates/clips/actions/request-transcript.ts +16 -31
- package/corpus/templates/clips/actions/view-screen.ts +57 -5
- package/corpus/templates/clips/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +69 -42
- package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +81 -68
- package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -3
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +9 -3
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -1
- package/corpus/templates/clips/app/hooks/use-library.ts +1 -1
- package/corpus/templates/clips/app/hooks/use-navigation-state.ts +10 -2
- package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +7 -1
- package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +8 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +8 -1
- package/corpus/templates/clips/app/lib/recording-visibility.ts +70 -0
- package/corpus/templates/clips/app/routes/_app.shared.tsx +20 -0
- package/corpus/templates/clips/app/routes/download.tsx +24 -8
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +115 -2
- package/corpus/templates/clips/app/routes/record.tsx +62 -0
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +25 -16
- package/corpus/templates/clips/changelog/2026-07-10-clips-desktop-is-now-available-for-linux-with-appimage-debia.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-clips-downloads-updates-sooner-in-the-background-and-offers-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-clips-shared-with-you-now-appear-in-a-searchable-shared-with.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-clips-with-missing-mobile-video-frames-can-be-repaired-witho.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-mobile-camera-recordings-pause-while-backgrounded.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-mp4-downloads-now-show-progress-immediately-after-the-option.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-recording-pages-now-open-as-soon-as-you-stop-with-a-share-li.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-recordings-now-seek-smoothly-downloads-use-the-correct-file-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-s3-compatible-storage-now-saves-hosted-recordings-without-re.md +6 -0
- package/corpus/templates/clips/desktop/README.md +22 -6
- package/corpus/templates/clips/desktop/package.json +1 -1
- package/corpus/templates/clips/desktop/src/app.tsx +32 -19
- package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +15 -9
- package/corpus/templates/clips/desktop/src/lib/finalization-guard.ts +22 -0
- package/corpus/templates/clips/desktop/src/lib/permissions.ts +3 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +97 -120
- package/corpus/templates/clips/desktop/src/lib/updater.ts +26 -4
- package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +4 -8
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +2 -2
- package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +11 -7
- package/corpus/templates/clips/desktop/src-tauri/tauri.linux.conf.json +11 -0
- package/corpus/templates/clips/netlify.toml +3 -0
- package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +106 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +9 -1
- package/corpus/templates/clips/server/lib/resumable-upload-provider.ts +52 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +433 -85
- package/corpus/templates/clips/server/lib/video-remux.ts +114 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +109 -0
- package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +22 -11
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +4 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +47 -5
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +10 -2
- package/corpus/templates/clips/shared/share-loader-response.ts +12 -0
- package/corpus/templates/clips/shared/transcript-status.ts +40 -0
- package/corpus/templates/content/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/content/.agents/skills/content/SKILL.md +57 -5
- package/corpus/templates/content/AGENTS.md +65 -55
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +10 -16
- package/corpus/templates/content/actions/_database-source-utils.ts +58 -11
- package/corpus/templates/content/actions/_property-utils.ts +30 -2
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +312 -114
- package/corpus/templates/content/actions/submit-content-database-form.ts +497 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +8 -1
- package/corpus/templates/content/actions/view-screen.ts +4 -1
- package/corpus/templates/content/agent-native.app-skill.json +1 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +250 -64
- package/corpus/templates/content/app/components/editor/database/FormView.tsx +460 -0
- package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
- package/corpus/templates/content/app/components/editor/database/settings.tsx +30 -37
- package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
- package/corpus/templates/content/app/components/editor/database/view-config.ts +29 -1
- package/corpus/templates/content/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +22 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/content/app/i18n-data.ts +225 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-backed-properties-now-load-current-source-values-as-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-database-refreshes-now-stay-explicit-and-accurate.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-database-form-views-now-collect-ordered-required-answers-and.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-database-tables-now-use-a-quieter-more-compact-layout-with-c.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-slack-intake-routes-to-content-database-forms.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -0
- package/corpus/templates/content/parity/matrix.ts +18 -0
- package/corpus/templates/content/shared/api.ts +27 -1
- package/corpus/templates/content/shared/database-form.ts +53 -0
- package/corpus/templates/design/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +26 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +85 -12
- package/corpus/templates/design/AGENTS.md +72 -18
- package/corpus/templates/design/DESIGN.md +1 -1
- package/corpus/templates/design/DEVELOPING.md +1 -1
- package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +116 -0
- package/corpus/templates/design/actions/create-design-from-template.ts +220 -0
- package/corpus/templates/design/actions/create-design-system.ts +92 -16
- package/corpus/templates/design/actions/delete-design-template.ts +28 -0
- package/corpus/templates/design/actions/delete-file.ts +7 -0
- package/corpus/templates/design/actions/edit-design.ts +3 -0
- package/corpus/templates/design/actions/export-design-as-figma-svg.ts +137 -5
- package/corpus/templates/design/actions/export-pdf.ts +1 -1
- package/corpus/templates/design/actions/generate-design.ts +3 -0
- package/corpus/templates/design/actions/get-design-snapshot.ts +9 -0
- package/corpus/templates/design/actions/get-figma-connection-status.ts +26 -0
- package/corpus/templates/design/actions/get-figma-design-context.ts +138 -0
- package/corpus/templates/design/actions/get-figma-styles.ts +2 -2
- package/corpus/templates/design/actions/import-figma-clipboard.ts +112 -16
- package/corpus/templates/design/actions/import-figma-frame.ts +15 -4
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +4 -0
- package/corpus/templates/design/actions/list-design-templates.ts +118 -0
- package/corpus/templates/design/actions/navigate.ts +16 -2
- package/corpus/templates/design/actions/provider-api-request.ts +11 -1
- package/corpus/templates/design/actions/save-design-as-template.ts +156 -0
- package/corpus/templates/design/actions/set-active-breakpoint.ts +13 -4
- package/corpus/templates/design/actions/take-design-screenshot.ts +73 -3
- package/corpus/templates/design/actions/update-file.ts +39 -22
- package/corpus/templates/design/actions/view-screen.ts +36 -1
- package/corpus/templates/design/actions/write-local-file.ts +50 -38
- package/corpus/templates/design/app/components/design/AutoLayoutSuggestionDialog.tsx +151 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +20 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +251 -22
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +3 -3
- package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +384 -9
- package/corpus/templates/design/app/components/design/EditPanel.tsx +105 -32
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +58 -28
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +539 -53
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +40 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +1 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +1 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +5 -1
- package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +2 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +3 -1
- package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +2 -0
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +19 -0
- package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +1 -0
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +27 -0
- package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +137 -81
- package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +25 -5
- package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +220 -3
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +13 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +22 -1
- package/corpus/templates/design/app/components/design/types.ts +4 -0
- package/corpus/templates/design/app/components/design-system/ProductionDesignSystemShowcase.tsx +208 -0
- package/corpus/templates/design/app/components/editor/FigmaLinkComposerBubble.tsx +321 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +24 -4
- package/corpus/templates/design/app/components/layout/Layout.tsx +16 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
- package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +72 -0
- package/corpus/templates/design/app/global.css +2 -35
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +10 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +127 -5
- package/corpus/templates/design/app/i18n-breakpoints.ts +209 -0
- package/corpus/templates/design/app/i18n-data.ts +1317 -59
- package/corpus/templates/design/app/i18n-template-feature.ts +458 -0
- package/corpus/templates/design/app/lib/design-clipboard.ts +202 -0
- package/corpus/templates/design/app/lib/design-file-upload.ts +87 -0
- package/corpus/templates/design/app/lib/design-import.ts +168 -11
- package/corpus/templates/design/app/lib/desktop-design-preview.ts +423 -0
- package/corpus/templates/design/app/lib/figma-clipboard.ts +74 -8
- package/corpus/templates/design/app/lib/figma-connection.ts +161 -0
- package/corpus/templates/design/app/lib/figma-svg-copy.ts +814 -22
- package/corpus/templates/design/app/lib/figma-url.ts +77 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +35 -0
- package/corpus/templates/design/app/pages/DesignSystems.tsx +236 -177
- package/corpus/templates/design/app/pages/Index.tsx +38 -0
- package/corpus/templates/design/app/pages/Templates.tsx +498 -0
- package/corpus/templates/design/app/pages/design-editor/auto-layout-suggestion.ts +328 -0
- package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/created-screen-navigation.ts +55 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +32 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +49 -2
- package/corpus/templates/design/app/pages/design-editor/export-capture.ts +296 -0
- package/corpus/templates/design/app/pages/design-editor/history.ts +101 -2
- package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +28 -1
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +34 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +202 -6
- package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +92 -0
- package/corpus/templates/design/app/pages/design-editor/save-failure.ts +58 -0
- package/corpus/templates/design/app/routes/templates.tsx +4 -6
- package/corpus/templates/design/changelog/2026-07-10-app-workspaces-now-use-clean-borderless-main-surfaces-throug.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-ask-chat-what-s-in-a-figma-file-or-frame-structure-screensho.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-canvas-edits-now-reject-malformed-html-before-it-can-corrupt.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-complex-designs-now-export-as-valid-secure-svgs-and-crisp-ra.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-complex-figma-masks-arcs-rich-text-transformed-images-and-ad.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-copied-layers-paste-across-designs-and-browser-tabs.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-copy-and-download-editable-figma-svg.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-copying-design-text-now-pastes-readable-text-into-other-apps.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-deleted-screens-can-be-restored-with-undo-and-removed-again-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-design-changes-now-save-before-switching-apps-and-retry-when.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-design-stays-usable-on-phones-by-keeping-editor-panels-and-f.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-download-all-screens-as-one-multi-page-pdf-from-the-overview.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-duplicated-layers-now-keep-labels-aria-relationships-fragmen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fig-import-results-stay-compact.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-figma-imports-now-load-real-fonts-fix-rotated-gradient-dashe.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-figma-links-in-chat-and-the-import-tab-now-offer-secure-one-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-cmd-z-not-restoring-content-after-an-agent-driven-desi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-download-pdf-being-unreachable-from-the-export-panel-e.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-dragging-a-layer-out-of-an-auto-layout-row-column-no-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-figma-svg-export-text-wrapping-sizing-and-inner-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-hiding-or-locking-one-layer-no-longer-hides-or-blocks-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-png-screenshots-of-tall-screens-being-cropped-to-one-v.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-fixed-png-svg-exports-capturing-broken-layout-when-webfonts-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-frame-tool-now-offers-standard-ad-unit-size-presets-medium-r.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-full-view-controls-stay-within-their-frame-instead-of-coveri.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-hover-focus-focus-visible-pressed-and-disabled-states-now-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-layer-drops-now-land-in-the-intended-grid-row-stay-visually-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-local-code-workspaces-now-keep-unsaved-edits-across-panel-sw.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-local-visual-editing-now-keeps-authenticated-sessions-shared.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-long-running-agent-work-no-longer-shows-a-premature-stuck-wa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-managed-figma-connections-are-recognized-automatically.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-new-designs-can-open-directly-in-the-editor-without-a-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-new-screens-are-selected-and-revealed-immediately.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-new-text-layers-undo-as-one-safe-creation.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-preview-and-apply-inferred-auto-layout-without-changing-yo.md +5 -0
- package/corpus/templates/design/changelog/2026-07-10-print-pdf-exports-and-paper-size-presets-letter-a4-now-match.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-responsive-frame-editing.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-reusable-design-templates.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-screen-overview-frames-now-use-a-clearer-interact-action-wit.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-start-designs-from-source-linked-material-3-carbon-or-primer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-tweaks-guidance.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-uploaded-fig-files-can-now-become-editable-design-screens-wi.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +3 -3
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/scripts/qa-figma-stress-import.ts +96 -0
- package/corpus/templates/design/server/db/index.ts +10 -0
- package/corpus/templates/design/server/db/schema.ts +44 -0
- package/corpus/templates/design/server/handlers/import-design-file.ts +114 -80
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +19 -6
- package/corpus/templates/design/server/lib/design-export.ts +240 -3
- package/corpus/templates/design/server/lib/design-template-data.ts +89 -0
- package/corpus/templates/design/server/lib/design-to-figma-svg.ts +250 -26
- package/corpus/templates/design/server/lib/fig-file-decoder.ts +839 -0
- package/corpus/templates/design/server/lib/fig-file-import.ts +287 -0
- package/corpus/templates/design/server/lib/fig-file-limits.ts +3 -0
- package/corpus/templates/design/server/lib/fig-file-to-html.ts +2568 -0
- package/corpus/templates/design/server/lib/figma-design-context.ts +359 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +478 -22
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +554 -29
- package/corpus/templates/design/server/lib/local-figma-qa-upload.ts +112 -0
- package/corpus/templates/design/server/lib/verify-write-grant.ts +16 -2
- package/corpus/templates/design/server/lib/visible-clipboard-html.ts +13 -3
- package/corpus/templates/design/server/plugins/agent-chat.ts +7 -0
- package/corpus/templates/design/server/plugins/db.ts +42 -0
- package/corpus/templates/design/server/plugins/local-figma-qa-upload.ts +7 -0
- package/corpus/templates/design/server/register-secrets.ts +8 -8
- package/corpus/templates/design/server/routes/api/qa-figma-import-assets/[assetId].get.ts +46 -0
- package/corpus/templates/design/server/source-workspace.ts +104 -12
- package/corpus/templates/design/shared/code-layer.ts +105 -28
- package/corpus/templates/design/shared/design-system-templates.ts +301 -0
- package/corpus/templates/design/shared/design-template-presets.ts +195 -0
- package/corpus/templates/design/shared/figma-url.ts +8 -0
- package/corpus/templates/design/shared/html-integrity.ts +306 -0
- package/corpus/templates/design/shared/interaction-states.ts +318 -23
- package/corpus/templates/design/shared/locked-layers.ts +151 -0
- package/corpus/templates/dispatch/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/dispatch/app/i18n/zh-TW.ts +48 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +536 -1
- package/corpus/templates/dispatch/changelog/2026-07-10-connect-slack-workspaces-with-oauth-and-manage-channel-ident.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-10-microsoft-teams-bots-and-discord-slash-commands-can-now-conn.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-10-slack-and-telegram-now-route-uptime-monitor-requests-to-anal.md +6 -0
- package/corpus/templates/forms/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +7 -0
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/actions/create-form.ts +44 -7
- package/corpus/templates/forms/actions/lib/assert-publishable-form.ts +38 -0
- package/corpus/templates/forms/actions/patch-form-fields.ts +4 -0
- package/corpus/templates/forms/actions/update-form.ts +2 -36
- package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +17 -0
- package/corpus/templates/forms/changelog/2026-07-10-agent-created-published-forms-now-return-the-anonymous-publi.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-10-published-forms-can-no-longer-be-edited-into-an-unusable-emp.md +6 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +4 -3
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/forms/shared/types.ts +5 -0
- package/corpus/templates/mail/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
- package/corpus/templates/mail/changelog/2026-07-10-mail-navigation-now-uses-a-clean-borderless-drawer.md +6 -0
- package/corpus/templates/plan/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +4 -1
- package/corpus/templates/plan/changelog/2026-07-10-local-plans-now-keep-valid-content-visible-when-one-generate.md +6 -0
- package/corpus/templates/plan/server/lib/local-plan-files.ts +4 -1
- package/corpus/templates/slides/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +88 -2
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/a2a/client.d.ts +9 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +1 -0
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +24 -69
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/types.d.ts +2 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/durable-background.d.ts +11 -0
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +17 -0
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +15 -5
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +44 -2
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +90 -9
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +109 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +206 -15
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +22 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/audit/record.d.ts.map +1 -1
- package/dist/audit/record.js +29 -0
- package/dist/audit/record.js.map +1 -1
- package/dist/audit/store.d.ts.map +1 -1
- package/dist/audit/store.js +62 -3
- package/dist/audit/store.js.map +1 -1
- package/dist/audit/types.d.ts +13 -0
- package/dist/audit/types.d.ts.map +1 -1
- package/dist/audit/types.js.map +1 -1
- package/dist/automation/index.d.ts +193 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js +464 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +10 -3
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +492 -35
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +7 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +32 -8
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +15 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +115 -47
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +14 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +35 -7
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +4 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +49 -4
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/automation.d.ts +14 -0
- package/dist/client/automation.d.ts.map +1 -0
- package/dist/client/automation.js +9 -0
- package/dist/client/automation.js.map +1 -0
- package/dist/client/chat/run-recovery.d.ts +4 -0
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +12 -10
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +8 -0
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/integrations/api.d.ts +115 -0
- package/dist/client/integrations/api.d.ts.map +1 -0
- package/dist/client/integrations/api.js +123 -0
- package/dist/client/integrations/api.js.map +1 -0
- package/dist/client/integrations/index.d.ts +1 -0
- package/dist/client/integrations/index.d.ts.map +1 -1
- package/dist/client/integrations/index.js +1 -0
- package/dist/client/integrations/index.js.map +1 -1
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
- package/dist/client/transcription/use-live-transcription.js +59 -5
- package/dist/client/transcription/use-live-transcription.js.map +1 -1
- package/dist/client/use-run-stuck-detection.d.ts +16 -1
- package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
- package/dist/client/use-run-stuck-detection.js +23 -4
- package/dist/client/use-run-stuck-detection.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +49 -4
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/workspace-deploy.d.ts.map +1 -1
- package/dist/deploy/workspace-deploy.js +31 -2
- package/dist/deploy/workspace-deploy.js.map +1 -1
- package/dist/file-upload/types.d.ts +2 -0
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +6 -4
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/adapters/discord.d.ts +3 -0
- package/dist/integrations/adapters/discord.d.ts.map +1 -0
- package/dist/integrations/adapters/discord.js +261 -0
- package/dist/integrations/adapters/discord.js.map +1 -0
- package/dist/integrations/adapters/index.d.ts +4 -0
- package/dist/integrations/adapters/index.d.ts.map +1 -0
- package/dist/integrations/adapters/index.js +26 -0
- package/dist/integrations/adapters/index.js.map +1 -0
- package/dist/integrations/adapters/microsoft-teams.d.ts +5 -0
- package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -0
- package/dist/integrations/adapters/microsoft-teams.js +295 -0
- package/dist/integrations/adapters/microsoft-teams.js.map +1 -0
- package/dist/integrations/adapters/slack.d.ts +8 -2
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +736 -27
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts +0 -2
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +49 -15
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts +0 -2
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +40 -17
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/catalog.d.ts +75 -0
- package/dist/integrations/catalog.d.ts.map +1 -0
- package/dist/integrations/catalog.js +451 -0
- package/dist/integrations/catalog.js.map +1 -0
- package/dist/integrations/controls-store.d.ts +44 -0
- package/dist/integrations/controls-store.d.ts.map +1 -0
- package/dist/integrations/controls-store.js +129 -0
- package/dist/integrations/controls-store.js.map +1 -0
- package/dist/integrations/index.d.ts +13 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +9 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/installations-store.d.ts +112 -0
- package/dist/integrations/installations-store.d.ts.map +1 -0
- package/dist/integrations/installations-store.js +493 -0
- package/dist/integrations/installations-store.js.map +1 -0
- package/dist/integrations/integration-memory.d.ts +24 -0
- package/dist/integrations/integration-memory.d.ts.map +1 -0
- package/dist/integrations/integration-memory.js +136 -0
- package/dist/integrations/integration-memory.js.map +1 -0
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -5
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/pending-tasks-store.d.ts +17 -0
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-store.js +71 -5
- package/dist/integrations/pending-tasks-store.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +520 -35
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/scope-store.d.ts +65 -0
- package/dist/integrations/scope-store.d.ts.map +1 -0
- package/dist/integrations/scope-store.js +361 -0
- package/dist/integrations/scope-store.js.map +1 -0
- package/dist/integrations/slack-manifest.d.ts +66 -0
- package/dist/integrations/slack-manifest.d.ts.map +1 -0
- package/dist/integrations/slack-manifest.js +70 -0
- package/dist/integrations/slack-manifest.js.map +1 -0
- package/dist/integrations/slack-oauth.d.ts +99 -0
- package/dist/integrations/slack-oauth.d.ts.map +1 -0
- package/dist/integrations/slack-oauth.js +226 -0
- package/dist/integrations/slack-oauth.js.map +1 -0
- package/dist/integrations/types.d.ts +144 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js +16 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/usage-budget-store.d.ts +84 -0
- package/dist/integrations/usage-budget-store.d.ts.map +1 -0
- package/dist/integrations/usage-budget-store.js +650 -0
- package/dist/integrations/usage-budget-store.js.map +1 -0
- package/dist/integrations/webhook-handler.d.ts +4 -0
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +415 -47
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/scheduler.d.ts +6 -0
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +83 -4
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +43 -11
- package/dist/jobs/tools.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +4 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +72 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +57 -15
- package/dist/resources/handlers.js.map +1 -1
- package/dist/resources/script-helpers.d.ts.map +1 -1
- package/dist/resources/script-helpers.js +34 -8
- package/dist/resources/script-helpers.js.map +1 -1
- package/dist/resources/store.d.ts +10 -0
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +54 -47
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +106 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +15 -4
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +248 -113
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +10 -14
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +3 -1
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +9 -2
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/edge.d.ts +1 -1
- package/dist/server/edge.d.ts.map +1 -1
- package/dist/server/edge.js +1 -1
- package/dist/server/edge.js.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/request-context.d.ts +18 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/social-og-image.d.ts.map +1 -1
- package/dist/server/social-og-image.js +3 -2
- package/dist/server/social-og-image.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +62 -44
- package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/dist/templates/default/AGENTS.md +7 -3
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
- package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
- package/dist/templates/workspace-core/AGENTS.md +3 -2
- package/dist/usage/store.d.ts +7 -0
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +24 -3
- package/dist/usage/store.js.map +1 -1
- package/docs/content/automation-connectors.mdx +80 -0
- package/docs/content/extensions.mdx +8 -0
- package/docs/content/locales/ar-SA/extensions.mdx +8 -0
- package/docs/content/locales/ar-SA/messaging.mdx +84 -15
- package/docs/content/locales/ar-SA/template-clips.mdx +1 -0
- package/docs/content/locales/ar-SA/template-design.mdx +1 -0
- package/docs/content/locales/de-DE/extensions.mdx +10 -0
- package/docs/content/locales/de-DE/messaging.mdx +92 -15
- package/docs/content/locales/de-DE/template-clips.mdx +1 -0
- package/docs/content/locales/de-DE/template-design.mdx +1 -0
- package/docs/content/locales/es-ES/extensions.mdx +10 -0
- package/docs/content/locales/es-ES/messaging.mdx +91 -15
- package/docs/content/locales/es-ES/template-clips.mdx +1 -0
- package/docs/content/locales/es-ES/template-design.mdx +1 -0
- package/docs/content/locales/fr-FR/extensions.mdx +10 -0
- package/docs/content/locales/fr-FR/messaging.mdx +91 -15
- package/docs/content/locales/fr-FR/template-clips.mdx +1 -0
- package/docs/content/locales/fr-FR/template-design.mdx +1 -0
- package/docs/content/locales/hi-IN/extensions.mdx +8 -0
- package/docs/content/locales/hi-IN/messaging.mdx +81 -15
- package/docs/content/locales/hi-IN/template-clips.mdx +1 -0
- package/docs/content/locales/hi-IN/template-design.mdx +1 -0
- package/docs/content/locales/ja-JP/extensions.mdx +9 -0
- package/docs/content/locales/ja-JP/messaging.mdx +81 -15
- package/docs/content/locales/ja-JP/template-clips.mdx +1 -0
- package/docs/content/locales/ja-JP/template-design.mdx +1 -0
- package/docs/content/locales/ko-KR/extensions.mdx +8 -0
- package/docs/content/locales/ko-KR/messaging.mdx +80 -15
- package/docs/content/locales/ko-KR/template-clips.mdx +1 -0
- package/docs/content/locales/ko-KR/template-design.mdx +1 -0
- package/docs/content/locales/pt-BR/extensions.mdx +9 -0
- package/docs/content/locales/pt-BR/messaging.mdx +88 -15
- package/docs/content/locales/pt-BR/template-clips.mdx +1 -0
- package/docs/content/locales/pt-BR/template-design.mdx +1 -0
- package/docs/content/locales/zh-CN/extensions.mdx +6 -0
- package/docs/content/locales/zh-CN/messaging.mdx +78 -15
- package/docs/content/locales/zh-CN/template-clips.mdx +1 -0
- package/docs/content/locales/zh-CN/template-design.mdx +1 -0
- package/docs/content/locales/zh-TW/extensions.mdx +6 -0
- package/docs/content/locales/zh-TW/messaging.mdx +78 -15
- package/docs/content/locales/zh-TW/template-clips.mdx +1 -0
- package/docs/content/locales/zh-TW/template-design.mdx +1 -0
- package/docs/content/messaging.mdx +227 -45
- package/docs/content/template-clips.mdx +3 -0
- package/docs/content/template-design.mdx +4 -0
- package/package.json +5 -1
- package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/src/templates/default/AGENTS.md +7 -3
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
- package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
- package/src/templates/workspace-core/AGENTS.md +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/integrations/adapters/slack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { H3Event } from \"h3\";\nimport { createError, getHeader, readRawBody } from \"h3\";\n\nimport type { EnvKeyConfig } from \"../../server/create-server.js\";\nimport { resolveSecret } from \"../../server/credential-provider.js\";\nimport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n OutboundTarget,\n} from \"../types.js\";\n\n/** Slack's max message length */\nconst SLACK_MAX_LENGTH = 4000;\nconst SLACK_SECTION_TEXT_MAX_LENGTH = 3000;\nconst SLACK_API_TIMEOUT_MS = 10_000;\n\n/**\n * Create a Slack platform adapter.\n *\n * Required env vars:\n * - SLACK_BOT_TOKEN — Bot user OAuth token (xoxb-...)\n * - SLACK_SIGNING_SECRET — Used to verify webhook signatures\n *\n * Optional env vars:\n * - SLACK_ALLOWED_TEAM_IDS — Comma-separated list of Slack workspace\n * `team_id` values (e.g. \"T012ABCDEF,T034GHIJKL\") that this deployment\n * accepts events from. Required in production and strongly recommended\n * to prevent cross-workspace event injection (H1 in the webhook audit):\n * the global `SLACK_SIGNING_SECRET` is the same key for every workspace\n * the app is installed to, so without an allowlist any installed\n * workspace can drive the agent. When unset the adapter accepts events\n * from any workspace in development, but rejects events in production.\n * - SLACK_ALLOWED_API_APP_IDS — Comma-separated list of Slack app IDs\n * (`api_app_id`) to additionally pin events to. Useful when the same\n * signing secret rotation surfaces multiple app installs.\n */\nexport function slackAdapter(): PlatformAdapter {\n return {\n platform: \"slack\",\n label: \"Slack\",\n\n getRequiredEnvKeys(): EnvKeyConfig[] {\n return [\n {\n key: \"SLACK_BOT_TOKEN\",\n label: \"Slack Bot Token\",\n required: true,\n helpText:\n \"In your Slack app's left nav: OAuth & Permissions → Bot User OAuth Token (starts with `xoxb-`).\",\n },\n {\n key: \"SLACK_SIGNING_SECRET\",\n label: \"Slack Signing Secret\",\n required: true,\n helpText:\n \"In your Slack app's left nav: Basic Information → App Credentials → Signing Secret.\",\n },\n ];\n },\n\n async handleVerification(\n event: H3Event,\n ): Promise<{ handled: boolean; response?: unknown }> {\n // Slack sends url_verification when first setting up the webhook.\n // readRawBodyCached caches the raw bytes on event.context.__rawBody so\n // subsequent verifyWebhook + parseIncomingMessage calls re-use them\n // without re-stringifying a parsed body (M2 in the audit).\n const body = await readRawBodyCached(event);\n try {\n const parsed = JSON.parse(body);\n if (parsed.type === \"url_verification\") {\n // Slack's URL verifier expects the raw challenge value in the\n // response body. Returning JSON works for some clients but the app\n // settings verifier rejects it as not matching the challenge.\n return { handled: true, response: parsed.challenge };\n }\n } catch {}\n return { handled: false };\n },\n\n async verifyWebhook(event: H3Event): Promise<boolean> {\n const signingSecret = await resolveSecret(\"SLACK_SIGNING_SECRET\");\n if (!signingSecret) return false;\n\n const signature = getHeader(event, \"x-slack-signature\");\n const timestamp = getHeader(event, \"x-slack-request-timestamp\");\n if (!signature || !timestamp) return false;\n\n // Reject requests older than 5 minutes (replay protection)\n const ts = parseInt(timestamp, 10);\n if (Math.abs(Date.now() / 1000 - ts) > 300) return false;\n\n const body = await readRawBodyCached(event);\n const crypto = await import(\"node:crypto\");\n const basestring = `v0:${timestamp}:${body}`;\n const expectedSignature =\n \"v0=\" +\n crypto\n .createHmac(\"sha256\", signingSecret)\n .update(basestring)\n .digest(\"hex\");\n\n // Timing-safe comparison\n try {\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature),\n );\n } catch {\n return false;\n }\n },\n\n async parseIncomingMessage(\n event: H3Event,\n ): Promise<IncomingMessage | null> {\n const raw = await readRawBodyCached(event);\n let payload: any;\n try {\n payload = JSON.parse(raw);\n } catch {\n return null;\n }\n\n // H1 (webhook audit): cross-workspace event injection. The global\n // SLACK_SIGNING_SECRET is the same key for every workspace this Slack\n // app is installed to — without a per-tenant allowlist any installed\n // workspace can drive the agent. We enforce SLACK_ALLOWED_TEAM_IDS\n // here AFTER the signature has already been verified by the webhook\n // handler, so this is purely a tenant-isolation gate (not a forgery\n // defense). When unset in production we surface a one-time warning\n // recommending it be configured.\n enforceWorkspaceAllowlist(payload);\n\n // Handle Events API wrapper\n if (payload.type === \"event_callback\") {\n const e = payload.event;\n if (!e) return null;\n\n // Ignore bot messages\n if (e.bot_id || e.subtype === \"bot_message\") return null;\n // Ignore message edits and deletes\n if (e.subtype === \"message_changed\" || e.subtype === \"message_deleted\")\n return null;\n\n // Handle both direct messages and app_mentions\n const text = e.text?.trim();\n if (!text) return null;\n\n // Remove bot mention from text (e.g., \"<@U123> do something\" → \"do something\")\n const cleanText = text.replace(/<@[A-Z0-9]+>/g, \"\").trim();\n if (!cleanText) return null;\n\n // Thread ID: use thread_ts if in a thread, otherwise message ts\n const threadTs = e.thread_ts || e.ts;\n const externalThreadId = `${e.channel}:${threadTs}`;\n\n return {\n platform: \"slack\",\n externalThreadId,\n text: cleanText,\n senderName: e.user,\n senderId: e.user,\n platformContext: {\n channelId: e.channel,\n threadTs: threadTs,\n messageTs: e.ts,\n teamId: payload.team_id,\n eventId: payload.event_id,\n },\n timestamp: Math.floor(parseFloat(e.ts) * 1000),\n };\n }\n\n return null;\n },\n\n async postProcessingPlaceholder(\n incoming: IncomingMessage,\n ): Promise<{ placeholderRef: string } | null> {\n // No placeholder reply in the thread — Slack's native assistant\n // status bar (\"agent-native is thinking…\", below the composer) is the\n // loading affordance. A second visible \"Working on it…\" reply was\n // redundant and added an extra chunk that we then had to overwrite.\n // We just set the native status and return null so sendResponse posts\n // the final reply as a fresh message.\n const token = await resolveSecret(\"SLACK_BOT_TOKEN\");\n if (!token) return null;\n\n const channelId = incoming.platformContext.channelId as string;\n const threadTs = incoming.platformContext.threadTs as string;\n if (!channelId || !threadTs) return null;\n\n // Best-effort: flip the native AI-assistant \"is thinking…\" status bar\n // in the channel input area. Requires `assistant:write` scope on the\n // app — otherwise silently no-ops.\n setSlackAssistantStatus(token, channelId, threadTs, \"is thinking…\");\n return null;\n },\n\n async sendResponse(\n message: OutgoingMessage,\n context: IncomingMessage,\n opts?: { placeholderRef?: string },\n ): Promise<void> {\n const token = await resolveSecret(\"SLACK_BOT_TOKEN\");\n if (!token) {\n console.error(\"[slack] SLACK_BOT_TOKEN not configured\");\n return;\n }\n\n const channelId = context.platformContext.channelId as string;\n const threadTs = context.platformContext.threadTs as string;\n const blocks = (message.platformContext as any)?.blocks as\n | unknown[]\n | undefined;\n const placeholderRef = opts?.placeholderRef;\n\n // Block-rich path: split text into chunks but render the FIRST chunk as\n // blocks (so we keep the in-place edit + button) and any overflow as\n // plain follow-up posts. The vast majority of replies fit in one block.\n const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);\n const hasProvidedBlocks = Array.isArray(blocks) && blocks.length > 0;\n const firstChunk = chunks[0] ?? (hasProvidedBlocks ? \"Response\" : \"\");\n if (!firstChunk) {\n if (threadTs) {\n setSlackAssistantStatus(token, channelId, threadTs, \"\");\n }\n return;\n }\n const restChunks = chunks.slice(1);\n\n const finalBlocks =\n blocks ??\n buildResponseBlocks(firstChunk, {\n threadDeepLinkUrl: (message.platformContext as any)\n ?.threadDeepLinkUrl,\n });\n\n const baseBody: Record<string, unknown> = {\n channel: channelId,\n text: firstChunk,\n blocks: finalBlocks,\n unfurl_links: false,\n unfurl_media: false,\n mrkdwn: true,\n };\n\n try {\n if (placeholderRef) {\n // Replace the \"thinking…\" placeholder in place.\n const res = await slackApiFetch(\"https://slack.com/api/chat.update\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ ...baseBody, ts: placeholderRef }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n error?: string;\n };\n if (!data.ok) {\n console.error(\"[slack] chat.update error:\", data.error);\n // Fall back to a fresh post so the user still sees a reply\n await postFresh(token, channelId, threadTs, baseBody);\n }\n } else {\n await postFresh(token, channelId, threadTs, baseBody);\n }\n\n // Clear the AI-assistant \"is thinking…\" status now that we've\n // delivered the final answer. Empty status clears it.\n if (threadTs) {\n setSlackAssistantStatus(token, channelId, threadTs, \"\");\n }\n\n // Overflow chunks (rare) — post as plain follow-ups in the same thread\n for (const chunk of restChunks) {\n await postFresh(token, channelId, threadTs, {\n channel: channelId,\n text: chunk,\n unfurl_links: false,\n unfurl_media: false,\n mrkdwn: true,\n });\n }\n } catch (err) {\n console.error(\"[slack] Failed to send message:\", err);\n throw err;\n }\n },\n\n async sendMessageToTarget(\n message: OutgoingMessage,\n target: OutboundTarget,\n ): Promise<void> {\n const token = await resolveSecret(\"SLACK_BOT_TOKEN\");\n if (!token) {\n console.error(\"[slack] SLACK_BOT_TOKEN not configured\");\n return;\n }\n\n const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);\n if (chunks.length === 0) return;\n for (const chunk of chunks) {\n const body: Record<string, unknown> = {\n channel: target.destination,\n text: chunk,\n };\n if (target.threadRef) body.thread_ts = target.threadRef;\n\n try {\n const res = await slackApiFetch(\n \"https://slack.com/api/chat.postMessage\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n },\n );\n const data = (await res.json()) as { ok: boolean; error?: string };\n if (!data.ok) {\n throw new Error(data.error || \"chat.postMessage failed\");\n }\n } catch (err) {\n console.error(\"[slack] Failed to send proactive message:\", err);\n throw err;\n }\n }\n },\n\n formatAgentResponse(\n text: string,\n opts?: { threadDeepLinkUrl?: string },\n ): OutgoingMessage {\n return {\n text: markdownToSlackMrkdwn(text),\n platformContext: opts?.threadDeepLinkUrl\n ? { threadDeepLinkUrl: opts.threadDeepLinkUrl }\n : {},\n };\n },\n\n async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {\n const hasToken = !!(await resolveSecret(\"SLACK_BOT_TOKEN\"));\n const hasSecret = !!(await resolveSecret(\"SLACK_SIGNING_SECRET\"));\n const configured = hasToken && hasSecret;\n\n return {\n platform: \"slack\",\n label: \"Slack\",\n enabled: false, // overridden by plugin\n configured,\n details: {\n hasToken,\n hasSecret,\n },\n error: !configured\n ? \"Save SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in settings\"\n : undefined,\n };\n },\n };\n}\n\n/**\n * Parse a comma-separated env var into a Set of trimmed, non-empty values.\n * Returns null when the env var is unset or empty (so callers can\n * distinguish \"no allowlist configured\" from \"empty allowlist\").\n */\nfunction parseAllowlistEnv(name: string): Set<string> | null {\n const raw = process.env[name];\n if (!raw) return null;\n const values = raw\n .split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n if (values.length === 0) return null;\n return new Set(values);\n}\n\nlet _missingAllowlistWarned = false;\n\n/**\n * Enforce that an incoming Slack event comes from an allowlisted workspace.\n *\n * H1 in the webhook audit: the framework uses a SINGLE global\n * SLACK_SIGNING_SECRET for every workspace the Slack app is installed to,\n * so a valid signature alone doesn't prove the request belongs to the\n * tenant the deployment intends to serve. This helper layers a per-tenant\n * allowlist on top of signature verification.\n *\n * Behavior:\n * - If `SLACK_ALLOWED_TEAM_IDS` is set: reject any payload whose\n * `team_id` isn't in the list.\n * - If `SLACK_ALLOWED_API_APP_IDS` is set: also reject payloads whose\n * `api_app_id` isn't in the list (bot apps can be installed under the\n * same Slack app id across multiple workspaces — pinning both keeps\n * the surface tight when team_id allows multiple workspaces).\n * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in production: reject the\n * event. Production must fail closed so any workspace with the shared\n * signing secret cannot drive the agent.\n * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in dev / single-tenant: log a\n * one-time warning and accept (current local setup behavior).\n *\n * Throws an h3 401 error when an allowlisted-but-mismatched payload is\n * received, which the integrations plugin surfaces to the caller as\n * \"Unrecognized Slack workspace\" without enqueuing the event.\n */\nfunction enforceWorkspaceAllowlist(payload: any): void {\n const teamId =\n typeof payload?.team_id === \"string\" ? payload.team_id : undefined;\n const apiAppId =\n typeof payload?.api_app_id === \"string\" ? payload.api_app_id : undefined;\n\n const allowedTeamIds = parseAllowlistEnv(\"SLACK_ALLOWED_TEAM_IDS\");\n const allowedAppIds = parseAllowlistEnv(\"SLACK_ALLOWED_API_APP_IDS\");\n\n if (!allowedTeamIds) {\n if (process.env.NODE_ENV === \"production\") {\n throw createError({\n statusCode: 401,\n statusMessage: \"Slack workspace allowlist is not configured\",\n });\n }\n if (!_missingAllowlistWarned) {\n _missingAllowlistWarned = true;\n console.warn(\n \"[slack] SLACK_ALLOWED_TEAM_IDS not set — accepting events from any workspace whose signature matches SLACK_SIGNING_SECRET. \" +\n \"Set SLACK_ALLOWED_TEAM_IDS to a comma-separated list of allowed team_id values before deploying to production.\",\n );\n }\n }\n\n if (allowedTeamIds) {\n if (!teamId || !allowedTeamIds.has(teamId)) {\n throw createError({\n statusCode: 401,\n statusMessage: \"Unrecognized Slack workspace\",\n });\n }\n }\n\n if (allowedAppIds) {\n if (!apiAppId || !allowedAppIds.has(apiAppId)) {\n throw createError({\n statusCode: 401,\n statusMessage: \"Unrecognized Slack workspace\",\n });\n }\n }\n}\n\n/**\n * Read the raw request body as a string and cache on the event context.\n *\n * This MUST read raw bytes from the request stream — never `JSON.stringify`\n * a parsed body, because Slack's HMAC is computed over the exact bytes Slack\n * sent. Re-stringifying a parsed object loses key ordering, whitespace, and\n * Unicode-escape choices, so the signature check would silently fail for\n * legitimate requests (M2 in the webhook security audit).\n *\n * h3 v2's body stream is consume-once, so we cache the raw string on the\n * event context after the first read. All call sites (handleVerification,\n * verifyWebhook, parseIncomingMessage) MUST go through this helper.\n */\nasync function readRawBodyCached(event: H3Event): Promise<string> {\n const cached = event.context.__rawBody;\n if (typeof cached === \"string\") return cached;\n // h3's readRawBody returns the bytes Slack actually sent, defaulting to\n // utf8-decoded. Returns undefined for empty bodies — we coerce to \"\" so\n // the HMAC check can proceed deterministically.\n const raw = (await readRawBody(event)) ?? \"\";\n event.context.__rawBody = raw;\n return raw;\n}\n\nfunction utf8ByteLength(text: string): number {\n return new TextEncoder().encode(text).length;\n}\n\nfunction prefixWithinUtf8ByteLimit(text: string, maxLength: number): string {\n let bytes = 0;\n let end = 0;\n for (const char of text) {\n const nextBytes = utf8ByteLength(char);\n if (bytes + nextBytes > maxLength) break;\n bytes += nextBytes;\n end += char.length;\n }\n return text.slice(0, end || 1);\n}\n\n/** Split a message into chunks that fit within the platform's byte limit. */\nfunction splitMessage(text: string, maxLength: number): string[] {\n if (utf8ByteLength(text) <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (utf8ByteLength(remaining) <= maxLength) {\n chunks.push(remaining);\n break;\n }\n\n const prefix = prefixWithinUtf8ByteLimit(remaining, maxLength);\n\n // Try to split at a newline\n let splitIdx = prefix.lastIndexOf(\"\\n\");\n if (splitIdx <= 0) {\n // Try to split at a space\n splitIdx = prefix.lastIndexOf(\" \");\n }\n if (splitIdx <= 0) {\n splitIdx = prefix.length;\n }\n chunks.push(remaining.slice(0, splitIdx));\n remaining = remaining.slice(splitIdx).trimStart();\n }\n return chunks;\n}\n\n/** Split a message and drop chunks Slack would render as blank messages. */\nfunction splitNonEmptyMessage(text: string, maxLength: number): string[] {\n return splitMessage(text, maxLength).filter(\n (chunk) => chunk.trim().length > 0,\n );\n}\n\n/** Hard cap on input length we feed to the regex-based mrkdwn converter.\n * L2 in the webhook audit: `\\*\\*(.+?)\\*\\*` with the `s` flag on a long\n * string of asterisks can exhibit super-linear backtracking. Slack\n * itself caps message bodies at 4000 chars (SLACK_MAX_LENGTH); we cap\n * the input here at 10x that as a defensive bound for any caller that\n * passes a longer rendering source through this helper before chunking. */\nconst MRKDWN_MAX_LENGTH = 40_000;\n\n/**\n * Convert standard markdown to Slack's mrkdwn dialect.\n * - `[text](url)` → `<url|text>`\n * - `**bold**` → `*bold*` (Slack uses single asterisks for bold)\n *\n * Inputs longer than MRKDWN_MAX_LENGTH are truncated before the regex\n * pass to bound worst-case backtracking on pathological input (L2 in the\n * webhook audit).\n */\nfunction markdownToSlackMrkdwn(text: string): string {\n const bounded =\n text.length > MRKDWN_MAX_LENGTH ? text.slice(0, MRKDWN_MAX_LENGTH) : text;\n return (\n bounded\n .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, \"<$2|$1>\")\n // Do not wrap bare URLs in Slack bold markers. Slack's autolinker can\n // treat the trailing `*` as part of the URL, producing a broken link.\n .replace(/\\*\\*<?(https?:\\/\\/[^\\s>*]+)>?\\*\\*/g, \"<$1>\")\n // Bounded character class instead of `.+?` with the `s` flag — caps\n // each bold span at 5000 chars so an attacker can't construct a\n // pathological \"**\" sequence that exhibits super-linear backtracking.\n // Newlines are allowed because `[^*]` excludes only the asterisk\n // itself, so multi-line bold spans still match.\n .replace(/\\*\\*([^*]{1,5000})\\*\\*/g, \"*$1*\")\n );\n}\n\n/**\n * Optionally set Slack's native AI-assistant status indicator (the small\n * \"is thinking…\" line under the message composer) for an app configured\n * with the `assistant:write` scope. Pure best-effort — fails silently for\n * apps that aren't set up as AI assistants.\n */\nfunction setSlackAssistantStatus(\n token: string,\n channelId: string,\n threadTs: string,\n status: string,\n): void {\n slackApiFetch(\"https://slack.com/api/assistant.threads.setStatus\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n channel_id: channelId,\n thread_ts: threadTs,\n status,\n }),\n }).catch(() => {});\n}\n\n/**\n * Block Kit payload for the final answer. We avoid auto-unfurl previews by\n * separating the deep-link out into a button instead of inlining it as a\n * `<url|text>` markdown link in the section body — that's what was producing\n * the giant \"Agent-Native Dispatch\" card in every thread reply.\n */\nfunction buildResponseBlocks(\n text: string,\n opts: { threadDeepLinkUrl?: string },\n): unknown[] {\n const sectionChunks = splitMessage(\n text || \"_(no response)_\",\n SLACK_SECTION_TEXT_MAX_LENGTH,\n );\n const blocks: any[] = sectionChunks.map((chunk) => ({\n type: \"section\",\n text: { type: \"mrkdwn\", text: chunk },\n }));\n if (opts.threadDeepLinkUrl) {\n blocks.push({\n type: \"actions\",\n elements: [\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Open thread\", emoji: true },\n url: opts.threadDeepLinkUrl,\n action_id: \"open_dispatch_thread\",\n },\n ],\n });\n }\n return blocks;\n}\n\n/**\n * Post a fresh message to a thread. Used as the placeholder-fallback path\n * (e.g. when chat.update fails) and for follow-up overflow chunks.\n */\nasync function postFresh(\n token: string,\n channelId: string,\n threadTs: string | undefined,\n body: Record<string, unknown>,\n): Promise<void> {\n const hasBlocks =\n Array.isArray(body.blocks) && (body.blocks as unknown[]).length > 0;\n if (\n typeof body.text === \"string\" &&\n body.text.trim().length === 0 &&\n !hasBlocks\n ) {\n return;\n }\n\n const payload: Record<string, unknown> = {\n ...body,\n channel: channelId,\n };\n if (threadTs && !payload.thread_ts) payload.thread_ts = threadTs;\n const res = await slackApiFetch(\"https://slack.com/api/chat.postMessage\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n });\n const data = (await res.json()) as { ok: boolean; error?: string };\n if (!data.ok) {\n console.error(\"[slack] chat.postMessage error:\", data.error);\n throw new Error(data.error || \"chat.postMessage failed\");\n }\n}\n\nasync function slackApiFetch(\n url: string,\n init: RequestInit,\n): Promise<Response> {\n const controller =\n typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = controller\n ? setTimeout(() => controller.abort(), SLACK_API_TIMEOUT_MS)\n : undefined;\n try {\n return await fetch(url, {\n ...init,\n signal: controller?.signal ?? init.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/integrations/adapters/slack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { H3Event } from \"h3\";\nimport { createError, getHeader, readRawBody } from \"h3\";\n\nimport type { EnvKeyConfig } from \"../../server/create-server.js\";\nimport { resolveSecret } from \"../../server/credential-provider.js\";\nimport { getRequestContext } from \"../../server/request-context.js\";\nimport { getIntegrationRequestContext } from \"../../server/request-context.js\";\nimport { createIntegrationControl } from \"../controls-store.js\";\nimport {\n getActiveIntegrationInstallationByKey,\n getActiveIntegrationInstallationForTenant,\n listIntegrationInstallations,\n resolveIntegrationTokenBundle,\n} from \"../installations-store.js\";\nimport { hasActivePendingTask } from \"../pending-tasks-store.js\";\nimport { slackInstallationKey } from \"../slack-oauth.js\";\nimport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n OutboundTarget,\n PlatformRunProgress,\n IntegrationContextMessage,\n IntegrationFileReference,\n} from \"../types.js\";\n\n/** Slack's max message length */\nconst SLACK_MAX_LENGTH = 4000;\nconst SLACK_SECTION_TEXT_MAX_LENGTH = 3000;\nconst SLACK_API_TIMEOUT_MS = 10_000;\n// Permalink lookup happens on Slack's acknowledgement path, so keep it well\n// inside Slack's three-second Events API deadline. Failure is non-fatal: the\n// normalized message still carries channel/thread ids for replies.\nconst SLACK_PERMALINK_TIMEOUT_MS = 1_000;\nconst SLACK_CONTEXT_MESSAGE_LIMIT = 15;\nconst SLACK_CONTEXT_TEXT_LIMIT = 2_000;\n\nexport interface SlackAdapterOptions {\n /** Resolve the bot token for the exact Slack installation. */\n resolveBotToken?: (incoming: IncomingMessage) => Promise<string | undefined>;\n /** Override active-thread detection for hosted adapters/tests. */\n isThreadActive?: (incoming: IncomingMessage) => Promise<boolean>;\n}\n\n/**\n * Create a Slack platform adapter.\n *\n * Required env vars:\n * - SLACK_BOT_TOKEN — Bot user OAuth token (xoxb-...)\n * - SLACK_SIGNING_SECRET — Used to verify webhook signatures\n *\n * Optional env vars:\n * - SLACK_ALLOWED_TEAM_IDS — Comma-separated list of Slack workspace\n * `team_id` values (e.g. \"T012ABCDEF,T034GHIJKL\") that this deployment\n * accepts events from. Required in production and strongly recommended\n * to prevent cross-workspace event injection (H1 in the webhook audit):\n * the global `SLACK_SIGNING_SECRET` is the same key for every workspace\n * the app is installed to, so without an allowlist any installed\n * workspace can drive the agent. When unset the adapter accepts events\n * from any workspace in development, but rejects events in production.\n * - SLACK_ALLOWED_API_APP_IDS — Comma-separated list of Slack app IDs\n * (`api_app_id`) to additionally pin events to. Useful when the same\n * signing secret rotation surfaces multiple app installs.\n */\nexport function slackAdapter(\n options: SlackAdapterOptions = {},\n): PlatformAdapter {\n const resolveBotToken = async (incoming: IncomingMessage) =>\n (await options.resolveBotToken?.(incoming)) ??\n (await resolveManagedSlackBotToken(incoming)) ??\n (await resolveSecret(\"SLACK_BOT_TOKEN\")) ??\n undefined;\n\n return {\n platform: \"slack\",\n label: \"Slack\",\n capabilities: {\n replyText: true,\n proactiveMessages: true,\n nativeThreads: true,\n contextualReplies: true,\n deferredWebhookResponse: false,\n interactionOnly: false,\n nativeContextHydration: true,\n liveRunProgress: true,\n },\n\n getRequiredEnvKeys(): EnvKeyConfig[] {\n return [\n {\n key: \"SLACK_BOT_TOKEN\",\n label: \"Slack Bot Token\",\n required: false,\n helpText:\n \"In your Slack app's left nav: OAuth & Permissions → Bot User OAuth Token (starts with `xoxb-`).\",\n },\n {\n key: \"SLACK_CLIENT_ID\",\n label: \"Slack OAuth Client ID\",\n required: false,\n helpText:\n \"Slack app Basic Information → App Credentials → Client ID.\",\n },\n {\n key: \"SLACK_CLIENT_SECRET\",\n label: \"Slack OAuth Client Secret\",\n required: false,\n helpText:\n \"Slack app Basic Information → App Credentials → Client Secret.\",\n },\n {\n key: \"SLACK_SIGNING_SECRET\",\n label: \"Slack Signing Secret\",\n required: true,\n helpText:\n \"In your Slack app's left nav: Basic Information → App Credentials → Signing Secret.\",\n },\n ];\n },\n\n async handleVerification(\n event: H3Event,\n ): Promise<{ handled: boolean; response?: unknown }> {\n // Slack sends url_verification when first setting up the webhook.\n // readRawBodyCached caches the raw bytes on event.context.__rawBody so\n // subsequent verifyWebhook + parseIncomingMessage calls re-use them\n // without re-stringifying a parsed body (M2 in the audit).\n const body = await readRawBodyCached(event);\n try {\n const parsed = JSON.parse(body);\n if (parsed.type === \"url_verification\") {\n // Slack's URL verifier expects the raw challenge value in the\n // response body. Returning JSON works for some clients but the app\n // settings verifier rejects it as not matching the challenge.\n return { handled: true, response: parsed.challenge };\n }\n } catch {}\n return { handled: false };\n },\n\n async verifyWebhook(event: H3Event): Promise<boolean> {\n const signingSecret = await resolveSecret(\"SLACK_SIGNING_SECRET\");\n if (!signingSecret) return false;\n\n const signature = getHeader(event, \"x-slack-signature\");\n const timestamp = getHeader(event, \"x-slack-request-timestamp\");\n if (!signature || !timestamp) return false;\n\n // Reject requests older than 5 minutes (replay protection)\n const ts = parseInt(timestamp, 10);\n if (Math.abs(Date.now() / 1000 - ts) > 300) return false;\n\n const body = await readRawBodyCached(event);\n const crypto = await import(\"node:crypto\");\n const basestring = `v0:${timestamp}:${body}`;\n const expectedSignature =\n \"v0=\" +\n crypto\n .createHmac(\"sha256\", signingSecret)\n .update(basestring)\n .digest(\"hex\");\n\n // Timing-safe comparison\n try {\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature),\n );\n } catch {\n return false;\n }\n },\n\n async parseIncomingMessage(\n event: H3Event,\n ): Promise<IncomingMessage | null> {\n const raw = await readRawBodyCached(event);\n let payload: any;\n try {\n payload = JSON.parse(raw);\n } catch {\n return null;\n }\n\n // H1 (webhook audit): cross-workspace event injection. The global\n // SLACK_SIGNING_SECRET is the same key for every workspace this Slack\n // app is installed to — without a per-tenant allowlist any installed\n // workspace can drive the agent. We enforce SLACK_ALLOWED_TEAM_IDS\n // here AFTER the signature has already been verified by the webhook\n // handler, so this is purely a tenant-isolation gate (not a forgery\n // defense). When unset in production we surface a one-time warning\n // recommending it be configured.\n await enforceWorkspaceAllowlist(payload);\n\n // Handle Events API wrapper\n if (payload.type === \"event_callback\") {\n const e = payload.event;\n if (!e) return null;\n\n // Ignore bot messages\n if (e.bot_id || e.subtype === \"bot_message\") return null;\n // Ignore message edits and deletes\n if (e.subtype === \"message_changed\" || e.subtype === \"message_deleted\")\n return null;\n\n // Handle DMs and explicit mentions. Ordinary channel replies are only\n // accepted while this exact workspace-qualified thread has queued or\n // executing work; broad message subscriptions must never invoke the\n // agent for general channel chatter.\n const text = e.text?.trim();\n if (!text) return null;\n\n const teamId =\n typeof payload.team_id === \"string\" ? payload.team_id : \"unknown\";\n const apiAppId =\n typeof payload.api_app_id === \"string\"\n ? payload.api_app_id\n : \"unknown\";\n const agentContext = normalizeSlackAgentContext(e.app_context, teamId);\n const isDm =\n typeof e.channel_type === \"string\"\n ? e.channel_type === \"im\"\n : typeof e.channel === \"string\" && e.channel.startsWith(\"D\");\n const isMention = e.type === \"app_mention\";\n const isThreadReply = !isDm && !isMention && !!e.thread_ts;\n if (!isDm && !isMention && !isThreadReply) return null;\n\n // Remove bot mention from text (e.g., \"<@U123> do something\" → \"do something\")\n const cleanText = text.replace(/<@[A-Z0-9]+>/g, \"\").trim();\n if (!cleanText) return null;\n\n // Thread ID: use thread_ts if in a thread, otherwise message ts\n const threadTs = e.thread_ts || e.ts;\n const externalThreadId = `${apiAppId}:${teamId}:${e.channel}:${threadTs}`;\n const partialIncoming: IncomingMessage = {\n platform: \"slack\",\n externalThreadId,\n text: cleanText,\n senderName: e.user,\n senderId: e.user,\n triggerKind: isDm ? \"dm\" : isMention ? \"mention\" : \"thread_reply\",\n conversationType: isDm ? \"dm\" : \"unknown\",\n tenantId: teamId,\n actorTrust: { memberType: \"unknown\", verified: true },\n platformContext: {\n channelId: e.channel,\n channelType: e.channel_type,\n threadTs,\n messageTs: e.ts,\n teamId,\n apiAppId,\n enterpriseId:\n typeof payload.enterprise_id === \"string\"\n ? payload.enterprise_id\n : undefined,\n eventId: payload.event_id,\n ...(agentContext\n ? {\n agentContext: agentContext.entities,\n activeContextChannelId: agentContext.channelId,\n }\n : {}),\n },\n threadRef: threadTs,\n replyRef: e.ts,\n timestamp: Math.floor(parseFloat(e.ts) * 1000),\n };\n\n if (isThreadReply) {\n const active = options.isThreadActive\n ? await options.isThreadActive(partialIncoming)\n : await hasActivePendingTask(\"slack\", externalThreadId);\n if (!active) return null;\n }\n\n const token = await resolveBotToken(partialIncoming);\n const threadPermalink = await resolveSlackThreadPermalink(\n e.channel,\n threadTs,\n token,\n );\n\n return {\n ...partialIncoming,\n platformContext: {\n ...partialIncoming.platformContext,\n ...(threadPermalink ? { threadPermalink } : {}),\n },\n ...(threadPermalink ? { sourceUrl: threadPermalink } : {}),\n };\n }\n\n return null;\n },\n\n getLegacyExternalThreadIds(incoming: IncomingMessage): string[] {\n const channelId = incoming.platformContext.channelId;\n const threadTs = incoming.platformContext.threadTs;\n return typeof channelId === \"string\" && typeof threadTs === \"string\"\n ? [`${channelId}:${threadTs}`]\n : [];\n },\n\n async postProcessingPlaceholder(\n incoming: IncomingMessage,\n ): Promise<{ placeholderRef: string } | null> {\n // No placeholder reply in the thread — Slack's native assistant\n // status bar (\"agent-native is thinking…\", below the composer) is the\n // loading affordance. A second visible \"Working on it…\" reply was\n // redundant and added an extra chunk that we then had to overwrite.\n // We just set the native status and return null so sendResponse posts\n // the final reply as a fresh message.\n const token = await resolveBotToken(incoming);\n if (!token) return null;\n\n const channelId = incoming.platformContext.channelId as string;\n const threadTs = incoming.platformContext.threadTs as string;\n if (!channelId || !threadTs) return null;\n\n // Best-effort: flip the native Agent \"is thinking…\" status bar in the\n // channel input area. Slack accepts chat:write for this method. The\n // canonical manifest separately requests assistant:write for Agent View\n // and app_context_changed events.\n setSlackAssistantStatus(token, channelId, threadTs, \"is thinking…\");\n return null;\n },\n\n async hydrateIncomingMessage(\n incoming: IncomingMessage,\n ): Promise<IncomingMessage> {\n const token = await resolveBotToken(incoming);\n if (!token) return incoming;\n return hydrateSlackContext(token, incoming);\n },\n\n async startRunProgress(\n incoming: IncomingMessage,\n ): Promise<PlatformRunProgress | null> {\n const token = await resolveBotToken(incoming);\n if (!token) return null;\n return startSlackRunProgress(token, incoming);\n },\n\n async sendResponse(\n message: OutgoingMessage,\n context: IncomingMessage,\n opts?: { placeholderRef?: string },\n ): Promise<void> {\n const token = await resolveBotToken(context);\n if (!token) {\n console.error(\"[slack] SLACK_BOT_TOKEN not configured\");\n return;\n }\n\n const channelId = context.platformContext.channelId as string;\n const threadTs = context.platformContext.threadTs as string;\n const blocks = (message.platformContext as any)?.blocks as\n | unknown[]\n | undefined;\n const placeholderRef = opts?.placeholderRef;\n\n // Block-rich path: split text into chunks but render the FIRST chunk as\n // blocks (so we keep the in-place edit + button) and any overflow as\n // plain follow-up posts. The vast majority of replies fit in one block.\n const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);\n const hasProvidedBlocks = Array.isArray(blocks) && blocks.length > 0;\n const firstChunk = chunks[0] ?? (hasProvidedBlocks ? \"Response\" : \"\");\n if (!firstChunk) {\n if (threadTs) {\n setSlackAssistantStatus(token, channelId, threadTs, \"\");\n }\n return;\n }\n const restChunks = chunks.slice(1);\n\n const finalBlocks =\n blocks ??\n buildResponseBlocks(firstChunk, {\n threadDeepLinkUrl: (message.platformContext as any)\n ?.threadDeepLinkUrl,\n });\n\n const baseBody: Record<string, unknown> = {\n channel: channelId,\n text: firstChunk,\n blocks: finalBlocks,\n unfurl_links: false,\n unfurl_media: false,\n mrkdwn: true,\n };\n\n try {\n if (placeholderRef) {\n // Replace the \"thinking…\" placeholder in place.\n const res = await slackApiFetch(\"https://slack.com/api/chat.update\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ ...baseBody, ts: placeholderRef }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n error?: string;\n };\n if (!data.ok) {\n console.error(\"[slack] chat.update error:\", data.error);\n // Fall back to a fresh post so the user still sees a reply\n await postFresh(token, channelId, threadTs, baseBody);\n }\n } else {\n await postFresh(token, channelId, threadTs, baseBody);\n }\n\n // Clear the AI-assistant \"is thinking…\" status now that we've\n // delivered the final answer. Empty status clears it.\n if (threadTs) {\n setSlackAssistantStatus(token, channelId, threadTs, \"\");\n }\n\n // Overflow chunks (rare) — post as plain follow-ups in the same thread\n for (const chunk of restChunks) {\n await postFresh(token, channelId, threadTs, {\n channel: channelId,\n text: chunk,\n unfurl_links: false,\n unfurl_media: false,\n mrkdwn: true,\n });\n }\n } catch (err) {\n console.error(\"[slack] Failed to send message:\", err);\n throw err;\n }\n },\n\n async sendMessageToTarget(\n message: OutgoingMessage,\n target: OutboundTarget,\n ): Promise<void> {\n const targetContext: IncomingMessage = {\n platform: \"slack\",\n externalThreadId: `${target.tenantId ?? \"unknown\"}:${target.destination}:${target.threadRef ?? \"root\"}`,\n text: \"\",\n platformContext: {\n channelId: target.destination,\n threadTs: target.threadRef,\n teamId: target.tenantId,\n },\n tenantId: target.tenantId,\n timestamp: Date.now(),\n };\n const token = await resolveBotToken(targetContext);\n if (!token) {\n console.error(\"[slack] SLACK_BOT_TOKEN not configured\");\n return;\n }\n\n const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);\n if (chunks.length === 0) return;\n for (const chunk of chunks) {\n const body: Record<string, unknown> = {\n channel: target.destination,\n text: chunk,\n };\n if (target.threadRef) body.thread_ts = target.threadRef;\n\n try {\n const res = await slackApiFetch(\n \"https://slack.com/api/chat.postMessage\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n },\n );\n const data = (await res.json()) as { ok: boolean; error?: string };\n if (!data.ok) {\n throw new Error(data.error || \"chat.postMessage failed\");\n }\n } catch (err) {\n console.error(\"[slack] Failed to send proactive message:\", err);\n throw err;\n }\n }\n },\n\n formatAgentResponse(\n text: string,\n opts?: { threadDeepLinkUrl?: string },\n ): OutgoingMessage {\n return {\n text: markdownToSlackMrkdwn(text),\n platformContext: opts?.threadDeepLinkUrl\n ? { threadDeepLinkUrl: opts.threadDeepLinkUrl }\n : {},\n };\n },\n\n async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {\n const hasToken = !!(await resolveSecret(\"SLACK_BOT_TOKEN\"));\n const hasSecret = !!(await resolveSecret(\"SLACK_SIGNING_SECRET\"));\n const ctx = getRequestContext();\n const managedInstallations = ctx?.userEmail\n ? await listIntegrationInstallations(\n {\n userEmail: ctx.userEmail,\n orgId: ctx.orgId ?? null,\n },\n \"slack\",\n ).catch(() => [])\n : [];\n const connectedInstallations = managedInstallations.filter(\n (installation) => installation.status === \"connected\",\n );\n const configured =\n hasSecret && (hasToken || connectedInstallations.length > 0);\n\n return {\n platform: \"slack\",\n label: \"Slack\",\n enabled: false, // overridden by plugin\n configured,\n details: {\n hasToken,\n hasSecret,\n managedInstallationCount: connectedInstallations.length,\n managedInstallations: connectedInstallations.map((installation) => ({\n id: installation.id,\n teamId: installation.teamId,\n teamName: installation.teamName,\n enterpriseId: installation.enterpriseId,\n health: installation.health,\n scopes: installation.scopes,\n })),\n },\n error: !configured\n ? \"Connect a Slack workspace with OAuth or save a bot token and signing secret\"\n : undefined,\n };\n },\n };\n}\n\n/**\n * Parse a comma-separated env var into a Set of trimmed, non-empty values.\n * Returns null when the env var is unset or empty (so callers can\n * distinguish \"no allowlist configured\" from \"empty allowlist\").\n */\nfunction parseAllowlistEnv(name: string): Set<string> | null {\n const raw = process.env[name];\n if (!raw) return null;\n const values = raw\n .split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n if (values.length === 0) return null;\n return new Set(values);\n}\n\nasync function resolveManagedSlackBotToken(\n incoming: IncomingMessage,\n): Promise<string | undefined> {\n const teamId =\n typeof incoming.platformContext.teamId === \"string\"\n ? incoming.platformContext.teamId\n : incoming.tenantId;\n const apiAppId =\n typeof incoming.platformContext.apiAppId === \"string\"\n ? incoming.platformContext.apiAppId\n : undefined;\n const enterpriseId =\n typeof incoming.platformContext.enterpriseId === \"string\"\n ? incoming.platformContext.enterpriseId\n : undefined;\n if (!teamId && !enterpriseId) return undefined;\n try {\n let installation = apiAppId\n ? await getActiveIntegrationInstallationByKey(\n \"slack\",\n slackInstallationKey({ teamId, enterpriseId, apiAppId }),\n )\n : null;\n if (!installation && teamId) {\n installation = await getActiveIntegrationInstallationForTenant(\n \"slack\",\n teamId,\n );\n }\n if (!installation && enterpriseId) {\n installation = await getActiveIntegrationInstallationForTenant(\n \"slack\",\n enterpriseId,\n );\n }\n const key =\n installation?.installationKey ??\n slackInstallationKey({ teamId, enterpriseId, apiAppId });\n return (await resolveIntegrationTokenBundle(\"slack\", key))?.accessToken;\n } catch {\n return undefined;\n }\n}\n\nlet _missingAllowlistWarned = false;\n\n/**\n * Enforce that an incoming Slack event comes from an allowlisted workspace.\n *\n * H1 in the webhook audit: the framework uses a SINGLE global\n * SLACK_SIGNING_SECRET for every workspace the Slack app is installed to,\n * so a valid signature alone doesn't prove the request belongs to the\n * tenant the deployment intends to serve. This helper layers a per-tenant\n * allowlist on top of signature verification.\n *\n * Behavior:\n * - If `SLACK_ALLOWED_TEAM_IDS` is set: reject any payload whose\n * `team_id` isn't in the list.\n * - If `SLACK_ALLOWED_API_APP_IDS` is set: also reject payloads whose\n * `api_app_id` isn't in the list (bot apps can be installed under the\n * same Slack app id across multiple workspaces — pinning both keeps\n * the surface tight when team_id allows multiple workspaces).\n * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in production: reject the\n * event. Production must fail closed so any workspace with the shared\n * signing secret cannot drive the agent.\n * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in dev / single-tenant: log a\n * one-time warning and accept (current local setup behavior).\n *\n * Throws an h3 401 error when an allowlisted-but-mismatched payload is\n * received, which the integrations plugin surfaces to the caller as\n * \"Unrecognized Slack workspace\" without enqueuing the event.\n */\nasync function enforceWorkspaceAllowlist(payload: any): Promise<void> {\n const teamId =\n typeof payload?.team_id === \"string\" ? payload.team_id : undefined;\n const apiAppId =\n typeof payload?.api_app_id === \"string\" ? payload.api_app_id : undefined;\n\n const allowedTeamIds = parseAllowlistEnv(\"SLACK_ALLOWED_TEAM_IDS\");\n const allowedAppIds = parseAllowlistEnv(\"SLACK_ALLOWED_API_APP_IDS\");\n\n if (!allowedTeamIds) {\n if (process.env.NODE_ENV === \"production\") {\n let managed = false;\n try {\n const key = slackInstallationKey({ teamId, apiAppId });\n managed = !!(await getActiveIntegrationInstallationByKey(\"slack\", key));\n } catch {}\n if (!managed) {\n throw createError({\n statusCode: 401,\n statusMessage: \"Slack workspace is not connected\",\n });\n }\n }\n if (!_missingAllowlistWarned) {\n _missingAllowlistWarned = true;\n console.warn(\n \"[slack] SLACK_ALLOWED_TEAM_IDS not set — accepting events from any workspace whose signature matches SLACK_SIGNING_SECRET. \" +\n \"Set SLACK_ALLOWED_TEAM_IDS to a comma-separated list of allowed team_id values before deploying to production.\",\n );\n }\n }\n\n if (allowedTeamIds) {\n if (!teamId || !allowedTeamIds.has(teamId)) {\n throw createError({\n statusCode: 401,\n statusMessage: \"Unrecognized Slack workspace\",\n });\n }\n }\n\n if (allowedAppIds) {\n if (!apiAppId || !allowedAppIds.has(apiAppId)) {\n throw createError({\n statusCode: 401,\n statusMessage: \"Unrecognized Slack workspace\",\n });\n }\n }\n}\n\n/**\n * Read the raw request body as a string and cache on the event context.\n *\n * This MUST read raw bytes from the request stream — never `JSON.stringify`\n * a parsed body, because Slack's HMAC is computed over the exact bytes Slack\n * sent. Re-stringifying a parsed object loses key ordering, whitespace, and\n * Unicode-escape choices, so the signature check would silently fail for\n * legitimate requests (M2 in the webhook security audit).\n *\n * h3 v2's body stream is consume-once, so we cache the raw string on the\n * event context after the first read. All call sites (handleVerification,\n * verifyWebhook, parseIncomingMessage) MUST go through this helper.\n */\nasync function readRawBodyCached(event: H3Event): Promise<string> {\n const cached = event.context.__rawBody;\n if (typeof cached === \"string\") return cached;\n // h3's readRawBody returns the bytes Slack actually sent, defaulting to\n // utf8-decoded. Returns undefined for empty bodies — we coerce to \"\" so\n // the HMAC check can proceed deterministically.\n const raw = (await readRawBody(event)) ?? \"\";\n event.context.__rawBody = raw;\n return raw;\n}\n\nfunction utf8ByteLength(text: string): number {\n return new TextEncoder().encode(text).length;\n}\n\nfunction prefixWithinUtf8ByteLimit(text: string, maxLength: number): string {\n let bytes = 0;\n let end = 0;\n for (const char of text) {\n const nextBytes = utf8ByteLength(char);\n if (bytes + nextBytes > maxLength) break;\n bytes += nextBytes;\n end += char.length;\n }\n return text.slice(0, end || 1);\n}\n\n/** Split a message into chunks that fit within the platform's byte limit. */\nfunction splitMessage(text: string, maxLength: number): string[] {\n if (utf8ByteLength(text) <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (utf8ByteLength(remaining) <= maxLength) {\n chunks.push(remaining);\n break;\n }\n\n const prefix = prefixWithinUtf8ByteLimit(remaining, maxLength);\n\n // Try to split at a newline\n let splitIdx = prefix.lastIndexOf(\"\\n\");\n if (splitIdx <= 0) {\n // Try to split at a space\n splitIdx = prefix.lastIndexOf(\" \");\n }\n if (splitIdx <= 0) {\n splitIdx = prefix.length;\n }\n chunks.push(remaining.slice(0, splitIdx));\n remaining = remaining.slice(splitIdx).trimStart();\n }\n return chunks;\n}\n\n/** Split a message and drop chunks Slack would render as blank messages. */\nfunction splitNonEmptyMessage(text: string, maxLength: number): string[] {\n return splitMessage(text, maxLength).filter(\n (chunk) => chunk.trim().length > 0,\n );\n}\n\n/** Hard cap on input length we feed to the regex-based mrkdwn converter.\n * L2 in the webhook audit: `\\*\\*(.+?)\\*\\*` with the `s` flag on a long\n * string of asterisks can exhibit super-linear backtracking. Slack\n * itself caps message bodies at 4000 chars (SLACK_MAX_LENGTH); we cap\n * the input here at 10x that as a defensive bound for any caller that\n * passes a longer rendering source through this helper before chunking. */\nconst MRKDWN_MAX_LENGTH = 40_000;\n\n/**\n * Convert standard markdown to Slack's mrkdwn dialect.\n * - `[text](url)` → `<url|text>`\n * - `**bold**` → `*bold*` (Slack uses single asterisks for bold)\n *\n * Inputs longer than MRKDWN_MAX_LENGTH are truncated before the regex\n * pass to bound worst-case backtracking on pathological input (L2 in the\n * webhook audit).\n */\nfunction markdownToSlackMrkdwn(text: string): string {\n const bounded =\n text.length > MRKDWN_MAX_LENGTH ? text.slice(0, MRKDWN_MAX_LENGTH) : text;\n return (\n bounded\n .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, \"<$2|$1>\")\n // Do not wrap bare URLs in Slack bold markers. Slack's autolinker can\n // treat the trailing `*` as part of the URL, producing a broken link.\n .replace(/\\*\\*<?(https?:\\/\\/[^\\s>*]+)>?\\*\\*/g, \"<$1>\")\n // Bounded character class instead of `.+?` with the `s` flag — caps\n // each bold span at 5000 chars so an attacker can't construct a\n // pathological \"**\" sequence that exhibits super-linear backtracking.\n // Newlines are allowed because `[^*]` excludes only the asterisk\n // itself, so multi-line bold spans still match.\n .replace(/\\*\\*([^*]{1,5000})\\*\\*/g, \"*$1*\")\n );\n}\n\n/**\n * Optionally set Slack's native Agent status indicator (the small \"is\n * thinking…\" line under the message composer). The method uses chat:write;\n * Agent View itself is configured separately by the Slack app manifest.\n * Pure best-effort — failures never block the response.\n */\nfunction setSlackAssistantStatus(\n token: string,\n channelId: string,\n threadTs: string,\n status: string,\n): void {\n slackApiFetch(\"https://slack.com/api/assistant.threads.setStatus\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n channel_id: channelId,\n thread_ts: threadTs,\n status,\n }),\n }).catch(() => {});\n}\n\n/**\n * Block Kit payload for the final answer. We avoid auto-unfurl previews by\n * separating the deep-link out into a button instead of inlining it as a\n * `<url|text>` markdown link in the section body — that's what was producing\n * the giant \"Agent-Native Dispatch\" card in every thread reply.\n */\nfunction buildResponseBlocks(\n text: string,\n opts: { threadDeepLinkUrl?: string },\n): unknown[] {\n const sectionChunks = splitMessage(\n text || \"_(no response)_\",\n SLACK_SECTION_TEXT_MAX_LENGTH,\n );\n const blocks: any[] = sectionChunks.map((chunk) => ({\n type: \"section\",\n text: { type: \"mrkdwn\", text: chunk },\n }));\n if (opts.threadDeepLinkUrl) {\n blocks.push({\n type: \"actions\",\n elements: [\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Open thread\", emoji: true },\n url: opts.threadDeepLinkUrl,\n action_id: \"open_dispatch_thread\",\n },\n ],\n });\n }\n return blocks;\n}\n\n/**\n * Post a fresh message to a thread. Used as the placeholder-fallback path\n * (e.g. when chat.update fails) and for follow-up overflow chunks.\n */\nasync function postFresh(\n token: string,\n channelId: string,\n threadTs: string | undefined,\n body: Record<string, unknown>,\n): Promise<void> {\n const hasBlocks =\n Array.isArray(body.blocks) && (body.blocks as unknown[]).length > 0;\n if (\n typeof body.text === \"string\" &&\n body.text.trim().length === 0 &&\n !hasBlocks\n ) {\n return;\n }\n\n const payload: Record<string, unknown> = {\n ...body,\n channel: channelId,\n };\n if (threadTs && !payload.thread_ts) payload.thread_ts = threadTs;\n const res = await slackApiFetch(\"https://slack.com/api/chat.postMessage\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n });\n const data = (await res.json()) as { ok: boolean; error?: string };\n if (!data.ok) {\n console.error(\"[slack] chat.postMessage error:\", data.error);\n throw new Error(data.error || \"chat.postMessage failed\");\n }\n}\n\nasync function slackApiFetch(\n url: string,\n init: RequestInit,\n timeoutMs = SLACK_API_TIMEOUT_MS,\n): Promise<Response> {\n const controller =\n typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = controller\n ? setTimeout(() => controller.abort(), timeoutMs)\n : undefined;\n try {\n return await fetch(url, {\n ...init,\n signal: controller?.signal ?? init.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nasync function resolveSlackThreadPermalink(\n channelId: unknown,\n threadTs: unknown,\n resolvedToken?: string,\n): Promise<string | undefined> {\n if (typeof channelId !== \"string\" || typeof threadTs !== \"string\") {\n return undefined;\n }\n const token = resolvedToken ?? (await resolveSecret(\"SLACK_BOT_TOKEN\"));\n if (!token) return undefined;\n\n try {\n const url = new URL(\"https://slack.com/api/chat.getPermalink\");\n url.searchParams.set(\"channel\", channelId);\n url.searchParams.set(\"message_ts\", threadTs);\n const res = await slackApiFetch(\n url.toString(),\n { headers: { Authorization: `Bearer ${token}` } },\n SLACK_PERMALINK_TIMEOUT_MS,\n );\n const data = (await res.json()) as {\n ok?: boolean;\n permalink?: unknown;\n };\n if (!data.ok || typeof data.permalink !== \"string\") return undefined;\n\n const permalink = new URL(data.permalink);\n const isSlackHost =\n permalink.hostname === \"slack.com\" ||\n permalink.hostname.endsWith(\".slack.com\");\n if (permalink.protocol !== \"https:\" || !isSlackHost) return undefined;\n return permalink.toString();\n } catch {\n return undefined;\n }\n}\n\nfunction boundedSlackText(value: unknown): string {\n return typeof value === \"string\"\n ? value.slice(0, SLACK_CONTEXT_TEXT_LIMIT)\n : \"\";\n}\n\nfunction normalizeSlackAgentContext(\n value: unknown,\n eventTeamId: string,\n): {\n entities: Array<{ type: string; value: string; teamId?: string }>;\n channelId?: string;\n} | null {\n if (!value || typeof value !== \"object\") return null;\n const rawEntities = (value as { entities?: unknown }).entities;\n if (!Array.isArray(rawEntities)) return null;\n const entities = rawEntities.slice(0, 10).flatMap((entity) => {\n if (!entity || typeof entity !== \"object\") return [];\n const record = entity as Record<string, unknown>;\n if (typeof record.type !== \"string\" || typeof record.value !== \"string\") {\n return [];\n }\n const teamId =\n typeof record.team_id === \"string\" ? record.team_id : undefined;\n if (teamId && eventTeamId !== \"unknown\" && teamId !== eventTeamId) {\n return [];\n }\n return [\n {\n type: record.type.slice(0, 100),\n value: record.value.slice(0, 200),\n ...(teamId ? { teamId } : {}),\n },\n ];\n });\n if (!entities.length) return null;\n const channelId = entities.find(\n (entity) =>\n entity.type === \"slack#/types/channel_id\" &&\n /^[CDG][A-Z0-9]+$/.test(entity.value),\n )?.value;\n return { entities, ...(channelId ? { channelId } : {}) };\n}\n\nfunction slackFileReference(value: unknown): IntegrationFileReference | null {\n if (!value || typeof value !== \"object\") return null;\n const file = value as Record<string, unknown>;\n if (typeof file.id !== \"string\") return null;\n return {\n id: file.id,\n ...(typeof file.name === \"string\" ? { name: file.name } : {}),\n ...(typeof file.mimetype === \"string\" ? { mimetype: file.mimetype } : {}),\n ...(typeof file.size === \"number\" ? { size: file.size } : {}),\n ...(typeof file.permalink === \"string\"\n ? { permalink: file.permalink }\n : {}),\n ...(typeof file.url_private_download === \"string\"\n ? { downloadUrl: file.url_private_download }\n : {}),\n };\n}\n\nasync function slackJson(\n token: string,\n method: string,\n params: Record<string, string>,\n timeoutMs = 2_000,\n): Promise<Record<string, any> | null> {\n try {\n const url = new URL(`https://slack.com/api/${method}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n const response = await slackApiFetch(\n url.toString(),\n { headers: { Authorization: `Bearer ${token}` } },\n timeoutMs,\n );\n const body = (await response.json()) as Record<string, any>;\n return body.ok ? body : null;\n } catch {\n return null;\n }\n}\n\nasync function hydrateSlackContext(\n token: string,\n incoming: IncomingMessage,\n): Promise<IncomingMessage> {\n const channelId = incoming.platformContext.channelId;\n const threadTs = incoming.platformContext.threadTs;\n const senderId = incoming.senderId;\n if (typeof channelId !== \"string\" || typeof threadTs !== \"string\") {\n return incoming;\n }\n\n const [thread, history, pins, conversation, user] = await Promise.all([\n slackJson(token, \"conversations.replies\", {\n channel: channelId,\n ts: threadTs,\n limit: String(SLACK_CONTEXT_MESSAGE_LIMIT),\n }),\n slackJson(token, \"conversations.history\", {\n channel: channelId,\n latest: String(incoming.platformContext.messageTs ?? threadTs),\n inclusive: \"true\",\n limit: String(SLACK_CONTEXT_MESSAGE_LIMIT),\n }),\n slackJson(token, \"pins.list\", { channel: channelId }),\n slackJson(token, \"conversations.info\", { channel: channelId }),\n senderId ? slackJson(token, \"users.info\", { user: senderId }) : null,\n ]);\n\n // Agent View can attach the Slack surface the user is currently viewing to\n // a DM. Treat it only as a context hint: Slack requires us to prove the bot\n // can access the referenced channel with conversations.info before reading\n // any history from it.\n const activeContextChannelId =\n typeof incoming.platformContext.activeContextChannelId === \"string\"\n ? incoming.platformContext.activeContextChannelId\n : null;\n const activeContextConversation =\n activeContextChannelId && activeContextChannelId !== channelId\n ? await slackJson(token, \"conversations.info\", {\n channel: activeContextChannelId,\n })\n : null;\n const activeContextHistory = activeContextConversation\n ? await slackJson(token, \"conversations.history\", {\n channel: activeContextChannelId!,\n limit: \"5\",\n })\n : null;\n const activeContextName =\n typeof activeContextConversation?.channel?.name === \"string\"\n ? activeContextConversation.channel.name\n : null;\n const activeContextMessages = Array.isArray(activeContextHistory?.messages)\n ? activeContextHistory.messages.map((message: Record<string, any>) => ({\n ...message,\n text: `[Active Slack context${activeContextName ? ` #${activeContextName}` : \"\"}] ${boundedSlackText(message.text)}`,\n }))\n : [];\n\n const rawMessages = [\n ...(Array.isArray(history?.messages) ? history.messages : []),\n ...(Array.isArray(pins?.items)\n ? pins.items\n .map((item: Record<string, any>) => item.message)\n .filter(Boolean)\n : []),\n ...(Array.isArray(thread?.messages) ? thread.messages : []),\n ...activeContextMessages,\n ];\n const uniqueMessages = [\n ...new Map(\n rawMessages.map((message: Record<string, any>, index) => [\n typeof message.ts === \"string\" ? message.ts : `unknown:${index}`,\n message,\n ]),\n ).values(),\n ].slice(-SLACK_CONTEXT_MESSAGE_LIMIT);\n\n const messages: IntegrationContextMessage[] = uniqueMessages.length\n ? uniqueMessages.map((message: Record<string, any>) => {\n const files = Array.isArray(message.files)\n ? message.files\n .map(slackFileReference)\n .filter(\n (\n file: IntegrationFileReference | null,\n ): file is IntegrationFileReference => file !== null,\n )\n : undefined;\n const reactions = Array.isArray(message.reactions)\n ? message.reactions\n .filter(\n (reaction: any) =>\n typeof reaction?.name === \"string\" &&\n typeof reaction?.count === \"number\",\n )\n .map((reaction: any) => ({\n name: reaction.name,\n count: reaction.count,\n }))\n : undefined;\n return {\n ...(typeof message.user === \"string\"\n ? { senderId: message.user }\n : {}),\n text: boundedSlackText(message.text),\n timestamp:\n typeof message.ts === \"string\"\n ? Math.floor(parseFloat(message.ts) * 1000)\n : incoming.timestamp,\n ...(reactions?.length ? { reactions } : {}),\n ...(files?.length ? { files } : {}),\n };\n })\n : [];\n\n const profile = user?.user?.profile;\n const isGuest = user?.user?.is_restricted === true;\n const isExternal = user?.user?.is_ultra_restricted === true;\n const isPrivate = conversation?.channel?.is_private === true;\n const isExternalShared = conversation?.channel?.is_ext_shared === true;\n const isMpim = conversation?.channel?.is_mpim === true;\n const isIm = conversation?.channel?.is_im === true;\n const conversationType = isIm\n ? \"dm\"\n : isMpim\n ? \"group_dm\"\n : isPrivate\n ? \"private_channel\"\n : \"channel\";\n\n const attachedFiles = messages.flatMap((message) => message.files ?? []);\n const detailedFiles = await Promise.all(\n [...new Set(attachedFiles.map((file) => file.id))]\n .slice(0, 5)\n .map(async (fileId) => {\n const result = await slackJson(token, \"files.info\", { file: fileId });\n return slackFileReference(result?.file);\n }),\n );\n const fileById = new Map(\n detailedFiles\n .filter((file): file is IntegrationFileReference => file !== null)\n .map((file) => [file.id, file]),\n );\n const hydratedMessages = messages.map((message) => ({\n ...message,\n ...(message.files?.length\n ? {\n files: message.files.map((file) => ({\n ...file,\n ...(fileById.get(file.id) ?? {}),\n })),\n }\n : {}),\n }));\n const hydratedFiles = hydratedMessages.flatMap(\n (message) => message.files ?? [],\n );\n return {\n ...incoming,\n ...(typeof profile?.display_name === \"string\" && profile.display_name\n ? { senderName: profile.display_name }\n : typeof profile?.real_name === \"string\" && profile.real_name\n ? { senderName: profile.real_name }\n : {}),\n ...(typeof profile?.email === \"string\"\n ? { senderEmail: profile.email, senderVerified: true }\n : {}),\n conversationType,\n actorTrust: {\n memberType: isExternal ? \"external\" : isGuest ? \"guest\" : \"member\",\n verified: true,\n },\n contextMessages: hydratedMessages,\n ...(hydratedFiles.length ? { files: hydratedFiles.slice(0, 20) } : {}),\n platformContext: {\n ...incoming.platformContext,\n channelName:\n typeof conversation?.channel?.name === \"string\"\n ? conversation.channel.name\n : undefined,\n isExternalShared,\n ...(activeContextChannelId\n ? {\n activeContextChannelId,\n ...(activeContextName\n ? { activeContextChannelName: activeContextName }\n : {}),\n }\n : {}),\n },\n };\n}\n\nfunction shortTaskTitle(value: unknown): string {\n const text = typeof value === \"string\" ? value : \"Working\";\n return text.replace(/[-_]/g, \" \").slice(0, 200);\n}\n\nasync function postSlackJson(\n token: string,\n method: string,\n body: Record<string, unknown>,\n): Promise<Record<string, any>> {\n const response = await slackApiFetch(`https://slack.com/api/${method}`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = (await response.json()) as Record<string, any>;\n if (!data.ok) throw new Error(data.error || `${method} failed`);\n return data;\n}\n\nasync function startSlackRunProgress(\n token: string,\n incoming: IncomingMessage,\n): Promise<PlatformRunProgress | null> {\n const channel = incoming.platformContext.channelId;\n const threadTs = incoming.platformContext.threadTs;\n if (typeof channel !== \"string\" || typeof threadTs !== \"string\") return null;\n\n let started: Record<string, any>;\n try {\n started = await postSlackJson(token, \"chat.startStream\", {\n channel,\n thread_ts: threadTs,\n ...(incoming.tenantId ? { recipient_team_id: incoming.tenantId } : {}),\n ...(incoming.senderId ? { recipient_user_id: incoming.senderId } : {}),\n task_display_mode: \"plan\",\n markdown_text: \"Working on your request…\",\n chunks: [\n {\n type: \"plan_update\",\n title: \"Working on your request\",\n },\n {\n type: \"task_update\",\n id: \"agent-native:context\",\n title: \"Understand the request\",\n status: \"in_progress\",\n details: \"Loading relevant context\",\n },\n ],\n });\n } catch {\n return null;\n }\n\n const streamTs = started.ts;\n if (typeof streamTs !== \"string\") return null;\n const tasks = new Map<string, { title: string; status: string }>();\n const toolTaskIds = new Map<string, string>();\n tasks.set(\"agent-native:context\", {\n title: \"Understand the request\",\n status: \"in_progress\",\n });\n let sequence = 0;\n let lastWriteAt = 0;\n let pending: Record<string, unknown> | null = null;\n let pendingTimer: ReturnType<typeof setTimeout> | null = null;\n let approvalControls: { approve: string; deny: string } | null = null;\n let cancelControl: string | null = null;\n\n const append = async (chunk: Record<string, unknown>) => {\n const now = Date.now();\n const write = async (value: Record<string, unknown>) => {\n lastWriteAt = Date.now();\n await postSlackJson(token, \"chat.appendStream\", {\n channel,\n ts: streamTs,\n markdown_text: \"Progress updated.\",\n chunks: [value],\n }).catch(() => {});\n };\n if (now - lastWriteAt >= 900) {\n await write(chunk);\n return;\n }\n pending = chunk;\n if (!pendingTimer) {\n pendingTimer = setTimeout(\n () => {\n const value = pending;\n pending = null;\n pendingTimer = null;\n if (value) void write(value);\n },\n 900 - (now - lastWriteAt),\n );\n }\n };\n\n const taskId = (prefix: string, explicit?: string) =>\n `${prefix}:${explicit || ++sequence}`.slice(0, 240);\n\n return {\n async onEvent(event) {\n if (!cancelControl) {\n const context = getIntegrationRequestContext();\n const ownerEmail = getRequestContext()?.userEmail;\n if (\n context?.lineage?.runId &&\n ownerEmail &&\n incoming.senderId &&\n incoming.tenantId\n ) {\n cancelControl = await createIntegrationControl({\n action: \"cancel\",\n ownerEmail,\n orgId: getRequestContext()?.orgId ?? null,\n requesterId: incoming.senderId,\n teamId: incoming.tenantId,\n apiAppId:\n typeof incoming.platformContext.apiAppId === \"string\"\n ? incoming.platformContext.apiAppId\n : null,\n channelId: channel,\n messageTs: streamTs,\n runId: context.lineage.runId,\n incoming,\n });\n await append({\n type: \"blocks\",\n blocks: [\n {\n type: \"actions\",\n block_id: `agent-native-running-${Date.now()}`,\n elements: [\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Cancel\" },\n style: \"danger\",\n action_id: \"agent_native_cancel\",\n value: cancelControl,\n },\n ],\n },\n ],\n });\n }\n }\n if (event.type === \"approval_required\") {\n const context = getIntegrationRequestContext();\n const ownerEmail = getRequestContext()?.userEmail;\n if (context && ownerEmail && incoming.senderId && incoming.tenantId) {\n const common = {\n ownerEmail,\n orgId: getRequestContext()?.orgId ?? null,\n requesterId: incoming.senderId,\n teamId: incoming.tenantId,\n apiAppId:\n typeof incoming.platformContext.apiAppId === \"string\"\n ? incoming.platformContext.apiAppId\n : null,\n channelId: channel,\n messageTs: streamTs,\n runId: context.lineage?.runId ?? null,\n approvalKey: event.approvalKey,\n incoming,\n };\n const [approve, deny] = await Promise.all([\n createIntegrationControl({ ...common, action: \"approve\" }),\n createIntegrationControl({ ...common, action: \"deny\" }),\n ]);\n approvalControls = { approve, deny };\n }\n await append({\n type: \"task_update\",\n id: \"agent-native:approval\",\n title: `Approve ${shortTaskTitle(event.tool)}`,\n status: \"pending\",\n details: \"Waiting for the requester\",\n });\n } else if (event.type === \"tool_start\") {\n const key = event.id || event.tool;\n const id = taskId(\"tool\", event.id);\n toolTaskIds.set(key, id);\n const title = shortTaskTitle(event.tool);\n tasks.set(id, { title, status: \"in_progress\" });\n await append({\n type: \"task_update\",\n id,\n title,\n status: \"in_progress\",\n });\n } else if (event.type === \"tool_done\") {\n const key = event.id || event.tool;\n const id = toolTaskIds.get(key) ?? taskId(\"tool\", event.id);\n const title = tasks.get(id)?.title ?? shortTaskTitle(event.tool);\n tasks.set(id, {\n title,\n status: event.isError ? \"error\" : \"complete\",\n });\n await append({\n type: \"task_update\",\n id,\n title,\n status: event.isError ? \"error\" : \"complete\",\n });\n } else if (event.type === \"agent_call\") {\n const id = taskId(\"agent\", event.agent);\n const status =\n event.status === \"start\"\n ? \"in_progress\"\n : event.status === \"done\"\n ? \"complete\"\n : \"error\";\n const title = `Ask ${shortTaskTitle(event.agent)}`;\n tasks.set(id, { title, status });\n await append({ type: \"task_update\", id, title, status });\n } else if (event.type === \"activity\") {\n await append({\n type: \"task_update\",\n id: \"agent-native:context\",\n title: \"Understand the request\",\n status: \"in_progress\",\n details: shortTaskTitle(event.label),\n });\n }\n },\n async complete(message) {\n if (pendingTimer) clearTimeout(pendingTimer);\n const finalChunks = [...tasks.entries()].map(([id, task]) => ({\n type: \"task_update\",\n id,\n title: task.title,\n status: task.status === \"in_progress\" ? \"complete\" : task.status,\n }));\n const messageBlocks = Array.isArray(message.platformContext.blocks)\n ? message.platformContext.blocks\n : [];\n const controlBlocks = approvalControls\n ? [\n {\n type: \"actions\",\n block_id: `agent-native-approval-${Date.now()}`,\n elements: [\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Approve\" },\n style: \"primary\",\n action_id: \"agent_native_approve\",\n value: approvalControls.approve,\n },\n {\n type: \"button\",\n text: { type: \"plain_text\", text: \"Deny\" },\n style: \"danger\",\n action_id: \"agent_native_deny\",\n value: approvalControls.deny,\n },\n ],\n },\n ]\n : [];\n await postSlackJson(token, \"chat.stopStream\", {\n channel,\n ts: streamTs,\n markdown_text: message.text || \"Done.\",\n ...(finalChunks.length ? { chunks: finalChunks } : {}),\n ...(messageBlocks.length || controlBlocks.length\n ? { blocks: [...messageBlocks, ...controlBlocks].slice(0, 50) }\n : {}),\n });\n setSlackAssistantStatus(token, channel, threadTs, \"\");\n },\n async fail(message) {\n if (pendingTimer) clearTimeout(pendingTimer);\n await postSlackJson(token, \"chat.stopStream\", {\n channel,\n ts: streamTs,\n markdown_text: message.slice(0, SLACK_MAX_LENGTH),\n }).catch(() => {});\n setSlackAssistantStatus(token, channel, threadTs, \"\");\n },\n };\n}\n"]}
|
|
@@ -4,8 +4,6 @@ import type { PlatformAdapter } from "../types.js";
|
|
|
4
4
|
*
|
|
5
5
|
* Required env vars:
|
|
6
6
|
* - TELEGRAM_BOT_TOKEN — Bot token from @BotFather
|
|
7
|
-
*
|
|
8
|
-
* Optional env vars:
|
|
9
7
|
* - TELEGRAM_WEBHOOK_SECRET — Secret token for webhook verification
|
|
10
8
|
*/
|
|
11
9
|
export declare function telegramAdapter(): PlatformAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/telegram.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,aAAa,CAAC;AAuBrB
|
|
1
|
+
{"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/telegram.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,aAAa,CAAC;AAuBrB;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,eAAe,CA8SjD"}
|
|
@@ -25,14 +25,20 @@ function shouldRefuseWhenSecretMissing() {
|
|
|
25
25
|
*
|
|
26
26
|
* Required env vars:
|
|
27
27
|
* - TELEGRAM_BOT_TOKEN — Bot token from @BotFather
|
|
28
|
-
*
|
|
29
|
-
* Optional env vars:
|
|
30
28
|
* - TELEGRAM_WEBHOOK_SECRET — Secret token for webhook verification
|
|
31
29
|
*/
|
|
32
30
|
export function telegramAdapter() {
|
|
33
31
|
return {
|
|
34
32
|
platform: "telegram",
|
|
35
33
|
label: "Telegram",
|
|
34
|
+
capabilities: {
|
|
35
|
+
replyText: true,
|
|
36
|
+
proactiveMessages: true,
|
|
37
|
+
nativeThreads: true,
|
|
38
|
+
contextualReplies: true,
|
|
39
|
+
deferredWebhookResponse: false,
|
|
40
|
+
interactionOnly: false,
|
|
41
|
+
},
|
|
36
42
|
getRequiredEnvKeys() {
|
|
37
43
|
return [
|
|
38
44
|
{
|
|
@@ -44,8 +50,8 @@ export function telegramAdapter() {
|
|
|
44
50
|
{
|
|
45
51
|
key: "TELEGRAM_WEBHOOK_SECRET",
|
|
46
52
|
label: "Telegram Webhook Secret",
|
|
47
|
-
required:
|
|
48
|
-
helpText: "
|
|
53
|
+
required: true,
|
|
54
|
+
helpText: "A random secret token. Telegram echoes it on every webhook so the adapter can verify the request came from Telegram.",
|
|
49
55
|
},
|
|
50
56
|
];
|
|
51
57
|
},
|
|
@@ -118,16 +124,23 @@ export function telegramAdapter() {
|
|
|
118
124
|
: text.replace(/^\/\w+\s*/, "").trim() || text;
|
|
119
125
|
const chat = message.chat;
|
|
120
126
|
const from = message.from;
|
|
127
|
+
const messageThreadId = message.message_thread_id;
|
|
128
|
+
const externalThreadId = messageThreadId === undefined
|
|
129
|
+
? `chat:${String(chat.id)}`
|
|
130
|
+
: `chat:${String(chat.id)}:thread:${String(messageThreadId)}`;
|
|
121
131
|
return {
|
|
122
132
|
platform: "telegram",
|
|
123
|
-
externalThreadId
|
|
133
|
+
externalThreadId,
|
|
124
134
|
text: cleanText,
|
|
125
135
|
senderName: from?.first_name + (from?.last_name ? ` ${from.last_name}` : ""),
|
|
126
136
|
senderId: String(from?.id),
|
|
137
|
+
threadRef: messageThreadId === undefined ? undefined : String(messageThreadId),
|
|
138
|
+
replyRef: String(message.message_id),
|
|
127
139
|
platformContext: {
|
|
128
140
|
chatId: chat.id,
|
|
129
141
|
chatType: chat.type,
|
|
130
142
|
messageId: message.message_id,
|
|
143
|
+
messageThreadId,
|
|
131
144
|
rawText: text,
|
|
132
145
|
fromId: from?.id,
|
|
133
146
|
fromUsername: from?.username,
|
|
@@ -135,6 +148,12 @@ export function telegramAdapter() {
|
|
|
135
148
|
timestamp: message.date * 1000,
|
|
136
149
|
};
|
|
137
150
|
},
|
|
151
|
+
getLegacyExternalThreadIds(incoming) {
|
|
152
|
+
const chatId = incoming.platformContext.chatId;
|
|
153
|
+
return typeof chatId === "string" || typeof chatId === "number"
|
|
154
|
+
? [String(chatId)]
|
|
155
|
+
: [];
|
|
156
|
+
},
|
|
138
157
|
async sendResponse(message, context) {
|
|
139
158
|
const token = await resolveSecret("TELEGRAM_BOT_TOKEN");
|
|
140
159
|
if (!token) {
|
|
@@ -143,16 +162,26 @@ export function telegramAdapter() {
|
|
|
143
162
|
}
|
|
144
163
|
const chatId = context.platformContext.chatId;
|
|
145
164
|
const chunks = splitMessage(message.text, TELEGRAM_MAX_LENGTH);
|
|
146
|
-
for (const chunk of chunks) {
|
|
165
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
147
166
|
try {
|
|
167
|
+
const body = {
|
|
168
|
+
chat_id: chatId,
|
|
169
|
+
text: chunk,
|
|
170
|
+
parse_mode: "Markdown",
|
|
171
|
+
};
|
|
172
|
+
if (context.threadRef) {
|
|
173
|
+
body.message_thread_id = Number(context.threadRef);
|
|
174
|
+
}
|
|
175
|
+
if (index === 0 && context.replyRef) {
|
|
176
|
+
body.reply_parameters = {
|
|
177
|
+
message_id: Number(context.replyRef),
|
|
178
|
+
allow_sending_without_reply: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
148
181
|
const res = await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
149
182
|
method: "POST",
|
|
150
183
|
headers: { "Content-Type": "application/json" },
|
|
151
|
-
body: JSON.stringify(
|
|
152
|
-
chat_id: chatId,
|
|
153
|
-
text: chunk,
|
|
154
|
-
parse_mode: "Markdown",
|
|
155
|
-
}),
|
|
184
|
+
body: JSON.stringify(body),
|
|
156
185
|
});
|
|
157
186
|
const data = (await res.json());
|
|
158
187
|
if (!data.ok) {
|
|
@@ -162,8 +191,8 @@ export function telegramAdapter() {
|
|
|
162
191
|
method: "POST",
|
|
163
192
|
headers: { "Content-Type": "application/json" },
|
|
164
193
|
body: JSON.stringify({
|
|
165
|
-
|
|
166
|
-
|
|
194
|
+
...body,
|
|
195
|
+
parse_mode: undefined,
|
|
167
196
|
}),
|
|
168
197
|
});
|
|
169
198
|
}
|
|
@@ -219,6 +248,8 @@ export function telegramAdapter() {
|
|
|
219
248
|
async getStatus(_baseUrl) {
|
|
220
249
|
const token = await resolveSecret("TELEGRAM_BOT_TOKEN");
|
|
221
250
|
const hasToken = !!token;
|
|
251
|
+
const hasWebhookSecret = !!(await resolveSecret("TELEGRAM_WEBHOOK_SECRET"));
|
|
252
|
+
const configured = hasToken && hasWebhookSecret;
|
|
222
253
|
let botName;
|
|
223
254
|
if (hasToken) {
|
|
224
255
|
try {
|
|
@@ -234,12 +265,15 @@ export function telegramAdapter() {
|
|
|
234
265
|
platform: "telegram",
|
|
235
266
|
label: "Telegram",
|
|
236
267
|
enabled: false, // overridden by plugin
|
|
237
|
-
configured
|
|
268
|
+
configured,
|
|
238
269
|
details: {
|
|
239
270
|
hasToken,
|
|
271
|
+
hasWebhookSecret,
|
|
240
272
|
botUsername: botName,
|
|
241
273
|
},
|
|
242
|
-
error: !
|
|
274
|
+
error: !configured
|
|
275
|
+
? "Save TELEGRAM_BOT_TOKEN and TELEGRAM_WEBHOOK_SECRET in settings"
|
|
276
|
+
: undefined,
|
|
243
277
|
};
|
|
244
278
|
},
|
|
245
279
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/integrations/adapters/telegram.ts"],"names":[],"mappings":"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","sourcesContent":["import type { H3Event } from \"h3\";\nimport { getHeader } from \"h3\";\n\nimport type { EnvKeyConfig } from \"../../server/create-server.js\";\nimport { resolveSecret } from \"../../server/credential-provider.js\";\nimport { readBody } from \"../../server/h3-helpers.js\";\nimport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n OutboundTarget,\n} from \"../types.js\";\n\n/** Telegram's max message length */\nconst TELEGRAM_MAX_LENGTH = 4096;\n\n/**\n * One-shot warning flag — log once per process when accepting unverified\n * webhooks (M6 in the webhook security audit).\n */\nlet _telegramUnverifiedWarned = false;\n\n/**\n * Returns true when the deployment is running in production mode and the\n * operator has NOT explicitly opted into accepting unverified webhooks for\n * local testing. In production we MUST refuse webhooks whose secret is\n * unset — otherwise an attacker can drive the agent loop with arbitrary\n * messages (C2 in the webhook security audit).\n */\nfunction shouldRefuseWhenSecretMissing(): boolean {\n if (process.env.AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS === \"1\") return false;\n return process.env.NODE_ENV === \"production\";\n}\n\n/**\n * Create a Telegram platform adapter.\n *\n * Required env vars:\n * - TELEGRAM_BOT_TOKEN — Bot token from @BotFather\n *\n * Optional env vars:\n * - TELEGRAM_WEBHOOK_SECRET — Secret token for webhook verification\n */\nexport function telegramAdapter(): PlatformAdapter {\n return {\n platform: \"telegram\",\n label: \"Telegram\",\n\n getRequiredEnvKeys(): EnvKeyConfig[] {\n return [\n {\n key: \"TELEGRAM_BOT_TOKEN\",\n label: \"Telegram Bot Token\",\n required: true,\n helpText:\n \"From @BotFather after `/newbot` — the long token Telegram gives you (looks like `123456:ABC-DEF...`).\",\n },\n {\n key: \"TELEGRAM_WEBHOOK_SECRET\",\n label: \"Telegram Webhook Secret\",\n required: false,\n helpText:\n \"Optional. Any random string — Telegram will echo it on every webhook so dispatch can verify the request came from Telegram.\",\n },\n ];\n },\n\n async handleVerification(\n event: H3Event,\n ): Promise<{ handled: boolean; response?: unknown }> {\n // Pre-read the raw body once and cache on the event context. h3 v2's\n // request body stream can only be consumed once; without this, the\n // later `parseIncomingMessage` call throws \"Body has already been read\"\n // because something upstream (signature check, dedupe, etc.) drains it.\n // Mirrors the Slack adapter's pattern.\n try {\n if (!event.context.__rawBody) {\n const body = await readBody(event);\n event.context.__rawBody = body;\n }\n } catch {\n // If we can't pre-read, parseIncomingMessage will surface the error\n }\n // Telegram has no challenge; we never short-circuit.\n return { handled: false };\n },\n\n async verifyWebhook(event: H3Event): Promise<boolean> {\n const secret = await resolveSecret(\"TELEGRAM_WEBHOOK_SECRET\");\n if (!secret) {\n if (shouldRefuseWhenSecretMissing()) {\n if (!_telegramUnverifiedWarned) {\n _telegramUnverifiedWarned = true;\n console.error(\n \"[telegram] TELEGRAM_WEBHOOK_SECRET not set — refusing webhook in production. \" +\n \"Set TELEGRAM_WEBHOOK_SECRET, or set AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS=1 for local testing only.\",\n );\n }\n return false;\n }\n if (!_telegramUnverifiedWarned) {\n _telegramUnverifiedWarned = true;\n console.warn(\n \"[telegram] TELEGRAM_WEBHOOK_SECRET not set — accepting webhook without verification (dev mode)\",\n );\n }\n // Dev mode: still require the bot token to be configured at all.\n return !!(await resolveSecret(\"TELEGRAM_BOT_TOKEN\"));\n }\n\n const headerSecret = getHeader(event, \"x-telegram-bot-api-secret-token\");\n if (!headerSecret) return false;\n\n // Timing-safe comparison\n try {\n const crypto = await import(\"node:crypto\");\n return crypto.timingSafeEqual(\n Buffer.from(secret),\n Buffer.from(headerSecret),\n );\n } catch {\n return false;\n }\n },\n\n async parseIncomingMessage(\n event: H3Event,\n ): Promise<IncomingMessage | null> {\n // Use the pre-cached raw body if available (set by handleVerification).\n // Falls back to readBody for paths that bypass handleVerification.\n const body = (event.context.__rawBody as any) ?? (await readBody(event));\n if (!body) return null;\n\n // Handle regular messages\n const message = body.message || body.edited_message;\n if (!message) return null;\n\n // Only process text messages\n const text = message.text?.trim();\n if (!text) return null;\n\n // Ignore bot commands that we don't handle (e.g., /start is fine)\n // Remove /start command prefix if present\n const cleanText =\n text === \"/start\"\n ? \"Hello! I'm ready to chat.\"\n : text.replace(/^\\/\\w+\\s*/, \"\").trim() || text;\n\n const chat = message.chat;\n const from = message.from;\n\n return {\n platform: \"telegram\",\n externalThreadId: String(chat.id),\n text: cleanText,\n senderName:\n from?.first_name + (from?.last_name ? ` ${from.last_name}` : \"\"),\n senderId: String(from?.id),\n platformContext: {\n chatId: chat.id,\n chatType: chat.type,\n messageId: message.message_id,\n rawText: text,\n fromId: from?.id,\n fromUsername: from?.username,\n },\n timestamp: message.date * 1000,\n };\n },\n\n async sendResponse(\n message: OutgoingMessage,\n context: IncomingMessage,\n ): Promise<void> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n if (!token) {\n console.error(\"[telegram] TELEGRAM_BOT_TOKEN not configured\");\n return;\n }\n\n const chatId = context.platformContext.chatId;\n const chunks = splitMessage(message.text, TELEGRAM_MAX_LENGTH);\n\n for (const chunk of chunks) {\n try {\n const res = await fetch(\n `https://api.telegram.org/bot${token}/sendMessage`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chat_id: chatId,\n text: chunk,\n parse_mode: \"Markdown\",\n }),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n description?: string;\n };\n if (!data.ok) {\n // Retry without Markdown if parsing fails\n if (data.description?.includes(\"parse\")) {\n await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n chat_id: chatId,\n text: chunk,\n }),\n });\n } else {\n console.error(\"[telegram] sendMessage error:\", data.description);\n }\n }\n } catch (err) {\n console.error(\"[telegram] Failed to send message:\", err);\n }\n }\n },\n\n async sendMessageToTarget(\n message: OutgoingMessage,\n target: OutboundTarget,\n ): Promise<void> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n if (!token) {\n console.error(\"[telegram] TELEGRAM_BOT_TOKEN not configured\");\n return;\n }\n\n const chunks = splitMessage(message.text, TELEGRAM_MAX_LENGTH);\n for (const chunk of chunks) {\n const body: Record<string, unknown> = {\n chat_id: target.destination,\n text: chunk,\n };\n if (target.threadRef) {\n body.message_thread_id = target.threadRef;\n }\n\n try {\n const res = await fetch(\n `https://api.telegram.org/bot${token}/sendMessage`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n description?: string;\n };\n if (!data.ok) {\n throw new Error(data.description || \"sendMessage failed\");\n }\n } catch (err) {\n console.error(\"[telegram] Failed to send proactive message:\", err);\n throw err;\n }\n }\n },\n\n formatAgentResponse(text: string): OutgoingMessage {\n // Telegram's legacy Markdown uses single asterisks for bold, not double.\n // `[text](url)` is already supported natively.\n // 's' flag (dotAll) so `.` matches newlines — bold text can span lines.\n const normalized = text.replace(/\\*\\*(.+?)\\*\\*/gs, \"*$1*\");\n return { text: normalized, platformContext: { parse_mode: \"Markdown\" } };\n },\n\n async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n const hasToken = !!token;\n\n let botName: string | undefined;\n if (hasToken) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { username?: string };\n };\n if (data.ok) {\n botName = data.result?.username;\n }\n } catch {}\n }\n\n return {\n platform: \"telegram\",\n label: \"Telegram\",\n enabled: false, // overridden by plugin\n configured: hasToken,\n details: {\n hasToken,\n botUsername: botName,\n },\n error: !hasToken ? \"Save TELEGRAM_BOT_TOKEN in settings\" : undefined,\n };\n },\n };\n}\n\n/** Split a message into chunks that fit within the platform's limit */\nfunction splitMessage(text: string, maxLength: number): string[] {\n if (text.length <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (remaining.length <= maxLength) {\n chunks.push(remaining);\n break;\n }\n let splitIdx = remaining.lastIndexOf(\"\\n\", maxLength);\n if (splitIdx <= 0) splitIdx = remaining.lastIndexOf(\" \", maxLength);\n if (splitIdx <= 0) splitIdx = maxLength;\n chunks.push(remaining.slice(0, splitIdx));\n remaining = remaining.slice(splitIdx).trimStart();\n }\n return chunks;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/integrations/adapters/telegram.ts"],"names":[],"mappings":"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","sourcesContent":["import type { H3Event } from \"h3\";\nimport { getHeader } from \"h3\";\n\nimport type { EnvKeyConfig } from \"../../server/create-server.js\";\nimport { resolveSecret } from \"../../server/credential-provider.js\";\nimport { readBody } from \"../../server/h3-helpers.js\";\nimport type {\n PlatformAdapter,\n IncomingMessage,\n OutgoingMessage,\n IntegrationStatus,\n OutboundTarget,\n} from \"../types.js\";\n\n/** Telegram's max message length */\nconst TELEGRAM_MAX_LENGTH = 4096;\n\n/**\n * One-shot warning flag — log once per process when accepting unverified\n * webhooks (M6 in the webhook security audit).\n */\nlet _telegramUnverifiedWarned = false;\n\n/**\n * Returns true when the deployment is running in production mode and the\n * operator has NOT explicitly opted into accepting unverified webhooks for\n * local testing. In production we MUST refuse webhooks whose secret is\n * unset — otherwise an attacker can drive the agent loop with arbitrary\n * messages (C2 in the webhook security audit).\n */\nfunction shouldRefuseWhenSecretMissing(): boolean {\n if (process.env.AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS === \"1\") return false;\n return process.env.NODE_ENV === \"production\";\n}\n\n/**\n * Create a Telegram platform adapter.\n *\n * Required env vars:\n * - TELEGRAM_BOT_TOKEN — Bot token from @BotFather\n * - TELEGRAM_WEBHOOK_SECRET — Secret token for webhook verification\n */\nexport function telegramAdapter(): PlatformAdapter {\n return {\n platform: \"telegram\",\n label: \"Telegram\",\n capabilities: {\n replyText: true,\n proactiveMessages: true,\n nativeThreads: true,\n contextualReplies: true,\n deferredWebhookResponse: false,\n interactionOnly: false,\n },\n\n getRequiredEnvKeys(): EnvKeyConfig[] {\n return [\n {\n key: \"TELEGRAM_BOT_TOKEN\",\n label: \"Telegram Bot Token\",\n required: true,\n helpText:\n \"From @BotFather after `/newbot` — the long token Telegram gives you (looks like `123456:ABC-DEF...`).\",\n },\n {\n key: \"TELEGRAM_WEBHOOK_SECRET\",\n label: \"Telegram Webhook Secret\",\n required: true,\n helpText:\n \"A random secret token. Telegram echoes it on every webhook so the adapter can verify the request came from Telegram.\",\n },\n ];\n },\n\n async handleVerification(\n event: H3Event,\n ): Promise<{ handled: boolean; response?: unknown }> {\n // Pre-read the raw body once and cache on the event context. h3 v2's\n // request body stream can only be consumed once; without this, the\n // later `parseIncomingMessage` call throws \"Body has already been read\"\n // because something upstream (signature check, dedupe, etc.) drains it.\n // Mirrors the Slack adapter's pattern.\n try {\n if (!event.context.__rawBody) {\n const body = await readBody(event);\n event.context.__rawBody = body;\n }\n } catch {\n // If we can't pre-read, parseIncomingMessage will surface the error\n }\n // Telegram has no challenge; we never short-circuit.\n return { handled: false };\n },\n\n async verifyWebhook(event: H3Event): Promise<boolean> {\n const secret = await resolveSecret(\"TELEGRAM_WEBHOOK_SECRET\");\n if (!secret) {\n if (shouldRefuseWhenSecretMissing()) {\n if (!_telegramUnverifiedWarned) {\n _telegramUnverifiedWarned = true;\n console.error(\n \"[telegram] TELEGRAM_WEBHOOK_SECRET not set — refusing webhook in production. \" +\n \"Set TELEGRAM_WEBHOOK_SECRET, or set AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS=1 for local testing only.\",\n );\n }\n return false;\n }\n if (!_telegramUnverifiedWarned) {\n _telegramUnverifiedWarned = true;\n console.warn(\n \"[telegram] TELEGRAM_WEBHOOK_SECRET not set — accepting webhook without verification (dev mode)\",\n );\n }\n // Dev mode: still require the bot token to be configured at all.\n return !!(await resolveSecret(\"TELEGRAM_BOT_TOKEN\"));\n }\n\n const headerSecret = getHeader(event, \"x-telegram-bot-api-secret-token\");\n if (!headerSecret) return false;\n\n // Timing-safe comparison\n try {\n const crypto = await import(\"node:crypto\");\n return crypto.timingSafeEqual(\n Buffer.from(secret),\n Buffer.from(headerSecret),\n );\n } catch {\n return false;\n }\n },\n\n async parseIncomingMessage(\n event: H3Event,\n ): Promise<IncomingMessage | null> {\n // Use the pre-cached raw body if available (set by handleVerification).\n // Falls back to readBody for paths that bypass handleVerification.\n const body = (event.context.__rawBody as any) ?? (await readBody(event));\n if (!body) return null;\n\n // Handle regular messages\n const message = body.message || body.edited_message;\n if (!message) return null;\n\n // Only process text messages\n const text = message.text?.trim();\n if (!text) return null;\n\n // Ignore bot commands that we don't handle (e.g., /start is fine)\n // Remove /start command prefix if present\n const cleanText =\n text === \"/start\"\n ? \"Hello! I'm ready to chat.\"\n : text.replace(/^\\/\\w+\\s*/, \"\").trim() || text;\n\n const chat = message.chat;\n const from = message.from;\n const messageThreadId = message.message_thread_id;\n const externalThreadId =\n messageThreadId === undefined\n ? `chat:${String(chat.id)}`\n : `chat:${String(chat.id)}:thread:${String(messageThreadId)}`;\n\n return {\n platform: \"telegram\",\n externalThreadId,\n text: cleanText,\n senderName:\n from?.first_name + (from?.last_name ? ` ${from.last_name}` : \"\"),\n senderId: String(from?.id),\n threadRef:\n messageThreadId === undefined ? undefined : String(messageThreadId),\n replyRef: String(message.message_id),\n platformContext: {\n chatId: chat.id,\n chatType: chat.type,\n messageId: message.message_id,\n messageThreadId,\n rawText: text,\n fromId: from?.id,\n fromUsername: from?.username,\n },\n timestamp: message.date * 1000,\n };\n },\n\n getLegacyExternalThreadIds(incoming: IncomingMessage): string[] {\n const chatId = incoming.platformContext.chatId;\n return typeof chatId === \"string\" || typeof chatId === \"number\"\n ? [String(chatId)]\n : [];\n },\n\n async sendResponse(\n message: OutgoingMessage,\n context: IncomingMessage,\n ): Promise<void> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n if (!token) {\n console.error(\"[telegram] TELEGRAM_BOT_TOKEN not configured\");\n return;\n }\n\n const chatId = context.platformContext.chatId;\n const chunks = splitMessage(message.text, TELEGRAM_MAX_LENGTH);\n\n for (const [index, chunk] of chunks.entries()) {\n try {\n const body: Record<string, unknown> = {\n chat_id: chatId,\n text: chunk,\n parse_mode: \"Markdown\",\n };\n if (context.threadRef) {\n body.message_thread_id = Number(context.threadRef);\n }\n if (index === 0 && context.replyRef) {\n body.reply_parameters = {\n message_id: Number(context.replyRef),\n allow_sending_without_reply: true,\n };\n }\n const res = await fetch(\n `https://api.telegram.org/bot${token}/sendMessage`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n description?: string;\n };\n if (!data.ok) {\n // Retry without Markdown if parsing fails\n if (data.description?.includes(\"parse\")) {\n await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...body,\n parse_mode: undefined,\n }),\n });\n } else {\n console.error(\"[telegram] sendMessage error:\", data.description);\n }\n }\n } catch (err) {\n console.error(\"[telegram] Failed to send message:\", err);\n }\n }\n },\n\n async sendMessageToTarget(\n message: OutgoingMessage,\n target: OutboundTarget,\n ): Promise<void> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n if (!token) {\n console.error(\"[telegram] TELEGRAM_BOT_TOKEN not configured\");\n return;\n }\n\n const chunks = splitMessage(message.text, TELEGRAM_MAX_LENGTH);\n for (const chunk of chunks) {\n const body: Record<string, unknown> = {\n chat_id: target.destination,\n text: chunk,\n };\n if (target.threadRef) {\n body.message_thread_id = target.threadRef;\n }\n\n try {\n const res = await fetch(\n `https://api.telegram.org/bot${token}/sendMessage`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n description?: string;\n };\n if (!data.ok) {\n throw new Error(data.description || \"sendMessage failed\");\n }\n } catch (err) {\n console.error(\"[telegram] Failed to send proactive message:\", err);\n throw err;\n }\n }\n },\n\n formatAgentResponse(text: string): OutgoingMessage {\n // Telegram's legacy Markdown uses single asterisks for bold, not double.\n // `[text](url)` is already supported natively.\n // 's' flag (dotAll) so `.` matches newlines — bold text can span lines.\n const normalized = text.replace(/\\*\\*(.+?)\\*\\*/gs, \"*$1*\");\n return { text: normalized, platformContext: { parse_mode: \"Markdown\" } };\n },\n\n async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {\n const token = await resolveSecret(\"TELEGRAM_BOT_TOKEN\");\n const hasToken = !!token;\n const hasWebhookSecret = !!(await resolveSecret(\n \"TELEGRAM_WEBHOOK_SECRET\",\n ));\n const configured = hasToken && hasWebhookSecret;\n\n let botName: string | undefined;\n if (hasToken) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { username?: string };\n };\n if (data.ok) {\n botName = data.result?.username;\n }\n } catch {}\n }\n\n return {\n platform: \"telegram\",\n label: \"Telegram\",\n enabled: false, // overridden by plugin\n configured,\n details: {\n hasToken,\n hasWebhookSecret,\n botUsername: botName,\n },\n error: !configured\n ? \"Save TELEGRAM_BOT_TOKEN and TELEGRAM_WEBHOOK_SECRET in settings\"\n : undefined,\n };\n },\n };\n}\n\n/** Split a message into chunks that fit within the platform's limit */\nfunction splitMessage(text: string, maxLength: number): string[] {\n if (text.length <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (remaining.length <= maxLength) {\n chunks.push(remaining);\n break;\n }\n let splitIdx = remaining.lastIndexOf(\"\\n\", maxLength);\n if (splitIdx <= 0) splitIdx = remaining.lastIndexOf(\" \", maxLength);\n if (splitIdx <= 0) splitIdx = maxLength;\n chunks.push(remaining.slice(0, splitIdx));\n remaining = remaining.slice(splitIdx).trimStart();\n }\n return chunks;\n}\n"]}
|
|
@@ -6,8 +6,6 @@ import type { PlatformAdapter } from "../types.js";
|
|
|
6
6
|
* - WHATSAPP_ACCESS_TOKEN — Permanent access token from Meta
|
|
7
7
|
* - WHATSAPP_VERIFY_TOKEN — Custom token for webhook verification
|
|
8
8
|
* - WHATSAPP_PHONE_NUMBER_ID — Phone number ID from Meta dashboard
|
|
9
|
-
*
|
|
10
|
-
* Optional env vars:
|
|
11
9
|
* - WHATSAPP_APP_SECRET — App secret for signature verification
|
|
12
10
|
*/
|
|
13
11
|
export declare function whatsappAdapter(): PlatformAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/whatsapp.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../../src/integrations/adapters/whatsapp.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,aAAa,CAAC;AAuBrB;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAqRjD"}
|