@agent-native/core 0.79.17 → 0.79.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/file-uploads.md +11 -4
- package/corpus/core/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/template-clips.md +14 -5
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builder-engine.ts +8 -3
- package/corpus/core/src/cli/mcp.ts +11 -6
- package/corpus/core/src/client/AssistantChat.tsx +6 -2
- package/corpus/core/src/client/chat/markdown-renderer.tsx +1 -0
- package/corpus/core/src/client/i18n.tsx +77 -65
- package/corpus/core/src/client/index.ts +7 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +5 -5
- package/corpus/core/src/client/org/TeamPage.tsx +11 -3
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +216 -0
- package/corpus/core/src/client/settings/index.ts +5 -0
- package/corpus/core/src/file-upload/index.ts +1 -0
- package/corpus/core/src/file-upload/registry.ts +22 -6
- package/corpus/core/src/file-upload/types.ts +6 -1
- package/corpus/core/src/integrations/adapters/email.ts +26 -18
- package/corpus/core/src/integrations/adapters/slack.ts +8 -7
- package/corpus/core/src/integrations/adapters/telegram.ts +9 -11
- package/corpus/core/src/integrations/adapters/whatsapp.ts +12 -9
- package/corpus/core/src/integrations/plugin.ts +79 -13
- package/corpus/core/src/onboarding/default-steps.ts +6 -3
- package/corpus/core/src/onboarding/types.ts +1 -1
- package/corpus/core/src/org/handlers.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +4 -7
- package/corpus/core/src/server/better-auth-instance.ts +19 -62
- package/corpus/core/src/server/core-routes-plugin.ts +93 -180
- package/corpus/core/src/server/create-server.ts +55 -116
- package/corpus/core/src/server/email-actions.ts +3 -6
- package/corpus/core/src/server/email.ts +52 -17
- package/corpus/core/src/server/index.ts +2 -1
- package/corpus/core/src/server/scoped-key-storage.ts +223 -0
- package/corpus/core/src/shared/agent-env.ts +3 -3
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -1
- package/corpus/core/src/styles/agent-native.css +47 -3
- package/corpus/core/src/templates/workspace-root/AGENTS.md +3 -2
- package/corpus/core/src/templates/workspace-root/README.md +1 -1
- package/corpus/core/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/terminal/pty-server.ts +3 -38
- package/corpus/core/src/triggers/dispatcher.ts +1 -2
- package/corpus/templates/.retired/issues/package.json +7 -0
- package/corpus/templates/.retired/meeting-notes/package.json +7 -0
- package/corpus/templates/.retired/recruiting/package.json +7 -0
- package/corpus/templates/.retired/scheduling/package.json +7 -0
- package/corpus/templates/.retired/voice/package.json +7 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -18
- package/corpus/templates/analytics/app/global.css +15 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +7 -1
- package/corpus/templates/analytics/app/i18n-data.ts +71 -2
- package/corpus/templates/analytics/app/pages/Ask.tsx +1 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +120 -73
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -11
- package/corpus/templates/analytics/app/routes/catalog.tsx +33 -176
- package/corpus/templates/analytics/app/routes/team.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-06-26-dashboard-templates-are-tucked-into-settings-and-show-simple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-ask-tab-uses-a-softer-dark-gray-canvas-while-sidebar-cha.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-sessions-page-shows-a-single-page-title-instead-of-repea.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +37 -28
- package/corpus/templates/assets/app/routes/settings.tsx +65 -43
- package/corpus/templates/assets/app/routes/team.tsx +2 -10
- package/corpus/templates/brain/app/routes/settings.tsx +390 -358
- package/corpus/templates/brain/app/routes/team.tsx +2 -8
- package/corpus/templates/calendar/actions/db-connect.ts +5 -29
- package/corpus/templates/calendar/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +4 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/calendar/app/pages/Settings.tsx +304 -271
- package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -17
- package/corpus/templates/calendar/server/handlers/google-auth.ts +22 -9
- package/corpus/templates/calendar/server/lib/booking-emails.ts +1 -1
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +1 -1
- package/corpus/templates/calendar/server/lib/google-calendar.ts +48 -28
- package/corpus/templates/chat/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/chat/app/routes/settings.tsx +54 -54
- package/corpus/templates/chat/app/routes/team.tsx +2 -10
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +8 -0
- package/corpus/templates/clips/actions/invite-member.ts +1 -1
- package/corpus/templates/clips/actions/request-transcript.ts +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +325 -333
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +80 -40
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +629 -643
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +263 -158
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +10 -2
- package/corpus/templates/clips/changelog/2026-06-26-long-desktop-recordings-are-checkpointed-so-macos-finalizati.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-non-mac-desktop-recordings-wait-for-upload-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-recording-details-button-stays-at-the-far-right-on-small-screen.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-s3-compatible-storage-keys-now-save-securely-from-clips-sett.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-shared-clip-links-guide-agents-through-processing-transcripts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-agent-sidebar-now-slides-in-smoothly-without-duplicate-e.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-clip-details-sidebar-now-collapses-into-a-slide-out-pane.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +55 -3
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +217 -5
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +176 -5
- package/corpus/templates/clips/server/lib/public-agent-context.ts +31 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +60 -14
- package/corpus/templates/clips/server/lib/video-storage.ts +37 -9
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +5 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +54 -55
- package/corpus/templates/content/app/routes/_app.team.tsx +2 -28
- package/corpus/templates/content/server/lib/notion.ts +43 -11
- package/corpus/templates/content/server/routes/api/notion/auth-url.get.ts +2 -2
- package/corpus/templates/content/server/routes/api/notion/status.get.ts +3 -3
- package/corpus/templates/design/app/routes/settings.tsx +60 -38
- package/corpus/templates/design/app/routes/team.tsx +2 -10
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/dispatch/app/routes/settings.tsx +70 -55
- package/corpus/templates/dispatch/app/routes/team.tsx +5 -1
- package/corpus/templates/forms/actions/db-connect.ts +7 -36
- package/corpus/templates/forms/actions/navigate.ts +2 -2
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +8 -47
- package/corpus/templates/forms/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/forms/app/components/layout/Layout.tsx +42 -25
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -76
- package/corpus/templates/forms/app/global.css +9 -25
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +4 -4
- package/corpus/templates/forms/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +1 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/forms/app/lib/route-prewarm.ts +9 -8
- package/corpus/templates/forms/app/pages/AskPage.tsx +70 -0
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +74 -81
- package/corpus/templates/forms/app/root.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.ask.tsx +14 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +54 -54
- package/corpus/templates/forms/app/routes/_app.team.tsx +2 -9
- package/corpus/templates/forms/app/routes/_index.tsx +21 -130
- package/corpus/templates/forms/changelog/2026-06-26-ask-forms-opens-as-a-standard-app-tab-with-a-simpler-sidebar.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-26-forms-are-shown-in-a-tighter-row-list-with-a-denser-sidebar.md +6 -0
- package/corpus/templates/forms/shared/navigation.ts +4 -2
- package/corpus/templates/macros/app/routes/settings.tsx +54 -54
- package/corpus/templates/macros/app/routes/team.tsx +2 -10
- package/corpus/templates/mail/actions/helpers.ts +2 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +5 -5
- package/corpus/templates/mail/app/routes/team.tsx +3 -2
- package/corpus/templates/mail/server/handlers/emails.ts +3 -2
- package/corpus/templates/mail/server/handlers/google-auth.ts +19 -12
- package/corpus/templates/mail/server/lib/automation-engine.ts +3 -2
- package/corpus/templates/mail/server/lib/email-state.ts +2 -3
- package/corpus/templates/mail/server/lib/google-auth.ts +28 -11
- package/corpus/templates/mail/server/lib/jobs.ts +3 -2
- package/corpus/templates/mail/server/onboarding.ts +9 -6
- package/corpus/templates/mail/server/routes/api/attachments.get.ts +3 -3
- package/corpus/templates/plan/actions/request-plan-access.ts +1 -1
- package/corpus/templates/plan/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +56 -4
- package/corpus/templates/plan/app/global.css +8 -3
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +75 -73
- package/corpus/templates/plan/app/routes/team.tsx +2 -8
- package/corpus/templates/plan/changelog/2026-06-26-canvas-grid-panning-now-stays-smooth-and-fills-the-workspace.md +6 -0
- package/corpus/templates/plan/server/lib/comment-notifications.ts +1 -1
- package/corpus/templates/slides/actions/check-image-gen.ts +2 -1
- package/corpus/templates/slides/actions/db-connect.ts +7 -45
- package/corpus/templates/slides/actions/edit-image.ts +6 -3
- package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
- package/corpus/templates/slides/actions/generate-image.ts +2 -2
- package/corpus/templates/slides/actions/generate-slides-ai.ts +5 -3
- package/corpus/templates/slides/actions/image-gen-status.ts +4 -3
- package/corpus/templates/slides/actions/image-search.ts +6 -3
- package/corpus/templates/slides/actions/search-images.ts +6 -3
- package/corpus/templates/slides/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/slides/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/slides/app/routes/settings.tsx +54 -54
- package/corpus/templates/slides/app/routes/team.tsx +2 -12
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +9 -9
- package/corpus/templates/slides/server/handlers/image-gen.ts +5 -1
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +9 -1
- package/corpus/templates/slides/server/handlers/image-providers/index.ts +18 -8
- package/corpus/templates/slides/server/handlers/image-providers/openai.ts +10 -4
- package/corpus/templates/slides/server/handlers/image-providers/types.ts +1 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +59 -34
- package/corpus/templates/slides/server/register-secrets.ts +60 -0
- package/corpus/templates/videos/actions/db-connect.ts +7 -45
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/videos/app/components/Sidebar.tsx +1 -9
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -3
- package/corpus/templates/videos/app/routes/settings.tsx +54 -54
- package/corpus/templates/videos/app/routes/team.tsx +2 -8
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +8 -3
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +3 -4
- package/dist/cli/mcp.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +6 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +1 -0
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +20 -9
- package/dist/client/i18n.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -3
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +6 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +2 -2
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +27 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -0
- package/dist/client/settings/SettingsTabsPage.js +108 -0
- package/dist/client/settings/SettingsTabsPage.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/file-upload/index.d.ts +1 -1
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -1
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/registry.d.ts +1 -0
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +24 -6
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/file-upload/types.d.ts +6 -1
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +18 -18
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +8 -7
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +9 -9
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +10 -9
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +47 -13
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +6 -6
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +6 -5
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/types.d.ts +1 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/org/handlers.js +1 -1
- package/dist/org/handlers.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +4 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +17 -56
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +67 -153
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts +3 -9
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +37 -91
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/email-actions.d.ts +2 -3
- package/dist/server/email-actions.d.ts.map +1 -1
- package/dist/server/email-actions.js +3 -6
- package/dist/server/email-actions.js.map +1 -1
- package/dist/server/email.d.ts +3 -3
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +40 -19
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/scoped-key-storage.d.ts +22 -0
- package/dist/server/scoped-key-storage.d.ts.map +1 -0
- package/dist/server/scoped-key-storage.js +152 -0
- package/dist/server/scoped-key-storage.js.map +1 -0
- package/dist/shared/agent-env.d.ts +3 -3
- package/dist/shared/agent-env.d.ts.map +1 -1
- package/dist/shared/agent-env.js +3 -3
- package/dist/shared/agent-env.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -1
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/styles/agent-native.css +47 -3
- package/dist/templates/workspace-root/AGENTS.md +3 -2
- package/dist/templates/workspace-root/README.md +1 -1
- package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +3 -36
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/file-uploads.md +11 -4
- package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/docs/content/multi-app-workspace.md +3 -3
- package/docs/content/template-clips.md +14 -5
- package/package.json +1 -1
- package/src/templates/workspace-root/AGENTS.md +3 -2
- package/src/templates/workspace-root/README.md +1 -1
- package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/server/env-var-writes.ts +0 -16
- package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
- package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
- package/corpus/templates/mail/app/pages/Team.tsx +0 -17
- package/dist/server/env-var-writes.d.ts +0 -10
- package/dist/server/env-var-writes.d.ts.map +0 -1
- package/dist/server/env-var-writes.js +0 -18
- package/dist/server/env-var-writes.js.map +0 -1
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
encodeOAuthState,
|
|
10
10
|
decodeOAuthState,
|
|
11
11
|
resolveOAuthOwner,
|
|
12
|
+
resolveSecret,
|
|
12
13
|
createOAuthSession,
|
|
13
14
|
oauthCallbackResponse,
|
|
14
15
|
oauthDesktopExchangePage,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
setDesktopExchange,
|
|
17
18
|
setDesktopExchangeError,
|
|
18
19
|
safeReturnPath,
|
|
20
|
+
runWithRequestContext,
|
|
19
21
|
} from "@agent-native/core/server";
|
|
20
22
|
import {
|
|
21
23
|
defineEventHandler,
|
|
@@ -41,9 +43,15 @@ const GOOGLE_IDENTITY_SCOPES = [
|
|
|
41
43
|
"https://www.googleapis.com/auth/userinfo.profile",
|
|
42
44
|
];
|
|
43
45
|
|
|
44
|
-
function resolveCalendarOAuthCredentials() {
|
|
45
|
-
const
|
|
46
|
-
const clientSecret =
|
|
46
|
+
async function resolveCalendarOAuthCredentials(event: H3Event) {
|
|
47
|
+
const session = await getSession(event).catch(() => null);
|
|
48
|
+
const { clientId, clientSecret } = await runWithRequestContext(
|
|
49
|
+
{ userEmail: session?.email, orgId: session?.orgId },
|
|
50
|
+
async () => ({
|
|
51
|
+
clientId: await resolveSecret("GOOGLE_CLIENT_ID"),
|
|
52
|
+
clientSecret: await resolveSecret("GOOGLE_CLIENT_SECRET"),
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
47
55
|
if (!clientId || !clientSecret) return null;
|
|
48
56
|
return { clientId, clientSecret };
|
|
49
57
|
}
|
|
@@ -192,7 +200,7 @@ export const getGoogleAuthUrl = defineEventHandler(async (event: H3Event) => {
|
|
|
192
200
|
const flowId = desktop ? (q.flow_id as string) || undefined : undefined;
|
|
193
201
|
const calendarConnect = isCalendarConnectRequest(q, owner);
|
|
194
202
|
const credentials = calendarConnect
|
|
195
|
-
? resolveCalendarOAuthCredentials()
|
|
203
|
+
? await resolveCalendarOAuthCredentials(event)
|
|
196
204
|
: resolveGoogleSignInCredentials();
|
|
197
205
|
|
|
198
206
|
if (!credentials) {
|
|
@@ -200,7 +208,7 @@ export const getGoogleAuthUrl = defineEventHandler(async (event: H3Event) => {
|
|
|
200
208
|
return {
|
|
201
209
|
error: "missing_credentials",
|
|
202
210
|
message: calendarConnect
|
|
203
|
-
? "Google Calendar OAuth credentials are not configured.
|
|
211
|
+
? "Google Calendar OAuth credentials are not configured. Save GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in settings."
|
|
204
212
|
: "Google sign-in credentials are not configured. Set GOOGLE_SIGN_IN_CLIENT_ID and GOOGLE_SIGN_IN_CLIENT_SECRET.",
|
|
205
213
|
};
|
|
206
214
|
}
|
|
@@ -229,7 +237,7 @@ export const getGoogleAuthUrl = defineEventHandler(async (event: H3Event) => {
|
|
|
229
237
|
});
|
|
230
238
|
|
|
231
239
|
const url = calendarConnect
|
|
232
|
-
? getAuthUrl(undefined, redirectUri, state)
|
|
240
|
+
? await getAuthUrl(undefined, redirectUri, state, owner)
|
|
233
241
|
: `${GOOGLE_AUTH_URL}?${new URLSearchParams({
|
|
234
242
|
client_id: credentials.clientId,
|
|
235
243
|
redirect_uri: redirectUri,
|
|
@@ -364,12 +372,12 @@ export const getGoogleAddAccountUrl = defineEventHandler(
|
|
|
364
372
|
setResponseStatus(event, 401);
|
|
365
373
|
return { error: "Must be logged in to add an account" };
|
|
366
374
|
}
|
|
367
|
-
if (!
|
|
375
|
+
if (!(await resolveCalendarOAuthCredentials(event))) {
|
|
368
376
|
setResponseStatus(event, 422);
|
|
369
377
|
return {
|
|
370
378
|
error: "missing_credentials",
|
|
371
379
|
message:
|
|
372
|
-
"Google OAuth credentials are not configured.
|
|
380
|
+
"Google OAuth credentials are not configured. Save GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in settings.",
|
|
373
381
|
};
|
|
374
382
|
}
|
|
375
383
|
try {
|
|
@@ -393,7 +401,12 @@ export const getGoogleAddAccountUrl = defineEventHandler(
|
|
|
393
401
|
app: OAUTH_STATE_APP_ID,
|
|
394
402
|
flowId,
|
|
395
403
|
});
|
|
396
|
-
const url = getAuthUrl(
|
|
404
|
+
const url = await getAuthUrl(
|
|
405
|
+
undefined,
|
|
406
|
+
redirectUri,
|
|
407
|
+
state,
|
|
408
|
+
session.email,
|
|
409
|
+
);
|
|
397
410
|
if (q.redirect === "1") {
|
|
398
411
|
return oauthRedirectResponse(url);
|
|
399
412
|
}
|
|
@@ -4,7 +4,12 @@ import {
|
|
|
4
4
|
deleteOAuthTokens,
|
|
5
5
|
listOAuthAccountsByOwner,
|
|
6
6
|
} from "@agent-native/core/oauth-tokens";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
isOAuthConnected,
|
|
9
|
+
getOAuthAccounts,
|
|
10
|
+
resolveSecret,
|
|
11
|
+
runWithRequestContext,
|
|
12
|
+
} from "@agent-native/core/server";
|
|
8
13
|
|
|
9
14
|
import type {
|
|
10
15
|
CalendarEvent,
|
|
@@ -56,48 +61,59 @@ function optionalString(value: unknown): string | undefined {
|
|
|
56
61
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
function getOAuth2Credentials() {
|
|
60
|
-
const credentials =
|
|
64
|
+
async function getOAuth2Credentials(owner?: string) {
|
|
65
|
+
const credentials = (
|
|
66
|
+
await resolveGoogleProviderCredentialCandidates(owner)
|
|
67
|
+
)[0];
|
|
61
68
|
if (!credentials) {
|
|
62
69
|
throw new Error(
|
|
63
|
-
"GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be
|
|
70
|
+
"GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be saved in settings",
|
|
64
71
|
);
|
|
65
72
|
}
|
|
66
73
|
return credentials;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
function getOAuth2RefreshCredentials() {
|
|
70
|
-
const candidates = resolveGoogleProviderCredentialCandidates();
|
|
76
|
+
async function getOAuth2RefreshCredentials(owner?: string) {
|
|
77
|
+
const candidates = await resolveGoogleProviderCredentialCandidates(owner);
|
|
71
78
|
if (!candidates.length) {
|
|
72
79
|
throw new Error(
|
|
73
|
-
"GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be
|
|
80
|
+
"GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be saved in settings",
|
|
74
81
|
);
|
|
75
82
|
}
|
|
76
83
|
return candidates;
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
function readCredentialPair(
|
|
86
|
+
async function readCredentialPair(
|
|
80
87
|
clientIdKey: string,
|
|
81
88
|
clientSecretKey: string,
|
|
82
|
-
): GoogleOAuthCredentials | null {
|
|
83
|
-
const clientId =
|
|
84
|
-
|
|
89
|
+
): Promise<GoogleOAuthCredentials | null> {
|
|
90
|
+
const [clientId, clientSecret] = await Promise.all([
|
|
91
|
+
resolveSecret(clientIdKey),
|
|
92
|
+
resolveSecret(clientSecretKey),
|
|
93
|
+
]);
|
|
85
94
|
if (!clientId || !clientSecret) return null;
|
|
86
95
|
return { clientId, clientSecret };
|
|
87
96
|
}
|
|
88
97
|
|
|
89
|
-
function resolveGoogleProviderCredentialCandidates(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
async function resolveGoogleProviderCredentialCandidates(
|
|
99
|
+
owner?: string,
|
|
100
|
+
): Promise<GoogleOAuthCredentials[]> {
|
|
101
|
+
const resolve = async () => {
|
|
102
|
+
const primary = await readCredentialPair(
|
|
103
|
+
"GOOGLE_CLIENT_ID",
|
|
104
|
+
"GOOGLE_CLIENT_SECRET",
|
|
105
|
+
);
|
|
106
|
+
const legacy = await readCredentialPair(
|
|
107
|
+
"GOOGLE_LEGACY_CLIENT_ID",
|
|
108
|
+
"GOOGLE_LEGACY_CLIENT_SECRET",
|
|
109
|
+
);
|
|
110
|
+
if (!primary) return legacy ? [legacy] : [];
|
|
111
|
+
if (!legacy || legacy.clientId === primary.clientId) return [primary];
|
|
112
|
+
return [primary, legacy];
|
|
113
|
+
};
|
|
114
|
+
return owner
|
|
115
|
+
? runWithRequestContext({ userEmail: owner }, resolve)
|
|
116
|
+
: await resolve();
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
/**
|
|
@@ -356,7 +372,10 @@ async function getValidAccessToken(
|
|
|
356
372
|
}
|
|
357
373
|
try {
|
|
358
374
|
let lastRefreshError: any;
|
|
359
|
-
for (const {
|
|
375
|
+
for (const {
|
|
376
|
+
clientId,
|
|
377
|
+
clientSecret,
|
|
378
|
+
} of await getOAuth2RefreshCredentials(owner)) {
|
|
360
379
|
try {
|
|
361
380
|
const oauth2 = createOAuth2Client(clientId, clientSecret, "");
|
|
362
381
|
const newTokens = await oauth2.refreshToken(tokens.refresh_token);
|
|
@@ -396,12 +415,13 @@ async function getValidAccessToken(
|
|
|
396
415
|
return tokens.access_token;
|
|
397
416
|
}
|
|
398
417
|
|
|
399
|
-
export function getAuthUrl(
|
|
418
|
+
export async function getAuthUrl(
|
|
400
419
|
origin?: string,
|
|
401
420
|
redirectUri?: string,
|
|
402
421
|
state?: string,
|
|
403
|
-
|
|
404
|
-
|
|
422
|
+
owner?: string,
|
|
423
|
+
): Promise<string> {
|
|
424
|
+
const { clientId, clientSecret } = await getOAuth2Credentials(owner);
|
|
405
425
|
const uri =
|
|
406
426
|
redirectUri ||
|
|
407
427
|
(origin ? `${origin}/_agent-native/google/callback` : undefined);
|
|
@@ -420,7 +440,7 @@ export async function exchangeCode(
|
|
|
420
440
|
redirectUri?: string,
|
|
421
441
|
owner?: string,
|
|
422
442
|
): Promise<string> {
|
|
423
|
-
const { clientId, clientSecret } = getOAuth2Credentials();
|
|
443
|
+
const { clientId, clientSecret } = await getOAuth2Credentials(owner);
|
|
424
444
|
const uri =
|
|
425
445
|
redirectUri ||
|
|
426
446
|
(origin ? `${origin}/_agent-native/google/callback` : undefined);
|
|
@@ -10,7 +10,6 @@ const pageTitleKeys: Record<string, string> = {
|
|
|
10
10
|
"/": "navigation.chat",
|
|
11
11
|
"/observability": "navigation.observability",
|
|
12
12
|
"/settings": "navigation.settings",
|
|
13
|
-
"/team": "navigation.team",
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
function resolveTitle(pathname: string, t: (key: string) => string): string {
|
|
@@ -60,7 +60,7 @@ function viewForPath(pathname: string): string {
|
|
|
60
60
|
if (pathname.startsWith("/database")) return "database";
|
|
61
61
|
if (pathname.startsWith("/extensions")) return "extensions";
|
|
62
62
|
if (pathname.startsWith("/observability")) return "observability";
|
|
63
|
-
if (pathname.startsWith("/team")) return "
|
|
63
|
+
if (pathname.startsWith("/team")) return "settings";
|
|
64
64
|
return "chat";
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -76,8 +76,10 @@ function pathForView(view?: string): string {
|
|
|
76
76
|
return "/extensions";
|
|
77
77
|
case "observability":
|
|
78
78
|
return "/observability";
|
|
79
|
+
case "settings":
|
|
80
|
+
return "/settings";
|
|
79
81
|
case "team":
|
|
80
|
-
return "/team";
|
|
82
|
+
return "/settings#team";
|
|
81
83
|
default:
|
|
82
84
|
return "/";
|
|
83
85
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChangelogSettingsCard,
|
|
3
3
|
LanguagePicker,
|
|
4
|
+
SettingsTabsPage,
|
|
4
5
|
openAgentSettings,
|
|
5
6
|
useT,
|
|
6
7
|
} from "@agent-native/core/client";
|
|
7
|
-
import {
|
|
8
|
+
import { TeamPage } from "@agent-native/core/client/org";
|
|
8
9
|
|
|
9
10
|
import { useSetPageTitle } from "@/components/layout/HeaderActions";
|
|
10
11
|
import { Button } from "@/components/ui/button";
|
|
@@ -29,60 +30,59 @@ export default function SettingsRoute() {
|
|
|
29
30
|
useSetPageTitle(t("settings.title"));
|
|
30
31
|
|
|
31
32
|
return (
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</p>
|
|
40
|
-
</div>
|
|
33
|
+
<SettingsTabsPage
|
|
34
|
+
teamLabel={t("navigation.team")}
|
|
35
|
+
general={
|
|
36
|
+
<div className="mx-auto w-full max-w-3xl space-y-6">
|
|
37
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
38
|
+
{t("settings.description")}
|
|
39
|
+
</p>
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
<Card>
|
|
42
|
+
<CardHeader>
|
|
43
|
+
<CardTitle className="text-base">
|
|
44
|
+
{t("settings.languageTitle")}
|
|
45
|
+
</CardTitle>
|
|
46
|
+
<CardDescription>
|
|
47
|
+
{t("settings.languageDescription")}
|
|
48
|
+
</CardDescription>
|
|
49
|
+
</CardHeader>
|
|
50
|
+
<CardContent className="max-w-xs space-y-1.5">
|
|
51
|
+
<Label>{t("settings.languageLabel")}</Label>
|
|
52
|
+
<LanguagePicker label={t("settings.languageLabel")} />
|
|
53
|
+
</CardContent>
|
|
54
|
+
</Card>
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
</main>
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle className="text-base">
|
|
59
|
+
{t("settings.agentTitle")}
|
|
60
|
+
</CardTitle>
|
|
61
|
+
<CardDescription>
|
|
62
|
+
{t("settings.agentDescription")}
|
|
63
|
+
</CardDescription>
|
|
64
|
+
</CardHeader>
|
|
65
|
+
<CardContent>
|
|
66
|
+
<Button variant="outline" onClick={() => openAgentSettings()}>
|
|
67
|
+
{t("settings.openAgentSettings")}
|
|
68
|
+
</Button>
|
|
69
|
+
</CardContent>
|
|
70
|
+
</Card>
|
|
71
|
+
</div>
|
|
72
|
+
}
|
|
73
|
+
team={
|
|
74
|
+
<div className="mx-auto w-full max-w-3xl">
|
|
75
|
+
<TeamPage
|
|
76
|
+
showTitle={false}
|
|
77
|
+
createOrgDescription={t("pages.teamCreateOrgDescription")}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
}
|
|
81
|
+
whatsNew={
|
|
82
|
+
<div className="mx-auto w-full max-w-3xl">
|
|
83
|
+
<ChangelogSettingsCard markdown={changelog} />
|
|
84
|
+
</div>
|
|
85
|
+
}
|
|
86
|
+
/>
|
|
87
87
|
);
|
|
88
88
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TeamPage } from "@agent-native/core/client/org";
|
|
1
|
+
import { Navigate } from "react-router";
|
|
3
2
|
|
|
4
|
-
import { useSetPageTitle } from "@/components/layout/HeaderActions";
|
|
5
3
|
import { APP_TITLE } from "@/lib/app-config";
|
|
6
4
|
|
|
7
5
|
export function meta() {
|
|
@@ -9,11 +7,5 @@ export function meta() {
|
|
|
9
7
|
}
|
|
10
8
|
|
|
11
9
|
export default function TeamRoute() {
|
|
12
|
-
|
|
13
|
-
useSetPageTitle(t("pages.teamTitle"));
|
|
14
|
-
return (
|
|
15
|
-
<main className="mx-auto w-full max-w-3xl px-4 py-6 sm:px-6 sm:py-10">
|
|
16
|
-
<TeamPage createOrgDescription={t("pages.teamCreateOrgDescription")} />
|
|
17
|
-
</main>
|
|
18
|
-
);
|
|
10
|
+
return <Navigate to="/settings#team" replace />;
|
|
19
11
|
}
|
|
@@ -11,7 +11,7 @@ description: >-
|
|
|
11
11
|
|
|
12
12
|
## Rule
|
|
13
13
|
|
|
14
|
-
Every AI feature in Clips goes through the agent chat unless it is the narrow media-pipeline exception below. The UI and server should not add broad shadow agents or inline chat workflows. **Exception:** transcription. Transcription takes audio, not prompts — the `request-transcript` action calls the transcription API directly. Provider priority for transcription: **native** first (browser Web Speech API
|
|
14
|
+
Every AI feature in Clips goes through the agent chat unless it is the narrow media-pipeline exception below. The UI and server should not add broad shadow agents or inline chat workflows. **Exception:** transcription. Transcription takes audio, not prompts — the `request-transcript` action calls the transcription API directly. Provider priority for transcription: **native** first (browser Web Speech API, desktop local Whisper/macOS SFSpeech when available, and desktop Web Speech fallback on non-mac, saved via `save-browser-transcript`, no key required) → **cloud fallback** when native text is missing: **Builder.io managed** Gemini (via `BUILDER_PRIVATE_KEY` or a connected Builder account, no extra key needed) → **Groq** `whisper-large-v3-turbo` via `GROQ_API_KEY` (fast, ~$0.04/hr). Clips never routes recording/meeting audio to OpenAI for transcription.
|
|
15
15
|
|
|
16
16
|
Builder.io is the primary setup path: it brings managed AI credits, object
|
|
17
17
|
storage, uploads, and transcription together. Bring-your-own-key setup belongs
|
|
@@ -99,7 +99,7 @@ Transcription takes an audio file and returns text + segments. That's not a prom
|
|
|
99
99
|
|
|
100
100
|
**Provider priority:**
|
|
101
101
|
|
|
102
|
-
1. **Native (highest priority).** The browser's Web Speech API
|
|
102
|
+
1. **Native (highest priority).** The browser's Web Speech API, desktop local Whisper/macOS SFSpeech when available, and desktop Web Speech fallback on non-mac run during recording and save results via `save-browser-transcript`. This gives an instant transcript with no API key when the local/browser recognizer is available. When `request-transcript` runs afterward, it preserves the ready native transcript and only falls back to a cloud provider if native text is missing.
|
|
103
103
|
2. **Cloud fallback — Builder.io managed (Gemini).** When a Builder account is connected (`BUILDER_PRIVATE_KEY` or per-user OAuth, no separate API key needed), `request-transcript` calls `transcribeWithBuilder()`, which routes audio to Builder.io's managed Gemini transcription. Returns text plus timestamped segments.
|
|
104
104
|
3. **Cloud fallback — Groq Whisper.** `GROQ_API_KEY` → `https://api.groq.com/openai/v1/audio/transcriptions`, model `whisper-large-v3-turbo`. Fast (~$0.04/hour of audio) Whisper-compatible speech-to-text used when Builder is unavailable.
|
|
105
105
|
|
|
@@ -107,6 +107,11 @@ Clips never routes recording/meeting audio to OpenAI for transcription. (Groq's
|
|
|
107
107
|
|
|
108
108
|
If no native transcript exists and no cloud fallback is available (no Builder connection and no Groq key), the action writes `status="failed"` so the UI can show a friendly prompt.
|
|
109
109
|
|
|
110
|
+
If Builder transcription fails because credits are exhausted, explain that
|
|
111
|
+
Builder.io credits/upgrade or a Groq key are the supported speech-to-text
|
|
112
|
+
fallbacks. Generic OpenAI or Anthropic chat keys power chat, but they do not
|
|
113
|
+
transcribe Clips recordings.
|
|
114
|
+
|
|
110
115
|
### Secret registration
|
|
111
116
|
|
|
112
117
|
Builder transcription needs no app-specific key (the connected Builder.io account or `BUILDER_PRIVATE_KEY` carries the grant). The only transcription API key declared in `server/register-secrets.ts` is the optional Groq key, so it appears in the agent sidebar settings UI:
|
|
@@ -30,7 +30,7 @@ Some recordings are linked to a meeting — when `meeting_id` is non-null on the
|
|
|
30
30
|
3. **Create row.** As soon as the stream is granted, call `create-recording` to insert the row with `status: "uploading"` and a pre-generated id. That id is used for every subsequent chunk upload.
|
|
31
31
|
4. **Record.** Start a `MediaRecorder` with `mimeType: "video/webm;codecs=vp9,opus"` (fallback to vp8, then browser default). Use `timeslice: 2000` so chunks arrive every 2s.
|
|
32
32
|
5. **Upload each chunk.** `ondataavailable` POSTs the chunk bytes to `/api/uploads/chunk` with headers `X-Recording-Id` and `X-Chunk-Index`. Don't retry inline — buffer failed chunks in `IndexedDB` and let a background worker re-send.
|
|
33
|
-
6. **Live transcription.** Alongside the MediaRecorder, `useLiveTranscription` runs the Web Speech API to accumulate transcript text in real time. On stop, the client calls `save-browser-transcript` to persist the result immediately — no API key needed.
|
|
33
|
+
6. **Live transcription.** Alongside the MediaRecorder, `useLiveTranscription` runs the Web Speech API to accumulate transcript text in real time. On stop, the client calls `save-browser-transcript` to persist the result immediately — no API key needed. Desktop recordings use local Whisper/macOS speech first when available, and fall back to Web Speech in the webview on non-mac before relying on upload transcription.
|
|
34
34
|
7. **Finalize.** On stop, send the final chunk to `/api/uploads/:id/chunk?isFinal=1`. The route calls `finalize-recording`, which stitches chunks, uploads the finished media when storage is configured, transitions `status` to `ready`, then kicks off `request-transcript` for higher-quality output (see `ai-video-tools`).
|
|
35
35
|
8. **Navigate.** Once the row is `ready` the UI navigates to `/r/:id`.
|
|
36
36
|
|
|
@@ -173,6 +173,13 @@ These endpoints follow the same access model as `/api/public-recording`:
|
|
|
173
173
|
- Password-protected clips require `password=<pw>` once; successful JSON
|
|
174
174
|
responses include short-lived tokenized links so the plaintext password is not
|
|
175
175
|
copied into downstream agent prompts, browser history, or logs.
|
|
176
|
+
- If the context or transcript response reports `transcript.status` as
|
|
177
|
+
`"pending"`, wait 15-30 seconds and retry the context/transcript URL a few
|
|
178
|
+
times before falling back to frames or telling the user no transcript exists.
|
|
179
|
+
- If transcription failed because Builder transcription credits are exhausted,
|
|
180
|
+
tell the user to upgrade or connect Builder.io credits, or configure a Groq
|
|
181
|
+
key for backup speech-to-text. Generic OpenAI or Anthropic chat keys do not
|
|
182
|
+
transcribe Clips recordings.
|
|
176
183
|
- Frame extraction must use the checked recording media path and must not expose
|
|
177
184
|
raw provider URLs.
|
|
178
185
|
|
|
@@ -52,6 +52,14 @@ Detailed media, meeting, dictation, editing, and sharing rules live in
|
|
|
52
52
|
segments; `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` for a screen
|
|
53
53
|
frame at a timestamp. Password-protected clips require the password once to
|
|
54
54
|
mint a short-lived token returned inside agent-context links.
|
|
55
|
+
- If public agent context or transcript APIs report `transcript.status` as
|
|
56
|
+
`"pending"`, wait 15-30 seconds and retry the context/transcript URL a few
|
|
57
|
+
times, especially for long recordings. Do not pivot straight to frames or tell
|
|
58
|
+
the user there is no transcript until the retry budget is exhausted.
|
|
59
|
+
- If transcription failed because Builder transcription credits are exhausted,
|
|
60
|
+
tell the user that clearly and point them to Builder.io credits/upgrade or a
|
|
61
|
+
Groq key for backup speech-to-text. Generic OpenAI or Anthropic chat keys do
|
|
62
|
+
not transcribe Clips recordings.
|
|
55
63
|
- Slack unfurls use `/api/slack/unfurl` for `link_shared` events and only
|
|
56
64
|
return playable `chat.unfurl` video blocks for ready public clips with no
|
|
57
65
|
password, no expiry hit, and no archive/trash marker. Private, org-only,
|
|
@@ -1008,7 +1008,7 @@ export default defineAction({
|
|
|
1008
1008
|
} catch (err) {
|
|
1009
1009
|
const reason = (err as Error).message;
|
|
1010
1010
|
const details = serializeError(err);
|
|
1011
|
-
if (reason.includes("credits exhausted")) {
|
|
1011
|
+
if (reason.toLowerCase().includes("credits exhausted")) {
|
|
1012
1012
|
const preserved = await preserveReadyTranscriptIfAvailable({
|
|
1013
1013
|
db,
|
|
1014
1014
|
recordingId: args.recordingId,
|