0.2.0-rc.2 withdrew every catalog/subagent seam this fork was written against, and all three calls degraded to silent no-ops: openSubagent(address) -> gone setSubagentCatalogOpen(id, open) -> gone refreshSubagents(id) -> gone The host's own subagent UI (dsh-client-ui-subagent) rebuilds a parent's child catalog with `sessions.refreshProjections(parentSessionId)`, so that is the only kick that still exists. Wire it into `observe()` and the catalog retry button, keeping the legacy names as fallbacks for older hosts. Without it the root catalog never hydrated: the page sat on "loading" or degraded to synthesized summary rows. Also document what the investigation settled: - docs/subagent-state-enumeration.md: the full state model (catalog child / diagnostic / session / job / sidechat) and proof that this fork already renders it 1:1 with upstream. - docs/plugin-conventions.md: the hard rules another sidebar plugin must follow (host schemastery, volatile prefs, ns = profile entry id, no colons in tab ids, never read a volatile field directly) plus the withdrawn-API replacement table and a pre-release checklist. - docs/feedback-0.2.0-rc2-contract-gaps.md: gaps 2/3 reframed. The ask is documenting the official paths (open(childSessionId) / refreshProjections(id)), not adding new APIs. Gates: typecheck 0, lint 0, build 0, test 131 files / 1385 passed.
3.6 KiB
子 Agent 完整状态枚举(对齐 better-sidebar 原版)
口径来源:better-sidebar 原版
src/client/SubagentView.tsx+src/subagent-activity.ts(本 fork 完整保留) 宿主事实来源:@deepseek-ai/*0.2.0-rc.2 真实包内代码 结论:本插件的状态渲染已 100% 对齐原版;枚举上限由宿主字段决定,不是插件缺口。
一、三个状态域 + 一个诊断分支
域 1:子代理 catalog 行(拓扑卡片)— 主战场
数据源:sessions.list.getSnapshot().subagentsByParent[parentId].entries[],其中 kind: 'child'。
| 字段 | 取值 | 渲染 |
|---|---|---|
activity |
'running' | 'inactive' |
StateDot state='ongoing' | state='done' |
mode |
'one-shot' | 'continuable' |
副行文本(一次性 / 可续) |
hasChildren |
boolean |
是否可展开(真叶子不给 aria-expanded) |
label? |
string |
主标签;缺省回退 summary.displayTitle,再回退 entry.id |
id |
string |
行标识 + address 组装 |
副行格式(原版 cardSecondary):displayTitle · mode · activity,空段跳过。
running 行额外显示实时活动:subagents.live 批量路由 → LastActivity { text?, tool?{name,args} }
(服务端 lastActivity() 扫会话事件日志尾部的最后一条 assistant 文本 + 最后一次工具调用)。
域 2:catalog 行不可读 → 诊断分支
kind: 'diagnostic'(损坏 / 不受支持 / 不可用)→ StateDot state='error'。
容器级状态另有 SidebarSubagentCatalog.state: 'loading' | 'ready' | 'error',驱动空态行与重试按钮。
域 3:会话行(非拓扑列表)
SidebarSessionSummary.running?: boolean → StateDot state={running ? 'ongoing' : 'done'}。
注意:宿主对会话只给这一个布尔,没有更细的状态。
域 4:后台 job 与 SideChat
| 面 | 字段 | 取值 → dot |
|---|---|---|
| 后台 job | job.status |
running/stopping/completed/killed/failed → jobDotState() |
| SideChat 行 | 行级 failed / running |
error / ongoing |
二、StateDot 的可用状态(宿主固定,插件改不了)
StateDot 来自 @deepseek-ai/dsh-client-ui-primitives,只有 3 个 state:
'ongoing'(活动)/ 'done'(静止)/ 'error'(失败)。
⇒ 插件能把 N 态数据映射到 3 个视觉态,仅此而已。要更细的视觉必须宿主开口子。
三、原版 vs 本 fork 对照(结论:已对齐)
| 面 | 原版 | 本 fork |
|---|---|---|
| activity → dot | running ? 'ongoing' : 'done' |
同 |
| diagnostic → dot | 'error' |
同 |
| 副行 mode·activity | cardSecondary |
同 |
| running 实时行 | LastActivity |
同 |
| 会话行 dot | running ? 'ongoing' : 'done' |
同 |
| job dot | jobDotState(status) |
同 |
| SideChat 失败行 | 'error' |
同 |
四、宿主侧真实缺口(不是枚举本身,而是枚举的「上游」)
0.2.0-rc.2 里原版依赖的三个 API 全部消失(app 内 @deepseek-ai/* 全量 grep 0 命中):
| 原版调用 | 0.2.0-rc.2 状态 | 官方替代 |
|---|---|---|
sessions.openSubagent(address) |
不存在 | sessions.open(childSessionId)(切主面板;最终走 replaceMain → retain) |
sessions.setSubagentCatalogOpen(id, open) |
不存在 | sessions.refreshProjections(id) |
sessions.refreshSubagents(id) |
不存在 | 同上 |
⇒ catalog 的来源(宿主 hydrate)曾长期缺失,这才是「恒加载中」与「点不进去」的真根因;枚举与渲染层面本插件无缺口。