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.
This commit is contained in:
@@ -124,7 +124,7 @@
|
||||
|
||||
## P. 桌宠系统
|
||||
|
||||
- [ ] ❌ **整组砍(2026-10-15 确认)**:桌宠状态 socket、Petdex 图鉴、pets store、PetdexView 全删(浪费资源)
|
||||
- [x] ❌ **整组砍(2026-10-15 确认,2026-10-20 执行)**:桌宠状态 socket、Petdex 图鉴、pets store、PetdexView 已全删(浪费资源)
|
||||
|
||||
## Q. 编程代理之外的特色杂项
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
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.
|
||||
@@ -66,7 +66,7 @@ CYBER 是本项目**唯一**的视觉语言。`docs/ui-baseline.md` 是它的**
|
||||
| --- | --- | --- |
|
||||
| **已落地** | `SettingsView.vue` | `cy-*` 骨架 + 令牌 |
|
||||
| **已落地(无骨架)** | `LoginView.vue` | 令牌密度最高(24 处),装饰位面合规 |
|
||||
| **部分落地** | `ChatView` / `GroupChatView` / `GlobalAgentView` / `HistoryView` / `JourneyView` / `WorkflowView` / `LogsView` / `PerformanceView` / `PluginsView` / `McpManagerView` / `MemoryView` / `PetdexView` / `TerminalView` / `SkillsView` / `SkillsUsageView` / `DevicesView` / `KanbanView` / `FilesView` / `HermesMissingView` | 用了基础令牌,但布局仍是 Arco 原生(`a-card` / `a-tabs`) |
|
||||
| **部分落地** | `ChatView` / `GroupChatView` / `GlobalAgentView` / `HistoryView` / `JourneyView` / `WorkflowView` / `LogsView` / `PerformanceView` / `PluginsView` / `McpManagerView` / `MemoryView` / `TerminalView` / `SkillsView` / `SkillsUsageView` / `DevicesView` / `KanbanView` / `FilesView` / `HermesMissingView` | 用了基础令牌,但布局仍是 Arco 原生(`a-card` / `a-tabs`) |
|
||||
| **未落地** | `JobsView` / `ModelsView` / `ProfilesView` / `UsageView` / `ChannelsView` / `VersionPreviewView` | style 块几乎没有色值,也没有语义色 |
|
||||
|
||||
**CYBER 目前是「孤岛式」的**:设置页 + 聊天链是两块完整的岛,其余 20+ 页面停留在迁移前原样。
|
||||
@@ -170,7 +170,7 @@ CYBER 主题**完成**的定义是下面五条同时成立:
|
||||
2. 按页面分批改,每批 3-5 个页面:
|
||||
- **批次 A(数据展示型)**:`UsageView` / `JobsView` / `LogsView` / `ModelsView` / `ProfilesView`
|
||||
- **批次 B(配置型)**:`DevicesView` / `ChannelsView` / `PluginsView` / `McpManagerView`
|
||||
- **批次 C(内容型)**:`FilesView` / `MemoryView` / `PetdexView` / `SkillsView` / `SkillsUsageView`
|
||||
- **批次 C(内容型)**:`FilesView` / `MemoryView` / `SkillsView` / `SkillsUsageView`
|
||||
- **批次 D(复杂型)**:`WorkflowView` / `KanbanView` / `JourneyView` / `PerformanceView` / `HistoryView` / `HermesMissingView` / `VersionPreviewView`
|
||||
3. 每批的替换模式:**Arco 结构 → `.cy-panel` 外壳**,但**保留** Arco 组件本身
|
||||
(`a-table` / `a-form` / `a-select` 都不动)。Arco 组件的外观已经被
|
||||
@@ -192,7 +192,7 @@ CYBER 主题**完成**的定义是下面五条同时成立:
|
||||
| --- | --- | --- |
|
||||
| A | `UsageView` / `JobsView` / `LogsView` / `ModelsView` / `ProfilesView` | 大部分已合规;`JobsView` 补 `cy-sec-t` 分节标题 + i18n key `jobs.sectionList` |
|
||||
| B | `DevicesView` / `ChannelsView` / `PluginsView` / `McpManagerView` | `ChannelsView` 内容区包进 `cy-panel`;`McpManagerView` 已合规(modal 内列表保留自定义边框,避免卡片套卡片) |
|
||||
| C | `FilesView` / `MemoryView` / `PetdexView` / `SkillsView` / `SkillsUsageView` | 已合规;`PetdexView` 棋盘格 `rgba(127,127,127,0.08)` → `rgba(var(--text-muted-rgb), 0.08)` |
|
||||
| C | `FilesView` / `MemoryView` / `SkillsView` / `SkillsUsageView` | 已合规 |
|
||||
| D | `WorkflowView` / `KanbanView` / `JourneyView` / `PerformanceView` / `HistoryView` / `HermesMissingView` / `VersionPreviewView` / `TerminalView` / `GlobalAgentView` | **全部已是令牌驱动**。这些是专用布局(画布 / 看板 / 终端 / 聊天流),原型的 `panel` 结构不适用,不需要套骨架类 |
|
||||
|
||||
**批次 D 的判定依据**:「cy-* 计数为 0」是**误报**。判断标准应是
|
||||
@@ -274,7 +274,6 @@ CYBER 主题**完成**的定义是下面五条同时成立:
|
||||
|
||||
| 位置 | 问题 | 修法 |
|
||||
| --- | --- | --- |
|
||||
| `views/hermes/PetdexView.vue` | 棋盘格 `rgba(127,127,127,0.08)` | → `rgba(var(--text-muted-rgb), 0.08)` |
|
||||
| `utils/hermes/kanban-status-colors.ts` | 分类色 `#c084fc` + `rgba(192,132,252,0.14)` 字面量 | 新增令牌 `--kanban-review` / `--kanban-review-rgb`;灰阶改走 `--text-muted-rgb` |
|
||||
| `components/hermes/chat/MessageList.vue` | 浅色主题遗留阴影 `rgba(15,23,42,0.05)` | → `var(--shadow-sm)` |
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
### 视觉细节
|
||||
|
||||
- **圆角 tag**:naive 的 `NTag round` 无 Arco 对应,改用了 `border-radius: 999px`(`PetdexView.vue`、`DevicesView.vue`)
|
||||
- **圆角 tag**:naive 的 `NTag round` 无 Arco 对应,改用了 `border-radius: 999px`(`DevicesView.vue`)
|
||||
- **按钮尺寸**:naive 的 `size="tiny"` → Arco `size="mini"`,可能与相邻元素不齐
|
||||
- **滚动条**:naive 的 `:native-scrollbar="false"` 无对应,已删除,滚动条样式会变
|
||||
|
||||
|
||||
Reference in New Issue
Block a user