@agent-native/core 0.141.7 → 0.144.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 +9 -0
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/AGENTS.md +35 -38
- package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
- package/corpus/templates/analytics/actions/navigate.ts +4 -5
- package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +44 -11
- package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
- package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
- package/corpus/templates/analytics/app/i18n-data.ts +680 -0
- package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
- package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
- package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
- package/corpus/templates/analytics/netlify.toml +7 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
- package/corpus/templates/analytics/server/db/index.ts +27 -0
- package/corpus/templates/analytics/server/db/schema.ts +10 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +133 -44
- package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
- package/corpus/templates/analytics/server/plugins/db.ts +52 -18
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +28 -2
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
- package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
- package/corpus/templates/brain/app/routes/sources.tsx +15 -7
- package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
- package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/AGENTS.md +11 -32
- package/corpus/templates/calendar/actions/update-event.ts +107 -1
- package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
- package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
- package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
- package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
- package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +48 -20
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
- package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
- package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
- package/corpus/templates/clips/server/plugins/db.ts +214 -26
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
- package/corpus/templates/crm/server/plugins/db.ts +11 -8
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/design/actions/import-from-url.ts +1 -1
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
- package/corpus/templates/design/app/pages/Index.tsx +6 -2
- package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
- package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +37 -1
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/slides/AGENTS.md +7 -9
- package/corpus/templates/slides/_gitignore +1 -0
- package/corpus/templates/slides/actions/export-pptx.ts +402 -36
- package/corpus/templates/slides/actions/import-file.ts +46 -85
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
- package/corpus/templates/slides/actions/import-pptx.ts +85 -60
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +173 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
- package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +4 -0
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
- package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
- package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
- package/corpus/templates/slides/app/pages/Index.tsx +91 -1
- package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +236 -13
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
- package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
- package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
- package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -3
- package/corpus/templates/slides/server/lib/emails.ts +7 -2
- package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
- package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -3
- package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
- package/corpus/templates/slides/shared/upload-types.ts +3 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/agent/production-agent.d.ts +17 -0
- package/dist/agent/production-agent.js +72 -1
- package/dist/cli/agent-plugin.d.ts +112 -0
- package/dist/cli/agent-plugin.js +1081 -0
- package/dist/cli/app-skill.js +39 -1
- package/dist/cli/code-agent-executor.d.ts +3 -0
- package/dist/cli/code-agent-executor.js +51 -13
- package/dist/cli/index.js +13 -0
- package/dist/cli/templates-meta.js +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.js +9 -2
- package/dist/client/AssistantChat.d.ts +8 -0
- package/dist/client/AssistantChat.js +23 -8
- package/dist/client/NewWorkspaceAppFlow.js +1 -0
- package/dist/client/agent-chat-adapter.js +123 -4
- package/dist/client/assistant-ui-recovery.d.ts +2 -1
- package/dist/client/assistant-ui-recovery.js +7 -3
- package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
- package/dist/client/org/TeamPage.js +1 -1
- package/dist/client/require-session.js +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +27 -10
- package/dist/client/resources/McpIntegrationDialog.js +77 -45
- package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
- package/dist/client/resources/mcp-integration-catalog.js +255 -2
- package/dist/client/resources/mcp-integration-logos.js +18 -2
- package/dist/client/settings/AccountSettingsCard.js +2 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +9 -0
- package/dist/db/client.js +51 -16
- package/dist/db/create-get-db.js +2 -2
- package/dist/db/ddl-guard.d.ts +11 -10
- package/dist/db/ddl-guard.js +40 -12
- package/dist/deploy/build.d.ts +2 -0
- package/dist/deploy/build.js +97 -4
- package/dist/deploy/workspace-deploy.js +0 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/guards/no-env-credentials.js +9 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/pptx.d.ts +68 -0
- package/dist/ingestion/pptx.js +660 -213
- package/dist/integrations/plugin.js +9 -6
- package/dist/localization/default-messages.d.ts +54 -0
- package/dist/localization/default-messages.js +57 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp-client/oauth-routes.d.ts +2 -0
- package/dist/mcp-client/oauth-routes.js +73 -6
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/onboarding/app-profile.js +11 -0
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.js +15 -1
- package/dist/scripts/call-agent.js +34 -4
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +36 -1
- package/dist/server/agent-chat-plugin.js +29 -8
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +47 -11
- package/dist/server/better-auth-instance.js +5 -3
- package/dist/server/core-routes-plugin.d.ts +8 -1
- package/dist/server/core-routes-plugin.js +28 -3
- package/dist/server/credential-provider.d.ts +3 -3
- package/dist/server/credential-provider.js +90 -4
- package/dist/server/onboarding-html.d.ts +2 -0
- package/dist/server/onboarding-html.js +115 -29
- package/dist/server/self-dispatch.d.ts +5 -4
- package/dist/server/self-dispatch.js +25 -14
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.js +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/cache-control.d.ts +26 -2
- package/dist/shared/cache-control.js +43 -2
- package/dist/shared/password-policy.d.ts +3 -0
- package/dist/shared/password-policy.js +3 -0
- package/dist/sharing/actions/set-resource-visibility.js +16 -4
- package/dist/sharing/registry.d.ts +14 -0
- package/dist/styles/agent-native.css +6 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-root/AGENTS.md +7 -0
- package/dist/user-profile/actions/change-password.js +8 -3
- package/dist/user-profile/actions/set-password.js +5 -1
- package/dist/vite/action-types-plugin.js +59 -0
- package/docs/content/skills-guide.mdx +13 -0
- package/package.json +6 -2
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-root/AGENTS.md +7 -0
|
@@ -90,6 +90,23 @@ function terminalTaskError(value) {
|
|
|
90
90
|
: {}),
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* A delegated failure must be an error at the caller's tool boundary. Returning
|
|
95
|
+
* an `Error: ...` string makes the production agent treat the failed call as a
|
|
96
|
+
* successful tool result, so it can spend the rest of its turn retrying or
|
|
97
|
+
* changing arguments while the real failure remains invisible to the loop
|
|
98
|
+
* breaker.
|
|
99
|
+
*/
|
|
100
|
+
class A2AInvocationError extends Error {
|
|
101
|
+
taskId;
|
|
102
|
+
errorCode;
|
|
103
|
+
constructor(message, options = {}) {
|
|
104
|
+
super(message);
|
|
105
|
+
this.name = "A2AInvocationError";
|
|
106
|
+
this.taskId = options.taskId;
|
|
107
|
+
this.errorCode = options.errorCode;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
93
110
|
function buildMessageIdempotencyKey(originatingTurnId, target, exactMessage) {
|
|
94
111
|
if (!originatingTurnId)
|
|
95
112
|
return undefined;
|
|
@@ -698,6 +715,12 @@ export async function run(args, context, selfAppId) {
|
|
|
698
715
|
? { terminalCode: invocationTerminalCode }
|
|
699
716
|
: {}),
|
|
700
717
|
});
|
|
718
|
+
if (terminalStatus === "error") {
|
|
719
|
+
throw new A2AInvocationError(responseText || `Error: The ${agent.name} agent returned no result.`, {
|
|
720
|
+
taskId: invocationTaskId,
|
|
721
|
+
errorCode: invocationTerminalCode,
|
|
722
|
+
});
|
|
723
|
+
}
|
|
701
724
|
return (responseText || `Error: The ${agent.name} agent returned no result.`);
|
|
702
725
|
}
|
|
703
726
|
// No context — use the async + poll call so we don't get cut off at the
|
|
@@ -745,6 +768,8 @@ export async function run(args, context, selfAppId) {
|
|
|
745
768
|
return expanded;
|
|
746
769
|
}
|
|
747
770
|
catch (err) {
|
|
771
|
+
if (err instanceof A2AInvocationError)
|
|
772
|
+
throw err;
|
|
748
773
|
const msg = err?.message ?? String(err);
|
|
749
774
|
const credentialMessage = formatDownstreamLlmCredentialFailure(agent.name, err);
|
|
750
775
|
if (credentialMessage)
|
|
@@ -760,10 +785,13 @@ export async function run(args, context, selfAppId) {
|
|
|
760
785
|
invocationStatus = "error";
|
|
761
786
|
invocationTaskId = terminal.taskId;
|
|
762
787
|
invocationTerminalCode = terminal.errorCode ?? terminal.state;
|
|
763
|
-
|
|
788
|
+
throw new A2AInvocationError(`Error calling ${agent.name}: remote task ${terminal.state}` +
|
|
764
789
|
(terminal.errorCode ? ` (${terminal.errorCode})` : "") +
|
|
765
790
|
(terminal.taskId ? ` [taskId: ${terminal.taskId}]` : "") +
|
|
766
|
-
(terminal.responseText ? `: ${terminal.responseText}` : "")
|
|
791
|
+
(terminal.responseText ? `: ${terminal.responseText}` : ""), {
|
|
792
|
+
taskId: terminal.taskId,
|
|
793
|
+
errorCode: terminal.errorCode ?? terminal.state,
|
|
794
|
+
});
|
|
767
795
|
}
|
|
768
796
|
const timeoutTaskId = getA2ATaskTimeoutTaskId(err);
|
|
769
797
|
if (timeoutTaskId) {
|
|
@@ -777,11 +805,13 @@ export async function run(args, context, selfAppId) {
|
|
|
777
805
|
if (/timeout|did not complete|Inactivity|504/i.test(msg)) {
|
|
778
806
|
invocationStatus = "error";
|
|
779
807
|
invocationTerminalCode = "timeout_without_task";
|
|
780
|
-
|
|
808
|
+
throw new A2AInvocationError(`Error calling ${agent.name}: the remote request timed out before a task id could be recovered.`, { errorCode: "timeout_without_task" });
|
|
781
809
|
}
|
|
782
810
|
invocationStatus = "error";
|
|
783
811
|
invocationTerminalCode = "call_failed";
|
|
784
|
-
|
|
812
|
+
throw new A2AInvocationError(`Error calling ${agent.name}: ${msg}`, {
|
|
813
|
+
errorCode: "call_failed",
|
|
814
|
+
});
|
|
785
815
|
}
|
|
786
816
|
finally {
|
|
787
817
|
trackA2AInvocation({
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
|
|
|
34
34
|
/** POST /_agent-native/secrets/:key — write a secret. */
|
|
35
35
|
export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
36
36
|
error: string;
|
|
37
|
-
status?: undefined;
|
|
38
37
|
ok?: undefined;
|
|
38
|
+
status?: undefined;
|
|
39
39
|
} | {
|
|
40
|
+
error?: undefined;
|
|
40
41
|
ok: boolean;
|
|
41
42
|
status: string;
|
|
42
|
-
error?: undefined;
|
|
43
43
|
} | {
|
|
44
|
+
ok?: undefined;
|
|
44
45
|
error: string;
|
|
45
46
|
removed?: undefined;
|
|
46
|
-
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
|
+
error?: undefined;
|
|
48
49
|
ok: boolean;
|
|
49
50
|
removed: boolean;
|
|
50
|
-
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — validate an optional candidate value
|
|
54
54
|
* or the current stored value without changing anything.
|
|
55
55
|
*/
|
|
56
56
|
export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
57
|
+
ok?: undefined;
|
|
57
58
|
error: string;
|
|
58
59
|
note?: undefined;
|
|
59
|
-
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
|
+
error?: undefined;
|
|
61
62
|
ok: boolean;
|
|
62
63
|
note?: undefined;
|
|
63
|
-
error?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
ok: boolean;
|
|
66
67
|
note: string;
|
|
67
|
-
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
+
error?: undefined;
|
|
98
99
|
ok: boolean;
|
|
99
100
|
key: string;
|
|
100
|
-
error?: undefined;
|
|
101
101
|
} | {
|
|
102
|
+
error?: undefined;
|
|
102
103
|
ok: boolean;
|
|
103
104
|
removed: boolean;
|
|
104
|
-
error?: undefined;
|
|
105
105
|
}>>;
|
|
@@ -75,7 +75,7 @@ type A2AAgentLoopRunner = typeof runAgentLoopDirectWithSoftTimeout;
|
|
|
75
75
|
export declare const DEFAULT_DELEGATED_MAX_ITERATIONS = 80;
|
|
76
76
|
export declare const DEFAULT_DELEGATED_MAX_RUN_INPUT_TOKENS = 750000;
|
|
77
77
|
export declare const DEFAULT_DELEGATED_MAX_TOOL_RESULT_CHARS = 20000;
|
|
78
|
-
export declare const DELEGATED_AGENT_EXECUTION_CONTRACT = "\n<delegated-agent-contract>\nThis request was delegated by another app. You are the specialist owner of the work.\n- Interpret the caller's natural-language objective using your own instructions, skills, data dictionary, credentials, and tools. Choose providers, schemas, queries, and joins here; never ask the caller to invent SQL or source-specific implementation details for you.\n- Finish the objective autonomously in this delegated turn whenever a safe, reasonable default exists. Do not bounce the work back with UI-navigation requests, implementation questions, or intermediate status. Ask for input only when authorization, missing credentials, or a consequential user choice truly blocks progress.\n- When evidence is incomplete, return the best grounded partial answer with explicit coverage gaps instead of refusing or asking the caller to choose your source, filter, dashboard, or workflow.\n- Minimize round trips. Filter, join, aggregate, paginate, stage, and reduce large datasets inside your own tools rather than returning raw records or transcripts.\n- Return a concise caller-ready result with the answer, source and coverage details, relevant counts or IDs, caveats/partial gaps, and exact artifact URLs. Do not return tool transcripts or large raw payloads.\n</delegated-agent-contract>";
|
|
78
|
+
export declare const DELEGATED_AGENT_EXECUTION_CONTRACT = "\n<delegated-agent-contract>\nThis request was delegated by another app. You are the specialist owner of the work.\n- Interpret the caller's natural-language objective using your own instructions, skills, data dictionary, credentials, and tools. Choose providers, schemas, queries, and joins here; never ask the caller to invent SQL or source-specific implementation details for you.\n- Finish the objective autonomously in this delegated turn whenever a safe, reasonable default exists. Do not bounce the work back with UI-navigation requests, implementation questions, or intermediate status. Ask for input only when authorization, missing credentials, or a consequential user choice truly blocks progress.\n- When evidence is incomplete, return the best grounded partial answer with explicit coverage gaps instead of refusing or asking the caller to choose your source, filter, dashboard, or workflow.\n- Reach for your own registered actions first and by name. They are the same actions this app's interactive chat uses and are almost always the shortest path to the answer. Do not rediscover your own capabilities by exploring, and never use a shell, filesystem, or code-execution tool to do what one of your actions already does \u2014 that is the difference between answering in seconds and answering in minutes.\n- Minimize round trips. Filter, join, aggregate, paginate, stage, and reduce large datasets inside your own tools rather than returning raw records or transcripts.\n- Return a concise caller-ready result with the answer, source and coverage details, relevant counts or IDs, caveats/partial gaps, and exact artifact URLs. Do not return tool transcripts or large raw payloads.\n</delegated-agent-contract>";
|
|
79
79
|
export interface DelegatedAgentLoopTelemetry {
|
|
80
80
|
runId: string;
|
|
81
81
|
threadId: string | null;
|
|
@@ -4,6 +4,7 @@ import { collectFinalResponseTextFromAgentEvents } from "../../a2a/response-text
|
|
|
4
4
|
import { resolveMainChatMaxOutputTokens } from "../../agent/engine/output-tokens.js";
|
|
5
5
|
import { filterInitialEngineTools, resolveAgentRequestReasoningEffort, } from "../../agent/production-agent.js";
|
|
6
6
|
import { runAgentLoopDirectWithSoftTimeout } from "../../agent/run-loop-with-resume.js";
|
|
7
|
+
import { resolveRunSoftTimeoutMs } from "../../agent/run-manager.js";
|
|
7
8
|
import { isAuthenticatedReadAction, isAutoReadExcludedActionName, } from "../../mcp/build-server.js";
|
|
8
9
|
import { withConfiguredAppBasePath } from "../app-base-path.js";
|
|
9
10
|
// ---------------------------------------------------------------------------
|
|
@@ -255,12 +256,44 @@ function formatA2ATerminalError(event) {
|
|
|
255
256
|
export const DEFAULT_DELEGATED_MAX_ITERATIONS = 80;
|
|
256
257
|
export const DEFAULT_DELEGATED_MAX_RUN_INPUT_TOKENS = 750_000;
|
|
257
258
|
export const DEFAULT_DELEGATED_MAX_TOOL_RESULT_CHARS = 20_000;
|
|
259
|
+
/**
|
|
260
|
+
* A sentence naming the wall clock this delegated step actually gets, or "" when
|
|
261
|
+
* there is no enforced budget (local dev returns 0 from the resolver).
|
|
262
|
+
*
|
|
263
|
+
* "I ran out of time before finishing this step" was 39% of all failed inbound
|
|
264
|
+
* A2A tasks in one measured week, clustered at 35-46s against a 40s foreground
|
|
265
|
+
* serverless wall. The callee was never told that wall exists: it is handed a
|
|
266
|
+
* nominal 80 iterations and 750k tokens and plans accordingly, while production
|
|
267
|
+
* iterations measure ~34s each — so a foreground chunk affords roughly one.
|
|
268
|
+
*
|
|
269
|
+
* The clock is already enforced correctly; a second, cruder cap on iterations
|
|
270
|
+
* would only waste budget. What was missing is that the agent could not see it.
|
|
271
|
+
* An agent that knows it has forty seconds scopes to forty seconds.
|
|
272
|
+
*/
|
|
273
|
+
function delegatedTimeBudgetNote(runSoftTimeoutMs, backgroundFunction) {
|
|
274
|
+
const softTimeoutMs = resolveRunSoftTimeoutMs(runSoftTimeoutMs, {
|
|
275
|
+
useHostedDefault: true,
|
|
276
|
+
backgroundFunction,
|
|
277
|
+
});
|
|
278
|
+
if (!Number.isFinite(softTimeoutMs) || softTimeoutMs <= 0)
|
|
279
|
+
return "";
|
|
280
|
+
const seconds = Math.max(1, Math.round(softTimeoutMs / 1000));
|
|
281
|
+
return (`\n<delegated-time-budget>\n` +
|
|
282
|
+
`This step is cut off after about ${seconds} seconds. Scope the work to fit it. ` +
|
|
283
|
+
`Prefer one decisive action over exploring, and note that a single tool call plus a model ` +
|
|
284
|
+
`response commonly takes tens of seconds — so plan on completing very few steps, not many. ` +
|
|
285
|
+
`If the objective cannot be finished in that window, return the best grounded partial answer ` +
|
|
286
|
+
`and say what is missing. Do not begin work you cannot finish, and do not treat this budget ` +
|
|
287
|
+
`as a reason to skip verifying what you do report.\n` +
|
|
288
|
+
`</delegated-time-budget>`);
|
|
289
|
+
}
|
|
258
290
|
export const DELEGATED_AGENT_EXECUTION_CONTRACT = `
|
|
259
291
|
<delegated-agent-contract>
|
|
260
292
|
This request was delegated by another app. You are the specialist owner of the work.
|
|
261
293
|
- Interpret the caller's natural-language objective using your own instructions, skills, data dictionary, credentials, and tools. Choose providers, schemas, queries, and joins here; never ask the caller to invent SQL or source-specific implementation details for you.
|
|
262
294
|
- Finish the objective autonomously in this delegated turn whenever a safe, reasonable default exists. Do not bounce the work back with UI-navigation requests, implementation questions, or intermediate status. Ask for input only when authorization, missing credentials, or a consequential user choice truly blocks progress.
|
|
263
295
|
- When evidence is incomplete, return the best grounded partial answer with explicit coverage gaps instead of refusing or asking the caller to choose your source, filter, dashboard, or workflow.
|
|
296
|
+
- Reach for your own registered actions first and by name. They are the same actions this app's interactive chat uses and are almost always the shortest path to the answer. Do not rediscover your own capabilities by exploring, and never use a shell, filesystem, or code-execution tool to do what one of your actions already does — that is the difference between answering in seconds and answering in minutes.
|
|
264
297
|
- Minimize round trips. Filter, join, aggregate, paginate, stage, and reduce large datasets inside your own tools rather than returning raw records or transcripts.
|
|
265
298
|
- Return a concise caller-ready result with the answer, source and coverage details, relevant counts or IDs, caveats/partial gaps, and exact artifact URLs. Do not return tool transcripts or large raw payloads.
|
|
266
299
|
</delegated-agent-contract>`;
|
|
@@ -271,7 +304,9 @@ async function runDelegatedAgentLoop(runOptions, pluginOptions, timeoutOptions,
|
|
|
271
304
|
const delegatedHardToolResultCap = policy?.maxToolResultChars ?? DEFAULT_DELEGATED_MAX_TOOL_RESULT_CHARS;
|
|
272
305
|
const resolvedRunOptions = {
|
|
273
306
|
...runOptions,
|
|
274
|
-
systemPrompt: runOptions.systemPrompt +
|
|
307
|
+
systemPrompt: runOptions.systemPrompt +
|
|
308
|
+
DELEGATED_AGENT_EXECUTION_CONTRACT +
|
|
309
|
+
delegatedTimeBudgetNote(pluginOptions.runSoftTimeoutMs, timeoutOptions?.backgroundFunction === true),
|
|
275
310
|
// Delegated runs resolve their own model and do not pass through the
|
|
276
311
|
// interactive request handler's output-token setup. Use the same
|
|
277
312
|
// model-aware headroom here so reasoning models (notably GPT-5.x) do
|
|
@@ -1237,17 +1237,38 @@ export function createAgentChatPlugin(options) {
|
|
|
1237
1237
|
? ""
|
|
1238
1238
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
1239
1239
|
const extra = await resolveExtraContext(context.event, owner);
|
|
1240
|
+
const a2aStoredModel = await getStoredModelForEngine(a2aEngine, {
|
|
1241
|
+
appId: options?.appId,
|
|
1242
|
+
});
|
|
1243
|
+
// Preference only, and last before the default: an app that pinned
|
|
1244
|
+
// a model keeps it. Read separately from the correlation sanitizer
|
|
1245
|
+
// below so it stays out of every identity/access path.
|
|
1246
|
+
const a2aCallerModelHint = sanitizeA2ACorrelationMetadata(context.metadata).callerModel;
|
|
1240
1247
|
const model = resolveDelegatedRunModel(a2aEngine, {
|
|
1241
1248
|
explicitModel: options?.model,
|
|
1242
|
-
storedModel:
|
|
1243
|
-
|
|
1244
|
-
}),
|
|
1245
|
-
// Preference only, and last before the default: an app that pinned
|
|
1246
|
-
// a model keeps it. Read separately from the correlation sanitizer
|
|
1247
|
-
// below so it stays out of every identity/access path.
|
|
1248
|
-
callerModelHint: sanitizeA2ACorrelationMetadata(context.metadata)
|
|
1249
|
-
.callerModel,
|
|
1249
|
+
storedModel: a2aStoredModel,
|
|
1250
|
+
callerModelHint: a2aCallerModelHint,
|
|
1250
1251
|
});
|
|
1252
|
+
// The interactive path logs its model AND where the model came from;
|
|
1253
|
+
// this path logged neither, so "the same app answers me in 27s but
|
|
1254
|
+
// takes 5 minutes when another app asks" had no way to be checked.
|
|
1255
|
+
// The usual answer is right here: the chat model picker is a
|
|
1256
|
+
// browser-local preference, so it reaches an interactive turn as the
|
|
1257
|
+
// highest-precedence request model and never reaches this path at
|
|
1258
|
+
// all — a delegated turn falls through to the app's stored model or
|
|
1259
|
+
// the engine default, which can be a different, weaker model.
|
|
1260
|
+
console.log(`[a2a] resolved engine=${a2aEngine.name} model=${model} ` +
|
|
1261
|
+
// A hint the callee's engine does not offer is dropped, so the
|
|
1262
|
+
// label is derived from what actually won — reporting
|
|
1263
|
+
// "caller-hint" for a rejected hint would send the next person
|
|
1264
|
+
// debugging this in exactly the wrong direction.
|
|
1265
|
+
`modelSource=${options?.model
|
|
1266
|
+
? "configured"
|
|
1267
|
+
: a2aStoredModel
|
|
1268
|
+
? "stored"
|
|
1269
|
+
: a2aCallerModelHint && model === a2aCallerModelHint
|
|
1270
|
+
? "caller-hint"
|
|
1271
|
+
: "default"} callerHint=${a2aCallerModelHint ?? "(none)"} appId=${options?.appId ?? "(none)"}`);
|
|
1251
1272
|
if (a2aRunContext) {
|
|
1252
1273
|
a2aRunContext.engine = a2aEngine;
|
|
1253
1274
|
a2aRunContext.model = model;
|
|
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
+
error?: undefined;
|
|
30
31
|
ok: boolean;
|
|
31
32
|
key: string;
|
|
32
33
|
baseUrlKey?: string;
|
|
33
34
|
scope: AgentEngineApiKeyScope;
|
|
34
|
-
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
package/dist/server/auth.js
CHANGED
|
@@ -48,11 +48,13 @@ import { readBody } from "../server/h3-helpers.js";
|
|
|
48
48
|
import { putSetting } from "../settings/store.js";
|
|
49
49
|
import { resolveSsrCacheHeaders } from "../shared/cache-control.js";
|
|
50
50
|
import { extractOAuthStateAppId } from "../shared/oauth-state.js";
|
|
51
|
-
import {
|
|
51
|
+
import { PASSWORD_MIN_LENGTH, PASSWORD_MIN_LENGTH_MESSAGE, } from "../shared/password-policy.js";
|
|
52
|
+
import { SIGN_IN_CONTINUATION_PARAM, SIGN_IN_ENTRY_PATH, SIGN_IN_LEGACY_ENTRY_PATH, SIGN_IN_LEGACY_RETURN_PARAM, decodeContinuation, normalizeAppPath, signInJourney, } from "../shared/sign-in-journey.js";
|
|
52
53
|
import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
|
|
53
54
|
import { normalizeWorkspaceAppAudience, workspaceAppAudienceFromEnv, workspaceAppRouteAccessFromEnv, } from "../shared/workspace-app-audience.js";
|
|
54
55
|
import { isValidWorkspaceAppIdFormat } from "../shared/workspace-app-id.js";
|
|
55
56
|
import { injectAnalyticsIntoHtml } from "./analytics.js";
|
|
57
|
+
import { getConfiguredAppBasePath } from "./app-base-path.js";
|
|
56
58
|
import { readAnalyticsAnonymousId, signupAttributionFromCookieHeader, } from "./attribution.js";
|
|
57
59
|
import { getAuthLoginMode } from "./auth-login-mode.js";
|
|
58
60
|
import { ensureGoogleAuthIdentity, getBetterAuth, getBetterAuthSync, } from "./better-auth-instance.js";
|
|
@@ -792,6 +794,35 @@ function getRequestHost(event) {
|
|
|
792
794
|
getHeader(event, "host") ??
|
|
793
795
|
undefined);
|
|
794
796
|
}
|
|
797
|
+
function parseRequestUrl(rawUrl) {
|
|
798
|
+
if (!rawUrl)
|
|
799
|
+
return null;
|
|
800
|
+
try {
|
|
801
|
+
return new URL(rawUrl, "http://an.invalid");
|
|
802
|
+
}
|
|
803
|
+
catch {
|
|
804
|
+
// coercion-ok: an invalid request URL has no query context to classify.
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function hasInitialPromptQuery(rawUrl) {
|
|
809
|
+
return !!parseRequestUrl(rawUrl)?.searchParams.get("initialPrompt")?.trim();
|
|
810
|
+
}
|
|
811
|
+
function requestHasInitialPrompt(event) {
|
|
812
|
+
const rawUrl = event.node?.req?.url ?? event.path ?? "/";
|
|
813
|
+
if (hasInitialPromptQuery(rawUrl))
|
|
814
|
+
return true;
|
|
815
|
+
const requestUrl = parseRequestUrl(rawUrl);
|
|
816
|
+
if (!requestUrl)
|
|
817
|
+
return false;
|
|
818
|
+
const continuation = requestUrl.searchParams.get(SIGN_IN_CONTINUATION_PARAM);
|
|
819
|
+
if (continuation &&
|
|
820
|
+
hasInitialPromptQuery(decodeContinuation(continuation, getConfiguredAppBasePath()) ?? undefined)) {
|
|
821
|
+
return true;
|
|
822
|
+
}
|
|
823
|
+
const legacyReturn = requestUrl.searchParams.get(SIGN_IN_LEGACY_RETURN_PARAM);
|
|
824
|
+
return legacyReturn ? hasInitialPromptQuery(legacyReturn) : false;
|
|
825
|
+
}
|
|
795
826
|
function getOnboardingHtmlOptions(options, event, rawPath, authMode) {
|
|
796
827
|
return {
|
|
797
828
|
authMode,
|
|
@@ -803,6 +834,7 @@ function getOnboardingHtmlOptions(options, event, rawPath, authMode) {
|
|
|
803
834
|
requestHost: event ? getRequestHost(event) : undefined,
|
|
804
835
|
requestPath: rawPath,
|
|
805
836
|
requestOrigin: event ? getOrigin(event) : undefined,
|
|
837
|
+
initialPrompt: event ? requestHasInitialPrompt(event) : false,
|
|
806
838
|
};
|
|
807
839
|
}
|
|
808
840
|
function getAuthOnboardingHtml(options, event, rawPath, authMode) {
|
|
@@ -1453,12 +1485,12 @@ function createAuthGuardFn() {
|
|
|
1453
1485
|
return;
|
|
1454
1486
|
if (p === "/_agent-native/speculation-rules.json")
|
|
1455
1487
|
return;
|
|
1456
|
-
// Liveness
|
|
1457
|
-
// can reach
|
|
1458
|
-
//
|
|
1459
|
-
// the gate below 401s anonymous /_agent-native/*
|
|
1460
|
-
//
|
|
1461
|
-
if (p === "/_agent-native/health")
|
|
1488
|
+
// Liveness probes: always public so uptime monitors and the keep-warm cron
|
|
1489
|
+
// can reach them without a session. Ping exposes only a static message;
|
|
1490
|
+
// health exposes only aggregate readiness and a trivial `SELECT 1`.
|
|
1491
|
+
// Without this bypass the gate below 401s anonymous /_agent-native/*
|
|
1492
|
+
// requests before either probe can run.
|
|
1493
|
+
if (p === "/_agent-native/ping" || p === "/_agent-native/health")
|
|
1462
1494
|
return;
|
|
1463
1495
|
if (getMethod(event) === "GET" && p.startsWith("/_agent-native/avatar/")) {
|
|
1464
1496
|
return;
|
|
@@ -2805,9 +2837,11 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2805
2837
|
setResponseStatus(event, 400);
|
|
2806
2838
|
return { error: VALID_AUTH_EMAIL_MESSAGE };
|
|
2807
2839
|
}
|
|
2808
|
-
if (!password ||
|
|
2840
|
+
if (!password ||
|
|
2841
|
+
typeof password !== "string" ||
|
|
2842
|
+
password.length < PASSWORD_MIN_LENGTH) {
|
|
2809
2843
|
setResponseStatus(event, 400);
|
|
2810
|
-
return { error:
|
|
2844
|
+
return { error: PASSWORD_MIN_LENGTH_MESSAGE };
|
|
2811
2845
|
}
|
|
2812
2846
|
if (await isGoogleSignInRequiredForEmail(email)) {
|
|
2813
2847
|
setResponseStatus(event, 403);
|
|
@@ -3049,9 +3083,11 @@ function mountAuthFallbackRoutes(app) {
|
|
|
3049
3083
|
setResponseStatus(event, 400);
|
|
3050
3084
|
return { error: VALID_AUTH_EMAIL_MESSAGE };
|
|
3051
3085
|
}
|
|
3052
|
-
if (!password ||
|
|
3086
|
+
if (!password ||
|
|
3087
|
+
typeof password !== "string" ||
|
|
3088
|
+
password.length < PASSWORD_MIN_LENGTH) {
|
|
3053
3089
|
setResponseStatus(event, 400);
|
|
3054
|
-
return { error:
|
|
3090
|
+
return { error: PASSWORD_MIN_LENGTH_MESSAGE };
|
|
3055
3091
|
}
|
|
3056
3092
|
if (await isGoogleSignInRequiredForEmail(email)) {
|
|
3057
3093
|
setResponseStatus(event, 403);
|
|
@@ -16,13 +16,14 @@ import { pgTable, text as pgText, timestamp as pgTimestamp, boolean as pgBoolean
|
|
|
16
16
|
import { sqliteTable, text as sqliteText, integer as sqliteInteger, } from "drizzle-orm/sqlite-core";
|
|
17
17
|
import { TEMPLATES } from "../cli/templates-meta.js";
|
|
18
18
|
import { getDbExec, isPostgres } from "../db/client.js";
|
|
19
|
-
import { getDialect, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions,
|
|
19
|
+
import { getDialect, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, attachNeonPoolErrorLogger, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
|
|
20
20
|
import { ensureTableExists } from "../db/ddl-guard.js";
|
|
21
21
|
import { CORE_RESET_PASSWORD_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, } from "../email-catalog/system-emails.js";
|
|
22
22
|
import { saveOAuthTokens } from "../oauth-tokens/store.js";
|
|
23
23
|
import { acceptPendingInvitationsForEmail } from "../org/accept-pending.js";
|
|
24
24
|
import { getAuthEmailForUserId, getRequiredAuthProviderForEmail, } from "../org/auth-policy.js";
|
|
25
25
|
import { autoJoinDomainMatchingOrgs } from "../org/auto-join-domain.js";
|
|
26
|
+
import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-policy.js";
|
|
26
27
|
import { flushTracking, identify, track } from "../tracking/index.js";
|
|
27
28
|
import { getAppProductionUrl } from "./app-url.js";
|
|
28
29
|
import { readAnalyticsAnonymousId, signupAttributionFromCookieHeader, } from "./attribution.js";
|
|
@@ -903,7 +904,8 @@ async function createBetterAuthInstance(config) {
|
|
|
903
904
|
emailAndPassword: {
|
|
904
905
|
enabled: true,
|
|
905
906
|
disableSignUp,
|
|
906
|
-
minPasswordLength:
|
|
907
|
+
minPasswordLength: PASSWORD_MIN_LENGTH,
|
|
908
|
+
maxPasswordLength: PASSWORD_MAX_LENGTH,
|
|
907
909
|
// Hosted deployments always require a working email provider before
|
|
908
910
|
// password signup can create a session. Local dev/test retain the fast
|
|
909
911
|
// path; hosted deployments without a provider disable password signup.
|
|
@@ -1195,7 +1197,7 @@ async function buildDatabaseConfig(dialect) {
|
|
|
1195
1197
|
// un-capped pool here is a primary contributor to "Max client
|
|
1196
1198
|
// connections reached" across concurrent serverless instances.
|
|
1197
1199
|
resetAuthOnPoolClose("neon", url);
|
|
1198
|
-
_neonAuthPool = sharedDbPool("neon", url, () => new Pool({ connectionString: url,
|
|
1200
|
+
_neonAuthPool = sharedDbPool("neon", url, () => new Pool({ connectionString: url, ...neonPoolOptions() }));
|
|
1199
1201
|
attachNeonPoolErrorLogger(_neonAuthPool, "db/neon-auth");
|
|
1200
1202
|
const { drizzle } = await import("drizzle-orm/neon-serverless");
|
|
1201
1203
|
const db = drizzle(buildResilientNeonPool(_neonAuthPool), {
|
|
@@ -62,7 +62,6 @@ export declare function resolveAgentEngineStatus<E extends AgentEngineStatusEntr
|
|
|
62
62
|
export declare function shareAgentEngineStatusLookup(identityKey: string, compute: () => Promise<AgentEngineStatusResult>): Promise<AgentEngineStatusResult>;
|
|
63
63
|
export declare function agentEngineStatusIdentityKey(userEmail: string | undefined, orgId: string | undefined): string;
|
|
64
64
|
export declare function getFrameworkEnvKeys(): EnvKeyConfig[];
|
|
65
|
-
/** Result of the `/_agent-native/health` liveness + DB-warmup probe. */
|
|
66
65
|
export interface DbHealthProbeResult {
|
|
67
66
|
/** The serverless function is live and served the request. */
|
|
68
67
|
ok: true;
|
|
@@ -70,6 +69,14 @@ export interface DbHealthProbeResult {
|
|
|
70
69
|
ready: boolean;
|
|
71
70
|
/** A trivial `SELECT 1` reached the database (false = no DB or unreachable). */
|
|
72
71
|
db: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* The probe hit its deadline instead of answering. Reported SEPARATELY from
|
|
74
|
+
* `db: false`, because "the database said no" and "the database never
|
|
75
|
+
* replied" are different failures and folding them together is exactly the
|
|
76
|
+
* coercion this repo bans — a monitor cannot tell an app with no database
|
|
77
|
+
* from one whose database is hanging.
|
|
78
|
+
*/
|
|
79
|
+
dbTimedOut?: boolean;
|
|
73
80
|
/** Round-trip time of the probe in milliseconds. */
|
|
74
81
|
ms: number;
|
|
75
82
|
/** Redacted database routing details useful for deploy/runtime checks. */
|
|
@@ -242,6 +242,13 @@ export function getFrameworkEnvKeys() {
|
|
|
242
242
|
})),
|
|
243
243
|
];
|
|
244
244
|
}
|
|
245
|
+
/** Result of the `/_agent-native/health` liveness + DB-warmup probe. */
|
|
246
|
+
/**
|
|
247
|
+
* Deliberately generous: a genuinely cold Neon compute can take seconds to
|
|
248
|
+
* accept its first connection, and reporting a slow-but-working database as
|
|
249
|
+
* timed out would flap. This is a ceiling on hanging, not a latency budget.
|
|
250
|
+
*/
|
|
251
|
+
const DB_HEALTH_PROBE_DEADLINE_MS = 5_000;
|
|
245
252
|
/**
|
|
246
253
|
* Run a trivial `SELECT 1` to confirm the database is reachable and, as a side
|
|
247
254
|
* effect, keep a scale-to-zero serverless database (e.g. Neon) warm. Touching
|
|
@@ -257,12 +264,29 @@ export async function runDbHealthProbe(exec = getDbExec, options = {}) {
|
|
|
257
264
|
let db = false;
|
|
258
265
|
let schema;
|
|
259
266
|
const dbExec = exec();
|
|
267
|
+
let dbTimedOut = false;
|
|
260
268
|
try {
|
|
261
|
-
await
|
|
262
|
-
|
|
269
|
+
// An UNBOUNDED await here is what took the docs site down: the health route
|
|
270
|
+
// hung for 20-40s until the CDN returned 502, the keep-warm cron failed
|
|
271
|
+
// every minute, and the function stayed permanently cold — a ~10x penalty
|
|
272
|
+
// on every cache miss. This function's own contract says "Always
|
|
273
|
+
// resolves"; without a deadline it did not.
|
|
274
|
+
let timer;
|
|
275
|
+
const deadline = new Promise((_, reject) => {
|
|
276
|
+
timer = setTimeout(() => reject(new Error("db probe deadline")), DB_HEALTH_PROBE_DEADLINE_MS);
|
|
277
|
+
});
|
|
278
|
+
try {
|
|
279
|
+
await Promise.race([dbExec.execute("SELECT 1"), deadline]);
|
|
280
|
+
db = true;
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
if (timer)
|
|
284
|
+
clearTimeout(timer);
|
|
285
|
+
}
|
|
263
286
|
}
|
|
264
|
-
catch {
|
|
287
|
+
catch (err) {
|
|
265
288
|
// Live even when the DB is unreachable or the app has no database.
|
|
289
|
+
dbTimedOut = err?.message === "db probe deadline";
|
|
266
290
|
}
|
|
267
291
|
if (db && options.schema) {
|
|
268
292
|
schema = await runDatabaseSchemaHealthCheck({
|
|
@@ -274,6 +298,7 @@ export async function runDbHealthProbe(exec = getDbExec, options = {}) {
|
|
|
274
298
|
ok: true,
|
|
275
299
|
ready: db && (!schema || schema.ok),
|
|
276
300
|
db,
|
|
301
|
+
...(dbTimedOut ? { dbTimedOut: true } : {}),
|
|
277
302
|
ms: Date.now() - startedAt,
|
|
278
303
|
database: {
|
|
279
304
|
configured: database.configured,
|
|
@@ -308,9 +308,9 @@ export declare function deleteBuilderCredentials(email: string, options?: {
|
|
|
308
308
|
export declare function prefetchSecrets(keys: readonly string[]): Promise<void>;
|
|
309
309
|
/**
|
|
310
310
|
* Resolve a request-scoped secret. Reads from `app_secrets` first (current
|
|
311
|
-
* user override, active org, workspace row for that org,
|
|
312
|
-
*
|
|
313
|
-
* policy allows it.
|
|
311
|
+
* user override, active org, workspace row for that org, the solo workspace
|
|
312
|
+
* row, then the explicitly designated workspace vault organization); falls
|
|
313
|
+
* back to `process.env` only when the deploy fallback policy allows it.
|
|
314
314
|
*
|
|
315
315
|
* Resolving several keys in one request? Call `prefetchSecrets` first.
|
|
316
316
|
*/
|
|
@@ -19,8 +19,56 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { createHash } from "node:crypto";
|
|
21
21
|
import { CREDENTIAL_STORE_UNAVAILABLE_ERROR_CODE } from "../agent/engine/credential-errors.js";
|
|
22
|
-
import { isLocalDatabase, isTransientDatabaseError } from "../db/client.js";
|
|
22
|
+
import { getDbExec, isLocalDatabase, isTransientDatabaseError, } from "../db/client.js";
|
|
23
|
+
import { getOrgSetting } from "../settings/org-settings.js";
|
|
23
24
|
import { getRequestUserEmail, getRequestOrgId } from "./request-context.js";
|
|
25
|
+
const DISPATCH_VAULT_ACCESS_SETTINGS_KEY = "dispatch-vault-access-settings";
|
|
26
|
+
/**
|
|
27
|
+
* The designated vault fallback is an all-apps compatibility path. Manual
|
|
28
|
+
* mode must use the per-app sync path instead, or a known key name would be
|
|
29
|
+
* enough to read the whole vault from an ungranted workspace app.
|
|
30
|
+
*/
|
|
31
|
+
async function canReadDesignatedVaultFallback(vaultOrgId, credentialKey) {
|
|
32
|
+
const access = await getOrgSetting(vaultOrgId, DISPATCH_VAULT_ACCESS_SETTINGS_KEY);
|
|
33
|
+
if (access?.mode !== "manual")
|
|
34
|
+
return { status: "allowed" };
|
|
35
|
+
// Manual mode is still usable across a Dispatch vault org and a separate
|
|
36
|
+
// app org, but only for this app's explicit active grant. The app identity
|
|
37
|
+
// comes from deployment configuration, never from request input.
|
|
38
|
+
const appId = [
|
|
39
|
+
process.env.AGENT_NATIVE_WORKSPACE_APP_ID,
|
|
40
|
+
process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID,
|
|
41
|
+
process.env.AGENT_NATIVE_APP_ID,
|
|
42
|
+
process.env.APP_NAME,
|
|
43
|
+
]
|
|
44
|
+
.find((value) => value?.trim())
|
|
45
|
+
?.trim();
|
|
46
|
+
if (!appId) {
|
|
47
|
+
return { status: "denied", reason: "missing-app-id" };
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const result = await getDbExec().execute({
|
|
51
|
+
sql: `SELECT 1
|
|
52
|
+
FROM vault_grants AS grants
|
|
53
|
+
INNER JOIN vault_secrets AS secrets ON secrets.id = grants.secret_id
|
|
54
|
+
WHERE grants.org_id = ?
|
|
55
|
+
AND grants.app_id = ?
|
|
56
|
+
AND grants.status = 'active'
|
|
57
|
+
AND secrets.org_id = grants.org_id
|
|
58
|
+
AND secrets.credential_key = ?
|
|
59
|
+
LIMIT 1`,
|
|
60
|
+
args: [vaultOrgId, appId, credentialKey],
|
|
61
|
+
});
|
|
62
|
+
return result.rows.length > 0
|
|
63
|
+
? { status: "allowed" }
|
|
64
|
+
: { status: "denied", reason: "no-active-grant" };
|
|
65
|
+
}
|
|
66
|
+
catch (cause) {
|
|
67
|
+
// A missing/unreadable grant table must fail closed. The app can still
|
|
68
|
+
// resolve a locally scoped credential or retry after the store recovers.
|
|
69
|
+
return { status: "unavailable", cause };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
24
72
|
/**
|
|
25
73
|
* Decide which `app_secrets` scope a Builder/credential write should use.
|
|
26
74
|
*
|
|
@@ -998,9 +1046,9 @@ export async function prefetchSecrets(keys) {
|
|
|
998
1046
|
}
|
|
999
1047
|
/**
|
|
1000
1048
|
* Resolve a request-scoped secret. Reads from `app_secrets` first (current
|
|
1001
|
-
* user override, active org, workspace row for that org,
|
|
1002
|
-
*
|
|
1003
|
-
* policy allows it.
|
|
1049
|
+
* user override, active org, workspace row for that org, the solo workspace
|
|
1050
|
+
* row, then the explicitly designated workspace vault organization); falls
|
|
1051
|
+
* back to `process.env` only when the deploy fallback policy allows it.
|
|
1004
1052
|
*
|
|
1005
1053
|
* Resolving several keys in one request? Call `prefetchSecrets` first.
|
|
1006
1054
|
*/
|
|
@@ -1100,6 +1148,44 @@ export async function resolveSecretDetailed(key) {
|
|
|
1100
1148
|
}
|
|
1101
1149
|
return { value: soloWorkspaceSecret.value, lookupFailed: false };
|
|
1102
1150
|
}
|
|
1151
|
+
// Dispatch's workspace vault is stored under the organization that
|
|
1152
|
+
// performed the sync. AGENT_VAULT_ORG_ID is an explicit single-workspace
|
|
1153
|
+
// deployment assertion; without it, never guess which other tenant owns
|
|
1154
|
+
// a shared key. This fallback keeps workspace apps from requiring every
|
|
1155
|
+
// builder to copy a vault key into app-local settings.
|
|
1156
|
+
const vaultOrgId = process.env.AGENT_VAULT_ORG_ID?.trim();
|
|
1157
|
+
if (vaultOrgId && vaultOrgId !== orgId) {
|
|
1158
|
+
const designatedVaultAccess = await canReadDesignatedVaultFallback(vaultOrgId, key);
|
|
1159
|
+
if (designatedVaultAccess.status === "unavailable") {
|
|
1160
|
+
lookupFailed = true;
|
|
1161
|
+
cause = designatedVaultAccess.cause;
|
|
1162
|
+
}
|
|
1163
|
+
if (designatedVaultAccess.status === "allowed") {
|
|
1164
|
+
const [vaultOrgRead, vaultWorkspaceRead] = await Promise.allSettled([
|
|
1165
|
+
readAppSecret({ key, scope: "org", scopeId: vaultOrgId }),
|
|
1166
|
+
readAppSecret({ key, scope: "workspace", scopeId: vaultOrgId }),
|
|
1167
|
+
]);
|
|
1168
|
+
const unwrap = (settled) => {
|
|
1169
|
+
if (settled.status === "rejected")
|
|
1170
|
+
throw settled.reason;
|
|
1171
|
+
return settled.value;
|
|
1172
|
+
};
|
|
1173
|
+
const vaultOrgSecret = unwrap(vaultOrgRead);
|
|
1174
|
+
if (vaultOrgSecret?.value) {
|
|
1175
|
+
if (traceLookup) {
|
|
1176
|
+
console.log(`[resolve-secret] key=${key} email=${email} vaultOrgId=${vaultOrgId} scope=org-vault hit=true`);
|
|
1177
|
+
}
|
|
1178
|
+
return { value: vaultOrgSecret.value, lookupFailed: false };
|
|
1179
|
+
}
|
|
1180
|
+
const vaultWorkspaceSecret = unwrap(vaultWorkspaceRead);
|
|
1181
|
+
if (vaultWorkspaceSecret?.value) {
|
|
1182
|
+
if (traceLookup) {
|
|
1183
|
+
console.log(`[resolve-secret] key=${key} email=${email} vaultOrgId=${vaultOrgId} scope=workspace-vault hit=true`);
|
|
1184
|
+
}
|
|
1185
|
+
return { value: vaultWorkspaceSecret.value, lookupFailed: false };
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1103
1189
|
}
|
|
1104
1190
|
catch (err) {
|
|
1105
1191
|
if (traceLookup) {
|
|
@@ -25,6 +25,8 @@ export interface OnboardingHtmlOptions {
|
|
|
25
25
|
googleOnly?: boolean;
|
|
26
26
|
/** Authentication surface to render. Defaults to the existing password flow. */
|
|
27
27
|
authMode?: "magic-link" | "password";
|
|
28
|
+
/** Render the quiet, centered auth surface used when the app has an initial prompt. */
|
|
29
|
+
initialPrompt?: boolean;
|
|
28
30
|
/**
|
|
29
31
|
* Product marketing content shown alongside the sign-in form.
|
|
30
32
|
* When provided, the page uses a split layout: marketing on the left,
|