@agent-native/core 0.103.1 → 0.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +30 -0
- package/corpus/core/package.json +9 -2
- package/corpus/core/src/agent/engine/credential-errors.ts +2 -2
- package/corpus/core/src/agent/production-agent.ts +30 -0
- package/corpus/core/src/agent/run-store.ts +12 -2
- package/corpus/core/src/cli/create.ts +1 -0
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +30 -11
- package/corpus/core/src/cli/templates-meta.ts +4 -3
- package/corpus/core/src/client/AgentAskPopover.tsx +89 -0
- package/corpus/core/src/client/AgentChatHome.tsx +4 -0
- package/corpus/core/src/client/AgentPanel.tsx +321 -223
- package/corpus/core/src/client/AssistantChat.tsx +6 -10
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +53 -372
- package/corpus/core/src/client/agent-chat-adapter.ts +13 -1
- package/corpus/core/src/client/agent-page/AgentContextTab.tsx +133 -149
- package/corpus/core/src/client/agent-page/AgentEmptyState.tsx +44 -0
- package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +153 -82
- package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +39 -0
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +368 -356
- package/corpus/core/src/client/agent-page/types.ts +1 -1
- package/corpus/core/src/client/analytics.ts +51 -5
- package/corpus/core/src/client/chat/run-recovery.tsx +12 -4
- package/corpus/core/src/client/composer/PromptComposer.tsx +5 -15
- package/corpus/core/src/client/composer/TiptapComposer.tsx +32 -3
- package/corpus/core/src/client/dynamic-suggestions.ts +3 -3
- package/corpus/core/src/client/index.ts +16 -1
- package/corpus/core/src/client/resources/ResourceTree.tsx +249 -38
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +307 -140
- package/corpus/core/src/client/session-replay.ts +158 -5
- package/corpus/core/src/client/settings/AutomationsSection.tsx +30 -10
- package/corpus/core/src/client/settings/SettingsPanel.tsx +3 -2
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +2 -0
- package/corpus/core/src/client/settings/agent-settings-search.ts +2 -2
- package/corpus/core/src/client/use-chat-threads.ts +2 -0
- package/corpus/core/src/connections/catalog.ts +49 -7
- package/corpus/core/src/db/index.ts +6 -1
- package/corpus/core/src/extensions/actions.ts +106 -16
- package/corpus/core/src/extensions/content-patch.ts +22 -0
- package/corpus/core/src/extensions/routes.ts +18 -0
- package/corpus/core/src/extensions/store.ts +8 -0
- package/corpus/core/src/index.ts +3 -0
- package/corpus/core/src/ingestion/docx.ts +158 -0
- package/corpus/core/src/ingestion/figma-node-to-html.ts +1860 -0
- package/corpus/core/src/ingestion/figma.ts +548 -0
- package/corpus/core/src/ingestion/index.ts +107 -0
- package/corpus/core/src/ingestion/media.ts +264 -0
- package/corpus/core/src/ingestion/notion.ts +121 -0
- package/corpus/core/src/ingestion/office.ts +214 -0
- package/corpus/core/src/ingestion/orchestration.ts +160 -0
- package/corpus/core/src/ingestion/pptx.ts +333 -0
- package/corpus/core/src/ingestion/selection.ts +81 -0
- package/corpus/core/src/ingestion/website.ts +151 -0
- package/corpus/core/src/integrations/plugin.ts +45 -37
- package/corpus/core/src/localization/default-messages.ts +35 -12
- package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
- package/corpus/core/src/observability/traces.ts +5 -3
- package/corpus/core/src/provider-api/index.ts +452 -8
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +18 -1
- package/corpus/core/src/search-utils/index.ts +112 -0
- package/corpus/core/src/secrets/register-framework-secrets.ts +61 -0
- package/corpus/core/src/server/action-discovery.ts +33 -8
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
- package/corpus/core/src/server/agent-chat/prompt-resources.ts +144 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
- package/corpus/core/src/server/core-routes-plugin.ts +12 -0
- package/corpus/core/src/server/index.ts +30 -0
- package/corpus/core/src/server/workspace-provider-oauth.ts +583 -0
- package/corpus/core/src/styles/agent-native.css +9 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +3 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/corpus/core/src/templates/workspace-root/.env.example +12 -0
- package/corpus/core/src/workspace-connections/index.ts +6 -0
- package/corpus/core/src/workspace-connections/lifecycle.ts +43 -0
- package/corpus/core/src/workspace-connections/store.ts +16 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +46 -3
- package/corpus/templates/analytics/AGENTS.md +9 -0
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +120 -6
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +92 -30
- package/corpus/templates/analytics/actions/update-dashboard.ts +5 -5
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +313 -220
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +9 -6
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +90 -64
- package/corpus/templates/analytics/app/i18n-data.ts +3 -3
- package/corpus/templates/analytics/app/lib/dashboard-list-loading.ts +25 -0
- package/corpus/templates/analytics/app/lib/item-popularity.ts +13 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +8 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +15 -3
- package/corpus/templates/analytics/changelog/2026-07-16-dashboard-filter-defaults-can-now-be-changed-reliably-withou.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-dashboard-lists-load-in-one-stable-order-without-popping-bet.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-fixed-dashboard-filter-dropdown-text-alignment.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-recurring-signed-in-users-can-now-be-viewed-as-weekly-bars-b.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-the-analytics-agent-can-now-duplicate-a-chart-and-place-the-.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +41 -1
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +47 -1
- package/corpus/templates/analytics/server/lib/session-replay.ts +68 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/analytics/server/routes/sessions/lookup.get.ts +47 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +16 -9
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +86 -0
- package/corpus/templates/assets/AGENTS.md +10 -0
- package/corpus/templates/assets/actions/create-generation-session.ts +59 -1
- package/corpus/templates/assets/actions/edit-image.ts +2 -0
- package/corpus/templates/assets/actions/generate-asset.ts +52 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +55 -0
- package/corpus/templates/assets/actions/generate-image.ts +219 -1
- package/corpus/templates/assets/actions/open-asset-picker.ts +14 -0
- package/corpus/templates/assets/actions/refine-image.ts +3 -0
- package/corpus/templates/assets/actions/restyle-image.ts +2 -0
- package/corpus/templates/assets/agent-native.app-skill.json +4 -0
- package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/assets/app/i18n-data.ts +29 -13
- package/corpus/templates/assets/app/routes/agent.tsx +7 -1
- package/corpus/templates/assets/app/routes/library.tsx +9 -0
- package/corpus/templates/assets/app/routes/settings.tsx +3 -0
- package/corpus/templates/assets/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/assets/package.json +1 -0
- package/corpus/templates/assets/server/lib/image-processing.ts +1 -22
- package/corpus/templates/assets/server/plugins/creative-context.ts +205 -0
- package/corpus/templates/brain/app/i18n-data.ts +3 -3
- package/corpus/templates/brain/app/lib/brain.ts +1 -1
- package/corpus/templates/brain/server/lib/search.ts +17 -67
- package/corpus/templates/calendar/app/i18n-data.ts +3 -3
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +19 -18
- package/corpus/templates/chat/app/i18n/en-US.ts +3 -3
- package/corpus/templates/chat/app/lib/agent-page.tsx +10 -1
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +1 -1
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/cleanup-transcript.ts +35 -4
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-organization.ts +3 -2
- package/corpus/templates/clips/actions/create-recording.ts +4 -1
- package/corpus/templates/clips/actions/finalize-recording.ts +44 -7
- package/corpus/templates/clips/actions/import-loom-recording.ts +4 -1
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +2 -2
- package/corpus/templates/clips/actions/list-meetings.ts +23 -5
- package/corpus/templates/clips/actions/list-organization-state.ts +1 -1
- package/corpus/templates/clips/actions/remove-silences.ts +10 -1
- package/corpus/templates/clips/actions/request-transcript.ts +53 -11
- package/corpus/templates/clips/actions/search-recordings-utils.ts +7 -0
- package/corpus/templates/clips/actions/search-recordings.ts +5 -8
- package/corpus/templates/clips/actions/set-organization-branding.ts +2 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +10 -5
- package/corpus/templates/clips/actions/update-ai-request-status.ts +38 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +3 -4
- package/corpus/templates/clips/app/components/editor/editor-selection.ts +19 -0
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +10 -10
- package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +1 -2
- package/corpus/templates/clips/app/components/library/library-grid.tsx +101 -93
- package/corpus/templates/clips/app/components/player/video-player.tsx +11 -0
- package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +53 -1
- package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -4
- package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +5 -9
- package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +6 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +129 -27
- package/corpus/templates/clips/app/routes/record.tsx +23 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -2
- package/corpus/templates/clips/changelog/2026-07-16-authorized-viewers-can-open-shared-private-clips-without-a-m.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-camera-bubble-hover-controls-appear-above-the-face.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-chrome-extension-recovers-stale-recorder-state.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-clips-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-clips-search-now-matches-recording-content-without-requiring.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-declined-meetings-no-longer-show-desktop-reminders.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-failed-desktop-saves-now-show-their-local-recovery-copy.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-long-desktop-clips-now-preserve-complete-playback-synced-aud.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-long-recording-lists-keep-stitch-and-library-actions-visible.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-organization-admins-can-choose-new-recording-visibility.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-remove-silences-now-shows-queued-active-completed-and-failed.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-settings-no-longer-repeats-the-builder-connection-status-in-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-transcripts-now-appear-from-native-browser-speech-sooner-wit.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +73 -1
- package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +32 -0
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +248 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +106 -0
- package/corpus/templates/clips/desktop/src/app.tsx +66 -28
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +335 -285
- package/corpus/templates/clips/desktop/src/lib/single-flight.ts +7 -0
- package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +51 -0
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +2 -2
- package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +10 -2
- package/corpus/templates/clips/desktop/src/styles.css +13 -11
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +8 -9
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +88 -13
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +13 -2
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +241 -6
- package/corpus/templates/clips/server/db/schema.ts +2 -2
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +64 -67
- package/corpus/templates/clips/server/lib/calendar-event-classification.ts +19 -0
- package/corpus/templates/clips/server/lib/google-calendar-client.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +40 -1
- package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/clips/server/plugins/db.ts +2 -2
- package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +1 -1
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -5
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +51 -1
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +1 -64
- package/corpus/templates/clips/shared/media-worker-contract.ts +32 -15
- package/corpus/templates/content/.agents/skills/content/SKILL.md +16 -0
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +85 -0
- package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +8 -0
- package/corpus/templates/content/AGENTS.md +9 -0
- package/corpus/templates/content/actions/create-document.ts +94 -0
- package/corpus/templates/content/actions/edit-document.ts +144 -4
- package/corpus/templates/content/actions/update-document.ts +138 -0
- package/corpus/templates/content/agent-native.app-skill.json +4 -0
- package/corpus/templates/content/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/content/app/i18n-data.ts +13 -4
- package/corpus/templates/content/app/routes/_app.agent.tsx +2 -1
- package/corpus/templates/content/app/routes/_app.settings.tsx +3 -0
- package/corpus/templates/content/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/content/package.json +1 -0
- package/corpus/templates/content/server/plugins/creative-context.ts +31 -0
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +116 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +16 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
- package/corpus/templates/design/AGENTS.md +6 -0
- package/corpus/templates/design/actions/clone-creative-context-design.ts +176 -0
- package/corpus/templates/design/actions/edit-design.ts +128 -0
- package/corpus/templates/design/actions/generate-design.ts +278 -14
- package/corpus/templates/design/actions/generate-screens.ts +42 -1
- package/corpus/templates/design/agent-native.app-skill.json +4 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -3
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +10 -4
- package/corpus/templates/design/app/routes/agent.tsx +2 -1
- package/corpus/templates/design/app/routes/settings.tsx +3 -0
- package/corpus/templates/design/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/design/changelog/2026-07-16-design-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/lib/figma-design-context.ts +5 -335
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1 -1859
- package/corpus/templates/design/server/lib/import-design-files.ts +6 -8
- package/corpus/templates/design/server/plugins/creative-context.ts +31 -0
- package/corpus/templates/design/shared/generation-session.ts +7 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +3 -3
- package/corpus/templates/forms/app/i18n/en-US.ts +3 -3
- package/corpus/templates/macros/app/i18n/en-US.ts +3 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +35 -5
- package/corpus/templates/mail/app/i18n/en-US.ts +3 -3
- package/corpus/templates/mail/changelog/2026-07-16-mail-previews-now-expand-to-show-the-full-message-without-an.md +6 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +30 -11
- package/corpus/templates/plan/AGENTS.md +21 -1
- package/corpus/templates/plan/actions/get-visual-plan.ts +1 -1
- package/corpus/templates/plan/actions/patch-visual-plan-source.ts +161 -0
- package/corpus/templates/plan/actions/read-visual-plan-source.ts +1 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +126 -10
- package/corpus/templates/plan/app/hooks/use-plans.ts +2 -0
- package/corpus/templates/plan/app/i18n/en-US.ts +3 -3
- package/corpus/templates/plan/app/pages/PlansPage.tsx +65 -62
- package/corpus/templates/plan/changelog/2026-07-16-local-plan-previews-now-load-annotations-containing-html-lik.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-16-plan-agents-now-prevent-stale-edits-from-overwriting-newer-p.md +6 -0
- package/corpus/templates/plan/server/plan-mdx.ts +75 -2
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +21 -4
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +122 -0
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +11 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +12 -3
- package/corpus/templates/slides/AGENTS.md +6 -0
- package/corpus/templates/slides/actions/add-slide.ts +230 -14
- package/corpus/templates/slides/actions/clone-context-slide.ts +302 -0
- package/corpus/templates/slides/actions/create-deck.ts +130 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +6 -2
- package/corpus/templates/slides/actions/import-file.ts +5 -4
- package/corpus/templates/slides/actions/patch-deck.ts +200 -10
- package/corpus/templates/slides/actions/update-slide.ts +208 -15
- package/corpus/templates/slides/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +16 -1
- package/corpus/templates/slides/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +6 -3
- package/corpus/templates/slides/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +176 -0
- package/corpus/templates/slides/app/routes/agent.tsx +7 -1
- package/corpus/templates/slides/app/routes/settings.tsx +3 -0
- package/corpus/templates/slides/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-16-google-slides-native-cloning.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/handlers/import/docx-parser.ts +4 -85
- package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +7 -421
- package/corpus/templates/slides/server/plugins/creative-context.ts +166 -0
- package/dist/agent/engine/credential-errors.d.ts +1 -1
- package/dist/agent/engine/credential-errors.d.ts.map +1 -1
- package/dist/agent/engine/credential-errors.js +2 -2
- package/dist/agent/engine/credential-errors.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +25 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +12 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +1 -0
- package/dist/cli/create.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 +30 -11
- 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 +4 -3
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AgentAskPopover.d.ts +11 -0
- package/dist/client/AgentAskPopover.d.ts.map +1 -0
- package/dist/client/AgentAskPopover.js +30 -0
- package/dist/client/AgentAskPopover.js.map +1 -0
- package/dist/client/AgentChatHome.d.ts +1 -1
- package/dist/client/AgentChatHome.d.ts.map +1 -1
- package/dist/client/AgentChatHome.js +2 -2
- package/dist/client/AgentChatHome.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +9 -19
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +119 -80
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +4 -4
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts +3 -9
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +49 -189
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentContextTab.js +26 -28
- package/dist/client/agent-page/AgentContextTab.js.map +1 -1
- package/dist/client/agent-page/AgentEmptyState.d.ts +13 -0
- package/dist/client/agent-page/AgentEmptyState.d.ts.map +1 -0
- package/dist/client/agent-page/AgentEmptyState.js +6 -0
- package/dist/client/agent-page/AgentEmptyState.js.map +1 -0
- package/dist/client/agent-page/AgentJobsTab.d.ts +1 -1
- package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.js +90 -58
- package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/client/agent-page/AgentTabFrame.d.ts +12 -0
- package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -0
- package/dist/client/agent-page/AgentTabFrame.js +7 -0
- package/dist/client/agent-page/AgentTabFrame.js.map +1 -0
- package/dist/client/agent-page/AgentTabsPage.d.ts +9 -1
- package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +135 -99
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/agent-page/types.d.ts +1 -1
- package/dist/client/agent-page/types.d.ts.map +1 -1
- package/dist/client/agent-page/types.js.map +1 -1
- package/dist/client/analytics.d.ts +10 -3
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +37 -2
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +10 -3
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +2 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +15 -3
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/dynamic-suggestions.js +3 -3
- package/dist/client/dynamic-suggestions.js.map +1 -1
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts +5 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +74 -5
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts +11 -2
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +105 -31
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/session-replay.d.ts +28 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +122 -8
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/AutomationsSection.d.ts +3 -1
- package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
- package/dist/client/settings/AutomationsSection.js +16 -6
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +3 -3
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +2 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/client/settings/agent-settings-search.js +2 -2
- package/dist/client/settings/agent-settings-search.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +2 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +41 -7
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +40 -7
- package/dist/connections/catalog.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -2
- package/dist/db/index.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +85 -15
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/content-patch.d.ts +4 -0
- package/dist/extensions/content-patch.d.ts.map +1 -1
- package/dist/extensions/content-patch.js +18 -0
- package/dist/extensions/content-patch.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +14 -0
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/store.d.ts +1 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +4 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ingestion/docx.d.ts +16 -0
- package/dist/ingestion/docx.d.ts.map +1 -0
- package/dist/ingestion/docx.js +129 -0
- package/dist/ingestion/docx.js.map +1 -0
- package/dist/ingestion/figma-node-to-html.d.ts +304 -0
- package/dist/ingestion/figma-node-to-html.d.ts.map +1 -0
- package/dist/ingestion/figma-node-to-html.js +1292 -0
- package/dist/ingestion/figma-node-to-html.js.map +1 -0
- package/dist/ingestion/figma.d.ts +115 -0
- package/dist/ingestion/figma.d.ts.map +1 -0
- package/dist/ingestion/figma.js +399 -0
- package/dist/ingestion/figma.js.map +1 -0
- package/dist/ingestion/index.d.ts +11 -0
- package/dist/ingestion/index.d.ts.map +1 -0
- package/dist/ingestion/index.js +11 -0
- package/dist/ingestion/index.js.map +1 -0
- package/dist/ingestion/media.d.ts +36 -0
- package/dist/ingestion/media.d.ts.map +1 -0
- package/dist/ingestion/media.js +178 -0
- package/dist/ingestion/media.js.map +1 -0
- package/dist/ingestion/notion.d.ts +12 -0
- package/dist/ingestion/notion.d.ts.map +1 -0
- package/dist/ingestion/notion.js +104 -0
- package/dist/ingestion/notion.js.map +1 -0
- package/dist/ingestion/office.d.ts +45 -0
- package/dist/ingestion/office.d.ts.map +1 -0
- package/dist/ingestion/office.js +141 -0
- package/dist/ingestion/office.js.map +1 -0
- package/dist/ingestion/orchestration.d.ts +52 -0
- package/dist/ingestion/orchestration.d.ts.map +1 -0
- package/dist/ingestion/orchestration.js +89 -0
- package/dist/ingestion/orchestration.js.map +1 -0
- package/dist/ingestion/pptx.d.ts +28 -0
- package/dist/ingestion/pptx.d.ts.map +1 -0
- package/dist/ingestion/pptx.js +255 -0
- package/dist/ingestion/pptx.js.map +1 -0
- package/dist/ingestion/selection.d.ts +20 -0
- package/dist/ingestion/selection.d.ts.map +1 -0
- package/dist/ingestion/selection.js +52 -0
- package/dist/ingestion/selection.js.map +1 -0
- package/dist/ingestion/website.d.ts +27 -0
- package/dist/ingestion/website.d.ts.map +1 -0
- package/dist/ingestion/website.js +100 -0
- package/dist/ingestion/website.js.map +1 -0
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +32 -27
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/localization/default-messages.d.ts +22 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +31 -9
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/hosted-model-experiment.d.ts +39 -0
- package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
- package/dist/observability/hosted-model-experiment.js +90 -0
- package/dist/observability/hosted-model-experiment.js.map +1 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +5 -3
- package/dist/observability/traces.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +35 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +339 -8
- package/dist/provider-api/index.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +18 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/search-utils/index.d.ts +12 -0
- package/dist/search-utils/index.d.ts.map +1 -0
- package/dist/search-utils/index.js +95 -0
- package/dist/search-utils/index.js.map +1 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +57 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/action-discovery.d.ts +8 -0
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +26 -9
- package/dist/server/action-discovery.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/prompt-resources.d.ts +19 -0
- package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
- package/dist/server/agent-chat/prompt-resources.js +95 -0
- package/dist/server/agent-chat/prompt-resources.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +7 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +5 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +48 -0
- package/dist/server/workspace-provider-oauth.d.ts.map +1 -0
- package/dist/server/workspace-provider-oauth.js +415 -0
- package/dist/server/workspace-provider-oauth.js.map +1 -0
- package/dist/styles/agent-native.css +9 -0
- package/dist/templates/chat/app/i18n/en-US.ts +3 -3
- package/dist/templates/chat/app/lib/agent-page.tsx +10 -1
- package/dist/templates/default/app/i18n/en-US.ts +3 -3
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/dist/templates/workspace-root/.env.example +12 -0
- package/dist/workspace-connections/index.d.ts +1 -0
- package/dist/workspace-connections/index.d.ts.map +1 -1
- package/dist/workspace-connections/index.js +1 -0
- package/dist/workspace-connections/index.js.map +1 -1
- package/dist/workspace-connections/lifecycle.d.ts +16 -0
- package/dist/workspace-connections/lifecycle.d.ts.map +1 -0
- package/dist/workspace-connections/lifecycle.js +14 -0
- package/dist/workspace-connections/lifecycle.js.map +1 -0
- package/dist/workspace-connections/store.d.ts.map +1 -1
- package/dist/workspace-connections/store.js +16 -0
- package/dist/workspace-connections/store.js.map +1 -1
- package/package.json +10 -3
- package/src/templates/chat/app/i18n/en-US.ts +3 -3
- package/src/templates/chat/app/lib/agent-page.spec.tsx +10 -1
- package/src/templates/chat/app/lib/agent-page.tsx +10 -1
- package/src/templates/default/app/i18n/en-US.ts +3 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/src/templates/workspace-root/.env.example +12 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { deleteCookie, defineEventHandler, getCookie, getMethod, getQuery, setCookie, setResponseStatus, } from "h3";
|
|
3
|
+
import { getWorkspaceConnectionProvider, } from "../connections/catalog.js";
|
|
4
|
+
import { saveOAuthTokens, setOAuthDisplayName } from "../oauth-tokens/store.js";
|
|
5
|
+
import { decryptSecretValue, encryptSecretValue } from "../secrets/crypto.js";
|
|
6
|
+
import { listWorkspaceConnections, upsertWorkspaceConnection, upsertWorkspaceConnectionGrant, } from "../workspace-connections/store.js";
|
|
7
|
+
import { getSession, safeReturnPath } from "./auth.js";
|
|
8
|
+
import { resolveSecret } from "./credential-provider.js";
|
|
9
|
+
import { decodeOAuthState, encodeOAuthState, getAppUrl, resolveOAuthRedirectUri, } from "./google-oauth.js";
|
|
10
|
+
import { runWithRequestContext } from "./request-context.js";
|
|
11
|
+
const SUPPORTED_PROVIDERS = new Set([
|
|
12
|
+
"figma",
|
|
13
|
+
"google_drive",
|
|
14
|
+
"notion",
|
|
15
|
+
]);
|
|
16
|
+
const FLOW_TTL_SECONDS = 10 * 60;
|
|
17
|
+
const PROVIDER_REQUEST_TIMEOUT_MS = 10_000;
|
|
18
|
+
const PROVIDER_RESPONSE_MAX_BYTES = 256 * 1024;
|
|
19
|
+
export function workspaceProviderOAuthPath(provider, phase) {
|
|
20
|
+
return `/_agent-native/connections/oauth/${provider}/${phase}`;
|
|
21
|
+
}
|
|
22
|
+
export function createWorkspaceProviderOAuthHandler(provider, phase) {
|
|
23
|
+
if (!SUPPORTED_PROVIDERS.has(provider)) {
|
|
24
|
+
throw new Error(`Unsupported workspace OAuth provider: ${provider}`);
|
|
25
|
+
}
|
|
26
|
+
return defineEventHandler((event) => phase === "start"
|
|
27
|
+
? handleWorkspaceProviderOAuthStart(event, provider)
|
|
28
|
+
: handleWorkspaceProviderOAuthCallback(event, provider));
|
|
29
|
+
}
|
|
30
|
+
export async function handleWorkspaceProviderOAuthStart(event, providerId) {
|
|
31
|
+
if (getMethod(event) !== "GET")
|
|
32
|
+
return methodNotAllowed(event);
|
|
33
|
+
const session = await getSession(event).catch(() => null);
|
|
34
|
+
if (!session?.email)
|
|
35
|
+
return unauthorized(event);
|
|
36
|
+
const provider = requiredProvider(providerId);
|
|
37
|
+
const query = getQuery(event);
|
|
38
|
+
const appId = normalizeAppId(text(query.appId) ??
|
|
39
|
+
process.env.AGENT_NATIVE_WORKSPACE_APP_ID ??
|
|
40
|
+
process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID ??
|
|
41
|
+
"creative-context");
|
|
42
|
+
const redirectUri = resolveOAuthRedirectUri(event, workspaceProviderOAuthPath(providerId, "callback"));
|
|
43
|
+
if (!redirectUri) {
|
|
44
|
+
setResponseStatus(event, 400);
|
|
45
|
+
return { error: "Invalid OAuth redirect URI." };
|
|
46
|
+
}
|
|
47
|
+
return runWithRequestContext({ userEmail: session.email, orgId: session.orgId }, async () => {
|
|
48
|
+
const [clientId, clientSecret] = await Promise.all([
|
|
49
|
+
resolveSecret(clientCredentialKey(providerId, "id")),
|
|
50
|
+
resolveSecret(clientCredentialKey(providerId, "secret")),
|
|
51
|
+
]);
|
|
52
|
+
if (!clientId || !clientSecret) {
|
|
53
|
+
setResponseStatus(event, 503);
|
|
54
|
+
return {
|
|
55
|
+
error: `${provider.label} OAuth client credentials are not configured.`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const verifier = crypto.randomBytes(48).toString("base64url");
|
|
59
|
+
const challenge = crypto
|
|
60
|
+
.createHash("sha256")
|
|
61
|
+
.update(verifier)
|
|
62
|
+
.digest("base64url");
|
|
63
|
+
const flowId = crypto.randomUUID();
|
|
64
|
+
const requestedReturnUrl = text(query.return);
|
|
65
|
+
const returnUrl = requestedReturnUrl
|
|
66
|
+
? safeReturnPath(requestedReturnUrl)
|
|
67
|
+
: undefined;
|
|
68
|
+
const state = encodeOAuthState({
|
|
69
|
+
redirectUri,
|
|
70
|
+
owner: session.email,
|
|
71
|
+
orgId: session.orgId,
|
|
72
|
+
app: appId,
|
|
73
|
+
returnUrl,
|
|
74
|
+
flowId,
|
|
75
|
+
});
|
|
76
|
+
const flow = {
|
|
77
|
+
provider: providerId,
|
|
78
|
+
flowId,
|
|
79
|
+
verifier,
|
|
80
|
+
redirectUri,
|
|
81
|
+
owner: session.email,
|
|
82
|
+
...(session.orgId ? { orgId: session.orgId } : {}),
|
|
83
|
+
appId,
|
|
84
|
+
expiresAt: Date.now() + FLOW_TTL_SECONDS * 1_000,
|
|
85
|
+
};
|
|
86
|
+
setCookie(event, flowCookieName(providerId), encryptSecretValue(JSON.stringify(flow)), {
|
|
87
|
+
httpOnly: true,
|
|
88
|
+
secure: redirectUri.startsWith("https://"),
|
|
89
|
+
sameSite: "lax",
|
|
90
|
+
path: "/",
|
|
91
|
+
maxAge: FLOW_TTL_SECONDS,
|
|
92
|
+
});
|
|
93
|
+
const authorizationUrl = buildWorkspaceProviderAuthorizationUrl({
|
|
94
|
+
provider,
|
|
95
|
+
clientId,
|
|
96
|
+
redirectUri,
|
|
97
|
+
state,
|
|
98
|
+
challenge,
|
|
99
|
+
});
|
|
100
|
+
return Response.redirect(authorizationUrl, 302);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
export async function handleWorkspaceProviderOAuthCallback(event, providerId) {
|
|
104
|
+
if (getMethod(event) !== "GET")
|
|
105
|
+
return methodNotAllowed(event);
|
|
106
|
+
const session = await getSession(event).catch(() => null);
|
|
107
|
+
if (!session?.email)
|
|
108
|
+
return unauthorized(event);
|
|
109
|
+
const query = getQuery(event);
|
|
110
|
+
const code = text(query.code);
|
|
111
|
+
const stateParam = text(query.state);
|
|
112
|
+
const providerError = text(query.error);
|
|
113
|
+
if (providerError) {
|
|
114
|
+
setResponseStatus(event, 400);
|
|
115
|
+
return { error: "OAuth authorization was not completed." };
|
|
116
|
+
}
|
|
117
|
+
if (!code || !stateParam) {
|
|
118
|
+
setResponseStatus(event, 400);
|
|
119
|
+
return { error: "OAuth callback is missing code or state." };
|
|
120
|
+
}
|
|
121
|
+
const flow = readStoredFlow(event, providerId);
|
|
122
|
+
deleteCookie(event, flowCookieName(providerId), { path: "/" });
|
|
123
|
+
const state = decodeOAuthState(stateParam, "");
|
|
124
|
+
if (!flow ||
|
|
125
|
+
!isWorkspaceProviderOAuthFlowValid({
|
|
126
|
+
flow,
|
|
127
|
+
state,
|
|
128
|
+
provider: providerId,
|
|
129
|
+
sessionEmail: session.email,
|
|
130
|
+
sessionOrgId: session.orgId,
|
|
131
|
+
})) {
|
|
132
|
+
setResponseStatus(event, 400);
|
|
133
|
+
return { error: "OAuth state is invalid or expired." };
|
|
134
|
+
}
|
|
135
|
+
const provider = requiredProvider(providerId);
|
|
136
|
+
return runWithRequestContext({ userEmail: session.email, orgId: session.orgId }, async () => {
|
|
137
|
+
const [clientId, clientSecret] = await Promise.all([
|
|
138
|
+
resolveSecret(clientCredentialKey(providerId, "id")),
|
|
139
|
+
resolveSecret(clientCredentialKey(providerId, "secret")),
|
|
140
|
+
]);
|
|
141
|
+
if (!clientId || !clientSecret) {
|
|
142
|
+
setResponseStatus(event, 503);
|
|
143
|
+
return {
|
|
144
|
+
error: `${provider.label} OAuth client credentials are not configured.`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const tokens = await exchangeWorkspaceProviderOAuthCode({
|
|
148
|
+
providerId,
|
|
149
|
+
provider,
|
|
150
|
+
clientId,
|
|
151
|
+
clientSecret,
|
|
152
|
+
code,
|
|
153
|
+
verifier: flow.verifier,
|
|
154
|
+
redirectUri: flow.redirectUri,
|
|
155
|
+
});
|
|
156
|
+
const identity = await resolveWorkspaceProviderIdentity(providerId, tokens);
|
|
157
|
+
await saveOAuthTokens(provider.oauth.provider, identity.accountId, tokens, session.email);
|
|
158
|
+
await setOAuthDisplayName(provider.oauth.provider, identity.accountId, identity.label);
|
|
159
|
+
const existing = (await listWorkspaceConnections({
|
|
160
|
+
provider: providerId,
|
|
161
|
+
includeDisabled: true,
|
|
162
|
+
})).find((connection) => connection.accountId === identity.accountId);
|
|
163
|
+
const scopes = mergeWorkspaceOAuthValues(existing?.scopes ?? [], tokenScopes(tokens, provider.oauth.scopes));
|
|
164
|
+
const connection = await upsertWorkspaceConnection({
|
|
165
|
+
...(existing ? { id: existing.id } : {}),
|
|
166
|
+
provider: providerId,
|
|
167
|
+
label: `${provider.label}: ${identity.label}`,
|
|
168
|
+
accountId: identity.accountId,
|
|
169
|
+
accountLabel: identity.label,
|
|
170
|
+
status: "connected",
|
|
171
|
+
scopes,
|
|
172
|
+
allowedApps: existing?.allowedApps ?? [],
|
|
173
|
+
config: { credentialMode: "oauth" },
|
|
174
|
+
lastCheckedAt: new Date(),
|
|
175
|
+
lastError: null,
|
|
176
|
+
});
|
|
177
|
+
await upsertWorkspaceConnectionGrant({
|
|
178
|
+
connectionId: connection.id,
|
|
179
|
+
appId: flow.appId,
|
|
180
|
+
provider: providerId,
|
|
181
|
+
scopes,
|
|
182
|
+
config: { credentialMode: "oauth" },
|
|
183
|
+
});
|
|
184
|
+
const returnPath = state.returnUrl ??
|
|
185
|
+
`/settings/connections?connected=${encodeURIComponent(providerId)}`;
|
|
186
|
+
return Response.redirect(getAppUrl(event, returnPath), 302);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
export function buildWorkspaceProviderAuthorizationUrl(input) {
|
|
190
|
+
if (!input.provider.oauth)
|
|
191
|
+
throw new Error("Provider does not support OAuth.");
|
|
192
|
+
const url = new URL(input.provider.oauth.authorizationUrl);
|
|
193
|
+
url.searchParams.set("client_id", input.clientId);
|
|
194
|
+
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
195
|
+
url.searchParams.set("response_type", "code");
|
|
196
|
+
url.searchParams.set("state", input.state);
|
|
197
|
+
if (input.provider.id === "figma") {
|
|
198
|
+
url.searchParams.set("code_challenge", input.challenge);
|
|
199
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
200
|
+
}
|
|
201
|
+
if (input.provider.id === "google_drive") {
|
|
202
|
+
url.searchParams.set("access_type", "offline");
|
|
203
|
+
url.searchParams.set("include_granted_scopes", "true");
|
|
204
|
+
url.searchParams.set("prompt", "consent");
|
|
205
|
+
}
|
|
206
|
+
if (input.provider.oauth.scopes.length) {
|
|
207
|
+
url.searchParams.set("scope", input.provider.oauth.scopes.join(" "));
|
|
208
|
+
}
|
|
209
|
+
if (input.provider.id === "notion")
|
|
210
|
+
url.searchParams.set("owner", "user");
|
|
211
|
+
return url.href;
|
|
212
|
+
}
|
|
213
|
+
export async function exchangeWorkspaceProviderOAuthCode(input) {
|
|
214
|
+
const tokenUrl = input.provider.oauth?.tokenUrl;
|
|
215
|
+
if (!tokenUrl)
|
|
216
|
+
throw new Error("Provider does not support OAuth.");
|
|
217
|
+
const authorization = `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString("base64")}`;
|
|
218
|
+
const fields = {
|
|
219
|
+
grant_type: "authorization_code",
|
|
220
|
+
code: input.code,
|
|
221
|
+
redirect_uri: input.redirectUri,
|
|
222
|
+
...(input.providerId === "figma" ? { code_verifier: input.verifier } : {}),
|
|
223
|
+
...(input.providerId === "google_drive"
|
|
224
|
+
? { client_id: input.clientId, client_secret: input.clientSecret }
|
|
225
|
+
: {}),
|
|
226
|
+
};
|
|
227
|
+
const { response, body } = await fetchBoundedProviderJson(tokenUrl, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
headers: input.providerId === "notion"
|
|
230
|
+
? {
|
|
231
|
+
Authorization: authorization,
|
|
232
|
+
Accept: "application/json",
|
|
233
|
+
"Content-Type": "application/json",
|
|
234
|
+
}
|
|
235
|
+
: input.providerId === "figma"
|
|
236
|
+
? {
|
|
237
|
+
Authorization: authorization,
|
|
238
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
239
|
+
}
|
|
240
|
+
: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
241
|
+
body: input.providerId === "notion"
|
|
242
|
+
? JSON.stringify(fields)
|
|
243
|
+
: new URLSearchParams(fields),
|
|
244
|
+
}, input.provider.label);
|
|
245
|
+
const accessToken = text(body.access_token);
|
|
246
|
+
if (!response.ok || !accessToken) {
|
|
247
|
+
throw new Error(`${input.provider.label} OAuth token exchange failed (${response.status}).`);
|
|
248
|
+
}
|
|
249
|
+
const expiresIn = Number(body.expires_in);
|
|
250
|
+
return {
|
|
251
|
+
...body,
|
|
252
|
+
...(Number.isFinite(expiresIn) && expiresIn > 0
|
|
253
|
+
? { expiry_date: Date.now() + expiresIn * 1_000 }
|
|
254
|
+
: {}),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
export async function resolveWorkspaceProviderIdentity(providerId, tokens) {
|
|
258
|
+
if (providerId === "notion") {
|
|
259
|
+
const owner = record(tokens.owner);
|
|
260
|
+
const user = record(owner?.user);
|
|
261
|
+
const person = record(user?.person);
|
|
262
|
+
const accountId = text(user?.id) ??
|
|
263
|
+
text(person?.email) ??
|
|
264
|
+
text(tokens.workspace_id) ??
|
|
265
|
+
text(tokens.bot_id);
|
|
266
|
+
if (!accountId)
|
|
267
|
+
throw new Error("Notion OAuth response did not identify the connected user.");
|
|
268
|
+
return {
|
|
269
|
+
accountId,
|
|
270
|
+
label: text(person?.email) ??
|
|
271
|
+
text(tokens.workspace_name) ??
|
|
272
|
+
"Notion workspace",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
if (providerId === "google_drive") {
|
|
276
|
+
const accessToken = text(tokens.access_token);
|
|
277
|
+
const { response, body } = await fetchBoundedProviderJson("https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,permissionId)", { headers: { Authorization: `Bearer ${accessToken}` } }, "Google Drive");
|
|
278
|
+
const user = record(body.user);
|
|
279
|
+
const accountId = text(user?.permissionId) ?? text(user?.emailAddress);
|
|
280
|
+
if (!response.ok || !accountId) {
|
|
281
|
+
throw new Error("Google Drive OAuth response did not identify the connected account.");
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
accountId,
|
|
285
|
+
label: text(user?.emailAddress) ??
|
|
286
|
+
text(user?.displayName) ??
|
|
287
|
+
"Google Drive account",
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const accessToken = text(tokens.access_token);
|
|
291
|
+
const { response, body: me } = await fetchBoundedProviderJson("https://api.figma.com/v1/me", { headers: { Authorization: `Bearer ${accessToken}` } }, "Figma");
|
|
292
|
+
const accountId = text(me.id) ?? text(me.email) ?? text(tokens.user_id);
|
|
293
|
+
if (!response.ok || !accountId) {
|
|
294
|
+
throw new Error("Figma OAuth response did not identify the connected user.");
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
accountId,
|
|
298
|
+
label: text(me.email) ?? text(me.handle) ?? "Figma account",
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function requiredProvider(providerId) {
|
|
302
|
+
const provider = getWorkspaceConnectionProvider(providerId);
|
|
303
|
+
if (!provider?.oauth)
|
|
304
|
+
throw new Error(`${providerId} OAuth is not configured.`);
|
|
305
|
+
return provider;
|
|
306
|
+
}
|
|
307
|
+
function readStoredFlow(event, provider) {
|
|
308
|
+
const encrypted = getCookie(event, flowCookieName(provider));
|
|
309
|
+
if (!encrypted)
|
|
310
|
+
return null;
|
|
311
|
+
try {
|
|
312
|
+
return JSON.parse(decryptSecretValue(encrypted));
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
export function isWorkspaceProviderOAuthFlowValid(input) {
|
|
319
|
+
return (input.flow.expiresAt >= (input.now ?? Date.now()) &&
|
|
320
|
+
input.flow.provider === input.provider &&
|
|
321
|
+
input.state.flowId === input.flow.flowId &&
|
|
322
|
+
input.state.redirectUri === input.flow.redirectUri &&
|
|
323
|
+
input.state.owner === input.flow.owner &&
|
|
324
|
+
input.sessionEmail === input.flow.owner &&
|
|
325
|
+
input.state.orgId === input.flow.orgId &&
|
|
326
|
+
input.sessionOrgId === input.flow.orgId &&
|
|
327
|
+
input.state.app === input.flow.appId);
|
|
328
|
+
}
|
|
329
|
+
async function fetchBoundedProviderJson(url, init, providerLabel) {
|
|
330
|
+
let response;
|
|
331
|
+
try {
|
|
332
|
+
response = await fetch(url, {
|
|
333
|
+
...init,
|
|
334
|
+
signal: AbortSignal.timeout(PROVIDER_REQUEST_TIMEOUT_MS),
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
throw new Error(`${providerLabel} OAuth request failed.`);
|
|
339
|
+
}
|
|
340
|
+
const declaredLength = Number(response.headers.get("content-length"));
|
|
341
|
+
if (Number.isFinite(declaredLength) &&
|
|
342
|
+
declaredLength > PROVIDER_RESPONSE_MAX_BYTES) {
|
|
343
|
+
throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);
|
|
344
|
+
}
|
|
345
|
+
if (!response.body)
|
|
346
|
+
return { response, body: {} };
|
|
347
|
+
const reader = response.body.getReader();
|
|
348
|
+
const chunks = [];
|
|
349
|
+
let length = 0;
|
|
350
|
+
try {
|
|
351
|
+
while (true) {
|
|
352
|
+
const chunk = await reader.read();
|
|
353
|
+
if (chunk.done)
|
|
354
|
+
break;
|
|
355
|
+
length += chunk.value.byteLength;
|
|
356
|
+
if (length > PROVIDER_RESPONSE_MAX_BYTES) {
|
|
357
|
+
await reader.cancel();
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
chunks.push(chunk.value);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
throw new Error(`${providerLabel} OAuth request failed.`);
|
|
365
|
+
}
|
|
366
|
+
if (length > PROVIDER_RESPONSE_MAX_BYTES) {
|
|
367
|
+
throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);
|
|
368
|
+
}
|
|
369
|
+
try {
|
|
370
|
+
const json = Buffer.concat(chunks).toString("utf8");
|
|
371
|
+
const body = JSON.parse(json);
|
|
372
|
+
return { response, body: record(body) ?? {} };
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
return { response, body: {} };
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function tokenScopes(tokens, fallback) {
|
|
379
|
+
const scope = text(tokens.scope);
|
|
380
|
+
return scope ? scope.split(/[ ,]+/).filter(Boolean) : [...fallback];
|
|
381
|
+
}
|
|
382
|
+
export function mergeWorkspaceOAuthValues(existing, incoming) {
|
|
383
|
+
return [...new Set([...existing, ...incoming])];
|
|
384
|
+
}
|
|
385
|
+
function clientCredentialKey(provider, field) {
|
|
386
|
+
const prefix = provider === "google_drive" ? "GOOGLE" : provider.toUpperCase();
|
|
387
|
+
return `${prefix}_CLIENT_${field === "id" ? "ID" : "SECRET"}`;
|
|
388
|
+
}
|
|
389
|
+
function flowCookieName(provider) {
|
|
390
|
+
return `an_workspace_oauth_${provider}`;
|
|
391
|
+
}
|
|
392
|
+
function normalizeAppId(value) {
|
|
393
|
+
const normalized = value.trim().toLowerCase();
|
|
394
|
+
if (!/^[a-z0-9][a-z0-9_-]{0,99}$/.test(normalized)) {
|
|
395
|
+
throw new Error("OAuth appId is invalid.");
|
|
396
|
+
}
|
|
397
|
+
return normalized;
|
|
398
|
+
}
|
|
399
|
+
function text(value) {
|
|
400
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
401
|
+
}
|
|
402
|
+
function record(value) {
|
|
403
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
404
|
+
? value
|
|
405
|
+
: null;
|
|
406
|
+
}
|
|
407
|
+
function methodNotAllowed(event) {
|
|
408
|
+
setResponseStatus(event, 405);
|
|
409
|
+
return { error: "Method not allowed" };
|
|
410
|
+
}
|
|
411
|
+
function unauthorized(event) {
|
|
412
|
+
setResponseStatus(event, 401);
|
|
413
|
+
return { error: "Authentication required" };
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=workspace-provider-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 { 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 = \"figma\" | \"google_drive\" | \"notion\";\n\nconst SUPPORTED_PROVIDERS = new Set<GenericWorkspaceOAuthProvider>([\n \"figma\",\n \"google_drive\",\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 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: session.orgId },\n async () => {\n const [clientId, clientSecret] = await Promise.all([\n resolveSecret(clientCredentialKey(providerId, \"id\")),\n resolveSecret(clientCredentialKey(providerId, \"secret\")),\n ]);\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: session.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 ...(session.orgId ? { orgId: session.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 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: session.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: session.orgId },\n async () => {\n const [clientId, clientSecret] = await Promise.all([\n resolveSecret(clientCredentialKey(providerId, \"id\")),\n resolveSecret(clientCredentialKey(providerId, \"secret\")),\n ]);\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 identity = await resolveWorkspaceProviderIdentity(\n providerId,\n tokens,\n );\n await saveOAuthTokens(\n provider.oauth!.provider,\n identity.accountId,\n tokens,\n session.email,\n );\n await setOAuthDisplayName(\n provider.oauth!.provider,\n identity.accountId,\n identity.label,\n );\n const existing = (\n await listWorkspaceConnections({\n provider: providerId,\n includeDisabled: true,\n })\n ).find((connection) => connection.accountId === identity.accountId);\n const scopes = mergeWorkspaceOAuthValues(\n existing?.scopes ?? [],\n tokenScopes(tokens, provider.oauth!.scopes),\n );\n const connection = await upsertWorkspaceConnection({\n ...(existing ? { id: existing.id } : {}),\n provider: providerId,\n label: `${provider.label}: ${identity.label}`,\n accountId: identity.accountId,\n accountLabel: identity.label,\n status: \"connected\",\n scopes,\n allowedApps: existing?.allowedApps ?? [],\n config: { credentialMode: \"oauth\" },\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: { credentialMode: \"oauth\" },\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\") {\n url.searchParams.set(\"code_challenge\", input.challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\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 const fields = {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n ...(input.providerId === \"figma\" ? { code_verifier: input.verifier } : {}),\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<{ accountId: string; label: string }> {\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 === \"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\nasync function fetchBoundedProviderJson(\n url: string,\n init: RequestInit,\n providerLabel: string,\n): Promise<{ response: Response; body: Record<string, 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: record(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 clientCredentialKey(\n provider: GenericWorkspaceOAuthProvider,\n field: \"id\" | \"secret\",\n): string {\n const prefix =\n provider === \"google_drive\" ? \"GOOGLE\" : provider.toUpperCase();\n return `${prefix}_CLIENT_${field === \"id\" ? \"ID\" : \"SECRET\"}`;\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 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"]}
|
|
@@ -155,6 +155,11 @@
|
|
|
155
155
|
box-shadow 260ms var(--ease-drawer);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
.agent-sidebar-shell[data-agent-sidebar-resizing="true"],
|
|
159
|
+
.agent-sidebar-shell[data-agent-sidebar-resizing="true"] * {
|
|
160
|
+
transition: none !important;
|
|
161
|
+
}
|
|
162
|
+
|
|
158
163
|
.agent-native-app-main {
|
|
159
164
|
container: agent-native-main / inline-size;
|
|
160
165
|
}
|
|
@@ -237,6 +242,10 @@
|
|
|
237
242
|
transition: width 260ms var(--ease-drawer);
|
|
238
243
|
}
|
|
239
244
|
|
|
245
|
+
.agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-resizing="true"] {
|
|
246
|
+
transition: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
240
249
|
.agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-state="open"] {
|
|
241
250
|
width: var(--agent-sidebar-width);
|
|
242
251
|
}
|
|
@@ -11,10 +11,10 @@ const messages = {
|
|
|
11
11
|
"Manage team members, organization access, and shared workspace preferences.",
|
|
12
12
|
openTeamSettings: "Open team settings",
|
|
13
13
|
openResourceSettings: "Open resource settings",
|
|
14
|
-
agentTitle: "Agent
|
|
14
|
+
agentTitle: "Agent workspace",
|
|
15
15
|
agentDescription:
|
|
16
|
-
"Open the agent
|
|
17
|
-
openAgentSettings: "Open agent
|
|
16
|
+
"Open the agent workspace for model, API keys, automations, voice, and other agent controls.",
|
|
17
|
+
openAgentSettings: "Open agent workspace",
|
|
18
18
|
},
|
|
19
19
|
chat: {
|
|
20
20
|
archiveChat: "Archive Chat",
|
|
@@ -8,6 +8,8 @@ type AgentClientModule = {
|
|
|
8
8
|
AgentChatSurface: ComponentType<{
|
|
9
9
|
mode?: "panel" | "page";
|
|
10
10
|
className?: string;
|
|
11
|
+
showHeader?: boolean;
|
|
12
|
+
showTabBar?: boolean;
|
|
11
13
|
}>;
|
|
12
14
|
AgentTabsPage?: ComponentType<AgentPageProps>;
|
|
13
15
|
};
|
|
@@ -33,7 +35,14 @@ export function resolveAgentPageComponent(
|
|
|
33
35
|
if (existing) return existing;
|
|
34
36
|
|
|
35
37
|
const legacyAgentPage = function LegacyAgentPage() {
|
|
36
|
-
return
|
|
38
|
+
return (
|
|
39
|
+
<client.AgentChatSurface
|
|
40
|
+
mode="page"
|
|
41
|
+
className="h-full"
|
|
42
|
+
showHeader={false}
|
|
43
|
+
showTabBar={false}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
37
46
|
};
|
|
38
47
|
legacyAgentPages.set(client, legacyAgentPage);
|
|
39
48
|
return legacyAgentPage;
|
|
@@ -18,10 +18,10 @@ const messages = {
|
|
|
18
18
|
languageDescription:
|
|
19
19
|
"Choose the interface language. This preference is saved for your account.",
|
|
20
20
|
languageLabel: "Interface language",
|
|
21
|
-
agentTitle: "Agent
|
|
21
|
+
agentTitle: "Agent workspace",
|
|
22
22
|
agentDescription:
|
|
23
|
-
"Open the agent
|
|
24
|
-
openAgentSettings: "Open agent
|
|
23
|
+
"Open the agent workspace for model, API keys, automations, voice, and other agent controls.",
|
|
24
|
+
openAgentSettings: "Open agent workspace",
|
|
25
25
|
workspaceTitle: "Workspace",
|
|
26
26
|
workspaceDescription: "Manage team access and shared workspace resources.",
|
|
27
27
|
openTeamSettings: "Open team settings",
|
|
@@ -200,9 +200,10 @@ extension content:
|
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
`update-extension` accepts the same `contentFromAttachment` for full-body
|
|
203
|
-
replacement
|
|
204
|
-
|
|
205
|
-
already
|
|
203
|
+
replacement, but full-body replacement requires `allowFullReplacement: true`.
|
|
204
|
+
Inline `content` still works for everything you author yourself — use
|
|
205
|
+
`contentFromAttachment` only to avoid regurgitating something the user already
|
|
206
|
+
pasted.
|
|
206
207
|
|
|
207
208
|
## Editing an extension
|
|
208
209
|
|
|
@@ -211,6 +212,13 @@ changes instead of regenerating the full HTML. For medium/large extensions,
|
|
|
211
212
|
add stable section comments around major blocks so future agents can target
|
|
212
213
|
them without touching unrelated indentation:
|
|
213
214
|
|
|
215
|
+
For data-only repairs, preserve the existing layout, CSS, copy, and
|
|
216
|
+
interactions. Do not reconstruct and submit the entire body. The action and
|
|
217
|
+
store reject full-body replacement unless `allowFullReplacement: true` is
|
|
218
|
+
explicitly supplied for a user-requested visual rewrite or complete replacement
|
|
219
|
+
body. If a focused edit fails, inspect the current body and adjust its target;
|
|
220
|
+
do not retry unchanged arguments.
|
|
221
|
+
|
|
214
222
|
```html
|
|
215
223
|
<!-- agent-native:section npm-daily-chart -->
|
|
216
224
|
<section>...</section>
|
|
@@ -243,7 +251,8 @@ Supported `edits` operations:
|
|
|
243
251
|
Use `expectedMatches` when ambiguity would be dangerous. Missing required
|
|
244
252
|
targets fail instead of silently doing nothing. Pass `format: true` to run
|
|
245
253
|
Prettier on the final HTML after the patch. Full `content` replacement is
|
|
246
|
-
still available for broad rewrites
|
|
254
|
+
still available for broad rewrites when `allowFullReplacement: true` is
|
|
255
|
+
supplied.
|
|
247
256
|
|
|
248
257
|
Legacy `patches` still work for simple literal replacements:
|
|
249
258
|
|
|
@@ -264,7 +273,7 @@ To replace the full content instead:
|
|
|
264
273
|
|
|
265
274
|
```
|
|
266
275
|
PUT /_agent-native/extensions/:id
|
|
267
|
-
{ "content": "full new HTML" }
|
|
276
|
+
{ "content": "full new HTML", "allowFullReplacement": true }
|
|
268
277
|
```
|
|
269
278
|
|
|
270
279
|
## History and rollback
|
|
@@ -70,6 +70,18 @@ DISPATCH_DEFAULT_OWNER_EMAIL=
|
|
|
70
70
|
GOOGLE_CLIENT_ID=
|
|
71
71
|
GOOGLE_CLIENT_SECRET=
|
|
72
72
|
|
|
73
|
+
# Optional workspace connectors. Register the matching callback URLs in each
|
|
74
|
+
# provider using APP_URL as the origin:
|
|
75
|
+
# /_agent-native/connections/oauth/google_drive/callback
|
|
76
|
+
# /_agent-native/connections/oauth/figma/callback
|
|
77
|
+
# /_agent-native/connections/oauth/notion/callback
|
|
78
|
+
# Google reuses the client above. User access and refresh tokens are encrypted
|
|
79
|
+
# in the workspace token store.
|
|
80
|
+
FIGMA_CLIENT_ID=
|
|
81
|
+
FIGMA_CLIENT_SECRET=
|
|
82
|
+
NOTION_CLIENT_ID=
|
|
83
|
+
NOTION_CLIENT_SECRET=
|
|
84
|
+
|
|
73
85
|
# Optional: GitHub sign-in.
|
|
74
86
|
GITHUB_CLIENT_ID=
|
|
75
87
|
GITHUB_CLIENT_SECRET=
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { deleteWorkspaceConnection, ensureWorkspaceConnectionsTable, getWorkspaceConnectionAppAccess, getWorkspaceConnection, getWorkspaceConnectionGrant, listWorkspaceConnectionProviderCatalogForApp, listWorkspaceConnectionGrants, listWorkspaceConnections, listWorkspaceConnectionsForApp, markWorkspaceConnectionUsed, resolveWorkspaceConnectionForApp, revokeWorkspaceConnectionGrant, serializeWorkspaceConnectionGrant, serializeWorkspaceConnection, summarizeWorkspaceConnectionProviderForApp, summarizeWorkspaceConnectionProviderReadiness, upsertWorkspaceConnectionGrant, upsertWorkspaceConnection, type ListWorkspaceConnectionProviderCatalogForAppOptions, type ListWorkspaceConnectionGrantsOptions, type ListWorkspaceConnectionsOptions, type ListWorkspaceConnectionsForAppOptions, type MarkWorkspaceConnectionUsedOptions, type MarkWorkspaceConnectionUsedResult, type ResolvedWorkspaceConnectionForApp, type ResolveWorkspaceConnectionForAppOptions, type SerializedWorkspaceConnectionGrant, type SerializedWorkspaceConnection, type SummarizeWorkspaceConnectionProviderForAppOptions, type SummarizeWorkspaceConnectionProviderReadinessOptions, type UpsertWorkspaceConnectionGrantInput, type UpsertWorkspaceConnectionInput, type WorkspaceConnectionAppAccess, type WorkspaceConnectionAppAccessMode, type WorkspaceConnection, type WorkspaceConnectionCredentialRef, type WorkspaceConnectionExplicitGrantSummary, type WorkspaceConnectionForApp, type WorkspaceConnectionForAppSummary, type WorkspaceConnectionGrant, type WorkspaceConnectionGrantAvailability, type WorkspaceConnectionGrantState, type WorkspaceConnectionProviderAppSummary, type WorkspaceConnectionProviderLike, type WorkspaceConnectionProviderCatalogForApp, type WorkspaceConnectionProviderCatalogForAppItem, type WorkspaceConnectionProviderReadiness, type WorkspaceConnectionProviderReadinessStatus, type WorkspaceConnectionPublicCredentialRef, type WorkspaceConnectionStatus, workspaceConnectionIsAvailableToApp, } from "./store.js";
|
|
2
2
|
export { resolveWorkspaceConnectionCredentialForApp, resolveWorkspaceConnectionCredentialsForApp, type ResolveWorkspaceConnectionCredentialForAppOptions, type ResolveWorkspaceConnectionCredentialsForAppOptions, type WorkspaceConnectionCredentialBackend, type WorkspaceConnectionCredentialProvenance, type WorkspaceConnectionCredentialResolution, type WorkspaceConnectionCredentialResolutionCheck, type WorkspaceConnectionCredentialResolutionStatus, type WorkspaceConnectionCredentialsResolution, } from "./credentials.js";
|
|
3
|
+
export { registerWorkspaceConnectionLifecycleListener, type WorkspaceConnectionLifecycleEvent, type WorkspaceConnectionLifecycleListener, } from "./lifecycle.js";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workspace-connections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,+BAA+B,EAC/B,+BAA+B,EAC/B,sBAAsB,EACtB,2BAA2B,EAC3B,4CAA4C,EAC5C,6BAA6B,EAC7B,wBAAwB,EACxB,8BAA8B,EAC9B,2BAA2B,EAC3B,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,EACjC,4BAA4B,EAC5B,0CAA0C,EAC1C,6CAA6C,EAC7C,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,mDAAmD,EACxD,KAAK,oCAAoC,EACzC,KAAK,+BAA+B,EACpC,KAAK,qCAAqC,EAC1C,KAAK,kCAAkC,EACvC,KAAK,iCAAiC,EACtC,KAAK,iCAAiC,EACtC,KAAK,uCAAuC,EAC5C,KAAK,kCAAkC,EACvC,KAAK,6BAA6B,EAClC,KAAK,iDAAiD,EACtD,KAAK,oDAAoD,EACzD,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACrC,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EACrC,KAAK,uCAAuC,EAC5C,KAAK,yBAAyB,EAC9B,KAAK,gCAAgC,EACrC,KAAK,wBAAwB,EAC7B,KAAK,oCAAoC,EACzC,KAAK,6BAA6B,EAClC,KAAK,qCAAqC,EAC1C,KAAK,+BAA+B,EACpC,KAAK,wCAAwC,EAC7C,KAAK,4CAA4C,EACjD,KAAK,oCAAoC,EACzC,KAAK,0CAA0C,EAC/C,KAAK,sCAAsC,EAC3C,KAAK,yBAAyB,EAC9B,mCAAmC,GACpC,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,0CAA0C,EAC1C,2CAA2C,EAC3C,KAAK,iDAAiD,EACtD,KAAK,kDAAkD,EACvD,KAAK,oCAAoC,EACzC,KAAK,uCAAuC,EAC5C,KAAK,uCAAuC,EAC5C,KAAK,4CAA4C,EACjD,KAAK,6CAA6C,EAClD,KAAK,wCAAwC,GAC9C,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workspace-connections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,+BAA+B,EAC/B,+BAA+B,EAC/B,sBAAsB,EACtB,2BAA2B,EAC3B,4CAA4C,EAC5C,6BAA6B,EAC7B,wBAAwB,EACxB,8BAA8B,EAC9B,2BAA2B,EAC3B,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,EACjC,4BAA4B,EAC5B,0CAA0C,EAC1C,6CAA6C,EAC7C,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,mDAAmD,EACxD,KAAK,oCAAoC,EACzC,KAAK,+BAA+B,EACpC,KAAK,qCAAqC,EAC1C,KAAK,kCAAkC,EACvC,KAAK,iCAAiC,EACtC,KAAK,iCAAiC,EACtC,KAAK,uCAAuC,EAC5C,KAAK,kCAAkC,EACvC,KAAK,6BAA6B,EAClC,KAAK,iDAAiD,EACtD,KAAK,oDAAoD,EACzD,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACrC,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EACrC,KAAK,uCAAuC,EAC5C,KAAK,yBAAyB,EAC9B,KAAK,gCAAgC,EACrC,KAAK,wBAAwB,EAC7B,KAAK,oCAAoC,EACzC,KAAK,6BAA6B,EAClC,KAAK,qCAAqC,EAC1C,KAAK,+BAA+B,EACpC,KAAK,wCAAwC,EAC7C,KAAK,4CAA4C,EACjD,KAAK,oCAAoC,EACzC,KAAK,0CAA0C,EAC/C,KAAK,sCAAsC,EAC3C,KAAK,yBAAyB,EAC9B,mCAAmC,GACpC,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,0CAA0C,EAC1C,2CAA2C,EAC3C,KAAK,iDAAiD,EACtD,KAAK,kDAAkD,EACvD,KAAK,oCAAoC,EACzC,KAAK,uCAAuC,EAC5C,KAAK,uCAAuC,EAC5C,KAAK,4CAA4C,EACjD,KAAK,6CAA6C,EAClD,KAAK,wCAAwC,GAC9C,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,4CAA4C,EAC5C,KAAK,iCAAiC,EACtC,KAAK,oCAAoC,GAC1C,MAAM,gBAAgB,CAAC"}
|