@agent-native/core 0.75.4 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +47 -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 +62 -28
- package/corpus/core/src/agent/production-agent.ts +16 -12
- package/corpus/core/src/cli/skills.ts +22 -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/deploy/build.ts +47 -113
- package/corpus/core/src/deploy/workspace-deploy.ts +62 -30
- 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/index.ts +8 -0
- package/corpus/core/src/server/self-dispatch.ts +29 -2
- 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/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 +5 -3
- 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/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/settings.tsx +45 -8
- 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-chrome-extension-setup-now-shows-a-clear-all-done-confirmati.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/clips/chrome-extension/src/permission.html +60 -0
- package/corpus/templates/clips/chrome-extension/src/permission.ts +28 -15
- 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/.agents/skills/visual-plan/references/wireframe.md +22 -4
- package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +22 -4
- 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 +32 -28
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +59 -28
- 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 +16 -12
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +22 -4
- package/dist/cli/skills.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/deploy/build.d.ts +32 -36
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +47 -104
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/workspace-deploy.js +62 -30
- package/dist/deploy/workspace-deploy.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/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/server/self-dispatch.d.ts +0 -10
- package/dist/server/self-dispatch.d.ts.map +1 -1
- package/dist/server/self-dispatch.js +27 -2
- package/dist/server/self-dispatch.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
|
@@ -1510,61 +1510,57 @@ export function isDurableBackgroundDeployEnabled(): boolean {
|
|
|
1510
1510
|
* 15-min async function instead of the synchronous `/*` catch-all.
|
|
1511
1511
|
* Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
|
|
1512
1512
|
*
|
|
1513
|
-
* GROUNDED IN THE REAL NETLIFY BUILD OUTPUT (verified from a local Nitro build)
|
|
1513
|
+
* GROUNDED IN THE REAL NETLIFY BUILD OUTPUT (verified from a local Nitro build)
|
|
1514
|
+
* AND THE NETLIFY DOCS DEFAULT-URL RULE:
|
|
1514
1515
|
* - Nitro's `netlify` preset emits exactly ONE function source at
|
|
1515
1516
|
* `.netlify/functions-internal/server/`. `server.mjs` re-exports `main.mjs`
|
|
1516
1517
|
* and declares `export const config = { path: "/*", excludedPath:
|
|
1517
|
-
* ["/.netlify/*"], preferStatic: true, ... }`.
|
|
1518
|
-
*
|
|
1519
|
-
*
|
|
1518
|
+
* ["/.netlify/*"], preferStatic: true, ... }`. The `/*` catch-all is an
|
|
1519
|
+
* IN-CODE Functions-API-v2 `config.path` and it ALREADY EXCLUDES
|
|
1520
|
+
* `/.netlify/*`.
|
|
1520
1521
|
* - The generated `.netlify/netlify.toml` sets
|
|
1521
1522
|
* `functionsDirectory = ".netlify/functions-internal"`. Netlify scans EXACTLY
|
|
1522
1523
|
* that dir; functions placed anywhere else (e.g. `.netlify/functions/`, which
|
|
1523
1524
|
* is the BUILD OUTPUT dir where `@netlify/build` later writes the zipped
|
|
1524
1525
|
* functions + `manifest.json`) are NEVER deployed.
|
|
1525
|
-
* -
|
|
1526
|
-
*
|
|
1527
|
-
*
|
|
1528
|
-
* `config.path`. So per-file `export const config` (including `background` and
|
|
1529
|
-
* `path`) IS honored — the `server` manifest entry's `routes: [{ pattern:
|
|
1530
|
-
* "/*" }]` came straight from `server.mjs`'s `config.path`.
|
|
1526
|
+
* - Every scanned function is reachable at its DEFAULT url
|
|
1527
|
+
* `/.netlify/functions/<name>` BY DEFAULT. A custom `config.path` REMOVES
|
|
1528
|
+
* that default url; declaring NO custom `config.path` KEEPS it.
|
|
1531
1529
|
*
|
|
1532
1530
|
* THEREFORE we:
|
|
1533
1531
|
* 1. Emit the background function INTO the scanned dir
|
|
1534
1532
|
* (`.netlify/functions-internal/server-agent-background/`), sharing the same
|
|
1535
1533
|
* built `main.mjs` bundle, so Netlify discovers it and honors its config.
|
|
1536
|
-
* 2. Give its `export const config`
|
|
1537
|
-
* immediate 202, 15-min budget)
|
|
1538
|
-
*
|
|
1539
|
-
*
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1542
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1534
|
+
* 2. Give its `export const config` `background: true` (→ async invoke,
|
|
1535
|
+
* immediate 202, 15-min budget) and NO custom `config.path`. With no custom
|
|
1536
|
+
* path the function keeps its DEFAULT url
|
|
1537
|
+
* `/.netlify/functions/server-agent-background`, and because the Nitro
|
|
1538
|
+
* `server` function's `/*` catch-all already excludes `/.netlify/*`, that
|
|
1539
|
+
* default-url namespace is NEVER shadowed by the synchronous function — no
|
|
1540
|
+
* catch-all patch is needed.
|
|
1541
|
+
* 3. The entry NORMALIZES/rewrites the incoming request pathname to
|
|
1542
|
+
* `AGENT_CHAT_PROCESS_RUN_PATH` before delegating to `./main.mjs`. The
|
|
1543
|
+
* function is reached at its default url
|
|
1544
|
+
* (`/.netlify/functions/server-agent-background`), so the Nitro router needs
|
|
1545
|
+
* the path rewritten to the framework `_process-run` route, preserving the
|
|
1546
|
+
* method, ALL headers (the HMAC `Authorization: Bearer` MUST survive), and
|
|
1547
|
+
* the body.
|
|
1546
1548
|
* 4. Set `globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true` at cold start
|
|
1547
1549
|
* (read back by `isInBackgroundFunctionRuntime()` so the worker takes the
|
|
1548
1550
|
* ~13-min soft-timeout). A `globalThis` flag — NOT `process.env` — keeps the
|
|
1549
1551
|
* no-env-mutation guard satisfied and carries no cross-request state.
|
|
1550
1552
|
*
|
|
1551
|
-
*
|
|
1552
|
-
*
|
|
1553
|
-
* (`resolveAgentChatProcessRunDispatchPath`) and the request entry no longer
|
|
1554
|
-
* needs to rewrite the path — it already arrives at the framework route. We keep
|
|
1555
|
-
* a defensive normalize-to-PROCESS_RUN_PATH in the entry anyway (cheap, and it
|
|
1556
|
-
* makes the function correct even if reached via its default function url).
|
|
1553
|
+
* The foreground dispatches to this DEFAULT url on hosted Netlify
|
|
1554
|
+
* (`resolveAgentChatProcessRunDispatchPath` → `AGENT_BACKGROUND_FUNCTION_URL_PATH`).
|
|
1557
1555
|
*
|
|
1558
|
-
* WHY THIS
|
|
1559
|
-
*
|
|
1560
|
-
*
|
|
1561
|
-
*
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1565
|
-
*
|
|
1566
|
-
* OUTPUT dir, which Netlify does not scan — so it never entered the manifest
|
|
1567
|
-
* → 404. We now emit into the SCANNED `functions-internal` dir.
|
|
1556
|
+
* WHY THIS IS THE DOC-CORRECT FIX: a prior attempt gave the function a custom
|
|
1557
|
+
* `config.path` (= the framework route) plus a catch-all `excludedPath` patch.
|
|
1558
|
+
* The custom `config.path` was NOT honored as a route in prod — a probe of
|
|
1559
|
+
* `POST /_agent-native/agent-chat/_process-run` returned 404. The doc-correct
|
|
1560
|
+
* approach (confirmed against the Netlify docs) is to use the DEFAULT function
|
|
1561
|
+
* url with no custom path: the function stays reachable at
|
|
1562
|
+
* `/.netlify/functions/<name>` and is never shadowed because `/.netlify/*` is
|
|
1563
|
+
* already excluded from the `server` catch-all.
|
|
1568
1564
|
*
|
|
1569
1565
|
* Safety net regardless of Netlify routing nuance: if the dispatch fast-fails
|
|
1570
1566
|
* (e.g. the function was not emitted), the foreground handler degrades to an
|
|
@@ -1596,11 +1592,6 @@ export function emitSingleTemplateNetlifyBackgroundFunction(
|
|
|
1596
1592
|
// copied bundle does NOT re-register the catch-all `config.path`.
|
|
1597
1593
|
fs.rmSync(path.join(dest, "server.mjs"), { force: true });
|
|
1598
1594
|
|
|
1599
|
-
// Make the `server` `/*` catch-all NOT match the process-run path, so only the
|
|
1600
|
-
// async background function matches it (function-vs-function path order is
|
|
1601
|
-
// undocumented on Netlify — don't rely on it).
|
|
1602
|
-
excludeProcessRunPathFromServerCatchAll(serverDir);
|
|
1603
|
-
|
|
1604
1595
|
const processRunPath = JSON.stringify(AGENT_CHAT_PROCESS_RUN_PATH);
|
|
1605
1596
|
const entry = `// Mark this isolate as the durable background runtime BEFORE the handler
|
|
1606
1597
|
// bundle is imported, so isInBackgroundFunctionRuntime() reliably returns true
|
|
@@ -1618,11 +1609,10 @@ let cachedHandler;
|
|
|
1618
1609
|
|
|
1619
1610
|
// Netlify v2 invokes this as (request, context). The Nitro netlify handler is a
|
|
1620
1611
|
// Web-standard \`async (Request) => Response\` (see nitro/presets/netlify/runtime).
|
|
1621
|
-
//
|
|
1622
|
-
//
|
|
1623
|
-
//
|
|
1624
|
-
//
|
|
1625
|
-
// (/.netlify/functions/${backgroundName}). Method, ALL headers (the HMAC
|
|
1612
|
+
// This function declares NO custom \`config.path\`, so it is reached at its
|
|
1613
|
+
// DEFAULT url (/.netlify/functions/${backgroundName}). The Nitro router only
|
|
1614
|
+
// knows the framework route, so we REWRITE the incoming pathname to
|
|
1615
|
+
// PROCESS_RUN_PATH before delegating. Method, ALL headers (the HMAC
|
|
1626
1616
|
// Authorization: Bearer MUST survive — the plugin verifies it) and the body are
|
|
1627
1617
|
// preserved by cloning the incoming Request with only its URL pathname set.
|
|
1628
1618
|
export default async function handler(request) {
|
|
@@ -1646,13 +1636,12 @@ export const config = {
|
|
|
1646
1636
|
generator: "agent-native build",
|
|
1647
1637
|
// background: true makes Netlify invoke this ASYNCHRONOUSLY (immediate HTTP
|
|
1648
1638
|
// 202 ack) with the 15-minute budget (Netlify docs:
|
|
1649
|
-
// build/functions/background-functions + build/functions/api).
|
|
1650
|
-
//
|
|
1651
|
-
//
|
|
1652
|
-
//
|
|
1653
|
-
// function
|
|
1639
|
+
// build/functions/background-functions + build/functions/api). We declare NO
|
|
1640
|
+
// custom path, so the function keeps its DEFAULT url
|
|
1641
|
+
// /.netlify/functions/${backgroundName}; the Nitro \`server\` /* catch-all
|
|
1642
|
+
// already excludes /.netlify/* so that default url is never shadowed by the
|
|
1643
|
+
// synchronous function. The foreground dispatches to that default url.
|
|
1654
1644
|
background: true,
|
|
1655
|
-
path: PROCESS_RUN_PATH,
|
|
1656
1645
|
nodeBundler: "none",
|
|
1657
1646
|
includedFiles: ["**"],
|
|
1658
1647
|
preferStatic: false,
|
|
@@ -1661,67 +1650,12 @@ export const config = {
|
|
|
1661
1650
|
fs.writeFileSync(path.join(dest, `${backgroundName}.mjs`), entry);
|
|
1662
1651
|
console.log(
|
|
1663
1652
|
`[build] Emitted durable-background function "${backgroundName}" into the ` +
|
|
1664
|
-
`scanned dir .netlify/functions-internal with config { background:true
|
|
1665
|
-
`path
|
|
1666
|
-
|
|
1667
|
-
`
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
/**
|
|
1672
|
-
* Append `AGENT_CHAT_PROCESS_RUN_PATH` to the Nitro `server` function's
|
|
1673
|
-
* `config.excludedPath` so its `/*` catch-all does NOT match the process-run
|
|
1674
|
-
* path. That guarantees the async background function (which declares
|
|
1675
|
-
* `config.path = AGENT_CHAT_PROCESS_RUN_PATH`) is the ONLY function that matches
|
|
1676
|
-
* that path — Netlify does not define a winner when two serverless functions
|
|
1677
|
-
* both match, so we make the match unambiguous instead of relying on order.
|
|
1678
|
-
*
|
|
1679
|
-
* The Nitro-generated `server/server.mjs` is small and deterministic:
|
|
1680
|
-
* export { default } from "./main.mjs";
|
|
1681
|
-
* export const config = { ... excludedPath: ["/.netlify/*"], ... };
|
|
1682
|
-
* We parse the `excludedPath: [...]` array literal and add our path if absent.
|
|
1683
|
-
* If the shape ever changes and we can't find/parse it, we log and leave the
|
|
1684
|
-
* file untouched (the inline-40s fallback still keeps chat working).
|
|
1685
|
-
*/
|
|
1686
|
-
function excludeProcessRunPathFromServerCatchAll(serverDir: string): void {
|
|
1687
|
-
const serverEntry = path.join(serverDir, "server.mjs");
|
|
1688
|
-
if (!fs.existsSync(serverEntry)) {
|
|
1689
|
-
console.warn(
|
|
1690
|
-
"[build] Durable-background: server/server.mjs not found; cannot exclude " +
|
|
1691
|
-
`${AGENT_CHAT_PROCESS_RUN_PATH} from the /* catch-all.`,
|
|
1692
|
-
);
|
|
1693
|
-
return;
|
|
1694
|
-
}
|
|
1695
|
-
const original = fs.readFileSync(serverEntry, "utf8");
|
|
1696
|
-
if (original.includes(AGENT_CHAT_PROCESS_RUN_PATH)) {
|
|
1697
|
-
// Already excluded (idempotent — emit may run on a re-used output tree).
|
|
1698
|
-
return;
|
|
1699
|
-
}
|
|
1700
|
-
const excludedPathRe = /excludedPath:\s*\[([^\]]*)\]/;
|
|
1701
|
-
const match = original.match(excludedPathRe);
|
|
1702
|
-
const quotedPath = JSON.stringify(AGENT_CHAT_PROCESS_RUN_PATH);
|
|
1703
|
-
if (match) {
|
|
1704
|
-
const existing = match[1].trim();
|
|
1705
|
-
const next = existing
|
|
1706
|
-
? `excludedPath: [${existing.replace(/,\s*$/, "")}, ${quotedPath}]`
|
|
1707
|
-
: `excludedPath: [${quotedPath}]`;
|
|
1708
|
-
fs.writeFileSync(serverEntry, original.replace(excludedPathRe, next));
|
|
1709
|
-
return;
|
|
1710
|
-
}
|
|
1711
|
-
// No existing `excludedPath` — inject one into the config object. Match the
|
|
1712
|
-
// `path: "/*"` line and add `excludedPath` right after it.
|
|
1713
|
-
const pathLineRe = /(path:\s*("\/\*"|'\/\*'),?)/;
|
|
1714
|
-
if (pathLineRe.test(original)) {
|
|
1715
|
-
fs.writeFileSync(
|
|
1716
|
-
serverEntry,
|
|
1717
|
-
original.replace(pathLineRe, `$1\n excludedPath: [${quotedPath}],`),
|
|
1718
|
-
);
|
|
1719
|
-
return;
|
|
1720
|
-
}
|
|
1721
|
-
console.warn(
|
|
1722
|
-
"[build] Durable-background: could not locate excludedPath/path in " +
|
|
1723
|
-
"server/server.mjs; leaving the /* catch-all unchanged (the background " +
|
|
1724
|
-
"function may be shadowed — the inline-40s fallback still applies).",
|
|
1653
|
+
`scanned dir .netlify/functions-internal with config { background:true } ` +
|
|
1654
|
+
`and NO custom path — reachable at its default url ` +
|
|
1655
|
+
`/.netlify/functions/${backgroundName} (never shadowed; the server /* ` +
|
|
1656
|
+
`catch-all already excludes /.netlify/*). REQUIRES real-deploy ` +
|
|
1657
|
+
`verification of Netlify async (202) invocation — see ` +
|
|
1658
|
+
`docs/design/durable-agent-runs.md.`,
|
|
1725
1659
|
);
|
|
1726
1660
|
}
|
|
1727
1661
|
|
|
@@ -696,24 +696,30 @@ function isDurableBackgroundDeployEnabled(): boolean {
|
|
|
696
696
|
/**
|
|
697
697
|
* Emit a SECOND Netlify function for `app` whose name ends in `-background`,
|
|
698
698
|
* re-exporting the SAME `main.mjs` handler bundle. Netlify invokes any function
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
699
|
+
* with `config.background: true` asynchronously (202 immediately, up to 15-min
|
|
700
|
+
* budget), which is exactly what the durable-background chat dispatch
|
|
701
|
+
* (`fireInternalDispatch` → the function's default url) needs.
|
|
702
702
|
*
|
|
703
|
-
*
|
|
704
|
-
*
|
|
705
|
-
*
|
|
706
|
-
*
|
|
703
|
+
* DOC-CORRECT DEFAULT-URL APPROACH (mirrors the single-template emit in
|
|
704
|
+
* deploy/build.ts): the function declares NO custom `config.path`, so it keeps
|
|
705
|
+
* its DEFAULT url `/.netlify/functions/<app>-agent-background`. The `<app>-server`
|
|
706
|
+
* function's catch-all already excludes `/.netlify/*`, so that default-url
|
|
707
|
+
* namespace is NEVER shadowed by the synchronous function — no overlapping
|
|
708
|
+
* `config.path` and no catch-all patch are needed. The foreground dispatches to
|
|
709
|
+
* that default url (`resolveAgentChatProcessRunDispatchPath` resolves the per-app
|
|
710
|
+
* name from `AGENT_NATIVE_WORKSPACE_APP_ID`); `fireInternalDispatch` strips the
|
|
711
|
+
* app base path for `/.netlify/*` targets so the request reaches the host-root
|
|
712
|
+
* function url. The entry then REWRITES the incoming pathname to the
|
|
713
|
+
* base-path-prefixed `_process-run` route before delegating to the Nitro router.
|
|
707
714
|
*
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
* win. See packages/core/docs/design/durable-agent-runs.md.
|
|
715
|
+
* It shares the same bundle (`includedFiles: ["**"]`) so `A2A_SECRET`, the DB
|
|
716
|
+
* URL, and the rest of the env/bundle are present. A prior attempt gave the
|
|
717
|
+
* function a custom `config.path` (the framework route) that overlapped the
|
|
718
|
+
* synchronous `<app>-server` catch-all; that path was not honored as a route in
|
|
719
|
+
* prod (probe → 404). The default url is the doc-correct fix.
|
|
720
|
+
*
|
|
721
|
+
* Safety net: if the dispatch fast-fails the foreground degrades to an inline
|
|
722
|
+
* 40s synchronous run (see production-agent.ts).
|
|
717
723
|
*/
|
|
718
724
|
function emitNetlifyBackgroundFunction(
|
|
719
725
|
workspaceRoot: string,
|
|
@@ -721,7 +727,9 @@ function emitNetlifyBackgroundFunction(
|
|
|
721
727
|
srcServerDir: string,
|
|
722
728
|
workspaceApps: WorkspaceAppManifestEntry[],
|
|
723
729
|
): void {
|
|
724
|
-
// Name MUST end in `-background`
|
|
730
|
+
// Name MUST end in `-background` (Netlify async convention + the runtime guard
|
|
731
|
+
// reads the -background Lambda-name suffix as a fallback). It is reached at its
|
|
732
|
+
// DEFAULT url /.netlify/functions/<app>-agent-background.
|
|
725
733
|
const backgroundName = `${app}-agent-background`;
|
|
726
734
|
const dest = path.join(netlifyFunctionsDir(workspaceRoot), backgroundName);
|
|
727
735
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
@@ -733,14 +741,20 @@ function emitNetlifyBackgroundFunction(
|
|
|
733
741
|
workspaceApps,
|
|
734
742
|
app,
|
|
735
743
|
);
|
|
736
|
-
//
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
// processor dispatch), so the route Netlify must map to this async function
|
|
740
|
-
// is `/<app>/_agent-native/agent-chat/_process-run`.
|
|
744
|
+
// The Nitro router for this app expects the base-path-prefixed framework route.
|
|
745
|
+
// The function is reached at its default url, so the entry rewrites the
|
|
746
|
+
// incoming pathname to `/<app>/_agent-native/agent-chat/_process-run`.
|
|
741
747
|
const processRunPath = `${basePath}${AGENT_CHAT_PROCESS_RUN_PATH}`;
|
|
742
|
-
const
|
|
743
|
-
|
|
748
|
+
const server = `// Mark this isolate as the durable background runtime BEFORE the handler bundle
|
|
749
|
+
// is imported, so isInBackgroundFunctionRuntime() reliably returns true in this
|
|
750
|
+
// function (the deployed Lambda name is not guaranteed to end in -background). A
|
|
751
|
+
// globalThis flag (NOT process.env) avoids the no-env-mutation guard and carries
|
|
752
|
+
// no cross-request state.
|
|
753
|
+
globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true;
|
|
754
|
+
|
|
755
|
+
const basePath = ${JSON.stringify(basePath)};
|
|
756
|
+
// The base-path-prefixed framework route the Nitro router dispatches to.
|
|
757
|
+
const PROCESS_RUN_PATH = ${JSON.stringify(processRunPath)};
|
|
744
758
|
|
|
745
759
|
function setBasePathEnv() {
|
|
746
760
|
const processRef = globalThis.process ??= { env: {} };
|
|
@@ -767,16 +781,33 @@ setBasePathEnv();
|
|
|
767
781
|
|
|
768
782
|
let cachedHandler;
|
|
769
783
|
|
|
770
|
-
|
|
784
|
+
// Reached at the DEFAULT url /.netlify/functions/${backgroundName}; REWRITE the
|
|
785
|
+
// incoming pathname to the base-path-prefixed _process-run route so the Nitro
|
|
786
|
+
// router runs the plugin. Method, ALL headers (the HMAC Authorization: Bearer
|
|
787
|
+
// MUST survive) and the body are preserved.
|
|
788
|
+
export default async function handler(request) {
|
|
771
789
|
setBasePathEnv();
|
|
772
790
|
cachedHandler ??= (await import("./main.mjs")).default;
|
|
773
|
-
|
|
791
|
+
const url = new URL(request.url);
|
|
792
|
+
url.pathname = PROCESS_RUN_PATH;
|
|
793
|
+
const method = request.method || "POST";
|
|
794
|
+
const hasBody = method !== "GET" && method !== "HEAD";
|
|
795
|
+
const body = hasBody ? await request.text() : undefined;
|
|
796
|
+
const rewritten = new Request(url.toString(), {
|
|
797
|
+
method,
|
|
798
|
+
headers: request.headers,
|
|
799
|
+
body,
|
|
800
|
+
});
|
|
801
|
+
return cachedHandler(rewritten);
|
|
774
802
|
}
|
|
775
803
|
|
|
776
804
|
export const config = {
|
|
777
805
|
name: ${JSON.stringify(`${app} agent background handler`)},
|
|
778
806
|
generator: "agent-native workspace deploy",
|
|
779
|
-
|
|
807
|
+
// background: true → async invoke (202, 15-min budget). NO custom path: the
|
|
808
|
+
// function keeps its default url /.netlify/functions/${backgroundName}, which
|
|
809
|
+
// the <app>-server catch-all never shadows (it excludes /.netlify/*).
|
|
810
|
+
background: true,
|
|
780
811
|
nodeBundler: "none",
|
|
781
812
|
includedFiles: ["**"],
|
|
782
813
|
preferStatic: false,
|
|
@@ -788,9 +819,10 @@ export const config = {
|
|
|
788
819
|
fs.writeFileSync(path.join(dest, `${backgroundName}.mjs`), server);
|
|
789
820
|
console.log(
|
|
790
821
|
`[workspace-deploy] Emitted durable-background function "${backgroundName}" ` +
|
|
791
|
-
`for app "${app}"
|
|
792
|
-
`
|
|
793
|
-
`
|
|
822
|
+
`for app "${app}" with config { background:true } and NO custom path — ` +
|
|
823
|
+
`reachable at its default url /.netlify/functions/${backgroundName} ` +
|
|
824
|
+
`(rewrites to ${processRunPath}). REQUIRES real-deploy verification of ` +
|
|
825
|
+
`Netlify async (202) invocation — see docs/design/durable-agent-runs.md.`,
|
|
794
826
|
);
|
|
795
827
|
}
|
|
796
828
|
|
|
@@ -25,6 +25,23 @@ export {
|
|
|
25
25
|
updateMcpAppModelContext,
|
|
26
26
|
useMcpAppHostContext,
|
|
27
27
|
CodeRequiredDialog,
|
|
28
|
+
AgentNativeI18nProvider,
|
|
29
|
+
LanguagePicker,
|
|
30
|
+
getLocaleInitScript,
|
|
31
|
+
localeDirection,
|
|
32
|
+
normalizeLocaleCode,
|
|
33
|
+
normalizeLocalePreference,
|
|
34
|
+
normalizeLocalizationPreference,
|
|
35
|
+
resolveLocaleFromCandidates,
|
|
36
|
+
resolveLocaleFromPreference,
|
|
37
|
+
useFormatters,
|
|
38
|
+
useLocale,
|
|
39
|
+
useT,
|
|
40
|
+
DEFAULT_LOCALE,
|
|
41
|
+
LOCALE_HYDRATION_GLOBAL,
|
|
42
|
+
LOCALE_METADATA,
|
|
43
|
+
LOCALE_STORAGE_KEY,
|
|
44
|
+
SUPPORTED_LOCALES,
|
|
28
45
|
useDbSync,
|
|
29
46
|
useFileWatcher,
|
|
30
47
|
useSession,
|
|
@@ -48,6 +65,14 @@ export {
|
|
|
48
65
|
type CodeRequiredDialogProps,
|
|
49
66
|
type AuthSession,
|
|
50
67
|
type UseAgentChatContextResult,
|
|
68
|
+
type AgentNativeI18nCatalog,
|
|
69
|
+
type AgentNativeI18nProviderProps,
|
|
70
|
+
type LocaleCode,
|
|
71
|
+
type LocaleHydrationPayload,
|
|
72
|
+
type LocaleMessages,
|
|
73
|
+
type LocaleMetadata,
|
|
74
|
+
type LocalePreference,
|
|
75
|
+
type LocalizationPreference,
|
|
51
76
|
} from "./client/index.js";
|
|
52
77
|
|
|
53
78
|
// Shared (isomorphic)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineAction } from "../../action.js";
|
|
3
|
+
import { getUserSetting } from "../../settings/user-settings.js";
|
|
4
|
+
import {
|
|
5
|
+
LOCALIZATION_SETTING_KEY,
|
|
6
|
+
normalizeLocalizationPreference,
|
|
7
|
+
type LocalizationPreference,
|
|
8
|
+
} from "../shared.js";
|
|
9
|
+
|
|
10
|
+
export default defineAction({
|
|
11
|
+
description:
|
|
12
|
+
"Get the current user's interface language preference. Returns { locale }, where locale is 'system' or a supported BCP-47 locale.",
|
|
13
|
+
schema: z.object({}),
|
|
14
|
+
http: { method: "GET" },
|
|
15
|
+
run: async (_args, ctx): Promise<LocalizationPreference> => {
|
|
16
|
+
if (!ctx?.userEmail) throw new Error("Not authenticated.");
|
|
17
|
+
const stored = await getUserSetting(
|
|
18
|
+
ctx.userEmail,
|
|
19
|
+
LOCALIZATION_SETTING_KEY,
|
|
20
|
+
);
|
|
21
|
+
return normalizeLocalizationPreference(stored);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineAction } from "../../action.js";
|
|
3
|
+
import { putUserSetting } from "../../settings/user-settings.js";
|
|
4
|
+
import {
|
|
5
|
+
LOCALIZATION_SETTING_KEY,
|
|
6
|
+
normalizeLocalePreference,
|
|
7
|
+
type LocalizationPreference,
|
|
8
|
+
} from "../shared.js";
|
|
9
|
+
|
|
10
|
+
export default defineAction({
|
|
11
|
+
description:
|
|
12
|
+
"Set the current user's interface language preference to 'system' or a supported BCP-47 locale.",
|
|
13
|
+
schema: z.object({
|
|
14
|
+
locale: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe("Language preference: 'system' or a supported BCP-47 locale."),
|
|
17
|
+
}),
|
|
18
|
+
run: async (args, ctx): Promise<LocalizationPreference> => {
|
|
19
|
+
if (!ctx?.userEmail) throw new Error("Not authenticated.");
|
|
20
|
+
const locale = normalizeLocalePreference(args.locale);
|
|
21
|
+
if (!locale) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"Unsupported locale. Use system, en-US, zh-CN, es-ES, fr-FR, de-DE, ja-JP, ko-KR, pt-BR, hi-IN, or ar-SA.",
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
const value: LocalizationPreference & Record<string, unknown> = { locale };
|
|
27
|
+
await putUserSetting(ctx.userEmail, LOCALIZATION_SETTING_KEY, value);
|
|
28
|
+
return value;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_LOCALE,
|
|
3
|
+
LOCALE_HYDRATION_GLOBAL,
|
|
4
|
+
LOCALE_STORAGE_KEY,
|
|
5
|
+
SUPPORTED_LOCALES,
|
|
6
|
+
localeDirection,
|
|
7
|
+
normalizeLocaleCode,
|
|
8
|
+
normalizeLocalizationPreference,
|
|
9
|
+
resolveLocaleFromPreference,
|
|
10
|
+
type LocaleCode,
|
|
11
|
+
type LocalePreference,
|
|
12
|
+
type LocalizationPreference,
|
|
13
|
+
} from "./shared.js";
|
|
14
|
+
|
|
15
|
+
interface RequestLike {
|
|
16
|
+
headers?: Headers | Record<string, string | string[] | undefined> | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type HeaderMap = Headers | Record<string, string | string[] | undefined>;
|
|
20
|
+
|
|
21
|
+
export interface ResolvedRequestLocale {
|
|
22
|
+
locale: LocaleCode;
|
|
23
|
+
preference: LocalizationPreference;
|
|
24
|
+
dir: "ltr" | "rtl";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ResolveLocaleFromRequestOptions {
|
|
28
|
+
request?: Request | RequestLike | null;
|
|
29
|
+
acceptLanguage?: string | null;
|
|
30
|
+
preference?: LocalizationPreference | LocalePreference | null;
|
|
31
|
+
fallback?: LocaleCode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface LocaleInitScriptOptions {
|
|
35
|
+
locale?: LocaleCode;
|
|
36
|
+
preference?: LocalizationPreference | LocalePreference;
|
|
37
|
+
messages?: Record<string, unknown> | null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readHeader(
|
|
41
|
+
headers: HeaderMap | undefined | null,
|
|
42
|
+
key: string,
|
|
43
|
+
): string | null {
|
|
44
|
+
if (!headers) return null;
|
|
45
|
+
if (typeof (headers as Headers).get === "function") {
|
|
46
|
+
return (headers as Headers).get(key);
|
|
47
|
+
}
|
|
48
|
+
const lowerKey = key.toLowerCase();
|
|
49
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
50
|
+
if (name.toLowerCase() !== lowerKey) continue;
|
|
51
|
+
if (Array.isArray(value)) return value.join(",");
|
|
52
|
+
return value ?? null;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function parseAcceptLanguage(header: string | null | undefined) {
|
|
58
|
+
if (!header) return [];
|
|
59
|
+
return header
|
|
60
|
+
.split(",")
|
|
61
|
+
.map((part) => {
|
|
62
|
+
const [tag, ...params] = part.trim().split(";");
|
|
63
|
+
const q = params
|
|
64
|
+
.map((param) => param.trim())
|
|
65
|
+
.find((param) => param.startsWith("q="));
|
|
66
|
+
const weight = q ? Number.parseFloat(q.slice(2)) : 1;
|
|
67
|
+
return {
|
|
68
|
+
tag,
|
|
69
|
+
weight: Number.isFinite(weight) ? weight : 0,
|
|
70
|
+
};
|
|
71
|
+
})
|
|
72
|
+
.filter((entry) => entry.tag && entry.weight > 0)
|
|
73
|
+
.sort((a, b) => b.weight - a.weight)
|
|
74
|
+
.map((entry) => entry.tag);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function resolveLocaleFromRequest(
|
|
78
|
+
options: ResolveLocaleFromRequestOptions = {},
|
|
79
|
+
): ResolvedRequestLocale {
|
|
80
|
+
const header =
|
|
81
|
+
options.acceptLanguage ??
|
|
82
|
+
readHeader(options.request?.headers, "accept-language");
|
|
83
|
+
const candidates = parseAcceptLanguage(header);
|
|
84
|
+
const preference = normalizeLocalizationPreference(
|
|
85
|
+
options.preference ?? { locale: "system" },
|
|
86
|
+
);
|
|
87
|
+
const locale =
|
|
88
|
+
preference.locale === "system"
|
|
89
|
+
? resolveLocaleFromPreference(preference, [
|
|
90
|
+
...candidates,
|
|
91
|
+
options.fallback ?? DEFAULT_LOCALE,
|
|
92
|
+
])
|
|
93
|
+
: (normalizeLocaleCode(preference.locale) ??
|
|
94
|
+
options.fallback ??
|
|
95
|
+
DEFAULT_LOCALE);
|
|
96
|
+
return {
|
|
97
|
+
locale,
|
|
98
|
+
preference,
|
|
99
|
+
dir: localeDirection(locale),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getLocaleInitScript(options: LocaleInitScriptOptions = {}) {
|
|
104
|
+
const safeLocale = normalizeLocaleCode(options.locale) ?? DEFAULT_LOCALE;
|
|
105
|
+
const shouldStorePreference = options.preference !== undefined;
|
|
106
|
+
const safePreference = normalizeLocalizationPreference(
|
|
107
|
+
options.preference ?? { locale: "system" },
|
|
108
|
+
);
|
|
109
|
+
const payload = {
|
|
110
|
+
locale: safeLocale,
|
|
111
|
+
preference: safePreference,
|
|
112
|
+
dir: localeDirection(safeLocale),
|
|
113
|
+
messages: options.messages ?? undefined,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return `(function(){try{var supported=${JSON.stringify(
|
|
117
|
+
SUPPORTED_LOCALES,
|
|
118
|
+
)};var payload=${JSON.stringify(
|
|
119
|
+
payload,
|
|
120
|
+
)};var shouldStorePreference=${JSON.stringify(
|
|
121
|
+
shouldStorePreference,
|
|
122
|
+
)};function valid(x){return supported.indexOf(x)>=0}function canon(x){if(typeof x!=='string'||!x)return null;try{var c=Intl.getCanonicalLocales(x)[0];if(valid(c))return c;var lang=c&&c.split('-')[0].toLowerCase();for(var i=0;i<supported.length;i++){if(supported[i].split('-')[0].toLowerCase()===lang)return supported[i]}}catch(e){}return null}function storageGet(k){try{return window.localStorage.getItem(k)}catch(e){return null}}function storageSet(k,v){try{window.localStorage.setItem(k,v)}catch(e){}}var stored=storageGet(${JSON.stringify(
|
|
123
|
+
LOCALE_STORAGE_KEY,
|
|
124
|
+
)});var pref=payload.preference&&payload.preference.locale;var locale=payload.locale;if(!valid(locale)){locale=null}if(!locale&&stored&&stored!=='system'){locale=canon(stored)}if(!locale&&pref&&pref!=='system'){locale=canon(pref)}if(!locale){var langs=navigator.languages&&navigator.languages.length?navigator.languages:[navigator.language];for(var j=0;j<langs.length&&!locale;j++){locale=canon(langs[j])}}if(!locale)locale=${JSON.stringify(
|
|
125
|
+
DEFAULT_LOCALE,
|
|
126
|
+
)};var root=document.documentElement;root.setAttribute('lang',locale);root.setAttribute('dir',locale==='ar-SA'?'rtl':'ltr');root.setAttribute('data-locale',locale);payload.locale=locale;payload.dir=locale==='ar-SA'?'rtl':'ltr';window[${JSON.stringify(
|
|
127
|
+
LOCALE_HYDRATION_GLOBAL,
|
|
128
|
+
)}]=payload;if(shouldStorePreference&&pref){storageSet(${JSON.stringify(
|
|
129
|
+
LOCALE_STORAGE_KEY,
|
|
130
|
+
)},pref)}}catch(e){}})();`;
|
|
131
|
+
}
|