Commit Graph
261 Commits
Author SHA1 Message Date
Neko Ayaka 1927e54c9c fix(stage-ui,stage-pocket,stage-web,stage-tamagotchi,ui-server-auth): analytics import not deferred or lazied 2026-07-30 14:33:21 +08:00
RainbowBird 97cf26082f refactor(ui): share user avatar fallbacks (#2143) 2026-07-29 18:38:37 +08:00
RainbowBird f414d165de fix(stage-ui): preserve character card runtime data (#2111) 2026-07-26 20:50:19 +08:00
RainbowBird 20355670a9 fix(stage-pages): sync active card sessions (#2110) 2026-07-26 17:45:04 +08:00
RainbowBird 019d3fa15f fix(stage-pages): validate and preserve AIRI Card drafts (#2109)
Signed-off-by: RainbowBird <git@luoling.moe>
2026-07-26 17:05:28 +08:00
eabec9a64f feat(stage-ui-mmd): add MMD support (#1997)
---------

Co-authored-by: nyueki <nyuek.i@proton.me>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Neko Ayaka <neko@ayaka.moe>
Co-authored-by-agent: Unknown
2026-07-20 16:13:55 +08:00
0xSelenicDove 38f7460558 fix(stage-tamagotchi): refresh chats after import (#2088) 2026-07-20 16:10:11 +08:00
Ayobami Adegoke 774aed92bb fix(stage-ui): make provider capability checks non-throwing and reset chat model on provider switch (#2078) 2026-07-18 03:03:12 +08:00
Ryanba fb2b3f5ce9 fix(stage-pages): add local provider WIP routes (#2045) 2026-07-17 17:53:09 +08:00
Alan-Yu-2077 f453a967f1 feat(stage-ui): add web search tool so the character can look things up online (#2066)
Co-authored-by-agent: Unknown
2026-07-17 17:49:06 +08:00
RainbowBird 0e4dc69ec0 fix(analytics): normalize PostHog event semantics (#2041) 2026-07-10 13:54:23 +08:00
RainbowBird 0642ede8d1 feat(analytics): expand PostHog coverage and forward server business facts (#2038)
## What

Closes the three structural gaps in AIRI's product analytics: the signup
surface had zero instrumentation, the payment funnel had no terminator
in PostHog, and SPA route changes emitted no pageviews. Also adds
semantic events for character cards, desktop-only features, and
data-maintenance actions.

## User paths

- User signs up / logs in / verifies email / resets password / links
OAuth / deletes account → each step now emits a PostHog event from
`apps/ui-server-auth` (previously fully uninstrumented), with
`identify()` wired on session load so anonymous funnel events merge into
the user person.
- User pays via Stripe → webhook writes `product_events` as before, and
the product-events service now forwards `payment_completed` (plus signup
and subscription lifecycle facts) to PostHog via posthog-node
`captureImmediate`, keyed by the Better Auth user id → the
`checkout_started → payment_completed` funnel closes end-to-end.
Per-request LLM/TTS volume is explicitly not forwarded.
- User navigates between routes in any surface (web / desktop / pocket /
docs) → `$pageview` + `$pageleave` fire per route change via the
posthog-js `defaults: '2025-05-24'` preset in the shared
`posthog.config.ts`.
- User creates / imports / duplicates / edits a ccv3 card, switches
stage background, runs destructive data actions (export / import / clear
chats, reset providers, wipe app data), or uses desktop differentiators
(Spotlight send, widget windows, in-app updater, MCP server management,
pairing QR) → dedicated low-cardinality events.

## Notable decisions

- Server forwarding defaults on: `POSTHOG_PROJECT_KEY` defaults to the
shared browser-safe phc_* project key; set it to an empty string to
disable. Postgres `product_events` remains the source of truth.
- Cross-surface events (`oauth_callback_failed`, account lifecycle)
share one stage vocabulary exported from stage-ui so the two emitters
cannot drift silently.
- Events captured right before full-page navigation use `sendBeacon` so
they survive the redirect (checkout, OAuth consent handoff, login
redirect).
- Removed dead wrappers (`trackSignup`, `trackFirstModelSelected`,
`trackModelChanged`) that duplicated live event streams under second
names.

## How tested

- `pnpm -F @proj-airi/server exec vitest run
src/services/domain/product-events.test.ts` — 6 passed, covering the
forwarding allowlist, the `user_signed_up → signup_completed` mapping,
non-forwarded per-request actions, and a throwing sink not failing the
webhook path nor losing the DB row.
- stage-ui suites (`use-analytics`, `use-linked-accounts`, exports
contract) — 22 passed, including new account/card/data/desktop event
assertions.
- Real transport smoke: posthog-node `captureImmediate` against
`us.i.posthog.com` with the production key resolved in 1380ms (one
`server_forwarding_smoke_test` event left in the project; filter by
event name).
- Browser-tested pageviews: `VITE_ENABLE_POSTHOG=true` dev build, two
`history.pushState` route changes each produced a `$pageview` with
`$pathname`, `navigation_type: pushState`, previous-page dwell time, and
the `surface` super property; batched POST to `us.i.posthog.com/e/`
returned 200. Note: posthog-js drops events from automated browsers
(`navigator.webdriver`) by default — the verification session bypassed
the bot filter locally; production config is untouched.
- Typecheck and lint pass for server, stage-ui, stage-pages, stage-web,
stage-tamagotchi, ui-server-auth.

Full verification record:
`apps/server/docs/ai-context/verifications/posthog-forwarding-and-pageview.md`

## Follow-ups (not in this PR)

- Bot channel usage stats (Discord / Telegram) once they route through
server-runtime counters.
- Main-process desktop events (tray menu, global shortcut fire) need
renderer relay plumbing.
- Confirm `payment_completed` arrives in PostHog after the first real
Stripe payment post-deploy.

https://claude.ai/code/session_01Q1yGavkQ1P41YhTWE4XKex
2026-07-08 15:33:39 +08:00
Dojiandautofix-ci[bot] 5aa44aedd3 feat(stage-ui): add character card import and export (#1998)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-08 14:14:43 +08:00
Lovehsigure_520 2da9d37add feat(analytics): add official provider ops metrics
Build on existing pricing funnel events with official provider, TTS usage, second-turn activation, and Flux balance bucket metrics.
2026-07-01 21:19:42 +08:00
RainbowBird 0daac71435 feat(analytics): add p0 operations events 2026-07-01 20:16:06 +08:00
RainbowBird 27255001bd refactor: streamline speech module by removing voice pack dependencies
- Removed voice pack related imports and functionality from speech.vue and Stage.vue.
- Simplified speech input handling by eliminating voice pack parameters in speech store.
- Updated tests to reflect changes in voice pack handling and speech input resolution.
- Adjusted Airi card store to remove voice pack binding logic, focusing on speech configuration updates.
- Enhanced voice pack list item structure for clarity and maintainability.
2026-07-01 19:23:33 +08:00
RainbowBird c2aee68513 feat: add upstreamVoiceId to voice packs and related services
- Introduced upstreamVoiceId field in voice pack schema and database.
- Updated voice pack service to handle upstreamVoiceId in CRUD operations.
- Modified API routes and tests to accommodate upstreamVoiceId.
- Enhanced UI components to include upstreamVoiceId in forms and displays.
- Adjusted speech processing logic to utilize upstreamVoiceId where applicable.
- Updated related tests to ensure proper functionality with new field.
2026-07-01 16:07:33 +08:00
RainbowBird 1f1ef49eed feat(speech): refactor voice pack handling and remove synthetic model references 2026-07-01 02:47:31 +08:00
RainbowBird 71482d3859 feat(speech): implement Voice Pack model option and integrate into settings 2026-07-01 00:45:08 +08:00
Lovehsigure_520 5f13127810 fix(analytics): address speech preview review (#2024)
## Summary
- attach manual preview analytics metadata to official TTS preview
requests
- avoid tracking custom voice selection during settings sync or every
input keystroke

## Tests
- corepack pnpm -F @proj-airi/stage-pages typecheck
- corepack pnpm exec eslint
packages/stage-pages/src/pages/settings/modules/speech.vue
- git diff --check
2026-07-01 00:20:36 +08:00
Lovehsigure_520 3d7a8300d8 feat(analytics): add product instrumentation for activation and voice flows (#2023) 2026-06-30 23:36:08 +08:00
Lovehsigure_520 8c6e4576e1 refactor(stage-tamagotchi,stage-ui): improve input transcription pipeline (#2001)
---------

Co-authored-by-agent: Codex <codex@openai.com>
2026-06-26 16:05:02 +08:00
Ryan Leiandleiyutian 70d1c317df feat(stage-ui): add Google Gemini TTS provider (#1828)
---------

Co-authored-by: leiyutian <leiyutian@echo.tech>
Co-authored-by-agent: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 06:41:45 +00:00
Doji 5c60cb7661 fix(stage-ui): sync module selections to active character card (#1979) 2026-06-18 11:21:00 +08:00
Doji 27569c94f2 fix(stage-pages): add vision provider settings (#1987) 2026-06-17 17:52:53 +08:00
Doji 3a41215785 fix(stage-pages): restore speech none option (#1969) 2026-06-14 11:34:07 +00:00
RainbowBird 3215687e98 feat(server): add Aliyun NLS ASR gateway and official transcription provider (#1970) 2026-06-14 04:22:07 +08:00
Neko Ayaka 0f975a4f73 refactor(stage-tamagotchi,plugin-*): unified to extension id 2026-06-12 19:27:23 +08:00
Doji 8b98a2c138 feat(stage-tamagotchi):add spotlight (#1959) 2026-06-12 02:53:35 +08:00
Nekoandautofix-ci[bot] 668440a732 refactor(extension-*,stage-tamagotchi,stage-ui,server-*): rename to extension, improve DX (#1892)
---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by-agent: Codex
2026-06-12 02:03:42 +08:00
RainbowBird 16f9aaa4e3 feat(auth): enhance OAuth linking flow with account selection and error handling
- 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.
2026-06-10 16:42:13 +08:00
Lulu aa5223ad73 feat(stage): hide BYOK providers for Steam builds via VITE_DISABLE_CUSTOM_PROVIDERS (#1908) 2026-06-10 16:36:31 +08:00
Lulu 0647f5b37a feat(stage): hide flux purchase UI for Steam builds via VITE_DISABLE_FLUX_PURCHASE (#1912) 2026-06-08 13:51:10 +08:00
RainbowBird 9382a12137 chore: cleanup and lint fix 2026-06-07 20:31:22 +08:00
RainbowBird 007fae6810 chore: update package dependencies and remove specific catalog references
- Removed specific catalog references for '@unocss/core', 'es-toolkit', 'nanoid', and 'valibot' in pnpm-workspace.yaml and various service package.json files.
- Updated versions for '@vueuse/core', 'es-toolkit', 'nanoid', 'reka-ui', and 'valibot' to their latest compatible versions.
- Cleaned up unused catalog entries in pnpm-workspace.yaml.
2026-06-07 19:45:28 +08:00
RainbowBird eae942702c feat(speech): enhance voice pack handling and add computed properties for UI logic 2026-06-07 01:56:04 +08:00
RainbowBird e6fa39ed4b feat(server): voice pack and tts routing (#1905)
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.
2026-06-05 22:39:30 +08:00
RainbowBird 7841df28f8 build(deps): migrate workspace dependencies to catalogs
Move direct external dependency versions into pnpm catalogs and update workspace packages to reference catalog entries.

Signed-off-by: RainbowBird <git@luoling.moe>

Commit-Message-Assisted-by: Codex
2026-06-03 17:12:13 +08:00
88fac74702 fix(stage-ui): correct provider source filter categories (#1929)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: LemonNeko <self@lemonneko.moe>
2026-06-02 16:02:00 +00:00
RainbowBird 7e96386ec0 fix(server): unblock FLUX checkout from Electron desktop renderer
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.
2026-05-26 01:56:47 +08:00
RainbowBird 6f63ce96e9 feat(server): server-controlled default streaming TTS model
The streaming speech provider settings page was seeding its model
picker with a hardcoded `volcengine/seed-tts-2.0`, which contradicts
the just-landed "streaming model catalog comes from the server"
contract. Now the default also comes from configKV.

- `UNSPEECH_UPSTREAM.streaming` gains `defaultModel?: string`.
- `GET /api/v1/audio/models/streaming` response gains `default: string
  | null` reading that field.
- admin slice apply: `streaming.defaultModel` survives key/URL
  rotation alongside `streaming.models`.
- `providerOfficialSpeechStreaming.listModels` stashes the value in a
  module-scope ref, exposed via `getDefaultStreamingModel()`.
- Streaming speech settings page reads the helper instead of the
  hardcoded id; falls back to the first server-returned model if the
  operator hasn't curated a default. `handleGenerateSpeech` no longer
  has a `seed-tts-2.0` backstop — a missing backend prefix in the
  selected model id now throws instead of silently defaulting.
2026-05-24 21:13:52 +08:00
jim139129 cd908015b3 fix(stage-ui): default artistry provider to none (#1854) 2026-05-21 03:05:55 +08:00
Neko Ayaka 10f340a651 fix(stage-ui): missing and incorrect flex gap 2026-05-20 01:46:18 +08:00
nyueki 4542a9d290 feat(stage-ui-spine): add Spine 2D runtime integration (#1810) 2026-05-19 19:13:35 +08:00
RainbowBird efe0f8ac19 refactor(server): streaming tts support model switch 2026-05-18 23:35:38 +08:00
RainbowBird ba9247fb47 feat(server,stage-ui): bidirectional streaming TTS + audio path refactor
Why:
- Add a real bidirectional streaming TTS path: raw LLM tokens are
  forwarded to the upstream model (Volcengine v3 via the unspeech ws
  bridge) without client-side segmentation, so the model owns sentence
  splitting and audio chunks play as they arrive.
- Move audio endpoints out of /api/v1/openai/. `/audio/voices`,
  `/audio/models`, `/audio/voices/streaming` are not real OpenAI public
  APIs, and the streaming TTS surface has nothing to do with OpenAI —
  keeping them under /openai/ mislabelled the contract.
- Introduce `capabilities.speech.transport` on ProviderDefinition so
  future streaming providers (ElevenLabs / Cartesia / OpenAI Realtime)
  opt in without touching Stage.vue or the session factory.
- Unify Stage.vue's TTS path through a single StageTtsSession so the
  chat-orchestrator hooks no longer branch on provider id.

What:
- apps/server: new ws proxy /api/v1/audio/speech/ws bridges client ↔
  unspeech with auth, pre-flight flux check, billing from upstream
  session.finished.usage, OTel spans.
- apps/server: audio routes moved from /api/v1/openai/audio/* to
  /api/v1/audio/* (hard cutover; 404 sentinel tests added).
- apps/server: new /api/v1/audio/voices/streaming proxy reads voices
  from unspeech /api/voices?provider=volcengine.
- apps/server: new STREAMING_TTS_UPSTREAM configKV entry +
  scripts/seed-streaming-tts.ts.
- stage-ui: new libs/speech/streaming-pipeline.ts opens one ws per LLM
  intent (appendText / finish / cancel + onSentence / onError / onDone).
- stage-ui: new libs/speech/tts-session.ts — StageTtsSession interface
  with segmenter and streaming adapters; factory dispatches by
  capabilities.speech.transport instead of hard-coded provider id.
- stage-ui: providerOfficialSpeechStreaming with capabilities.speech =
  { transport: 'bidirectional-ws' }; settings page with model/voice
  picker + ws-based preview.
- stage-ui: Stage.vue chat hooks collapsed to a single currentSession;
  hot-swap watcher cancels mid-session on provider/voice/model change;
  unmount cancels and drains playback.

Tests:
- 9 streaming-pipeline tests (happy path / buffered / error / cancel /
  truncation)
- 11 tts-session tests (factory branch coverage + adapter contracts)
- 4 audio-speech-ws route tests (forwarding / billing / pre-flight /
  config-missing)
- 3 legacy-path 404 sentinels in v1 route tests
- Verification doc updated to reflect automated coverage.
2026-05-18 23:34:35 +08:00
Neko Ayaka f33d485b82 feat(stage-ui): io tracer for CALL tokens 2026-05-18 01:23:14 +08:00
RainbowBird 3984677b01 feat(analytics): integrate PostHog for server-side event tracking
- Added a new PostHog client for capturing server-side business events such as Stripe webhooks and subscription state changes.
- Implemented various tracking functions for pricing funnel steps, character creation, and chat session starts.
- Enhanced the flux meter tests to handle partial charges and report unbilled flux correctly.
- Updated the CharacterDialog and Flux settings pages to track user interactions with analytics events.
- Introduced a mechanism to identify users on PostHog based on authentication state to ensure accurate funnel tracking.
- Added necessary dependencies for PostHog integration in the project.
2026-05-15 16:20:47 +08:00
RainbowBird 54b0af0a08 chore(stage-pages): resolve type 2026-05-08 21:34:11 +08:00
RainbowBird 99956014fa feat(server): admin api (#1788) 2026-05-08 21:14:00 +08:00