@agent-native/core 0.114.16 → 0.115.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +2 -0
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +41 -0
- package/corpus/core/agent-native.eject.json +2 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +16 -0
- package/corpus/core/docs/content/recurring-jobs.mdx +35 -6
- package/corpus/core/export-snapshot.json +4 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/action.ts +22 -1
- package/corpus/core/src/agent/production-agent.ts +122 -3
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +19 -2
- package/corpus/core/src/cli/templates-meta.ts +12 -0
- package/corpus/core/src/client/AssistantChat.tsx +53 -26
- package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +19 -0
- package/corpus/core/src/client/agent-page/use-jobs.ts +1 -0
- package/corpus/core/src/client/blocks/library/wireframe.tsx +3 -1
- package/corpus/core/src/client/chat/message-components.tsx +35 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +38 -3
- package/corpus/core/src/connections/catalog.ts +20 -1
- package/corpus/core/src/connections/reader.ts +65 -0
- package/corpus/core/src/dashboard-storage/index.ts +27 -0
- package/corpus/core/src/dashboard-storage/panel-source.ts +168 -0
- package/corpus/core/src/dashboard-storage/schema.ts +62 -0
- package/corpus/core/src/dashboard-storage/store.ts +333 -0
- package/corpus/core/src/deploy/build.ts +95 -16
- package/corpus/core/src/eject/provider-api-definitions.ts +1 -0
- package/corpus/core/src/eject/workspace-connections.ts +1 -0
- package/corpus/core/src/extensions/actions.ts +199 -73
- package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +2 -0
- package/corpus/core/src/jobs/scheduler.ts +71 -4
- package/corpus/core/src/jobs/tools.ts +31 -1
- package/corpus/core/src/localization/default-messages.ts +1 -0
- package/corpus/core/src/mcp-client/index.ts +6 -0
- package/corpus/core/src/provider-api/actions/provider-api.ts +1 -1
- package/corpus/core/src/provider-api/index.ts +190 -5
- package/corpus/core/src/secrets/register-framework-secrets.ts +8 -0
- package/corpus/core/src/server/agent-chat/context-tools.ts +9 -0
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +22 -2
- package/corpus/core/src/server/core-routes-plugin.ts +1 -0
- package/corpus/core/src/server/credential-provider.ts +9 -3
- package/corpus/core/src/server/workspace-provider-oauth.ts +181 -4
- package/corpus/core/src/styles/agent-native.css +45 -2
- package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/corpus/core/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/corpus/core/src/triggers/actions.ts +11 -2
- package/corpus/core/src/triggers/dispatcher.ts +20 -1
- package/corpus/core/src/triggers/types.ts +5 -0
- package/corpus/core/src/vite/action-types-plugin.ts +9 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/analytics/AGENTS.md +11 -11
- package/corpus/templates/analytics/_gitignore +39 -0
- package/corpus/templates/analytics/actions/query-dashboard-panel.ts +30 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +2 -1
- package/corpus/templates/analytics/app/lib/sql-query.ts +11 -25
- package/corpus/templates/analytics/changelog/2026-07-21-fixed-extension-updates-failing-before-changes-could-be-appl.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +1 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +51 -0
- package/corpus/templates/analytics/server/lib/prometheus.ts +1 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/calendar/_gitignore +39 -0
- package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/templates/chat/AGENTS.md +1 -1
- package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/clips/AGENTS.md +7 -0
- package/corpus/templates/clips/actions/prepare-crm-call-evidence.ts +58 -0
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +88 -11
- package/corpus/templates/clips/changelog/2026-07-21-crm-call-evidence-handoff.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-21-recording-retries-and-restarts-keep-their-upload-session-so-.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +20 -5
- package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +19 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +9 -0
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +54 -28
- package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/content/_gitignore +39 -0
- package/corpus/templates/content/learnings.defaults.md +5 -0
- package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +133 -0
- package/corpus/templates/crm/.agents/skills/crm/SKILL.md +128 -0
- package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +145 -0
- package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
- package/corpus/templates/crm/.env.example +5 -0
- package/corpus/templates/crm/AGENTS.md +120 -0
- package/corpus/templates/crm/CHANGELOG.md +1 -0
- package/corpus/templates/crm/DEVELOPING.md +66 -0
- package/corpus/templates/crm/README.md +106 -0
- package/corpus/templates/crm/_gitignore +12 -0
- package/corpus/templates/crm/actions/_crm-action-utils.ts +87 -0
- package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
- package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
- package/corpus/templates/crm/actions/apply-crm-proposals.ts +203 -0
- package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
- package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
- package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
- package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
- package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
- package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
- package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
- package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +33 -0
- package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
- package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
- package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
- package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
- package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
- package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-proposals.ts +31 -0
- package/corpus/templates/crm/actions/list-crm-records.ts +79 -0
- package/corpus/templates/crm/actions/list-crm-saved-views.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
- package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
- package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
- package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
- package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
- package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
- package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
- package/corpus/templates/crm/actions/navigate.ts +63 -0
- package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
- package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
- package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
- package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
- package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
- package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
- package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
- package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
- package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
- package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +275 -0
- package/corpus/templates/crm/actions/run.ts +11 -0
- package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
- package/corpus/templates/crm/actions/save-crm-saved-view.ts +119 -0
- package/corpus/templates/crm/actions/sync-crm.ts +146 -0
- package/corpus/templates/crm/actions/update-crm-record.ts +508 -0
- package/corpus/templates/crm/actions/view-screen.ts +218 -0
- package/corpus/templates/crm/agent-native.app-skill.json +58 -0
- package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
- package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +83 -0
- package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +225 -0
- package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +413 -0
- package/corpus/templates/crm/app/components/crm/RecordActions.tsx +510 -0
- package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +134 -0
- package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +367 -0
- package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +92 -0
- package/corpus/templates/crm/app/components/crm/Surface.tsx +96 -0
- package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +106 -0
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +84 -0
- package/corpus/templates/crm/app/entry.client.tsx +16 -0
- package/corpus/templates/crm/app/entry.server.tsx +10 -0
- package/corpus/templates/crm/app/global.css +167 -0
- package/corpus/templates/crm/app/hooks/use-navigation-state.ts +60 -0
- package/corpus/templates/crm/app/i18n/en-US.ts +89 -0
- package/corpus/templates/crm/app/i18n/index.ts +34 -0
- package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
- package/corpus/templates/crm/app/lib/navigation.ts +54 -0
- package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
- package/corpus/templates/crm/app/lib/types.ts +172 -0
- package/corpus/templates/crm/app/lib/utils.ts +1 -0
- package/corpus/templates/crm/app/root.tsx +88 -0
- package/corpus/templates/crm/app/routes/_index.tsx +26 -0
- package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
- package/corpus/templates/crm/app/routes/agent.tsx +5 -0
- package/corpus/templates/crm/app/routes/ask.tsx +53 -0
- package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
- package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
- package/corpus/templates/crm/app/routes/people.tsx +41 -0
- package/corpus/templates/crm/app/routes/proposals.tsx +266 -0
- package/corpus/templates/crm/app/routes/records.$recordId.tsx +35 -0
- package/corpus/templates/crm/app/routes/settings.tsx +63 -0
- package/corpus/templates/crm/app/routes/setup.tsx +308 -0
- package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
- package/corpus/templates/crm/app/routes/views.tsx +333 -0
- package/corpus/templates/crm/app/routes.ts +17 -0
- package/corpus/templates/crm/app/vite-env.d.ts +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +6 -0
- package/corpus/templates/crm/components.json +20 -0
- package/corpus/templates/crm/docs/architecture/crm-contract.md +180 -0
- package/corpus/templates/crm/learnings.defaults.md +5 -0
- package/corpus/templates/crm/package.json +59 -0
- package/corpus/templates/crm/public/favicon.svg +1 -0
- package/corpus/templates/crm/public/icon-180.svg +1 -0
- package/corpus/templates/crm/public/manifest.json +11 -0
- package/corpus/templates/crm/react-router.config.ts +7 -0
- package/corpus/templates/crm/server/crm/adapter.ts +32 -0
- package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
- package/corpus/templates/crm/server/crm/crm-mirror.ts +711 -0
- package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1143 -0
- package/corpus/templates/crm/server/crm/native-adapter.ts +1715 -0
- package/corpus/templates/crm/server/crm/read-through.ts +207 -0
- package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
- package/corpus/templates/crm/server/db/crm-store.ts +1170 -0
- package/corpus/templates/crm/server/db/index.ts +169 -0
- package/corpus/templates/crm/server/db/schema.ts +441 -0
- package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
- package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
- package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +100 -0
- package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +144 -0
- package/corpus/templates/crm/server/lib/intelligence/summary.ts +141 -0
- package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
- package/corpus/templates/crm/server/middleware/auth.ts +4 -0
- package/corpus/templates/crm/server/plugins/agent-chat.ts +68 -0
- package/corpus/templates/crm/server/plugins/auth.ts +14 -0
- package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
- package/corpus/templates/crm/server/plugins/db.ts +454 -0
- package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
- package/corpus/templates/crm/shared/crm-contract.ts +254 -0
- package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
- package/corpus/templates/crm/ssr-entry.ts +11 -0
- package/corpus/templates/crm/tsconfig.json +24 -0
- package/corpus/templates/crm/vite.config.ts +15 -0
- package/corpus/templates/crm/vitest.config.ts +5 -0
- package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/forms/_gitignore +39 -0
- package/corpus/templates/forms/learnings.defaults.md +5 -0
- package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/macros/_gitignore +39 -0
- package/corpus/templates/macros/learnings.defaults.md +5 -0
- package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/mail/_gitignore +39 -0
- package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +19 -2
- package/corpus/templates/plan/AGENTS.md +10 -0
- package/corpus/templates/plan/actions/create-prototype-plan.ts +27 -3
- package/corpus/templates/plan/actions/get-plan-blocks.ts +1 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +3 -2
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +18 -4
- package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +10 -3
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +3 -1
- package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
- package/corpus/templates/plan/app/lib/create-plan-routing.ts +39 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +31 -107
- package/corpus/templates/plan/changelog/2026-07-22-high-fidelity-mockup-requests-now-preserve-branded-css-use-d.md +6 -0
- package/corpus/templates/plan/shared/plan-content.ts +110 -2
- package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/slides/_gitignore +39 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/templates/tasks/_gitignore +39 -0
- package/corpus/toolkit/CHANGELOG.md +12 -0
- package/corpus/toolkit/README.md +30 -0
- package/corpus/toolkit/agent-native.eject.json +33 -0
- package/corpus/toolkit/package.json +15 -1
- package/corpus/toolkit/src/dashboard/DataTable.tsx +273 -0
- package/corpus/toolkit/src/dashboard/DateRangePicker.tsx +57 -0
- package/corpus/toolkit/src/dashboard/GenericChartPanel.tsx +461 -0
- package/corpus/toolkit/src/dashboard/MetricCard.tsx +54 -0
- package/corpus/toolkit/src/dashboard/StatsCard.tsx +49 -0
- package/corpus/toolkit/src/dashboard/dashboard-layout.ts +329 -0
- package/corpus/toolkit/src/dashboard/index.ts +6 -0
- package/corpus/toolkit/src/index.ts +1 -0
- package/corpus/toolkit/src/ui/calendar.tsx +8 -8
- package/corpus/toolkit/src/ui/date-picker.tsx +4 -1
- package/dist/action.d.ts +14 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +3 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +97 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js +19 -2
- package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +12 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +4 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +30 -17
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.js +3 -1
- package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +1 -0
- package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
- package/dist/client/agent-page/use-jobs.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +3 -2
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +5 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +17 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +3 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +17 -7
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +17 -3
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +16 -1
- package/dist/connections/catalog.js.map +1 -1
- package/dist/connections/reader.d.ts +18 -0
- package/dist/connections/reader.d.ts.map +1 -1
- package/dist/connections/reader.js +41 -0
- package/dist/connections/reader.js.map +1 -1
- package/dist/dashboard-storage/index.d.ts +4 -0
- package/dist/dashboard-storage/index.d.ts.map +1 -0
- package/dist/dashboard-storage/index.js +4 -0
- package/dist/dashboard-storage/index.js.map +1 -0
- package/dist/dashboard-storage/panel-source.d.ts +68 -0
- package/dist/dashboard-storage/panel-source.d.ts.map +1 -0
- package/dist/dashboard-storage/panel-source.js +76 -0
- package/dist/dashboard-storage/panel-source.js.map +1 -0
- package/dist/dashboard-storage/schema.d.ts +562 -0
- package/dist/dashboard-storage/schema.d.ts.map +1 -0
- package/dist/dashboard-storage/schema.js +32 -0
- package/dist/dashboard-storage/schema.js.map +1 -0
- package/dist/dashboard-storage/store.d.ts +62 -0
- package/dist/dashboard-storage/store.d.ts.map +1 -0
- package/dist/dashboard-storage/store.js +227 -0
- package/dist/dashboard-storage/store.js.map +1 -0
- package/dist/deploy/build.d.ts +7 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +78 -14
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/provider-api-definitions.d.ts +2 -1
- package/dist/eject/provider-api-definitions.d.ts.map +1 -1
- package/dist/eject/provider-api-definitions.js +1 -0
- package/dist/eject/provider-api-definitions.js.map +1 -1
- package/dist/eject/workspace-connections.d.ts.map +1 -1
- package/dist/eject/workspace-connections.js +1 -0
- package/dist/eject/workspace-connections.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +165 -67
- package/dist/extensions/actions.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/actions/list-recurring-jobs.d.ts +1 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
- package/dist/jobs/actions/list-recurring-jobs.js +1 -0
- package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
- package/dist/jobs/scheduler.d.ts +17 -2
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +51 -2
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +32 -2
- package/dist/jobs/tools.js.map +1 -1
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +1 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/index.d.ts +2 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +5 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +8 -6
- package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
- package/dist/provider-api/actions/provider-api.js +1 -1
- package/dist/provider-api/actions/provider-api.js.map +1 -1
- package/dist/provider-api/index.d.ts +11 -7
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +143 -5
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +7 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
- package/dist/server/agent-chat/context-tools.js +9 -0
- package/dist/server/agent-chat/context-tools.js.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +18 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +1 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +4 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +9 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.d.ts.map +1 -1
- package/dist/server/workspace-provider-oauth.js +141 -4
- package/dist/server/workspace-provider-oauth.js.map +1 -1
- package/dist/styles/agent-native.css +45 -2
- package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/chat/AGENTS.md +1 -1
- package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/dist/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +10 -2
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +15 -0
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/triggers/types.d.ts +5 -0
- package/dist/triggers/types.d.ts.map +1 -1
- package/dist/triggers/types.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +4 -1
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +16 -0
- package/docs/content/recurring-jobs.mdx +35 -6
- package/package.json +7 -3
- package/src/action.ts +22 -1
- package/src/agent/production-agent.ts +122 -3
- package/src/cli/skills-content/visual-plan-skill.ts +19 -2
- package/src/cli/templates-meta.ts +12 -0
- package/src/client/AssistantChat.tsx +53 -26
- package/src/client/agent-page/AgentJobsTab.tsx +19 -0
- package/src/client/agent-page/use-jobs.ts +1 -0
- package/src/client/blocks/library/wireframe.tsx +3 -1
- package/src/client/chat/message-components.tsx +35 -1
- package/src/client/chat/tool-call-display.tsx +38 -3
- package/src/connections/catalog.ts +20 -1
- package/src/connections/reader.ts +65 -0
- package/src/dashboard-storage/index.ts +27 -0
- package/src/dashboard-storage/panel-source.ts +168 -0
- package/src/dashboard-storage/schema.ts +62 -0
- package/src/dashboard-storage/store.ts +333 -0
- package/src/deploy/build.ts +95 -16
- package/src/eject/provider-api-definitions.ts +1 -0
- package/src/eject/workspace-connections.ts +1 -0
- package/src/extensions/actions.ts +199 -73
- package/src/jobs/actions/list-recurring-jobs.ts +2 -0
- package/src/jobs/scheduler.ts +71 -4
- package/src/jobs/tools.ts +31 -1
- package/src/localization/default-messages.ts +1 -0
- package/src/mcp-client/index.ts +6 -0
- package/src/provider-api/actions/provider-api.ts +1 -1
- package/src/provider-api/index.ts +190 -5
- package/src/secrets/register-framework-secrets.ts +8 -0
- package/src/server/agent-chat/context-tools.ts +9 -0
- package/src/server/agent-chat/framework-prompts.ts +2 -2
- package/src/server/agent-chat-plugin.ts +22 -2
- package/src/server/core-routes-plugin.ts +1 -0
- package/src/server/credential-provider.ts +9 -3
- package/src/server/workspace-provider-oauth.ts +181 -4
- package/src/styles/agent-native.css +45 -2
- package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/chat/AGENTS.md +1 -1
- package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/src/triggers/actions.ts +11 -2
- package/src/triggers/dispatcher.ts +20 -1
- package/src/triggers/types.ts +5 -0
- package/src/vite/action-types-plugin.ts +9 -1
- package/corpus/templates/analytics/server/handlers/sql-query.ts +0 -36
- package/corpus/templates/analytics/server/routes/api/sql-query.post.ts +0 -1
|
@@ -14,6 +14,7 @@ const SUPPORTED_PROVIDERS = new Set([
|
|
|
14
14
|
"google_drive",
|
|
15
15
|
"github",
|
|
16
16
|
"hubspot",
|
|
17
|
+
"salesforce",
|
|
17
18
|
"jira",
|
|
18
19
|
"sentry",
|
|
19
20
|
"notion",
|
|
@@ -21,6 +22,8 @@ const SUPPORTED_PROVIDERS = new Set([
|
|
|
21
22
|
const FLOW_TTL_SECONDS = 10 * 60;
|
|
22
23
|
const PROVIDER_REQUEST_TIMEOUT_MS = 10_000;
|
|
23
24
|
const PROVIDER_RESPONSE_MAX_BYTES = 256 * 1024;
|
|
25
|
+
const SALESFORCE_PRODUCTION_LOGIN_URL = "https://login.salesforce.com";
|
|
26
|
+
const SALESFORCE_SANDBOX_LOGIN_URL = "https://test.salesforce.com";
|
|
24
27
|
export function workspaceProviderOAuthPath(provider, phase) {
|
|
25
28
|
return `/_agent-native/connections/oauth/${provider}/${phase}`;
|
|
26
29
|
}
|
|
@@ -53,6 +56,13 @@ export async function handleWorkspaceProviderOAuthStart(event, providerId) {
|
|
|
53
56
|
}
|
|
54
57
|
const provider = requiredProvider(providerId);
|
|
55
58
|
const query = getQuery(event);
|
|
59
|
+
const salesforceLoginUrl = providerId === "salesforce"
|
|
60
|
+
? resolveSalesforceOAuthLoginUrl(text(query.environment))
|
|
61
|
+
: undefined;
|
|
62
|
+
if (providerId === "salesforce" && !salesforceLoginUrl) {
|
|
63
|
+
setResponseStatus(event, 400);
|
|
64
|
+
return { error: "Salesforce environment must be production or sandbox." };
|
|
65
|
+
}
|
|
56
66
|
const appId = normalizeAppId(text(query.appId) ??
|
|
57
67
|
process.env.AGENT_NATIVE_WORKSPACE_APP_ID ??
|
|
58
68
|
process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID ??
|
|
@@ -96,6 +106,7 @@ export async function handleWorkspaceProviderOAuthStart(event, providerId) {
|
|
|
96
106
|
owner: session.email,
|
|
97
107
|
orgId,
|
|
98
108
|
appId,
|
|
109
|
+
...(salesforceLoginUrl ? { salesforceLoginUrl } : {}),
|
|
99
110
|
expiresAt: Date.now() + FLOW_TTL_SECONDS * 1_000,
|
|
100
111
|
};
|
|
101
112
|
setCookie(event, flowCookieName(providerId), encryptSecretValue(JSON.stringify(flow)), {
|
|
@@ -111,6 +122,11 @@ export async function handleWorkspaceProviderOAuthStart(event, providerId) {
|
|
|
111
122
|
redirectUri,
|
|
112
123
|
state,
|
|
113
124
|
challenge,
|
|
125
|
+
...(salesforceLoginUrl
|
|
126
|
+
? {
|
|
127
|
+
authorizationUrl: salesforceOAuthEndpoint(salesforceLoginUrl, "authorize"),
|
|
128
|
+
}
|
|
129
|
+
: {}),
|
|
114
130
|
});
|
|
115
131
|
return Response.redirect(authorizationUrl, 302);
|
|
116
132
|
});
|
|
@@ -177,6 +193,11 @@ export async function handleWorkspaceProviderOAuthCallback(event, providerId) {
|
|
|
177
193
|
code,
|
|
178
194
|
verifier: flow.verifier,
|
|
179
195
|
redirectUri: flow.redirectUri,
|
|
196
|
+
...(providerId === "salesforce"
|
|
197
|
+
? {
|
|
198
|
+
tokenUrl: salesforceOAuthEndpoint(flow.salesforceLoginUrl ?? SALESFORCE_PRODUCTION_LOGIN_URL, "token"),
|
|
199
|
+
}
|
|
200
|
+
: {}),
|
|
180
201
|
});
|
|
181
202
|
const identities = await resolveWorkspaceProviderIdentities(providerId, tokens);
|
|
182
203
|
if (!identities.length) {
|
|
@@ -194,10 +215,17 @@ export async function handleWorkspaceProviderOAuthCallback(event, providerId) {
|
|
|
194
215
|
const scopes = mergeWorkspaceOAuthValues(existing?.scopes ?? [], identity.scopes ?? tokenScopes(tokens, provider.oauth.scopes));
|
|
195
216
|
const connectionConfig = {
|
|
196
217
|
credentialMode: "oauth",
|
|
197
|
-
...(providerId === "hubspot" ||
|
|
218
|
+
...(providerId === "hubspot" ||
|
|
219
|
+
providerId === "salesforce" ||
|
|
220
|
+
providerId === "jira"
|
|
198
221
|
? { externalAccountId: identity.accountId }
|
|
199
222
|
: {}),
|
|
200
223
|
...(identity.config ?? {}),
|
|
224
|
+
...(providerId === "salesforce"
|
|
225
|
+
? {
|
|
226
|
+
salesforceLoginUrl: flow.salesforceLoginUrl ?? SALESFORCE_PRODUCTION_LOGIN_URL,
|
|
227
|
+
}
|
|
228
|
+
: {}),
|
|
201
229
|
};
|
|
202
230
|
const connection = await upsertWorkspaceConnection({
|
|
203
231
|
...(existing ? { id: existing.id } : {}),
|
|
@@ -228,7 +256,7 @@ export async function handleWorkspaceProviderOAuthCallback(event, providerId) {
|
|
|
228
256
|
export function buildWorkspaceProviderAuthorizationUrl(input) {
|
|
229
257
|
if (!input.provider.oauth)
|
|
230
258
|
throw new Error("Provider does not support OAuth.");
|
|
231
|
-
const url = new URL(input.provider.oauth.authorizationUrl);
|
|
259
|
+
const url = new URL(input.authorizationUrl ?? input.provider.oauth.authorizationUrl);
|
|
232
260
|
url.searchParams.set("client_id", input.clientId);
|
|
233
261
|
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
234
262
|
url.searchParams.set("response_type", "code");
|
|
@@ -257,7 +285,7 @@ export function buildWorkspaceProviderAuthorizationUrl(input) {
|
|
|
257
285
|
return url.href;
|
|
258
286
|
}
|
|
259
287
|
export async function exchangeWorkspaceProviderOAuthCode(input) {
|
|
260
|
-
const tokenUrl = input.provider.oauth?.tokenUrl;
|
|
288
|
+
const tokenUrl = input.tokenUrl ?? input.provider.oauth?.tokenUrl;
|
|
261
289
|
if (!tokenUrl)
|
|
262
290
|
throw new Error("Provider does not support OAuth.");
|
|
263
291
|
const authorization = `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString("base64")}`;
|
|
@@ -311,6 +339,30 @@ export async function exchangeWorkspaceProviderOAuthCode(input) {
|
|
|
311
339
|
: {}),
|
|
312
340
|
};
|
|
313
341
|
}
|
|
342
|
+
if (input.providerId === "salesforce") {
|
|
343
|
+
const { response, body } = await fetchBoundedProviderJson(tokenUrl, {
|
|
344
|
+
method: "POST",
|
|
345
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
346
|
+
body: new URLSearchParams({
|
|
347
|
+
grant_type: "authorization_code",
|
|
348
|
+
client_id: input.clientId,
|
|
349
|
+
client_secret: input.clientSecret,
|
|
350
|
+
code: input.code,
|
|
351
|
+
redirect_uri: input.redirectUri,
|
|
352
|
+
}),
|
|
353
|
+
}, input.provider.label);
|
|
354
|
+
const accessToken = text(body.access_token);
|
|
355
|
+
if (!response.ok || !accessToken) {
|
|
356
|
+
throw new Error(`${input.provider.label} OAuth token exchange failed (${response.status}).`);
|
|
357
|
+
}
|
|
358
|
+
const expiresIn = Number(body.expires_in);
|
|
359
|
+
return {
|
|
360
|
+
...body,
|
|
361
|
+
...(Number.isFinite(expiresIn) && expiresIn > 0
|
|
362
|
+
? { expiry_date: Date.now() + expiresIn * 1_000 }
|
|
363
|
+
: {}),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
314
366
|
if (input.providerId === "jira") {
|
|
315
367
|
const { response, body } = await fetchBoundedProviderJsonValue(tokenUrl, {
|
|
316
368
|
method: "POST",
|
|
@@ -486,6 +538,22 @@ async function resolveWorkspaceProviderIdentitySingle(providerId, tokens) {
|
|
|
486
538
|
label: text(body.hub_domain) ?? `HubSpot portal ${accountId}`,
|
|
487
539
|
};
|
|
488
540
|
}
|
|
541
|
+
if (providerId === "salesforce") {
|
|
542
|
+
const instanceUrl = normalizeSalesforceInstanceUrl(text(tokens.instance_url));
|
|
543
|
+
const identity = parseSalesforceIdentityUrl(text(tokens.id));
|
|
544
|
+
if (!instanceUrl || !identity) {
|
|
545
|
+
throw new Error("Salesforce OAuth response did not identify the connected organization.");
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
accountId: identity.organizationId,
|
|
549
|
+
label: instanceUrl.hostname,
|
|
550
|
+
config: {
|
|
551
|
+
salesforceInstanceUrl: instanceUrl.origin,
|
|
552
|
+
salesforceIdentityUrl: identity.url.href,
|
|
553
|
+
salesforceOrganizationId: identity.organizationId,
|
|
554
|
+
},
|
|
555
|
+
};
|
|
556
|
+
}
|
|
489
557
|
if (providerId === "sentry") {
|
|
490
558
|
const accessToken = text(tokens.access_token);
|
|
491
559
|
const { response, body: user } = await fetchBoundedProviderJson("https://sentry.io/api/0/users/me/", {
|
|
@@ -561,8 +629,11 @@ export function canConnectWorkspaceProviderOAuth(orgId, role) {
|
|
|
561
629
|
return Boolean(orgId) && (role === "owner" || role === "admin");
|
|
562
630
|
}
|
|
563
631
|
export function scopedOAuthAccountId(provider, owner, accountId) {
|
|
564
|
-
if (provider !== "hubspot" &&
|
|
632
|
+
if (provider !== "hubspot" &&
|
|
633
|
+
provider !== "salesforce" &&
|
|
634
|
+
provider !== "jira") {
|
|
565
635
|
return accountId;
|
|
636
|
+
}
|
|
566
637
|
const ownerKey = crypto
|
|
567
638
|
.createHash("sha256")
|
|
568
639
|
.update(`${provider}:${owner.trim().toLowerCase()}`)
|
|
@@ -641,8 +712,74 @@ function clientCredentialKeys(provider, field) {
|
|
|
641
712
|
const integrationPrefix = `HUBSPOT_INTEGRATION_CLIENT_${suffix}`;
|
|
642
713
|
return [integrationPrefix, `HUBSPOT_CLIENT_${suffix}`];
|
|
643
714
|
}
|
|
715
|
+
if (provider === "salesforce") {
|
|
716
|
+
const integrationPrefix = `SALESFORCE_INTEGRATION_CLIENT_${suffix}`;
|
|
717
|
+
const consumerCredential = `SALESFORCE_CONSUMER_${field === "id" ? "KEY" : "SECRET"}`;
|
|
718
|
+
return [
|
|
719
|
+
integrationPrefix,
|
|
720
|
+
`SALESFORCE_CLIENT_${suffix}`,
|
|
721
|
+
consumerCredential,
|
|
722
|
+
];
|
|
723
|
+
}
|
|
644
724
|
return [`${prefix}_CLIENT_${suffix}`];
|
|
645
725
|
}
|
|
726
|
+
function normalizeSalesforceInstanceUrl(value) {
|
|
727
|
+
if (!value)
|
|
728
|
+
return null;
|
|
729
|
+
try {
|
|
730
|
+
const url = new URL(value);
|
|
731
|
+
const host = url.hostname.toLowerCase();
|
|
732
|
+
if (url.protocol !== "https:" ||
|
|
733
|
+
url.username ||
|
|
734
|
+
url.password ||
|
|
735
|
+
url.port ||
|
|
736
|
+
(host !== "salesforce.com" && !host.endsWith(".salesforce.com"))) {
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
return new URL(url.origin);
|
|
740
|
+
}
|
|
741
|
+
catch {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
function parseSalesforceIdentityUrl(value) {
|
|
746
|
+
if (!value)
|
|
747
|
+
return null;
|
|
748
|
+
try {
|
|
749
|
+
const url = new URL(value);
|
|
750
|
+
const host = url.hostname.toLowerCase();
|
|
751
|
+
if (url.protocol !== "https:" ||
|
|
752
|
+
url.username ||
|
|
753
|
+
url.password ||
|
|
754
|
+
url.port ||
|
|
755
|
+
(host !== "salesforce.com" && !host.endsWith(".salesforce.com"))) {
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
const match = url.pathname.match(/^\/id\/([^/]+)\/[^/]+\/?$/);
|
|
759
|
+
if (!match?.[1])
|
|
760
|
+
return null;
|
|
761
|
+
return { organizationId: match[1], url };
|
|
762
|
+
}
|
|
763
|
+
catch {
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
export function resolveSalesforceOAuthLoginUrl(environment) {
|
|
768
|
+
const normalized = environment?.trim().toLowerCase();
|
|
769
|
+
if (!normalized || normalized === "production") {
|
|
770
|
+
return SALESFORCE_PRODUCTION_LOGIN_URL;
|
|
771
|
+
}
|
|
772
|
+
if (normalized === "sandbox")
|
|
773
|
+
return SALESFORCE_SANDBOX_LOGIN_URL;
|
|
774
|
+
return null;
|
|
775
|
+
}
|
|
776
|
+
export function salesforceOAuthEndpoint(loginUrl, phase) {
|
|
777
|
+
if (loginUrl !== SALESFORCE_PRODUCTION_LOGIN_URL &&
|
|
778
|
+
loginUrl !== SALESFORCE_SANDBOX_LOGIN_URL) {
|
|
779
|
+
throw new Error("Invalid Salesforce OAuth login URL.");
|
|
780
|
+
}
|
|
781
|
+
return `${loginUrl}/services/oauth2/${phase}`;
|
|
782
|
+
}
|
|
646
783
|
async function resolveProviderClientCredentials(provider) {
|
|
647
784
|
const [clientId, clientSecret] = await Promise.all(["id", "secret"].map(async (field) => {
|
|
648
785
|
for (const key of clientCredentialKeys(provider, field)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-provider-oauth.js","sourceRoot":"","sources":["../../src/server/workspace-provider-oauth.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,iBAAiB,GAElB,MAAM,IAAI,CAAC;AAEZ,OAAO,EACL,8BAA8B,GAE/B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAW7D,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAgC;IACjE,OAAO;IACP,cAAc;IACd,QAAQ;IACR,SAAS;IACT,MAAM;IACN,QAAQ;IACR,QAAQ;CACT,CAAC,CAAC;AACH,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,CAAC;AACjC,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAC3C,MAAM,2BAA2B,GAAG,GAAG,GAAG,IAAI,CAAC;AAa/C,MAAM,UAAU,0BAA0B,CACxC,QAAuC,EACvC,KAA2B;IAE3B,OAAO,oCAAoC,QAAQ,IAAI,KAAK,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,QAAuC,EACvC,KAA2B;IAE3B,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE,CAClC,KAAK,KAAK,OAAO;QACf,CAAC,CAAC,iCAAiC,CAAC,KAAK,EAAE,QAAQ,CAAC;QACpD,CAAC,CAAC,oCAAoC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,KAAc,EACd,UAAyC;IAEzC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,KAAK;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,EAAE,KAAK;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,MAAM,kCAAkC,CAAC,KAAK,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EACH,wEAAwE;SAC3E,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EACH,wEAAwE;SAC3E,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,cAAc,CAC1B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,6BAA6B;QACzC,OAAO,CAAC,GAAG,CAAC,kCAAkC;QAC9C,kBAAkB,CACrB,CAAC;IACF,MAAM,WAAW,GAAG,uBAAuB,CACzC,KAAK,EACL,0BAA0B,CAAC,UAAU,EAAE,UAAU,CAAC,CACnD,CAAC;IACF,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;IAClD,CAAC;IACD,OAAO,qBAAqB,CAC1B,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EACnC,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAC5B,MAAM,gCAAgC,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,+CAA+C;aACxE,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,MAAM;aACrB,UAAU,CAAC,QAAQ,CAAC;aACpB,MAAM,CAAC,QAAQ,CAAC;aAChB,MAAM,CAAC,WAAW,CAAC,CAAC;QACvB,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACnC,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,kBAAkB;YAClC,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC;YACpC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,KAAK,GAAG,gBAAgB,CAAC;YAC7B,WAAW;YACX,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK;YACL,GAAG,EAAE,KAAK;YACV,SAAS;YACT,MAAM;SACP,CAAC,CAAC;QACH,MAAM,IAAI,GAA+B;YACvC,QAAQ,EAAE,UAAU;YACpB,MAAM;YACN,QAAQ;YACR,WAAW;YACX,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK;YACL,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,GAAG,KAAK;SACjD,CAAC;QACF,SAAS,CACP,KAAK,EACL,cAAc,CAAC,UAAU,CAAC,EAC1B,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EACxC;YACE,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC;YAC1C,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,gBAAgB;SACzB,CACF,CAAC;QACF,MAAM,gBAAgB,GAAG,sCAAsC,CAAC;YAC9D,QAAQ;YACR,QAAQ;YACR,WAAW;YACX,KAAK;YACL,SAAS;SACV,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oCAAoC,CACxD,KAAc,EACd,UAAyC;IAEzC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,KAAK;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,EAAE,KAAK;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,MAAM,kCAAkC,CAAC,KAAK,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EACH,wEAAwE;SAC3E,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EACH,wEAAwE;SAC3E,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,aAAa,EAAE,CAAC;QAClB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACzB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,0CAA0C,EAAE,CAAC;IAC/D,CAAC;IACD,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC/C,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,gBAAgB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC/C,IACE,CAAC,IAAI;QACL,CAAC,iCAAiC,CAAC;YACjC,IAAI;YACJ,KAAK;YACL,QAAQ,EAAE,UAAU;YACpB,YAAY,EAAE,OAAO,CAAC,KAAK;YAC3B,YAAY,EAAE,KAAK;SACpB,CAAC,EACF,CAAC;QACD,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9C,OAAO,qBAAqB,CAC1B,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EACnC,KAAK,IAAI,EAAE;QACT,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAC5B,MAAM,gCAAgC,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;gBACL,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,+CAA+C;aACxE,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,kCAAkC,CAAC;YACtD,UAAU;YACV,QAAQ;YACR,QAAQ;YACR,YAAY;YACZ,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,kCAAkC,CACzD,UAAU,EACV,MAAM,CACP,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,CAAC,KAAK,8CAA8C,CAChE,CAAC;QACJ,CAAC;QACD,MAAM,mBAAmB,GAAG,MAAM,wBAAwB,CAAC;YACzD,QAAQ,EAAE,UAAU;YACpB,eAAe,EAAE,IAAI;SACtB,CAAC,CAAC;QACH,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,oBAAoB,CACpC,UAAU,EACV,OAAO,CAAC,KAAK,EACb,QAAQ,CAAC,SAAS,CACnB,CAAC;YACF,MAAM,eAAe,CACnB,QAAQ,CAAC,KAAM,CAAC,QAAQ,EACxB,SAAS,EACT,MAAM,EACN,OAAO,CAAC,KAAK,CACd,CAAC;YACF,MAAM,mBAAmB,CACvB,QAAQ,CAAC,KAAM,CAAC,QAAQ,EACxB,SAAS,EACT,QAAQ,CAAC,KAAK,CACf,CAAC;YACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CACvC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS,CACnD,CAAC;YACF,MAAM,MAAM,GAAG,yBAAyB,CACtC,QAAQ,EAAE,MAAM,IAAI,EAAE,EACtB,QAAQ,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAM,CAAC,MAAM,CAAC,CAC/D,CAAC;YACF,MAAM,gBAAgB,GAAG;gBACvB,cAAc,EAAE,OAAO;gBACvB,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,MAAM;oBACnD,CAAC,CAAC,EAAE,iBAAiB,EAAE,QAAQ,CAAC,SAAS,EAAE;oBAC3C,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;aAC3B,CAAC;YACF,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC;gBACjD,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxC,QAAQ,EAAE,UAAU;gBACpB,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,EAAE;gBAC7C,SAAS;gBACT,YAAY,EAAE,QAAQ,CAAC,KAAK;gBAC5B,MAAM,EAAE,WAAW;gBACnB,MAAM;gBACN,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,EAAE;gBACxC,MAAM,EAAE,gBAAgB;gBACxB,aAAa,EAAE,IAAI,IAAI,EAAE;gBACzB,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;YACH,MAAM,8BAA8B,CAAC;gBACnC,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,UAAU;gBACpB,MAAM;gBACN,MAAM,EAAE,gBAAgB;aACzB,CAAC,CAAC;QACL,CAAC;QACD,MAAM,UAAU,GACd,KAAK,CAAC,SAAS;YACf,mCAAmC,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;QACtE,OAAO,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9D,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,KAMtD;IACC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK;QACvB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC3D,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACxD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAC9C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACxD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACnC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;QACjC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;QACtD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;QACzC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAC/C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;QACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,QAAQ;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1E,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CAAC,KAQxD;IACC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAChD,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC3G,IAAI,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CACvD,QAAQ,EACR;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,SAAS,EAAE,KAAK,CAAC,QAAQ;gBACzB,aAAa,EAAE,KAAK,CAAC,YAAY;gBACjC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,YAAY,EAAE,KAAK,CAAC,WAAW;aAChC,CAAC;SACH,EACD,KAAK,CAAC,QAAQ,CAAC,KAAK,CACrB,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,iCAAiC,QAAQ,CAAC,MAAM,IAAI,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC5C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBACzB,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,EAAE;gBAC/D,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CACvD,QAAQ,EACR;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,KAAK,CAAC,QAAQ;gBACzB,aAAa,EAAE,KAAK,CAAC,YAAY;gBACjC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,YAAY,EAAE,KAAK,CAAC,WAAW;aAChC,CAAC;SACH,EACD,KAAK,CAAC,QAAQ,CAAC,KAAK,CACrB,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,iCAAiC,QAAQ,CAAC,MAAM,IAAI,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC5C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBACzB,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,EAAE;gBAC/D,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QAChC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,6BAA6B,CAC5D,QAAQ,EACR;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,KAAK,CAAC,QAAQ;gBACzB,aAAa,EAAE,KAAK,CAAC,YAAY;gBACjC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,YAAY,EAAE,KAAK,CAAC,WAAW;aAChC,CAAC;SACH,EACD,KAAK,CAAC,QAAQ,CAAC,KAAK,CACrB,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,iCAAiC,QAAQ,CAAC,MAAM,IAAI,CAC5E,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC/C,OAAO;YACL,GAAG,SAAS;YACZ,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;gBAC7C,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,KAAK,EAAE;gBACjD,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG;QACb,UAAU,EAAE,oBAAoB;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,KAAK,CAAC,WAAW;QAC/B,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,KAAK,QAAQ;YAC/D,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,QAAQ,EAAE;YACnC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,QAAQ;YAC/B,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE;YAClE,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,cAAc;YACrC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE;YAClE,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CACvD,QAAQ,EACR;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EACL,KAAK,CAAC,UAAU,KAAK,QAAQ;YAC3B,CAAC,CAAC;gBACE,aAAa,EAAE,aAAa;gBAC5B,MAAM,EAAE,kBAAkB;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACH,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK,OAAO;gBAC5B,CAAC,CAAC;oBACE,aAAa,EAAE,aAAa;oBAC5B,cAAc,EAAE,mCAAmC;iBACpD;gBACH,CAAC,CAAC,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAC/D,IAAI,EACF,KAAK,CAAC,UAAU,KAAK,QAAQ;YAC3B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACxB,CAAC,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC;KAClC,EACD,KAAK,CAAC,QAAQ,CAAC,KAAK,CACrB,CAAC;IACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,iCAAiC,QAAQ,CAAC,MAAM,IAAI,CAC5E,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1C,OAAO;QACL,GAAG,IAAI;QACP,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;YAC7C,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,KAAK,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,UAAyC,EACzC,MAA+B;IAE/B,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,kCAAkC,CACzD,UAAU,EACV,MAAM,CACP,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,8CAA8C,CAC5D,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,UAAyC,EACzC,MAA+B;IAE/B,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,6BAA6B,CAC5D,4DAA4D,EAC5D;YACE,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,aAAa,EAAE,UAAU,WAAW,EAAE;aACvC;SACF,EACD,MAAM,CACP,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YACpC,IAAI,SAAc,CAAC;YACnB,IAAI,CAAC;gBACH,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,IACE,SAAS,CAAC,QAAQ,KAAK,QAAQ;gBAC/B,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAC9C,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;gBACzC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CACjB,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CACtD;gBACH,CAAC,CAAC,SAAS,CAAC;YACd,OAAO;gBACL;oBACE,SAAS,EAAE,OAAO;oBAClB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,SAAS,CAAC,QAAQ;oBAC9C,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrC,MAAM,EAAE;wBACN,gBAAgB,EAAE,OAAO;wBACzB,mBAAmB,EAAE,qCAAqC,kBAAkB,CAAC,OAAO,CAAC,EAAE;wBACvF,OAAO,EAAE,SAAS,CAAC,MAAM;qBAC1B;iBACF;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,CAAC,MAAM,sCAAsC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5E,CAAC;AASD,KAAK,UAAU,sCAAsC,CACnD,UAAyC,EACzC,MAA+B;IAE/B,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,GACb,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtB,IAAI,CAAC,SAAS;YACZ,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,OAAO;YACL,SAAS;YACT,KAAK,EACH,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;gBAC3B,kBAAkB;SACrB,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAE,CAAC;QAC/C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CAC7D,6BAA6B,EAC7B;YACE,OAAO,EAAE;gBACP,MAAM,EAAE,6BAA6B;gBACrC,aAAa,EAAE,UAAU,WAAW,EAAE;gBACtC,sBAAsB,EAAE,YAAY;aACrC;SACF,EACD,QAAQ,CACT,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO;YACL,SAAS;YACT,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,gBAAgB;SAC/D,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAE,CAAC;QAC/C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CACvD,iDAAiD,kBAAkB,CAAC,WAAW,CAAC,EAAE,EAClF,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,EAC3C,SAAS,CACV,CAAC;QACF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,SAAS;YACT,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,kBAAkB,SAAS,EAAE;SAC9D,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAE,CAAC;QAC/C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CAC7D,mCAAmC,EACnC;YACE,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,aAAa,EAAE,UAAU,WAAW,EAAE;aACvC;SACF,EACD,QAAQ,CACT,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,SAAS;YACT,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,gBAAgB;SACjE,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAE,CAAC;QAC/C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,wBAAwB,CACvD,8FAA8F,EAC9F,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,WAAW,EAAE,EAAE,EAAE,EACvD,cAAc,CACf,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,SAAS;YACT,KAAK,EACH,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;gBACxB,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;gBACvB,sBAAsB;SACzB,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAE,CAAC;IAC/C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,wBAAwB,CAC3D,6BAA6B,EAC7B,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,WAAW,EAAE,EAAE,EAAE,EACvD,OAAO,CACR,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,OAAO;QACL,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,eAAe;KAC5D,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,UAAyC;IAEzC,MAAM,QAAQ,GAAG,8BAA8B,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,EAAE,KAAK;QAClB,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,2BAA2B,CAAC,CAAC;IAC5D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CACrB,KAAc,EACd,QAAuC;IAEvC,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CACf,kBAAkB,CAAC,SAAS,CAAC,CACA,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,KAOjD;IACC,OAAO,CACL,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;QACtC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM;QACxC,KAAK,CAAC,KAAK,CAAC,WAAW,KAAK,KAAK,CAAC,IAAI,CAAC,WAAW;QAClD,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK;QACtC,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK;QACvC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK;QACtC,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK;QACvC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,KAAgC,EAChC,IAA+B;IAE/B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,QAAuC,EACvC,KAAa,EACb,SAAiB;IAEjB,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM;SACpB,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,GAAG,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;SACnD,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,GAAG,SAAS,KAAK,QAAQ,EAAE,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,GAAW,EACX,IAAiB,EACjB,aAAqB;IAErB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,6BAA6B,CAC5D,GAAG,EACH,IAAI,EACJ,aAAa,CACd,CAAC;IACF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,6BAA6B,CAC1C,GAAW,EACX,IAAiB,EACjB,aAAqB;IAErB,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,GAAG,IAAI;YACP,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,2BAA2B,CAAC;SACzD,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,aAAa,wBAAwB,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACtE,IACE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC/B,cAAc,GAAG,2BAA2B,EAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,aAAa,0CAA0C,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI;gBAAE,MAAM;YACtB,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;YACjC,IAAI,MAAM,GAAG,2BAA2B,EAAE,CAAC;gBACzC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM;YACR,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,aAAa,wBAAwB,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,MAAM,GAAG,2BAA2B,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,GAAG,aAAa,0CAA0C,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,MAA+B,EAC/B,QAA2B;IAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAA2B,EAC3B,QAA2B;IAE3B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB,CAC3B,QAAuC,EACvC,KAAsB;IAEtB,MAAM,MAAM,GACV,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAClE,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,6BAA6B,MAAM,EAAE,CAAC;QAChE,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,iBAAiB,GAAG,8BAA8B,MAAM,EAAE,CAAC;QACjE,OAAO,CAAC,iBAAiB,EAAE,kBAAkB,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,WAAW,MAAM,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,gCAAgC,CAC7C,QAAuC;IAEvC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/C,CAAC,IAAI,EAAE,QAAQ,CAAW,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9C,KAAK,MAAM,GAAG,IAAI,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CACH,CAAC;IACF,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,cAAc,CAAC,QAAuC;IAC7D,OAAO,sBAAsB,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAChE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,kCAAkC,CAAC,KAAc;IAC9D,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC7D,IACE,CAAC,OAAO;QACR,CAAC,gCAAgC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,EAC9D,CAAC;QACD,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import crypto from \"node:crypto\";\n\nimport {\n deleteCookie,\n defineEventHandler,\n getCookie,\n getMethod,\n getQuery,\n setCookie,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport {\n getWorkspaceConnectionProvider,\n type WorkspaceConnectionProvider,\n} from \"../connections/catalog.js\";\nimport { saveOAuthTokens, setOAuthDisplayName } from \"../oauth-tokens/store.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { decryptSecretValue, encryptSecretValue } from \"../secrets/crypto.js\";\nimport {\n listWorkspaceConnections,\n upsertWorkspaceConnection,\n upsertWorkspaceConnectionGrant,\n} from \"../workspace-connections/store.js\";\nimport { getSession, safeReturnPath } from \"./auth.js\";\nimport { resolveSecret } from \"./credential-provider.js\";\nimport {\n decodeOAuthState,\n encodeOAuthState,\n getAppUrl,\n resolveOAuthRedirectUri,\n type OAuthStatePayload,\n} from \"./google-oauth.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nexport type GenericWorkspaceOAuthProvider =\n | \"figma\"\n | \"google_drive\"\n | \"github\"\n | \"hubspot\"\n | \"jira\"\n | \"sentry\"\n | \"notion\";\n\nconst SUPPORTED_PROVIDERS = new Set<GenericWorkspaceOAuthProvider>([\n \"figma\",\n \"google_drive\",\n \"github\",\n \"hubspot\",\n \"jira\",\n \"sentry\",\n \"notion\",\n]);\nconst FLOW_TTL_SECONDS = 10 * 60;\nconst PROVIDER_REQUEST_TIMEOUT_MS = 10_000;\nconst PROVIDER_RESPONSE_MAX_BYTES = 256 * 1024;\n\nexport interface WorkspaceProviderOAuthFlow {\n provider: GenericWorkspaceOAuthProvider;\n flowId: string;\n verifier: string;\n redirectUri: string;\n owner: string;\n orgId?: string;\n appId: string;\n expiresAt: number;\n}\n\nexport function workspaceProviderOAuthPath(\n provider: GenericWorkspaceOAuthProvider,\n phase: \"start\" | \"callback\",\n): string {\n return `/_agent-native/connections/oauth/${provider}/${phase}`;\n}\n\nexport function createWorkspaceProviderOAuthHandler(\n provider: GenericWorkspaceOAuthProvider,\n phase: \"start\" | \"callback\",\n) {\n if (!SUPPORTED_PROVIDERS.has(provider)) {\n throw new Error(`Unsupported workspace OAuth provider: ${provider}`);\n }\n return defineEventHandler((event) =>\n phase === \"start\"\n ? handleWorkspaceProviderOAuthStart(event, provider)\n : handleWorkspaceProviderOAuthCallback(event, provider),\n );\n}\n\nexport async function handleWorkspaceProviderOAuthStart(\n event: H3Event,\n providerId: GenericWorkspaceOAuthProvider,\n): Promise<Response | Record<string, unknown>> {\n if (getMethod(event) !== \"GET\") return methodNotAllowed(event);\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return unauthorized(event);\n const orgContext = await requireWorkspaceProviderOAuthAdmin(event);\n if (!orgContext) {\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const orgId = orgContext.orgId;\n if (!orgId) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const provider = requiredProvider(providerId);\n const query = getQuery(event);\n const appId = normalizeAppId(\n text(query.appId) ??\n process.env.AGENT_NATIVE_WORKSPACE_APP_ID ??\n process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID ??\n \"creative-context\",\n );\n const redirectUri = resolveOAuthRedirectUri(\n event,\n workspaceProviderOAuthPath(providerId, \"callback\"),\n );\n if (!redirectUri) {\n setResponseStatus(event, 400);\n return { error: \"Invalid OAuth redirect URI.\" };\n }\n return runWithRequestContext(\n { userEmail: session.email, orgId },\n async () => {\n const [clientId, clientSecret] =\n await resolveProviderClientCredentials(providerId);\n if (!clientId || !clientSecret) {\n setResponseStatus(event, 503);\n return {\n error: `${provider.label} OAuth client credentials are not configured.`,\n };\n }\n const verifier = crypto.randomBytes(48).toString(\"base64url\");\n const challenge = crypto\n .createHash(\"sha256\")\n .update(verifier)\n .digest(\"base64url\");\n const flowId = crypto.randomUUID();\n const requestedReturnUrl = text(query.return);\n const returnUrl = requestedReturnUrl\n ? safeReturnPath(requestedReturnUrl)\n : undefined;\n const state = encodeOAuthState({\n redirectUri,\n owner: session.email,\n orgId,\n app: appId,\n returnUrl,\n flowId,\n });\n const flow: WorkspaceProviderOAuthFlow = {\n provider: providerId,\n flowId,\n verifier,\n redirectUri,\n owner: session.email,\n orgId,\n appId,\n expiresAt: Date.now() + FLOW_TTL_SECONDS * 1_000,\n };\n setCookie(\n event,\n flowCookieName(providerId),\n encryptSecretValue(JSON.stringify(flow)),\n {\n httpOnly: true,\n secure: redirectUri.startsWith(\"https://\"),\n sameSite: \"lax\",\n path: \"/\",\n maxAge: FLOW_TTL_SECONDS,\n },\n );\n const authorizationUrl = buildWorkspaceProviderAuthorizationUrl({\n provider,\n clientId,\n redirectUri,\n state,\n challenge,\n });\n return Response.redirect(authorizationUrl, 302);\n },\n );\n}\n\nexport async function handleWorkspaceProviderOAuthCallback(\n event: H3Event,\n providerId: GenericWorkspaceOAuthProvider,\n): Promise<Response | Record<string, unknown>> {\n if (getMethod(event) !== \"GET\") return methodNotAllowed(event);\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return unauthorized(event);\n const orgContext = await requireWorkspaceProviderOAuthAdmin(event);\n if (!orgContext) {\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const orgId = orgContext.orgId;\n if (!orgId) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const query = getQuery(event);\n const code = text(query.code);\n const stateParam = text(query.state);\n const providerError = text(query.error);\n if (providerError) {\n setResponseStatus(event, 400);\n return { error: \"OAuth authorization was not completed.\" };\n }\n if (!code || !stateParam) {\n setResponseStatus(event, 400);\n return { error: \"OAuth callback is missing code or state.\" };\n }\n const flow = readStoredFlow(event, providerId);\n deleteCookie(event, flowCookieName(providerId), { path: \"/\" });\n const state = decodeOAuthState(stateParam, \"\");\n if (\n !flow ||\n !isWorkspaceProviderOAuthFlowValid({\n flow,\n state,\n provider: providerId,\n sessionEmail: session.email,\n sessionOrgId: orgId,\n })\n ) {\n setResponseStatus(event, 400);\n return { error: \"OAuth state is invalid or expired.\" };\n }\n const provider = requiredProvider(providerId);\n return runWithRequestContext(\n { userEmail: session.email, orgId },\n async () => {\n const [clientId, clientSecret] =\n await resolveProviderClientCredentials(providerId);\n if (!clientId || !clientSecret) {\n setResponseStatus(event, 503);\n return {\n error: `${provider.label} OAuth client credentials are not configured.`,\n };\n }\n const tokens = await exchangeWorkspaceProviderOAuthCode({\n providerId,\n provider,\n clientId,\n clientSecret,\n code,\n verifier: flow.verifier,\n redirectUri: flow.redirectUri,\n });\n const identities = await resolveWorkspaceProviderIdentities(\n providerId,\n tokens,\n );\n if (!identities.length) {\n throw new Error(\n `${provider.label} OAuth did not return an accessible account.`,\n );\n }\n const existingConnections = await listWorkspaceConnections({\n provider: providerId,\n includeDisabled: true,\n });\n for (const identity of identities) {\n const accountId = scopedOAuthAccountId(\n providerId,\n session.email,\n identity.accountId,\n );\n await saveOAuthTokens(\n provider.oauth!.provider,\n accountId,\n tokens,\n session.email,\n );\n await setOAuthDisplayName(\n provider.oauth!.provider,\n accountId,\n identity.label,\n );\n const existing = existingConnections.find(\n (connection) => connection.accountId === accountId,\n );\n const scopes = mergeWorkspaceOAuthValues(\n existing?.scopes ?? [],\n identity.scopes ?? tokenScopes(tokens, provider.oauth!.scopes),\n );\n const connectionConfig = {\n credentialMode: \"oauth\",\n ...(providerId === \"hubspot\" || providerId === \"jira\"\n ? { externalAccountId: identity.accountId }\n : {}),\n ...(identity.config ?? {}),\n };\n const connection = await upsertWorkspaceConnection({\n ...(existing ? { id: existing.id } : {}),\n provider: providerId,\n label: `${provider.label}: ${identity.label}`,\n accountId,\n accountLabel: identity.label,\n status: \"connected\",\n scopes,\n allowedApps: existing?.allowedApps ?? [],\n config: connectionConfig,\n lastCheckedAt: new Date(),\n lastError: null,\n });\n await upsertWorkspaceConnectionGrant({\n connectionId: connection.id,\n appId: flow.appId,\n provider: providerId,\n scopes,\n config: connectionConfig,\n });\n }\n const returnPath =\n state.returnUrl ??\n `/settings/connections?connected=${encodeURIComponent(providerId)}`;\n return Response.redirect(getAppUrl(event, returnPath), 302);\n },\n );\n}\n\nexport function buildWorkspaceProviderAuthorizationUrl(input: {\n provider: WorkspaceConnectionProvider;\n clientId: string;\n redirectUri: string;\n state: string;\n challenge: string;\n}): string {\n if (!input.provider.oauth)\n throw new Error(\"Provider does not support OAuth.\");\n const url = new URL(input.provider.oauth.authorizationUrl);\n url.searchParams.set(\"client_id\", input.clientId);\n url.searchParams.set(\"redirect_uri\", input.redirectUri);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"state\", input.state);\n if (input.provider.id === \"figma\" || input.provider.id === \"sentry\") {\n url.searchParams.set(\"code_challenge\", input.challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n }\n if (input.provider.id === \"github\") {\n url.searchParams.set(\"allow_signup\", \"true\");\n }\n if (input.provider.id === \"jira\") {\n url.searchParams.set(\"audience\", \"api.atlassian.com\");\n url.searchParams.set(\"prompt\", \"consent\");\n }\n if (input.provider.id === \"google_drive\") {\n url.searchParams.set(\"access_type\", \"offline\");\n url.searchParams.set(\"include_granted_scopes\", \"true\");\n url.searchParams.set(\"prompt\", \"consent\");\n }\n if (input.provider.oauth.scopes.length) {\n url.searchParams.set(\"scope\", input.provider.oauth.scopes.join(\" \"));\n }\n if (input.provider.id === \"notion\") url.searchParams.set(\"owner\", \"user\");\n return url.href;\n}\n\nexport async function exchangeWorkspaceProviderOAuthCode(input: {\n providerId: GenericWorkspaceOAuthProvider;\n provider: WorkspaceConnectionProvider;\n clientId: string;\n clientSecret: string;\n code: string;\n verifier: string;\n redirectUri: string;\n}): Promise<Record<string, unknown>> {\n const tokenUrl = input.provider.oauth?.tokenUrl;\n if (!tokenUrl) throw new Error(\"Provider does not support OAuth.\");\n const authorization = `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString(\"base64\")}`;\n if (input.providerId === \"github\") {\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n return {\n ...body,\n ...(Number.isFinite(Number(body.expires_in)) &&\n Number(body.expires_in) > 0\n ? { expiry_date: Date.now() + Number(body.expires_in) * 1_000 }\n : {}),\n };\n }\n if (input.providerId === \"hubspot\") {\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n return {\n ...body,\n ...(Number.isFinite(Number(body.expires_in)) &&\n Number(body.expires_in) > 0\n ? { expiry_date: Date.now() + Number(body.expires_in) * 1_000 }\n : {}),\n };\n }\n if (input.providerId === \"jira\") {\n const { response, body } = await fetchBoundedProviderJsonValue(\n tokenUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"authorization_code\",\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const tokenBody = record(body) ?? {};\n const accessToken = text(tokenBody.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n const expiresIn = Number(tokenBody.expires_in);\n return {\n ...tokenBody,\n ...(Number.isFinite(expiresIn) && expiresIn > 0\n ? { expiry_date: Date.now() + expiresIn * 1_000 }\n : {}),\n };\n }\n const fields = {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n ...(input.providerId === \"figma\" || input.providerId === \"sentry\"\n ? { code_verifier: input.verifier }\n : {}),\n ...(input.providerId === \"sentry\"\n ? { client_id: input.clientId, client_secret: input.clientSecret }\n : {}),\n ...(input.providerId === \"google_drive\"\n ? { client_id: input.clientId, client_secret: input.clientSecret }\n : {}),\n };\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers:\n input.providerId === \"notion\"\n ? {\n Authorization: authorization,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n }\n : input.providerId === \"figma\"\n ? {\n Authorization: authorization,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n }\n : { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body:\n input.providerId === \"notion\"\n ? JSON.stringify(fields)\n : new URLSearchParams(fields),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n const expiresIn = Number(body.expires_in);\n return {\n ...body,\n ...(Number.isFinite(expiresIn) && expiresIn > 0\n ? { expiry_date: Date.now() + expiresIn * 1_000 }\n : {}),\n };\n}\n\nexport async function resolveWorkspaceProviderIdentity(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity> {\n const [identity] = await resolveWorkspaceProviderIdentities(\n providerId,\n tokens,\n );\n if (!identity) {\n throw new Error(\n `${providerId} OAuth response did not identify an account.`,\n );\n }\n return identity;\n}\n\nexport async function resolveWorkspaceProviderIdentities(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity[]> {\n if (providerId === \"jira\") {\n const accessToken = text(tokens.access_token);\n if (!accessToken) {\n throw new Error(\"Jira OAuth response did not include an access token.\");\n }\n const { response, body } = await fetchBoundedProviderJsonValue(\n \"https://api.atlassian.com/oauth/token/accessible-resources\",\n {\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n },\n \"Jira\",\n );\n if (!response.ok || !Array.isArray(body)) {\n throw new Error(\"Jira OAuth response did not identify accessible sites.\");\n }\n return body.flatMap((resource) => {\n const entry = record(resource);\n const cloudId = text(entry?.id);\n const siteUrl = text(entry?.url);\n if (!cloudId || !siteUrl) return [];\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(siteUrl);\n } catch {\n return [];\n }\n if (\n parsedUrl.protocol !== \"https:\" ||\n !parsedUrl.hostname.endsWith(\".atlassian.net\")\n ) {\n return [];\n }\n const scopes = Array.isArray(entry?.scopes)\n ? entry.scopes.filter(\n (scope): scope is string => typeof scope === \"string\",\n )\n : undefined;\n return [\n {\n accountId: cloudId,\n label: text(entry?.name) ?? parsedUrl.hostname,\n ...(scopes?.length ? { scopes } : {}),\n config: {\n atlassianCloudId: cloudId,\n atlassianApiBaseUrl: `https://api.atlassian.com/ex/jira/${encodeURIComponent(cloudId)}`,\n siteUrl: parsedUrl.origin,\n },\n },\n ];\n });\n }\n return [await resolveWorkspaceProviderIdentitySingle(providerId, tokens)];\n}\n\ntype WorkspaceProviderIdentity = {\n accountId: string;\n label: string;\n scopes?: string[];\n config?: Record<string, unknown>;\n};\n\nasync function resolveWorkspaceProviderIdentitySingle(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity> {\n if (providerId === \"notion\") {\n const owner = record(tokens.owner);\n const user = record(owner?.user);\n const person = record(user?.person);\n const accountId =\n text(user?.id) ??\n text(person?.email) ??\n text(tokens.workspace_id) ??\n text(tokens.bot_id);\n if (!accountId)\n throw new Error(\n \"Notion OAuth response did not identify the connected user.\",\n );\n return {\n accountId,\n label:\n text(person?.email) ??\n text(tokens.workspace_name) ??\n \"Notion workspace\",\n };\n }\n if (providerId === \"github\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body: user } = await fetchBoundedProviderJson(\n \"https://api.github.com/user\",\n {\n headers: {\n Accept: \"application/vnd.github+json\",\n Authorization: `Bearer ${accessToken}`,\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n },\n \"GitHub\",\n );\n const accountId = text(user.login) ?? text(user.id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"GitHub OAuth response did not identify the connected user.\",\n );\n }\n return {\n accountId,\n label: text(user.name) ?? text(user.login) ?? \"GitHub account\",\n };\n }\n if (providerId === \"hubspot\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body } = await fetchBoundedProviderJson(\n `https://api.hubapi.com/oauth/v1/access-tokens/${encodeURIComponent(accessToken)}`,\n { headers: { Accept: \"application/json\" } },\n \"HubSpot\",\n );\n const accountId = scalarText(body.hub_id) ?? scalarText(body.user_id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"HubSpot OAuth response did not identify the connected portal.\",\n );\n }\n return {\n accountId,\n label: text(body.hub_domain) ?? `HubSpot portal ${accountId}`,\n };\n }\n if (providerId === \"sentry\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body: user } = await fetchBoundedProviderJson(\n \"https://sentry.io/api/0/users/me/\",\n {\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n },\n \"Sentry\",\n );\n const accountId = text(user.id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Sentry OAuth response did not identify the connected account.\",\n );\n }\n return {\n accountId,\n label: text(user?.email) ?? text(user?.name) ?? \"Sentry account\",\n };\n }\n if (providerId === \"google_drive\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body } = await fetchBoundedProviderJson(\n \"https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,permissionId)\",\n { headers: { Authorization: `Bearer ${accessToken}` } },\n \"Google Drive\",\n );\n const user = record(body.user);\n const accountId = text(user?.permissionId) ?? text(user?.emailAddress);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Google Drive OAuth response did not identify the connected account.\",\n );\n }\n return {\n accountId,\n label:\n text(user?.emailAddress) ??\n text(user?.displayName) ??\n \"Google Drive account\",\n };\n }\n const accessToken = text(tokens.access_token)!;\n const { response, body: me } = await fetchBoundedProviderJson(\n \"https://api.figma.com/v1/me\",\n { headers: { Authorization: `Bearer ${accessToken}` } },\n \"Figma\",\n );\n const accountId = text(me.id) ?? text(me.email) ?? text(tokens.user_id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Figma OAuth response did not identify the connected user.\",\n );\n }\n return {\n accountId,\n label: text(me.email) ?? text(me.handle) ?? \"Figma account\",\n };\n}\n\nfunction requiredProvider(\n providerId: GenericWorkspaceOAuthProvider,\n): WorkspaceConnectionProvider {\n const provider = getWorkspaceConnectionProvider(providerId);\n if (!provider?.oauth)\n throw new Error(`${providerId} OAuth is not configured.`);\n return provider;\n}\n\nfunction readStoredFlow(\n event: H3Event,\n provider: GenericWorkspaceOAuthProvider,\n): WorkspaceProviderOAuthFlow | null {\n const encrypted = getCookie(event, flowCookieName(provider));\n if (!encrypted) return null;\n try {\n return JSON.parse(\n decryptSecretValue(encrypted),\n ) as WorkspaceProviderOAuthFlow;\n } catch {\n return null;\n }\n}\n\nexport function isWorkspaceProviderOAuthFlowValid(input: {\n flow: WorkspaceProviderOAuthFlow;\n state: OAuthStatePayload;\n provider: GenericWorkspaceOAuthProvider;\n sessionEmail: string;\n sessionOrgId?: string;\n now?: number;\n}): boolean {\n return (\n input.flow.expiresAt >= (input.now ?? Date.now()) &&\n input.flow.provider === input.provider &&\n input.state.flowId === input.flow.flowId &&\n input.state.redirectUri === input.flow.redirectUri &&\n input.state.owner === input.flow.owner &&\n input.sessionEmail === input.flow.owner &&\n input.state.orgId === input.flow.orgId &&\n input.sessionOrgId === input.flow.orgId &&\n input.state.app === input.flow.appId\n );\n}\n\nexport function canConnectWorkspaceProviderOAuth(\n orgId: string | null | undefined,\n role: string | null | undefined,\n): boolean {\n return Boolean(orgId) && (role === \"owner\" || role === \"admin\");\n}\n\nexport function scopedOAuthAccountId(\n provider: GenericWorkspaceOAuthProvider,\n owner: string,\n accountId: string,\n): string {\n if (provider !== \"hubspot\" && provider !== \"jira\") return accountId;\n const ownerKey = crypto\n .createHash(\"sha256\")\n .update(`${provider}:${owner.trim().toLowerCase()}`)\n .digest(\"hex\")\n .slice(0, 24);\n return `${accountId}::${ownerKey}`;\n}\n\nasync function fetchBoundedProviderJson(\n url: string,\n init: RequestInit,\n providerLabel: string,\n): Promise<{ response: Response; body: Record<string, unknown> }> {\n const { response, body } = await fetchBoundedProviderJsonValue(\n url,\n init,\n providerLabel,\n );\n return { response, body: record(body) ?? {} };\n}\n\nasync function fetchBoundedProviderJsonValue(\n url: string,\n init: RequestInit,\n providerLabel: string,\n): Promise<{ response: Response; body: unknown }> {\n let response: Response;\n try {\n response = await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(PROVIDER_REQUEST_TIMEOUT_MS),\n });\n } catch {\n throw new Error(`${providerLabel} OAuth request failed.`);\n }\n const declaredLength = Number(response.headers.get(\"content-length\"));\n if (\n Number.isFinite(declaredLength) &&\n declaredLength > PROVIDER_RESPONSE_MAX_BYTES\n ) {\n throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);\n }\n if (!response.body) return { response, body: {} };\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let length = 0;\n try {\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) break;\n length += chunk.value.byteLength;\n if (length > PROVIDER_RESPONSE_MAX_BYTES) {\n await reader.cancel();\n break;\n }\n chunks.push(chunk.value);\n }\n } catch {\n throw new Error(`${providerLabel} OAuth request failed.`);\n }\n if (length > PROVIDER_RESPONSE_MAX_BYTES) {\n throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);\n }\n try {\n const json = Buffer.concat(chunks).toString(\"utf8\");\n const body = JSON.parse(json) as unknown;\n return { response, body };\n } catch {\n return { response, body: {} };\n }\n}\n\nfunction tokenScopes(\n tokens: Record<string, unknown>,\n fallback: readonly string[],\n): string[] {\n const scope = text(tokens.scope);\n return scope ? scope.split(/[ ,]+/).filter(Boolean) : [...fallback];\n}\n\nexport function mergeWorkspaceOAuthValues(\n existing: readonly string[],\n incoming: readonly string[],\n): string[] {\n return [...new Set([...existing, ...incoming])];\n}\n\nfunction clientCredentialKeys(\n provider: GenericWorkspaceOAuthProvider,\n field: \"id\" | \"secret\",\n): string[] {\n const prefix =\n provider === \"google_drive\" ? \"GOOGLE\" : provider.toUpperCase();\n const suffix = field === \"id\" ? \"ID\" : \"SECRET\";\n if (provider === \"github\") {\n const integrationPrefix = `GITHUB_INTEGRATION_CLIENT_${suffix}`;\n return [integrationPrefix, `GITHUB_CLIENT_${suffix}`];\n }\n if (provider === \"hubspot\") {\n const integrationPrefix = `HUBSPOT_INTEGRATION_CLIENT_${suffix}`;\n return [integrationPrefix, `HUBSPOT_CLIENT_${suffix}`];\n }\n return [`${prefix}_CLIENT_${suffix}`];\n}\n\nasync function resolveProviderClientCredentials(\n provider: GenericWorkspaceOAuthProvider,\n): Promise<[string | null, string | null]> {\n const [clientId, clientSecret] = await Promise.all(\n ([\"id\", \"secret\"] as const).map(async (field) => {\n for (const key of clientCredentialKeys(provider, field)) {\n const value = await resolveSecret(key);\n if (value) return value;\n }\n return null;\n }),\n );\n return [clientId, clientSecret];\n}\n\nfunction flowCookieName(provider: GenericWorkspaceOAuthProvider): string {\n return `an_workspace_oauth_${provider}`;\n}\n\nfunction normalizeAppId(value: string): string {\n const normalized = value.trim().toLowerCase();\n if (!/^[a-z0-9][a-z0-9_-]{0,99}$/.test(normalized)) {\n throw new Error(\"OAuth appId is invalid.\");\n }\n return normalized;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction scalarText(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return text(value);\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction methodNotAllowed(event: H3Event) {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n}\n\nfunction unauthorized(event: H3Event) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n}\n\nasync function requireWorkspaceProviderOAuthAdmin(event: H3Event) {\n const context = await getOrgContext(event).catch(() => null);\n if (\n !context ||\n !canConnectWorkspaceProviderOAuth(context.orgId, context.role)\n ) {\n setResponseStatus(event, 403);\n return null;\n }\n return context;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-provider-oauth.js","sourceRoot":"","sources":["../../src/server/workspace-provider-oauth.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\n\nimport {\n deleteCookie,\n defineEventHandler,\n getCookie,\n getMethod,\n getQuery,\n setCookie,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport {\n getWorkspaceConnectionProvider,\n type WorkspaceConnectionProvider,\n} from \"../connections/catalog.js\";\nimport { saveOAuthTokens, setOAuthDisplayName } from \"../oauth-tokens/store.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { decryptSecretValue, encryptSecretValue } from \"../secrets/crypto.js\";\nimport {\n listWorkspaceConnections,\n upsertWorkspaceConnection,\n upsertWorkspaceConnectionGrant,\n} from \"../workspace-connections/store.js\";\nimport { getSession, safeReturnPath } from \"./auth.js\";\nimport { resolveSecret } from \"./credential-provider.js\";\nimport {\n decodeOAuthState,\n encodeOAuthState,\n getAppUrl,\n resolveOAuthRedirectUri,\n type OAuthStatePayload,\n} from \"./google-oauth.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nexport type GenericWorkspaceOAuthProvider =\n | \"figma\"\n | \"google_drive\"\n | \"github\"\n | \"hubspot\"\n | \"salesforce\"\n | \"jira\"\n | \"sentry\"\n | \"notion\";\n\nconst SUPPORTED_PROVIDERS = new Set<GenericWorkspaceOAuthProvider>([\n \"figma\",\n \"google_drive\",\n \"github\",\n \"hubspot\",\n \"salesforce\",\n \"jira\",\n \"sentry\",\n \"notion\",\n]);\nconst FLOW_TTL_SECONDS = 10 * 60;\nconst PROVIDER_REQUEST_TIMEOUT_MS = 10_000;\nconst PROVIDER_RESPONSE_MAX_BYTES = 256 * 1024;\nconst SALESFORCE_PRODUCTION_LOGIN_URL = \"https://login.salesforce.com\";\nconst SALESFORCE_SANDBOX_LOGIN_URL = \"https://test.salesforce.com\";\n\nexport interface WorkspaceProviderOAuthFlow {\n provider: GenericWorkspaceOAuthProvider;\n flowId: string;\n verifier: string;\n redirectUri: string;\n owner: string;\n orgId?: string;\n appId: string;\n salesforceLoginUrl?: string;\n expiresAt: number;\n}\n\nexport function workspaceProviderOAuthPath(\n provider: GenericWorkspaceOAuthProvider,\n phase: \"start\" | \"callback\",\n): string {\n return `/_agent-native/connections/oauth/${provider}/${phase}`;\n}\n\nexport function createWorkspaceProviderOAuthHandler(\n provider: GenericWorkspaceOAuthProvider,\n phase: \"start\" | \"callback\",\n) {\n if (!SUPPORTED_PROVIDERS.has(provider)) {\n throw new Error(`Unsupported workspace OAuth provider: ${provider}`);\n }\n return defineEventHandler((event) =>\n phase === \"start\"\n ? handleWorkspaceProviderOAuthStart(event, provider)\n : handleWorkspaceProviderOAuthCallback(event, provider),\n );\n}\n\nexport async function handleWorkspaceProviderOAuthStart(\n event: H3Event,\n providerId: GenericWorkspaceOAuthProvider,\n): Promise<Response | Record<string, unknown>> {\n if (getMethod(event) !== \"GET\") return methodNotAllowed(event);\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return unauthorized(event);\n const orgContext = await requireWorkspaceProviderOAuthAdmin(event);\n if (!orgContext) {\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const orgId = orgContext.orgId;\n if (!orgId) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const provider = requiredProvider(providerId);\n const query = getQuery(event);\n const salesforceLoginUrl =\n providerId === \"salesforce\"\n ? resolveSalesforceOAuthLoginUrl(text(query.environment))\n : undefined;\n if (providerId === \"salesforce\" && !salesforceLoginUrl) {\n setResponseStatus(event, 400);\n return { error: \"Salesforce environment must be production or sandbox.\" };\n }\n const appId = normalizeAppId(\n text(query.appId) ??\n process.env.AGENT_NATIVE_WORKSPACE_APP_ID ??\n process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID ??\n \"creative-context\",\n );\n const redirectUri = resolveOAuthRedirectUri(\n event,\n workspaceProviderOAuthPath(providerId, \"callback\"),\n );\n if (!redirectUri) {\n setResponseStatus(event, 400);\n return { error: \"Invalid OAuth redirect URI.\" };\n }\n return runWithRequestContext(\n { userEmail: session.email, orgId },\n async () => {\n const [clientId, clientSecret] =\n await resolveProviderClientCredentials(providerId);\n if (!clientId || !clientSecret) {\n setResponseStatus(event, 503);\n return {\n error: `${provider.label} OAuth client credentials are not configured.`,\n };\n }\n const verifier = crypto.randomBytes(48).toString(\"base64url\");\n const challenge = crypto\n .createHash(\"sha256\")\n .update(verifier)\n .digest(\"base64url\");\n const flowId = crypto.randomUUID();\n const requestedReturnUrl = text(query.return);\n const returnUrl = requestedReturnUrl\n ? safeReturnPath(requestedReturnUrl)\n : undefined;\n const state = encodeOAuthState({\n redirectUri,\n owner: session.email,\n orgId,\n app: appId,\n returnUrl,\n flowId,\n });\n const flow: WorkspaceProviderOAuthFlow = {\n provider: providerId,\n flowId,\n verifier,\n redirectUri,\n owner: session.email,\n orgId,\n appId,\n ...(salesforceLoginUrl ? { salesforceLoginUrl } : {}),\n expiresAt: Date.now() + FLOW_TTL_SECONDS * 1_000,\n };\n setCookie(\n event,\n flowCookieName(providerId),\n encryptSecretValue(JSON.stringify(flow)),\n {\n httpOnly: true,\n secure: redirectUri.startsWith(\"https://\"),\n sameSite: \"lax\",\n path: \"/\",\n maxAge: FLOW_TTL_SECONDS,\n },\n );\n const authorizationUrl = buildWorkspaceProviderAuthorizationUrl({\n provider,\n clientId,\n redirectUri,\n state,\n challenge,\n ...(salesforceLoginUrl\n ? {\n authorizationUrl: salesforceOAuthEndpoint(\n salesforceLoginUrl,\n \"authorize\",\n ),\n }\n : {}),\n });\n return Response.redirect(authorizationUrl, 302);\n },\n );\n}\n\nexport async function handleWorkspaceProviderOAuthCallback(\n event: H3Event,\n providerId: GenericWorkspaceOAuthProvider,\n): Promise<Response | Record<string, unknown>> {\n if (getMethod(event) !== \"GET\") return methodNotAllowed(event);\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return unauthorized(event);\n const orgContext = await requireWorkspaceProviderOAuthAdmin(event);\n if (!orgContext) {\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const orgId = orgContext.orgId;\n if (!orgId) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can connect shared OAuth accounts.\",\n };\n }\n const query = getQuery(event);\n const code = text(query.code);\n const stateParam = text(query.state);\n const providerError = text(query.error);\n if (providerError) {\n setResponseStatus(event, 400);\n return { error: \"OAuth authorization was not completed.\" };\n }\n if (!code || !stateParam) {\n setResponseStatus(event, 400);\n return { error: \"OAuth callback is missing code or state.\" };\n }\n const flow = readStoredFlow(event, providerId);\n deleteCookie(event, flowCookieName(providerId), { path: \"/\" });\n const state = decodeOAuthState(stateParam, \"\");\n if (\n !flow ||\n !isWorkspaceProviderOAuthFlowValid({\n flow,\n state,\n provider: providerId,\n sessionEmail: session.email,\n sessionOrgId: orgId,\n })\n ) {\n setResponseStatus(event, 400);\n return { error: \"OAuth state is invalid or expired.\" };\n }\n const provider = requiredProvider(providerId);\n return runWithRequestContext(\n { userEmail: session.email, orgId },\n async () => {\n const [clientId, clientSecret] =\n await resolveProviderClientCredentials(providerId);\n if (!clientId || !clientSecret) {\n setResponseStatus(event, 503);\n return {\n error: `${provider.label} OAuth client credentials are not configured.`,\n };\n }\n const tokens = await exchangeWorkspaceProviderOAuthCode({\n providerId,\n provider,\n clientId,\n clientSecret,\n code,\n verifier: flow.verifier,\n redirectUri: flow.redirectUri,\n ...(providerId === \"salesforce\"\n ? {\n tokenUrl: salesforceOAuthEndpoint(\n flow.salesforceLoginUrl ?? SALESFORCE_PRODUCTION_LOGIN_URL,\n \"token\",\n ),\n }\n : {}),\n });\n const identities = await resolveWorkspaceProviderIdentities(\n providerId,\n tokens,\n );\n if (!identities.length) {\n throw new Error(\n `${provider.label} OAuth did not return an accessible account.`,\n );\n }\n const existingConnections = await listWorkspaceConnections({\n provider: providerId,\n includeDisabled: true,\n });\n for (const identity of identities) {\n const accountId = scopedOAuthAccountId(\n providerId,\n session.email,\n identity.accountId,\n );\n await saveOAuthTokens(\n provider.oauth!.provider,\n accountId,\n tokens,\n session.email,\n );\n await setOAuthDisplayName(\n provider.oauth!.provider,\n accountId,\n identity.label,\n );\n const existing = existingConnections.find(\n (connection) => connection.accountId === accountId,\n );\n const scopes = mergeWorkspaceOAuthValues(\n existing?.scopes ?? [],\n identity.scopes ?? tokenScopes(tokens, provider.oauth!.scopes),\n );\n const connectionConfig = {\n credentialMode: \"oauth\",\n ...(providerId === \"hubspot\" ||\n providerId === \"salesforce\" ||\n providerId === \"jira\"\n ? { externalAccountId: identity.accountId }\n : {}),\n ...(identity.config ?? {}),\n ...(providerId === \"salesforce\"\n ? {\n salesforceLoginUrl:\n flow.salesforceLoginUrl ?? SALESFORCE_PRODUCTION_LOGIN_URL,\n }\n : {}),\n };\n const connection = await upsertWorkspaceConnection({\n ...(existing ? { id: existing.id } : {}),\n provider: providerId,\n label: `${provider.label}: ${identity.label}`,\n accountId,\n accountLabel: identity.label,\n status: \"connected\",\n scopes,\n allowedApps: existing?.allowedApps ?? [],\n config: connectionConfig,\n lastCheckedAt: new Date(),\n lastError: null,\n });\n await upsertWorkspaceConnectionGrant({\n connectionId: connection.id,\n appId: flow.appId,\n provider: providerId,\n scopes,\n config: connectionConfig,\n });\n }\n const returnPath =\n state.returnUrl ??\n `/settings/connections?connected=${encodeURIComponent(providerId)}`;\n return Response.redirect(getAppUrl(event, returnPath), 302);\n },\n );\n}\n\nexport function buildWorkspaceProviderAuthorizationUrl(input: {\n provider: WorkspaceConnectionProvider;\n clientId: string;\n redirectUri: string;\n state: string;\n challenge: string;\n authorizationUrl?: string;\n}): string {\n if (!input.provider.oauth)\n throw new Error(\"Provider does not support OAuth.\");\n const url = new URL(\n input.authorizationUrl ?? input.provider.oauth.authorizationUrl,\n );\n url.searchParams.set(\"client_id\", input.clientId);\n url.searchParams.set(\"redirect_uri\", input.redirectUri);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"state\", input.state);\n if (input.provider.id === \"figma\" || input.provider.id === \"sentry\") {\n url.searchParams.set(\"code_challenge\", input.challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n }\n if (input.provider.id === \"github\") {\n url.searchParams.set(\"allow_signup\", \"true\");\n }\n if (input.provider.id === \"jira\") {\n url.searchParams.set(\"audience\", \"api.atlassian.com\");\n url.searchParams.set(\"prompt\", \"consent\");\n }\n if (input.provider.id === \"google_drive\") {\n url.searchParams.set(\"access_type\", \"offline\");\n url.searchParams.set(\"include_granted_scopes\", \"true\");\n url.searchParams.set(\"prompt\", \"consent\");\n }\n if (input.provider.oauth.scopes.length) {\n url.searchParams.set(\"scope\", input.provider.oauth.scopes.join(\" \"));\n }\n if (input.provider.id === \"notion\") url.searchParams.set(\"owner\", \"user\");\n return url.href;\n}\n\nexport async function exchangeWorkspaceProviderOAuthCode(input: {\n providerId: GenericWorkspaceOAuthProvider;\n provider: WorkspaceConnectionProvider;\n clientId: string;\n clientSecret: string;\n code: string;\n verifier: string;\n redirectUri: string;\n tokenUrl?: string;\n}): Promise<Record<string, unknown>> {\n const tokenUrl = input.tokenUrl ?? input.provider.oauth?.tokenUrl;\n if (!tokenUrl) throw new Error(\"Provider does not support OAuth.\");\n const authorization = `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString(\"base64\")}`;\n if (input.providerId === \"github\") {\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n return {\n ...body,\n ...(Number.isFinite(Number(body.expires_in)) &&\n Number(body.expires_in) > 0\n ? { expiry_date: Date.now() + Number(body.expires_in) * 1_000 }\n : {}),\n };\n }\n if (input.providerId === \"hubspot\") {\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n return {\n ...body,\n ...(Number.isFinite(Number(body.expires_in)) &&\n Number(body.expires_in) > 0\n ? { expiry_date: Date.now() + Number(body.expires_in) * 1_000 }\n : {}),\n };\n }\n if (input.providerId === \"salesforce\") {\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n const expiresIn = Number(body.expires_in);\n return {\n ...body,\n ...(Number.isFinite(expiresIn) && expiresIn > 0\n ? { expiry_date: Date.now() + expiresIn * 1_000 }\n : {}),\n };\n }\n if (input.providerId === \"jira\") {\n const { response, body } = await fetchBoundedProviderJsonValue(\n tokenUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"authorization_code\",\n client_id: input.clientId,\n client_secret: input.clientSecret,\n code: input.code,\n redirect_uri: input.redirectUri,\n }),\n },\n input.provider.label,\n );\n const tokenBody = record(body) ?? {};\n const accessToken = text(tokenBody.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n const expiresIn = Number(tokenBody.expires_in);\n return {\n ...tokenBody,\n ...(Number.isFinite(expiresIn) && expiresIn > 0\n ? { expiry_date: Date.now() + expiresIn * 1_000 }\n : {}),\n };\n }\n const fields = {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n ...(input.providerId === \"figma\" || input.providerId === \"sentry\"\n ? { code_verifier: input.verifier }\n : {}),\n ...(input.providerId === \"sentry\"\n ? { client_id: input.clientId, client_secret: input.clientSecret }\n : {}),\n ...(input.providerId === \"google_drive\"\n ? { client_id: input.clientId, client_secret: input.clientSecret }\n : {}),\n };\n const { response, body } = await fetchBoundedProviderJson(\n tokenUrl,\n {\n method: \"POST\",\n headers:\n input.providerId === \"notion\"\n ? {\n Authorization: authorization,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n }\n : input.providerId === \"figma\"\n ? {\n Authorization: authorization,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n }\n : { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body:\n input.providerId === \"notion\"\n ? JSON.stringify(fields)\n : new URLSearchParams(fields),\n },\n input.provider.label,\n );\n const accessToken = text(body.access_token);\n if (!response.ok || !accessToken) {\n throw new Error(\n `${input.provider.label} OAuth token exchange failed (${response.status}).`,\n );\n }\n const expiresIn = Number(body.expires_in);\n return {\n ...body,\n ...(Number.isFinite(expiresIn) && expiresIn > 0\n ? { expiry_date: Date.now() + expiresIn * 1_000 }\n : {}),\n };\n}\n\nexport async function resolveWorkspaceProviderIdentity(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity> {\n const [identity] = await resolveWorkspaceProviderIdentities(\n providerId,\n tokens,\n );\n if (!identity) {\n throw new Error(\n `${providerId} OAuth response did not identify an account.`,\n );\n }\n return identity;\n}\n\nexport async function resolveWorkspaceProviderIdentities(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity[]> {\n if (providerId === \"jira\") {\n const accessToken = text(tokens.access_token);\n if (!accessToken) {\n throw new Error(\"Jira OAuth response did not include an access token.\");\n }\n const { response, body } = await fetchBoundedProviderJsonValue(\n \"https://api.atlassian.com/oauth/token/accessible-resources\",\n {\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n },\n \"Jira\",\n );\n if (!response.ok || !Array.isArray(body)) {\n throw new Error(\"Jira OAuth response did not identify accessible sites.\");\n }\n return body.flatMap((resource) => {\n const entry = record(resource);\n const cloudId = text(entry?.id);\n const siteUrl = text(entry?.url);\n if (!cloudId || !siteUrl) return [];\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(siteUrl);\n } catch {\n return [];\n }\n if (\n parsedUrl.protocol !== \"https:\" ||\n !parsedUrl.hostname.endsWith(\".atlassian.net\")\n ) {\n return [];\n }\n const scopes = Array.isArray(entry?.scopes)\n ? entry.scopes.filter(\n (scope): scope is string => typeof scope === \"string\",\n )\n : undefined;\n return [\n {\n accountId: cloudId,\n label: text(entry?.name) ?? parsedUrl.hostname,\n ...(scopes?.length ? { scopes } : {}),\n config: {\n atlassianCloudId: cloudId,\n atlassianApiBaseUrl: `https://api.atlassian.com/ex/jira/${encodeURIComponent(cloudId)}`,\n siteUrl: parsedUrl.origin,\n },\n },\n ];\n });\n }\n return [await resolveWorkspaceProviderIdentitySingle(providerId, tokens)];\n}\n\ntype WorkspaceProviderIdentity = {\n accountId: string;\n label: string;\n scopes?: string[];\n config?: Record<string, unknown>;\n};\n\nasync function resolveWorkspaceProviderIdentitySingle(\n providerId: GenericWorkspaceOAuthProvider,\n tokens: Record<string, unknown>,\n): Promise<WorkspaceProviderIdentity> {\n if (providerId === \"notion\") {\n const owner = record(tokens.owner);\n const user = record(owner?.user);\n const person = record(user?.person);\n const accountId =\n text(user?.id) ??\n text(person?.email) ??\n text(tokens.workspace_id) ??\n text(tokens.bot_id);\n if (!accountId)\n throw new Error(\n \"Notion OAuth response did not identify the connected user.\",\n );\n return {\n accountId,\n label:\n text(person?.email) ??\n text(tokens.workspace_name) ??\n \"Notion workspace\",\n };\n }\n if (providerId === \"github\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body: user } = await fetchBoundedProviderJson(\n \"https://api.github.com/user\",\n {\n headers: {\n Accept: \"application/vnd.github+json\",\n Authorization: `Bearer ${accessToken}`,\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n },\n \"GitHub\",\n );\n const accountId = text(user.login) ?? text(user.id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"GitHub OAuth response did not identify the connected user.\",\n );\n }\n return {\n accountId,\n label: text(user.name) ?? text(user.login) ?? \"GitHub account\",\n };\n }\n if (providerId === \"hubspot\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body } = await fetchBoundedProviderJson(\n `https://api.hubapi.com/oauth/v1/access-tokens/${encodeURIComponent(accessToken)}`,\n { headers: { Accept: \"application/json\" } },\n \"HubSpot\",\n );\n const accountId = scalarText(body.hub_id) ?? scalarText(body.user_id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"HubSpot OAuth response did not identify the connected portal.\",\n );\n }\n return {\n accountId,\n label: text(body.hub_domain) ?? `HubSpot portal ${accountId}`,\n };\n }\n if (providerId === \"salesforce\") {\n const instanceUrl = normalizeSalesforceInstanceUrl(\n text(tokens.instance_url),\n );\n const identity = parseSalesforceIdentityUrl(text(tokens.id));\n if (!instanceUrl || !identity) {\n throw new Error(\n \"Salesforce OAuth response did not identify the connected organization.\",\n );\n }\n return {\n accountId: identity.organizationId,\n label: instanceUrl.hostname,\n config: {\n salesforceInstanceUrl: instanceUrl.origin,\n salesforceIdentityUrl: identity.url.href,\n salesforceOrganizationId: identity.organizationId,\n },\n };\n }\n if (providerId === \"sentry\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body: user } = await fetchBoundedProviderJson(\n \"https://sentry.io/api/0/users/me/\",\n {\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n },\n \"Sentry\",\n );\n const accountId = text(user.id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Sentry OAuth response did not identify the connected account.\",\n );\n }\n return {\n accountId,\n label: text(user?.email) ?? text(user?.name) ?? \"Sentry account\",\n };\n }\n if (providerId === \"google_drive\") {\n const accessToken = text(tokens.access_token)!;\n const { response, body } = await fetchBoundedProviderJson(\n \"https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,permissionId)\",\n { headers: { Authorization: `Bearer ${accessToken}` } },\n \"Google Drive\",\n );\n const user = record(body.user);\n const accountId = text(user?.permissionId) ?? text(user?.emailAddress);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Google Drive OAuth response did not identify the connected account.\",\n );\n }\n return {\n accountId,\n label:\n text(user?.emailAddress) ??\n text(user?.displayName) ??\n \"Google Drive account\",\n };\n }\n const accessToken = text(tokens.access_token)!;\n const { response, body: me } = await fetchBoundedProviderJson(\n \"https://api.figma.com/v1/me\",\n { headers: { Authorization: `Bearer ${accessToken}` } },\n \"Figma\",\n );\n const accountId = text(me.id) ?? text(me.email) ?? text(tokens.user_id);\n if (!response.ok || !accountId) {\n throw new Error(\n \"Figma OAuth response did not identify the connected user.\",\n );\n }\n return {\n accountId,\n label: text(me.email) ?? text(me.handle) ?? \"Figma account\",\n };\n}\n\nfunction requiredProvider(\n providerId: GenericWorkspaceOAuthProvider,\n): WorkspaceConnectionProvider {\n const provider = getWorkspaceConnectionProvider(providerId);\n if (!provider?.oauth)\n throw new Error(`${providerId} OAuth is not configured.`);\n return provider;\n}\n\nfunction readStoredFlow(\n event: H3Event,\n provider: GenericWorkspaceOAuthProvider,\n): WorkspaceProviderOAuthFlow | null {\n const encrypted = getCookie(event, flowCookieName(provider));\n if (!encrypted) return null;\n try {\n return JSON.parse(\n decryptSecretValue(encrypted),\n ) as WorkspaceProviderOAuthFlow;\n } catch {\n return null;\n }\n}\n\nexport function isWorkspaceProviderOAuthFlowValid(input: {\n flow: WorkspaceProviderOAuthFlow;\n state: OAuthStatePayload;\n provider: GenericWorkspaceOAuthProvider;\n sessionEmail: string;\n sessionOrgId?: string;\n now?: number;\n}): boolean {\n return (\n input.flow.expiresAt >= (input.now ?? Date.now()) &&\n input.flow.provider === input.provider &&\n input.state.flowId === input.flow.flowId &&\n input.state.redirectUri === input.flow.redirectUri &&\n input.state.owner === input.flow.owner &&\n input.sessionEmail === input.flow.owner &&\n input.state.orgId === input.flow.orgId &&\n input.sessionOrgId === input.flow.orgId &&\n input.state.app === input.flow.appId\n );\n}\n\nexport function canConnectWorkspaceProviderOAuth(\n orgId: string | null | undefined,\n role: string | null | undefined,\n): boolean {\n return Boolean(orgId) && (role === \"owner\" || role === \"admin\");\n}\n\nexport function scopedOAuthAccountId(\n provider: GenericWorkspaceOAuthProvider,\n owner: string,\n accountId: string,\n): string {\n if (\n provider !== \"hubspot\" &&\n provider !== \"salesforce\" &&\n provider !== \"jira\"\n ) {\n return accountId;\n }\n const ownerKey = crypto\n .createHash(\"sha256\")\n .update(`${provider}:${owner.trim().toLowerCase()}`)\n .digest(\"hex\")\n .slice(0, 24);\n return `${accountId}::${ownerKey}`;\n}\n\nasync function fetchBoundedProviderJson(\n url: string,\n init: RequestInit,\n providerLabel: string,\n): Promise<{ response: Response; body: Record<string, unknown> }> {\n const { response, body } = await fetchBoundedProviderJsonValue(\n url,\n init,\n providerLabel,\n );\n return { response, body: record(body) ?? {} };\n}\n\nasync function fetchBoundedProviderJsonValue(\n url: string,\n init: RequestInit,\n providerLabel: string,\n): Promise<{ response: Response; body: unknown }> {\n let response: Response;\n try {\n response = await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(PROVIDER_REQUEST_TIMEOUT_MS),\n });\n } catch {\n throw new Error(`${providerLabel} OAuth request failed.`);\n }\n const declaredLength = Number(response.headers.get(\"content-length\"));\n if (\n Number.isFinite(declaredLength) &&\n declaredLength > PROVIDER_RESPONSE_MAX_BYTES\n ) {\n throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);\n }\n if (!response.body) return { response, body: {} };\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let length = 0;\n try {\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) break;\n length += chunk.value.byteLength;\n if (length > PROVIDER_RESPONSE_MAX_BYTES) {\n await reader.cancel();\n break;\n }\n chunks.push(chunk.value);\n }\n } catch {\n throw new Error(`${providerLabel} OAuth request failed.`);\n }\n if (length > PROVIDER_RESPONSE_MAX_BYTES) {\n throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);\n }\n try {\n const json = Buffer.concat(chunks).toString(\"utf8\");\n const body = JSON.parse(json) as unknown;\n return { response, body };\n } catch {\n return { response, body: {} };\n }\n}\n\nfunction tokenScopes(\n tokens: Record<string, unknown>,\n fallback: readonly string[],\n): string[] {\n const scope = text(tokens.scope);\n return scope ? scope.split(/[ ,]+/).filter(Boolean) : [...fallback];\n}\n\nexport function mergeWorkspaceOAuthValues(\n existing: readonly string[],\n incoming: readonly string[],\n): string[] {\n return [...new Set([...existing, ...incoming])];\n}\n\nfunction clientCredentialKeys(\n provider: GenericWorkspaceOAuthProvider,\n field: \"id\" | \"secret\",\n): string[] {\n const prefix =\n provider === \"google_drive\" ? \"GOOGLE\" : provider.toUpperCase();\n const suffix = field === \"id\" ? \"ID\" : \"SECRET\";\n if (provider === \"github\") {\n const integrationPrefix = `GITHUB_INTEGRATION_CLIENT_${suffix}`;\n return [integrationPrefix, `GITHUB_CLIENT_${suffix}`];\n }\n if (provider === \"hubspot\") {\n const integrationPrefix = `HUBSPOT_INTEGRATION_CLIENT_${suffix}`;\n return [integrationPrefix, `HUBSPOT_CLIENT_${suffix}`];\n }\n if (provider === \"salesforce\") {\n const integrationPrefix = `SALESFORCE_INTEGRATION_CLIENT_${suffix}`;\n const consumerCredential = `SALESFORCE_CONSUMER_${\n field === \"id\" ? \"KEY\" : \"SECRET\"\n }`;\n return [\n integrationPrefix,\n `SALESFORCE_CLIENT_${suffix}`,\n consumerCredential,\n ];\n }\n return [`${prefix}_CLIENT_${suffix}`];\n}\n\nfunction normalizeSalesforceInstanceUrl(value: string | undefined): URL | null {\n if (!value) return null;\n try {\n const url = new URL(value);\n const host = url.hostname.toLowerCase();\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.port ||\n (host !== \"salesforce.com\" && !host.endsWith(\".salesforce.com\"))\n ) {\n return null;\n }\n return new URL(url.origin);\n } catch {\n return null;\n }\n}\n\nfunction parseSalesforceIdentityUrl(\n value: string | undefined,\n): { organizationId: string; url: URL } | null {\n if (!value) return null;\n try {\n const url = new URL(value);\n const host = url.hostname.toLowerCase();\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.port ||\n (host !== \"salesforce.com\" && !host.endsWith(\".salesforce.com\"))\n ) {\n return null;\n }\n const match = url.pathname.match(/^\\/id\\/([^/]+)\\/[^/]+\\/?$/);\n if (!match?.[1]) return null;\n return { organizationId: match[1], url };\n } catch {\n return null;\n }\n}\n\nexport function resolveSalesforceOAuthLoginUrl(\n environment: string | undefined,\n): string | null {\n const normalized = environment?.trim().toLowerCase();\n if (!normalized || normalized === \"production\") {\n return SALESFORCE_PRODUCTION_LOGIN_URL;\n }\n if (normalized === \"sandbox\") return SALESFORCE_SANDBOX_LOGIN_URL;\n return null;\n}\n\nexport function salesforceOAuthEndpoint(\n loginUrl: string,\n phase: \"authorize\" | \"token\",\n): string {\n if (\n loginUrl !== SALESFORCE_PRODUCTION_LOGIN_URL &&\n loginUrl !== SALESFORCE_SANDBOX_LOGIN_URL\n ) {\n throw new Error(\"Invalid Salesforce OAuth login URL.\");\n }\n return `${loginUrl}/services/oauth2/${phase}`;\n}\n\nasync function resolveProviderClientCredentials(\n provider: GenericWorkspaceOAuthProvider,\n): Promise<[string | null, string | null]> {\n const [clientId, clientSecret] = await Promise.all(\n ([\"id\", \"secret\"] as const).map(async (field) => {\n for (const key of clientCredentialKeys(provider, field)) {\n const value = await resolveSecret(key);\n if (value) return value;\n }\n return null;\n }),\n );\n return [clientId, clientSecret];\n}\n\nfunction flowCookieName(provider: GenericWorkspaceOAuthProvider): string {\n return `an_workspace_oauth_${provider}`;\n}\n\nfunction normalizeAppId(value: string): string {\n const normalized = value.trim().toLowerCase();\n if (!/^[a-z0-9][a-z0-9_-]{0,99}$/.test(normalized)) {\n throw new Error(\"OAuth appId is invalid.\");\n }\n return normalized;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction scalarText(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return text(value);\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction methodNotAllowed(event: H3Event) {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n}\n\nfunction unauthorized(event: H3Event) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n}\n\nasync function requireWorkspaceProviderOAuthAdmin(event: H3Event) {\n const context = await getOrgContext(event).catch(() => null);\n if (\n !context ||\n !canConnectWorkspaceProviderOAuth(context.orgId, context.role)\n ) {\n setResponseStatus(event, 403);\n return null;\n }\n return context;\n}\n"]}
|
|
@@ -771,6 +771,7 @@
|
|
|
771
771
|
|
|
772
772
|
.agent-composer-missing-key-trigger {
|
|
773
773
|
display: flex;
|
|
774
|
+
cursor: pointer;
|
|
774
775
|
min-height: 4.5rem;
|
|
775
776
|
width: 100%;
|
|
776
777
|
flex: 1;
|
|
@@ -783,6 +784,9 @@
|
|
|
783
784
|
text-align: start;
|
|
784
785
|
color: hsl(var(--foreground));
|
|
785
786
|
outline: none;
|
|
787
|
+
transition:
|
|
788
|
+
background-color 150ms ease-out,
|
|
789
|
+
box-shadow 150ms ease-out;
|
|
786
790
|
}
|
|
787
791
|
|
|
788
792
|
.agent-composer-missing-key-trigger:hover {
|
|
@@ -793,6 +797,14 @@
|
|
|
793
797
|
box-shadow: inset 0 0 0 2px hsl(var(--ring));
|
|
794
798
|
}
|
|
795
799
|
|
|
800
|
+
.agent-composer-missing-key-content {
|
|
801
|
+
display: flex;
|
|
802
|
+
min-width: 0;
|
|
803
|
+
flex-direction: column;
|
|
804
|
+
align-items: flex-start;
|
|
805
|
+
gap: 0.5rem;
|
|
806
|
+
}
|
|
807
|
+
|
|
796
808
|
.agent-composer-missing-key-copy {
|
|
797
809
|
display: flex;
|
|
798
810
|
min-width: 0;
|
|
@@ -812,6 +824,31 @@
|
|
|
812
824
|
color: hsl(var(--muted-foreground));
|
|
813
825
|
}
|
|
814
826
|
|
|
827
|
+
.agent-composer-missing-key-cta {
|
|
828
|
+
display: inline-flex;
|
|
829
|
+
min-height: 2rem;
|
|
830
|
+
align-items: center;
|
|
831
|
+
justify-content: center;
|
|
832
|
+
border-radius: 0.375rem;
|
|
833
|
+
background: hsl(var(--foreground));
|
|
834
|
+
padding: 0.5rem 0.75rem;
|
|
835
|
+
color: hsl(var(--background));
|
|
836
|
+
font-size: 0.75rem;
|
|
837
|
+
font-weight: 600;
|
|
838
|
+
line-height: 1rem;
|
|
839
|
+
transition:
|
|
840
|
+
opacity 150ms ease-out,
|
|
841
|
+
transform 150ms ease-out;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
.agent-composer-missing-key-trigger:hover .agent-composer-missing-key-cta {
|
|
845
|
+
opacity: 0.9;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.agent-composer-missing-key-trigger:active .agent-composer-missing-key-cta {
|
|
849
|
+
transform: scale(0.98);
|
|
850
|
+
}
|
|
851
|
+
|
|
815
852
|
.agent-composer-root--hero .agent-composer-missing-key-trigger {
|
|
816
853
|
min-height: 7.5rem;
|
|
817
854
|
justify-content: center;
|
|
@@ -824,6 +861,10 @@
|
|
|
824
861
|
line-height: 1.375rem;
|
|
825
862
|
}
|
|
826
863
|
|
|
864
|
+
.agent-composer-root--hero .agent-composer-missing-key-content {
|
|
865
|
+
align-items: center;
|
|
866
|
+
}
|
|
867
|
+
|
|
827
868
|
.agent-composer-stack {
|
|
828
869
|
position: relative;
|
|
829
870
|
flex-shrink: 0;
|
|
@@ -881,13 +922,15 @@
|
|
|
881
922
|
line-height: 1.125rem;
|
|
882
923
|
}
|
|
883
924
|
|
|
884
|
-
.agent-thinking-indicator__text
|
|
925
|
+
.agent-thinking-indicator__text,
|
|
926
|
+
.agent-running-shimmer {
|
|
885
927
|
display: inline-block;
|
|
886
928
|
}
|
|
887
929
|
|
|
888
930
|
@media (prefers-reduced-motion: no-preference) {
|
|
889
931
|
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
|
|
890
|
-
.agent-thinking-indicator__text
|
|
932
|
+
.agent-thinking-indicator__text,
|
|
933
|
+
.agent-running-shimmer {
|
|
891
934
|
color: transparent;
|
|
892
935
|
background: linear-gradient(
|
|
893
936
|
90deg,
|