@agent-native/core 0.169.1 → 0.171.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/agent-native.eject.json +4 -1
- package/bin/agent-native.js +23 -5
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- package/corpus/templates/analytics/app/routes/$.tsx +10 -0
- package/corpus/templates/analytics/app/routes.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
- package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
- package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
- package/corpus/templates/analytics/server/lib/slack.ts +4 -2
- package/corpus/templates/analytics/vitest.config.ts +6 -1
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/assets/app/routes/library.tsx +5 -3
- package/corpus/templates/assets/app/routes.ts +3 -1
- package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
- package/corpus/templates/assets/vitest.config.ts +6 -1
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/brain/app/routes/sources.tsx +8 -3
- package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
- package/corpus/templates/brain/vitest.config.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
- package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
- package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
- package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
- package/corpus/templates/calendar/app/routes.ts +3 -1
- package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
- package/corpus/templates/calendar/server/onboarding.ts +85 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/calendar/shared/api.ts +9 -1
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/chat/app/routes.ts +3 -1
- package/corpus/templates/chat/vitest.config.ts +8 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/clips/actions/get-meeting.ts +9 -4
- package/corpus/templates/clips/actions/list-recordings.ts +16 -3
- package/corpus/templates/clips/actions/search-meetings.ts +1 -0
- package/corpus/templates/clips/actions/view-screen.ts +8 -1
- package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
- package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
- package/corpus/templates/clips/desktop/src/app.tsx +53 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
- package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
- package/corpus/templates/clips/server/lib/emails.ts +17 -33
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
- package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
- package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
- package/corpus/templates/content/app/i18n-data.ts +25 -0
- package/corpus/templates/content/app/routes.ts +3 -1
- package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
- package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
- package/corpus/templates/content/vitest.config.ts +7 -1
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
- package/corpus/templates/design/actions/generate-design.ts +98 -47
- package/corpus/templates/design/actions/get-design-system.ts +6 -1
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
- package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
- package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
- package/corpus/templates/design/app/pages/Index.tsx +2 -0
- package/corpus/templates/design/app/pages/Templates.tsx +0 -10
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
- package/corpus/templates/design/app/routes.ts +3 -1
- package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
- package/corpus/templates/design/shared/canvas-math.ts +612 -206
- package/corpus/templates/design/shared/pen-path.ts +37 -0
- package/corpus/templates/design/vitest.config.ts +7 -1
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
- package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
- package/corpus/templates/dispatch/app/routes.ts +3 -1
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/factory/.env.example +2 -7
- package/corpus/templates/factory/AGENTS.md +3 -0
- package/corpus/templates/factory/README.md +5 -3
- package/corpus/templates/factory/actions/create-factory.ts +16 -3
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
- package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
- package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
- package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
- package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
- package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
- package/corpus/templates/factory/app/routes/factory.tsx +84 -11
- package/corpus/templates/factory/app/routes.ts +3 -1
- package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
- package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
- package/corpus/templates/factory/vitest.config.ts +17 -2
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
- package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
- package/corpus/templates/forms/vitest.config.ts +1 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/macros/app/routes.ts +3 -1
- package/corpus/templates/macros/vitest.config.ts +6 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
- package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
- package/corpus/templates/mail/app/routes/$.tsx +9 -0
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
- package/corpus/templates/mail/app/routes/$view.tsx +47 -1
- package/corpus/templates/mail/app/routes.ts +3 -1
- package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
- package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
- package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
- package/corpus/templates/mail/server/onboarding.ts +66 -18
- package/corpus/templates/mail/vitest.config.ts +6 -1
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/plan/app/routes/settings.tsx +4 -1
- package/corpus/templates/plan/app/routes.ts +3 -1
- package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/plan/netlify.toml +1 -1
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/slides/actions/patch-deck.ts +79 -10
- package/corpus/templates/slides/actions/update-slide.ts +11 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
- package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/slides/app/routes.ts +3 -1
- package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
- package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/slides/tsconfig.json +5 -0
- package/corpus/templates/slides/vitest.config.ts +6 -1
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
- package/corpus/templates/tasks/app/routes.ts +3 -1
- package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/tasks/vitest.config.ts +7 -1
- package/dist/action.d.ts +91 -0
- package/dist/action.js +50 -0
- package/dist/agent/abort-reasons.d.ts +38 -0
- package/dist/agent/abort-reasons.js +49 -0
- package/dist/agent/engine/ai-sdk-engine.js +8 -5
- package/dist/agent/engine/anthropic-engine.js +7 -5
- package/dist/agent/engine/first-event-timeout.d.ts +42 -17
- package/dist/agent/engine/first-event-timeout.js +67 -25
- package/dist/agent/production-agent.d.ts +23 -0
- package/dist/agent/production-agent.js +107 -102
- package/dist/agent/run-loop-with-resume.d.ts +2 -28
- package/dist/agent/run-loop-with-resume.js +25 -40
- package/dist/agent/run-manager.js +5 -4
- package/dist/agent/run-store.d.ts +55 -0
- package/dist/agent/run-store.js +124 -1
- package/dist/agent/tool-search.js +2 -1
- package/dist/agent/types.d.ts +9 -4
- package/dist/app-config/auth.d.ts +1 -0
- package/dist/app-config/auth.js +7 -0
- package/dist/app-config/configuration-error.d.ts +11 -0
- package/dist/app-config/configuration-error.js +14 -0
- package/dist/app-config/index.d.ts +1 -0
- package/dist/app-config/index.js +1 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +10 -0
- package/dist/app-config/plugins.d.ts +34 -0
- package/dist/app-config/plugins.js +39 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
- package/dist/app-config/run-lifecycle-invariants.js +18 -25
- package/dist/app-config/schema.d.ts +17 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/chat-threads/schema-migrations.js +20 -0
- package/dist/chat-threads/store.js +21 -4
- package/dist/cli/native-dependencies.d.ts +4 -0
- package/dist/cli/native-dependencies.js +15 -0
- package/dist/client/EnvironmentBadge.d.ts +1 -1
- package/dist/client/EnvironmentBadge.js +40 -5
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -14
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +2 -1
- package/dist/client/agent-page/use-jobs.js +3 -5
- package/dist/client/agent-sidebar-state.js +3 -1
- package/dist/client/blocks/library/code-tabs.js +5 -0
- package/dist/client/blocks/library/code.js +1 -0
- package/dist/client/chat-first/apps-rail.js +2 -2
- package/dist/client/chat-model-groups.d.ts +12 -0
- package/dist/client/chat-model-groups.js +3 -2
- package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
- package/dist/client/integrations/GoogleProductLogo.js +45 -0
- package/dist/client/integrations/index.d.ts +2 -0
- package/dist/client/integrations/index.js +2 -0
- package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
- package/dist/client/integrations/workspace-provider-oauth.js +13 -0
- package/dist/client/resources/mcp-integration-catalog.js +0 -29
- package/dist/client/settings/SettingsTabsPage.js +10 -6
- package/dist/client/sharing/ShareButton.js +11 -2
- package/dist/client/use-chat-models.d.ts +6 -0
- package/dist/client/use-chat-models.js +10 -0
- package/dist/client/use-db-sync.js +27 -9
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +111 -9
- package/dist/connections/catalog.js +86 -30
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/ddl-guard.d.ts +0 -4
- package/dist/db/ddl-guard.js +46 -0
- package/dist/deploy/build.d.ts +19 -0
- package/dist/deploy/build.js +190 -16
- package/dist/deploy/function-bundle.d.ts +45 -0
- package/dist/deploy/function-bundle.js +337 -0
- package/dist/deploy/workspace-deploy.js +19 -1
- package/dist/eject/workspace-connections.js +4 -0
- package/dist/email-catalog/registry.d.ts +4 -0
- package/dist/email-catalog/registry.js +79 -14
- package/dist/extensions/content-patch.js +14 -2
- package/dist/integrations/plugin.d.ts +10 -0
- package/dist/integrations/plugin.js +40 -6
- package/dist/jobs/actions/run-automation-now.d.ts +2 -1
- package/dist/jobs/actions/run-automation-now.js +11 -5
- package/dist/jobs/frontmatter.js +53 -2
- package/dist/jobs/run-now.d.ts +11 -1
- package/dist/jobs/run-now.js +42 -7
- package/dist/jobs/scheduler.d.ts +1 -0
- package/dist/jobs/scheduler.js +2 -1
- package/dist/localization/core-messages/ar-SA.js +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts +2 -5
- package/dist/localization/default-messages.js +2 -5
- package/dist/mcp/build-server.d.ts +9 -0
- package/dist/mcp/build-server.js +37 -8
- package/dist/mcp-client/oauth-client.d.ts +7 -0
- package/dist/mcp-client/oauth-client.js +12 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/lifecycle.d.ts +11 -0
- package/dist/oauth-tokens/lifecycle.js +17 -0
- package/dist/oauth-tokens/store.js +7 -0
- package/dist/observability/posthog-ai.d.ts +15 -1
- package/dist/observability/posthog-ai.js +24 -12
- package/dist/observability/traces.js +158 -28
- package/dist/onboarding/app-profile.js +2 -2
- package/dist/onboarding/plugin.js +10 -2
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
- package/dist/server/agent-chat/action-filters-a2a.js +48 -9
- package/dist/server/agent-chat-plugin.js +36 -9
- package/dist/server/agent-discovery.js +43 -20
- package/dist/server/auth.js +18 -16
- package/dist/server/beta-opt-out-html.js +45 -4
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +37 -7
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.js +87 -6
- package/dist/server/builder-oauth.d.ts +1 -7
- package/dist/server/builder-oauth.js +80 -163
- package/dist/server/core-routes-plugin.d.ts +29 -0
- package/dist/server/core-routes-plugin.js +100 -20
- package/dist/server/default-plugins.d.ts +18 -0
- package/dist/server/default-plugins.js +22 -0
- package/dist/server/edge.d.ts +1 -0
- package/dist/server/edge.js +1 -0
- package/dist/server/framework-request-handler.js +31 -3
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.js +3 -0
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/onboarding-html.js +37 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.js +72 -20
- package/dist/shared/agent-sidebar-url.d.ts +1 -0
- package/dist/shared/agent-sidebar-url.js +1 -0
- package/dist/shared/environment-lanes.d.ts +2 -0
- package/dist/shared/environment-lanes.js +3 -1
- package/dist/shared/index.d.ts +3 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/surface-visibility.d.ts +31 -0
- package/dist/shared/surface-visibility.js +57 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/chat/app/routes.ts +3 -1
- package/dist/templates/chat/vitest.config.ts +8 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/default/app/routes.ts +3 -1
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/tracking/registry.d.ts +11 -0
- package/dist/tracking/registry.js +5 -2
- package/dist/triggers/actions.js +10 -3
- package/dist/usage/store.js +23 -3
- package/dist/user-profile/actions/get-auth-methods.js +18 -5
- package/dist/vite/client.js +33 -7
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/authentication.mdx +40 -21
- package/docs/content/environment-variables.mdx +1 -0
- package/docs/content/template-clips-capture-everywhere.mdx +29 -30
- package/docs/content/template-clips-developers.mdx +4 -4
- package/docs/content/template-clips.mdx +3 -1
- package/package.json +2 -2
- package/src/eject/workspace-connections.ts +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/chat/app/routes.ts +3 -1
- package/src/templates/chat/vitest.config.ts +8 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/default/app/routes.ts +3 -1
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
|
@@ -52,6 +52,43 @@ export function createSmoothNode(
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Per-drag memory for Figma's Alt-breaks-the-handle-pair gesture on a new pen
|
|
57
|
+
* anchor. Owned by the drag state, not by a single move event.
|
|
58
|
+
*/
|
|
59
|
+
export interface PenCuspLatch {
|
|
60
|
+
broken: boolean;
|
|
61
|
+
handleIn?: PenPoint;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function createPenCuspLatch(): PenCuspLatch {
|
|
65
|
+
return { broken: false };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Builds the anchor a new-anchor drag is currently describing.
|
|
70
|
+
*
|
|
71
|
+
* Alt is a one-way latch for the life of the drag: releasing it does not
|
|
72
|
+
* re-mirror the pair, and breaking it freezes `handleIn` at the tangent it
|
|
73
|
+
* had when Alt went down rather than deleting it, so the segment already
|
|
74
|
+
* drawn keeps its curve. Alt held from the first tick has no earlier tangent
|
|
75
|
+
* to keep, leaving the incoming side a corner.
|
|
76
|
+
*/
|
|
77
|
+
export function createPenDragNode(
|
|
78
|
+
anchor: PenPoint,
|
|
79
|
+
handleOut: PenPoint,
|
|
80
|
+
latch: PenCuspLatch,
|
|
81
|
+
altKey: boolean,
|
|
82
|
+
): PenNode {
|
|
83
|
+
if (altKey) latch.broken = true;
|
|
84
|
+
if (!latch.broken) latch.handleIn = mirrorPoint(anchor, handleOut);
|
|
85
|
+
return {
|
|
86
|
+
point: { ...anchor },
|
|
87
|
+
handleIn: latch.handleIn ? { ...latch.handleIn } : undefined,
|
|
88
|
+
handleOut: { ...handleOut },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
55
92
|
export function appendPenNode(path: PenPath | null, node: PenNode): PenPath {
|
|
56
93
|
return {
|
|
57
94
|
nodes: [...(path?.nodes ?? []), clonePenNode(node)],
|
|
@@ -15,7 +15,13 @@ export default mergeConfig(
|
|
|
15
15
|
test: {
|
|
16
16
|
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
17
17
|
// e2e/ holds Playwright (@playwright/test) specs; run via `pnpm e2e`, not vitest.
|
|
18
|
-
exclude: [
|
|
18
|
+
exclude: [
|
|
19
|
+
"**/node_modules/**",
|
|
20
|
+
"**/.git/**",
|
|
21
|
+
"**/dist/**",
|
|
22
|
+
"**/.react-router/**",
|
|
23
|
+
"**/e2e/**",
|
|
24
|
+
],
|
|
19
25
|
},
|
|
20
26
|
}),
|
|
21
27
|
);
|
|
@@ -19,10 +19,17 @@ data, and generated extension/app content may mention credential **names** such
|
|
|
19
19
|
as `OPENAI_API_KEY`, but must not contain real API keys, tokens, webhook URLs,
|
|
20
20
|
signing secrets, OAuth refresh tokens, or private Builder/customer data.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`${keys.NAME}` substitution.
|
|
25
|
-
|
|
22
|
+
Provider secret values are supplied at runtime through the encrypted
|
|
23
|
+
`app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
24
|
+
`${keys.NAME}` substitution. Deployment configuration is reserved for
|
|
25
|
+
deploy-level secrets and non-provider configuration. Examples must use obvious
|
|
26
|
+
placeholders such as `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not
|
|
27
|
+
real-looking copied values.
|
|
28
|
+
|
|
29
|
+
Provider credentials and provider account identifiers are workspace data. Use
|
|
30
|
+
standard workspace connections and org/workspace vault scopes; never put them
|
|
31
|
+
in `.env` or deployment environment variables, and never add a provider-specific
|
|
32
|
+
action or startup bootstrap just to write a credential for one organization.
|
|
26
33
|
|
|
27
34
|
## Credential Modeling Preflight
|
|
28
35
|
|
|
@@ -8,6 +8,10 @@ import {
|
|
|
8
8
|
isProviderApiId,
|
|
9
9
|
listProviderApiCatalog,
|
|
10
10
|
} from "@agent-native/core/provider-api";
|
|
11
|
+
import {
|
|
12
|
+
hasWorkspaceProviderOAuthCredentials,
|
|
13
|
+
isGoogleWorkspaceOAuthProvider,
|
|
14
|
+
} from "@agent-native/core/server";
|
|
11
15
|
import {
|
|
12
16
|
getWorkspaceConnectionAppAccess,
|
|
13
17
|
listWorkspaceConnectionGrants,
|
|
@@ -46,6 +50,8 @@ type GrantSummary = {
|
|
|
46
50
|
lastUsedAt?: string | null;
|
|
47
51
|
};
|
|
48
52
|
|
|
53
|
+
type GoogleOAuthAvailability = "configured" | "unconfigured";
|
|
54
|
+
|
|
49
55
|
function unique(values: string[]) {
|
|
50
56
|
return Array.from(
|
|
51
57
|
new Set(values.map((value) => value.trim()).filter(Boolean)),
|
|
@@ -117,21 +123,40 @@ export default defineAction({
|
|
|
117
123
|
}),
|
|
118
124
|
http: { method: "GET" },
|
|
119
125
|
run: async (args) => {
|
|
120
|
-
const
|
|
126
|
+
const catalogProviders = listWorkspaceConnectionProviders({
|
|
121
127
|
capability: args.capability as WorkspaceConnectionCapability | undefined,
|
|
122
128
|
templateUse: args.templateUse as
|
|
123
129
|
| WorkspaceConnectionTemplateUse
|
|
124
130
|
| undefined,
|
|
125
131
|
});
|
|
126
|
-
const
|
|
132
|
+
const googleOAuthAvailability: GoogleOAuthAvailability =
|
|
133
|
+
(await hasWorkspaceProviderOAuthCredentials("gmail"))
|
|
134
|
+
? "configured"
|
|
135
|
+
: "unconfigured";
|
|
136
|
+
const googleOAuthConfigured = googleOAuthAvailability === "configured";
|
|
137
|
+
const providers = catalogProviders.filter(
|
|
138
|
+
(provider) =>
|
|
139
|
+
googleOAuthConfigured || !isGoogleWorkspaceOAuthProvider(provider.id),
|
|
140
|
+
);
|
|
141
|
+
const allConnections = await listWorkspaceConnections({
|
|
127
142
|
provider: args.provider,
|
|
128
143
|
appId: args.appId,
|
|
129
144
|
includeDisabled: args.includeDisabled,
|
|
130
145
|
});
|
|
131
|
-
const
|
|
146
|
+
const connections = allConnections.filter(
|
|
147
|
+
(connection) =>
|
|
148
|
+
googleOAuthConfigured ||
|
|
149
|
+
!isGoogleWorkspaceOAuthProvider(connection.provider),
|
|
150
|
+
);
|
|
151
|
+
const allExplicitGrants = await listWorkspaceConnectionGrants({
|
|
132
152
|
provider: args.provider,
|
|
133
153
|
appId: args.appId,
|
|
134
154
|
});
|
|
155
|
+
const explicitGrants = allExplicitGrants.filter(
|
|
156
|
+
(grant) =>
|
|
157
|
+
googleOAuthConfigured ||
|
|
158
|
+
!isGoogleWorkspaceOAuthProvider(grant.provider),
|
|
159
|
+
);
|
|
135
160
|
const grantApps = await listGrantApps();
|
|
136
161
|
const legacyGrants = connections.flatMap<GrantSummary>((connection) => {
|
|
137
162
|
if (connection.allowedApps.length === 0) {
|
|
@@ -246,6 +271,12 @@ export default defineAction({
|
|
|
246
271
|
});
|
|
247
272
|
|
|
248
273
|
return {
|
|
274
|
+
availability: {
|
|
275
|
+
googleOAuth: {
|
|
276
|
+
status: googleOAuthAvailability,
|
|
277
|
+
retryable: false,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
249
280
|
providers: providersWithReadiness,
|
|
250
281
|
connections,
|
|
251
282
|
grants,
|
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
} from "@agent-native/core/client/hooks";
|
|
6
6
|
import { useT } from "@agent-native/core/client/i18n";
|
|
7
7
|
import {
|
|
8
|
+
GoogleProductLogo,
|
|
8
9
|
IntegrationConnectionChoice,
|
|
9
10
|
IntegrationGrid,
|
|
11
|
+
startWorkspaceProviderOAuth as startManagedWorkspaceProviderOAuth,
|
|
10
12
|
} from "@agent-native/core/client/integrations";
|
|
11
13
|
import { useAppRoles, useOrgRole } from "@agent-native/core/client/org";
|
|
12
14
|
import {
|
|
@@ -361,7 +363,8 @@ interface SetupWizardFormState {
|
|
|
361
363
|
|
|
362
364
|
interface ProviderChoice {
|
|
363
365
|
provider: WorkspaceConnectionProvider;
|
|
364
|
-
personalIntegration
|
|
366
|
+
personalIntegration?: DefaultMcpIntegration;
|
|
367
|
+
personalOAuth?: boolean;
|
|
365
368
|
}
|
|
366
369
|
|
|
367
370
|
const EMPTY_RESPONSE: WorkspaceConnectionsResponse = {
|
|
@@ -433,9 +436,18 @@ const MCP_INTEGRATIONS_BY_ID = new Map(
|
|
|
433
436
|
]),
|
|
434
437
|
);
|
|
435
438
|
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
+
const GOOGLE_PRODUCT_BY_PROVIDER = {
|
|
440
|
+
gmail: "gmail",
|
|
441
|
+
google_calendar: "calendar",
|
|
442
|
+
google_docs: "docs",
|
|
443
|
+
google_drive: "drive",
|
|
444
|
+
google_sheets: "sheets",
|
|
445
|
+
google_slides: "slides",
|
|
446
|
+
} as const;
|
|
447
|
+
|
|
448
|
+
function isGoogleWorkspaceProvider(providerId: string): boolean {
|
|
449
|
+
return providerId in GOOGLE_PRODUCT_BY_PROVIDER;
|
|
450
|
+
}
|
|
439
451
|
|
|
440
452
|
function cx(...classes: Array<string | false | null | undefined>) {
|
|
441
453
|
return classes.filter(Boolean).join(" ");
|
|
@@ -446,9 +458,14 @@ function iconForProvider(providerId: string): IconComponent {
|
|
|
446
458
|
}
|
|
447
459
|
|
|
448
460
|
function logoForProvider(providerId: string, providerName: string): ReactNode {
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
461
|
+
const googleProduct =
|
|
462
|
+
GOOGLE_PRODUCT_BY_PROVIDER[
|
|
463
|
+
providerId as keyof typeof GOOGLE_PRODUCT_BY_PROVIDER
|
|
464
|
+
];
|
|
465
|
+
if (googleProduct) {
|
|
466
|
+
return <GoogleProductLogo product={googleProduct} className="size-7" />;
|
|
467
|
+
}
|
|
468
|
+
const integration = MCP_INTEGRATIONS_BY_ID.get(providerId);
|
|
452
469
|
if (!integration?.logoUrl) {
|
|
453
470
|
const Icon = iconForProvider(providerId);
|
|
454
471
|
return <Icon size={18} />;
|
|
@@ -766,7 +783,10 @@ function summarizeUserAccess(
|
|
|
766
783
|
return `${labels.join(", ")}${suffix}`;
|
|
767
784
|
}
|
|
768
785
|
|
|
769
|
-
function startWorkspaceProviderOAuth(
|
|
786
|
+
function startWorkspaceProviderOAuth(
|
|
787
|
+
provider: WorkspaceConnectionProvider,
|
|
788
|
+
scope: "user" | "organization" = "organization",
|
|
789
|
+
) {
|
|
770
790
|
const returnPath = `${window.location.pathname}${window.location.search}`;
|
|
771
791
|
if (provider.id === "slack") {
|
|
772
792
|
const params = new URLSearchParams({ return: returnPath });
|
|
@@ -777,15 +797,11 @@ function startWorkspaceProviderOAuth(provider: WorkspaceConnectionProvider) {
|
|
|
777
797
|
);
|
|
778
798
|
return;
|
|
779
799
|
}
|
|
780
|
-
|
|
800
|
+
startManagedWorkspaceProviderOAuth(provider.id, {
|
|
781
801
|
appId: "dispatch",
|
|
782
|
-
|
|
802
|
+
returnPath,
|
|
803
|
+
scope,
|
|
783
804
|
});
|
|
784
|
-
window.location.assign(
|
|
785
|
-
agentNativePath(
|
|
786
|
-
`/_agent-native/connections/oauth/${provider.id}/start?${params.toString()}`,
|
|
787
|
-
),
|
|
788
|
-
);
|
|
789
805
|
}
|
|
790
806
|
|
|
791
807
|
function providerHasOAuth(provider: WorkspaceConnectionProvider): boolean {
|
|
@@ -820,7 +836,10 @@ function ConnectionRow({
|
|
|
820
836
|
canManageGrant: (appId: string) => boolean;
|
|
821
837
|
}) {
|
|
822
838
|
const t = useT();
|
|
823
|
-
const
|
|
839
|
+
const providerLogo = logoForProvider(
|
|
840
|
+
connection.provider,
|
|
841
|
+
provider?.label ?? connection.provider,
|
|
842
|
+
);
|
|
824
843
|
const missingKeys = missingRequiredCredentialKeys(
|
|
825
844
|
provider,
|
|
826
845
|
connection.credentialRefs,
|
|
@@ -837,7 +856,7 @@ function ConnectionRow({
|
|
|
837
856
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
838
857
|
<div className="flex min-w-0 items-start gap-3">
|
|
839
858
|
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-background/80">
|
|
840
|
-
|
|
859
|
+
{providerLogo}
|
|
841
860
|
</div>
|
|
842
861
|
<div className="min-w-0">
|
|
843
862
|
<div className="flex flex-wrap items-center gap-2">
|
|
@@ -2787,6 +2806,10 @@ export default function WorkspaceIntegrationsRoute() {
|
|
|
2787
2806
|
}
|
|
2788
2807
|
|
|
2789
2808
|
function openProviderConnection(provider: WorkspaceConnectionProvider) {
|
|
2809
|
+
if (isGoogleWorkspaceProvider(provider.id)) {
|
|
2810
|
+
setProviderChoice({ provider, personalOAuth: true });
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2790
2813
|
const personalIntegration = personalIntegrations.get(provider.id);
|
|
2791
2814
|
if (personalIntegration) {
|
|
2792
2815
|
setProviderChoice({ provider, personalIntegration });
|
|
@@ -3195,14 +3218,16 @@ export default function WorkspaceIntegrationsRoute() {
|
|
|
3195
3218
|
actionLabel: connected
|
|
3196
3219
|
? canManageConnection(active[0])
|
|
3197
3220
|
? "Manage"
|
|
3198
|
-
: personalIntegrations.has(provider.id)
|
|
3221
|
+
: personalIntegrations.has(provider.id) ||
|
|
3222
|
+
isGoogleWorkspaceProvider(provider.id)
|
|
3199
3223
|
? "Connect for me"
|
|
3200
3224
|
: "Admin only"
|
|
3201
3225
|
: "Connect",
|
|
3202
3226
|
disabled:
|
|
3203
3227
|
!connected &&
|
|
3204
3228
|
!canManageConnections &&
|
|
3205
|
-
!personalIntegrations.has(provider.id)
|
|
3229
|
+
!personalIntegrations.has(provider.id) &&
|
|
3230
|
+
!isGoogleWorkspaceProvider(provider.id),
|
|
3206
3231
|
onAction: () =>
|
|
3207
3232
|
connected
|
|
3208
3233
|
? canManageConnection(active[0])
|
|
@@ -3416,14 +3441,23 @@ export default function WorkspaceIntegrationsRoute() {
|
|
|
3416
3441
|
)}
|
|
3417
3442
|
showWorkspaceOption={canManageConnections}
|
|
3418
3443
|
onPersonal={() => {
|
|
3419
|
-
|
|
3444
|
+
const provider = providerChoice.provider;
|
|
3420
3445
|
setProviderChoice(null);
|
|
3446
|
+
if (providerChoice.personalOAuth) {
|
|
3447
|
+
startWorkspaceProviderOAuth(provider, "user");
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
if (providerChoice.personalIntegration) {
|
|
3451
|
+
setPersonalIntegrationId(
|
|
3452
|
+
providerChoice.personalIntegration.id,
|
|
3453
|
+
);
|
|
3454
|
+
}
|
|
3421
3455
|
}}
|
|
3422
3456
|
onWorkspace={() => {
|
|
3423
3457
|
const provider = providerChoice.provider;
|
|
3424
3458
|
setProviderChoice(null);
|
|
3425
3459
|
if (providerHasOAuth(provider)) {
|
|
3426
|
-
startWorkspaceProviderOAuth(provider);
|
|
3460
|
+
startWorkspaceProviderOAuth(provider, "organization");
|
|
3427
3461
|
} else {
|
|
3428
3462
|
openSetup(provider);
|
|
3429
3463
|
}
|
|
@@ -15,4 +15,6 @@ import { flatRoutes } from "@react-router/fs-routes";
|
|
|
15
15
|
* route here via `app/routes/<name>.tsx`, then register the tab in
|
|
16
16
|
* `app/dispatch-extensions.tsx`.
|
|
17
17
|
*/
|
|
18
|
-
export default flatRoutes(
|
|
18
|
+
export default flatRoutes({
|
|
19
|
+
ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
20
|
+
}) satisfies RouteConfig;
|
|
@@ -19,10 +19,17 @@ data, and generated extension/app content may mention credential **names** such
|
|
|
19
19
|
as `OPENAI_API_KEY`, but must not contain real API keys, tokens, webhook URLs,
|
|
20
20
|
signing secrets, OAuth refresh tokens, or private Builder/customer data.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`${keys.NAME}` substitution.
|
|
25
|
-
|
|
22
|
+
Provider secret values are supplied at runtime through the encrypted
|
|
23
|
+
`app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
24
|
+
`${keys.NAME}` substitution. Deployment configuration is reserved for
|
|
25
|
+
deploy-level secrets and non-provider configuration. Examples must use obvious
|
|
26
|
+
placeholders such as `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not
|
|
27
|
+
real-looking copied values.
|
|
28
|
+
|
|
29
|
+
Provider credentials and provider account identifiers are workspace data. Use
|
|
30
|
+
standard workspace connections and org/workspace vault scopes; never put them
|
|
31
|
+
in `.env` or deployment environment variables, and never add a provider-specific
|
|
32
|
+
action or startup bootstrap just to write a credential for one organization.
|
|
26
33
|
|
|
27
34
|
## Credential Modeling Preflight
|
|
28
35
|
|
|
@@ -29,13 +29,8 @@ BUILDER_PROJECT_ID=
|
|
|
29
29
|
BUILDER_PRIVATE_KEY=
|
|
30
30
|
FACTORY_BUILDER_WEBHOOK_SECRET=
|
|
31
31
|
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
SLACK_BOT_TOKEN=
|
|
35
|
-
GITHUB_TOKEN=
|
|
36
|
-
SENTRY_SERVER_TOKEN=
|
|
37
|
-
SENTRY_AUTH_TOKEN=
|
|
38
|
-
SENTRY_ORG_SLUG=
|
|
32
|
+
# Provider credentials and account identifiers belong in standard shared
|
|
33
|
+
# integrations and the org/workspace vault. Do not put provider keys in .env.
|
|
39
34
|
|
|
40
35
|
# Skip login/signup (local dev / preview only)
|
|
41
36
|
# AUTH_DISABLED=true
|
|
@@ -31,6 +31,9 @@ decisions, feedback, agent runs, and provider audit records.
|
|
|
31
31
|
- Provider credentials belong to Dispatch/shared workspace integrations, never
|
|
32
32
|
to a Factory or Factory graph. Agents use shared provider APIs and connected
|
|
33
33
|
MCP tools through the workspace grant boundary.
|
|
34
|
+
- Never put provider keys or account identifiers in `.env`, deployment env, or
|
|
35
|
+
Factory actions/bootstrap. Configure standard integrations and resolve them
|
|
36
|
+
from the multitenant org/workspace vault.
|
|
34
37
|
- For external integrations, inspect the workspace/provider connection catalog first; reuse its scoped resolver.
|
|
35
38
|
|
|
36
39
|
## Application state
|
|
@@ -37,9 +37,11 @@ If Dispatch synced the vault into a different organization, set
|
|
|
37
37
|
|
|
38
38
|
Connect providers in Dispatch or in Settings -> Integrations. Factory resolves
|
|
39
39
|
Slack, GitHub, Sentry, Builder, and other supported provider credentials from
|
|
40
|
-
the shared workspace vault
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
the shared workspace vault. Provider deployment environment variables are not
|
|
41
|
+
supported for Factory. To migrate an existing deployment, add the provider
|
|
42
|
+
connection in the standard workspace integration surface, verify it, and then
|
|
43
|
+
remove the old deployment variables. Factory never stores keys per factory. All
|
|
44
|
+
apps that read shared `app_secrets` rows must use the same
|
|
43
45
|
`WORKSPACE_SECRETS_ENCRYPTION_KEY` (or the workspace's existing shared
|
|
44
46
|
encryption fallback). Never copy raw tokens between apps or add a second
|
|
45
47
|
env-only read in a provider client.
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../server/lib/factory-automation-plan.js";
|
|
21
21
|
import {
|
|
22
22
|
assertUniqueSlackChannelForFactory,
|
|
23
|
+
builderSlackUserIdSchema,
|
|
23
24
|
factoryConfigRowId,
|
|
24
25
|
resolveUniqueFactoryId,
|
|
25
26
|
} from "../server/lib/factory-scope.js";
|
|
@@ -40,8 +41,10 @@ export default defineAction({
|
|
|
40
41
|
schema: z.object({
|
|
41
42
|
name: z.string().trim().min(1).max(120),
|
|
42
43
|
description: z.string().trim().max(500).optional(),
|
|
44
|
+
slackWorkspace: z.enum(["primary", "secondary"]).optional(),
|
|
43
45
|
slackChannelId: z.string().trim().max(128).optional(),
|
|
44
46
|
slackChannelName: z.string().trim().max(200).optional(),
|
|
47
|
+
builderSlackUserId: builderSlackUserIdSchema.optional(),
|
|
45
48
|
observeSlack: z.boolean().optional(),
|
|
46
49
|
repository: z.string().trim().max(256).optional(),
|
|
47
50
|
observeGithub: z.boolean().optional(),
|
|
@@ -111,7 +114,16 @@ export default defineAction({
|
|
|
111
114
|
orgId,
|
|
112
115
|
});
|
|
113
116
|
|
|
114
|
-
|
|
117
|
+
const shouldWriteConfig =
|
|
118
|
+
automationPlan.hasConfig ||
|
|
119
|
+
Boolean(input.slackChannelId?.trim()) ||
|
|
120
|
+
Boolean(input.slackChannelName?.trim()) ||
|
|
121
|
+
Boolean(input.builderSlackUserId?.trim()) ||
|
|
122
|
+
Boolean(input.slackWorkspace) ||
|
|
123
|
+
Boolean(input.sentryOrgSlug?.trim()) ||
|
|
124
|
+
Boolean(input.sentryProjectSlug?.trim()) ||
|
|
125
|
+
Boolean(input.sentryEnvironment?.trim());
|
|
126
|
+
if (shouldWriteConfig) {
|
|
115
127
|
const slackChannelId = input.slackChannelId?.trim() || null;
|
|
116
128
|
await assertUniqueSlackChannelForFactory(
|
|
117
129
|
tx as unknown as typeof db,
|
|
@@ -122,10 +134,11 @@ export default defineAction({
|
|
|
122
134
|
await tx.insert(triageConfig).values({
|
|
123
135
|
id: factoryConfigRowId(orgId, factoryId),
|
|
124
136
|
factoryId,
|
|
125
|
-
slackWorkspace:
|
|
137
|
+
slackWorkspace:
|
|
138
|
+
input.slackWorkspace === "secondary" ? "secondary" : "primary",
|
|
126
139
|
slackChannelId,
|
|
127
140
|
slackChannelName: input.slackChannelName?.trim() || null,
|
|
128
|
-
builderSlackUserId: null,
|
|
141
|
+
builderSlackUserId: input.builderSlackUserId?.trim() || null,
|
|
129
142
|
pollingEnabled: automationPlan.pollingEnabled ? 1 : 0,
|
|
130
143
|
githubPollingEnabled: automationPlan.githubPollingEnabled ? 1 : 0,
|
|
131
144
|
sentryPollingEnabled: automationPlan.sentryPollingEnabled ? 1 : 0,
|
|
@@ -7,9 +7,17 @@ import { and, desc, eq, inArray } from "drizzle-orm";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { getDb } from "../server/db/index.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
factoryAuditEvents,
|
|
12
|
+
triageItems,
|
|
13
|
+
triageRuns,
|
|
14
|
+
} from "../server/db/schema.js";
|
|
15
|
+
import { projectFactoryAuditReport } from "../server/lib/factory-audit-report.js";
|
|
11
16
|
import {
|
|
12
17
|
factoryIdSchema,
|
|
18
|
+
orgFactoryItemFilter,
|
|
19
|
+
orgFactoryRunFilter,
|
|
20
|
+
readAutomationDisplayName,
|
|
13
21
|
readAutomationFactoryId,
|
|
14
22
|
} from "../server/lib/factory-scope.js";
|
|
15
23
|
import {
|
|
@@ -39,23 +47,30 @@ export default defineAction({
|
|
|
39
47
|
const factoryDefinitions = definitions.filter(
|
|
40
48
|
({ meta, name, resource }) =>
|
|
41
49
|
meta.domain === "factory" &&
|
|
42
|
-
readAutomationFactoryId(meta, resource.content) ===
|
|
50
|
+
readAutomationFactoryId(meta, resource.content, resource.path) ===
|
|
51
|
+
factoryId &&
|
|
43
52
|
(!automation || name === automation),
|
|
44
53
|
);
|
|
45
54
|
const runGroups = await Promise.all(
|
|
46
|
-
factoryDefinitions.map(async ({ name, resource }) =>
|
|
47
|
-
listAutomationRuns({
|
|
55
|
+
factoryDefinitions.map(async ({ name, resource }) => {
|
|
56
|
+
const runs = await listAutomationRuns({
|
|
48
57
|
owners: [resource.owner],
|
|
49
58
|
automation: name,
|
|
50
59
|
appId: "factory",
|
|
51
60
|
limit,
|
|
52
|
-
})
|
|
53
|
-
|
|
61
|
+
});
|
|
62
|
+
// Absent must stay distinguishable from a stored label so the client
|
|
63
|
+
// can derive its own fallback instead of rendering the nested path.
|
|
64
|
+
const displayName = readAutomationDisplayName(resource.content);
|
|
65
|
+
return runs.map((run) => ({ run, displayName }));
|
|
66
|
+
}),
|
|
54
67
|
);
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
const entries = runGroups
|
|
69
|
+
.flat()
|
|
70
|
+
.sort((a, b) => b.run.startedAt - a.run.startedAt);
|
|
71
|
+
const boundedEntries = entries.slice(0, limit);
|
|
72
|
+
const runIds = boundedEntries
|
|
73
|
+
.map(({ run }) => run.runId)
|
|
59
74
|
.filter((runId): runId is string => Boolean(runId));
|
|
60
75
|
|
|
61
76
|
const db = getDb();
|
|
@@ -80,33 +95,98 @@ export default defineAction({
|
|
|
80
95
|
eventsByRun.set(event.automationRunId, current);
|
|
81
96
|
}
|
|
82
97
|
|
|
98
|
+
const itemIds = [
|
|
99
|
+
...new Set(
|
|
100
|
+
events.flatMap((event) => {
|
|
101
|
+
const ids: string[] = [];
|
|
102
|
+
if (event.itemId) ids.push(event.itemId);
|
|
103
|
+
const details = parseDetails(event.detailsJson);
|
|
104
|
+
const listed = details.itemIds;
|
|
105
|
+
if (Array.isArray(listed)) {
|
|
106
|
+
for (const value of listed) {
|
|
107
|
+
if (typeof value === "string" && value) ids.push(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return ids;
|
|
111
|
+
}),
|
|
112
|
+
),
|
|
113
|
+
];
|
|
114
|
+
const itemRows = itemIds.length
|
|
115
|
+
? await db
|
|
116
|
+
.select({
|
|
117
|
+
id: triageItems.id,
|
|
118
|
+
title: triageItems.title,
|
|
119
|
+
summary: triageItems.summary,
|
|
120
|
+
source: triageItems.source,
|
|
121
|
+
sourceUrl: triageItems.sourceUrl,
|
|
122
|
+
})
|
|
123
|
+
.from(triageItems)
|
|
124
|
+
.where(
|
|
125
|
+
and(
|
|
126
|
+
orgFactoryItemFilter(orgId, factoryId),
|
|
127
|
+
inArray(triageItems.id, itemIds),
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
: [];
|
|
131
|
+
const runRows = itemIds.length
|
|
132
|
+
? await db
|
|
133
|
+
.select({
|
|
134
|
+
itemId: triageRuns.itemId,
|
|
135
|
+
status: triageRuns.status,
|
|
136
|
+
error: triageRuns.error,
|
|
137
|
+
provider: triageRuns.provider,
|
|
138
|
+
startedAt: triageRuns.startedAt,
|
|
139
|
+
})
|
|
140
|
+
.from(triageRuns)
|
|
141
|
+
.where(
|
|
142
|
+
and(
|
|
143
|
+
orgFactoryRunFilter(orgId, factoryId),
|
|
144
|
+
inArray(triageRuns.itemId, itemIds),
|
|
145
|
+
),
|
|
146
|
+
)
|
|
147
|
+
: [];
|
|
148
|
+
|
|
83
149
|
return {
|
|
84
|
-
runs:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
150
|
+
runs: boundedEntries.map(({ run, displayName }) => {
|
|
151
|
+
const mappedEvents = (eventsByRun.get(run.runId ?? "") ?? []).map(
|
|
152
|
+
(event) => ({
|
|
153
|
+
id: event.id,
|
|
154
|
+
automationRunId: event.automationRunId,
|
|
155
|
+
automationThreadId: event.automationThreadId,
|
|
156
|
+
automationName: event.automationName,
|
|
157
|
+
itemId: event.itemId,
|
|
158
|
+
source: event.source,
|
|
159
|
+
sourceUrl: event.sourceUrl,
|
|
160
|
+
action: event.action,
|
|
161
|
+
kind: event.kind,
|
|
162
|
+
status: event.status,
|
|
163
|
+
summary: event.summary,
|
|
164
|
+
details: parseDetails(event.detailsJson),
|
|
165
|
+
createdAt: event.createdAt,
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
168
|
+
const report = projectFactoryAuditReport(
|
|
169
|
+
mappedEvents,
|
|
170
|
+
itemRows,
|
|
171
|
+
runRows,
|
|
172
|
+
{ startedAt: run.startedAt, finishedAt: run.finishedAt },
|
|
173
|
+
);
|
|
174
|
+
return {
|
|
175
|
+
id: run.id,
|
|
176
|
+
automation: run.automation,
|
|
177
|
+
displayName,
|
|
178
|
+
runId: run.runId,
|
|
179
|
+
threadId: run.threadId,
|
|
180
|
+
status: run.status,
|
|
181
|
+
startedAt: run.startedAt,
|
|
182
|
+
finishedAt: run.finishedAt,
|
|
183
|
+
error: run.error,
|
|
184
|
+
counts: report.counts,
|
|
185
|
+
items: report.items,
|
|
186
|
+
trace: report.trace,
|
|
187
|
+
};
|
|
188
|
+
}),
|
|
189
|
+
count: boundedEntries.length,
|
|
110
190
|
};
|
|
111
191
|
},
|
|
112
192
|
});
|
|
@@ -43,7 +43,8 @@ export default defineAction({
|
|
|
43
43
|
const scoped = definitions.filter(
|
|
44
44
|
({ meta, resource }) =>
|
|
45
45
|
meta.domain === "factory" &&
|
|
46
|
-
readAutomationFactoryId(meta, resource.content) ===
|
|
46
|
+
readAutomationFactoryId(meta, resource.content, resource.path) ===
|
|
47
|
+
factoryId,
|
|
47
48
|
);
|
|
48
49
|
return Promise.all(
|
|
49
50
|
scoped.map(async ({ resource, name, meta, body, canUpdate }) => {
|