- Implemented `buildBedrockSlice` function to handle multi-kilobyte Bedrock bearer tokens.
- Enhanced `createAdminRouterConfigService` to classify Bedrock and OpenAI-compatible LLM upstreams by baseURL.
- Added new interfaces for `AdminRouterBedrockSlice` and `AdminRouterOpenAICompatibleSlice`.
- Updated router config form to support Bedrock and OpenAI-compatible slices.
- Created tests for Bedrock and OpenAI-compatible slice compilation and behavior.
- Modified UI components to accommodate new slice types and improve user experience.
- Ensured proper normalization of API server URLs to HTTPS when necessary.
Add a form-first LLM/TTS router config editor and a redacted admin config snapshot so operators can inspect configKV state before applying changes.
Preserve existing encrypted key entries when loaded slices are submitted without new plaintext keys.
Signed-off-by: RainbowBird <git@luoling.moe>
Commit-Message-Assisted-by: Claude (via Claude Code)
- Added `prompt: 'select_account'` for Google and GitHub providers to force account selection during OAuth linking.
- Introduced localized error messages for account linking issues in multiple languages.
- Implemented a function to resolve OAuth error codes to specific i18n keys for better user feedback.
- Updated account settings page to display relevant error messages based on OAuth linking status.
Add PostHog product events for manual TTS stop clicks and conversation controls across Web, mobile, and Electron chat surfaces. Document the events in metrics ownership and cover the analytics API with Vitest.
Signed-off-by: RainbowBird <git@luoling.moe>
Commit-Message-Assisted-by: Codex
Track per-app TTS concurrency in Redis, route capped upstreams by
available pool capacity, and surface pool saturation metrics. Document
the Voice Pack plan so the remaining backend and card-binding work has
an explicit implementation map.
Upgrade @moeru/eventa to v1.0.0-beta.8 through the pnpm catalog and remove the local Hono adapter copy.
Keep AIRI on business-level Eventa usage while adapter contract tests live upstream in @moeru/eventa.
Signed-off-by: RainbowBird <git@luoling.moe>
Commit-Message-Assisted-by: Claude (via Claude Code)
Separate OpenAI-compatible route wiring from chat, speech, catalog, billing, and telemetry pipeline code.
Signed-off-by: RainbowBird <git@luoling.moe>
Commit-Message-Assisted-by: Claude (via Claude Code)
The packaged Electron renderer loads from file://, so its Stripe checkout
and portal requests carry no Referer and an opaque/absent Origin.
resolveTrustedRequestOrigin() returned undefined and the routes threw
INVALID_ORIGIN ("Missing trusted request origin"), blocking FLUX purchases
on desktop. Web and mobile were unaffected because they send a trusted web
origin. CORS was not the blocker: file:// requests already reach the API
(balance, providers, characters all work), so only the checkout-specific
redirect-base dependency failed.
Stripe success_url/cancel_url/return_url must be http(s) URLs, so file://
can never be a valid redirect base. Replace the trusted-origin requirement
with resolveCheckoutRedirectBase(), which prefers the request's trusted
origin (web/mobile return to where they started) and falls back to a
configured canonical web app URL (WEB_APP_URL, default https://airi.moeru.ai)
for origin-less clients like the desktop app.
On the client, the desktop app opens checkout in the system browser via
window.open (routed through setWindowOpenHandler -> shell.openExternal)
instead of navigating the file:// window to Stripe, and refreshes the FLUX
balance on window focus since it never receives the success_url redirect.