@agent-native/core 0.149.1 → 0.149.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/analytics/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/analytics/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +2 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/analytics/AGENTS.md +25 -32
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +150 -46
- package/corpus/templates/analytics/app/global.css +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +37 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
- package/corpus/templates/analytics/changelog/2026-08-10-dashboard-tables-can-be-copied-and-sorted-by-multiple-column.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/assets/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/assets/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/assets/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/assets/AGENTS.md +6 -9
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/brain/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/brain/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/brain/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/brain/AGENTS.md +5 -12
- package/corpus/templates/brain/app/global.css +1 -1
- package/corpus/templates/brain/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/brain/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/calendar/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/calendar/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/calendar/AGENTS.md +8 -9
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/chat/AGENTS.md +32 -80
- package/corpus/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/clips/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/clips/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/clips/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/clips/AGENTS.md +25 -31
- package/corpus/templates/clips/changelog/2026-08-10-clips-desktop-sign-in-now-starts-with-magic-links-and-google.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.css +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +274 -137
- package/corpus/templates/clips/desktop/src/styles.css +35 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/content/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/content/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/content/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/content/AGENTS.md +5 -9
- package/corpus/templates/content/app/global.css +1 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/crm/AGENTS.md +7 -11
- package/corpus/templates/crm/app/global.css +1 -1
- package/corpus/templates/crm/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/crm/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/design/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/design/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/design/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +4 -2
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +70 -3
- package/corpus/templates/design/AGENTS.md +13 -21
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +19 -2
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +115 -7
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +82 -7
- package/corpus/templates/design/app/components/design/design-trace.ts +120 -0
- package/corpus/templates/design/app/components/design/dnd-debug.ts +2 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +40 -26
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -1
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +12 -3
- package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +4 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +7 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -5
- package/corpus/templates/design/app/pages/DesignSystems.tsx +3 -2
- package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +100 -13
- package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +14 -0
- package/corpus/templates/design/changelog/2026-08-10-marquee-selecting-layers-far-down-a-tall-screen-now-selects-.md +6 -0
- package/corpus/templates/design/changelog/2026-08-10-the-frame-tool-draws-a-plain-frame-by-default-with-screen-av.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +27 -32
- package/corpus/templates/design/playwright.config.ts +3 -5
- package/corpus/templates/design/shared/breakpoint-media.ts +9 -2
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/dispatch/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/dispatch/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/dispatch/AGENTS.md +9 -16
- package/corpus/templates/dispatch/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/factory/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/factory/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/factory/AGENTS.md +10 -24
- package/corpus/templates/factory/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/forms/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/forms/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/forms/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/forms/AGENTS.md +11 -17
- package/corpus/templates/forms/app/global.css +1 -0
- package/corpus/templates/forms/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/forms/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/macros/AGENTS.md +8 -8
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/mail/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/mail/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/mail/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/mail/AGENTS.md +5 -6
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/plan/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/plan/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/plan/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/plan/AGENTS.md +5 -14
- package/corpus/templates/plan/app/global.css +1 -0
- package/corpus/templates/plan/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/corpus/templates/plan/changelog/2026-08-11-plan-no-longer-reloads-when-runtime-state-changes.md +6 -0
- package/corpus/templates/plan/server/ui-plan-html.ts +4 -1
- package/corpus/templates/plan/vite.config.ts +5 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/slides/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/slides/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -2
- package/corpus/templates/slides/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +6 -3
- package/corpus/templates/slides/.agents/skills/deck-management/SKILL.md +6 -1
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +3 -2
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +3 -0
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +3 -3
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/slides/AGENTS.md +33 -35
- package/corpus/templates/slides/actions/add-deck.ts +2 -0
- package/corpus/templates/slides/actions/add-slide.ts +15 -1
- package/corpus/templates/slides/actions/create-deck.ts +18 -6
- package/corpus/templates/slides/actions/get-deck-reference-context.ts +2 -2
- package/corpus/templates/slides/actions/get-deck.ts +83 -7
- package/corpus/templates/slides/actions/import-file.ts +2 -1
- package/corpus/templates/slides/actions/patch-deck.ts +165 -9
- package/corpus/templates/slides/actions/save-deck.ts +24 -1
- package/corpus/templates/slides/actions/update-slide.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +2 -2
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -23
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +2 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +6 -6
- package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +3 -3
- package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +4 -4
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +432 -668
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +296 -259
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +13 -1
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +56 -174
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +241 -116
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +42 -14
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +6 -12
- package/corpus/templates/slides/app/components/editor/editor-command-model.ts +35 -0
- package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Layout.tsx +34 -35
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +8 -10
- package/corpus/templates/slides/app/components/layout/layout-route-policy.ts +2 -5
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +45 -40
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +63 -16
- package/corpus/templates/slides/app/context/DeckContext.tsx +2 -1
- package/corpus/templates/slides/app/global.css +76 -1
- package/corpus/templates/slides/app/hooks/use-generating-slide-preview.ts +25 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +52 -23
- package/corpus/templates/slides/app/lib/recent-references.ts +23 -1
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +104 -3
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -33
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +2 -2
- package/corpus/templates/slides/app/pages/Index.tsx +315 -151
- package/corpus/templates/slides/app/root.tsx +43 -0
- package/corpus/templates/slides/changelog/2026-08-10-ai-editing-avatar-badge.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-generated-decks-keep-a-clear-human-readable-title.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-new-deck-creation-now-shows-progress-opens-the-editor-direct.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-presentation-reveals-now-follow-valid-targets.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-editing-controls-are-consolidated-into-one-focused-me.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-now-verify-and-restyle-every-imported-slide-in-one-pa.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-slides-only-suggests-a-google-connection-for-relevant-reques.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-10-the-google-slides-import-option-is-now-labeled-slides.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-faster-slides-chat-deck-reads.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-chat-can-read-one-slide-without-loading-the-full-deck.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-clearly-indicate-when-an-ai-agent-is-editing-alongsid.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/corpus/templates/slides/server/lib/validate-slide-animations.ts +163 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -5
- package/corpus/templates/slides/shared/api.ts +47 -15
- package/corpus/templates/slides/shared/deck-title.ts +135 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +54 -488
- package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +136 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/examples.md +94 -0
- package/corpus/templates/tasks/.agents/skills/actions/references/provider-apis.md +95 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +9 -35
- package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -5
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/corpus/templates/tasks/AGENTS.md +5 -20
- package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +4 -1
- package/dist/agent/engine/ai-sdk-engine.js +1 -1
- package/dist/agent/production-agent.d.ts +21 -1
- package/dist/agent/production-agent.js +505 -355
- package/dist/agent/run-manager.js +156 -14
- package/dist/agent/run-store.d.ts +11 -10
- package/dist/agent/run-store.js +17 -13
- package/dist/agent/tool-approval-store.d.ts +18 -0
- package/dist/agent/tool-approval-store.js +122 -0
- package/dist/agent/types.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +11 -2
- package/dist/client/AgentPanel.js +31 -6
- package/dist/client/AssistantChat.d.ts +9 -4
- package/dist/client/AssistantChat.js +221 -149
- package/dist/client/active-run-state.d.ts +9 -1
- package/dist/client/active-run-state.js +34 -3
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat-adapter.d.ts +8 -0
- package/dist/client/agent-chat-adapter.js +125 -28
- package/dist/client/agent-chat.d.ts +1 -1
- package/dist/client/chat/markdown-renderer.js +14 -2
- package/dist/client/chat/message-components.d.ts +13 -3
- package/dist/client/chat/message-components.js +57 -52
- package/dist/client/chat/run-recovery.d.ts +1 -0
- package/dist/client/chat/run-recovery.js +8 -0
- package/dist/client/chat/tool-call-display.d.ts +5 -5
- package/dist/client/chat/tool-call-display.js +9 -212
- package/dist/client/chat-first/apps-rail.js +3 -3
- package/dist/client/chat-first/browser-pane.js +4 -1
- package/dist/client/chat-first/chat-history.d.ts +3 -1
- package/dist/client/chat-first/chat-history.js +7 -4
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +52 -41
- package/dist/client/chat-first/types.d.ts +3 -0
- package/dist/client/chat-first.d.ts +10 -0
- package/dist/client/chat-first.js +37 -2
- package/dist/client/components/ui/message-scroller.js +4 -1
- package/dist/client/i18n.js +3 -1
- package/dist/client/resources/McpConnectionSuggestion.js +9 -1
- package/dist/client/sse-event-processor.d.ts +4 -2
- package/dist/client/sse-event-processor.js +46 -6
- package/dist/client/use-chat-models.js +156 -80
- package/dist/client/use-run-stuck-detection.d.ts +2 -0
- package/dist/client/use-run-stuck-detection.js +85 -9
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts +0 -4
- package/dist/integrations/adapters/slack.js +6 -30
- package/dist/integrations/catalog.js +1 -1
- package/dist/integrations/pending-tasks-store.d.ts +0 -8
- package/dist/integrations/pending-tasks-store.js +0 -21
- package/dist/integrations/slack-manifest.d.ts +2 -2
- package/dist/integrations/slack-manifest.js +0 -3
- package/dist/integrations/webhook-handler.js +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/scripts/docs/source-search.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js +7 -2
- package/dist/server/agent-chat/prompt-resources.js +2 -2
- package/dist/server/agent-chat/skill-frontmatter.d.ts +31 -2
- package/dist/server/agent-chat/skill-frontmatter.js +41 -15
- package/dist/server/agent-chat-plugin.js +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agents-bundle.d.ts +16 -19
- package/dist/server/agents-bundle.js +19 -35
- package/dist/server/auth.js +262 -31
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/onboarding-html.js +56 -9
- package/dist/server/prompts/framework-core-compact.d.ts +6 -1
- package/dist/server/prompts/framework-core-compact.js +12 -9
- package/dist/server/prompts/framework-core.d.ts +6 -1
- package/dist/server/prompts/framework-core.js +11 -9
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/shared-rules.d.ts +15 -11
- package/dist/server/prompts/shared-rules.js +17 -13
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/reasoning-effort.d.ts +8 -8
- package/dist/shared/reasoning-effort.js +10 -10
- package/dist/shared/streaming-text-smoothing.js +41 -11
- package/dist/styles/agent-native.css +19 -32
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/chat/AGENTS.md +32 -80
- package/dist/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/dist/templates/workspace-core/AGENTS.md +7 -16
- package/docs/content/messaging.mdx +6 -7
- package/docs/content/template-chat.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/chat/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/chat/AGENTS.md +32 -80
- package/src/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/default/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/headless/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/headless/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
- package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
- package/src/templates/workspace-core/AGENTS.md +7 -16
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Result is cached in module scope so it's only computed once per cold start.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
import { DEFAULT_SKILL_SCOPE, isRuntimeVisibleScope, normalizeSkillScope, } from "./agent-chat/skill-frontmatter.js";
|
|
24
|
+
export { DEFAULT_SKILL_SCOPE, isRuntimeVisibleScope, normalizeSkillScope, };
|
|
24
25
|
const DEFAULT_AGENT_INSTRUCTIONS_PATH = "AGENTS.md";
|
|
25
26
|
export function resolveAgentInstructionPaths(instructions) {
|
|
26
27
|
return {
|
|
@@ -29,26 +30,6 @@ export function resolveAgentInstructionPaths(instructions) {
|
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
let cached = null;
|
|
32
|
-
/**
|
|
33
|
-
* Coerce a raw frontmatter `scope` value into a known `SkillScope`. Unknown,
|
|
34
|
-
* empty, or malformed values fall back to the default (`both`) so a typo never
|
|
35
|
-
* silently hides a skill from the runtime agent. Optionally warns once per
|
|
36
|
-
* distinct bad value to aid debugging without spamming logs.
|
|
37
|
-
*/
|
|
38
|
-
const warnedBadScopes = new Set();
|
|
39
|
-
export function normalizeSkillScope(raw) {
|
|
40
|
-
if (!raw)
|
|
41
|
-
return DEFAULT_SKILL_SCOPE;
|
|
42
|
-
const value = raw.trim().toLowerCase();
|
|
43
|
-
if (value === "runtime" || value === "dev" || value === "both") {
|
|
44
|
-
return value;
|
|
45
|
-
}
|
|
46
|
-
if (value && !warnedBadScopes.has(value)) {
|
|
47
|
-
warnedBadScopes.add(value);
|
|
48
|
-
console.warn(`[agents-bundle] Unknown skill scope "${raw}" — treating as "${DEFAULT_SKILL_SCOPE}". Valid values: runtime, dev, both.`);
|
|
49
|
-
}
|
|
50
|
-
return DEFAULT_SKILL_SCOPE;
|
|
51
|
-
}
|
|
52
33
|
/**
|
|
53
34
|
* Parse the YAML frontmatter at the top of a skill file.
|
|
54
35
|
* Only pulls out `name`, `description`, and `scope` — deliberately simple, no
|
|
@@ -57,8 +38,11 @@ export function normalizeSkillScope(raw) {
|
|
|
57
38
|
* - Inline: `description: Some text`
|
|
58
39
|
* - Folded scalar: `description: >-\n multi\n line` → "multi line"
|
|
59
40
|
* - Literal scalar: `description: |\n multi\n line` → "multi\nline"
|
|
41
|
+
*
|
|
42
|
+
* `sourceLabel` only names the file in the invalid-scope log; pass it wherever
|
|
43
|
+
* a path is known so a typo is traceable to the SKILL.md that carries it.
|
|
60
44
|
*/
|
|
61
|
-
export function parseSkillFrontmatter(content) {
|
|
45
|
+
export function parseSkillFrontmatter(content, sourceLabel) {
|
|
62
46
|
const match = content.match(/^---\r?\n([\s\S]+?)\r?\n---/);
|
|
63
47
|
if (!match)
|
|
64
48
|
return {};
|
|
@@ -106,7 +90,7 @@ export function parseSkillFrontmatter(content) {
|
|
|
106
90
|
else if (key === "description" && value)
|
|
107
91
|
result.description = value;
|
|
108
92
|
else if (key === "scope" && value)
|
|
109
|
-
result.scope = normalizeSkillScope(value);
|
|
93
|
+
result.scope = normalizeSkillScope(value, sourceLabel ?? result.name);
|
|
110
94
|
}
|
|
111
95
|
return result;
|
|
112
96
|
}
|
|
@@ -170,7 +154,7 @@ function readSkillsDir(skillsDir, rootForRelative, out, skipExistingNames) {
|
|
|
170
154
|
if (!fs.existsSync(realSkillFile))
|
|
171
155
|
continue;
|
|
172
156
|
const content = fs.readFileSync(realSkillFile, "utf-8");
|
|
173
|
-
const meta = parseSkillFrontmatter(content);
|
|
157
|
+
const meta = parseSkillFrontmatter(content, path.relative(rootForRelative, skillFile).replace(/\\/g, "/"));
|
|
174
158
|
const name = meta.name ?? entry.name;
|
|
175
159
|
if (skipExistingNames && out[name])
|
|
176
160
|
continue; // Template wins
|
|
@@ -375,17 +359,19 @@ export async function loadAgentsBundle() {
|
|
|
375
359
|
*/
|
|
376
360
|
/**
|
|
377
361
|
* Skills visible to the agent-native RUNTIME agent. Excludes `scope: dev`
|
|
378
|
-
* skills (those are for the human's coding agent only)
|
|
379
|
-
* `scope: runtime`, or `scope: both`
|
|
380
|
-
* runtime agent's view of skills is
|
|
381
|
-
* dev-scoped skill is invisible to the
|
|
362
|
+
* skills (those are for the human's coding agent only) and skills whose scope
|
|
363
|
+
* could not be read. Skills with no scope, `scope: runtime`, or `scope: both`
|
|
364
|
+
* are all included. Use this anywhere the runtime agent's view of skills is
|
|
365
|
+
* built (prompt block + docs-search) so a dev-scoped skill is invisible to the
|
|
366
|
+
* runtime agent everywhere.
|
|
382
367
|
*/
|
|
383
368
|
export function getRuntimeSkills(bundle) {
|
|
384
|
-
return Object.values(bundle.skills).filter((skill) => skill.meta.scope
|
|
369
|
+
return Object.values(bundle.skills).filter((skill) => isRuntimeVisibleScope(skill.meta.scope));
|
|
385
370
|
}
|
|
386
371
|
/**
|
|
387
372
|
* Skills visible to development/coding agents. Excludes `scope: runtime`
|
|
388
|
-
* skills that are intended only for the deployed in-app agent.
|
|
373
|
+
* skills that are intended only for the deployed in-app agent. An `invalid`
|
|
374
|
+
* scope stays visible here on purpose — this is the audience that can fix it.
|
|
389
375
|
*/
|
|
390
376
|
export function getDevelopmentSkills(bundle) {
|
|
391
377
|
return Object.values(bundle.skills).filter((skill) => skill.meta.scope !== "runtime");
|
|
@@ -437,14 +423,12 @@ function generateSkillsPromptBlockForEntries(entries, mode) {
|
|
|
437
423
|
extras = ` (also contains: ${s.extraFiles.join(", ")})`;
|
|
438
424
|
}
|
|
439
425
|
}
|
|
440
|
-
const runtimeHint = mode === "runtime"
|
|
441
|
-
? ` Read with \`docs-search --slug "${skillDocsSlug(s.meta.name)}"\` before starting a task it applies to.`
|
|
442
|
-
: "";
|
|
426
|
+
const runtimeHint = mode === "runtime" ? ` [${skillDocsSlug(s.meta.name)}]` : "";
|
|
443
427
|
return `- \`${s.meta.name}\` at \`${s.dir}/\` — ${s.meta.description || "(no description)"}${extras}${runtimeHint}`;
|
|
444
428
|
});
|
|
445
429
|
const readHint = mode === "runtime"
|
|
446
|
-
? `To read a skill in the in-app runtime agent:
|
|
447
|
-
\`docs-search --slug "
|
|
430
|
+
? `To read a skill in the in-app runtime agent, before starting a task it applies to:
|
|
431
|
+
\`docs-search --slug "<slug>"\` — each skill's slug is the [bracketed] token ending its line
|
|
448
432
|
\`docs-search --query "<topic>"\` to discover matching docs/skills`
|
|
449
433
|
: `To read a skill in dev mode (when you have bash access):
|
|
450
434
|
\`bash(command="cat <skill-dir>/SKILL.md")\`
|
package/dist/server/auth.js
CHANGED
|
@@ -63,7 +63,7 @@ import { resolveAuthCookieNamespace } from "./cookie-namespace.js";
|
|
|
63
63
|
import { getAllowedCorsOrigin, readCorsAllowedOrigins, } from "./cors-origins.js";
|
|
64
64
|
import { readDesktopSso, writeDesktopSso, clearDesktopSso, } from "./desktop-sso.js";
|
|
65
65
|
import { resolveGoogleSignInCredentials } from "./google-oauth-credentials.js";
|
|
66
|
-
import { isElectron as isElectronRequest, getAppBasePath, getAppUrl, getOrigin, encodeOAuthState, decodeOAuthState, createOAuthSession, oauthCallbackResponse, oauthErrorPage, resolveOAuthRedirectUri, isAllowedOAuthRedirectUri, } from "./google-oauth.js";
|
|
66
|
+
import { isElectron as isElectronRequest, getAppBasePath, getAppUrl, getOrigin, encodeOAuthState, decodeOAuthState, createOAuthSession, oauthCallbackResponse, oauthDesktopExchangePage, oauthErrorPage, resolveOAuthRedirectUri, isAllowedOAuthRedirectUri, } from "./google-oauth.js";
|
|
67
67
|
// Pure env-read feature switch from a leaf module (no dependency back on
|
|
68
68
|
// auth.ts), so the guard and the SSO route handler share one validator and
|
|
69
69
|
// can never disagree about whether federated SSO is enabled.
|
|
@@ -1025,6 +1025,8 @@ function areGenericGoogleOAuthRoutesEnabled(app) {
|
|
|
1025
1025
|
}
|
|
1026
1026
|
const _desktopExchanges = new Map();
|
|
1027
1027
|
const DESKTOP_EXCHANGE_ERROR_PREFIX = "__error__::";
|
|
1028
|
+
const DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX = "__magic-link-challenge__::";
|
|
1029
|
+
const DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX = "__magic-link-exchange__::";
|
|
1028
1030
|
const DESKTOP_AUTH_TOKEN_BODY_ORIGINS = new Set([
|
|
1029
1031
|
"tauri://localhost",
|
|
1030
1032
|
"http://tauri.localhost",
|
|
@@ -1033,6 +1035,90 @@ const DESKTOP_AUTH_TOKEN_BODY_ORIGINS = new Set([
|
|
|
1033
1035
|
]);
|
|
1034
1036
|
// 5-minute TTL for exchange entries (short — single-use tokens).
|
|
1035
1037
|
const DESKTOP_EXCHANGE_TTL_MS = 5 * 60 * 1000;
|
|
1038
|
+
function normalizeDesktopFlowId(value) {
|
|
1039
|
+
if (typeof value !== "string")
|
|
1040
|
+
return null;
|
|
1041
|
+
const flowId = value.trim();
|
|
1042
|
+
return /^[A-Za-z0-9_-]{1,128}$/.test(flowId) ? flowId : null;
|
|
1043
|
+
}
|
|
1044
|
+
function normalizeDesktopFlowVerifier(value) {
|
|
1045
|
+
if (typeof value !== "string")
|
|
1046
|
+
return null;
|
|
1047
|
+
const verifier = value.trim();
|
|
1048
|
+
return /^[A-Za-z0-9_-]{32,128}$/.test(verifier) ? verifier : null;
|
|
1049
|
+
}
|
|
1050
|
+
function desktopFlowVerifierHash(verifier) {
|
|
1051
|
+
return crypto.createHash("sha256").update(verifier).digest("base64url");
|
|
1052
|
+
}
|
|
1053
|
+
function matchesDesktopFlowVerifier(verifier, expectedHash) {
|
|
1054
|
+
const actual = Buffer.from(desktopFlowVerifierHash(verifier));
|
|
1055
|
+
const expected = Buffer.from(expectedHash);
|
|
1056
|
+
return (actual.length === expected.length &&
|
|
1057
|
+
crypto.timingSafeEqual(actual, expected));
|
|
1058
|
+
}
|
|
1059
|
+
function parseDesktopExchangeStoredEntry(packed) {
|
|
1060
|
+
if (packed.startsWith(DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX)) {
|
|
1061
|
+
const verifierHash = packed.slice(DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX.length);
|
|
1062
|
+
return verifierHash ? { challenge: true, verifierHash } : null;
|
|
1063
|
+
}
|
|
1064
|
+
if (packed.startsWith(DESKTOP_EXCHANGE_ERROR_PREFIX)) {
|
|
1065
|
+
const raw = packed.slice(DESKTOP_EXCHANGE_ERROR_PREFIX.length);
|
|
1066
|
+
return {
|
|
1067
|
+
error: JSON.parse(Buffer.from(raw, "base64url").toString()),
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
const isMagicLinkExchange = packed.startsWith(DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX);
|
|
1071
|
+
const encoded = isMagicLinkExchange
|
|
1072
|
+
? packed.slice(DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX.length)
|
|
1073
|
+
: packed;
|
|
1074
|
+
const verifierSeparator = isMagicLinkExchange ? encoded.indexOf("::") : -1;
|
|
1075
|
+
const verifierHash = verifierSeparator >= 0 ? encoded.slice(0, verifierSeparator) : undefined;
|
|
1076
|
+
const tokenAndEmail = verifierSeparator >= 0 ? encoded.slice(verifierSeparator + 2) : encoded;
|
|
1077
|
+
const sepIdx = tokenAndEmail.indexOf("::");
|
|
1078
|
+
if (sepIdx === -1)
|
|
1079
|
+
return null;
|
|
1080
|
+
return {
|
|
1081
|
+
token: tokenAndEmail.slice(0, sepIdx),
|
|
1082
|
+
email: tokenAndEmail.slice(sepIdx + 2),
|
|
1083
|
+
...(verifierHash ? { verifierHash } : {}),
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
function isDesktopMagicLinkCallbackPath(value) {
|
|
1087
|
+
try {
|
|
1088
|
+
return new URL(value, "http://agent-native.invalid").pathname.endsWith("/_agent-native/auth/magic-link/desktop-callback");
|
|
1089
|
+
}
|
|
1090
|
+
catch {
|
|
1091
|
+
// coercion-ok: malformed callback URLs are treated as non-desktop callbacks.
|
|
1092
|
+
return false;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
function withDesktopMagicLinkFlow(callbackURL, flow) {
|
|
1096
|
+
const url = new URL(callbackURL, "http://agent-native.invalid");
|
|
1097
|
+
url.searchParams.set("flow_id", flow.flowId);
|
|
1098
|
+
url.searchParams.set("verifier", flow.verifier);
|
|
1099
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
1100
|
+
}
|
|
1101
|
+
async function persistDesktopMagicLinkChallenge(flowId, verifierHash) {
|
|
1102
|
+
await addSession(`dex:${flowId}`, `${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}${verifierHash}`);
|
|
1103
|
+
}
|
|
1104
|
+
async function issueDesktopMagicLinkFlow() {
|
|
1105
|
+
const flowId = crypto.randomBytes(32).toString("base64url");
|
|
1106
|
+
const verifier = crypto.randomBytes(32).toString("base64url");
|
|
1107
|
+
const verifierHash = desktopFlowVerifierHash(verifier);
|
|
1108
|
+
_desktopExchanges.set(flowId, {
|
|
1109
|
+
challenge: true,
|
|
1110
|
+
verifierHash,
|
|
1111
|
+
expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
|
|
1112
|
+
});
|
|
1113
|
+
try {
|
|
1114
|
+
await persistDesktopMagicLinkChallenge(flowId, verifierHash);
|
|
1115
|
+
}
|
|
1116
|
+
catch (error) {
|
|
1117
|
+
_desktopExchanges.delete(flowId);
|
|
1118
|
+
throw error;
|
|
1119
|
+
}
|
|
1120
|
+
return { flowId, verifier };
|
|
1121
|
+
}
|
|
1036
1122
|
export function setDesktopExchange(flowId, token, email) {
|
|
1037
1123
|
_desktopExchanges.set(flowId, {
|
|
1038
1124
|
token,
|
|
@@ -1059,9 +1145,12 @@ export function setDesktopExchangeError(flowId, error) {
|
|
|
1059
1145
|
* Non-fatal — if the DB isn't ready yet the in-memory Map still works for
|
|
1060
1146
|
* same-instance requests.
|
|
1061
1147
|
*/
|
|
1062
|
-
async function persistDesktopExchangeToDB(flowId, token, email) {
|
|
1148
|
+
async function persistDesktopExchangeToDB(flowId, token, email, verifierHash) {
|
|
1063
1149
|
try {
|
|
1064
|
-
|
|
1150
|
+
const packed = verifierHash
|
|
1151
|
+
? `${DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX}${verifierHash}::${token}::${email}`
|
|
1152
|
+
: `${token}::${email}`;
|
|
1153
|
+
await addSession(`dex:${flowId}`, packed);
|
|
1065
1154
|
}
|
|
1066
1155
|
catch {
|
|
1067
1156
|
// non-fatal — in-memory Map is the primary path
|
|
@@ -1090,8 +1179,12 @@ async function consumeDesktopExchangeFromDB(flowId) {
|
|
|
1090
1179
|
// redeemed with the session table's default 30-day TTL.
|
|
1091
1180
|
const client = getDbExec();
|
|
1092
1181
|
const { rows } = await client.execute({
|
|
1093
|
-
sql: `DELETE FROM sessions WHERE token = ? AND created_at > ? RETURNING email`,
|
|
1094
|
-
args: [
|
|
1182
|
+
sql: `DELETE FROM sessions WHERE token = ? AND created_at > ? AND email NOT LIKE ? RETURNING email`,
|
|
1183
|
+
args: [
|
|
1184
|
+
`dex:${flowId}`,
|
|
1185
|
+
Date.now() - DESKTOP_EXCHANGE_TTL_MS,
|
|
1186
|
+
`${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}%`,
|
|
1187
|
+
],
|
|
1095
1188
|
});
|
|
1096
1189
|
forgetCachedSessionEmail(`dex:${flowId}`);
|
|
1097
1190
|
if (rows.length === 0)
|
|
@@ -1099,21 +1192,72 @@ async function consumeDesktopExchangeFromDB(flowId) {
|
|
|
1099
1192
|
const packed = (rows[0].email ?? rows[0][0]);
|
|
1100
1193
|
if (!packed)
|
|
1101
1194
|
return null;
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1195
|
+
return parseDesktopExchangeStoredEntry(packed);
|
|
1196
|
+
}
|
|
1197
|
+
catch {
|
|
1198
|
+
// coercion-ok: a DB fallback outage leaves the exchange pending so polling can retry without consuming a token.
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
async function readDesktopMagicLinkChallengeFromDB(flowId) {
|
|
1203
|
+
try {
|
|
1204
|
+
const client = getDbExec();
|
|
1205
|
+
const { rows } = await client.execute({
|
|
1206
|
+
sql: `SELECT email FROM sessions WHERE token = ? AND created_at > ? LIMIT 1`,
|
|
1207
|
+
args: [`dex:${flowId}`, Date.now() - DESKTOP_EXCHANGE_TTL_MS],
|
|
1208
|
+
});
|
|
1209
|
+
if (rows.length === 0)
|
|
1210
|
+
return null;
|
|
1211
|
+
const packed = (rows[0].email ?? rows[0][0]);
|
|
1212
|
+
if (!packed)
|
|
1110
1213
|
return null;
|
|
1111
|
-
|
|
1214
|
+
const entry = parseDesktopExchangeStoredEntry(packed);
|
|
1215
|
+
return entry && "challenge" in entry
|
|
1216
|
+
? { verifierHash: entry.verifierHash }
|
|
1217
|
+
: null;
|
|
1112
1218
|
}
|
|
1113
1219
|
catch {
|
|
1114
1220
|
return null;
|
|
1115
1221
|
}
|
|
1116
1222
|
}
|
|
1223
|
+
async function claimDesktopMagicLinkFlow(flowId, verifier, token, email) {
|
|
1224
|
+
const verifierHash = desktopFlowVerifierHash(verifier);
|
|
1225
|
+
const entry = _desktopExchanges.get(flowId);
|
|
1226
|
+
if (entry) {
|
|
1227
|
+
if (!("challenge" in entry) ||
|
|
1228
|
+
entry.expiresAt < Date.now() ||
|
|
1229
|
+
!matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
|
|
1230
|
+
return false;
|
|
1231
|
+
}
|
|
1232
|
+
_desktopExchanges.set(flowId, {
|
|
1233
|
+
token,
|
|
1234
|
+
email,
|
|
1235
|
+
verifierHash,
|
|
1236
|
+
expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
|
|
1237
|
+
});
|
|
1238
|
+
await persistDesktopExchangeToDB(flowId, token, email, verifierHash);
|
|
1239
|
+
return true;
|
|
1240
|
+
}
|
|
1241
|
+
try {
|
|
1242
|
+
const client = getDbExec();
|
|
1243
|
+
const packed = `${DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX}${verifierHash}::${token}::${email}`;
|
|
1244
|
+
const { rows } = await client.execute({
|
|
1245
|
+
sql: `UPDATE sessions SET email = ?, created_at = ? WHERE token = ? AND created_at > ? AND email = ? RETURNING email`,
|
|
1246
|
+
args: [
|
|
1247
|
+
packed,
|
|
1248
|
+
Date.now(),
|
|
1249
|
+
`dex:${flowId}`,
|
|
1250
|
+
Date.now() - DESKTOP_EXCHANGE_TTL_MS,
|
|
1251
|
+
`${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}${verifierHash}`,
|
|
1252
|
+
],
|
|
1253
|
+
});
|
|
1254
|
+
return rows.length > 0;
|
|
1255
|
+
}
|
|
1256
|
+
catch {
|
|
1257
|
+
// coercion-ok: a failed DB claim must not issue a native session token.
|
|
1258
|
+
return false;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1117
1261
|
setInterval(() => {
|
|
1118
1262
|
const now = Date.now();
|
|
1119
1263
|
for (const [k, v] of _desktopExchanges) {
|
|
@@ -2640,15 +2784,7 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2640
2784
|
emailDomain: email.split("@")[1] || "",
|
|
2641
2785
|
});
|
|
2642
2786
|
if (flowId && sessionToken) {
|
|
2643
|
-
|
|
2644
|
-
token: sessionToken,
|
|
2645
|
-
email,
|
|
2646
|
-
expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
|
|
2647
|
-
});
|
|
2648
|
-
// Also persist to DB for cross-instance durability (Cloudflare
|
|
2649
|
-
// Workers, multi-region). Fire-and-forget — in-memory Map is
|
|
2650
|
-
// still the primary fast path for same-instance requests.
|
|
2651
|
-
void persistDesktopExchangeToDB(flowId, sessionToken, email);
|
|
2787
|
+
setDesktopExchange(flowId, sessionToken, email);
|
|
2652
2788
|
logGoogleOAuthDebug(event, "callback-exchange-stored", {
|
|
2653
2789
|
flowId,
|
|
2654
2790
|
desktop,
|
|
@@ -2687,13 +2823,23 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2687
2823
|
return { error: "Method not allowed" };
|
|
2688
2824
|
}
|
|
2689
2825
|
const query = getQuery(event);
|
|
2690
|
-
const flowId = query.flow_id;
|
|
2826
|
+
const flowId = normalizeDesktopFlowId(query.flow_id);
|
|
2691
2827
|
if (!flowId) {
|
|
2692
2828
|
setResponseStatus(event, 400);
|
|
2693
2829
|
return { error: "Missing flow_id" };
|
|
2694
2830
|
}
|
|
2831
|
+
const verifier = normalizeDesktopFlowVerifier(getQuery(event).verifier);
|
|
2695
2832
|
let entry = _desktopExchanges.get(flowId);
|
|
2696
2833
|
if (!entry || entry.expiresAt < Date.now()) {
|
|
2834
|
+
const challenge = await readDesktopMagicLinkChallengeFromDB(flowId);
|
|
2835
|
+
if (challenge) {
|
|
2836
|
+
if (!verifier ||
|
|
2837
|
+
!matchesDesktopFlowVerifier(verifier, challenge.verifierHash)) {
|
|
2838
|
+
setResponseStatus(event, 403);
|
|
2839
|
+
return { error: "Invalid desktop exchange verifier." };
|
|
2840
|
+
}
|
|
2841
|
+
return { pending: true, flow: oauthDebugFlowId(flowId) };
|
|
2842
|
+
}
|
|
2697
2843
|
// In-memory miss — fall back to the DB-persisted entry. This handles
|
|
2698
2844
|
// cross-instance routing (Cloudflare Workers, multi-region) where the
|
|
2699
2845
|
// OAuth callback and the polling request may hit different isolates.
|
|
@@ -2709,11 +2855,35 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2709
2855
|
entry =
|
|
2710
2856
|
"error" in fromDb
|
|
2711
2857
|
? { error: fromDb.error, expiresAt: Date.now() + 1 }
|
|
2712
|
-
:
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2858
|
+
: "challenge" in fromDb
|
|
2859
|
+
? {
|
|
2860
|
+
challenge: true,
|
|
2861
|
+
verifierHash: fromDb.verifierHash,
|
|
2862
|
+
expiresAt: Date.now() + 1,
|
|
2863
|
+
}
|
|
2864
|
+
: {
|
|
2865
|
+
token: fromDb.token,
|
|
2866
|
+
email: fromDb.email,
|
|
2867
|
+
...(fromDb.verifierHash
|
|
2868
|
+
? { verifierHash: fromDb.verifierHash }
|
|
2869
|
+
: {}),
|
|
2870
|
+
expiresAt: Date.now() + 1,
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
if ("challenge" in entry) {
|
|
2874
|
+
if (!verifier ||
|
|
2875
|
+
!matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
|
|
2876
|
+
setResponseStatus(event, 403);
|
|
2877
|
+
return { error: "Invalid desktop exchange verifier." };
|
|
2878
|
+
}
|
|
2879
|
+
return { pending: true, flow: oauthDebugFlowId(flowId) };
|
|
2880
|
+
}
|
|
2881
|
+
if ("token" in entry && entry.verifierHash) {
|
|
2882
|
+
if (!verifier ||
|
|
2883
|
+
!matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
|
|
2884
|
+
setResponseStatus(event, 403);
|
|
2885
|
+
return { error: "Invalid desktop exchange verifier." };
|
|
2886
|
+
}
|
|
2717
2887
|
}
|
|
2718
2888
|
_desktopExchanges.delete(flowId);
|
|
2719
2889
|
// Also wipe the DB-persisted entry so it cannot be replayed via the
|
|
@@ -2735,6 +2905,13 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2735
2905
|
// still make a follow-up /auth/session?_session=... request, but the
|
|
2736
2906
|
// OAuth handoff should not depend on that second request succeeding.
|
|
2737
2907
|
setFrameworkSessionCookie(event, entry.token);
|
|
2908
|
+
if (isElectronRequest(event)) {
|
|
2909
|
+
await writeDesktopSso({
|
|
2910
|
+
email: entry.email,
|
|
2911
|
+
token: entry.token,
|
|
2912
|
+
expiresAt: Date.now() + sessionMaxAge * 1000,
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2738
2915
|
setResponseHeader(event, "Referrer-Policy", "no-referrer");
|
|
2739
2916
|
logGoogleOAuthDebug(event, "exchange-success", {
|
|
2740
2917
|
flowId,
|
|
@@ -2742,6 +2919,52 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
2742
2919
|
});
|
|
2743
2920
|
return { token: entry.token, email: entry.email };
|
|
2744
2921
|
}));
|
|
2922
|
+
// Magic-link verification happens in the system browser, so native shells
|
|
2923
|
+
// need the verified browser session copied into the same one-time exchange
|
|
2924
|
+
// used by Google OAuth before they can establish their own WebView session.
|
|
2925
|
+
app.use("/_agent-native/auth/magic-link/desktop-callback", defineEventHandler(async (event) => {
|
|
2926
|
+
if (!isReadMethod(event)) {
|
|
2927
|
+
setResponseStatus(event, 405);
|
|
2928
|
+
return { error: "Method not allowed" };
|
|
2929
|
+
}
|
|
2930
|
+
const flowId = normalizeDesktopFlowId(getQuery(event).flow_id);
|
|
2931
|
+
const verifier = normalizeDesktopFlowVerifier(getQuery(event).verifier);
|
|
2932
|
+
if (!flowId) {
|
|
2933
|
+
setResponseStatus(event, 400);
|
|
2934
|
+
return { error: "Missing flow_id" };
|
|
2935
|
+
}
|
|
2936
|
+
if (!verifier) {
|
|
2937
|
+
return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
|
|
2938
|
+
}
|
|
2939
|
+
const session = await getSession(event);
|
|
2940
|
+
if (!session?.email || !session.token) {
|
|
2941
|
+
setDesktopExchangeError(flowId, {
|
|
2942
|
+
message: AUTH_MAGIC_LINK_FALLBACK,
|
|
2943
|
+
code: "callback_error",
|
|
2944
|
+
});
|
|
2945
|
+
return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
|
|
2946
|
+
}
|
|
2947
|
+
try {
|
|
2948
|
+
// Better Auth owns the browser cookie, while native clients resolve
|
|
2949
|
+
// the exchanged token through the framework session table.
|
|
2950
|
+
await addSession(session.token, session.email);
|
|
2951
|
+
}
|
|
2952
|
+
catch (error) {
|
|
2953
|
+
captureAuthError(error, {
|
|
2954
|
+
route: "magic-link",
|
|
2955
|
+
email: session.email,
|
|
2956
|
+
});
|
|
2957
|
+
setDesktopExchangeError(flowId, {
|
|
2958
|
+
message: AUTH_MAGIC_LINK_FALLBACK,
|
|
2959
|
+
code: "callback_error",
|
|
2960
|
+
});
|
|
2961
|
+
return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
|
|
2962
|
+
}
|
|
2963
|
+
if (!(await claimDesktopMagicLinkFlow(flowId, verifier, session.token, session.email))) {
|
|
2964
|
+
return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
|
|
2965
|
+
}
|
|
2966
|
+
return oauthDesktopExchangePage("Sign-in complete. You can return to the app.");
|
|
2967
|
+
}));
|
|
2745
2968
|
// Initialize Better Auth. Forward `googleScopes` into the BetterAuthConfig
|
|
2746
2969
|
// so the social provider requests the broader product scopes (Gmail,
|
|
2747
2970
|
// Calendar, etc.) up front during the primary sign-in — eliminating the
|
|
@@ -3050,9 +3273,10 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
3050
3273
|
const body = await readBody(event);
|
|
3051
3274
|
const rawEmail = typeof body?.email === "string" ? body.email : "";
|
|
3052
3275
|
const email = normalizeAuthEmail(rawEmail);
|
|
3053
|
-
|
|
3276
|
+
let callbackURL = typeof body?.callbackURL === "string"
|
|
3054
3277
|
? safeReturnPath(body.callbackURL)
|
|
3055
3278
|
: "/";
|
|
3279
|
+
let desktopFlow;
|
|
3056
3280
|
if (!email) {
|
|
3057
3281
|
setResponseStatus(event, 400);
|
|
3058
3282
|
return { error: VALID_AUTH_EMAIL_MESSAGE };
|
|
@@ -3062,6 +3286,10 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
3062
3286
|
return { error: GOOGLE_AUTH_REQUIRED_MESSAGE };
|
|
3063
3287
|
}
|
|
3064
3288
|
try {
|
|
3289
|
+
if (isDesktopMagicLinkCallbackPath(callbackURL)) {
|
|
3290
|
+
desktopFlow = await issueDesktopMagicLinkFlow();
|
|
3291
|
+
callbackURL = withDesktopMagicLinkFlow(callbackURL, desktopFlow);
|
|
3292
|
+
}
|
|
3065
3293
|
await auth.api.signInMagicLink({
|
|
3066
3294
|
body: {
|
|
3067
3295
|
email,
|
|
@@ -3070,7 +3298,10 @@ async function mountBetterAuthRoutes(app, options) {
|
|
|
3070
3298
|
},
|
|
3071
3299
|
headers: event.headers,
|
|
3072
3300
|
});
|
|
3073
|
-
return {
|
|
3301
|
+
return {
|
|
3302
|
+
ok: true,
|
|
3303
|
+
...(desktopFlow ?? {}),
|
|
3304
|
+
};
|
|
3074
3305
|
}
|
|
3075
3306
|
catch (e) {
|
|
3076
3307
|
if (!isExpectedAuthFailure(e)) {
|
|
@@ -253,3 +253,4 @@ export declare function resetBetterAuth(): Promise<void>;
|
|
|
253
253
|
export declare function configureLocalSqlite(sqlite: {
|
|
254
254
|
pragma(statement: string): unknown;
|
|
255
255
|
}): void;
|
|
256
|
+
export declare function buildDatabaseConfig(dialect: string): Promise<BetterAuthOptions["database"]>;
|
|
@@ -16,7 +16,7 @@ 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, neonPoolOptions, guardNeonPool, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
|
|
19
|
+
import { getDialect, getCloudflareD1Binding, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, guardNeonPool, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
|
|
20
20
|
import { CORE_RESET_PASSWORD_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, } from "../email-catalog/system-emails.js";
|
|
21
21
|
import { saveOAuthTokens } from "../oauth-tokens/store.js";
|
|
22
22
|
import { acceptPendingInvitationsForEmail } from "../org/accept-pending.js";
|
|
@@ -1126,7 +1126,7 @@ export function configureLocalSqlite(sqlite) {
|
|
|
1126
1126
|
sqlite.pragma("busy_timeout = 10000");
|
|
1127
1127
|
sqlite.pragma("journal_mode = WAL");
|
|
1128
1128
|
}
|
|
1129
|
-
async function buildDatabaseConfig(dialect) {
|
|
1129
|
+
export async function buildDatabaseConfig(dialect) {
|
|
1130
1130
|
if (dialect === "postgres") {
|
|
1131
1131
|
const url = getDatabaseUrl();
|
|
1132
1132
|
const { buildResilientNeonPool, buildResilientPostgresJsClient, isNeonUrl, } = await import("../db/create-get-db.js");
|
|
@@ -1180,6 +1180,21 @@ async function buildDatabaseConfig(dialect) {
|
|
|
1180
1180
|
schema: pgAuthSchema,
|
|
1181
1181
|
});
|
|
1182
1182
|
}
|
|
1183
|
+
if (dialect === "d1") {
|
|
1184
|
+
const d1 = getCloudflareD1Binding();
|
|
1185
|
+
if (!d1) {
|
|
1186
|
+
throw new Error("Cloudflare D1 database binding is unavailable; configure the DB binding before initializing Better Auth.");
|
|
1187
|
+
}
|
|
1188
|
+
const { drizzle } = await import("drizzle-orm/d1");
|
|
1189
|
+
const db = drizzle(d1, {
|
|
1190
|
+
schema: sqliteAuthSchema,
|
|
1191
|
+
});
|
|
1192
|
+
const { drizzleAdapter } = await import("better-auth/adapters/drizzle");
|
|
1193
|
+
return drizzleAdapter(db, {
|
|
1194
|
+
provider: "sqlite",
|
|
1195
|
+
schema: sqliteAuthSchema,
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1183
1198
|
// SQLite / libsql
|
|
1184
1199
|
const url = getDatabaseUrl("file:./data/app.db");
|
|
1185
1200
|
if (url.startsWith("file:") || !url.includes("://")) {
|