Commit Graph
2063 Commits
Author SHA1 Message Date
Neko Ayaka 5c0916baa3 fix(stage-ui,stage-tamagotchi,stage-web,stage-pocket): incorrectly initialized 2026-08-19 04:17:21 +08:00
Neko c595fd645c fix(i18n): remove Neko from default ReLU prompt (#2316) 2026-08-19 03:58:07 +08:00
Neko 2770267dc7 fix(stage-tamagotchi): sync pairing settings and QR state (#2318) 2026-08-18 19:55:15 +00:00
Neko Ayaka d2b837fa01 fix(stage-ui,stage-tamagotchi,stage-web): infinite write config causing forever loading 2026-08-19 01:07:30 +08:00
Neko 677329427f fix(plugin-sdk-tamagotchi): allow nullable enum tool parameters (#2314) 2026-08-18 20:28:55 +08:00
RainbowBird d832137fde fix(analytics): remove model discovery events (#2312) 2026-08-18 11:41:10 +08:00
RainbowBird 07b26b530f fix(analytics): remove TS product events table (#2306) 2026-08-17 10:16:44 +00:00
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
RainbowBird 44cd0cfe68 fix(stage-ui): normalize streaming transcription audio chunks (#2285) 2026-08-15 19:37:45 +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
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
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
Neko Ayaka 0ef3a26f7d feat(testing-audio): now entire audio input/output pipeline can be tested 2026-08-13 22:12:24 +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
Neko 9f5249454b fix(core-agent): preserve tool messages across chat turns (#2257) 2026-08-12 00:06:04 +08:00
Neko 2433e61378 fix(stage-ui): synchronize auth state across windows (#2256) 2026-08-11 22:42:03 +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
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
Neko Ayaka 98fa1f0855 refactor(stage-ui,core-agent,stage-tamagotchi): better structure for llm, agent, and mini-agent 2026-08-09 04:05:38 +08:00
Neko Ayaka 38a008500d chore(deps): updated patch 2026-08-09 03:35:50 +08:00
Neko Ayaka 16f7dfaf4d chore(deps): updated 2026-08-09 01:46:13 +08:00
Neko Ayaka 83ea2afbd7 refactor(*): generalize events 2026-08-09 01:34:48 +08:00
584e4960e9 feat(stage-pocket): improve permission management (#2184)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: LemonNeko <17664845+LemonNekoGH@users.noreply.github.com>
2026-08-08 20:16:10 +08:00
5f3746ead8 fix(stage-tamagotchi): grant screen capture through the media permission (#2178)
## Description

Screen capture in Stage Tamagotchi is denied before it ever reaches the
desktop picker: `navigator.mediaDevices.getDisplayMedia()` resolves with
`NotAllowedError: Permission denied`, so the vision screen-capture panel
can list sources but never start a stream.

The cause is in `shouldGrantElectronPermission`. Electron reports
**screen capture as the `media` permission**, not as `display-capture`,
and it only appends `audio`/`video` to `details.mediaTypes` for *device*
capture — so a `getDisplayMedia()` request arrives as `media` with an
**empty** `mediaTypes` list
([`web_contents_permission_helper.cc#L249-L274`](https://github.com/electron/electron/blob/v41.2.1/shell/browser/web_contents_permission_helper.cc#L249-L274)).

The handler took an early return for every `media` operation and
required audio-only details, so display capture was rejected before the
allowlisted `display-capture` entry could be consulted:

```ts
if (permission === 'media')
  return shouldGrantAudioCapturePermission(webContents, permission, requestingOrigin, details)

return LOCAL_APP_PERMISSION_NAMES.has(permission) && shouldGrantLocalAppPermission(...)
```

The fix resolves a `media` operation that declares no device media type
back to `display-capture`, so the existing allowlist and local-frame
checks decide the outcome — which is what `LOCAL_APP_PERMISSION_NAMES`
already intended:

```ts
const allowlistPermission = isDisplayCaptureMediaPermission(permission, details) ? 'display-capture' : permission

return LOCAL_APP_PERMISSION_NAMES.has(allowlistPermission)
  && shouldGrantLocalAppPermission(webContents, requestingOrigin, details)
```

Camera and microphone operations always report their device media type
(`['video']`, `['audio']`, `mediaType: 'audio'`), so they never take
this path and stay exactly as strict as before. Remote frames are still
rejected, because the local-frame check is unchanged and still applies
to display capture.

Three regression tests are added: screen capture from a local page is
granted, screen capture from a remote page is rejected, and a camera
request is still denied now that it shares the `media` permission.

## Linked Issues

Closes #2177

## Additional Context

- **Regression range.** This was introduced by #2002 (`5e8bf75`,
2026-07-10), which added the permission allowlist. Nothing on the
failing path is platform-specific — the `media` vs `display-capture`
mismatch is in Electron's browser process — so although the issue was
reported on Windows, screen capture has been broken on macOS and Linux
since that commit too. Worth noting for anyone triaging similar reports.
- **Detection signal.** The predicate keys on `mediaTypes.length === 0`
rather than on the absence of the field, so a `media` operation with
*no* `mediaTypes` at all (e.g. permission *checks*, which send
`mediaType: 'unknown'` instead) is not silently promoted to display
capture. That keeps the change to exactly the shape Electron documents
for `getDisplayMedia()` requests.
- **Deliberately out of scope.** #2104 (camera snapshot denied) is a
policy decision — whether the camera should join the allowlist — not
this bug, and #2132 (`systemPreferences.getMediaAccessStatus` undefined
on Linux) is unrelated. Happy to follow up on either if you'd like them
addressed.
- **Second layer still applies.** `setDisplayMediaRequestHandler` in
`packages/electron-screen-capture` is only installed inside the
`setSource` mutex window, so a grant here still requires the renderer to
have selected a source first. This change does not widen that.
- **Verification.** `media-permissions.test.ts` goes 16/16 → 19/19; with
only the tests applied, the new local-screen-capture case fails as
expected. Type checking and the repo ESLint config both pass clean on
the two touched files.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-08 14:40:50 +09:00
Neko Ayaka eb35c4d66a refactor(*): cleaner provider design, simplified chat store 2026-08-08 01:34:44 +08:00
Neko Ayaka 5f1c52ec52 refactor(providers): now simplified 2026-08-07 05:08:38 +08:00
Neko Ayaka c124e0147d refactor(audio,stage-ui): simplify code 2026-08-07 04:36:50 +08:00
ff7f64ace8 feat(server): add Steam OpenID sign-in and account linking plugin (#2226)
## Summary

Adds a self-contained better-auth plugin
(`server/apps/api/src/libs/auth-plugins/steam.ts`) implementing Steam
OpenID 2.0 sign-in, account linking, and callback verification via "dumb
mode".

Steam's web login is OpenID 2.0, not OAuth2/OIDC, so it cannot be
registered as a `socialProviders` entry, and better-auth has no plugin
hook for extending its OAuth2 endpoints with a non-OAuth2 protocol. The
plugin therefore adds the endpoints Steam's protocol needs: `POST
/sign-in/steam`, `POST /link/steam`, and `GET /steam/callback`.

- Callback verification uses OpenID "dumb mode"
(`openid.mode=check_authentication`): one extra round trip to Steam
instead of managing RSA association state.
- New sign-ups get a placeholder `<steamid64>@steam.placeholder.local`
with `emailVerified: true`, mirroring Apple Sign In's
`<sub>@apple.placeholder.local`.
- The plugin's request/query schemas use Zod; a `// NOTICE:` documents
that better-auth's OpenAPI generator is Zod-native. Steam verification
uses `ofetch`.
- Wires Steam into `apps/ui-server-auth` sign-in and profile "Connected
accounts", plus the shared `OAuthProvider` / `defaultSignInProviders` in
`packages/stage-ui`.
- Linking routes through `/link/steam` via the client's `$fetch`;
unlinking needs no special-casing (`/unlink-account` already takes a
free-form `providerId`).

No Steam Web API key is required for this browser-based flow.

We intentionally do not depend on community Steam packages (e.g.
`better-auth-steam`) or the still-open upstream draft
([better-auth#4877](https://github.com/better-auth/better-auth/pull/4877)).
Steam never returns an email, and we need sign-up that does not ask the
user for one plus first-class account linking; the available options
either require an email at sign-in, lack linking, or are abandoned /
blocked — shipping a small in-tree plugin is the safer auth dependency
for this requirement.

## Test plan

- [x] `pnpm exec vitest run
server/apps/api/src/libs/auth-plugins/steam.test.ts` — 6/6 passing
- [x] `pnpm -F @proj-airi/ui-server-auth exec vitest run` — 32/32
passing
- [x] `pnpm -F @proj-airi/stage-ui exec vitest run
src/libs/steam-auth-client.test.ts
src/composables/use-linked-accounts.test.ts` — 5/5 passing
- [x] `pnpm -F @proj-airi/api-server typecheck`
- [x] `pnpm -F @proj-airi/ui-server-auth typecheck`
- [x] `pnpm -F @proj-airi/stage-ui typecheck`

## Follow-ups

- Desktop Steam ticket sign-in (top of this stack): silent startup
ticket exchange for Steam builds; the server resolves or creates the
AIRI user for the verified SteamID before issuing an OIDC code.
- Steam persona name/avatar via `GetPlayerSummaries` inside the plugin,
if display names beyond `Steam User <id>` are wanted.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-08-05 23:57:55 +08:00
Neko Ayaka 774b2daf03 style: prevent use of .ts, .js import 2026-08-05 20:34:14 +08:00
Neko Ayaka f2d411ea22 chore(deps): updated eventa to v1.0.0-beta.14 2026-08-05 20:32:58 +08:00
Neko 55ea1767e4 fix(stage-ui-live2d): recover from model render failures (#2225) 2026-08-05 20:28:39 +08:00
Ryanba 4421b5810b fix(stage-ui-live2d): read bundled model ZIPs as array buffers (#2224) 2026-08-05 15:39:34 +08:00
Neko Ayaka 0f20a2784b chore(deps): updated eventa to v1.0.0-beta.13 2026-08-05 00:49:14 +08:00
Neko Ayaka 4f7a9d63e9 chore(deps): updated eventa to v1.0.0-beta.9 2026-08-04 22:05:57 +08:00
Neko 5a56770f1c fix(stage-ui-live2d): support CJK paths in Live2D archives (#2219) 2026-08-04 22:05:40 +08:00
Neko 7dc8e2c4a3 refactor(stage-ui): improve onboarding, scrollable, and animated (#2215) 2026-08-04 17:51:15 +08:00