Files
moeka-project/apps/server
RainbowBird be2c355b0e refactor(server): merge STREAMING_TTS_UPSTREAM + UNSPEECH_REST_BASE_URL into UNSPEECH_UPSTREAM
One unspeech deployment = one configKV entry. The split into two keys
modelled a hypothetical split deployment (operators pointing REST and
WS at different unspeech instances) that nobody actually runs, and the
explanatory comments justifying the split were exactly the migration-
narrative anti-pattern we just banned from source.

Schema:

  UNSPEECH_UPSTREAM = {
    restBaseURL: string,                  // required, http(s)://host:port
    streaming?: {                         // optional, only when ws TTS is on
      baseURL: string,                    // ws(s)://host:port/...
      keys: [{ id, ciphertext }],
      adapterParams: {},
      models?: [{ id, name?, description? }],
    },
  }

Admin slice surface flattens to one `kind: 'unspeech'`:

  { kind: 'unspeech', restBaseURL,
    streaming?: { upstreamURL, plaintextKey, keyEntryId? } }

Read-site changes:
- routeTts + listTtsVoices read UNSPEECH_UPSTREAM.restBaseURL via
  getOrThrow; absent entry → 503 CONFIG_NOT_SET.
- audio-speech-ws dials UNSPEECH_UPSTREAM.streaming and 1008-closes
  with streaming_tts_not_configured when the subtree is absent.
- handleListStreamingVoices reads .restBaseURL directly (no more
  ws→http scheme swap) and 503s on missing streaming subtree.
- handleListStreamingTTSModels reads .streaming.models.
- config-sync-subscriber listens for UNSPEECH_UPSTREAM invalidations
  instead of UNSPEECH_REST_BASE_URL.

Drive-by: tighten ConfigKVService.getOrThrow return to
`Exclude<ConfigDefinitions[K], undefined>` so call sites stop needing
non-null assertions on optional schema entries — the runtime already
throws, the type now reflects it.

Migration: operators repost a single admin slice to rewrite the merged
entry. Old STREAMING_TTS_UPSTREAM and UNSPEECH_REST_BASE_URL rows
become dead data and can be deleted from configKV; nothing reads them.
2026-05-19 23:28:42 +08:00
..
2026-05-18 23:48:11 +08:00
2026-01-05 16:26:44 +08:00
2026-05-18 23:33:24 +08:00

@proj-airi/server

HTTP and WebSocket backend for AIRI. This app owns auth, billing, chat synchronization, gateway forwarding, and server-side observability export.

What It Does

  • Serves the Hono-based API and WebSocket endpoints.
  • Uses Postgres as the source of truth for users, billing, and durable state.
  • Uses Redis for cache, KV, Pub/Sub, and Streams.
  • Forwards GenAI requests to the configured upstream gateway and records billing from usage.
  • Exports traces, metrics, and logs through OpenTelemetry.

How To Use It

Install dependencies from the repo root and run scoped commands:

pnpm -F @proj-airi/server typecheck
pnpm -F @proj-airi/server exec vitest run
pnpm -F @proj-airi/server build

For local observability infrastructure, use:

docker compose -f apps/server/docker-compose.otel.yml up -d

ADDITIONAL_TRUSTED_ORIGINS (LAN / Capacitor dev)

When the mobile dev server uses a non-localhost origin (for example https://10.x.x.x:5273 from cap copy ios / capacitor.config.json), set ADDITIONAL_TRUSTED_ORIGINS in apps/server/.env.local to a comma-separated list of exact origins (parsed and normalized at startup). Example:

ADDITIONAL_TRUSTED_ORIGINS=https://10.0.0.129:5273,https://198.18.0.1:5273

Restart the API server after changing this variable.