The pet feature was three loosely coupled subsystems that no core flow depended on: the Petdex catalog page, the pet install/preference store, and the pet-state socket. All three are removed. The only cross-boundary touch point was a try/catch-wrapped observer that mapped chat-run events to pet animations. Removing it leaves the /chat-run event contract unchanged: no event name, field name, field type, or emission timing changed. Removing petdexPublicRoutes also closes the unauthenticated outbound proxy at /api/hermes/petdex/asset, which shrinks the SSRF surface.
60 lines
3.3 KiB
Markdown
60 lines
3.3 KiB
Markdown
---
|
|
date: 2026-10-20
|
|
pr: pending
|
|
feature: Remove the desktop-pet system (pet-state socket, Petdex catalog, pets store)
|
|
impact: The optional "宠物" sidebar entry and the whole pet subsystem are gone. The only cross-boundary touch point was a try/catch-wrapped observer that mapped chat-run events to pet animations; removing it does not change any /chat-run event name, field name, field type, or emission timing. No chat behavior changed.
|
|
---
|
|
|
|
# Remove the desktop-pet system
|
|
|
|
## What changed
|
|
|
|
The pet feature was three loosely coupled subsystems that no core flow
|
|
depended on. All three are removed.
|
|
|
|
| Area | Removed |
|
|
| --- | --- |
|
|
| Client | `views/hermes/PetdexView.vue`, `stores/hermes/pets.ts`, `stores/hermes/pet-state.ts`, `api/hermes/pets.ts`, `api/hermes/petdex.ts`, `api/hermes/pet-state.ts`, `public/icons/pet-resize.svg` (orphan) |
|
|
| Client wiring | `router/index.ts` route `hermes.petdex`, `AppSidebar.vue` nav item, `sidebar.petdex` + `petdex.*` i18n keys in `zh.ts` / `en.ts` |
|
|
| Server | `services/hermes/pets.ts`, `services/hermes/petdex.ts`, `services/hermes/pet-state-socket.ts`, `controllers/hermes/pets.ts`, `controllers/hermes/petdex.ts`, `routes/hermes/pets.ts`, `routes/hermes/petdex.ts` |
|
|
| Server wiring | `routes/index.ts` (three `app.use` registrations), `index.ts` (`PetStateSocketServer` import, field, and `init()`) |
|
|
| Chat chain | `run-chat/index.ts` and `run-chat/handle-bridge-run.ts` pet observation calls, `resolvePetEventProfile`, `observePetEvent` |
|
|
| Tests | `tests/server/pets-service.test.ts`, `tests/server/petdex-service.test.ts`, `tests/client/pets-store.test.ts`, `/api/hermes/pets/active` mock in `tests/e2e/fixtures.ts` |
|
|
|
|
## Why it was safe
|
|
|
|
The pet subsystem sat on a single boundary crossing: the chat-run event
|
|
stream. `run-chat/index.ts` (`emitExternalEvent`, `emitToSession`) and
|
|
`run-chat/handle-bridge-run.ts` (two `emit` closures) each called
|
|
`observeRunChatPetEvent(profile, event, tagged)` to translate a chat event
|
|
into a pet animation state. Every call was wrapped in a `try/catch` that only
|
|
logged at `debug` level, so a pet failure could never break a run.
|
|
|
|
Removing those calls leaves the surrounding emit paths intact: the tagged
|
|
payload, the `session:<id>` room broadcast, the direct `socket.emit` fallback,
|
|
the waiter wake-ups, and the session event buffer are all unchanged.
|
|
|
|
Everything else was an island: the client `pets` store was consumed only by
|
|
`PetdexView`, and the client `pet-state` store had no callers at all — the
|
|
client never connected to the `/pet-state` namespace, so the server-side
|
|
`pet.state.snapshot` / `pet.state.updated` events had no consumer.
|
|
|
|
## Not changed
|
|
|
|
The `/chat-run` Socket.IO contract is untouched: no event name, field name,
|
|
field type, or emission timing changed. This fragment exists because the
|
|
touched files sit on the chat chain path, not because any chat behavior moved.
|
|
|
|
## Side effect
|
|
|
|
`routes/index.ts` registered `petdexPublicRoutes` before the auth middleware,
|
|
which exposed `/api/hermes/petdex/asset` as an unauthenticated outbound proxy
|
|
(with a `petdex.dev` host allowlist). Removing it closes that endpoint and
|
|
shrinks the SSRF surface.
|
|
|
|
## Local data
|
|
|
|
Persisted pet state lives under
|
|
`<HERMES_WEB_UI_HOME>/profile-metadata/<base64url(profile)>/pets/`. Deleting
|
|
the code does not remove those files; they can be deleted manually.
|