@agent-native/core 0.75.5 → 0.76.1
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 +48 -0
- package/corpus/core/docs/AGENTS.md +1 -0
- package/corpus/core/docs/content/client.md +15 -0
- package/corpus/core/docs/content/internationalization.md +145 -0
- package/corpus/core/docs/content/locales/ar-SA/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/de-DE/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/es-ES/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/fr-FR/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/hi-IN/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/ja-JP/internationalization.md +114 -0
- package/corpus/core/docs/content/locales/ko-KR/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/pt-BR/internationalization.md +102 -0
- package/corpus/core/docs/content/locales/zh-CN/internationalization.md +102 -0
- package/corpus/core/docs/content/skills-guide.md +19 -18
- package/corpus/core/package.json +7 -1
- package/corpus/core/src/agent/durable-background.ts +38 -2
- package/corpus/core/src/agent/production-agent.ts +54 -0
- package/corpus/core/src/agent/run-manager.ts +27 -0
- package/corpus/core/src/agent/run-store.ts +185 -4
- package/corpus/core/src/client/CommandMenu.tsx +16 -0
- package/corpus/core/src/client/app-providers.tsx +26 -1
- package/corpus/core/src/client/i18n.tsx +605 -0
- package/corpus/core/src/client/index.ts +28 -0
- package/corpus/core/src/index.browser.ts +25 -0
- package/corpus/core/src/localization/actions/get-localization-preference.ts +23 -0
- package/corpus/core/src/localization/actions/set-localization-preference.ts +30 -0
- package/corpus/core/src/localization/index.ts +2 -0
- package/corpus/core/src/localization/server.ts +131 -0
- package/corpus/core/src/localization/shared.ts +163 -0
- package/corpus/core/src/server/action-discovery.ts +8 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +71 -0
- package/corpus/core/src/server/auth.ts +13 -0
- package/corpus/core/src/server/index.ts +8 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
- package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/core/src/templates/default/AGENTS.md +16 -15
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +29 -0
- package/corpus/core/src/templates/default/app/i18n/index.ts +13 -0
- package/corpus/core/src/templates/default/app/root.tsx +20 -1
- package/corpus/core/src/templates/default/app/routes/_index.tsx +24 -9
- package/corpus/core/src/templates/default/app/routes/settings.tsx +67 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/core/src/vite/action-types-plugin.ts +10 -0
- package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +12 -12
- package/corpus/templates/analytics/app/components/layout/Header.tsx +18 -15
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
- package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +9 -3
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +28 -26
- package/corpus/templates/analytics/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/analytics/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/analytics/app/i18n/en-US.ts +3 -0
- package/corpus/templates/analytics/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/analytics/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/analytics/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/analytics/app/i18n/index.ts +31 -0
- package/corpus/templates/analytics/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/analytics/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/analytics/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/analytics/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/analytics/app/i18n-data.ts +433 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +50 -16
- package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +2 -2
- package/corpus/templates/analytics/app/root.tsx +14 -1
- package/corpus/templates/analytics/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +17 -8
- package/corpus/templates/assets/app/components/layout/Layout.tsx +10 -6
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +40 -23
- package/corpus/templates/assets/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/assets/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/assets/app/i18n/en-US.ts +3 -0
- package/corpus/templates/assets/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/assets/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/assets/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/assets/app/i18n/index.ts +31 -0
- package/corpus/templates/assets/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/assets/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/assets/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/assets/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/assets/app/i18n-data.ts +668 -0
- package/corpus/templates/assets/app/root.tsx +40 -15
- package/corpus/templates/assets/app/routes/_index.tsx +9 -10
- package/corpus/templates/assets/app/routes/settings.tsx +37 -6
- package/corpus/templates/assets/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +12 -8
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +23 -12
- package/corpus/templates/brain/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/brain/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/brain/app/i18n/en-US.ts +3 -0
- package/corpus/templates/brain/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/brain/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/brain/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/brain/app/i18n/index.ts +31 -0
- package/corpus/templates/brain/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/brain/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/brain/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/brain/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/brain/app/i18n-data.ts +624 -0
- package/corpus/templates/brain/app/root.tsx +27 -12
- package/corpus/templates/brain/app/routes/knowledge.tsx +6 -6
- package/corpus/templates/brain/app/routes/ops.tsx +4 -4
- package/corpus/templates/brain/app/routes/search.tsx +4 -4
- package/corpus/templates/brain/app/routes/settings.tsx +48 -11
- package/corpus/templates/brain/app/routes/sources.tsx +3 -3
- package/corpus/templates/brain/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/brain/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +2 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +16 -9
- package/corpus/templates/calendar/app/i18n/ar-SA.ts +57 -0
- package/corpus/templates/calendar/app/i18n/de-DE.ts +58 -0
- package/corpus/templates/calendar/app/i18n/en-US.ts +57 -0
- package/corpus/templates/calendar/app/i18n/es-ES.ts +58 -0
- package/corpus/templates/calendar/app/i18n/fr-FR.ts +58 -0
- package/corpus/templates/calendar/app/i18n/hi-IN.ts +57 -0
- package/corpus/templates/calendar/app/i18n/index.ts +31 -0
- package/corpus/templates/calendar/app/i18n/ja-JP.ts +58 -0
- package/corpus/templates/calendar/app/i18n/ko-KR.ts +57 -0
- package/corpus/templates/calendar/app/i18n/pt-BR.ts +57 -0
- package/corpus/templates/calendar/app/i18n/zh-CN.ts +57 -0
- package/corpus/templates/calendar/app/i18n-data.ts +516 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +2 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +63 -28
- package/corpus/templates/calendar/app/root.tsx +78 -7
- package/corpus/templates/calendar/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/calendar/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/chat/app/components/layout/Header.tsx +17 -11
- package/corpus/templates/chat/app/components/layout/Layout.tsx +12 -8
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +47 -18
- package/corpus/templates/chat/app/i18n/ar-SA.ts +62 -0
- package/corpus/templates/chat/app/i18n/de-DE.ts +63 -0
- package/corpus/templates/chat/app/i18n/en-US.ts +63 -0
- package/corpus/templates/chat/app/i18n/es-ES.ts +63 -0
- package/corpus/templates/chat/app/i18n/fr-FR.ts +63 -0
- package/corpus/templates/chat/app/i18n/hi-IN.ts +63 -0
- package/corpus/templates/chat/app/i18n/index.ts +31 -0
- package/corpus/templates/chat/app/i18n/ja-JP.ts +63 -0
- package/corpus/templates/chat/app/i18n/ko-KR.ts +63 -0
- package/corpus/templates/chat/app/i18n/pt-BR.ts +63 -0
- package/corpus/templates/chat/app/i18n/zh-CN.ts +61 -0
- package/corpus/templates/chat/app/i18n-data.ts +475 -0
- package/corpus/templates/chat/app/root.tsx +18 -5
- package/corpus/templates/chat/app/routes/_index.tsx +9 -8
- package/corpus/templates/chat/app/routes/settings.tsx +86 -0
- package/corpus/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/clips/app/components/layout/Header.tsx +23 -17
- package/corpus/templates/clips/app/components/library/empty-state.tsx +10 -34
- package/corpus/templates/clips/app/components/library/library-layout.tsx +45 -34
- package/corpus/templates/clips/app/i18n/ar-SA.ts +182 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +184 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +179 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +183 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +184 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +180 -0
- package/corpus/templates/clips/app/i18n/index.ts +41 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +180 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +178 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +183 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +173 -0
- package/corpus/templates/clips/app/root.tsx +104 -10
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +154 -95
- package/corpus/templates/clips/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-clips-now-includes-a-language-picker-and-simplified-chinese-ui.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/content/app/components/EmptyState.tsx +7 -5
- package/corpus/templates/content/app/components/ThemeToggle.tsx +4 -2
- package/corpus/templates/content/app/components/layout/Header.tsx +2 -0
- package/corpus/templates/content/app/components/layout/Layout.tsx +8 -7
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +41 -1
- package/corpus/templates/content/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/content/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/content/app/i18n/en-US.ts +3 -0
- package/corpus/templates/content/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/content/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/content/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/content/app/i18n/index.ts +31 -0
- package/corpus/templates/content/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/content/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/content/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/content/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/content/app/i18n-data.ts +490 -0
- package/corpus/templates/content/app/root.tsx +110 -23
- package/corpus/templates/content/app/routes/_app.settings.tsx +84 -0
- package/corpus/templates/content/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/content/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +16 -8
- package/corpus/templates/design/app/components/layout/Layout.tsx +8 -6
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +25 -9
- package/corpus/templates/design/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/design/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/design/app/i18n/en-US.ts +3 -0
- package/corpus/templates/design/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/design/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/design/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/design/app/i18n/index.ts +31 -0
- package/corpus/templates/design/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/design/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/design/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/design/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +350 -0
- package/corpus/templates/design/app/root.tsx +40 -15
- package/corpus/templates/design/app/routes/settings.tsx +43 -0
- package/corpus/templates/design/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/design/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/dispatch/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/en-US.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/index.ts +31 -0
- package/corpus/templates/dispatch/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/dispatch/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +267 -0
- package/corpus/templates/dispatch/app/root.tsx +18 -4
- package/corpus/templates/dispatch/app/routes/settings.tsx +86 -0
- package/corpus/templates/dispatch/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/forms/app/components/layout/Header.tsx +16 -9
- package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -4
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +34 -17
- package/corpus/templates/forms/app/i18n/ar-SA.ts +58 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +59 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +59 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +59 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +59 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +59 -0
- package/corpus/templates/forms/app/i18n/index.ts +31 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +59 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +59 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +59 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +56 -0
- package/corpus/templates/forms/app/root.tsx +65 -16
- package/corpus/templates/forms/app/routes/_app.settings.tsx +85 -0
- package/corpus/templates/forms/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +29 -17
- package/corpus/templates/macros/app/components/layout/Header.tsx +16 -10
- package/corpus/templates/macros/app/i18n/ar-SA.ts +54 -0
- package/corpus/templates/macros/app/i18n/de-DE.ts +55 -0
- package/corpus/templates/macros/app/i18n/en-US.ts +55 -0
- package/corpus/templates/macros/app/i18n/es-ES.ts +55 -0
- package/corpus/templates/macros/app/i18n/fr-FR.ts +55 -0
- package/corpus/templates/macros/app/i18n/hi-IN.ts +55 -0
- package/corpus/templates/macros/app/i18n/index.ts +31 -0
- package/corpus/templates/macros/app/i18n/ja-JP.ts +55 -0
- package/corpus/templates/macros/app/i18n/ko-KR.ts +55 -0
- package/corpus/templates/macros/app/i18n/pt-BR.ts +55 -0
- package/corpus/templates/macros/app/i18n/zh-CN.ts +53 -0
- package/corpus/templates/macros/app/root.tsx +65 -15
- package/corpus/templates/macros/app/routes/settings.tsx +85 -0
- package/corpus/templates/macros/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/macros/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +9 -4
- package/corpus/templates/mail/app/i18n/ar-SA.ts +33 -0
- package/corpus/templates/mail/app/i18n/de-DE.ts +33 -0
- package/corpus/templates/mail/app/i18n/en-US.ts +32 -0
- package/corpus/templates/mail/app/i18n/es-ES.ts +33 -0
- package/corpus/templates/mail/app/i18n/fr-FR.ts +33 -0
- package/corpus/templates/mail/app/i18n/hi-IN.ts +32 -0
- package/corpus/templates/mail/app/i18n/index.ts +31 -0
- package/corpus/templates/mail/app/i18n/ja-JP.ts +32 -0
- package/corpus/templates/mail/app/i18n/ko-KR.ts +33 -0
- package/corpus/templates/mail/app/i18n/pt-BR.ts +34 -0
- package/corpus/templates/mail/app/i18n/zh-CN.ts +32 -0
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +67 -13
- package/corpus/templates/mail/app/root.tsx +20 -0
- package/corpus/templates/mail/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/mail/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/plan/app/components/layout/Header.tsx +19 -12
- package/corpus/templates/plan/app/components/layout/Layout.tsx +11 -7
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +41 -28
- package/corpus/templates/plan/app/i18n/ar-SA.ts +77 -0
- package/corpus/templates/plan/app/i18n/de-DE.ts +78 -0
- package/corpus/templates/plan/app/i18n/en-US.ts +78 -0
- package/corpus/templates/plan/app/i18n/es-ES.ts +78 -0
- package/corpus/templates/plan/app/i18n/fr-FR.ts +78 -0
- package/corpus/templates/plan/app/i18n/hi-IN.ts +78 -0
- package/corpus/templates/plan/app/i18n/index.ts +31 -0
- package/corpus/templates/plan/app/i18n/ja-JP.ts +79 -0
- package/corpus/templates/plan/app/i18n/ko-KR.ts +77 -0
- package/corpus/templates/plan/app/i18n/pt-BR.ts +78 -0
- package/corpus/templates/plan/app/i18n/zh-CN.ts +74 -0
- package/corpus/templates/plan/app/root.tsx +45 -8
- package/corpus/templates/plan/app/routes/settings.tsx +86 -0
- package/corpus/templates/plan/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/slides/app/components/layout/Header.tsx +23 -11
- package/corpus/templates/slides/app/components/layout/Layout.tsx +7 -6
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +23 -11
- package/corpus/templates/slides/app/i18n/ar-SA.ts +54 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +56 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +55 -0
- package/corpus/templates/slides/app/i18n/es-ES.ts +55 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +55 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +55 -0
- package/corpus/templates/slides/app/i18n/index.ts +31 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +55 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +55 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +55 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +53 -0
- package/corpus/templates/slides/app/root.tsx +50 -8
- package/corpus/templates/slides/app/routes/settings.tsx +85 -0
- package/corpus/templates/slides/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +14 -9
- package/corpus/templates/videos/app/components/Sidebar.tsx +16 -9
- package/corpus/templates/videos/app/components/StudioHeader.tsx +12 -8
- package/corpus/templates/videos/app/components/layout/Header.tsx +21 -15
- package/corpus/templates/videos/app/components/layout/Layout.tsx +10 -7
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +21 -6
- package/corpus/templates/videos/app/i18n/ar-SA.ts +73 -0
- package/corpus/templates/videos/app/i18n/de-DE.ts +75 -0
- package/corpus/templates/videos/app/i18n/en-US.ts +74 -0
- package/corpus/templates/videos/app/i18n/es-ES.ts +75 -0
- package/corpus/templates/videos/app/i18n/fr-FR.ts +75 -0
- package/corpus/templates/videos/app/i18n/hi-IN.ts +74 -0
- package/corpus/templates/videos/app/i18n/index.ts +31 -0
- package/corpus/templates/videos/app/i18n/ja-JP.ts +74 -0
- package/corpus/templates/videos/app/i18n/ko-KR.ts +74 -0
- package/corpus/templates/videos/app/i18n/pt-BR.ts +75 -0
- package/corpus/templates/videos/app/i18n/zh-CN.ts +72 -0
- package/corpus/templates/videos/app/pages/Index.tsx +11 -9
- package/corpus/templates/videos/app/root.tsx +45 -7
- package/corpus/templates/videos/app/routes/settings.tsx +85 -0
- package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
- package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
- package/dist/agent/durable-background.d.ts +15 -0
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +28 -2
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +34 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +8 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +18 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +99 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +155 -4
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +3 -0
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +9 -0
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/app-providers.d.ts +8 -1
- package/dist/client/app-providers.d.ts.map +1 -1
- package/dist/client/app-providers.js +7 -5
- package/dist/client/app-providers.js.map +1 -1
- package/dist/client/i18n.d.ts +54 -0
- package/dist/client/i18n.d.ts.map +1 -0
- package/dist/client/i18n.js +354 -0
- package/dist/client/i18n.js.map +1 -0
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/localization/actions/get-localization-preference.d.ts +4 -0
- package/dist/localization/actions/get-localization-preference.d.ts.map +1 -0
- package/dist/localization/actions/get-localization-preference.js +16 -0
- package/dist/localization/actions/get-localization-preference.js.map +1 -0
- package/dist/localization/actions/set-localization-preference.d.ts +6 -0
- package/dist/localization/actions/set-localization-preference.d.ts.map +1 -0
- package/dist/localization/actions/set-localization-preference.js +24 -0
- package/dist/localization/actions/set-localization-preference.js.map +1 -0
- package/dist/localization/index.d.ts +3 -0
- package/dist/localization/index.d.ts.map +1 -0
- package/dist/localization/index.js +3 -0
- package/dist/localization/index.js.map +1 -0
- package/dist/localization/server.d.ts +25 -0
- package/dist/localization/server.d.ts.map +1 -0
- package/dist/localization/server.js +69 -0
- package/dist/localization/server.js.map +1 -0
- package/dist/localization/shared.d.ts +25 -0
- package/dist/localization/shared.d.ts.map +1 -0
- package/dist/localization/shared.js +134 -0
- package/dist/localization/shared.js.map +1 -0
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +58 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +12 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/dist/templates/default/AGENTS.md +16 -15
- package/dist/templates/default/app/i18n/en-US.ts +29 -0
- package/dist/templates/default/app/i18n/index.ts +13 -0
- package/dist/templates/default/app/root.tsx +20 -1
- package/dist/templates/default/app/routes/_index.tsx +24 -9
- package/dist/templates/default/app/routes/settings.tsx +67 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +8 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/AGENTS.md +1 -0
- package/docs/content/client.md +15 -0
- package/docs/content/internationalization.md +145 -0
- package/docs/content/locales/ar-SA/internationalization.md +102 -0
- package/docs/content/locales/de-DE/internationalization.md +102 -0
- package/docs/content/locales/es-ES/internationalization.md +102 -0
- package/docs/content/locales/fr-FR/internationalization.md +102 -0
- package/docs/content/locales/hi-IN/internationalization.md +102 -0
- package/docs/content/locales/ja-JP/internationalization.md +114 -0
- package/docs/content/locales/ko-KR/internationalization.md +102 -0
- package/docs/content/locales/pt-BR/internationalization.md +102 -0
- package/docs/content/locales/zh-CN/internationalization.md +102 -0
- package/docs/content/skills-guide.md +19 -18
- package/package.json +7 -1
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
- package/src/templates/default/AGENTS.md +16 -15
- package/src/templates/default/app/i18n/en-US.ts +29 -0
- package/src/templates/default/app/i18n/index.ts +13 -0
- package/src/templates/default/app/root.tsx +20 -1
- package/src/templates/default/app/routes/_index.tsx +24 -9
- package/src/templates/default/app/routes/settings.tsx +67 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
|
@@ -285,8 +285,37 @@ export type ProcessRunPreparation =
|
|
|
285
285
|
status: number;
|
|
286
286
|
/** Error payload. */
|
|
287
287
|
error: string;
|
|
288
|
+
/**
|
|
289
|
+
* The run id parsed from the body, when present. Carried even on failure
|
|
290
|
+
* so the route can RECORD the auth/validation failure ONTO the run
|
|
291
|
+
* (diag_stage) before returning the error status — otherwise a 401/503 in
|
|
292
|
+
* the unreadable Netlify background function would leave the run to time
|
|
293
|
+
* out with no clue why. Null when no run id could be parsed.
|
|
294
|
+
*/
|
|
295
|
+
runId: string | null;
|
|
288
296
|
};
|
|
289
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Parse the run id from a `_process-run` request body without authenticating.
|
|
300
|
+
* Mirrors the precedence in `prepareProcessRunRequest` (marker.runId, then
|
|
301
|
+
* top-level taskId). Returns null when neither is a usable string. Used so the
|
|
302
|
+
* route can attach a diagnostic to the run even on an auth/validation failure.
|
|
303
|
+
*/
|
|
304
|
+
export function extractProcessRunId(body: unknown): string | null {
|
|
305
|
+
if (!body || typeof body !== "object") return null;
|
|
306
|
+
const record = body as Record<string, unknown>;
|
|
307
|
+
const marker = record[AGENT_CHAT_BACKGROUND_RUN_FIELD] as
|
|
308
|
+
| { runId?: unknown }
|
|
309
|
+
| undefined;
|
|
310
|
+
if (marker && typeof marker.runId === "string" && marker.runId) {
|
|
311
|
+
return marker.runId;
|
|
312
|
+
}
|
|
313
|
+
if (typeof record.taskId === "string" && record.taskId) {
|
|
314
|
+
return record.taskId;
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
290
319
|
/**
|
|
291
320
|
* Pure, transport-agnostic core of the `_process-run` route: validate the body,
|
|
292
321
|
* authenticate the HMAC self-dispatch, and produce the body the re-entered
|
|
@@ -308,7 +337,12 @@ export function prepareProcessRunRequest(
|
|
|
308
337
|
authHeader: string | undefined,
|
|
309
338
|
): ProcessRunPreparation {
|
|
310
339
|
if (!body || typeof body !== "object") {
|
|
311
|
-
return {
|
|
340
|
+
return {
|
|
341
|
+
ok: false,
|
|
342
|
+
status: 400,
|
|
343
|
+
error: "Invalid request body",
|
|
344
|
+
runId: null,
|
|
345
|
+
};
|
|
312
346
|
}
|
|
313
347
|
const record = body as Record<string, unknown>;
|
|
314
348
|
const marker = record[AGENT_CHAT_BACKGROUND_RUN_FIELD] as
|
|
@@ -321,7 +355,7 @@ export function prepareProcessRunRequest(
|
|
|
321
355
|
? (record.taskId as string)
|
|
322
356
|
: "";
|
|
323
357
|
if (!runId) {
|
|
324
|
-
return { ok: false, status: 400, error: "runId required" };
|
|
358
|
+
return { ok: false, status: 400, error: "runId required", runId: null };
|
|
325
359
|
}
|
|
326
360
|
|
|
327
361
|
if (hasConfiguredA2ASecret()) {
|
|
@@ -331,6 +365,7 @@ export function prepareProcessRunRequest(
|
|
|
331
365
|
ok: false,
|
|
332
366
|
status: 401,
|
|
333
367
|
error: "Invalid or expired processor token",
|
|
368
|
+
runId,
|
|
334
369
|
};
|
|
335
370
|
}
|
|
336
371
|
} else if (isA2AProductionRuntime()) {
|
|
@@ -339,6 +374,7 @@ export function prepareProcessRunRequest(
|
|
|
339
374
|
status: 503,
|
|
340
375
|
error:
|
|
341
376
|
"Agent chat background processor not configured — set A2A_SECRET on this deployment.",
|
|
377
|
+
runId,
|
|
342
378
|
};
|
|
343
379
|
}
|
|
344
380
|
|
|
@@ -109,6 +109,8 @@ import {
|
|
|
109
109
|
updateRunHeartbeat,
|
|
110
110
|
updateRunStatusIfRunning,
|
|
111
111
|
claimBackgroundRun,
|
|
112
|
+
recordRunDiagnostic,
|
|
113
|
+
RUN_DIAG_STAGE,
|
|
112
114
|
} from "./run-store.js";
|
|
113
115
|
import {
|
|
114
116
|
classifyToolCallJournal,
|
|
@@ -4599,6 +4601,30 @@ export function createProductionAgentHandler(
|
|
|
4599
4601
|
isBackgroundWorker || baseHandleRunComplete
|
|
4600
4602
|
? async (run: ActiveRun) => {
|
|
4601
4603
|
try {
|
|
4604
|
+
// DIAGNOSTIC: a background worker that completed in an errored
|
|
4605
|
+
// state threw inside the loop. Record it (with the last error
|
|
4606
|
+
// event's message when available) so the failure cause is
|
|
4607
|
+
// readable from the client. Skipped for clean completions and for
|
|
4608
|
+
// recoverable soft-timeout boundaries (those chain a continuation
|
|
4609
|
+
// below, they did not "throw").
|
|
4610
|
+
if (
|
|
4611
|
+
isBackgroundWorker &&
|
|
4612
|
+
run.status === "errored" &&
|
|
4613
|
+
!endsAtInternalContinuationBoundary(run)
|
|
4614
|
+
) {
|
|
4615
|
+
const errEvent = [...run.events]
|
|
4616
|
+
.reverse()
|
|
4617
|
+
.find((e) => e.event.type === "error")?.event as
|
|
4618
|
+
| { error?: string; errorCode?: string }
|
|
4619
|
+
| undefined;
|
|
4620
|
+
await recordRunDiagnostic(
|
|
4621
|
+
run.runId,
|
|
4622
|
+
RUN_DIAG_STAGE.workerThrew,
|
|
4623
|
+
errEvent?.errorCode || errEvent?.error
|
|
4624
|
+
? `${errEvent.errorCode ?? ""} ${errEvent.error ?? ""}`.trim()
|
|
4625
|
+
: "run ended in errored state",
|
|
4626
|
+
).catch(() => {});
|
|
4627
|
+
}
|
|
4602
4628
|
// Persist the (partial) assistant turn to thread_data FIRST — the
|
|
4603
4629
|
// server-driven continuation below rebuilds from it, so it must be
|
|
4604
4630
|
// committed before we re-fire.
|
|
@@ -4689,6 +4715,17 @@ export function createProductionAgentHandler(
|
|
|
4689
4715
|
// on entry so a slow cold-start doesn't leave the row looking stale to the
|
|
4690
4716
|
// reaper before startRun's 1.5s heartbeat timer takes over.
|
|
4691
4717
|
if (isBackgroundWorker) {
|
|
4718
|
+
// DIAGNOSTIC: the re-entered handler recognized itself as the background
|
|
4719
|
+
// worker. Record the runtime regime too — `isInBackgroundFunctionRuntime()`
|
|
4720
|
+
// reads a globalThis marker set by the bg-fn entry, which may NOT be set in
|
|
4721
|
+
// this isolate; recording the ACTUAL resolved value reveals whether the
|
|
4722
|
+
// worker is on the 13-min `-background` budget or the 40s clamp. This is
|
|
4723
|
+
// the proof the worker reached its own code (vs. dying at auth before it).
|
|
4724
|
+
await recordRunDiagnostic(
|
|
4725
|
+
runId,
|
|
4726
|
+
RUN_DIAG_STAGE.workerEntered,
|
|
4727
|
+
`runsInBackgroundFunction=${runsInBackgroundFunction} continuationCount=${backgroundContinuationCount}`,
|
|
4728
|
+
).catch(() => {});
|
|
4692
4729
|
// A chained continuation chunk's runId was minted by the prior chunk and
|
|
4693
4730
|
// never inserted, so insert its background row now (idempotently — a
|
|
4694
4731
|
// duplicate Netlify delivery that already inserted it just PK-collides and
|
|
@@ -4703,8 +4740,16 @@ export function createProductionAgentHandler(
|
|
|
4703
4740
|
if (!won) {
|
|
4704
4741
|
// Already claimed by an earlier delivery — return a benign ack so
|
|
4705
4742
|
// Netlify doesn't retry a successful handoff.
|
|
4743
|
+
await recordRunDiagnostic(runId, RUN_DIAG_STAGE.workerClaimLost).catch(
|
|
4744
|
+
() => {},
|
|
4745
|
+
);
|
|
4706
4746
|
return { ok: true, skipped: "already-claimed" };
|
|
4707
4747
|
}
|
|
4748
|
+
// DIAGNOSTIC: this worker won the claim and now OWNS the run. If a run
|
|
4749
|
+
// ever stalls at this stage it means the loop below failed to start.
|
|
4750
|
+
await recordRunDiagnostic(runId, RUN_DIAG_STAGE.workerClaimed).catch(
|
|
4751
|
+
() => {},
|
|
4752
|
+
);
|
|
4708
4753
|
await updateRunHeartbeat(runId).catch(() => {});
|
|
4709
4754
|
}
|
|
4710
4755
|
|
|
@@ -4719,6 +4764,15 @@ export function createProductionAgentHandler(
|
|
|
4719
4764
|
|
|
4720
4765
|
send({ type: "activity", label: "Starting agent" });
|
|
4721
4766
|
|
|
4767
|
+
// DIAGNOSTIC: the agent loop body actually started running. For a
|
|
4768
|
+
// background worker, a run that is claimed but never reaches this stage
|
|
4769
|
+
// died between claiming and loop start. Best-effort, background only.
|
|
4770
|
+
if (isBackgroundWorker) {
|
|
4771
|
+
await recordRunDiagnostic(runId, RUN_DIAG_STAGE.workerStarted).catch(
|
|
4772
|
+
() => {},
|
|
4773
|
+
);
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4722
4776
|
// Notify listeners that a run has started (used by agent teams)
|
|
4723
4777
|
if (options.onRunStart) {
|
|
4724
4778
|
await options.onRunStart(send, threadId ?? runId);
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
updateRunHeartbeat,
|
|
16
16
|
bumpRunProgress,
|
|
17
17
|
reapIfStale,
|
|
18
|
+
reapUnclaimedBackgroundRun,
|
|
18
19
|
ensureTerminalRunEvent,
|
|
19
20
|
setRunError,
|
|
20
21
|
STALE_RUN_ERROR_EVENT,
|
|
@@ -1022,6 +1023,14 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
|
|
|
1022
1023
|
status: string;
|
|
1023
1024
|
heartbeatAt: number;
|
|
1024
1025
|
lastProgressAt: number | null;
|
|
1026
|
+
/** How the run was dispatched (NULL/foreground, background, background-processing). */
|
|
1027
|
+
dispatchMode?: string | null;
|
|
1028
|
+
/**
|
|
1029
|
+
* Last reached `_process-run` worker stage as a JSON string
|
|
1030
|
+
* `{stage,detail?,at}`. Surfaced so a silent background-worker death is
|
|
1031
|
+
* diagnosable from the client WITHOUT the unreadable bg-fn logs.
|
|
1032
|
+
*/
|
|
1033
|
+
diagStage?: string | null;
|
|
1025
1034
|
} | null> {
|
|
1026
1035
|
// Check memory first — return both running AND recently-completed runs
|
|
1027
1036
|
// that still have events in memory. This allows sub-agent tabs to replay
|
|
@@ -1055,6 +1064,20 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
|
|
|
1055
1064
|
const sqlRun = await getRunByThread(threadId, { includeTerminal: true });
|
|
1056
1065
|
if (!sqlRun) return null;
|
|
1057
1066
|
if (sqlRun.status === "running") {
|
|
1067
|
+
// FALLBACK HARDENING: a background-dispatched run that is still UNCLAIMED
|
|
1068
|
+
// (dispatch_mode === 'background', never flipped to 'background-processing')
|
|
1069
|
+
// past the tight grace means the bg-fn worker never started — a silent
|
|
1070
|
+
// async-worker death that the 202-ack inline fallback can't catch. Reap it
|
|
1071
|
+
// early and recoverably (background_worker_never_started) so the run no
|
|
1072
|
+
// longer hangs for the full 90s window and the client's recoverable-error
|
|
1073
|
+
// path can re-drive the turn. Only fires when there is provably no live
|
|
1074
|
+
// worker; a claimed/heartbeating run is left alone by the conditional SQL.
|
|
1075
|
+
if (sqlRun.dispatchMode === "background") {
|
|
1076
|
+
const recovered = await reapUnclaimedBackgroundRun(sqlRun.id).catch(
|
|
1077
|
+
() => false,
|
|
1078
|
+
);
|
|
1079
|
+
if (recovered) return null;
|
|
1080
|
+
}
|
|
1058
1081
|
// If the producer is dead (no recent heartbeat), reap before the
|
|
1059
1082
|
// client can see a stale "running" status and enter a reconnect
|
|
1060
1083
|
// loop it can never exit.
|
|
@@ -1067,6 +1090,8 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
|
|
|
1067
1090
|
status: sqlRun.status,
|
|
1068
1091
|
heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,
|
|
1069
1092
|
lastProgressAt: sqlRun.lastProgressAt,
|
|
1093
|
+
dispatchMode: sqlRun.dispatchMode,
|
|
1094
|
+
diagStage: sqlRun.diagStage,
|
|
1070
1095
|
};
|
|
1071
1096
|
}
|
|
1072
1097
|
if (sqlRun.status === "completed" || sqlRun.status === "errored") {
|
|
@@ -1092,6 +1117,8 @@ export async function getActiveRunForThreadAsync(threadId: string): Promise<{
|
|
|
1092
1117
|
status: sqlRun.status,
|
|
1093
1118
|
heartbeatAt: sqlRun.heartbeatAt ?? sqlRun.startedAt,
|
|
1094
1119
|
lastProgressAt: sqlRun.lastProgressAt,
|
|
1120
|
+
dispatchMode: sqlRun.dispatchMode,
|
|
1121
|
+
diagStage: sqlRun.diagStage,
|
|
1095
1122
|
};
|
|
1096
1123
|
}
|
|
1097
1124
|
} catch {
|
|
@@ -44,6 +44,40 @@ export const STALE_RUN_ERROR_EVENT = {
|
|
|
44
44
|
"The run heartbeat stopped while the run was still marked running. Partial output and tool calls were preserved when available.",
|
|
45
45
|
} as const;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Terminal error for a background-dispatched run whose worker NEVER claimed it
|
|
49
|
+
* (the foreground fired the self-dispatch, Netlify acked it async with a 202,
|
|
50
|
+
* but the `_process-run` worker never ran far enough to flip
|
|
51
|
+
* `dispatch_mode background → background-processing`). Distinct errorCode so the
|
|
52
|
+
* client (and prod triage) can tell "the worker died silently" apart from "a
|
|
53
|
+
* claimed worker's heartbeat went stale". Recoverable so the client surfaces a
|
|
54
|
+
* retry affordance and re-drives the turn. See `reapUnclaimedBackgroundRun`.
|
|
55
|
+
*/
|
|
56
|
+
export const UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT = {
|
|
57
|
+
type: "error",
|
|
58
|
+
error:
|
|
59
|
+
"The agent run was handed off to a background worker that never started. It was recovered so you can try again.",
|
|
60
|
+
errorCode: "background_worker_never_started",
|
|
61
|
+
recoverable: true,
|
|
62
|
+
details:
|
|
63
|
+
"A background-dispatched run was acknowledged (HTTP 202) but its worker never claimed the run, so no progress was produced. The run was reaped early (it had no live worker to protect) so the turn can be retried.",
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Grace period before a never-claimed background run (dispatch_mode still
|
|
68
|
+
* 'background', no worker claim) is treated as a dead handoff and reaped.
|
|
69
|
+
*
|
|
70
|
+
* This is intentionally MUCH tighter than `BACKGROUND_RUN_STALE_MS` (90s). The
|
|
71
|
+
* wide 90s window exists ONLY to protect a CLAIMED worker whose heartbeat lags
|
|
72
|
+
* during a slow cold start. A run that is still `dispatch_mode = 'background'`
|
|
73
|
+
* has, by definition, NO worker — nothing to protect — so once a Netlify
|
|
74
|
+
* background function has had a reasonable cold-start window to claim it and
|
|
75
|
+
* hasn't, the handoff is dead and should surface promptly instead of leaving
|
|
76
|
+
* the user staring at a spinner for 90s. 25s comfortably exceeds a normal
|
|
77
|
+
* Netlify Lambda cold start while still failing fast on a silent worker death.
|
|
78
|
+
*/
|
|
79
|
+
export const UNCLAIMED_BACKGROUND_RUN_GRACE_MS = 25_000;
|
|
80
|
+
|
|
47
81
|
async function ensureRunTables(): Promise<void> {
|
|
48
82
|
if (!_initPromise) {
|
|
49
83
|
_initPromise = (async () => {
|
|
@@ -61,7 +95,8 @@ async function ensureRunTables(): Promise<void> {
|
|
|
61
95
|
turn_id TEXT,
|
|
62
96
|
error_code TEXT,
|
|
63
97
|
error_detail TEXT,
|
|
64
|
-
dispatch_mode TEXT
|
|
98
|
+
dispatch_mode TEXT,
|
|
99
|
+
diag_stage TEXT
|
|
65
100
|
)
|
|
66
101
|
`);
|
|
67
102
|
// Backfill heartbeat_at on older deployments.
|
|
@@ -118,11 +153,16 @@ async function ensureRunTables(): Promise<void> {
|
|
|
118
153
|
// normal synchronous path, "background" for a run dispatched into a
|
|
119
154
|
// Netlify background function. The reaper/claim widen the stale window
|
|
120
155
|
// for background rows so a slow cold-start isn't falsely reaped.
|
|
156
|
+
// diag_stage records the last reached pipeline stage (+ any error) for a
|
|
157
|
+
// background-dispatched run so a silent worker death is DIAGNOSABLE from
|
|
158
|
+
// the client (/runs/active surfaces it) without reading the unreadable
|
|
159
|
+
// Netlify background-function logs. See recordRunDiagnostic.
|
|
121
160
|
for (const col of [
|
|
122
161
|
"turn_id",
|
|
123
162
|
"error_code",
|
|
124
163
|
"error_detail",
|
|
125
164
|
"dispatch_mode",
|
|
165
|
+
"diag_stage",
|
|
126
166
|
] as const) {
|
|
127
167
|
try {
|
|
128
168
|
if (isPostgres()) {
|
|
@@ -416,6 +456,72 @@ export async function setRunError(
|
|
|
416
456
|
}
|
|
417
457
|
}
|
|
418
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Diagnostic stage names recorded onto a background run as it moves through the
|
|
461
|
+
* `_process-run` worker pipeline. Each value is the LAST stage successfully
|
|
462
|
+
* reached, so a stuck run's `diag_stage` reveals exactly where it died. Ordered
|
|
463
|
+
* roughly by execution; the literal strings are the client-readable contract.
|
|
464
|
+
*/
|
|
465
|
+
export const RUN_DIAG_STAGE = {
|
|
466
|
+
/** The `_process-run` route handler was entered (the request reached Nitro). */
|
|
467
|
+
routeEntered: "route_entered",
|
|
468
|
+
/** HMAC auth + body validation in prepareProcessRunRequest FAILED. */
|
|
469
|
+
authFailed: "auth_failed",
|
|
470
|
+
/** HMAC auth + body validation PASSED; about to invoke the worker handler. */
|
|
471
|
+
authPassed: "auth_passed",
|
|
472
|
+
/** The re-entered agent-chat handler recognized itself as the bg worker. */
|
|
473
|
+
workerEntered: "worker_entered",
|
|
474
|
+
/** The worker won the atomic claim (it owns the run). */
|
|
475
|
+
workerClaimed: "worker_claimed",
|
|
476
|
+
/** The worker LOST the claim (a duplicate delivery already owns the run). */
|
|
477
|
+
workerClaimLost: "worker_claim_lost",
|
|
478
|
+
/** The agent loop started (startRun fired). */
|
|
479
|
+
workerStarted: "worker_started",
|
|
480
|
+
/** The worker threw before/while running the loop (message carried in detail). */
|
|
481
|
+
workerThrew: "worker_threw",
|
|
482
|
+
/** The route handler caught an error from the worker invocation. */
|
|
483
|
+
routeThrew: "route_threw",
|
|
484
|
+
} as const;
|
|
485
|
+
|
|
486
|
+
export type RunDiagStage = (typeof RUN_DIAG_STAGE)[keyof typeof RUN_DIAG_STAGE];
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Record the last reached pipeline stage (+ optional short detail) for a run.
|
|
490
|
+
*
|
|
491
|
+
* PURPOSE: a Netlify background function's logs are not readable from the build
|
|
492
|
+
* tooling, so when its worker dies silently the run just times out with no clue
|
|
493
|
+
* WHY. This writes the failure stage straight onto the `agent_runs` row, which
|
|
494
|
+
* `/runs/active` and `listRunsForThread` surface to the client — so the next
|
|
495
|
+
* prod run's death cause is readable WITHOUT bg-fn logs. Cheap, additive, and
|
|
496
|
+
* best-effort: it must never throw or perturb the run (it is called on the auth
|
|
497
|
+
* path BEFORE a 401 is returned, and around the worker body).
|
|
498
|
+
*
|
|
499
|
+
* The stored value is a compact JSON `{ stage, detail?, at }` capped to 2 KB so
|
|
500
|
+
* a long stack can't bloat the row.
|
|
501
|
+
*/
|
|
502
|
+
export async function recordRunDiagnostic(
|
|
503
|
+
runId: string,
|
|
504
|
+
stage: RunDiagStage,
|
|
505
|
+
detail?: string,
|
|
506
|
+
): Promise<void> {
|
|
507
|
+
if (!runId) return;
|
|
508
|
+
try {
|
|
509
|
+
await ensureRunTables();
|
|
510
|
+
const client = getDbExec();
|
|
511
|
+
const payload = JSON.stringify({
|
|
512
|
+
stage,
|
|
513
|
+
...(detail ? { detail: detail.slice(0, 1500) } : {}),
|
|
514
|
+
at: Date.now(),
|
|
515
|
+
}).slice(0, 2000);
|
|
516
|
+
await client.execute({
|
|
517
|
+
sql: `UPDATE agent_runs SET diag_stage = ? WHERE id = ?`,
|
|
518
|
+
args: [payload, runId],
|
|
519
|
+
});
|
|
520
|
+
} catch {
|
|
521
|
+
// Diagnostics are best-effort; never let them break the run or the route.
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
419
525
|
/** Update the run's liveness heartbeat. Called periodically by run-manager. */
|
|
420
526
|
export async function updateRunHeartbeat(runId: string): Promise<void> {
|
|
421
527
|
await ensureRunTables();
|
|
@@ -490,6 +596,68 @@ export async function reapIfStale(
|
|
|
490
596
|
return reaped;
|
|
491
597
|
}
|
|
492
598
|
|
|
599
|
+
/**
|
|
600
|
+
* FALLBACK HARDENING for the "dispatched with 202 but the worker never started"
|
|
601
|
+
* case. A background-dispatched run sits in `dispatch_mode = 'background'` until
|
|
602
|
+
* the worker wins `claimBackgroundRun` (which flips it to
|
|
603
|
+
* `background-processing`). If the worker silently dies (e.g. the bg-fn 401s
|
|
604
|
+
* before it can claim), the row stays `background`, never heartbeats again, and
|
|
605
|
+
* — because dispatch returned 202 — the foreground already returned the SSE
|
|
606
|
+
* stream, so the existing fast-fail inline fallback never engaged. The run would
|
|
607
|
+
* otherwise hang for the full 90s background window and then error opaquely.
|
|
608
|
+
*
|
|
609
|
+
* This reaps such a run EARLY and DISTINCTLY: a row that is still unclaimed
|
|
610
|
+
* (`dispatch_mode = 'background'`) past the tight `UNCLAIMED_BACKGROUND_RUN_GRACE_MS`
|
|
611
|
+
* grace is a dead handoff — there is no live worker to protect with the wide
|
|
612
|
+
* window — so we flip it to `errored` with the recoverable
|
|
613
|
+
* `background_worker_never_started` code. The client's existing recoverable-error
|
|
614
|
+
* path then lets the user (or auto-recovery) re-drive the turn. Idempotent and
|
|
615
|
+
* conditional: only an unclaimed, still-running, grace-exceeded row matches, so a
|
|
616
|
+
* claimed worker, a fresh dispatch, or a terminal row is never touched.
|
|
617
|
+
*
|
|
618
|
+
* Returns true when this call reaped the run.
|
|
619
|
+
*/
|
|
620
|
+
export async function reapUnclaimedBackgroundRun(
|
|
621
|
+
runId: string,
|
|
622
|
+
): Promise<boolean> {
|
|
623
|
+
await ensureRunTables();
|
|
624
|
+
const client = getDbExec();
|
|
625
|
+
const completedAt = Date.now();
|
|
626
|
+
const cutoff = completedAt - UNCLAIMED_BACKGROUND_RUN_GRACE_MS;
|
|
627
|
+
const { rowsAffected } = await client.execute({
|
|
628
|
+
sql: `UPDATE agent_runs
|
|
629
|
+
SET status = 'errored',
|
|
630
|
+
completed_at = ?,
|
|
631
|
+
error_code = ?,
|
|
632
|
+
error_detail = ?
|
|
633
|
+
WHERE id = ?
|
|
634
|
+
AND status = 'running'
|
|
635
|
+
AND dispatch_mode = 'background'
|
|
636
|
+
AND COALESCE(heartbeat_at, started_at) < ?`,
|
|
637
|
+
args: [
|
|
638
|
+
completedAt,
|
|
639
|
+
UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.errorCode,
|
|
640
|
+
UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.details,
|
|
641
|
+
runId,
|
|
642
|
+
cutoff,
|
|
643
|
+
],
|
|
644
|
+
});
|
|
645
|
+
const reaped = (rowsAffected ?? 0) > 0;
|
|
646
|
+
if (reaped) {
|
|
647
|
+
await recordRunDiagnostic(
|
|
648
|
+
runId,
|
|
649
|
+
RUN_DIAG_STAGE.workerThrew,
|
|
650
|
+
"unclaimed background dispatch reaped (worker never claimed the run)",
|
|
651
|
+
);
|
|
652
|
+
await safeAppendTerminalRunEvent(
|
|
653
|
+
runId,
|
|
654
|
+
UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT,
|
|
655
|
+
"reap-unclaimed-background",
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
return reaped;
|
|
659
|
+
}
|
|
660
|
+
|
|
493
661
|
export async function updateRunStatus(
|
|
494
662
|
runId: string,
|
|
495
663
|
status: "completed" | "errored" | "aborted",
|
|
@@ -644,12 +812,14 @@ export async function getRunByThread(
|
|
|
644
812
|
heartbeatAt: number | null;
|
|
645
813
|
completedAt: number | null;
|
|
646
814
|
lastProgressAt: number | null;
|
|
815
|
+
dispatchMode: string | null;
|
|
816
|
+
diagStage: string | null;
|
|
647
817
|
} | null> {
|
|
648
818
|
await ensureRunTables();
|
|
649
819
|
const client = getDbExec();
|
|
650
820
|
const sql = options?.includeTerminal
|
|
651
|
-
? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`
|
|
652
|
-
: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;
|
|
821
|
+
? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`
|
|
822
|
+
: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;
|
|
653
823
|
const { rows } = await client.execute({ sql, args: [threadId] });
|
|
654
824
|
if (rows.length === 0) return null;
|
|
655
825
|
const r = rows[0] as {
|
|
@@ -661,6 +831,8 @@ export async function getRunByThread(
|
|
|
661
831
|
heartbeat_at: number | string | null;
|
|
662
832
|
completed_at: number | string | null;
|
|
663
833
|
last_progress_at: number | string | null;
|
|
834
|
+
dispatch_mode?: string | null;
|
|
835
|
+
diag_stage?: string | null;
|
|
664
836
|
};
|
|
665
837
|
return {
|
|
666
838
|
id: r.id,
|
|
@@ -672,6 +844,8 @@ export async function getRunByThread(
|
|
|
672
844
|
completedAt: r.completed_at == null ? null : Number(r.completed_at),
|
|
673
845
|
lastProgressAt:
|
|
674
846
|
r.last_progress_at == null ? null : Number(r.last_progress_at),
|
|
847
|
+
dispatchMode: r.dispatch_mode ?? null,
|
|
848
|
+
diagStage: r.diag_stage ?? null,
|
|
675
849
|
};
|
|
676
850
|
}
|
|
677
851
|
|
|
@@ -686,6 +860,9 @@ export interface AgentRunSummary {
|
|
|
686
860
|
lastProgressAt: number | null;
|
|
687
861
|
errorCode: string | null;
|
|
688
862
|
abortReason: string | null;
|
|
863
|
+
dispatchMode: string | null;
|
|
864
|
+
/** Last reached `_process-run` worker stage (JSON `{stage,detail?,at}`). */
|
|
865
|
+
diagStage: string | null;
|
|
689
866
|
}
|
|
690
867
|
|
|
691
868
|
export async function listRunsForThread(
|
|
@@ -696,7 +873,7 @@ export async function listRunsForThread(
|
|
|
696
873
|
const limit = Math.min(Math.max(options.limit ?? 10, 1), 50);
|
|
697
874
|
const client = getDbExec();
|
|
698
875
|
const { rows } = await client.execute({
|
|
699
|
-
sql: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, error_code, abort_reason
|
|
876
|
+
sql: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, error_code, abort_reason, dispatch_mode, diag_stage
|
|
700
877
|
FROM agent_runs
|
|
701
878
|
WHERE thread_id = ?
|
|
702
879
|
ORDER BY started_at DESC
|
|
@@ -715,6 +892,8 @@ export async function listRunsForThread(
|
|
|
715
892
|
last_progress_at?: number | string | null;
|
|
716
893
|
error_code?: string | null;
|
|
717
894
|
abort_reason?: string | null;
|
|
895
|
+
dispatch_mode?: string | null;
|
|
896
|
+
diag_stage?: string | null;
|
|
718
897
|
};
|
|
719
898
|
return {
|
|
720
899
|
id: row.id,
|
|
@@ -728,6 +907,8 @@ export async function listRunsForThread(
|
|
|
728
907
|
row.last_progress_at == null ? null : Number(row.last_progress_at),
|
|
729
908
|
errorCode: row.error_code ?? null,
|
|
730
909
|
abortReason: row.abort_reason ?? null,
|
|
910
|
+
dispatchMode: row.dispatch_mode ?? null,
|
|
911
|
+
diagStage: row.diag_stage ?? null,
|
|
731
912
|
};
|
|
732
913
|
});
|
|
733
914
|
}
|
|
@@ -63,6 +63,22 @@ export function openAgentSidebar() {
|
|
|
63
63
|
window.dispatchEvent(new Event("agent-panel:open"));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
export function openAgentSettings(
|
|
67
|
+
section?: string | { section?: string | null },
|
|
68
|
+
) {
|
|
69
|
+
if (typeof window === "undefined") return;
|
|
70
|
+
|
|
71
|
+
const normalizedSection =
|
|
72
|
+
typeof section === "string" ? section : section?.section;
|
|
73
|
+
|
|
74
|
+
openAgentSidebar();
|
|
75
|
+
window.dispatchEvent(
|
|
76
|
+
new CustomEvent("agent-panel:open-settings", {
|
|
77
|
+
detail: normalizedSection ? { section: normalizedSection } : undefined,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
66
82
|
export function focusAgentChat() {
|
|
67
83
|
window.dispatchEvent(
|
|
68
84
|
new CustomEvent("agent-panel:set-mode", {
|
|
@@ -53,6 +53,10 @@ import { TooltipProvider } from "@radix-ui/react-tooltip";
|
|
|
53
53
|
import { Toaster } from "sonner";
|
|
54
54
|
import { ClientOnly } from "./ClientOnly.js";
|
|
55
55
|
import { DefaultSpinner } from "./DefaultSpinner.js";
|
|
56
|
+
import {
|
|
57
|
+
AgentNativeI18nProvider,
|
|
58
|
+
type AgentNativeI18nProviderProps,
|
|
59
|
+
} from "./i18n.js";
|
|
56
60
|
|
|
57
61
|
export interface AppProvidersProps {
|
|
58
62
|
/** QueryClient instance — create with `createAgentNativeQueryClient()`. */
|
|
@@ -94,6 +98,13 @@ export interface AppProvidersProps {
|
|
|
94
98
|
*/
|
|
95
99
|
disableThemeTransitions?: boolean;
|
|
96
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Optional localization runtime configuration. When omitted, AppProviders
|
|
103
|
+
* still mounts the i18n provider with an English fallback so templates can
|
|
104
|
+
* call useT/useLocale before they add catalogs. Pass false to opt out.
|
|
105
|
+
*/
|
|
106
|
+
i18n?: Omit<AgentNativeI18nProviderProps, "children"> | false;
|
|
107
|
+
|
|
97
108
|
/**
|
|
98
109
|
* When true the providers render without a `<ClientOnly>` gate so SSR
|
|
99
110
|
* streams real markup for public/unauthenticated paths.
|
|
@@ -119,6 +130,7 @@ function ProvidersInner({
|
|
|
119
130
|
tooltipDelayDuration,
|
|
120
131
|
toaster = DEFAULT_TOASTER,
|
|
121
132
|
disableThemeTransitions = true,
|
|
133
|
+
i18n,
|
|
122
134
|
children,
|
|
123
135
|
}: {
|
|
124
136
|
queryClient: QueryClient;
|
|
@@ -127,8 +139,18 @@ function ProvidersInner({
|
|
|
127
139
|
tooltipDelayDuration?: number;
|
|
128
140
|
toaster?: React.ReactNode | null;
|
|
129
141
|
disableThemeTransitions?: boolean;
|
|
142
|
+
i18n?: Omit<AgentNativeI18nProviderProps, "children"> | false;
|
|
130
143
|
children: React.ReactNode;
|
|
131
144
|
}) {
|
|
145
|
+
const localizedChildren =
|
|
146
|
+
i18n === false ? (
|
|
147
|
+
children
|
|
148
|
+
) : (
|
|
149
|
+
<AgentNativeI18nProvider {...(i18n ?? {})}>
|
|
150
|
+
{children}
|
|
151
|
+
</AgentNativeI18nProvider>
|
|
152
|
+
);
|
|
153
|
+
|
|
132
154
|
return (
|
|
133
155
|
<QueryClientProvider client={queryClient}>
|
|
134
156
|
<ThemeProvider
|
|
@@ -138,7 +160,7 @@ function ProvidersInner({
|
|
|
138
160
|
disableTransitionOnChange={disableThemeTransitions}
|
|
139
161
|
>
|
|
140
162
|
<TooltipProvider delayDuration={tooltipDelayDuration}>
|
|
141
|
-
{
|
|
163
|
+
{localizedChildren}
|
|
142
164
|
{toaster}
|
|
143
165
|
</TooltipProvider>
|
|
144
166
|
</ThemeProvider>
|
|
@@ -155,6 +177,7 @@ export function AppProviders({
|
|
|
155
177
|
tooltipDelayDuration,
|
|
156
178
|
toaster,
|
|
157
179
|
disableThemeTransitions,
|
|
180
|
+
i18n,
|
|
158
181
|
children,
|
|
159
182
|
}: AppProvidersProps) {
|
|
160
183
|
const fallback = clientOnlyFallback ?? <DefaultSpinner />;
|
|
@@ -168,6 +191,7 @@ export function AppProviders({
|
|
|
168
191
|
tooltipDelayDuration={tooltipDelayDuration}
|
|
169
192
|
toaster={toaster}
|
|
170
193
|
disableThemeTransitions={disableThemeTransitions}
|
|
194
|
+
i18n={i18n}
|
|
171
195
|
>
|
|
172
196
|
{children}
|
|
173
197
|
</ProvidersInner>
|
|
@@ -183,6 +207,7 @@ export function AppProviders({
|
|
|
183
207
|
tooltipDelayDuration={tooltipDelayDuration}
|
|
184
208
|
toaster={toaster}
|
|
185
209
|
disableThemeTransitions={disableThemeTransitions}
|
|
210
|
+
i18n={i18n}
|
|
186
211
|
>
|
|
187
212
|
{children}
|
|
188
213
|
</ProvidersInner>
|