Files
hermes-ui/docs/chat-chain-changes/2026-10-20-remove-pet-system.md
T
toor b709ec6742
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
remove the desktop-pet system
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.
2026-10-20 13:24:17 +08:00

3.3 KiB

date, pr, feature, impact
date pr feature impact
2026-10-20 pending Remove the desktop-pet system (pet-state socket, Petdex catalog, pets store) 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.