@agent-native/core 0.169.1 → 0.170.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/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 +16 -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/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/file-upload/actions/upload-image.d.ts +1 -1
- 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/routes.d.ts +3 -3
- 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/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 +23 -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/transcribe-voice.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 +24 -5
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -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
|
@@ -5054,7 +5054,13 @@ export default function SlideEditor({
|
|
|
5054
5054
|
(patch: SlideStylePatch) => {
|
|
5055
5055
|
const editing = editingElRef.current;
|
|
5056
5056
|
const element = editing ?? resolveSelectedElement();
|
|
5057
|
-
|
|
5057
|
+
// Inline edits entered without selectElementForStyling (the text-box
|
|
5058
|
+
// tool) leave selectedElementSelector null, so fall back the same way the
|
|
5059
|
+
// snapshot readers do rather than dropping the write.
|
|
5060
|
+
const selector =
|
|
5061
|
+
selectedElementSelector ??
|
|
5062
|
+
(editing ? getBuilderSelector(editing) : null);
|
|
5063
|
+
if (!element || !selector) return;
|
|
5058
5064
|
|
|
5059
5065
|
const inlinePatch = inlineInspectorStylePatch(patch);
|
|
5060
5066
|
const inlineKeys = INLINE_INSPECTOR_STYLE_KEYS.filter(
|
|
@@ -5117,11 +5123,7 @@ export default function SlideEditor({
|
|
|
5117
5123
|
richTextSelectionRef.current,
|
|
5118
5124
|
)
|
|
5119
5125
|
: undefined;
|
|
5120
|
-
const snapshot = buildStyleSnapshot(
|
|
5121
|
-
element,
|
|
5122
|
-
selectedElementSelector,
|
|
5123
|
-
inlineTextStyle,
|
|
5124
|
-
);
|
|
5126
|
+
const snapshot = buildStyleSnapshot(element, selector, inlineTextStyle);
|
|
5125
5127
|
if (!editing) {
|
|
5126
5128
|
invalidateSelectionOverlayMeasurement();
|
|
5127
5129
|
}
|
|
@@ -5129,7 +5131,7 @@ export default function SlideEditor({
|
|
|
5129
5131
|
if (!editing) {
|
|
5130
5132
|
syncSelectionToAppState(
|
|
5131
5133
|
buildSelectionState(getSlideSelectionMode(snapshot), [
|
|
5132
|
-
selectionItemForElement(element,
|
|
5134
|
+
selectionItemForElement(element, selector, snapshot),
|
|
5133
5135
|
]),
|
|
5134
5136
|
);
|
|
5135
5137
|
}
|
|
@@ -5211,15 +5213,25 @@ export default function SlideEditor({
|
|
|
5211
5213
|
converted.focus({ preventScroll: true });
|
|
5212
5214
|
}
|
|
5213
5215
|
|
|
5216
|
+
// Committing while an edit is open re-renders the slide from `content`
|
|
5217
|
+
// and replaces the contentEditable node; stash a draft instead and let
|
|
5218
|
+
// exitInlineEdit flush it.
|
|
5219
|
+
if (editing) {
|
|
5220
|
+
captureInlineEditDraft(slide.id);
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5223
|
+
|
|
5214
5224
|
const html = readCurrentSlideContentHtml();
|
|
5215
5225
|
if (html !== null) onUpdateSlideRef.current({ content: html });
|
|
5216
5226
|
const selector = getBuilderSelector(converted);
|
|
5217
5227
|
if (selector) selectElementForStyling(converted, selector);
|
|
5218
5228
|
},
|
|
5219
5229
|
[
|
|
5230
|
+
captureInlineEditDraft,
|
|
5220
5231
|
readCurrentSlideContentHtml,
|
|
5221
5232
|
resolveSelectedElement,
|
|
5222
5233
|
selectElementForStyling,
|
|
5234
|
+
slide.id,
|
|
5223
5235
|
],
|
|
5224
5236
|
);
|
|
5225
5237
|
|
|
@@ -300,42 +300,55 @@ function cleanNode(
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
function sanitizeHtmlString(html: string, scopeSelector?: string): string {
|
|
303
|
-
return
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
303
|
+
return (
|
|
304
|
+
html
|
|
305
|
+
.replace(/<style\b[^>]*>([\s\S]*?)<\/\s*style\s*>/gi, (_match, css) => {
|
|
306
|
+
const safeCss = sanitizeStyleSheet(String(css), scopeSelector);
|
|
307
|
+
return safeCss
|
|
308
|
+
? `<style>${safeCss.replace(/<\/style/gi, "<\\/style")}</style>`
|
|
309
|
+
: "";
|
|
310
|
+
})
|
|
311
|
+
.replace(
|
|
312
|
+
/<(script|iframe|object|embed|form|input|button|select|textarea|meta|base|link|svg|math)\b[\s\S]*?<\/\s*\1\s*>/gi,
|
|
313
|
+
"",
|
|
314
|
+
)
|
|
315
|
+
// Anything left here is a blocked element that never closed. The opening-tag
|
|
316
|
+
// pass below would strip only its tag and leave the body behind as slide
|
|
317
|
+
// text — which is how a script's JavaScript renders as visible copy on the
|
|
318
|
+
// SSR'd share/present pages, where DOMParser is undefined and this regex
|
|
319
|
+
// twin runs instead of cleanNode(). An unclosed raw-text or embedding
|
|
320
|
+
// element swallows the rest of the document in a real parser, so dropping
|
|
321
|
+
// the remainder is what keeps this path agreeing with the DOM path.
|
|
322
|
+
.replace(
|
|
323
|
+
/<(script|style|textarea|iframe|object|embed|svg|math)\b[\s\S]*$/i,
|
|
324
|
+
"",
|
|
325
|
+
)
|
|
326
|
+
.replace(
|
|
327
|
+
/<(script|iframe|object|embed|form|input|button|select|textarea|meta|base|link|svg|math)\b[^>]*\/?>/gi,
|
|
328
|
+
"",
|
|
329
|
+
)
|
|
330
|
+
.replace(/\s+on[a-z][\w:-]*\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
331
|
+
.replace(/\s+srcdoc\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
332
|
+
.replace(/\s+srcset\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "")
|
|
333
|
+
.replace(
|
|
334
|
+
/\s+(href|src|xlink:href)\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/gi,
|
|
335
|
+
(match, attr, _raw, dq, sq, bare) => {
|
|
336
|
+
const value = dq ?? sq ?? bare ?? "";
|
|
337
|
+
const safe = sanitizeSlideUrl(
|
|
338
|
+
value,
|
|
339
|
+
String(attr).toLowerCase() === "src" ? "image" : "link",
|
|
340
|
+
);
|
|
341
|
+
return safe ? ` ${attr}="${escapeHtml(safe)}"` : "";
|
|
342
|
+
},
|
|
343
|
+
)
|
|
344
|
+
.replace(
|
|
345
|
+
/\s+style\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/gi,
|
|
346
|
+
(_match, _raw, dq, sq, bare) => {
|
|
347
|
+
const safe = sanitizeStyle(dq ?? sq ?? bare ?? "");
|
|
348
|
+
return safe ? ` style="${escapeHtml(safe)}"` : "";
|
|
349
|
+
},
|
|
350
|
+
)
|
|
351
|
+
);
|
|
339
352
|
}
|
|
340
353
|
|
|
341
354
|
export function sanitizeSlideHtml(
|
|
@@ -42,16 +42,23 @@ export default function ApproveDeckAccessRequestRoute() {
|
|
|
42
42
|
const deckId = searchParams.get("deckId") ?? "";
|
|
43
43
|
const approvalTokenFromUrl = searchParams.get("token") ?? "";
|
|
44
44
|
const approvalTokenStorageKey = deckAccessApprovalSessionKey(deckId);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
// Only the URL token is knowable on the server, so reading storage in the
|
|
46
|
+
// initializer makes the first client render disagree with the server's and
|
|
47
|
+
// React re-renders the page from scratch. Adopt the stored token after mount.
|
|
48
|
+
const [approvalToken, setApprovalToken] = useState(
|
|
49
|
+
() => approvalTokenFromUrl ?? "",
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (approvalTokenFromUrl || !deckId) return;
|
|
48
54
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
const stored = sessionStorage.getItem(approvalTokenStorageKey);
|
|
56
|
+
if (stored) setApprovalToken(stored);
|
|
57
|
+
// Unavailable tab storage is an absent continuation: the page then asks
|
|
58
|
+
// for the token rather than silently continuing without one.
|
|
59
|
+
// coercion-ok: the absent case is visible to the user, not swallowed.
|
|
60
|
+
} catch {}
|
|
61
|
+
}, [approvalTokenFromUrl, deckId, approvalTokenStorageKey]);
|
|
55
62
|
const [state, setState] = useState<ApprovalState>({ kind: "loading" });
|
|
56
63
|
|
|
57
64
|
useEffect(() => {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type RouteConfig } from "@react-router/dev/routes";
|
|
2
2
|
import { flatRoutes } from "@react-router/fs-routes";
|
|
3
3
|
|
|
4
|
-
export default flatRoutes(
|
|
4
|
+
export default flatRoutes({
|
|
5
|
+
ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
6
|
+
}) satisfies RouteConfig;
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
decodeOAuthState,
|
|
3
3
|
encodeOAuthState,
|
|
4
4
|
getAppUrl,
|
|
5
|
+
getCredentialContext,
|
|
5
6
|
getSession,
|
|
6
7
|
isElectron,
|
|
7
8
|
oauthCallbackResponse,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
resolveOAuthRedirectUri,
|
|
10
11
|
safeReturnPath,
|
|
11
12
|
} from "@agent-native/core/server";
|
|
13
|
+
import { resolveWorkspaceConnectionForApp } from "@agent-native/core/workspace-connections";
|
|
12
14
|
import {
|
|
13
15
|
defineEventHandler,
|
|
14
16
|
getQuery,
|
|
@@ -27,8 +29,45 @@ import {
|
|
|
27
29
|
isGoogleDocsOAuthConfigured,
|
|
28
30
|
listGoogleDocsAccounts,
|
|
29
31
|
} from "../lib/google-docs-oauth.js";
|
|
32
|
+
import { getSlidesProviderApiRuntime } from "../lib/provider-api.js";
|
|
33
|
+
import { withSlidesRequestContext } from "./request-auth-context.js";
|
|
30
34
|
const OAUTH_STATE_APP_ID = process.env.APP_NAME || "slides";
|
|
31
35
|
|
|
36
|
+
async function resolveManagedGoogleDriveAccount() {
|
|
37
|
+
if (!getCredentialContext()) return null;
|
|
38
|
+
const connection = await resolveWorkspaceConnectionForApp({
|
|
39
|
+
appId: "slides",
|
|
40
|
+
provider: "google_drive",
|
|
41
|
+
requireConnected: true,
|
|
42
|
+
});
|
|
43
|
+
if (!connection.available) return null;
|
|
44
|
+
const credential =
|
|
45
|
+
await getSlidesProviderApiRuntime().resolveOAuthAccessToken({
|
|
46
|
+
provider: "google_drive",
|
|
47
|
+
});
|
|
48
|
+
if (!credential.accountId) return null;
|
|
49
|
+
return {
|
|
50
|
+
email: credential.accountId,
|
|
51
|
+
accessToken: credential.accessToken,
|
|
52
|
+
scope: "https://www.googleapis.com/auth/drive.readonly",
|
|
53
|
+
shared: true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function getAvailableGoogleDocsAccessToken(
|
|
58
|
+
event: H3Event,
|
|
59
|
+
owner: string,
|
|
60
|
+
) {
|
|
61
|
+
return withSlidesRequestContext(event, async () => {
|
|
62
|
+
const local = await getGoogleDocsAccessToken(owner);
|
|
63
|
+
if (local) return local;
|
|
64
|
+
const managed = await resolveManagedGoogleDriveAccount();
|
|
65
|
+
return managed
|
|
66
|
+
? { accessToken: managed.accessToken, accountEmail: managed.email }
|
|
67
|
+
: null;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
32
71
|
async function requireSessionEmail(event: H3Event): Promise<string | null> {
|
|
33
72
|
const session = await getSession(event);
|
|
34
73
|
if (!session?.email) {
|
|
@@ -160,6 +199,18 @@ export const getGoogleDocsStatus = defineEventHandler(
|
|
|
160
199
|
|
|
161
200
|
try {
|
|
162
201
|
const accounts = await listGoogleDocsAccounts(owner);
|
|
202
|
+
if (accounts.length === 0) {
|
|
203
|
+
const managed = await withSlidesRequestContext(event, () =>
|
|
204
|
+
resolveManagedGoogleDriveAccount(),
|
|
205
|
+
);
|
|
206
|
+
if (managed) {
|
|
207
|
+
accounts.push({
|
|
208
|
+
email: managed.email,
|
|
209
|
+
scope: managed.scope,
|
|
210
|
+
shared: true,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
163
214
|
const picker = await getGooglePickerConfig(owner);
|
|
164
215
|
return {
|
|
165
216
|
configured: await isGoogleDocsOAuthConfigured(owner),
|
|
@@ -206,7 +257,7 @@ export const getGoogleDocsPickerToken = defineEventHandler(
|
|
|
206
257
|
}
|
|
207
258
|
|
|
208
259
|
try {
|
|
209
|
-
const token = await
|
|
260
|
+
const token = await getAvailableGoogleDocsAccessToken(event, owner);
|
|
210
261
|
if (!token) {
|
|
211
262
|
setResponseStatus(event, 401);
|
|
212
263
|
return {
|
|
@@ -47,7 +47,10 @@ export async function prepareSlidesChatAttachments(args: {
|
|
|
47
47
|
path: string;
|
|
48
48
|
url?: string;
|
|
49
49
|
type: string;
|
|
50
|
-
|
|
50
|
+
// Unset (not 0) for an attachment we never downloaded — an already-hosted
|
|
51
|
+
// URL-only attachment has no known byte size, and "0" would misreport it
|
|
52
|
+
// as an empty file instead of an unmeasured one.
|
|
53
|
+
size?: number;
|
|
51
54
|
}> = [];
|
|
52
55
|
const failed: Array<{ name: string; reason: string }> = [];
|
|
53
56
|
const nextAttachments = [...args.attachments];
|
|
@@ -55,10 +58,33 @@ export async function prepareSlidesChatAttachments(args: {
|
|
|
55
58
|
for (let index = 0; index < args.attachments.length; index++) {
|
|
56
59
|
const attachment = args.attachments[index];
|
|
57
60
|
if (!attachment) continue;
|
|
61
|
+
const ext = path.extname(attachment.name).toLowerCase();
|
|
62
|
+
|
|
63
|
+
// An attachment can arrive already durably hosted — a plain `url` with no
|
|
64
|
+
// inline `data` (e.g. `referenceImagePaths`/image content parts wrap an
|
|
65
|
+
// uploaded file as `{ type: "image", url }`, per
|
|
66
|
+
// packages/core/src/client/agent-chat-adapter.ts). There are no bytes to
|
|
67
|
+
// save, but the file IS attached; skipping it here because only `data`
|
|
68
|
+
// was ever recognized as "attached" is what silently drops it and leaves
|
|
69
|
+
// the agent with no signal it exists.
|
|
70
|
+
if (
|
|
71
|
+
typeof attachment.data !== "string" &&
|
|
72
|
+
typeof attachment.url === "string"
|
|
73
|
+
) {
|
|
74
|
+
if (isSlidesReferenceFileExtension(ext)) {
|
|
75
|
+
uploaded.push({
|
|
76
|
+
originalName: attachment.name,
|
|
77
|
+
path: attachment.url,
|
|
78
|
+
url: attachment.url,
|
|
79
|
+
type: attachment.contentType || "application/octet-stream",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
58
85
|
const dataUrl = attachmentDataUrl(attachment);
|
|
59
86
|
if (!dataUrl) continue;
|
|
60
87
|
|
|
61
|
-
const ext = path.extname(attachment.name).toLowerCase();
|
|
62
88
|
if (!isSlidesReferenceFileExtension(ext)) continue;
|
|
63
89
|
|
|
64
90
|
const decoded = decodeDataUrl(dataUrl);
|
|
@@ -93,7 +119,7 @@ export async function prepareSlidesChatAttachments(args: {
|
|
|
93
119
|
const fileList = uploaded
|
|
94
120
|
.map(
|
|
95
121
|
(file) =>
|
|
96
|
-
`- ${file.originalName} (${file.type}
|
|
122
|
+
`- ${file.originalName} (${file.type}${typeof file.size === "number" ? `, ${(file.size / 1024).toFixed(1)}KB` : ""}) at path: ${file.path}${file.url ? `; embeddable URL: ${file.url}` : ""}`,
|
|
97
123
|
)
|
|
98
124
|
.join("\n");
|
|
99
125
|
const failureList = failed
|
|
@@ -14,7 +14,8 @@ const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
|
14
14
|
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
15
15
|
const USERINFO_URL = "https://www.googleapis.com/oauth2/v2/userinfo";
|
|
16
16
|
|
|
17
|
-
export const GOOGLE_DOCS_PROVIDER = "google
|
|
17
|
+
export const GOOGLE_DOCS_PROVIDER = "google";
|
|
18
|
+
const LEGACY_GOOGLE_DOCS_PROVIDER = "google-docs";
|
|
18
19
|
export const GOOGLE_DRIVE_READONLY_SCOPE =
|
|
19
20
|
"https://www.googleapis.com/auth/drive.readonly";
|
|
20
21
|
export const GOOGLE_DOCS_SCOPES = [
|
|
@@ -35,6 +36,18 @@ export function hasGoogleDriveExportScope(scope?: string): boolean {
|
|
|
35
36
|
);
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
function hasGoogleDriveAccessScope(scope?: string): boolean {
|
|
40
|
+
if (!scope?.trim()) return true;
|
|
41
|
+
const grantedScopes = new Set(
|
|
42
|
+
(scope ?? "").split(/\s+/).filter((value) => value.length > 0),
|
|
43
|
+
);
|
|
44
|
+
return [
|
|
45
|
+
"https://www.googleapis.com/auth/drive",
|
|
46
|
+
"https://www.googleapis.com/auth/drive.file",
|
|
47
|
+
GOOGLE_DRIVE_READONLY_SCOPE,
|
|
48
|
+
].some((requiredScope) => grantedScopes.has(requiredScope));
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
interface GoogleDocsTokens {
|
|
39
52
|
access_token: string;
|
|
40
53
|
refresh_token?: string;
|
|
@@ -130,6 +143,7 @@ export async function getGoogleDocsAuthUrl(
|
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
async function refreshGoogleDocsToken(
|
|
146
|
+
provider: string,
|
|
133
147
|
accountId: string,
|
|
134
148
|
owner: string,
|
|
135
149
|
tokens: GoogleDocsTokens,
|
|
@@ -143,7 +157,7 @@ async function refreshGoogleDocsToken(
|
|
|
143
157
|
}
|
|
144
158
|
|
|
145
159
|
if (!tokens.refresh_token) {
|
|
146
|
-
await deleteOAuthTokens(
|
|
160
|
+
await deleteOAuthTokens(provider, accountId, owner);
|
|
147
161
|
throw new Error("Google Docs connection expired. Please reconnect.");
|
|
148
162
|
}
|
|
149
163
|
|
|
@@ -190,7 +204,7 @@ async function refreshGoogleDocsToken(
|
|
|
190
204
|
|
|
191
205
|
if (!data?.access_token) {
|
|
192
206
|
if (isPermanentGoogleRefreshError(data?.error)) {
|
|
193
|
-
await deleteOAuthTokens(
|
|
207
|
+
await deleteOAuthTokens(provider, accountId, owner);
|
|
194
208
|
}
|
|
195
209
|
throw new Error(
|
|
196
210
|
data?.error_description ||
|
|
@@ -208,7 +222,7 @@ async function refreshGoogleDocsToken(
|
|
|
208
222
|
scope: data.scope ?? tokens.scope,
|
|
209
223
|
};
|
|
210
224
|
await saveOAuthTokens(
|
|
211
|
-
|
|
225
|
+
provider,
|
|
212
226
|
accountId,
|
|
213
227
|
updated as unknown as Record<string, unknown>,
|
|
214
228
|
owner,
|
|
@@ -286,23 +300,26 @@ export async function listGoogleDocsAccounts(owner: string): Promise<
|
|
|
286
300
|
Array<{
|
|
287
301
|
email: string;
|
|
288
302
|
scope?: string;
|
|
303
|
+
shared?: boolean;
|
|
289
304
|
}>
|
|
290
305
|
> {
|
|
291
|
-
const accounts = await
|
|
292
|
-
return accounts
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
306
|
+
const accounts = await listGoogleProviderAccounts(owner);
|
|
307
|
+
return accounts
|
|
308
|
+
.map((account) => ({
|
|
309
|
+
email: account.accountId,
|
|
310
|
+
scope:
|
|
311
|
+
typeof account.tokens.scope === "string"
|
|
312
|
+
? account.tokens.scope
|
|
313
|
+
: undefined,
|
|
314
|
+
}))
|
|
315
|
+
.filter((account) => hasGoogleDriveAccessScope(account.scope));
|
|
299
316
|
}
|
|
300
317
|
|
|
301
318
|
export async function disconnectGoogleDocs(owner: string): Promise<void> {
|
|
302
|
-
const accounts = await
|
|
319
|
+
const accounts = await listGoogleProviderAccounts(owner);
|
|
303
320
|
await Promise.all(
|
|
304
321
|
accounts.map((account) =>
|
|
305
|
-
deleteOAuthTokens(
|
|
322
|
+
deleteOAuthTokens(account.provider, account.accountId, owner),
|
|
306
323
|
),
|
|
307
324
|
);
|
|
308
325
|
}
|
|
@@ -311,17 +328,50 @@ export async function getGoogleDocsAccessToken(owner: string): Promise<{
|
|
|
311
328
|
accessToken: string;
|
|
312
329
|
accountEmail: string;
|
|
313
330
|
} | null> {
|
|
314
|
-
const accounts = await
|
|
331
|
+
const accounts = await listGoogleProviderAccounts(owner);
|
|
315
332
|
if (accounts.length === 0) return null;
|
|
316
333
|
|
|
317
334
|
const account = accounts[0];
|
|
318
|
-
const stored = await getOAuthTokens(
|
|
335
|
+
const stored = await getOAuthTokens(
|
|
336
|
+
account.provider,
|
|
337
|
+
account.accountId,
|
|
338
|
+
owner,
|
|
339
|
+
);
|
|
319
340
|
if (!stored) return null;
|
|
320
341
|
|
|
321
342
|
const accessToken = await refreshGoogleDocsToken(
|
|
343
|
+
account.provider,
|
|
322
344
|
account.accountId,
|
|
323
345
|
owner,
|
|
324
346
|
stored as unknown as GoogleDocsTokens,
|
|
325
347
|
);
|
|
326
348
|
return { accessToken, accountEmail: account.accountId };
|
|
327
349
|
}
|
|
350
|
+
|
|
351
|
+
async function listGoogleProviderAccounts(owner: string): Promise<
|
|
352
|
+
Array<{
|
|
353
|
+
provider: string;
|
|
354
|
+
accountId: string;
|
|
355
|
+
tokens: Record<string, unknown>;
|
|
356
|
+
}>
|
|
357
|
+
> {
|
|
358
|
+
const accounts = await Promise.all(
|
|
359
|
+
[GOOGLE_DOCS_PROVIDER, LEGACY_GOOGLE_DOCS_PROVIDER].map(async (provider) =>
|
|
360
|
+
(await listOAuthAccountsByOwner(provider, owner)).map((account) => ({
|
|
361
|
+
provider,
|
|
362
|
+
accountId: account.accountId,
|
|
363
|
+
tokens: account.tokens,
|
|
364
|
+
})),
|
|
365
|
+
),
|
|
366
|
+
);
|
|
367
|
+
const seen = new Set<string>();
|
|
368
|
+
return accounts.flat().filter((account) => {
|
|
369
|
+
if (!hasGoogleDriveAccessScope(String(account.tokens.scope ?? ""))) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
const key = account.accountId.toLowerCase();
|
|
373
|
+
if (seen.has(key)) return false;
|
|
374
|
+
seen.add(key);
|
|
375
|
+
return true;
|
|
376
|
+
});
|
|
377
|
+
}
|
|
@@ -86,10 +86,21 @@ export async function applySlideContentEdits(
|
|
|
86
86
|
|
|
87
87
|
export async function formatSlideHtml(content: string): Promise<string> {
|
|
88
88
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
// prettier's main entry `import()`s all 13 parser plugins, so a bundler
|
|
90
|
+
// inlines ~3.5MB of flow/typescript/yaml/markdown parsers just to format
|
|
91
|
+
// HTML. Load the standalone core plus only the plugins the HTML printer
|
|
92
|
+
// reaches, which still formats embedded <style> and <script>.
|
|
93
|
+
const [{ format }, ...plugins] = await Promise.all([
|
|
94
|
+
import("prettier/standalone"),
|
|
95
|
+
import("prettier/plugins/html"),
|
|
96
|
+
import("prettier/plugins/postcss"),
|
|
97
|
+
import("prettier/plugins/babel"),
|
|
98
|
+
import("prettier/plugins/estree"),
|
|
99
|
+
]);
|
|
100
|
+
return await format(content, {
|
|
91
101
|
parser: "html",
|
|
92
102
|
htmlWhitespaceSensitivity: "ignore",
|
|
103
|
+
plugins,
|
|
93
104
|
});
|
|
94
105
|
} catch (error) {
|
|
95
106
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -100,14 +100,17 @@ When a Google Drive or Google Slides request needs authentication, tell the user
|
|
|
100
100
|
search: async (query: string) => {
|
|
101
101
|
const db = getDb();
|
|
102
102
|
const access = accessFilter(decks, deckShares);
|
|
103
|
+
// Project only id/title — decks.data is the full deck JSON (every
|
|
104
|
+
// slide) and must not be pulled into this per-keystroke search.
|
|
105
|
+
const mentionColumns = { id: decks.id, title: decks.title };
|
|
103
106
|
const rows = query
|
|
104
107
|
? await db
|
|
105
|
-
.select()
|
|
108
|
+
.select(mentionColumns)
|
|
106
109
|
.from(decks)
|
|
107
110
|
.where(and(access, like(decks.title, `%${query}%`)))
|
|
108
111
|
.limit(15)
|
|
109
112
|
: await db
|
|
110
|
-
.select()
|
|
113
|
+
.select(mentionColumns)
|
|
111
114
|
.from(decks)
|
|
112
115
|
.where(access)
|
|
113
116
|
.orderBy(desc(decks.updatedAt))
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
"extends": "@agent-native/core/tsconfig.base.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"ignoreDeprecations": "6.0",
|
|
5
|
+
// The shared base targets ES2020, but `new Error(message, { cause })`
|
|
6
|
+
// needs ErrorOptions from lib.es2022.error.d.ts (matches packages/core's
|
|
7
|
+
// own tsconfig.json, which already targets ES2022 for the same reason).
|
|
8
|
+
"target": "ES2022",
|
|
9
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
10
|
"rootDirs": [".", "./.react-router/types"],
|
|
6
11
|
"paths": {
|
|
7
12
|
"*": ["./*"],
|
|
@@ -16,7 +16,12 @@ export default mergeConfig(
|
|
|
16
16
|
},
|
|
17
17
|
test: {
|
|
18
18
|
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
19
|
-
exclude: [
|
|
19
|
+
exclude: [
|
|
20
|
+
"**/node_modules/**",
|
|
21
|
+
"**/.git/**",
|
|
22
|
+
"**/dist/**",
|
|
23
|
+
"**/.react-router/**",
|
|
24
|
+
],
|
|
20
25
|
},
|
|
21
26
|
}),
|
|
22
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
|
|
|
@@ -15,7 +15,10 @@ export function meta() {
|
|
|
15
15
|
|
|
16
16
|
export default function SettingsRoute() {
|
|
17
17
|
const t = useT();
|
|
18
|
-
|
|
18
|
+
// Tasks embeds an ExtensionSlot in TaskFieldsSidebar and wires /extensions
|
|
19
|
+
// into agent navigation, so the settings management tab must exist too —
|
|
20
|
+
// otherwise the /settings/extensions destination silently falls back to General.
|
|
21
|
+
const agentSettingsTabs = useAgentSettingsTabs({ extensionTools: true });
|
|
19
22
|
useSetPageTitle(t("header.pageSettings"));
|
|
20
23
|
|
|
21
24
|
return (
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type RouteConfig } from "@react-router/dev/routes";
|
|
2
2
|
import { flatRoutes } from "@react-router/fs-routes";
|
|
3
3
|
|
|
4
|
-
export default flatRoutes(
|
|
4
|
+
export default flatRoutes({
|
|
5
|
+
ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
6
|
+
}) satisfies RouteConfig;
|