@agent-native/core 0.132.1 → 0.133.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 +198 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/correlation.ts +11 -1
- package/corpus/core/src/a2a/types.ts +11 -3
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +33 -46
- package/corpus/core/src/agent/engine/builder-engine.ts +22 -10
- package/corpus/core/src/agent/engine/error-detail.ts +184 -3
- package/corpus/core/src/agent/engine/failure-taxonomy.ts +123 -0
- package/corpus/core/src/agent/engine/index.ts +8 -0
- package/corpus/core/src/agent/engine/registry.ts +92 -8
- package/corpus/core/src/agent/engine/translate-ai-sdk.ts +17 -2
- package/corpus/core/src/agent/production-agent.ts +13 -33
- package/corpus/core/src/agent/run-loop-with-resume.ts +1 -1
- package/corpus/core/src/agent/run-manager.ts +43 -14
- package/corpus/core/src/agent/run-store.ts +30 -3
- package/corpus/core/src/agent/thread-data-builder.ts +36 -4
- package/corpus/core/src/chat-threads/store.ts +42 -0
- package/corpus/core/src/cli/templates-meta.ts +13 -0
- package/corpus/core/src/cli/workspace-dev.ts +1 -0
- package/corpus/core/src/client/error-format.ts +12 -0
- package/corpus/core/src/client/use-chat-threads.ts +76 -16
- package/corpus/core/src/credentials/index.ts +51 -12
- package/corpus/core/src/extensions/url-safety.ts +46 -12
- package/corpus/core/src/integrations/adapters/slack.ts +32 -10
- package/corpus/core/src/integrations/google-docs-poller.ts +12 -1
- package/corpus/core/src/integrations/installations-store.ts +30 -0
- package/corpus/core/src/integrations/plugin.ts +5 -5
- package/corpus/core/src/integrations/types.ts +7 -0
- package/corpus/core/src/integrations/webhook-handler.ts +24 -1
- package/corpus/core/src/jobs/background-automation-runner.ts +38 -1
- package/corpus/core/src/provider-api/index.ts +8 -2
- package/corpus/core/src/scripts/call-agent.ts +6 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +46 -10
- package/corpus/core/src/server/agent-discovery.ts +2 -0
- package/corpus/core/src/server/builder-design-systems.ts +21 -0
- package/corpus/core/src/server/credential-provider.ts +51 -12
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/server/onboarding-html.ts +37 -2
- package/corpus/core/src/shared/reasoning-effort.ts +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -2
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +39 -19
- package/corpus/templates/assets/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/brain/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +54 -25
- package/corpus/templates/calendar/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +37 -21
- package/corpus/templates/clips/changelog/2026-07-30-meeting-microphone-transcription-works-reliably-from-the-fir.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +1 -1
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +13 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +25 -132
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +34 -17
- package/corpus/templates/content/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +5 -0
- package/corpus/templates/design/actions/create-design-system.ts +1 -0
- package/corpus/templates/design/actions/set-default-design-system.ts +34 -26
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +5 -3
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +23 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +3 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +21 -4
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -7
- package/corpus/templates/design/app/i18n-data.ts +39 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +229 -12
- package/corpus/templates/design/app/pages/DesignSystems.tsx +10 -4
- package/corpus/templates/design/changelog/2026-07-30-fixed-the-keyboard-shortcuts-panel-not-opening-with-ctrl-shi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/design/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +19 -4
- package/corpus/templates/dispatch/AGENTS.md +4 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +562 -0
- package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +198 -0
- package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +182 -0
- package/corpus/templates/factory/.agents/skills/capture-learnings/SKILL.md +89 -0
- package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +221 -0
- package/corpus/templates/factory/.agents/skills/customizing-agent-native/SKILL.md +220 -0
- package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +263 -0
- package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +52 -0
- package/corpus/templates/factory/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +174 -0
- package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +232 -0
- package/corpus/templates/factory/.agents/skills/security/SKILL.md +324 -0
- package/corpus/templates/factory/.agents/skills/self-modifying-code/SKILL.md +119 -0
- package/corpus/templates/factory/.agents/skills/shadcn-ui/SKILL.md +123 -0
- package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +232 -0
- package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +178 -0
- package/corpus/templates/factory/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
- package/corpus/templates/factory/.env.example +24 -0
- package/corpus/templates/factory/.ignore +0 -0
- package/corpus/templates/factory/.oxfmtrc.json +8 -0
- package/corpus/templates/factory/AGENTS.md +90 -0
- package/corpus/templates/factory/CHANGELOG.md +10 -0
- package/corpus/templates/factory/DEVELOPING.md +185 -0
- package/corpus/templates/factory/README.md +64 -0
- package/corpus/templates/factory/_gitignore +42 -0
- package/corpus/templates/factory/actions/add-factory-comment.ts +55 -0
- package/corpus/templates/factory/actions/approve-factory-item.ts +214 -0
- package/corpus/templates/factory/actions/babysit-pull-request.ts +126 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +172 -0
- package/corpus/templates/factory/actions/get-factory-graph.ts +62 -0
- package/corpus/templates/factory/actions/get-triage-config.ts +42 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +74 -0
- package/corpus/templates/factory/actions/hello.ts +13 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +100 -0
- package/corpus/templates/factory/actions/list-factories.ts +40 -0
- package/corpus/templates/factory/actions/list-factory-comments.ts +40 -0
- package/corpus/templates/factory/actions/list-triage-items.ts +85 -0
- package/corpus/templates/factory/actions/list-triage-rules.ts +44 -0
- package/corpus/templates/factory/actions/navigate.ts +41 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +118 -0
- package/corpus/templates/factory/actions/reconcile-triage-run.ts +179 -0
- package/corpus/templates/factory/actions/record-triage-feedback.ts +58 -0
- package/corpus/templates/factory/actions/run.ts +2 -0
- package/corpus/templates/factory/actions/save-factory-graph.ts +129 -0
- package/corpus/templates/factory/actions/save-triage-config.ts +67 -0
- package/corpus/templates/factory/actions/save-triage-rule.ts +89 -0
- package/corpus/templates/factory/actions/suggest-factory-rules.ts +70 -0
- package/corpus/templates/factory/actions/view-screen.ts +73 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +441 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +388 -0
- package/corpus/templates/factory/app/components/layout/Header.tsx +60 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +190 -0
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +538 -0
- package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +28 -0
- package/corpus/templates/factory/app/components/ui/button.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/card.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/input.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/label.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/factory/app/components/ui/toolkit-provider.tsx +17 -0
- package/corpus/templates/factory/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/factory/app/design-system.ts +3 -0
- package/corpus/templates/factory/app/entry.client.tsx +22 -0
- package/corpus/templates/factory/app/entry.server.tsx +10 -0
- package/corpus/templates/factory/app/global.css +93 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +113 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +211 -0
- package/corpus/templates/factory/app/i18n/index.ts +34 -0
- package/corpus/templates/factory/app/i18n-data.ts +556 -0
- package/corpus/templates/factory/app/lib/agent-page.tsx +49 -0
- package/corpus/templates/factory/app/lib/app-config.ts +11 -0
- package/corpus/templates/factory/app/lib/tab-id.ts +1 -0
- package/corpus/templates/factory/app/lib/utils.ts +1 -0
- package/corpus/templates/factory/app/root.tsx +175 -0
- package/corpus/templates/factory/app/routes/_index.tsx +94 -0
- package/corpus/templates/factory/app/routes/agent.tsx +24 -0
- package/corpus/templates/factory/app/routes/chat.$threadId.tsx +1 -0
- package/corpus/templates/factory/app/routes/database.tsx +17 -0
- package/corpus/templates/factory/app/routes/extensions.$id.$slug.tsx +2 -0
- package/corpus/templates/factory/app/routes/extensions.$id.tsx +11 -0
- package/corpus/templates/factory/app/routes/extensions._index.tsx +11 -0
- package/corpus/templates/factory/app/routes/extensions.tsx +5 -0
- package/corpus/templates/factory/app/routes/factory.tsx +1003 -0
- package/corpus/templates/factory/app/routes/observability.tsx +19 -0
- package/corpus/templates/factory/app/routes/settings.tsx +89 -0
- package/corpus/templates/factory/app/routes/team.tsx +11 -0
- package/corpus/templates/factory/app/routes.ts +4 -0
- package/corpus/templates/factory/app/vite-env.d.ts +6 -0
- package/corpus/templates/factory/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
- package/corpus/templates/factory/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/factory/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-29-sidebar-footers-now-keep-feedback-search-and-collapse-togeth.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-31-added-an-inspectable-observe-only-factory-queue-for-slack-.md +6 -0
- package/corpus/templates/factory/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/factory/components.json +20 -0
- package/corpus/templates/factory/data/sync-config.json +1 -0
- package/corpus/templates/factory/learnings.defaults.md +5 -0
- package/corpus/templates/factory/netlify.toml +10 -0
- package/corpus/templates/factory/package.json +105 -0
- package/corpus/templates/factory/public/agent-native-icon-dark.svg +10 -0
- package/corpus/templates/factory/public/agent-native-icon-light.svg +10 -0
- package/corpus/templates/factory/public/agent-native-logo-dark.svg +21 -0
- package/corpus/templates/factory/public/agent-native-logo-light.svg +21 -0
- package/corpus/templates/factory/public/favicon.svg +1 -0
- package/corpus/templates/factory/public/icon-180.svg +1 -0
- package/corpus/templates/factory/public/icon-192.svg +1 -0
- package/corpus/templates/factory/public/icon-512.svg +1 -0
- package/corpus/templates/factory/public/manifest.json +21 -0
- package/corpus/templates/factory/react-router.config.ts +7 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +129 -0
- package/corpus/templates/factory/server/connectors/slack.ts +129 -0
- package/corpus/templates/factory/server/db/index.ts +6 -0
- package/corpus/templates/factory/server/db/schema.ts +193 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +212 -0
- package/corpus/templates/factory/server/factory-graph/store.ts +121 -0
- package/corpus/templates/factory/server/lib/require-workspace-member.ts +55 -0
- package/corpus/templates/factory/server/middleware/auth.ts +15 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +58 -0
- package/corpus/templates/factory/server/plugins/auth.ts +14 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +247 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +116 -0
- package/corpus/templates/factory/server/plugins/integrations.ts +46 -0
- package/corpus/templates/factory/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +116 -0
- package/corpus/templates/factory/server/triage/ai-services-git.ts +197 -0
- package/corpus/templates/factory/server/triage/builder-executor.ts +118 -0
- package/corpus/templates/factory/server/triage/contracts.ts +164 -0
- package/corpus/templates/factory/server/triage/github-ingestion.ts +35 -0
- package/corpus/templates/factory/server/triage/guards.ts +121 -0
- package/corpus/templates/factory/server/triage/ids.ts +27 -0
- package/corpus/templates/factory/server/triage/pr-babysit.ts +100 -0
- package/corpus/templates/factory/server/triage/pr-monitor.ts +220 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +55 -0
- package/corpus/templates/factory/server/triage/slack-poller.ts +152 -0
- package/corpus/templates/factory/ssr-entry.ts +15 -0
- package/corpus/templates/factory/tsconfig.json +21 -0
- package/corpus/templates/factory/vite.config.ts +19 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +55 -5
- package/corpus/templates/forms/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -2
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +21 -6
- package/corpus/templates/plan/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +12 -0
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +11 -0
- package/corpus/templates/slides/AGENTS.md +5 -6
- package/corpus/templates/slides/actions/_await-fit-check.ts +20 -10
- package/corpus/templates/slides/actions/add-slide.ts +17 -4
- package/corpus/templates/slides/actions/create-design-system.ts +16 -4
- package/corpus/templates/slides/actions/delete-design-system.ts +18 -2
- package/corpus/templates/slides/actions/get-layout-overflows.ts +88 -0
- package/corpus/templates/slides/actions/import-file.ts +1 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +8 -0
- package/corpus/templates/slides/actions/patch-deck.ts +48 -16
- package/corpus/templates/slides/actions/set-default-design-system.ts +49 -19
- package/corpus/templates/slides/actions/update-slide.ts +13 -3
- package/corpus/templates/slides/actions/view-screen.ts +87 -10
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +155 -28
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +21 -17
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +849 -341
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +102 -2
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +13 -16
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +60 -12
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +11 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +66 -19
- package/corpus/templates/slides/app/i18n/en-US.ts +23 -0
- package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +8 -15
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -3
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +4 -3
- package/corpus/templates/slides/app/pages/Index.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-31-design-system-details-now-show-their-source-and-indexing-sta.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-design-system-indexing-keeps-your-chosen-name-when-you-uploa.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-design-system-setup-keeps-focus-rings-visible-and-uses-a-sim.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-skip-prompt-is-now-available-in-the-new-deck-prompt-header.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-slides-now-detect-real-text-and-box-overflow-across-the-deck.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-31-the-agent-native-logo-stays-visible-when-the-sidebar-is-coll.md +6 -0
- package/corpus/templates/slides/server/handlers/design-systems.ts +1 -0
- package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +1 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +23 -4
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/slides/server/plugins/creative-context.ts +16 -3
- package/corpus/templates/slides/server/workspace-defaults.ts +5 -1
- package/corpus/templates/slides/shared/slide-fit.ts +26 -0
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +30 -3
- package/corpus/templates/tasks/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/dist/a2a/correlation.d.ts +4 -1
- package/dist/a2a/correlation.d.ts.map +1 -1
- package/dist/a2a/correlation.js +8 -1
- package/dist/a2a/correlation.js.map +1 -1
- package/dist/a2a/types.d.ts +11 -3
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +27 -41
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +18 -8
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/error-detail.d.ts +61 -0
- package/dist/agent/engine/error-detail.d.ts.map +1 -1
- package/dist/agent/engine/error-detail.js +145 -3
- package/dist/agent/engine/error-detail.js.map +1 -1
- package/dist/agent/engine/failure-taxonomy.d.ts +24 -0
- package/dist/agent/engine/failure-taxonomy.d.ts.map +1 -0
- package/dist/agent/engine/failure-taxonomy.js +88 -0
- package/dist/agent/engine/failure-taxonomy.js.map +1 -0
- package/dist/agent/engine/index.d.ts +2 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +2 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +16 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +71 -6
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.js +14 -2
- package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +13 -24
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.js +1 -1
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +39 -10
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +10 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +20 -3
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +28 -4
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/chat-threads/store.d.ts +13 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +35 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +13 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspace-dev.d.ts.map +1 -1
- package/dist/cli/workspace-dev.js +1 -0
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +10 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +66 -16
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/credentials/index.d.ts +9 -2
- package/dist/credentials/index.d.ts.map +1 -1
- package/dist/credentials/index.js +50 -8
- package/dist/credentials/index.js.map +1 -1
- package/dist/extensions/url-safety.d.ts.map +1 -1
- package/dist/extensions/url-safety.js +38 -12
- package/dist/extensions/url-safety.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +25 -8
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +13 -1
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/integrations/installations-store.d.ts +10 -0
- package/dist/integrations/installations-store.d.ts.map +1 -1
- package/dist/integrations/installations-store.js +24 -0
- package/dist/integrations/installations-store.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +6 -5
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +7 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +16 -1
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/background-automation-runner.d.ts.map +1 -1
- package/dist/jobs/background-automation-runner.js +35 -2
- package/dist/jobs/background-automation-runner.js.map +1 -1
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/provider-api/index.js +7 -3
- package/dist/provider-api/index.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +6 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -9
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +2 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +11 -1
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +49 -12
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +37 -2
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/reasoning-effort.d.ts +1 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +1 -1
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/dist/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- package/package.json +1 -1
- package/src/a2a/correlation.ts +11 -1
- package/src/a2a/types.ts +11 -3
- package/src/agent/engine/ai-sdk-engine.ts +33 -46
- package/src/agent/engine/builder-engine.ts +22 -10
- package/src/agent/engine/error-detail.ts +184 -3
- package/src/agent/engine/failure-taxonomy.ts +123 -0
- package/src/agent/engine/index.ts +8 -0
- package/src/agent/engine/registry.ts +92 -8
- package/src/agent/engine/translate-ai-sdk.ts +17 -2
- package/src/agent/production-agent.ts +13 -33
- package/src/agent/run-loop-with-resume.ts +1 -1
- package/src/agent/run-manager.ts +43 -14
- package/src/agent/run-store.ts +30 -3
- package/src/agent/thread-data-builder.ts +36 -4
- package/src/chat-threads/store.ts +42 -0
- package/src/cli/templates-meta.ts +13 -0
- package/src/cli/workspace-dev.ts +1 -0
- package/src/client/error-format.ts +12 -0
- package/src/client/use-chat-threads.ts +76 -16
- package/src/credentials/index.ts +51 -12
- package/src/extensions/url-safety.ts +46 -12
- package/src/integrations/adapters/slack.ts +32 -10
- package/src/integrations/google-docs-poller.ts +12 -1
- package/src/integrations/installations-store.ts +30 -0
- package/src/integrations/plugin.ts +5 -5
- package/src/integrations/types.ts +7 -0
- package/src/integrations/webhook-handler.ts +24 -1
- package/src/jobs/background-automation-runner.ts +38 -1
- package/src/provider-api/index.ts +8 -2
- package/src/scripts/call-agent.ts +6 -0
- package/src/server/agent-chat-plugin.ts +46 -10
- package/src/server/agent-discovery.ts +2 -0
- package/src/server/builder-design-systems.ts +21 -0
- package/src/server/credential-provider.ts +51 -12
- package/src/server/index.ts +1 -0
- package/src/server/onboarding-html.ts +37 -2
- package/src/shared/reasoning-effort.ts +1 -1
- package/src/templates/chat/app/components/layout/Sidebar.tsx +30 -3
- package/src/templates/chat/changelog/2026-07-31-clicking-the-agent-native-logo-now-toggles-the-app-sidebar.md +6 -0
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +11 -0
- package/corpus/templates/clips/desktop/src/lib/media-device-selection.ts +0 -157
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-docs-poller.d.ts","sourceRoot":"","sources":["../../src/integrations/google-docs-poller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"google-docs-poller.d.ts","sourceRoot":"","sources":["../../src/integrations/google-docs-poller.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAuCtC,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqExE;AAiMD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAa5D;AA+LD;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAoDD;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAW1D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isInBackgroundFunctionRuntime } from "../agent/durable-background.js";
|
|
1
2
|
import { createAnthropicEngine } from "../agent/engine/index.js";
|
|
2
3
|
import { actionsToEngineTools, filterInitialEngineTools, } from "../agent/production-agent.js";
|
|
3
4
|
import { runAgentLoopDirectWithSoftTimeout } from "../agent/run-loop-with-resume.js";
|
|
@@ -346,7 +347,18 @@ async function processComment(fileId, commentId, text, senderName, options, exis
|
|
|
346
347
|
actions: runnableActions,
|
|
347
348
|
send,
|
|
348
349
|
signal,
|
|
349
|
-
}, undefined,
|
|
350
|
+
}, undefined,
|
|
351
|
+
// Same omission the scheduled-job runner had: without this, a
|
|
352
|
+
// poller-driven reply inherits the interactive clamp (40s soft
|
|
353
|
+
// timeout, a no-progress backstop at 0.75x that, 6 continuations)
|
|
354
|
+
// even though no client is waiting on a response. Uses the runtime
|
|
355
|
+
// check rather than a hardcoded `true` — matching webhook-handler.ts
|
|
356
|
+
// in this same subsystem — because unlike the job runner there is no
|
|
357
|
+
// hard-abort cap here to bound a wider ceiling.
|
|
358
|
+
{
|
|
359
|
+
useHostedDefault: true,
|
|
360
|
+
backgroundFunction: isInBackgroundFunctionRuntime(),
|
|
361
|
+
}));
|
|
350
362
|
}, async (completedRun) => {
|
|
351
363
|
try {
|
|
352
364
|
let responseText = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-docs-poller.js","sourceRoot":"","sources":["../../src/integrations/google-docs-poller.ts"],"names":[],"mappings":"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","sourcesContent":["import { createAnthropicEngine } from \"../agent/engine/index.js\";\nimport type { EngineMessage } from \"../agent/engine/types.js\";\nimport {\n actionsToEngineTools,\n filterInitialEngineTools,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../agent/run-loop-with-resume.js\";\nimport { startRun, type ActiveRun } from \"../agent/run-manager.js\";\nimport {\n buildAssistantMessage,\n extractThreadMeta,\n} from \"../agent/thread-data-builder.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport {\n createThread,\n getThread,\n updateThreadData,\n} from \"../chat-threads/store.js\";\nimport { resolveOrgIdForEmail } from \"../org/context.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n getServiceAccountAccessToken,\n getServiceAccountEmail,\n getStartPageToken,\n googleDocsAdapter,\n listChanges,\n listDocComments,\n} from \"./adapters/google-docs.js\";\nimport {\n getIntegrationConfig,\n integrationConfigWriteEpoch,\n saveIntegrationConfig,\n} from \"./config-store.js\";\nimport { getThreadMapping, saveThreadMapping } from \"./thread-mapping-store.js\";\nimport type { IncomingMessage } from \"./types.js\";\n\nconst PLATFORM = \"google-docs\";\nconst DEFAULT_TRIGGER = \"@agent\";\n\n/** Track processed comment IDs to avoid reprocessing */\nconst processedComments = new Set<string>();\n/** Track last-checked time per document for comment filtering */\nconst lastCheckedTimes = new Map<string, string>();\n\nexport interface GoogleDocsPollerOptions {\n /** Polling interval in milliseconds (fallback mode). Default: 30000 (30s) */\n intervalMs?: number;\n /** Trigger keyword in comments. Default: \"@agent\" (case-insensitive) */\n triggerKeyword?: string;\n /** System prompt for the agent */\n systemPrompt: string;\n /** Action entries for the agent */\n actions: Record<string, ActionEntry>;\n /**\n * Tool names to expose on the FIRST engine request. See\n * `WebhookHandlerOptions.initialToolNames` (`webhook-handler.ts`) — same\n * semantics, shared `actions` source from `createIntegrationsPlugin`. Omit\n * to keep the full `actions` set visible up front (current behavior).\n */\n initialToolNames?: string[];\n /** Model to use */\n model: string;\n /** Anthropic API key */\n apiKey: string;\n /** Thread owner email */\n ownerEmail: string;\n /** Webhook URL for push mode (set by plugin from WEBHOOK_BASE_URL) */\n webhookUrl?: string;\n}\n\nlet pollerInterval: ReturnType<typeof setInterval> | null = null;\nlet activeOptions: GoogleDocsPollerOptions | null = null;\n\n// ─── Watch Channel Management ───────────────────────────────────────────────\n\n/** How long a watch channel lasts (Google max is ~24h, we use 23h to renew early) */\nconst WATCH_CHANNEL_TTL_MS = 23 * 60 * 60 * 1000;\nlet watchRenewalTimer: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Register a Google Drive changes.watch channel so Google pushes\n * notifications to our webhook instead of us polling.\n *\n * Returns true if the watch was registered successfully.\n */\nexport async function registerWatch(webhookUrl: string): Promise<boolean> {\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return false;\n\n // Get the current page token as the starting point\n let pageToken = await getPageToken();\n if (!pageToken) {\n pageToken = await getStartPageToken(accessToken);\n await setPageToken(pageToken);\n }\n\n const channelId = `gdocs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const expiration = Date.now() + WATCH_CHANNEL_TTL_MS;\n\n try {\n const res = await fetch(\n \"https://www.googleapis.com/drive/v3/changes/watch\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n id: channelId,\n type: \"web_hook\",\n address: webhookUrl,\n expiration: expiration,\n payload: true,\n }),\n },\n );\n\n if (!res.ok) {\n const err = await res.text();\n console.error(\"[google-docs] Failed to register watch:\", err);\n return false;\n }\n\n const data = (await res.json()) as {\n id: string;\n resourceId: string;\n expiration: string;\n };\n\n // Save channel info for renewal and stopping\n await saveIntegrationConfig(\n PLATFORM,\n {\n channelId: data.id,\n resourceId: data.resourceId,\n expiration: data.expiration,\n webhookUrl,\n },\n \"watch-channel\",\n );\n\n console.log(\n `[google-docs] Watch registered (channel: ${data.id}, expires: ${new Date(parseInt(data.expiration)).toISOString()})`,\n );\n\n // Schedule renewal before expiration\n scheduleWatchRenewal(webhookUrl);\n\n return true;\n } catch (err) {\n console.error(\"[google-docs] Watch registration error:\", err);\n return false;\n }\n}\n\n/**\n * Stop an existing watch channel.\n */\nasync function stopWatch(): Promise<void> {\n const config = await getIntegrationConfig(PLATFORM, \"watch-channel\");\n if (!config?.configData?.channelId) return;\n\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return;\n\n try {\n await fetch(\"https://www.googleapis.com/drive/v3/channels/stop\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n id: config.configData.channelId,\n resourceId: config.configData.resourceId,\n }),\n });\n } catch {\n // Best effort — channel may have expired already\n }\n\n await saveIntegrationConfig(PLATFORM, {}, \"watch-channel\");\n}\n\n/**\n * Schedule automatic watch renewal before the channel expires.\n */\nfunction scheduleWatchRenewal(webhookUrl: string): void {\n if (watchRenewalTimer) clearTimeout(watchRenewalTimer);\n\n // Renew 1 hour before expiration\n const renewIn = WATCH_CHANNEL_TTL_MS - 60 * 60 * 1000;\n\n watchRenewalTimer = setTimeout(async () => {\n console.log(\"[google-docs] Renewing watch channel...\");\n await stopWatch();\n await registerWatch(webhookUrl);\n }, renewIn);\n}\n\n// ─── Page Token Management ──────────────────────────────────────────────────\n\nasync function getPageToken(): Promise<string | null> {\n const config = await getIntegrationConfig(PLATFORM, \"page-token\");\n return (config?.configData?.pageToken as string) ?? null;\n}\n\nasync function setPageToken(token: string): Promise<void> {\n await saveIntegrationConfig(PLATFORM, { pageToken: token }, \"page-token\");\n}\n\n// ─── Comment Detection ──────────────────────────────────────────────────────\n\nfunction isAgentMention(commentText: string, triggerKeyword: string): boolean {\n return commentText.toLowerCase().includes(triggerKeyword.toLowerCase());\n}\n\nfunction commentKey(fileId: string, commentId: string): string {\n return `${fileId}:${commentId}`;\n}\n\n/**\n * Check a single document for new agent-directed comments.\n */\nasync function checkDocumentComments(\n fileId: string,\n accessToken: string,\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n const triggerKeyword = options.triggerKeyword ?? DEFAULT_TRIGGER;\n const serviceEmail = getServiceAccountEmail();\n\n const lastChecked = lastCheckedTimes.get(fileId);\n const comments = await listDocComments(fileId, accessToken, lastChecked);\n const now = new Date().toISOString();\n\n for (const comment of comments) {\n if (comment.resolved) continue;\n\n const key = commentKey(fileId, comment.id);\n\n // Skip comments authored by the service account\n if (\n serviceEmail &&\n comment.author.emailAddress?.toLowerCase() === serviceEmail.toLowerCase()\n ) {\n continue;\n }\n\n const existingMapping = await getThreadMapping(PLATFORM, key);\n\n if (existingMapping) {\n // Durable per-reply dedup: the in-memory `processedComments` Set does not\n // survive serverless cold starts (see pending-tasks-store H3 note), which\n // would let already-answered replies be reprocessed and double-posted.\n // Persist processed reply ids in the existing SQL thread mapping instead.\n const persistedReplyIds =\n existingMapping.platformContext.processedReplyIds;\n const processedReplyIds = new Set<string>(\n Array.isArray(persistedReplyIds) ? (persistedReplyIds as string[]) : [],\n );\n\n // Check for new follow-up replies from users\n const newUserReplies = (comment.replies ?? []).filter((r) => {\n if (\n serviceEmail &&\n r.author.emailAddress?.toLowerCase() === serviceEmail.toLowerCase()\n ) {\n return false;\n }\n const replyKey = `${key}:reply:${r.id}`;\n if (processedReplyIds.has(r.id) || processedComments.has(replyKey))\n return false;\n if (!isAgentMention(r.content, triggerKeyword)) return false;\n return true;\n });\n\n for (const reply of newUserReplies) {\n const replyKey = `${key}:reply:${reply.id}`;\n processedComments.add(replyKey);\n processedReplyIds.add(reply.id);\n // Persist immediately so a crash/cold-start between replies cannot\n // re-answer this reply on the next invocation.\n await saveThreadMapping(\n PLATFORM,\n key,\n existingMapping.internalThreadId,\n {\n ...existingMapping.platformContext,\n processedReplyIds: Array.from(processedReplyIds),\n },\n );\n\n const text = reply.content\n .replace(\n new RegExp(\n triggerKeyword.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n \"gi\",\n ),\n \"\",\n )\n .trim();\n\n await processComment(\n fileId,\n comment.id,\n text,\n reply.author.displayName,\n options,\n existingMapping.internalThreadId,\n );\n }\n continue;\n }\n\n // New comment — check if it mentions the agent\n if (!isAgentMention(comment.content, triggerKeyword)) continue;\n\n processedComments.add(key);\n\n let text = comment.content;\n if (comment.quotedFileContent?.value) {\n text = `[Highlighted text: \"${comment.quotedFileContent.value}\"]\\n\\n${text}`;\n }\n\n text = text\n .replace(\n new RegExp(triggerKeyword.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"gi\"),\n \"\",\n )\n .trim();\n\n await processComment(\n fileId,\n comment.id,\n text,\n comment.author.displayName,\n options,\n );\n }\n\n lastCheckedTimes.set(fileId, now);\n}\n\n// ─── Process Changes ────────────────────────────────────────────────────────\n\n/**\n * Process pending Drive changes — called by both push notifications and polling.\n * Fetches changes since the last page token, finds Google Docs that changed,\n * and checks their comments for agent mentions.\n */\nexport async function processChanges(\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return;\n\n let pageToken = await getPageToken();\n if (!pageToken) {\n pageToken = await getStartPageToken(accessToken);\n await setPageToken(pageToken);\n return; // First run — just save the cursor\n }\n\n const { changes, nextPageToken } = await listChanges(pageToken, accessToken);\n await setPageToken(nextPageToken);\n\n if (changes.length === 0) return;\n\n // Deduplicate and filter to Google Docs\n const docFileIds = new Set<string>();\n for (const change of changes) {\n if (change.removed) continue;\n if (\n change.file?.mimeType === \"application/vnd.google-apps.document\" ||\n !change.file?.mimeType\n ) {\n docFileIds.add(change.fileId);\n }\n }\n\n for (const fileId of docFileIds) {\n try {\n await checkDocumentComments(fileId, accessToken, options);\n } catch (err) {\n console.error(`[google-docs] Error checking comments on ${fileId}:`, err);\n }\n }\n}\n\n/**\n * Handle a push notification from Google Drive changes.watch.\n * Called from the integration webhook route.\n */\nexport async function handlePushNotification(): Promise<void> {\n if (!activeOptions) {\n console.warn(\n \"[google-docs] Push notification received but poller not configured\",\n );\n return;\n }\n\n try {\n await processChanges(activeOptions);\n } catch (err) {\n console.error(\"[google-docs] Error processing push notification:\", err);\n }\n}\n\n// ─── Agent Processing ───────────────────────────────────────────────────────\n\nasync function processComment(\n fileId: string,\n commentId: string,\n text: string,\n senderName: string,\n options: GoogleDocsPollerOptions,\n existingThreadId?: string,\n): Promise<void> {\n const adapter = googleDocsAdapter();\n const key = commentKey(fileId, commentId);\n\n const incoming: IncomingMessage = {\n platform: PLATFORM,\n externalThreadId: key,\n text,\n senderName,\n platformContext: { fileId, commentId },\n timestamp: Date.now(),\n };\n\n let threadId = existingThreadId;\n if (!threadId) {\n const thread = await createThread(options.ownerEmail, {\n title: `Google Doc: ${senderName}`,\n });\n await saveThreadMapping(PLATFORM, key, thread.id, { fileId, commentId });\n threadId = thread.id;\n }\n\n const thread = await getThread(threadId);\n const existingMessages: EngineMessage[] = [];\n if (thread?.threadData) {\n try {\n const data = JSON.parse(thread.threadData);\n if (Array.isArray(data.messages)) {\n for (const msg of data.messages) {\n const m = msg.message ?? msg;\n const textContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content\n .filter((c: any) => c.type === \"text\")\n .map((c: any) => c.text)\n .join(\"\\n\")\n : \"\";\n if (m.role === \"user\") {\n existingMessages.push({\n role: \"user\",\n content: [{ type: \"text\", text: textContent }],\n });\n } else if (m.role === \"assistant\") {\n existingMessages.push({\n role: \"assistant\",\n content: [{ type: \"text\", text: textContent }],\n });\n }\n }\n }\n } catch {}\n }\n\n const messages: EngineMessage[] = [\n ...existingMessages,\n { role: \"user\", content: [{ type: \"text\", text }] },\n ];\n\n const engine = createAnthropicEngine({ apiKey: options.apiKey });\n // Attach tool-search on a shallow copy so framework additions merged in by\n // `createIntegrationsPlugin` (integration memory, `call-agent`) can be\n // deferred behind it without mutating the plugin's long-lived registry.\n // `runAgentLoop`'s `expandActiveTools` re-expands from `availableTools`\n // after a tool-search call, so anything filtered out of the initial\n // `tools` list stays reachable.\n const runnableActions = attachToolSearch({ ...options.actions });\n const availableTools = actionsToEngineTools(runnableActions);\n const tools = filterInitialEngineTools(\n availableTools,\n options.initialToolNames,\n );\n const runId = `gdocs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const capturedThreadId = threadId;\n const orgId = (await resolveOrgIdForEmail(options.ownerEmail)) ?? undefined;\n\n startRun(\n runId,\n capturedThreadId,\n async (send, signal) => {\n await runWithRequestContext(\n { userEmail: options.ownerEmail, orgId, isIntegrationCaller: true },\n () =>\n // Wrapper, not raw `runAgentLoop`: a doc-comment reply has no client\n // driving continuation, so a transport-level cut has to be resumed\n // inside this invocation or the commenter never gets an answer.\n runAgentLoopDirectWithSoftTimeout(\n {\n engine,\n model: options.model,\n systemPrompt: options.systemPrompt,\n tools,\n availableTools,\n messages,\n actions: runnableActions,\n send,\n signal,\n },\n undefined,\n { useHostedDefault: true },\n ),\n );\n },\n async (completedRun: ActiveRun) => {\n try {\n let responseText = \"\";\n for (const runEvent of completedRun.events) {\n if (runEvent.event.type === \"text\") {\n responseText += runEvent.event.text;\n }\n }\n if (!responseText.trim()) responseText = \"(No response)\";\n\n const outgoing = adapter.formatAgentResponse(responseText);\n await adapter.sendResponse(outgoing, incoming);\n await persistThreadData(capturedThreadId, text, completedRun, thread);\n } catch (err) {\n console.error(\"[google-docs] Error sending response:\", err);\n }\n },\n // No userId here: `options.ownerEmail` is PII (email), which the\n // terminal event must not carry.\n { model: options.model, engineName: engine.name },\n );\n}\n\nasync function persistThreadData(\n threadId: string,\n userText: string,\n completedRun: ActiveRun,\n thread: any,\n): Promise<void> {\n try {\n let repo: any;\n try {\n repo = JSON.parse(thread?.threadData || \"{}\");\n } catch {\n repo = {};\n }\n if (!Array.isArray(repo.messages)) repo.messages = [];\n\n repo.messages.push({\n id: `msg-${Date.now()}-user`,\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n createdAt: new Date().toISOString(),\n });\n\n const assistantMsg = buildAssistantMessage(\n completedRun.events ?? [],\n completedRun.runId,\n );\n if (assistantMsg) repo.messages.push(assistantMsg);\n\n const meta = extractThreadMeta(repo);\n await updateThreadData(\n threadId,\n JSON.stringify(repo),\n meta.title || thread?.title || \"Google Doc Comment\",\n meta.preview || thread?.preview || \"\",\n repo.messages.length,\n );\n } catch {\n // Best-effort\n }\n}\n\n// ─── Poller (Hybrid: Push Primary, Poll Fallback) ───────────────────────────\n\n/**\n * Start the Google Docs integration.\n *\n * Hybrid approach:\n * 1. Attempts to register a Google Drive changes.watch webhook for\n * near-instant push notifications (~seconds latency)\n * 2. Falls back to polling if the watch registration fails\n * (e.g. domain not verified, local dev)\n * 3. Even in push mode, polls at a slow interval (5min) as a safety net\n * in case a push notification is missed\n */\nexport async function startGoogleDocsPoller(\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n if (pollerInterval) {\n console.warn(\"[google-docs] Already running\");\n return;\n }\n\n activeOptions = options;\n\n // Check if integration is enabled before trying to register watch\n const config = await getIntegrationConfig(PLATFORM);\n if (!config?.configData?.enabled) {\n // Still start the poll loop so it picks up when enabled later\n startPollLoop(options, options.intervalMs ?? 30_000);\n return;\n }\n\n // Try to register push notifications\n const webhookUrl = options.webhookUrl;\n let pushMode = false;\n\n if (webhookUrl) {\n pushMode = await registerWatch(webhookUrl);\n if (pushMode) {\n console.log(\"[google-docs] Push mode active — using Drive webhooks\");\n // In push mode, still poll slowly as a safety net (every 5 min)\n startPollLoop(options, 5 * 60 * 1000);\n }\n }\n\n if (!pushMode) {\n console.log(\n \"[google-docs] Polling mode — push registration failed or no webhook URL\",\n );\n startPollLoop(options, options.intervalMs ?? 30_000);\n }\n}\n\n/** Backoff for the config probe while google-docs is disabled. */\nconst DISABLED_CONFIG_RECHECK_MS = 5 * 60 * 1000;\n\nfunction startPollLoop(\n options: GoogleDocsPollerOptions,\n intervalMs: number,\n): void {\n let disabledUntil = 0;\n let disabledAtConfigWriteEpoch = -1;\n\n async function poll() {\n try {\n // The loop starts even when google-docs was never configured (so it picks\n // up a later enable), which used to mean one `integration_configs` read\n // every 30s per app forever. While disabled, re-read only every\n // DISABLED_CONFIG_RECHECK_MS — or immediately after any in-process config\n // write, so enabling the integration still takes effect on the next tick.\n const epoch = integrationConfigWriteEpoch();\n if (Date.now() < disabledUntil && epoch === disabledAtConfigWriteEpoch) {\n return;\n }\n const config = await getIntegrationConfig(PLATFORM);\n if (!config?.configData?.enabled) {\n disabledUntil = Date.now() + DISABLED_CONFIG_RECHECK_MS;\n disabledAtConfigWriteEpoch = epoch;\n return;\n }\n disabledUntil = 0;\n await processChanges(options);\n } catch (err) {\n // Unwrap ErrorEvent (Neon WS driver emits these on network failure) so logs show the real cause\n const detail =\n err instanceof Error\n ? err\n : ((err as any)?.error ?? (err as any)?.message ?? err);\n console.error(\"[google-docs] Poller error:\", detail);\n }\n }\n\n setTimeout(poll, 5000);\n pollerInterval = setInterval(poll, intervalMs);\n\n const email = getServiceAccountEmail();\n if (process.env.DEBUG) {\n console.log(\n `[google-docs] Poll loop started (interval: ${intervalMs / 1000}s, service account: ${email ?? \"not configured\"})`,\n );\n }\n}\n\n/**\n * Stop the Google Docs integration.\n */\nexport async function stopGoogleDocsPoller(): Promise<void> {\n if (pollerInterval) {\n clearInterval(pollerInterval);\n pollerInterval = null;\n }\n if (watchRenewalTimer) {\n clearTimeout(watchRenewalTimer);\n watchRenewalTimer = null;\n }\n await stopWatch();\n activeOptions = null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"google-docs-poller.js","sourceRoot":"","sources":["../../src/integrations/google-docs-poller.ts"],"names":[],"mappings":"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","sourcesContent":["import { isInBackgroundFunctionRuntime } from \"../agent/durable-background.js\";\nimport { createAnthropicEngine } from \"../agent/engine/index.js\";\nimport type { EngineMessage } from \"../agent/engine/types.js\";\nimport {\n actionsToEngineTools,\n filterInitialEngineTools,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../agent/run-loop-with-resume.js\";\nimport { startRun, type ActiveRun } from \"../agent/run-manager.js\";\nimport {\n buildAssistantMessage,\n extractThreadMeta,\n} from \"../agent/thread-data-builder.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport {\n createThread,\n getThread,\n updateThreadData,\n} from \"../chat-threads/store.js\";\nimport { resolveOrgIdForEmail } from \"../org/context.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n getServiceAccountAccessToken,\n getServiceAccountEmail,\n getStartPageToken,\n googleDocsAdapter,\n listChanges,\n listDocComments,\n} from \"./adapters/google-docs.js\";\nimport {\n getIntegrationConfig,\n integrationConfigWriteEpoch,\n saveIntegrationConfig,\n} from \"./config-store.js\";\nimport { getThreadMapping, saveThreadMapping } from \"./thread-mapping-store.js\";\nimport type { IncomingMessage } from \"./types.js\";\n\nconst PLATFORM = \"google-docs\";\nconst DEFAULT_TRIGGER = \"@agent\";\n\n/** Track processed comment IDs to avoid reprocessing */\nconst processedComments = new Set<string>();\n/** Track last-checked time per document for comment filtering */\nconst lastCheckedTimes = new Map<string, string>();\n\nexport interface GoogleDocsPollerOptions {\n /** Polling interval in milliseconds (fallback mode). Default: 30000 (30s) */\n intervalMs?: number;\n /** Trigger keyword in comments. Default: \"@agent\" (case-insensitive) */\n triggerKeyword?: string;\n /** System prompt for the agent */\n systemPrompt: string;\n /** Action entries for the agent */\n actions: Record<string, ActionEntry>;\n /**\n * Tool names to expose on the FIRST engine request. See\n * `WebhookHandlerOptions.initialToolNames` (`webhook-handler.ts`) — same\n * semantics, shared `actions` source from `createIntegrationsPlugin`. Omit\n * to keep the full `actions` set visible up front (current behavior).\n */\n initialToolNames?: string[];\n /** Model to use */\n model: string;\n /** Anthropic API key */\n apiKey: string;\n /** Thread owner email */\n ownerEmail: string;\n /** Webhook URL for push mode (set by plugin from WEBHOOK_BASE_URL) */\n webhookUrl?: string;\n}\n\nlet pollerInterval: ReturnType<typeof setInterval> | null = null;\nlet activeOptions: GoogleDocsPollerOptions | null = null;\n\n// ─── Watch Channel Management ───────────────────────────────────────────────\n\n/** How long a watch channel lasts (Google max is ~24h, we use 23h to renew early) */\nconst WATCH_CHANNEL_TTL_MS = 23 * 60 * 60 * 1000;\nlet watchRenewalTimer: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Register a Google Drive changes.watch channel so Google pushes\n * notifications to our webhook instead of us polling.\n *\n * Returns true if the watch was registered successfully.\n */\nexport async function registerWatch(webhookUrl: string): Promise<boolean> {\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return false;\n\n // Get the current page token as the starting point\n let pageToken = await getPageToken();\n if (!pageToken) {\n pageToken = await getStartPageToken(accessToken);\n await setPageToken(pageToken);\n }\n\n const channelId = `gdocs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const expiration = Date.now() + WATCH_CHANNEL_TTL_MS;\n\n try {\n const res = await fetch(\n \"https://www.googleapis.com/drive/v3/changes/watch\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n id: channelId,\n type: \"web_hook\",\n address: webhookUrl,\n expiration: expiration,\n payload: true,\n }),\n },\n );\n\n if (!res.ok) {\n const err = await res.text();\n console.error(\"[google-docs] Failed to register watch:\", err);\n return false;\n }\n\n const data = (await res.json()) as {\n id: string;\n resourceId: string;\n expiration: string;\n };\n\n // Save channel info for renewal and stopping\n await saveIntegrationConfig(\n PLATFORM,\n {\n channelId: data.id,\n resourceId: data.resourceId,\n expiration: data.expiration,\n webhookUrl,\n },\n \"watch-channel\",\n );\n\n console.log(\n `[google-docs] Watch registered (channel: ${data.id}, expires: ${new Date(parseInt(data.expiration)).toISOString()})`,\n );\n\n // Schedule renewal before expiration\n scheduleWatchRenewal(webhookUrl);\n\n return true;\n } catch (err) {\n console.error(\"[google-docs] Watch registration error:\", err);\n return false;\n }\n}\n\n/**\n * Stop an existing watch channel.\n */\nasync function stopWatch(): Promise<void> {\n const config = await getIntegrationConfig(PLATFORM, \"watch-channel\");\n if (!config?.configData?.channelId) return;\n\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return;\n\n try {\n await fetch(\"https://www.googleapis.com/drive/v3/channels/stop\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n id: config.configData.channelId,\n resourceId: config.configData.resourceId,\n }),\n });\n } catch {\n // Best effort — channel may have expired already\n }\n\n await saveIntegrationConfig(PLATFORM, {}, \"watch-channel\");\n}\n\n/**\n * Schedule automatic watch renewal before the channel expires.\n */\nfunction scheduleWatchRenewal(webhookUrl: string): void {\n if (watchRenewalTimer) clearTimeout(watchRenewalTimer);\n\n // Renew 1 hour before expiration\n const renewIn = WATCH_CHANNEL_TTL_MS - 60 * 60 * 1000;\n\n watchRenewalTimer = setTimeout(async () => {\n console.log(\"[google-docs] Renewing watch channel...\");\n await stopWatch();\n await registerWatch(webhookUrl);\n }, renewIn);\n}\n\n// ─── Page Token Management ──────────────────────────────────────────────────\n\nasync function getPageToken(): Promise<string | null> {\n const config = await getIntegrationConfig(PLATFORM, \"page-token\");\n return (config?.configData?.pageToken as string) ?? null;\n}\n\nasync function setPageToken(token: string): Promise<void> {\n await saveIntegrationConfig(PLATFORM, { pageToken: token }, \"page-token\");\n}\n\n// ─── Comment Detection ──────────────────────────────────────────────────────\n\nfunction isAgentMention(commentText: string, triggerKeyword: string): boolean {\n return commentText.toLowerCase().includes(triggerKeyword.toLowerCase());\n}\n\nfunction commentKey(fileId: string, commentId: string): string {\n return `${fileId}:${commentId}`;\n}\n\n/**\n * Check a single document for new agent-directed comments.\n */\nasync function checkDocumentComments(\n fileId: string,\n accessToken: string,\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n const triggerKeyword = options.triggerKeyword ?? DEFAULT_TRIGGER;\n const serviceEmail = getServiceAccountEmail();\n\n const lastChecked = lastCheckedTimes.get(fileId);\n const comments = await listDocComments(fileId, accessToken, lastChecked);\n const now = new Date().toISOString();\n\n for (const comment of comments) {\n if (comment.resolved) continue;\n\n const key = commentKey(fileId, comment.id);\n\n // Skip comments authored by the service account\n if (\n serviceEmail &&\n comment.author.emailAddress?.toLowerCase() === serviceEmail.toLowerCase()\n ) {\n continue;\n }\n\n const existingMapping = await getThreadMapping(PLATFORM, key);\n\n if (existingMapping) {\n // Durable per-reply dedup: the in-memory `processedComments` Set does not\n // survive serverless cold starts (see pending-tasks-store H3 note), which\n // would let already-answered replies be reprocessed and double-posted.\n // Persist processed reply ids in the existing SQL thread mapping instead.\n const persistedReplyIds =\n existingMapping.platformContext.processedReplyIds;\n const processedReplyIds = new Set<string>(\n Array.isArray(persistedReplyIds) ? (persistedReplyIds as string[]) : [],\n );\n\n // Check for new follow-up replies from users\n const newUserReplies = (comment.replies ?? []).filter((r) => {\n if (\n serviceEmail &&\n r.author.emailAddress?.toLowerCase() === serviceEmail.toLowerCase()\n ) {\n return false;\n }\n const replyKey = `${key}:reply:${r.id}`;\n if (processedReplyIds.has(r.id) || processedComments.has(replyKey))\n return false;\n if (!isAgentMention(r.content, triggerKeyword)) return false;\n return true;\n });\n\n for (const reply of newUserReplies) {\n const replyKey = `${key}:reply:${reply.id}`;\n processedComments.add(replyKey);\n processedReplyIds.add(reply.id);\n // Persist immediately so a crash/cold-start between replies cannot\n // re-answer this reply on the next invocation.\n await saveThreadMapping(\n PLATFORM,\n key,\n existingMapping.internalThreadId,\n {\n ...existingMapping.platformContext,\n processedReplyIds: Array.from(processedReplyIds),\n },\n );\n\n const text = reply.content\n .replace(\n new RegExp(\n triggerKeyword.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n \"gi\",\n ),\n \"\",\n )\n .trim();\n\n await processComment(\n fileId,\n comment.id,\n text,\n reply.author.displayName,\n options,\n existingMapping.internalThreadId,\n );\n }\n continue;\n }\n\n // New comment — check if it mentions the agent\n if (!isAgentMention(comment.content, triggerKeyword)) continue;\n\n processedComments.add(key);\n\n let text = comment.content;\n if (comment.quotedFileContent?.value) {\n text = `[Highlighted text: \"${comment.quotedFileContent.value}\"]\\n\\n${text}`;\n }\n\n text = text\n .replace(\n new RegExp(triggerKeyword.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"gi\"),\n \"\",\n )\n .trim();\n\n await processComment(\n fileId,\n comment.id,\n text,\n comment.author.displayName,\n options,\n );\n }\n\n lastCheckedTimes.set(fileId, now);\n}\n\n// ─── Process Changes ────────────────────────────────────────────────────────\n\n/**\n * Process pending Drive changes — called by both push notifications and polling.\n * Fetches changes since the last page token, finds Google Docs that changed,\n * and checks their comments for agent mentions.\n */\nexport async function processChanges(\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n const accessToken = await getServiceAccountAccessToken();\n if (!accessToken) return;\n\n let pageToken = await getPageToken();\n if (!pageToken) {\n pageToken = await getStartPageToken(accessToken);\n await setPageToken(pageToken);\n return; // First run — just save the cursor\n }\n\n const { changes, nextPageToken } = await listChanges(pageToken, accessToken);\n await setPageToken(nextPageToken);\n\n if (changes.length === 0) return;\n\n // Deduplicate and filter to Google Docs\n const docFileIds = new Set<string>();\n for (const change of changes) {\n if (change.removed) continue;\n if (\n change.file?.mimeType === \"application/vnd.google-apps.document\" ||\n !change.file?.mimeType\n ) {\n docFileIds.add(change.fileId);\n }\n }\n\n for (const fileId of docFileIds) {\n try {\n await checkDocumentComments(fileId, accessToken, options);\n } catch (err) {\n console.error(`[google-docs] Error checking comments on ${fileId}:`, err);\n }\n }\n}\n\n/**\n * Handle a push notification from Google Drive changes.watch.\n * Called from the integration webhook route.\n */\nexport async function handlePushNotification(): Promise<void> {\n if (!activeOptions) {\n console.warn(\n \"[google-docs] Push notification received but poller not configured\",\n );\n return;\n }\n\n try {\n await processChanges(activeOptions);\n } catch (err) {\n console.error(\"[google-docs] Error processing push notification:\", err);\n }\n}\n\n// ─── Agent Processing ───────────────────────────────────────────────────────\n\nasync function processComment(\n fileId: string,\n commentId: string,\n text: string,\n senderName: string,\n options: GoogleDocsPollerOptions,\n existingThreadId?: string,\n): Promise<void> {\n const adapter = googleDocsAdapter();\n const key = commentKey(fileId, commentId);\n\n const incoming: IncomingMessage = {\n platform: PLATFORM,\n externalThreadId: key,\n text,\n senderName,\n platformContext: { fileId, commentId },\n timestamp: Date.now(),\n };\n\n let threadId = existingThreadId;\n if (!threadId) {\n const thread = await createThread(options.ownerEmail, {\n title: `Google Doc: ${senderName}`,\n });\n await saveThreadMapping(PLATFORM, key, thread.id, { fileId, commentId });\n threadId = thread.id;\n }\n\n const thread = await getThread(threadId);\n const existingMessages: EngineMessage[] = [];\n if (thread?.threadData) {\n try {\n const data = JSON.parse(thread.threadData);\n if (Array.isArray(data.messages)) {\n for (const msg of data.messages) {\n const m = msg.message ?? msg;\n const textContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content\n .filter((c: any) => c.type === \"text\")\n .map((c: any) => c.text)\n .join(\"\\n\")\n : \"\";\n if (m.role === \"user\") {\n existingMessages.push({\n role: \"user\",\n content: [{ type: \"text\", text: textContent }],\n });\n } else if (m.role === \"assistant\") {\n existingMessages.push({\n role: \"assistant\",\n content: [{ type: \"text\", text: textContent }],\n });\n }\n }\n }\n } catch {}\n }\n\n const messages: EngineMessage[] = [\n ...existingMessages,\n { role: \"user\", content: [{ type: \"text\", text }] },\n ];\n\n const engine = createAnthropicEngine({ apiKey: options.apiKey });\n // Attach tool-search on a shallow copy so framework additions merged in by\n // `createIntegrationsPlugin` (integration memory, `call-agent`) can be\n // deferred behind it without mutating the plugin's long-lived registry.\n // `runAgentLoop`'s `expandActiveTools` re-expands from `availableTools`\n // after a tool-search call, so anything filtered out of the initial\n // `tools` list stays reachable.\n const runnableActions = attachToolSearch({ ...options.actions });\n const availableTools = actionsToEngineTools(runnableActions);\n const tools = filterInitialEngineTools(\n availableTools,\n options.initialToolNames,\n );\n const runId = `gdocs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const capturedThreadId = threadId;\n const orgId = (await resolveOrgIdForEmail(options.ownerEmail)) ?? undefined;\n\n startRun(\n runId,\n capturedThreadId,\n async (send, signal) => {\n await runWithRequestContext(\n { userEmail: options.ownerEmail, orgId, isIntegrationCaller: true },\n () =>\n // Wrapper, not raw `runAgentLoop`: a doc-comment reply has no client\n // driving continuation, so a transport-level cut has to be resumed\n // inside this invocation or the commenter never gets an answer.\n runAgentLoopDirectWithSoftTimeout(\n {\n engine,\n model: options.model,\n systemPrompt: options.systemPrompt,\n tools,\n availableTools,\n messages,\n actions: runnableActions,\n send,\n signal,\n },\n undefined,\n // Same omission the scheduled-job runner had: without this, a\n // poller-driven reply inherits the interactive clamp (40s soft\n // timeout, a no-progress backstop at 0.75x that, 6 continuations)\n // even though no client is waiting on a response. Uses the runtime\n // check rather than a hardcoded `true` — matching webhook-handler.ts\n // in this same subsystem — because unlike the job runner there is no\n // hard-abort cap here to bound a wider ceiling.\n {\n useHostedDefault: true,\n backgroundFunction: isInBackgroundFunctionRuntime(),\n },\n ),\n );\n },\n async (completedRun: ActiveRun) => {\n try {\n let responseText = \"\";\n for (const runEvent of completedRun.events) {\n if (runEvent.event.type === \"text\") {\n responseText += runEvent.event.text;\n }\n }\n if (!responseText.trim()) responseText = \"(No response)\";\n\n const outgoing = adapter.formatAgentResponse(responseText);\n await adapter.sendResponse(outgoing, incoming);\n await persistThreadData(capturedThreadId, text, completedRun, thread);\n } catch (err) {\n console.error(\"[google-docs] Error sending response:\", err);\n }\n },\n // No userId here: `options.ownerEmail` is PII (email), which the\n // terminal event must not carry.\n { model: options.model, engineName: engine.name },\n );\n}\n\nasync function persistThreadData(\n threadId: string,\n userText: string,\n completedRun: ActiveRun,\n thread: any,\n): Promise<void> {\n try {\n let repo: any;\n try {\n repo = JSON.parse(thread?.threadData || \"{}\");\n } catch {\n repo = {};\n }\n if (!Array.isArray(repo.messages)) repo.messages = [];\n\n repo.messages.push({\n id: `msg-${Date.now()}-user`,\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n createdAt: new Date().toISOString(),\n });\n\n const assistantMsg = buildAssistantMessage(\n completedRun.events ?? [],\n completedRun.runId,\n );\n if (assistantMsg) repo.messages.push(assistantMsg);\n\n const meta = extractThreadMeta(repo);\n await updateThreadData(\n threadId,\n JSON.stringify(repo),\n meta.title || thread?.title || \"Google Doc Comment\",\n meta.preview || thread?.preview || \"\",\n repo.messages.length,\n );\n } catch {\n // Best-effort\n }\n}\n\n// ─── Poller (Hybrid: Push Primary, Poll Fallback) ───────────────────────────\n\n/**\n * Start the Google Docs integration.\n *\n * Hybrid approach:\n * 1. Attempts to register a Google Drive changes.watch webhook for\n * near-instant push notifications (~seconds latency)\n * 2. Falls back to polling if the watch registration fails\n * (e.g. domain not verified, local dev)\n * 3. Even in push mode, polls at a slow interval (5min) as a safety net\n * in case a push notification is missed\n */\nexport async function startGoogleDocsPoller(\n options: GoogleDocsPollerOptions,\n): Promise<void> {\n if (pollerInterval) {\n console.warn(\"[google-docs] Already running\");\n return;\n }\n\n activeOptions = options;\n\n // Check if integration is enabled before trying to register watch\n const config = await getIntegrationConfig(PLATFORM);\n if (!config?.configData?.enabled) {\n // Still start the poll loop so it picks up when enabled later\n startPollLoop(options, options.intervalMs ?? 30_000);\n return;\n }\n\n // Try to register push notifications\n const webhookUrl = options.webhookUrl;\n let pushMode = false;\n\n if (webhookUrl) {\n pushMode = await registerWatch(webhookUrl);\n if (pushMode) {\n console.log(\"[google-docs] Push mode active — using Drive webhooks\");\n // In push mode, still poll slowly as a safety net (every 5 min)\n startPollLoop(options, 5 * 60 * 1000);\n }\n }\n\n if (!pushMode) {\n console.log(\n \"[google-docs] Polling mode — push registration failed or no webhook URL\",\n );\n startPollLoop(options, options.intervalMs ?? 30_000);\n }\n}\n\n/** Backoff for the config probe while google-docs is disabled. */\nconst DISABLED_CONFIG_RECHECK_MS = 5 * 60 * 1000;\n\nfunction startPollLoop(\n options: GoogleDocsPollerOptions,\n intervalMs: number,\n): void {\n let disabledUntil = 0;\n let disabledAtConfigWriteEpoch = -1;\n\n async function poll() {\n try {\n // The loop starts even when google-docs was never configured (so it picks\n // up a later enable), which used to mean one `integration_configs` read\n // every 30s per app forever. While disabled, re-read only every\n // DISABLED_CONFIG_RECHECK_MS — or immediately after any in-process config\n // write, so enabling the integration still takes effect on the next tick.\n const epoch = integrationConfigWriteEpoch();\n if (Date.now() < disabledUntil && epoch === disabledAtConfigWriteEpoch) {\n return;\n }\n const config = await getIntegrationConfig(PLATFORM);\n if (!config?.configData?.enabled) {\n disabledUntil = Date.now() + DISABLED_CONFIG_RECHECK_MS;\n disabledAtConfigWriteEpoch = epoch;\n return;\n }\n disabledUntil = 0;\n await processChanges(options);\n } catch (err) {\n // Unwrap ErrorEvent (Neon WS driver emits these on network failure) so logs show the real cause\n const detail =\n err instanceof Error\n ? err\n : ((err as any)?.error ?? (err as any)?.message ?? err);\n console.error(\"[google-docs] Poller error:\", detail);\n }\n }\n\n setTimeout(poll, 5000);\n pollerInterval = setInterval(poll, intervalMs);\n\n const email = getServiceAccountEmail();\n if (process.env.DEBUG) {\n console.log(\n `[google-docs] Poll loop started (interval: ${intervalMs / 1000}s, service account: ${email ?? \"not configured\"})`,\n );\n }\n}\n\n/**\n * Stop the Google Docs integration.\n */\nexport async function stopGoogleDocsPoller(): Promise<void> {\n if (pollerInterval) {\n clearInterval(pollerInterval);\n pollerInterval = null;\n }\n if (watchRenewalTimer) {\n clearTimeout(watchRenewalTimer);\n watchRenewalTimer = null;\n }\n await stopWatch();\n activeOptions = null;\n}\n"]}
|
|
@@ -109,4 +109,14 @@ export declare function resolveIntegrationTokenBundle(platform: string, installa
|
|
|
109
109
|
export declare function getActiveIntegrationInstallationByKey(platform: string, installationKey: string): Promise<IntegrationInstallation | null>;
|
|
110
110
|
/** Resolve a connected installation by workspace or enterprise tenant id. */
|
|
111
111
|
export declare function getActiveIntegrationInstallationForTenant(platform: string, tenantId: string): Promise<IntegrationInstallation | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Every connected installation for a tenant, newest first.
|
|
114
|
+
*
|
|
115
|
+
* A workspace can legitimately have several apps of the same platform
|
|
116
|
+
* connected at once (e.g. a product-specific Slack app alongside a generic
|
|
117
|
+
* one). Callers that cannot name an app id must see that ambiguity rather
|
|
118
|
+
* than receive an arbitrary winner — picking the most recently updated row
|
|
119
|
+
* silently sends as whichever app happened to reconnect last.
|
|
120
|
+
*/
|
|
121
|
+
export declare function listActiveIntegrationInstallationsForTenant(platform: string, tenantId: string): Promise<IntegrationInstallation[]>;
|
|
112
122
|
//# sourceMappingURL=installations-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installations-store.d.ts","sourceRoot":"","sources":["../../src/integrations/installations-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1D,MAAM,MAAM,6BAA6B,GACrC,WAAW,GACX,cAAc,GACd,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,MAAM,6BAA6B,GACrC,SAAS,GACT,SAAS,GACT,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,6BAA6B,CAAC;IACtC,MAAM,EAAE,6BAA6B,CAAC;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAQD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gEAAgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,sBAAsB,CAAC;IACpC,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AA0ND;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,CAAC,CAyIlC;AAED,6EAA6E;AAC7E,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iBAAiB,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAqBpC;AAED,kEAAkE;AAClE,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAUzC;AAED,iFAAiF;AACjF,wBAAsB,6BAA6B,CACjD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAoDzC;AAED,gFAAgF;AAChF,wBAAsB,iCAAiC,CACrD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAoBzC;AAED;;;;;;GAMG;AACH,wBAAsB,6BAA6B,CACjD,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAkBxC;AAED,0DAA0D;AAC1D,wBAAsB,qCAAqC,CACzD,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAIzC;AAED,6EAA6E;AAC7E,wBAAsB,yCAAyC,CAC7D,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAgBzC"}
|
|
1
|
+
{"version":3,"file":"installations-store.d.ts","sourceRoot":"","sources":["../../src/integrations/installations-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -490,4 +490,28 @@ export async function getActiveIntegrationInstallationForTenant(platform, tenant
|
|
|
490
490
|
? toSafeInstallation(rowToRaw(rows[0]))
|
|
491
491
|
: null;
|
|
492
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Every connected installation for a tenant, newest first.
|
|
495
|
+
*
|
|
496
|
+
* A workspace can legitimately have several apps of the same platform
|
|
497
|
+
* connected at once (e.g. a product-specific Slack app alongside a generic
|
|
498
|
+
* one). Callers that cannot name an app id must see that ambiguity rather
|
|
499
|
+
* than receive an arbitrary winner — picking the most recently updated row
|
|
500
|
+
* silently sends as whichever app happened to reconnect last.
|
|
501
|
+
*/
|
|
502
|
+
export async function listActiveIntegrationInstallationsForTenant(platform, tenantId) {
|
|
503
|
+
await ensureTable();
|
|
504
|
+
const { rows } = await getDbExec().execute({
|
|
505
|
+
sql: `SELECT * FROM ${TABLE}
|
|
506
|
+
WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)
|
|
507
|
+
AND status = 'connected'
|
|
508
|
+
ORDER BY updated_at DESC`,
|
|
509
|
+
args: [
|
|
510
|
+
normalizePlatform(platform),
|
|
511
|
+
required(tenantId, "tenantId"),
|
|
512
|
+
required(tenantId, "tenantId"),
|
|
513
|
+
],
|
|
514
|
+
});
|
|
515
|
+
return rows.map((row) => toSafeInstallation(rowToRaw(row)));
|
|
516
|
+
}
|
|
493
517
|
//# sourceMappingURL=installations-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installations-store.js","sourceRoot":"","sources":["../../src/integrations/installations-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable metadata and encrypted credentials for managed messaging installs.\n *\n * The installation row deliberately contains only provider metadata and an\n * opaque `app_secrets` key. OAuth access and refresh tokens are serialized as\n * one bundle and encrypted by the framework secrets vault. List/read helpers\n * never expose the secret key or token values.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\n\nimport {\n getDbExec,\n intType,\n isPostgres,\n isUniqueViolation,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport type { SecretScope } from \"../secrets/register.js\";\nimport {\n deleteAppSecret,\n readAppSecret,\n writeAppSecret,\n} from \"../secrets/storage.js\";\n\nconst TABLE = \"integration_installations\";\nlet _initPromise: Promise<void> | undefined;\n\nexport type IntegrationInstallationStatus =\n | \"connected\"\n | \"disconnected\"\n | \"revoked\"\n | \"error\";\n\nexport type IntegrationInstallationHealth =\n | \"unknown\"\n | \"healthy\"\n | \"degraded\"\n | \"revoked\";\n\nexport interface IntegrationTokenBundle {\n accessToken: string;\n refreshToken?: string;\n tokenType?: string;\n expiresAt?: number;\n}\n\n/** Safe-to-return installation metadata. No secret reference or token value. */\nexport interface IntegrationInstallation {\n id: string;\n platform: string;\n installationKey: string;\n teamId: string | null;\n teamName: string | null;\n enterpriseId: string | null;\n enterpriseName: string | null;\n isEnterpriseInstall: boolean;\n apiAppId: string | null;\n botUserId: string | null;\n scopes: string[];\n installedByExternalUserId: string | null;\n ownerEmail: string;\n orgId: string | null;\n status: IntegrationInstallationStatus;\n health: IntegrationInstallationHealth;\n lastError: string | null;\n healthCheckedAt: number | null;\n lastHealthyAt: number | null;\n tokenExpiresAt: number | null;\n createdAt: number;\n updatedAt: number;\n disconnectedAt: number | null;\n}\n\ninterface RawInstallation extends IntegrationInstallation {\n tokenSecretKey: string;\n secretScope: SecretScope;\n secretScopeId: string;\n}\n\nexport interface InstallationActor {\n userEmail: string;\n orgId?: string | null;\n /** Must come from a verified active organization membership. */\n isOrgAdmin?: boolean;\n}\n\nexport interface UpsertIntegrationInstallationInput {\n platform: string;\n installationKey: string;\n teamId?: string | null;\n teamName?: string | null;\n enterpriseId?: string | null;\n enterpriseName?: string | null;\n isEnterpriseInstall?: boolean;\n apiAppId?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n installedByExternalUserId?: string | null;\n ownerEmail: string;\n orgId?: string | null;\n secretScope: SecretScope;\n secretScopeId: string;\n tokenBundle: IntegrationTokenBundle;\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nexport interface IntegrationInstallationUpdate {\n teamName?: string | null;\n enterpriseName?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nfunction createSql(): string {\n const integer = intType();\n return `CREATE TABLE IF NOT EXISTS ${TABLE} (\n id TEXT PRIMARY KEY,\n platform TEXT NOT NULL,\n installation_key TEXT NOT NULL,\n team_id TEXT,\n team_name TEXT,\n enterprise_id TEXT,\n enterprise_name TEXT,\n is_enterprise_install ${integer} NOT NULL DEFAULT 0,\n api_app_id TEXT,\n bot_user_id TEXT,\n scopes_json TEXT NOT NULL DEFAULT '[]',\n installed_by_external_user_id TEXT,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n token_secret_key TEXT NOT NULL,\n secret_scope TEXT NOT NULL,\n secret_scope_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'connected',\n health TEXT NOT NULL DEFAULT 'unknown',\n last_error TEXT,\n health_checked_at ${integer},\n last_healthy_at ${integer},\n token_expires_at ${integer},\n created_at ${integer} NOT NULL,\n updated_at ${integer} NOT NULL,\n disconnected_at ${integer}\n )`;\n}\n\nconst INDEXES = [\n [\n \"idx_integration_installations_key\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_installations_key ON ${TABLE}(platform, installation_key)`,\n ],\n [\n \"idx_integration_installations_team\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_team ON ${TABLE}(platform, team_id, status)`,\n ],\n [\n \"idx_integration_installations_owner\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_owner ON ${TABLE}(owner_email, updated_at)`,\n ],\n [\n \"idx_integration_installations_org\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_org ON ${TABLE}(org_id, updated_at)`,\n ],\n] as const;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const ddl = createSql();\n if (isPostgres()) {\n await ensureTableExists(TABLE, ddl);\n for (const [name, sql] of INDEXES) {\n await ensureIndexExists(name, sql);\n }\n return;\n }\n await retryOnDdlRace(() => client.execute(ddl));\n for (const [, sql] of INDEXES) {\n await retryOnDdlRace(() => client.execute(sql));\n }\n })().catch((error) => {\n _initPromise = undefined;\n throw error;\n });\n }\n return _initPromise;\n}\n\nfunction required(value: string, name: string): string {\n const normalized = value.trim();\n if (!normalized) throw new Error(`${name} is required`);\n if (normalized.length > 512) throw new Error(`${name} is too long`);\n return normalized;\n}\n\nfunction normalizePlatform(value: string): string {\n return required(value, \"platform\").toLowerCase();\n}\n\nfunction normalizeEmail(value: string): string {\n return required(value, \"ownerEmail\").toLowerCase();\n}\n\nfunction normalizeScopes(scopes: readonly string[] | undefined): string[] {\n return Array.from(\n new Set(\n (scopes ?? [])\n .map((scope) => scope.trim())\n .filter(Boolean)\n .sort(),\n ),\n );\n}\n\nfunction parseScopes(value: unknown): string[] {\n if (typeof value !== \"string\") return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) &&\n parsed.every((item) => typeof item === \"string\")\n ? parsed\n : [];\n } catch {\n return [];\n }\n}\n\nfunction toBoolean(value: unknown): boolean {\n return value === true || value === 1 || value === \"1\" || value === \"true\";\n}\n\nfunction nullableNumber(value: unknown): number | null {\n return value == null ? null : Number(value);\n}\n\nfunction rowToRaw(row: Record<string, unknown>): RawInstallation {\n return {\n id: String(row.id),\n platform: String(row.platform),\n installationKey: String(row.installation_key),\n teamId: (row.team_id as string | null) ?? null,\n teamName: (row.team_name as string | null) ?? null,\n enterpriseId: (row.enterprise_id as string | null) ?? null,\n enterpriseName: (row.enterprise_name as string | null) ?? null,\n isEnterpriseInstall: toBoolean(row.is_enterprise_install),\n apiAppId: (row.api_app_id as string | null) ?? null,\n botUserId: (row.bot_user_id as string | null) ?? null,\n scopes: parseScopes(row.scopes_json),\n installedByExternalUserId:\n (row.installed_by_external_user_id as string | null) ?? null,\n ownerEmail: String(row.owner_email),\n orgId: (row.org_id as string | null) ?? null,\n tokenSecretKey: String(row.token_secret_key),\n secretScope: row.secret_scope as SecretScope,\n secretScopeId: String(row.secret_scope_id),\n status: row.status as IntegrationInstallationStatus,\n health: row.health as IntegrationInstallationHealth,\n lastError: (row.last_error as string | null) ?? null,\n healthCheckedAt: nullableNumber(row.health_checked_at),\n lastHealthyAt: nullableNumber(row.last_healthy_at),\n tokenExpiresAt: nullableNumber(row.token_expires_at),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n disconnectedAt: nullableNumber(row.disconnected_at),\n };\n}\n\nfunction toSafeInstallation(row: RawInstallation): IntegrationInstallation {\n const {\n tokenSecretKey: _tokenSecretKey,\n secretScope: _scope,\n secretScopeId: _scopeId,\n ...safe\n } = row;\n return safe;\n}\n\nfunction tokenSecretKey(platform: string, installationKey: string): string {\n const digest = createHash(\"sha256\")\n .update(`${platform}\\0${installationKey}`)\n .digest(\"hex\")\n .slice(0, 32);\n return `integration:${platform}:${digest}:oauth-token-bundle`;\n}\n\nfunction sameOwner(a: string, b: string): boolean {\n return a.trim().toLowerCase() === b.trim().toLowerCase();\n}\n\nfunction sameScope(\n row: Pick<RawInstallation, \"ownerEmail\" | \"orgId\">,\n ownerEmail: string,\n orgId: string | null,\n): boolean {\n if (row.orgId || orgId) return !!row.orgId && row.orgId === orgId;\n return sameOwner(row.ownerEmail, ownerEmail);\n}\n\nfunction canMutate(row: RawInstallation, actor: InstallationActor): boolean {\n if (row.orgId) {\n return actor.orgId === row.orgId && actor.isOrgAdmin === true;\n }\n return sameOwner(row.ownerEmail, actor.userEmail);\n}\n\nasync function selectRawById(id: string): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function selectRawByKey(\n platform: string,\n installationKey: string,\n): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE platform = ? AND installation_key = ? LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(installationKey, \"installationKey\"),\n ],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\n/**\n * Create or refresh a managed install. Re-installs may rotate tokens inside\n * the same owner/org scope, but cannot silently move an existing provider\n * installation into another Agent Native tenant.\n */\nexport async function upsertIntegrationInstallation(\n input: UpsertIntegrationInstallationInput,\n): Promise<IntegrationInstallation> {\n await ensureTable();\n const platform = normalizePlatform(input.platform);\n const installationKey = required(input.installationKey, \"installationKey\");\n const ownerEmail = normalizeEmail(input.ownerEmail);\n const orgId = input.orgId?.trim() || null;\n const secretScopeId = required(input.secretScopeId, \"secretScopeId\");\n const accessToken = input.tokenBundle.accessToken?.trim();\n if (!accessToken) throw new Error(\"tokenBundle.accessToken is required\");\n\n const existing = await selectRawByKey(platform, installationKey);\n if (existing && !sameScope(existing, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n const secretKey =\n existing?.tokenSecretKey ?? tokenSecretKey(platform, installationKey);\n const persistTokenBundle = (key: string) =>\n writeAppSecret({\n key,\n value: JSON.stringify(input.tokenBundle),\n scope: input.secretScope,\n scopeId: secretScopeId,\n description: `${platform} OAuth token bundle for a managed installation`,\n });\n await persistTokenBundle(secretKey);\n\n const now = Date.now();\n let id = existing?.id ?? randomUUID();\n const scopesJson = JSON.stringify(normalizeScopes(input.scopes));\n const tokenExpiresAt =\n input.tokenExpiresAt ?? input.tokenBundle.expiresAt ?? null;\n\n const updateExisting = async (rowId: string, rowSecretKey: string) => {\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET\n team_id = ?, team_name = ?, enterprise_id = ?, enterprise_name = ?,\n is_enterprise_install = ?, api_app_id = ?, bot_user_id = ?, scopes_json = ?,\n installed_by_external_user_id = ?, owner_email = ?, org_id = ?,\n token_secret_key = ?, secret_scope = ?, secret_scope_id = ?, status = ?,\n health = ?, last_error = ?, health_checked_at = ?, last_healthy_at = ?,\n token_expires_at = ?, updated_at = ?, disconnected_at = ?\n WHERE id = ?`,\n args: [\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n rowSecretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n null,\n rowId,\n ],\n });\n };\n\n if (existing) {\n await updateExisting(existing.id, existing.tokenSecretKey);\n } else {\n try {\n await getDbExec().execute({\n sql: `INSERT INTO ${TABLE} (\n id, platform, installation_key, team_id, team_name, enterprise_id,\n enterprise_name, is_enterprise_install, api_app_id, bot_user_id,\n scopes_json, installed_by_external_user_id, owner_email, org_id,\n token_secret_key, secret_scope, secret_scope_id, status, health,\n last_error, health_checked_at, last_healthy_at, token_expires_at,\n created_at, updated_at, disconnected_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n platform,\n installationKey,\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n secretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n now,\n null,\n ],\n });\n } catch (error) {\n if (!isUniqueViolation(error)) throw error;\n\n const raced = await selectRawByKey(platform, installationKey);\n if (!raced) throw error;\n if (!sameScope(raced, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n id = raced.id;\n if (raced.tokenSecretKey !== secretKey) {\n await persistTokenBundle(raced.tokenSecretKey);\n }\n await updateExisting(raced.id, raced.tokenSecretKey);\n }\n }\n\n const stored = await selectRawById(id);\n if (!stored) throw new Error(\"Managed installation was not persisted\");\n return toSafeInstallation(stored);\n}\n\n/** List installations visible to the owner or active organization member. */\nexport async function listIntegrationInstallations(\n actor: InstallationActor,\n platform?: string,\n): Promise<IntegrationInstallation[]> {\n await ensureTable();\n const ownerEmail = normalizeEmail(actor.userEmail);\n const args: unknown[] = [ownerEmail];\n let visibility = \"owner_email = ?\";\n if (actor.orgId) {\n visibility = `(owner_email = ? OR org_id = ?)`;\n args.push(actor.orgId);\n }\n let platformFilter = \"\";\n if (platform) {\n platformFilter = \" AND platform = ?\";\n args.push(normalizePlatform(platform));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE ${visibility}${platformFilter} ORDER BY updated_at DESC`,\n args,\n });\n return rows.map((row) =>\n toSafeInstallation(rowToRaw(row as Record<string, unknown>)),\n );\n}\n\n/** Read one installation through owner/org visibility scoping. */\nexport async function getIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (\n !sameOwner(row.ownerEmail, actor.userEmail) &&\n (!row.orgId || row.orgId !== actor.orgId)\n ) {\n return null;\n }\n return toSafeInstallation(row);\n}\n\n/** Update non-secret installation metadata after an owner/admin access check. */\nexport async function updateIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n patch: IntegrationInstallationUpdate,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to update this installation.\");\n }\n const next = {\n teamName: patch.teamName === undefined ? row.teamName : patch.teamName,\n enterpriseName:\n patch.enterpriseName === undefined\n ? row.enterpriseName\n : patch.enterpriseName,\n botUserId: patch.botUserId === undefined ? row.botUserId : patch.botUserId,\n scopes:\n patch.scopes === undefined ? row.scopes : normalizeScopes(patch.scopes),\n status: patch.status ?? row.status,\n health: patch.health ?? row.health,\n lastError: patch.lastError === undefined ? row.lastError : patch.lastError,\n healthCheckedAt:\n patch.healthCheckedAt === undefined\n ? row.healthCheckedAt\n : patch.healthCheckedAt,\n lastHealthyAt:\n patch.lastHealthyAt === undefined\n ? row.lastHealthyAt\n : patch.lastHealthyAt,\n tokenExpiresAt:\n patch.tokenExpiresAt === undefined\n ? row.tokenExpiresAt\n : patch.tokenExpiresAt,\n };\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET team_name = ?, enterprise_name = ?, bot_user_id = ?,\n scopes_json = ?, status = ?, health = ?, last_error = ?, health_checked_at = ?,\n last_healthy_at = ?, token_expires_at = ?, updated_at = ? WHERE id = ?`,\n args: [\n next.teamName,\n next.enterpriseName,\n next.botUserId,\n JSON.stringify(next.scopes),\n next.status,\n next.health,\n next.lastError,\n next.healthCheckedAt,\n next.lastHealthyAt,\n next.tokenExpiresAt,\n Date.now(),\n id,\n ],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/** Delete the encrypted token bundle and retain disconnected audit metadata. */\nexport async function disconnectIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to disconnect this installation.\");\n }\n await deleteAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET status = 'disconnected', health = 'unknown',\n last_error = NULL, token_expires_at = NULL, disconnected_at = ?, updated_at = ?\n WHERE id = ?`,\n args: [now, now, id],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/**\n * Resolve credentials for a verified provider webhook/runtime path.\n *\n * This is intentionally separate from every user-facing list/read helper.\n * Callers must first authenticate the provider webhook (or run inside a\n * trusted OAuth callback) and must never log or return the result.\n */\nexport async function resolveIntegrationTokenBundle(\n platform: string,\n installationKey: string,\n): Promise<IntegrationTokenBundle | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\" || row.health === \"revoked\")\n return null;\n const secret = await readAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n if (!secret) return null;\n try {\n const parsed = JSON.parse(secret.value) as Partial<IntegrationTokenBundle>;\n if (typeof parsed.accessToken !== \"string\" || !parsed.accessToken)\n return null;\n return parsed as IntegrationTokenBundle;\n } catch {\n return null;\n }\n}\n\n/** Safe metadata lookup for a verified provider event. */\nexport async function getActiveIntegrationInstallationByKey(\n platform: string,\n installationKey: string,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\") return null;\n return toSafeInstallation(row);\n}\n\n/** Resolve a connected installation by workspace or enterprise tenant id. */\nexport async function getActiveIntegrationInstallationForTenant(\n platform: string,\n tenantId: string,\n): Promise<IntegrationInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE}\n WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)\n AND status = 'connected'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(tenantId, \"tenantId\"),\n required(tenantId, \"tenantId\"),\n ],\n });\n return rows[0]\n ? toSafeInstallation(rowToRaw(rows[0] as Record<string, unknown>))\n : null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"installations-store.js","sourceRoot":"","sources":["../../src/integrations/installations-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable metadata and encrypted credentials for managed messaging installs.\n *\n * The installation row deliberately contains only provider metadata and an\n * opaque `app_secrets` key. OAuth access and refresh tokens are serialized as\n * one bundle and encrypted by the framework secrets vault. List/read helpers\n * never expose the secret key or token values.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\n\nimport {\n getDbExec,\n intType,\n isPostgres,\n isUniqueViolation,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport type { SecretScope } from \"../secrets/register.js\";\nimport {\n deleteAppSecret,\n readAppSecret,\n writeAppSecret,\n} from \"../secrets/storage.js\";\n\nconst TABLE = \"integration_installations\";\nlet _initPromise: Promise<void> | undefined;\n\nexport type IntegrationInstallationStatus =\n | \"connected\"\n | \"disconnected\"\n | \"revoked\"\n | \"error\";\n\nexport type IntegrationInstallationHealth =\n | \"unknown\"\n | \"healthy\"\n | \"degraded\"\n | \"revoked\";\n\nexport interface IntegrationTokenBundle {\n accessToken: string;\n refreshToken?: string;\n tokenType?: string;\n expiresAt?: number;\n}\n\n/** Safe-to-return installation metadata. No secret reference or token value. */\nexport interface IntegrationInstallation {\n id: string;\n platform: string;\n installationKey: string;\n teamId: string | null;\n teamName: string | null;\n enterpriseId: string | null;\n enterpriseName: string | null;\n isEnterpriseInstall: boolean;\n apiAppId: string | null;\n botUserId: string | null;\n scopes: string[];\n installedByExternalUserId: string | null;\n ownerEmail: string;\n orgId: string | null;\n status: IntegrationInstallationStatus;\n health: IntegrationInstallationHealth;\n lastError: string | null;\n healthCheckedAt: number | null;\n lastHealthyAt: number | null;\n tokenExpiresAt: number | null;\n createdAt: number;\n updatedAt: number;\n disconnectedAt: number | null;\n}\n\ninterface RawInstallation extends IntegrationInstallation {\n tokenSecretKey: string;\n secretScope: SecretScope;\n secretScopeId: string;\n}\n\nexport interface InstallationActor {\n userEmail: string;\n orgId?: string | null;\n /** Must come from a verified active organization membership. */\n isOrgAdmin?: boolean;\n}\n\nexport interface UpsertIntegrationInstallationInput {\n platform: string;\n installationKey: string;\n teamId?: string | null;\n teamName?: string | null;\n enterpriseId?: string | null;\n enterpriseName?: string | null;\n isEnterpriseInstall?: boolean;\n apiAppId?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n installedByExternalUserId?: string | null;\n ownerEmail: string;\n orgId?: string | null;\n secretScope: SecretScope;\n secretScopeId: string;\n tokenBundle: IntegrationTokenBundle;\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nexport interface IntegrationInstallationUpdate {\n teamName?: string | null;\n enterpriseName?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nfunction createSql(): string {\n const integer = intType();\n return `CREATE TABLE IF NOT EXISTS ${TABLE} (\n id TEXT PRIMARY KEY,\n platform TEXT NOT NULL,\n installation_key TEXT NOT NULL,\n team_id TEXT,\n team_name TEXT,\n enterprise_id TEXT,\n enterprise_name TEXT,\n is_enterprise_install ${integer} NOT NULL DEFAULT 0,\n api_app_id TEXT,\n bot_user_id TEXT,\n scopes_json TEXT NOT NULL DEFAULT '[]',\n installed_by_external_user_id TEXT,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n token_secret_key TEXT NOT NULL,\n secret_scope TEXT NOT NULL,\n secret_scope_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'connected',\n health TEXT NOT NULL DEFAULT 'unknown',\n last_error TEXT,\n health_checked_at ${integer},\n last_healthy_at ${integer},\n token_expires_at ${integer},\n created_at ${integer} NOT NULL,\n updated_at ${integer} NOT NULL,\n disconnected_at ${integer}\n )`;\n}\n\nconst INDEXES = [\n [\n \"idx_integration_installations_key\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_installations_key ON ${TABLE}(platform, installation_key)`,\n ],\n [\n \"idx_integration_installations_team\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_team ON ${TABLE}(platform, team_id, status)`,\n ],\n [\n \"idx_integration_installations_owner\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_owner ON ${TABLE}(owner_email, updated_at)`,\n ],\n [\n \"idx_integration_installations_org\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_org ON ${TABLE}(org_id, updated_at)`,\n ],\n] as const;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const ddl = createSql();\n if (isPostgres()) {\n await ensureTableExists(TABLE, ddl);\n for (const [name, sql] of INDEXES) {\n await ensureIndexExists(name, sql);\n }\n return;\n }\n await retryOnDdlRace(() => client.execute(ddl));\n for (const [, sql] of INDEXES) {\n await retryOnDdlRace(() => client.execute(sql));\n }\n })().catch((error) => {\n _initPromise = undefined;\n throw error;\n });\n }\n return _initPromise;\n}\n\nfunction required(value: string, name: string): string {\n const normalized = value.trim();\n if (!normalized) throw new Error(`${name} is required`);\n if (normalized.length > 512) throw new Error(`${name} is too long`);\n return normalized;\n}\n\nfunction normalizePlatform(value: string): string {\n return required(value, \"platform\").toLowerCase();\n}\n\nfunction normalizeEmail(value: string): string {\n return required(value, \"ownerEmail\").toLowerCase();\n}\n\nfunction normalizeScopes(scopes: readonly string[] | undefined): string[] {\n return Array.from(\n new Set(\n (scopes ?? [])\n .map((scope) => scope.trim())\n .filter(Boolean)\n .sort(),\n ),\n );\n}\n\nfunction parseScopes(value: unknown): string[] {\n if (typeof value !== \"string\") return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) &&\n parsed.every((item) => typeof item === \"string\")\n ? parsed\n : [];\n } catch {\n return [];\n }\n}\n\nfunction toBoolean(value: unknown): boolean {\n return value === true || value === 1 || value === \"1\" || value === \"true\";\n}\n\nfunction nullableNumber(value: unknown): number | null {\n return value == null ? null : Number(value);\n}\n\nfunction rowToRaw(row: Record<string, unknown>): RawInstallation {\n return {\n id: String(row.id),\n platform: String(row.platform),\n installationKey: String(row.installation_key),\n teamId: (row.team_id as string | null) ?? null,\n teamName: (row.team_name as string | null) ?? null,\n enterpriseId: (row.enterprise_id as string | null) ?? null,\n enterpriseName: (row.enterprise_name as string | null) ?? null,\n isEnterpriseInstall: toBoolean(row.is_enterprise_install),\n apiAppId: (row.api_app_id as string | null) ?? null,\n botUserId: (row.bot_user_id as string | null) ?? null,\n scopes: parseScopes(row.scopes_json),\n installedByExternalUserId:\n (row.installed_by_external_user_id as string | null) ?? null,\n ownerEmail: String(row.owner_email),\n orgId: (row.org_id as string | null) ?? null,\n tokenSecretKey: String(row.token_secret_key),\n secretScope: row.secret_scope as SecretScope,\n secretScopeId: String(row.secret_scope_id),\n status: row.status as IntegrationInstallationStatus,\n health: row.health as IntegrationInstallationHealth,\n lastError: (row.last_error as string | null) ?? null,\n healthCheckedAt: nullableNumber(row.health_checked_at),\n lastHealthyAt: nullableNumber(row.last_healthy_at),\n tokenExpiresAt: nullableNumber(row.token_expires_at),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n disconnectedAt: nullableNumber(row.disconnected_at),\n };\n}\n\nfunction toSafeInstallation(row: RawInstallation): IntegrationInstallation {\n const {\n tokenSecretKey: _tokenSecretKey,\n secretScope: _scope,\n secretScopeId: _scopeId,\n ...safe\n } = row;\n return safe;\n}\n\nfunction tokenSecretKey(platform: string, installationKey: string): string {\n const digest = createHash(\"sha256\")\n .update(`${platform}\\0${installationKey}`)\n .digest(\"hex\")\n .slice(0, 32);\n return `integration:${platform}:${digest}:oauth-token-bundle`;\n}\n\nfunction sameOwner(a: string, b: string): boolean {\n return a.trim().toLowerCase() === b.trim().toLowerCase();\n}\n\nfunction sameScope(\n row: Pick<RawInstallation, \"ownerEmail\" | \"orgId\">,\n ownerEmail: string,\n orgId: string | null,\n): boolean {\n if (row.orgId || orgId) return !!row.orgId && row.orgId === orgId;\n return sameOwner(row.ownerEmail, ownerEmail);\n}\n\nfunction canMutate(row: RawInstallation, actor: InstallationActor): boolean {\n if (row.orgId) {\n return actor.orgId === row.orgId && actor.isOrgAdmin === true;\n }\n return sameOwner(row.ownerEmail, actor.userEmail);\n}\n\nasync function selectRawById(id: string): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function selectRawByKey(\n platform: string,\n installationKey: string,\n): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE platform = ? AND installation_key = ? LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(installationKey, \"installationKey\"),\n ],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\n/**\n * Create or refresh a managed install. Re-installs may rotate tokens inside\n * the same owner/org scope, but cannot silently move an existing provider\n * installation into another Agent Native tenant.\n */\nexport async function upsertIntegrationInstallation(\n input: UpsertIntegrationInstallationInput,\n): Promise<IntegrationInstallation> {\n await ensureTable();\n const platform = normalizePlatform(input.platform);\n const installationKey = required(input.installationKey, \"installationKey\");\n const ownerEmail = normalizeEmail(input.ownerEmail);\n const orgId = input.orgId?.trim() || null;\n const secretScopeId = required(input.secretScopeId, \"secretScopeId\");\n const accessToken = input.tokenBundle.accessToken?.trim();\n if (!accessToken) throw new Error(\"tokenBundle.accessToken is required\");\n\n const existing = await selectRawByKey(platform, installationKey);\n if (existing && !sameScope(existing, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n const secretKey =\n existing?.tokenSecretKey ?? tokenSecretKey(platform, installationKey);\n const persistTokenBundle = (key: string) =>\n writeAppSecret({\n key,\n value: JSON.stringify(input.tokenBundle),\n scope: input.secretScope,\n scopeId: secretScopeId,\n description: `${platform} OAuth token bundle for a managed installation`,\n });\n await persistTokenBundle(secretKey);\n\n const now = Date.now();\n let id = existing?.id ?? randomUUID();\n const scopesJson = JSON.stringify(normalizeScopes(input.scopes));\n const tokenExpiresAt =\n input.tokenExpiresAt ?? input.tokenBundle.expiresAt ?? null;\n\n const updateExisting = async (rowId: string, rowSecretKey: string) => {\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET\n team_id = ?, team_name = ?, enterprise_id = ?, enterprise_name = ?,\n is_enterprise_install = ?, api_app_id = ?, bot_user_id = ?, scopes_json = ?,\n installed_by_external_user_id = ?, owner_email = ?, org_id = ?,\n token_secret_key = ?, secret_scope = ?, secret_scope_id = ?, status = ?,\n health = ?, last_error = ?, health_checked_at = ?, last_healthy_at = ?,\n token_expires_at = ?, updated_at = ?, disconnected_at = ?\n WHERE id = ?`,\n args: [\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n rowSecretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n null,\n rowId,\n ],\n });\n };\n\n if (existing) {\n await updateExisting(existing.id, existing.tokenSecretKey);\n } else {\n try {\n await getDbExec().execute({\n sql: `INSERT INTO ${TABLE} (\n id, platform, installation_key, team_id, team_name, enterprise_id,\n enterprise_name, is_enterprise_install, api_app_id, bot_user_id,\n scopes_json, installed_by_external_user_id, owner_email, org_id,\n token_secret_key, secret_scope, secret_scope_id, status, health,\n last_error, health_checked_at, last_healthy_at, token_expires_at,\n created_at, updated_at, disconnected_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n platform,\n installationKey,\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n secretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n now,\n null,\n ],\n });\n } catch (error) {\n if (!isUniqueViolation(error)) throw error;\n\n const raced = await selectRawByKey(platform, installationKey);\n if (!raced) throw error;\n if (!sameScope(raced, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n id = raced.id;\n if (raced.tokenSecretKey !== secretKey) {\n await persistTokenBundle(raced.tokenSecretKey);\n }\n await updateExisting(raced.id, raced.tokenSecretKey);\n }\n }\n\n const stored = await selectRawById(id);\n if (!stored) throw new Error(\"Managed installation was not persisted\");\n return toSafeInstallation(stored);\n}\n\n/** List installations visible to the owner or active organization member. */\nexport async function listIntegrationInstallations(\n actor: InstallationActor,\n platform?: string,\n): Promise<IntegrationInstallation[]> {\n await ensureTable();\n const ownerEmail = normalizeEmail(actor.userEmail);\n const args: unknown[] = [ownerEmail];\n let visibility = \"owner_email = ?\";\n if (actor.orgId) {\n visibility = `(owner_email = ? OR org_id = ?)`;\n args.push(actor.orgId);\n }\n let platformFilter = \"\";\n if (platform) {\n platformFilter = \" AND platform = ?\";\n args.push(normalizePlatform(platform));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE ${visibility}${platformFilter} ORDER BY updated_at DESC`,\n args,\n });\n return rows.map((row) =>\n toSafeInstallation(rowToRaw(row as Record<string, unknown>)),\n );\n}\n\n/** Read one installation through owner/org visibility scoping. */\nexport async function getIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (\n !sameOwner(row.ownerEmail, actor.userEmail) &&\n (!row.orgId || row.orgId !== actor.orgId)\n ) {\n return null;\n }\n return toSafeInstallation(row);\n}\n\n/** Update non-secret installation metadata after an owner/admin access check. */\nexport async function updateIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n patch: IntegrationInstallationUpdate,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to update this installation.\");\n }\n const next = {\n teamName: patch.teamName === undefined ? row.teamName : patch.teamName,\n enterpriseName:\n patch.enterpriseName === undefined\n ? row.enterpriseName\n : patch.enterpriseName,\n botUserId: patch.botUserId === undefined ? row.botUserId : patch.botUserId,\n scopes:\n patch.scopes === undefined ? row.scopes : normalizeScopes(patch.scopes),\n status: patch.status ?? row.status,\n health: patch.health ?? row.health,\n lastError: patch.lastError === undefined ? row.lastError : patch.lastError,\n healthCheckedAt:\n patch.healthCheckedAt === undefined\n ? row.healthCheckedAt\n : patch.healthCheckedAt,\n lastHealthyAt:\n patch.lastHealthyAt === undefined\n ? row.lastHealthyAt\n : patch.lastHealthyAt,\n tokenExpiresAt:\n patch.tokenExpiresAt === undefined\n ? row.tokenExpiresAt\n : patch.tokenExpiresAt,\n };\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET team_name = ?, enterprise_name = ?, bot_user_id = ?,\n scopes_json = ?, status = ?, health = ?, last_error = ?, health_checked_at = ?,\n last_healthy_at = ?, token_expires_at = ?, updated_at = ? WHERE id = ?`,\n args: [\n next.teamName,\n next.enterpriseName,\n next.botUserId,\n JSON.stringify(next.scopes),\n next.status,\n next.health,\n next.lastError,\n next.healthCheckedAt,\n next.lastHealthyAt,\n next.tokenExpiresAt,\n Date.now(),\n id,\n ],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/** Delete the encrypted token bundle and retain disconnected audit metadata. */\nexport async function disconnectIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to disconnect this installation.\");\n }\n await deleteAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET status = 'disconnected', health = 'unknown',\n last_error = NULL, token_expires_at = NULL, disconnected_at = ?, updated_at = ?\n WHERE id = ?`,\n args: [now, now, id],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/**\n * Resolve credentials for a verified provider webhook/runtime path.\n *\n * This is intentionally separate from every user-facing list/read helper.\n * Callers must first authenticate the provider webhook (or run inside a\n * trusted OAuth callback) and must never log or return the result.\n */\nexport async function resolveIntegrationTokenBundle(\n platform: string,\n installationKey: string,\n): Promise<IntegrationTokenBundle | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\" || row.health === \"revoked\")\n return null;\n const secret = await readAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n if (!secret) return null;\n try {\n const parsed = JSON.parse(secret.value) as Partial<IntegrationTokenBundle>;\n if (typeof parsed.accessToken !== \"string\" || !parsed.accessToken)\n return null;\n return parsed as IntegrationTokenBundle;\n } catch {\n return null;\n }\n}\n\n/** Safe metadata lookup for a verified provider event. */\nexport async function getActiveIntegrationInstallationByKey(\n platform: string,\n installationKey: string,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\") return null;\n return toSafeInstallation(row);\n}\n\n/** Resolve a connected installation by workspace or enterprise tenant id. */\nexport async function getActiveIntegrationInstallationForTenant(\n platform: string,\n tenantId: string,\n): Promise<IntegrationInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE}\n WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)\n AND status = 'connected'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(tenantId, \"tenantId\"),\n required(tenantId, \"tenantId\"),\n ],\n });\n return rows[0]\n ? toSafeInstallation(rowToRaw(rows[0] as Record<string, unknown>))\n : null;\n}\n\n/**\n * Every connected installation for a tenant, newest first.\n *\n * A workspace can legitimately have several apps of the same platform\n * connected at once (e.g. a product-specific Slack app alongside a generic\n * one). Callers that cannot name an app id must see that ambiguity rather\n * than receive an arbitrary winner — picking the most recently updated row\n * silently sends as whichever app happened to reconnect last.\n */\nexport async function listActiveIntegrationInstallationsForTenant(\n platform: string,\n tenantId: string,\n): Promise<IntegrationInstallation[]> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE}\n WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)\n AND status = 'connected'\n ORDER BY updated_at DESC`,\n args: [\n normalizePlatform(platform),\n required(tenantId, \"tenantId\"),\n required(tenantId, \"tenantId\"),\n ],\n });\n return rows.map((row) =>\n toSafeInstallation(rowToRaw(row as Record<string, unknown>)),\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"AA6CA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/integrations/plugin.ts"],"names":[],"mappings":"AA6CA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AA0HzD,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EAK1B,MAAM,YAAY,CAAC;AAYpB,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAyM9D,eAAO,MAAM,sCAAsC;uBACrC,OAAO;;;uBACP,UAAU;;;uBACV,UAAU;;;uBACV,iBAAiB;;;uBACjB,SAAS;;;uBACT,aAAa;;;uBACb,OAAO;;EAIlB,CAAC;AAEJ,eAAO,MAAM,gCAAgC,0GAE5C,CAAC;AAEF,wBAAgB,gCAAgC,IAAI,eAAe,EAAE,CAEpE;AAUD,KAAK,yBAAyB,GAAG;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAgCF,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsFlC;AAmOD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,CAAC,EAAE,yBAAyB,GAClC,cAAc,CAwnFhB;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,gBAA6B,CAAC"}
|
|
@@ -32,7 +32,7 @@ import { IntegrationIdentityDeclinedError, resolveDefaultIntegrationExecutionCon
|
|
|
32
32
|
import { disconnectIntegrationInstallation, listIntegrationInstallations, resolveIntegrationTokenBundle, updateIntegrationInstallation, upsertIntegrationInstallation, } from "./installations-store.js";
|
|
33
33
|
import { recoverDueIntegrationCampaigns } from "./integration-campaign-recovery.js";
|
|
34
34
|
import { claimIntegrationCampaignDeliveryForTask, completeIntegrationCampaignTaskAfterA2A, completeIntegrationCampaignTask, failIntegrationCampaignTaskDeliveryContainment, failDisabledIntegrationCampaignTask, failIntegrationCampaign, refreshIntegrationCampaignTaskA2AReceiptRetry, terminalizeIntegrationCampaignForTask, transitionIntegrationCampaignTaskToA2AReceiptRetry, transitionIntegrationCampaignTaskToDeliveryRetry, waitForA2AIntegrationCampaign, } from "./integration-campaigns-store.js";
|
|
35
|
-
import { dispatchPendingIntegrationTask, INTEGRATION_CAMPAIGN_PROCESSOR_FIELD, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, integrationDispatchScopeValue, isInIntegrationRecoveryRuntime,
|
|
35
|
+
import { dispatchPendingIntegrationTask, INTEGRATION_CAMPAIGN_PROCESSOR_FIELD, INTEGRATION_RETRY_SWEEP_TOKEN_SUBJECT, integrationDispatchScopeValue, isInIntegrationRecoveryRuntime, isIntegrationDurableDispatchEnabledForTask, } from "./integration-durable-dispatch.js";
|
|
36
36
|
import { forgetIntegrationMemory, integrationMemoryActions, listIntegrationMemory, rememberForIntegrationScope, } from "./integration-memory.js";
|
|
37
37
|
import { extractBearerToken, verifyInternalToken } from "./internal-token.js";
|
|
38
38
|
import { retryStuckPendingTasks, startPendingTasksRetryJob, } from "./pending-tasks-retry-job.js";
|
|
@@ -1372,15 +1372,16 @@ export function createIntegrationsPlugin(options) {
|
|
|
1372
1372
|
setResponseStatus(event, 401);
|
|
1373
1373
|
return { error: "Invalid or expired internal token" };
|
|
1374
1374
|
}
|
|
1375
|
-
if (!isIntegrationDurableDispatchConfigured()) {
|
|
1376
|
-
return { ok: true, disabled: true };
|
|
1377
|
-
}
|
|
1378
1375
|
const webhookBaseUrl = getBaseUrl(event);
|
|
1379
1376
|
const [pendingTasks, campaigns, a2aContinuations] = await Promise.all([
|
|
1377
|
+
// Portable (fire-and-forget) dispatch loses tasks whenever the
|
|
1378
|
+
// self-dispatch POST dies with the container, and the in-process
|
|
1379
|
+
// retry interval does not survive a serverless freeze. Sweeping only
|
|
1380
|
+
// durable scopes left those deployments with no recovery at all, so
|
|
1381
|
+
// the queue is swept regardless of dispatch mode.
|
|
1380
1382
|
retryStuckPendingTasks({
|
|
1381
1383
|
webhookBaseUrl,
|
|
1382
1384
|
limit: 20,
|
|
1383
|
-
durableOnly: true,
|
|
1384
1385
|
}).catch((error) => {
|
|
1385
1386
|
console.error("[integrations] Pending-task recovery failed:", error);
|
|
1386
1387
|
return { error: "pending-task-recovery-failed" };
|