Commit Graph
4224 Commits
Author SHA1 Message Date
AdairLi c4778686ff fix(stage-ui): flashing and unreadable validator (#2302)
## Description

Fix the flashing validator on the provider setting page which is unable
to read and interface. Now it is stable to show the status of the
provider and help users to do the further config.

## Linked Issues

#2301 


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved credential validation stability by preventing repeated
validation for equivalent credential values.
* Preserved debounced validation behavior and manual test state resets.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-17 11:24:20 +08:00
Neko 73c05d37eb fix(stage-tamagotchi): prevent auxiliary renderer request storms (#2304) 2026-08-16 22:08:18 +08:00
yzxcj797 d768f5a334 docs: fix three groups of dead links (#2300) 2026-08-16 20:44:21 +08:00
RainbowBird 85a3f08987 fix(docker): update drizzle-migration build process to prevent virtual import issues 2026-08-16 17:03:38 +08:00
RainbowBird c25791a357 refactor(auth): replace admin plugin with ban guard (#2303) 2026-08-16 16:16:36 +08:00
RainbowBird 88625a8d84 feat(api): hot-reload ConfigKV from Postgres (#2289)
## Summary

- Add the `config_kv` schema and Drizzle migration `0020`.
- Keep the ConfigKV schema, cache store, and invalidation contract in
the Resource API.
- Read ConfigKV through a five-minute Redis cache with PostgreSQL
fallback.
- Reload Router and TTS voice state through `configkv:invalidate`.
- Keep Auth rate limits fixed at 20 requests per 60 seconds.

## Stack

- Depends on #2294 for the Redis test implementation.
- This PR adds ConfigKV-specific cache-aside and Pub/Sub tests on top of
that implementation.

## Deployment

Run migration `0020` before this runtime reaches production traffic.

Then freeze ConfigKV writes. Audit and backfill the data with
[proj-airi/backend#2](https://github.com/proj-airi/backend/pull/2).
Merge
[proj-airi/backend#4](https://github.com/proj-airi/backend/pull/4)
first, so
the fixed Auth rate-limit keys are skipped.

Keep writes frozen until the hashes match and two API instances pass the
Pub/Sub reload check. This PR does not run production DDL or data
migration.

## Verification

- `pnpm exec vitest run <ConfigKV cache store, sync subscriber, and Auth
rate-limit tests>` (12 tests passed)
- `pnpm -F @proj-airi/api-server typecheck`
- `git diff --check`

See #2294 for its frozen-install, ESLint, and 73-test verification.

## Visual changes

None. This PR changes backend persistence and rate-limit wiring only.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added centralized configuration storage with validation, caching,
refresh, and automatic synchronization across services.
- Configuration updates now refresh related language-model and
text-to-speech settings automatically.

- **Bug Fixes**
- Improved recovery after service reconnects by clearing stale
configuration and reloading current values.
- Invalid or unavailable configuration data now produces clearer
service-unavailable responses.

- **Changes**
- Authentication rate limiting now uses a consistent limit of 20
requests per minute per client.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: RainbowBird <git@luoling.moe>
Signed-off-by: RainbowBird <rbxin2003@outlook.com>
2026-08-15 22:24:32 +08:00
RainbowBirdandautofix-ci[bot] ab5e43ae0c test(server): use ioredis-mock for Redis behavior (#2294)
## Summary

- Replace Redis command fakes with `ioredis-mock` in API tests.
- Run the production Lua scripts through `EVAL`.
- Keep Redis behavior tests on the same command and Pub/Sub
implementation used by production code.

## Stack

- This PR is the base for #2289.
- It replaces #2291 as the merge-to-`main` unit. #2291 merged into the
old
  ConfigKV branch before the stack could be reordered.

## Tests

- `pnpm install --frozen-lockfile --offline --ignore-scripts`
- `pnpm exec vitest run <6 changed API test files>` (73 tests passed)
- `pnpm exec eslint <7 changed API TypeScript files>`
- `git diff --check`

## Visual changes

None. This PR changes test infrastructure only.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
  * Added isolated in-memory Redis support for automated testing.
* Updated billing, Stripe, flux, concurrency, and user-deletion tests to
use a shared Redis test setup.
* Improved verification of Redis operations while preserving existing
test coverage and expected outcomes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: RainbowBird <rbxin2003@outlook.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-15 21:43:30 +08:00
RainbowBird 44cd0cfe68 fix(stage-ui): normalize streaming transcription audio chunks (#2285) 2026-08-15 19:37:45 +08:00
RainbowBird 3da1ce163c chore(server): remove admin routes 2026-08-15 14:27:59 +08:00
c71de3a0b1 feat(stage-ui): add DeepSeek thinking mode toggle (#2280)
Co-authored-by: 冼健聪 <mark.xian@evenrealities.com>
Co-authored-by: RainbowBird <git@luoling.moe>
2026-08-14 19:53:14 +08:00
Neko 133df1f1e6 test: run Vitest browser projects headlessly (#2284) 2026-08-14 19:31:00 +08:00
RainbowBird f45bb2e678 fix(stage-ui): make streaming transcription requests half-duplex (#2283) 2026-08-14 19:21:48 +08:00
Lovehsigure_520 497546e02f fix(auth-ui): hide sign-in form during provider handoff (#2282) 2026-08-14 11:04:57 +00:00
Neko Ayaka ebf34968e2 chore(deps): updated 2026-08-14 18:47:19 +08:00
Neko Ayaka e93a637058 chore(deps): updated 2026-08-14 18:40:02 +08:00
Lovehsigure_520 71fe77ebc6 fix(auth): preserve mobile provider hints (#2281) 2026-08-14 17:19:28 +08:00
ColumbinaandRainbowBird 96465c8130 fix(stage-tamagotchi): repair chat-list add, switch, and delete (#2086)
Co-authored-by: RainbowBird <git@luoling.moe>
2026-08-14 08:24:56 +00:00
Nekoandgithub-actions[bot] cc791fab95 chore: update sponsors svg (#2279)
This PR updates generated SponsorKit assets from the scheduled sponsors
workflow.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-14 04:00:40 +00:00
Neko Ayaka addfec1981 refactor(testing-audio,stage-ui): added pinia-plugin-tracing, directly assert from history of pinia 2026-08-14 03:22:32 +08:00
d4fe2bef59 fix(stage-tamagotchi): install desktop entry and appstream metainfo f… (#2245)
## Description

I understand that flatpak workflow already left my hand last year, and
this is not suitable for my ability and role at AIRI. However, I'd like
to ask if I have permissions to post my opinion to solve this:

- It may be better to manage sandbox permissions with smaller
boundaries.
- It is considerable to copy a desktop shortcut, and the metainfo to
properly trigger an app.

```
diff --git a/apps/stage-tamagotchi/ai.moeru.airi.flatpak.yml b/apps/stage-tamagotchi/ai.moeru.airi.flatpak.yml
index c8f9c33fd..311af5d74 100644
--- a/apps/stage-tamagotchi/ai.moeru.airi.flatpak.yml
+++ b/apps/stage-tamagotchi/ai.moeru.airi.flatpak.yml
@@ -22,7 +22,10 @@ finish-args:
   - --talk-name=org.freedesktop.portal.Desktop
   - --system-talk-name=org.freedesktop.login1
   - --system-talk-name=org.freedesktop.UPower
-  - --filesystem=home:rw
+  # Filesystem permissions
+  - --filesystem=xdg-download:rw
+  - --filesystem=xdg-config/airi:create
+  - --filesystem=~/.config/airi:create
 
 modules:
   - name: AIRI-App
@@ -34,6 +37,9 @@ modules:
       - install airi.sh /app/bin/airi.sh
       - chmod +x /app/bin/airi/airi.sh
       - chmod +x /app/bin/airi/airi
+      - install -Dm644 ai.moeru.airi.desktop /app/share/applications/ai.moeru.airi.desktop
+      - install -Dm644 ai.moeru.airi.metainfo.xml /app/share/metainfo/ai.moeru.airi.metainfo.xml
+      - install -Dm644 build/icons/icon.png /app/share/icons/hicolor/512x512/apps/ai.moeru.airi.png
     sources:
       - type: dir
         only-arches: [x86_64]
```

This block is an overview of this patch.

This bug was reported at Discord AIRI chatroom by Scarface.

```
OS: Bazzite DX 44.20260714.0
DE: KDE Plasma 6.7.2
Wayland

Hey. I wanted to give this a try but I'm facing some issues with the flatpak.

Unfortunately, I can't get it to run and it doesn't seem to even print out any logs whatsoever.

I tried running it from the terminal and noticed the following:

1) The flatpak runs
2) Processes are created
3) There is no output in the terminal even when using the verbose flag 
4) A blank taskbar icon appears that when clicked on creates a KDE toast pop up that says "No exec field in"

I went with the manual installation (git clone -> pnpm ...) and it works fine but if possible i'd like to keep using the Flatpak

Couldn't find anyone else with the same issue on Github or here. Any suggestions are appreciated.
```

## Linked Issues

Scarface mentioned that he `Couldn't find anyone else with the same
issue on Github or here. Any suggestions are appreciated.`

I could not find a same bug for this, too.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Liet Blue <127093491+lietblue@users.noreply.github.com>
Co-authored-by: Liet Blue <lietblue@posteo.net>
2026-08-13 14:39:05 +00:00
Neko Ayaka 0ef3a26f7d feat(testing-audio): now entire audio input/output pipeline can be tested 2026-08-13 22:12:24 +08:00
Neko Ayaka 8d241c3d71 chore(.gitignore): updated 2026-08-13 19:50:09 +08:00
Neko Ayaka 0d2a24aef5 chore: updated 2026-08-13 19:50:09 +08:00
935347828c chore: update README release artifacts to v0.11.3 (#2277)
## Description

Updates stable desktop download links after the v0.11.3 release.

## Linked Issues

None.

## Additional Context

Generated by the post-release README workflow.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-13 19:26:52 +08:00
Columbina 5977a9dcfe docs(en): refresh manual and provider guides (#2153) 2026-08-13 18:18:24 +08:00
RainbowBird 27111382b4 fix(server): reconcile auth split with main 2026-08-12 23:33:58 +08:00
RainbowBird d5c95dca13 chore(server): define Railway service deployment config 2026-08-12 23:33:58 +08:00
RainbowBird 818cd0803f fix(auth-server): revoke social authorizations on account deletion (#2221) 2026-08-12 23:33:58 +08:00
RainbowBirdandautofix-ci[bot] 22b5249c64 refactor(server): split independent auth service (#2202)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-12 23:33:58 +08:00
Neko Ayaka a9906bf13b fix(deps): pin eventa to beta.13 2026-08-12 18:15:04 +08:00
Neko b6011381bc fix(stage-ui): export streaming transcription input (#2266) 2026-08-12 05:51:27 +08:00
Neko 57397889a5 feat(stage-pages): add Hearing playground (#2265) 2026-08-12 05:27:59 +08:00
Neko ac0192e5b6 fix(stage-tamagotchi): sync hearing text with chat input (#2264) 2026-08-12 05:00:57 +08:00
Neko 01eac03af1 fix(stage-ui): correct VAD segment processing (#2258) 2026-08-12 04:16:53 +08:00
Neko 82b82c644f fix(stage-tamagotchi): replace streaming caption corrections (#2263) 2026-08-12 02:57:03 +08:00
Neko b04cc02a5a fix(stage-ui): preserve streaming transcript corrections (#2261) 2026-08-12 00:58:53 +08:00
Neko 788a509940 fix(stage-ui): share streaming transcription sessions (#2260) 2026-08-12 00:36:26 +08:00
Weathercoldandgithub-actions[bot] 9f34877bab chore(nix): update pnpmDeps hash (#2254)
Auto-generated by CI to keep Nix pnpmDeps hash up-to-date.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-11 16:16:37 +00:00
Neko 9f5249454b fix(core-agent): preserve tool messages across chat turns (#2257) 2026-08-12 00:06:04 +08:00
Neko 1ca59ea5c5 fix(api-server): pin Eventa WebSocket protocol (#2259) 2026-08-12 00:04:41 +08:00
RainbowBird d4f1837994 fix(auth): trust proxy client IP for rate limits 2026-08-11 23:03:21 +08:00
Neko 2433e61378 fix(stage-ui): synchronize auth state across windows (#2256) 2026-08-11 22:42:03 +08:00
Doji d0b809a1f8 fix(stage-tamagotchi): let AIRI start on Linux ARM64 (#2253) 2026-08-11 20:26:54 +08:00
Lovehsigure_520 28dec4bc5f fix(ci): update release README links through PR (#2152) 2026-08-11 17:55:47 +08:00
fd8b7a0ae3 feat(core-agent): bump xsai / remove patches (#2164)
## Summary

- Bump catalog `@xsai/*`, `@xsai-ext/providers`, and `xsschema` to
**0.5.0-beta.8**, and delete the three `@xsai/*` pnpm patches — the
beta.2 ones from #1602 and the beta.8 regenerations that landed on main
in `38a008500`.
- Always capture tool failures on the core-agent chat path: xsAI beta.8
marks failed tool executions with `isError: true` on `tool-result.done`,
and `llm-service.ts` maps that to AIRI's `tool-error` event via
`toAiriStreamEvent`, so the agent loop continues instead of aborting.
- Remove the `captureToolErrors` request flag (and stop forwarding it
into `streamText`).
- Rebased onto latest `main` (`b230e16b2`). Includes one follow-up fix:
steps are marked settled before the finish listener runs, and finish
listener failures still reject the stream.

### Related

- Supersedes / follows up on
[#1602](https://github.com/moeru-ai/airi/pull/1602) (`captureToolErrors`
+ xsai patches).

### Scope of capture

| Case | Covered |
| --- | --- |
| A — unknown tool | yes |
| B — invalid / unparseable arguments JSON | yes |
| C — `validate` failure | yes |
| D — `execute` throw | yes |
| `missing_name` / `missing_arguments` | no (xsai still aborts) |
| `repairToolCall` | no |

Error copy on beta.8: `Tool "<toolName>" execution failed: …` (produced
by xsAI).

## Test plan

### Automated (Vitest)

- [x] core-agent `llm-service.test.ts` — 16/16
- [x] core-agent full suite — 82/82
- [x] stage-ui `llm.test.ts` + `chat.contract.test.ts` — 44/44 (the
previous `stepsSettled` timing failure is fixed in this branch)
- [x] stage-ui full suite — 594 passed / 0 failed (one
browser-test-runner teardown error, not a test failure)
- [x] typecheck — core-agent, stage-ui, component-calling, satori-bot
pass; telegram-bot fails only at `src/utils/velin.ts`, which is
pre-existing on main and untouched by this PR

### Real-environment E2E (rebase branch, DeepSeek V4 Flash via DeepSeek
API)

Harness: `/Users/lulu/GitHub/airi-e2e/pr2164/tool-error-e2e-rebase.mjs`
— drives the built `core-agent` `streamFrom` with a deliberately failing
tool.

| Case | Result | Evidence |
| --- | --- | --- |
| D — execute throw | **pass** | `tool-error` carried `Tool
"always_fail" execution failed: boom: deterministic tool failure`; the
model answered: "The always_fail tool threw a deterministic error as
expected." |
| A — unknown tool | **pass** | The model called the unavailable
`search_the_moon_database` after being told truthfully that this tests
AIRI's error capture; runtime returned `tool-error` and the conversation
continued. |
| B — bad arguments JSON | not observed on real model | providers rarely
emit invalid `arguments`; covered by unit test |
| C — `validate` failure | pass (earlier manual run with a temporary
validate-gated tool) | — |

Evidence artifacts:
`/Users/lulu/GitHub/airi-e2e/artifacts/pr2164/tool-error-e2e-2026-08-10T16-49-15-384Z.{json,log}`

### Notes / non-goals

- Fallout-only updates for the xsai beta.8 API rename: `textStream`,
`inputTokens` / `outputTokens` / `totalTokens` in component-calling /
telegram / satori.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-11 17:51:15 +08:00
Neko Ayaka b230e16b2e fix(stage-ui): mock for test 2026-08-10 18:33:24 +08:00
Weathercoldandgithub-actions[bot] a671d56f78 chore(nix): update pnpmDeps hash (#2248)
Auto-generated by CI to keep Nix pnpmDeps hash up-to-date.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-10 07:40:27 +00:00
b3fac81c5a feat(minecraft): desktop relay via a Minecraft adapter (#1916)
> **Reworked.** This PR has been rebuilt around the neutral Context Flow
architecture, per @shinohara-rin's review. Minecraft is no longer
special-cased in the generic stage-ui runtime — desktop relay &
read-aloud are now reintroduced through a **Minecraft adapter** that
contributes into the existing generic stores.

## Stacked PRs (please review/merge in order)

This rework is split as you suggested — "first restore
`services/minecraft` to only own Minecraft semantics, then reintroduce
desktop relay/read-aloud through ... a Minecraft adapter":

1. **#1949** — generic stage-ui robustness fixes (spark:command result
guard + TTS session isolation), split out as you noted they were
separable.
2. **#1950** — `refactor(minecraft)`: restore `services/minecraft` to
neutral Minecraft semantics (removes the desktop-relay assumptions baked
into the merged #1915 — `handleActionIntent`'s
`username='主人'`/`relayedFrom`, the `master:` status hint, and the
`minecraft:speech` forwarding).
3. **this PR** — reintroduces desktop relay & read-aloud via the
Minecraft adapter.

Because #1949 and #1950 are not merged yet, their commits currently
appear in this PR's diff. Once they land I'll rebase this PR onto `main`
so the diff shrinks to just the adapter work.

## The adapter (`apps/stage-tamagotchi/src/renderer/stores/minecraft/`)

The renderer owns the entire desktop ↔ in-game-bot integration and
contributes into the **existing** generic stores — the same pattern as
`mcp-tools.ts` / `plugin-tools.ts`:

- **`relayToMinecraft` tool** →
`useLlmToolsStore.registerTools('minecraft', …)`, registered **only
while the bot is online** (a hard capability gate, replacing the old
prompt-only "don't relay when offline"). `execute()` re-checks
availability, so a relay is never acked after the bot disconnects.
- **Persona directive** →
`useLlmToolsetPromptsStore.registerToolsetPrompts('minecraft', …)`,
re-registered whenever online/master/runtime-context change so the model
gets a fresh directive each turn.
- **Read-aloud** → consumes the bot's `minecraft:speech` chat into the
stage TTS (Chinese-gated), and binds 主人 by **parsing the bot's neutral
status text** — no desktop-specific hint from the bot service.
- **Notify muting** →
`orchestratorStore.muteNotifySource('minecraft-bot')`.

## Generic, non-Minecraft additions

- **`useSystemSpeechStore`** (stage-ui): a neutral bridge so any module
can voice a one-off system line; `Stage.vue` consumes it via
independent, tracked TTS sessions cancelled on unmount /
provider-or-voice change.
- **`orchestrator.muteNotifySource(id)`**: a generic primitive so a
module suppresses only **its own** notifies — every other module/plugin
notify still reacts (this fixes the earlier P1 where all
`character`-targeted notifies were dropped).
- **`./tools/*` export** from stage-ui so app-side tool authors can
reuse the shared spark-command normalizers.

## services/minecraft

Re-adds the bot's own-chat forwarding on `minecraft:speech`, now landing
**together with** its adapter consumer so the read-aloud contract is
never half-present on `main`.

## How tested

- `pnpm -F @proj-airi/stage-ui typecheck` + `pnpm -F
@proj-airi/stage-tamagotchi typecheck` → 0 errors.
- 16 new unit tests (persona prompt builder + relay tool: availability
gate, do/stop, full-label fidelity, master parsing, read-aloud gating);
orchestrator suite 5/5.
- `eslint` → 0 problems.

## Addressed review points

- Restore non-Minecraft notifications → generic `muteNotifySource` (only
the bot's source is muted).
- Isolate / track-and-cancel one-off system TTS sessions → `Stage.vue`
`oneOffSessions`.
- Re-check bot availability before relaying → `isAvailable()` in
`execute()`.
- Read the master hint that actually exists → desktop now parses the
master from neutral status **text** (the `master:` hint is removed in
#1950).
- Defer Minecraft init until after channel config → adapter `setup()`
runs after the configured `serverChannelStore.initialize(...)`.

---------

Co-authored-by: Rin <shinohara-rin@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-10 15:30:45 +08:00
Neko Ayaka 07d5baf410 fix(stage-ui,stage-tamagotchi): should not flash messages, stream correctly, and sync tool call renderer 2026-08-10 14:32:42 +08:00
Neko Ayaka 66d7ef207e refactor(stage-web,stage-pages,stage-ui): better structure for asr & vad 2026-08-09 18:22:29 +08:00