mirror of
https://github.com/moeru-ai/airi.git
synced 2026-10-30 19:34:10 +08:00
## Summary The main process sent the cursor position to the main window 60 times each second, also when the cursor did not move. Each IPC message then reached two eventa contexts in the renderer: the shared context, and a context that the screen capture composable created for itself. In a profile of the desktop main window, IPC message handling took about 4% of the main thread, where the Stage renders. - **Cursor.** The screen service sends a position only when it differs from the last position that it sent. When a renderer starts the loop again, for example after a reload, the next position is sent even if it did not change. In the renderer, a consumer that mounts later starts from the last position. - **Screen capture.** `useElectronScreenCapture` takes the eventa context of the window, and the callers pass `getElectronEventaContext()`. Before, each call created a context, and its IPC listener stayed for the life of the page. Each later mount of the vision or screen capture devtools page added one more listener. ## Boundaries and risks | Invariant or boundary | Failure mode | Protection | Evidence or gap | | --- | --- | --- | --- | | Consumers keep the cursor position | A consumer needs a message while the cursor stays still | The renderer keeps the last position. Window-relative positions also follow `useElectronWindowBounds`, so a moved window updates them without a cursor message | Code inspection of `useElectronRelativeMouse` and `useElectronMouseInElement` | | A consumer that mounts later gets a position | A component mounts while the cursor stays still and keeps its initial position | `useElectronMouse` keeps the last position, and each new consumer starts from it | `electron-mouse.browser.test.ts` | | A reloaded renderer gets a position | After a reload, no position arrives until the cursor moves | `startLoopGetCursorScreenPoint` clears the last sent position | `screen.test.ts` | | Screen capture invokes still reach the main process | An invoke on the shared context does not resolve | `setupElectronScreenCapture` already runs on the shared context for system audio lip sync | Typecheck and the ambient light browser test. In a dev run, `checkMacOSPermission` through the shared context returned `granted` in 24 ms. Not verified at runtime: ambient light capture, vision, and the screen capture devtools page | ## Verification ```sh pnpm -F @proj-airi/stage-tamagotchi exec vitest run src/main/services/electron/screen.test.ts pnpm exec vitest run --config apps/stage-tamagotchi/vitest.config.ts --project browser src/renderer/electron-mouse.browser.test.ts pnpm -F @proj-airi/stage-tamagotchi exec vitest run <21 test files that import electron-screen-capture, electron-vueuse, or the screen service> pnpm -F @proj-airi/electron-screen-capture typecheck pnpm -F @proj-airi/stage-tamagotchi typecheck pnpm typecheck pnpm lint ``` - The screen service tests pass, 2 of 2. Without the unchanged-position check, both fail. Without the reset on loop start, the reload test fails. - The late consumer test passes. Without the kept position, the late consumer reads 0 instead of 10. - In the run of 22 files, 176 of 178 tests pass. In that run, the startup test of `app.browser.test.ts` received no provider capability report, and a test of `home-assistant.browser.test.ts` failed after 21.8 s. Alone, both files pass, 13 of 13, on this branch and on a branch without this change. - Typecheck: `electron-screen-capture` and `stage-tamagotchi` pass, and the root typecheck passes, 55 of 55 tasks. - Lint: 0 errors. The 659 warnings are the same count as on `main`. - These checks ran on `99dce26f9`. After the rebase onto `e68f64c8c`, the screen service and ambient light tests (8 of 8) and the root typecheck (55 of 55) ran again and passed. Lint of the changed files reports 0 errors. - After the rebase onto `6b1cb3b25`, the screen service and ambient light tests (8 of 8) and the `electron-screen-capture` and `stage-tamagotchi` typechecks ran again and passed. The two new `main` commits change only `server/` and the root Vitest projects. - After the review fix, the late consumer, ambient light, and chat click-through browser tests pass, 17 of 17. The `electron-vueuse` typecheck and the root typecheck (56 of 56) pass. Lint of the changed files reports 0 errors. - A manual test in the desktop dev app on `60dd98699`, before the review fix, found no problem. Runtime, desktop dev, main window, 15 s profile 4 minutes after launch: | Measurement | Before | After | | --- | --- | --- | | IPC message handling (`renderer_init` `onMessage`) | 629 ms (4.1%) | 115 ms (0.8%) | | eventa contexts that handle each message | 2 | 1 | | Main window frame rate | 118.5 fps | 120.0 fps | The cursor did not move during the After profile, so it has no cursor messages. A moving cursor still sends up to 60 messages each second, to one context.