refactor(tasks): 移植主 Agent 同款合并活动折叠(数据层)
把上一轮验证过的数据层搬到工作图基座上,图/树两种模式共用:
- 新增 src/process-activity.ts:宿主 ui-chat 的 process group 算法移植
(activity() 分类表逐条照抄、liveToolDetail 键优先级与 160 字截断、
counts 计数排序与并列规则、preparing 语义、按 user/reply 边界切范围)。
按本轮设计裁剪掉逐阶段列表(阶段改由徽标 + 颜色表达)。新增一条
偏差:最新范围为空(子代理刚回复完)时回退到上一个「做过事」的范围,
否则已结算卡片的小条只会显示「已完成分析」。
- chatT:从宿主 chat 命名空间读 message.stepProcess.* 措辞(方法调用 +
try/catch 兜底,key 未命中即回退),4 个回归用例钉住「不许解绑 bind」。
- subagents.live 载荷换新:SidebarChildLiveView { running?, text?, summary?,
lastEventTime? },报告树内每个子节点(含已结算)与拓扑根;删除
expand/stages 机制;childActivity → childLive(「不在 map 里 = 未运行」
的读法随旧协议一起作废)。
- tasks-model 消费新形状;LiveLine 与节点详情浮窗改显示合并活动措辞。
- 删除 src/subagent-activity.ts 与 tests/subagent-activity.spec.ts。
验证:typecheck / lint 通过;pnpm test 1252 passed / 9 skipped。
(cherry picked from commit 5e5284f214846b0c366048acbee459f3a7a79456)
This commit is contained in:
+52
-2
@@ -976,7 +976,17 @@ export const LOCALE_NS = 'betterSidebar'
|
||||
// path most sessions never enter.
|
||||
|
||||
/** The DSH locale service attached by the client apply (absent → browser detection). */
|
||||
let localeService: { getSnapshot(): { active: string } } | undefined
|
||||
let localeService: {
|
||||
getSnapshot(): { active: string }
|
||||
/**
|
||||
* Bind one registered namespace to a translate function (DSH's
|
||||
* `LocaleRuntime.bind`). Optional because a consumer may attach only the
|
||||
* snapshot face. The untyped overload is what makes cross-package key reads
|
||||
* possible: an UNREGISTERED namespace yields a function that returns the key
|
||||
* itself, which is exactly how {@link chatT} detects "not available".
|
||||
*/
|
||||
bind?(ns: string): (key: string, params?: Record<string, string | number>) => string
|
||||
} | undefined
|
||||
|
||||
/**
|
||||
* The better-locale override store attached by the client apply
|
||||
@@ -1003,10 +1013,50 @@ let betterLocaleStore: {
|
||||
* `t()` function, and the Sidebar root's locale subscription re-renders the
|
||||
* whole tree on switches.
|
||||
*/
|
||||
export function attachLocale(service: { getSnapshot(): { active: string } } | undefined): void {
|
||||
export function attachLocale(service: {
|
||||
getSnapshot(): { active: string }
|
||||
/** Optional namespace binding ({@link chatT} needs it; a bare snapshot face is still valid). */
|
||||
bind?(ns: string): (key: string, params?: Record<string, string | number>) => string
|
||||
} | undefined): void {
|
||||
localeService = service
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a key in the HOST's own `chat` namespace — the wording the main
|
||||
* conversation's merged "process" header uses (`message.stepProcess.*`,
|
||||
* registered by `@deepseek-ai/dsh-client-ui-chat`). The Tasks page reads it so
|
||||
* a running node reads exactly like the main agent's own activity line instead
|
||||
* of inventing a second vocabulary (and without adding ~40 keys to 20 plugin
|
||||
* dictionaries).
|
||||
*
|
||||
* Deliberately untyped: these keys are NOT a documented host contract. A host
|
||||
* that renames one, or a deployment where the chat target never mounted,
|
||||
* returns the key unchanged — the caller then falls back to its own wording
|
||||
* ({@link chatT} answers undefined) rather than printing `message.…`.
|
||||
*
|
||||
* @param key - full `chat`-namespace key.
|
||||
* @param params - `{name}` placeholders to interpolate (the host does this).
|
||||
* @returns the translated text, or undefined when unavailable.
|
||||
*/
|
||||
export function chatT(key: string, params?: Record<string, string | number>): string | undefined {
|
||||
const service = localeService
|
||||
if (service === undefined) return undefined
|
||||
try {
|
||||
// MUST stay a METHOD call: DSH's `bind` reads `this.bound`, so a detached
|
||||
// reference (`const bind = service.bind; bind('chat')`) throws
|
||||
// "Cannot read properties of undefined (reading 'bound')" — caught by the
|
||||
// real-host mount lane, invisible to closure fakes in unit tests.
|
||||
const translate = service.bind?.('chat')
|
||||
if (typeof translate !== 'function') return undefined
|
||||
const text = translate(key, params)
|
||||
return typeof text === 'string' && text !== '' && text !== key ? text : undefined
|
||||
} catch {
|
||||
// The namespace seam is undocumented: a host that reshapes it must degrade
|
||||
// to the caller's own wording, never break a render.
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach (or detach, with undefined) the better-locale override store.
|
||||
* When attached with an active override, `t()` consults the store's
|
||||
|
||||
Reference in New Issue
Block a user