@deepseek-ai/dsh-client-ui-subagent 0.2.1-alpha.1 → 0.2.1-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -9,14 +9,14 @@
9
9
  en: 930db612ece65ad4
10
10
  zh: ad7e9d9afb4545ac
11
11
  /deepseek-ai-dsh-client-ui-subagent/summary:
12
- en: 50f267d55833a683
13
- zh: 89d6b827576baa8b
12
+ en: 6e0bbf514ad3bef7
13
+ zh: 5a29d88c124d35cc
14
14
  /deepseek-ai-dsh-client-ui-subagent/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-client-ui-subagent/use-this-package:
18
- en: 06f6bac3153361f5
19
- zh: e8b23941cbd16036
18
+ en: 9aafcfbd6a33173c
19
+ zh: 6dbd48672f58cd2d
20
20
  /deepseek-ai-dsh-client-ui-subagent/use-this-package/browsing-the-tree:
21
21
  en: 3508631091820123
22
22
  zh: ec7da9e5bedb22ba
@@ -30,14 +30,14 @@
30
30
  en: c158f12dcaed87b7
31
31
  zh: e5d315e7b1fb4fa9
32
32
  /deepseek-ai-dsh-client-ui-subagent/understand-the-implementation/catalog-derivation:
33
- en: 5e1c83ef8eb26c52
34
- zh: f5be8f1e78c74859
33
+ en: 5531dcc1fb976cff
34
+ zh: 6fe779f4f1c34266
35
35
  /deepseek-ai-dsh-client-ui-subagent/understand-the-implementation/duration-completion-and-tokens:
36
36
  en: b817e9907392f59c
37
37
  zh: e42feb97d572a989
38
38
  /deepseek-ai-dsh-client-ui-subagent/understand-the-implementation/composer-election:
39
- en: 1c15af4dd7c0b791
40
- zh: f789737ab4dd8cb2
39
+ en: 13c33af89ba0942e
40
+ zh: 00374c7944728ae2
41
41
  /deepseek-ai-dsh-client-ui-subagent/further-exploration:
42
42
  en: 1766e9012e307178
43
43
  zh: f3ee637f5941aae5
package/README.md CHANGED
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- Use this package to browse every subagent conversation beneath a parent session, open any descendant, and see whether it is running together with its token usage and active-turn duration. Completed one-shot conversations open as read-only execution records. Continuable conversations accept follow-up prompts in submission order while they run and provide Stop independently. The ordinary session sidebar omits subagent conversations, so the parent header catalog is their navigation entry point. The separate `@` source inserts a running child's label into a user message without resolving it into a continuation address.
12
+ Browse local subagent conversations and external tasks from the parent header. Local conversations show activity, token usage, and duration; continuable children accept follow-up prompts and support Stop. External tasks appear as non-navigable leaves without an execution status. Historical one-shot conversations open as read-only records. The ordinary sidebar omits subagent conversations, and the separate `@` source inserts a running child's label without granting continuation authority.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -25,7 +25,7 @@ Use this package to browse every subagent conversation beneath a parent session,
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
- The session header keeps the current session title as the lineage breadcrumb; when the session's direct catalog has entries or a read has failed, the descendant-count trigger renders at the start of the header actions band, with no breadcrumb separator. An absent catalog, an empty loading catalog, or a successfully loaded empty catalog hides the count trigger. The trigger opens that direct catalog, reports its total and running counts, and loads nested catalogs only when their rows expand. Select any depth to open that child's conversation with its exact `{parentSessionId, childSessionId, mode}` address, or use the row's trailing arrow to open the same address in the right Sidebar, preferring a separate pane when room permits.
28
+ The session header keeps the current session title as the lineage breadcrumb; when the session's direct catalog has entries or a read has failed, the descendant-count trigger renders after the preset label in the header actions band, with no breadcrumb separator. An absent catalog, an empty loading catalog, or a successfully loaded empty catalog hides the count trigger. The trigger opens that direct catalog, reports its total and running counts, and loads nested catalogs only when their rows expand. Select a local child at any depth to open that child's conversation with its exact `{parentSessionId, childSessionId, mode}` address, or use the row's trailing arrow to open the same address in the right Sidebar, preferring a separate pane when room permits.
29
29
 
30
30
  This package registers the `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` resource and builtin Sidebar tab type. The resource retains the child `SessionReference` directly from its address without refreshing the parent catalog, and releases the reference when the tab record closes. The tab renders the shared `conversation.content` Factory through `sidebar.chat.conversation`, fixes the local View to Chat, and omits the main Conversation header and width controls.
31
31
 
@@ -55,11 +55,11 @@ The [subagent runtime](../../subagent/subagent/README.md) owns continuation and
55
55
 
56
56
  ### Catalog derivation
57
57
 
58
- The header lineage renderer reads `projectionsBySession` through the standard `useSessions` hook. The renderer selects `subagentCatalog` from each Session’s shared values for membership, disclosure, and counts; Activity prefers the unified UI status and falls back to Session summaries; summaries supply titles and usage. Expanding a row loads its initial catalog when needed. Live projection frames update every loaded level without menu subscriptions or repeated membership queries. A row remains expandable while its catalog is absent, loading, or failed, and becomes a known leaf after a ready empty catalog.
58
+ The header lineage renderer reads `projectionsBySession` through the standard `useSessions` hook. The renderer selects `subagentCatalog` from each Session’s shared values for membership, disclosure, and counts; Activity prefers the unified UI status and falls back to Session summaries; summaries supply titles and usage. Expanding a row reads its target's projections, including ordinary cold history. A list row with `formatStatus: migration-required` displays “Migration required” before expansion and keeps its history-opening actions without descendant expansion or changing its subagent mode; a projection read requiring migration without a catalog supplies the same notice. Opening the Session supplies its catalog through history and control projections. Otherwise, an available catalog remains usable, including an explicit empty catalog. Live projection frames update every loaded level without menu subscriptions or repeated membership queries. Other rows remain expandable while their catalogs are absent, loading, or failed, and become known leaves after ready empty catalogs. External rows are always leaves and do not load child Sessions.
59
59
 
60
60
  Opening a catalog dropdown does not request its root catalog. Child-catalog expansion and failed-read retries call `refreshProjection`; shared projection-value changes update the display automatically.
61
61
 
62
- Breadcrumb addresses derive from the Provider-bound Session address and loaded parent catalogs, including never-selected ancestors.
62
+ Breadcrumb addresses derive from the Provider-bound Session address, loaded parent catalogs, or already-listed subagent lineage, including never-selected ancestors.
63
63
 
64
64
  ### Duration, completion, and tokens
65
65
 
@@ -71,6 +71,8 @@ One-shot children always elect a read-only composer. A continuable child elects
71
71
 
72
72
  Unknown-mode catalog rows remain visible and clickable, using the child id when no label is available. Their composer is read-only until child history establishes a supported mode; a read failure is reported in the child conversation.
73
73
 
74
+ Lineage-menu highlights follow the [standard menu edge geometry](../../../docs/ui-radius.md#nested-hover); tree disclosure controls retain their separate left gutter.
75
+
74
76
  </details>
75
77
 
76
78
  -----
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- 使用本包可浏览父会话下的每个 subagent 对话、打开任意后代,并查看其是否正在运行以及 token 用量和活跃轮次耗时。已完成的 one-shot 对话会作为只读执行记录打开。可继续对话在运行期间按提交顺序接收后续提示词,并独立提供 Stop。普通会话侧边栏会省略 subagent 对话,因此父会话页头目录是它们的导航入口。独立的 `@` source 会把运行中 child 的 label 插入用户消息,但不会把它解析成继续执行地址。
12
+ 从父会话页头浏览本地子代理对话与外部任务。本地对话展示活跃状态、token 用量和耗时;可继续子代理接受后续提示词并支持 Stop。外部任务显示为不可打开的叶子项,不展示执行状态。历史一次性对话以只读记录打开。普通侧边栏省略子代理对话;独立的 `@` 来源插入运行中子代理的标签,不授予继续执行权限。
13
13
 
14
14
  ## 目录
15
15
 
@@ -25,7 +25,7 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 会话页头把当前会话标题作为谱系面包屑;当会话的直接目录有子项或读取失败时,后代数量触发器渲染在页头操作区的最前方,不带任何面包屑分隔符。目录缺席、空目录加载中或成功加载为空时,均隐藏数量触发器。触发器打开该直接目录,报告总数与运行数,并且只在行展开时加载嵌套目录。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话;也可以使用行尾箭头在右侧 Sidebar 打开同一地址,并在空间允许时优先使用独立分栏。
28
+ 会话页头把当前会话标题作为谱系面包屑;当会话的直接目录有子项或读取失败时,后代数量触发器渲染在页头操作区中预设标签之后,不带任何面包屑分隔符。目录缺席、空目录加载中或成功加载为空时,均隐藏数量触发器。触发器打开该直接目录,报告总数与运行数,并且只在行展开时加载嵌套目录。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话;也可以使用行尾箭头在右侧 Sidebar 打开同一地址,并在空间允许时优先使用独立分栏。
29
29
 
30
30
  本包注册 `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` 资源与 builtin Sidebar tab 类型。资源直接根据地址保留 child 的 `SessionReference`,不刷新 parent 目录,并在 tab 记录关闭时释放 reference。tab 通过 `sidebar.chat.conversation` 渲染共享 `conversation.content` Factory,把局部 View 固定为 Chat,并省略主 Conversation 的 Header 与宽度控制。
31
31
 
@@ -55,11 +55,11 @@ kind: "package-reference"
55
55
 
56
56
  ### 目录派生
57
57
 
58
- 页头谱系 renderer 通过标准 `useSessions` 钩子读取 `projectionsBySession`。renderer 从每个 Session 的共享值中选择 `subagentCatalog`,用于成员关系、展开控件与数量;活动状态优先使用统一 UI status,缺少时使用 Session 摘要;摘要提供标题与用量。展开行会按需加载初始目录。实时 projection 帧更新所有已加载层级,无需菜单订阅或重复成员查询。行在目录缺席、加载中或失败时保持可展开,并在目录就绪且为空后成为已知叶子。
58
+ 页头谱系 renderer 通过标准 `useSessions` 钩子读取 `projectionsBySession`。renderer 从每个 Session 的共享值中选择 `subagentCatalog`,用于成员关系、展开控件与数量;活动状态优先使用统一 UI status,缺少时使用 Session 摘要;摘要提供标题与用量。展开行读取目标投影,包括普通冷历史。列表行的 `formatStatus` 为 `migration-required` 时,行在展开前即显示“需要迁移”,保留打开历史的操作,但不能展开下级,也不改变子会话的 mode;投影读取需要迁移且缺少目录时,也显示同一提示。打开会话后,历史与 control 投影提供其目录。其他情况下,已有目录仍可使用,包括显式空目录。实时 projection 帧更新所有已加载层级,无需菜单订阅或重复成员查询。其他行在目录缺席、加载中或失败时保持可展开,并在目录就绪且为空后成为已知叶子。外部行始终为叶子,不加载子 Session。
59
59
 
60
60
  打开目录下拉菜单不会请求其根目录。展开子节点目录或重试失败读取时调用 `refreshProjection`;共享投影值的变化会自动更新显示。
61
61
 
62
- 面包屑地址从 Provider 所绑定的 Session 地址和已加载的 parent 目录推导,也包括从未选中过的祖先。
62
+ 面包屑地址从 Provider 所绑定的 Session 地址、已加载的 parent 目录或已列出的 subagent 谱系推导,也包括从未选中过的祖先。
63
63
 
64
64
  ### 耗时、完成状态与 token
65
65
 
@@ -71,6 +71,8 @@ one-shot child 始终选用只读编辑器。可继续 child 仅在其确切 par
71
71
 
72
72
  模式未知的目录项仍可见、可点击,没有标签时显示子会话 id。读取子历史并确认受支持模式前,输入区保持只读;读取失败在该子会话中报告。
73
73
 
74
+ 会话树菜单高亮遵循[标准菜单边缘几何](../../../docs/ui-radius.zh.md#nested-hover);树形展开控件保留独立的左侧空间。
75
+
74
76
  </details>
75
77
 
76
78
  -----
package/lib/client.js CHANGED
@@ -9,7 +9,7 @@ window.__ModuleLoader__.load({
9
9
  let react_dom = require("react-dom");
10
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
11
11
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-subagent/src/client/SubagentHeaderLineage.module.css.mjs
12
- const css$2 = ".ZKlsPq_root{align-items:center;gap:10px;min-width:0;display:inline-flex;position:relative}.ZKlsPq_switcherRoot{min-width:0;margin-left:6px}.ZKlsPq_trigger,.ZKlsPq_switcherTrigger{border-radius:var(--dsw-radius-sm);min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;align-items:center;padding:3px 2px;font-size:12px;line-height:18px;display:inline-flex}.ZKlsPq_trigger{gap:4px}.ZKlsPq_switcherTrigger{min-width:0;max-width:244px;color:var(--dsw-alias-label-primary);gap:4px;font-weight:500}.ZKlsPq_ancestorSwitcherTrigger{color:var(--dsw-alias-label-tertiary);font-weight:400}.ZKlsPq_switcherTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.ZKlsPq_switcherTrigger svg{flex:none}.ZKlsPq_activitySlot{flex:none;justify-content:center;align-items:center;width:14px;height:14px;display:inline-flex}.ZKlsPq_trigger:hover,.ZKlsPq_trigger:focus-visible,.ZKlsPq_switcherTrigger:hover,.ZKlsPq_switcherTrigger:focus-visible{color:var(--dsw-alias-label-primary)}.ZKlsPq_ancestorSwitcherTrigger:hover,.ZKlsPq_ancestorSwitcherTrigger:focus-visible{color:var(--dsw-alias-label-tertiary)}.ZKlsPq_trigger svg,.ZKlsPq_switcherTrigger svg{transition:transform .12s}.ZKlsPq_triggerOpen{transform:rotate(180deg)}.ZKlsPq_menu{z-index:100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:336px;max-width:min(400px,100vw - 32px);max-height:min(560px,100vh - 140px);box-shadow:var(--dsw-elevation-prominent);flex-direction:column;padding:3px;display:flex;position:fixed;overflow:hidden}.ZKlsPq_menu:before{content:\"\";z-index:-1;border-radius:inherit;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);position:absolute;inset:0}.ZKlsPq_menuBody{flex-direction:column;flex:auto;min-height:0;display:flex;overflow:auto}.ZKlsPq_node{min-width:0;position:relative}.ZKlsPq_menuBody>.ZKlsPq_node{margin-left:-2px}.ZKlsPq_row{box-sizing:border-box;border-radius:var(--dsw-radius-lg);width:100%;min-height:44px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;outline:none;align-items:flex-start;gap:6px;padding:6px 7px 6px 9px;font-size:12px;line-height:17px;display:flex;position:relative}.ZKlsPq_row:hover>.ZKlsPq_clickarea,.ZKlsPq_row:focus-visible>.ZKlsPq_clickarea{background:var(--dsw-alias-interactive-bg-hover)}.ZKlsPq_clickarea{box-sizing:border-box;border-radius:var(--dsw-radius-lg);flex:1;align-self:stretch;align-items:flex-start;gap:6px;min-width:0;margin:-6px -7px;padding:6px 7px;display:flex}.ZKlsPq_rowActivitySlot{flex:none;justify-content:center;align-items:center;width:14px;height:17px;display:inline-flex}.ZKlsPq_disclosure,.ZKlsPq_disclosureSpace{flex:none;width:14px;height:17px}.ZKlsPq_disclosure{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0;transition:transform .12s;display:inline-flex}.ZKlsPq_disclosure svg{width:12px;height:12px}.ZKlsPq_disclosure:hover{color:var(--dsw-alias-label-primary)}.ZKlsPq_disclosureOpen{transform:rotate(90deg)}.ZKlsPq_content{flex-direction:column;flex:1;min-width:0;display:flex}.ZKlsPq_label,.ZKlsPq_summary{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ZKlsPq_label{color:inherit;font-weight:400}.ZKlsPq_currentLabel{font-weight:600}.ZKlsPq_summary,.ZKlsPq_metrics{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.ZKlsPq_metrics{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;flex:none;grid-template-rows:17px 15px;display:grid}.ZKlsPq_metricToken{grid-row:1;line-height:17px}.ZKlsPq_metricDuration{grid-row:2}.ZKlsPq_sidebarButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;justify-content:center;align-items:center;margin:4px 0;padding:6px;display:inline-flex}.ZKlsPq_sidebarButton:hover,.ZKlsPq_sidebarButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.ZKlsPq_children{margin-left:16px;padding-left:3px;position:relative}.ZKlsPq_children:before,.ZKlsPq_children>.ZKlsPq_node:before{content:\"\";border-left:.5px solid var(--dsw-alias-border-l2);position:absolute;left:0}.ZKlsPq_children:before{height:23px;top:-23px}.ZKlsPq_children[aria-busy=true]:before{content:none}.ZKlsPq_children>.ZKlsPq_node:before{top:0;bottom:0;left:-3px}.ZKlsPq_children>.ZKlsPq_node:last-child:before{height:15px;bottom:auto}.ZKlsPq_children>.ZKlsPq_node>.ZKlsPq_row:before{content:\"\";border-top:.5px solid var(--dsw-alias-border-l2);width:12px;position:absolute;top:14px;left:-3px}.ZKlsPq_notice,.ZKlsPq_error{color:var(--dsw-alias-label-tertiary);padding:8px 10px;font-size:11px;line-height:16px}.ZKlsPq_error{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:10px;display:flex}.ZKlsPq_refresh{border-radius:var(--dsw-radius-sm);color:inherit;cursor:pointer;background:0 0;border:0;flex:none;align-items:center;gap:3px;padding:3px 5px;display:inline-flex}.ZKlsPq_refresh svg{width:12px;height:12px}.ZKlsPq_refresh:hover{background:var(--dsw-alias-interactive-bg-hover)}";
12
+ const css$2 = ".ZKlsPq_root{align-items:center;gap:10px;min-width:0;display:inline-flex;position:relative}.ZKlsPq_switcherRoot{min-width:0;margin-left:6px}.ZKlsPq_trigger,.ZKlsPq_switcherTrigger{border-radius:var(--dsw-radius-sm);min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;align-items:center;padding:3px 2px;font-size:12px;line-height:18px;display:inline-flex}.ZKlsPq_trigger{gap:4px}.ZKlsPq_switcherTrigger{min-width:0;max-width:244px;color:var(--dsw-alias-label-primary);gap:4px;font-weight:500}.ZKlsPq_ancestorSwitcherTrigger{color:var(--dsw-alias-label-tertiary);font-weight:400}.ZKlsPq_switcherTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.ZKlsPq_switcherTrigger svg{flex:none}.ZKlsPq_activitySlot{flex:none;justify-content:center;align-items:center;width:14px;height:14px;display:inline-flex}.ZKlsPq_trigger:hover,.ZKlsPq_trigger:focus-visible,.ZKlsPq_switcherTrigger:hover,.ZKlsPq_switcherTrigger:focus-visible{color:var(--dsw-alias-label-primary)}.ZKlsPq_ancestorSwitcherTrigger:hover,.ZKlsPq_ancestorSwitcherTrigger:focus-visible{color:var(--dsw-alias-label-tertiary)}.ZKlsPq_trigger svg,.ZKlsPq_switcherTrigger svg{transition:transform .12s}.ZKlsPq_triggerOpen{transform:rotate(180deg)}.ZKlsPq_menu{z-index:100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:336px;max-width:min(400px,100vw - 32px);max-height:min(560px,100vh - 140px);box-shadow:var(--dsw-elevation-prominent);flex-direction:column;padding:4px;display:flex;position:fixed;overflow:hidden}.ZKlsPq_menu:before{content:\"\";z-index:-1;border-radius:inherit;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);position:absolute;inset:0}.ZKlsPq_menuBody{flex-direction:column;flex:auto;min-height:0;display:flex;overflow:auto}.ZKlsPq_node{min-width:0;position:relative}.ZKlsPq_menuBody>.ZKlsPq_node{margin-left:-2px}.ZKlsPq_row{box-sizing:border-box;border-radius:var(--dsw-radius-md);width:100%;min-height:44px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;outline:none;align-items:flex-start;gap:6px;padding:6px 7px 6px 9px;font-size:12px;line-height:17px;display:flex;position:relative}.ZKlsPq_row:hover>.ZKlsPq_clickarea,.ZKlsPq_row:focus-visible>.ZKlsPq_clickarea{background:var(--dsw-alias-interactive-bg-hover)}.ZKlsPq_clickarea{box-sizing:border-box;border-radius:var(--dsw-radius-md);flex:1;align-self:stretch;align-items:flex-start;gap:6px;min-width:0;margin:-6px -7px;padding:6px 7px;display:flex}.ZKlsPq_rowActivitySlot{flex:none;justify-content:center;align-items:center;width:14px;height:17px;display:inline-flex}.ZKlsPq_disclosure,.ZKlsPq_disclosureSpace{flex:none;width:14px;height:17px}.ZKlsPq_disclosure{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0;transition:transform .12s;display:inline-flex}.ZKlsPq_disclosure svg{width:12px;height:12px}.ZKlsPq_disclosure:hover{color:var(--dsw-alias-label-primary)}.ZKlsPq_disclosureOpen{transform:rotate(90deg)}.ZKlsPq_content{flex-direction:column;flex:1;min-width:0;display:flex}.ZKlsPq_label,.ZKlsPq_summary{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ZKlsPq_label{color:inherit;font-weight:400}.ZKlsPq_currentLabel{font-weight:600}.ZKlsPq_summary,.ZKlsPq_metrics{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.ZKlsPq_metrics{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;flex:none;grid-template-rows:17px 15px;display:grid}.ZKlsPq_metricToken{grid-row:1;line-height:17px}.ZKlsPq_metricDuration{grid-row:2}.ZKlsPq_sidebarButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;justify-content:center;align-items:center;margin:4px 0;padding:6px;display:inline-flex}.ZKlsPq_sidebarButton:hover,.ZKlsPq_sidebarButton:focus-visible{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.ZKlsPq_children{margin-left:16px;padding-left:3px;position:relative}.ZKlsPq_children:before,.ZKlsPq_children>.ZKlsPq_node:before{content:\"\";border-left:.5px solid var(--dsw-alias-border-l2);position:absolute;left:0}.ZKlsPq_children:before{height:23px;top:-23px}.ZKlsPq_children[aria-busy=true]:before{content:none}.ZKlsPq_children>.ZKlsPq_node:before{top:0;bottom:0;left:-3px}.ZKlsPq_children>.ZKlsPq_node:last-child:before{height:15px;bottom:auto}.ZKlsPq_children>.ZKlsPq_node>.ZKlsPq_row:before{content:\"\";border-top:.5px solid var(--dsw-alias-border-l2);width:12px;position:absolute;top:14px;left:-3px}.ZKlsPq_notice,.ZKlsPq_error{color:var(--dsw-alias-label-tertiary);padding:8px 10px;font-size:11px;line-height:16px}.ZKlsPq_error{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:10px;display:flex}.ZKlsPq_refresh{border-radius:var(--dsw-radius-sm);color:inherit;cursor:pointer;background:0 0;border:0;flex:none;align-items:center;gap:3px;padding:3px 5px;display:inline-flex}.ZKlsPq_refresh svg{width:12px;height:12px}.ZKlsPq_refresh:hover{background:var(--dsw-alias-interactive-bg-hover)}";
13
13
  const tagId$2 = "@deepseek-ai/dsh-client-ui-subagent/SubagentHeaderLineage.module.css";
14
14
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
15
15
  const tag = document.createElement("style");
@@ -174,7 +174,7 @@ window.__ModuleLoader__.load({
174
174
  };
175
175
  }, [running]);
176
176
  const emptyLoading = catalog.state === "loading" && catalog.entries.length === 0;
177
- const reserveDisclosure = catalog.entries.some((entry) => !isKnownLeaf(catalogs[entry.id]));
177
+ const reserveDisclosure = catalog.entries.some((entry) => entry.mode !== "external" && !isKnownLeaf(catalogs[entry.id]) && summaries[entry.id]?.formatStatus !== "migration-required" && catalogs[entry.id]?.state !== "migration-required");
178
178
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
179
179
  emptyLoading && (0, react_jsx_runtime.jsx)(CatalogLoadingRows, { t }),
180
180
  catalog.state === "error" && (0, react_jsx_runtime.jsxs)("div", {
@@ -189,19 +189,22 @@ window.__ModuleLoader__.load({
189
189
  })]
190
190
  }),
191
191
  catalog.entries.map((entry) => {
192
+ const external = entry.mode === "external";
192
193
  const childCatalog = catalogs[entry.id];
193
194
  const isCurrent = entry.id === currentSessionId;
194
- const isExpanded = expanded.has(entry.id);
195
- const knownLeaf = isKnownLeaf(childCatalog);
195
+ const knownLeaf = external || isKnownLeaf(childCatalog);
196
+ const requiresOpening = summaries[entry.id]?.formatStatus === "migration-required" || childCatalog?.state === "migration-required";
197
+ const canExpand = !knownLeaf && !requiresOpening;
198
+ const isExpanded = canExpand && expanded.has(entry.id);
196
199
  const childLoading = childCatalog === void 0 || childCatalog.state === "loading" && childCatalog.entries.length === 0;
197
200
  const summary = summaries[entry.id];
198
201
  const label = entry.label ?? entry.id;
199
- const mode = entry.mode === "unknown" ? t("mode.unknown") : entry.mode === "one-shot" ? t("mode.oneShot") : t("mode.continuable");
200
- const completed = entry.activity === "inactive" && summary?.projectionValues?.subagentTiming?.lastTurnCompleted === true;
201
- const activity = entry.activity === "running" ? t("activity.running") : completed ? t("activity.completed") : t("activity.inactive");
202
+ const mode = external ? t("mode.external") : entry.mode === "unknown" ? t("mode.unknown") : entry.mode === "one-shot" ? t("mode.oneShot") : t("mode.continuable");
203
+ const completed = !external && entry.activity === "inactive" && summary?.projectionValues?.subagentTiming?.lastTurnCompleted === true;
204
+ const activity = external ? void 0 : entry.activity === "running" ? t("activity.running") : completed ? t("activity.completed") : t("activity.inactive");
202
205
  const secondary = [
203
206
  summary?.title,
204
- mode,
207
+ requiresOpening ? t("catalog.migrationRequired") : mode,
205
208
  activity
206
209
  ].filter((value) => value !== void 0).join(" · ");
207
210
  const totalTokens = tokenTotal(summary?.projectionValues?.tokenUsage);
@@ -213,6 +216,7 @@ window.__ModuleLoader__.load({
213
216
  };
214
217
  const metrics = [tokenMetric, durationMetric?.exact].filter((value) => value !== void 0).join(" · ");
215
218
  const open = () => {
219
+ if (external) return;
216
220
  openChild({
217
221
  parentSessionId,
218
222
  childSessionId: entry.id,
@@ -220,22 +224,12 @@ window.__ModuleLoader__.load({
220
224
  });
221
225
  closeCatalog();
222
226
  };
223
- const openAside = (event) => {
224
- event.preventDefault();
225
- event.stopPropagation();
226
- openChildAside({
227
- parentSessionId,
228
- childSessionId: entry.id,
229
- mode: entry.mode
230
- });
231
- closeCatalog();
232
- };
233
227
  const handleKey = (event) => {
234
228
  if (event.key === "Enter" || event.key === " ") {
235
229
  event.preventDefault();
236
230
  event.stopPropagation();
237
231
  open();
238
- } else if (event.key === "ArrowRight" && !knownLeaf && !isExpanded || event.key === "ArrowLeft" && isExpanded) {
232
+ } else if (event.key === "ArrowRight" && canExpand && !isExpanded || event.key === "ArrowLeft" && isExpanded) {
239
233
  event.preventDefault();
240
234
  event.stopPropagation();
241
235
  toggleBranch(entry.id);
@@ -250,7 +244,8 @@ window.__ModuleLoader__.load({
250
244
  className: SubagentHeaderLineage_module_css_default.node,
251
245
  children: [(0, react_jsx_runtime.jsxs)("div", {
252
246
  role: "treeitem",
253
- tabIndex: 0,
247
+ tabIndex: external ? -1 : 0,
248
+ "aria-disabled": external || void 0,
254
249
  "aria-level": level,
255
250
  "aria-current": isCurrent || void 0,
256
251
  "aria-label": [
@@ -258,11 +253,11 @@ window.__ModuleLoader__.load({
258
253
  secondary,
259
254
  metrics
260
255
  ].filter((value) => value !== "").join(" "),
261
- ...knownLeaf ? {} : { "aria-expanded": isExpanded },
256
+ ...canExpand ? { "aria-expanded": isExpanded } : {},
262
257
  className: SubagentHeaderLineage_module_css_default.row,
263
258
  onClick: open,
264
259
  onKeyDown: handleKey,
265
- children: [knownLeaf ? reserveDisclosure && (0, react_jsx_runtime.jsx)("span", { className: SubagentHeaderLineage_module_css_default.disclosureSpace }) : (0, react_jsx_runtime.jsx)("button", {
260
+ children: [!canExpand ? reserveDisclosure && (0, react_jsx_runtime.jsx)("span", { className: SubagentHeaderLineage_module_css_default.disclosureSpace }) : (0, react_jsx_runtime.jsx)("button", {
266
261
  type: "button",
267
262
  tabIndex: -1,
268
263
  className: `${SubagentHeaderLineage_module_css_default.disclosure} ${isExpanded ? SubagentHeaderLineage_module_css_default.disclosureOpen : ""}`,
@@ -297,7 +292,7 @@ window.__ModuleLoader__.load({
297
292
  children: durationMetric.compact
298
293
  })]
299
294
  }),
300
- !isCurrent && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
295
+ !isCurrent && !external && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
301
296
  label: t("open.sidebar"),
302
297
  side: "bottom",
303
298
  align: "end",
@@ -305,7 +300,16 @@ window.__ModuleLoader__.load({
305
300
  type: "button",
306
301
  className: SubagentHeaderLineage_module_css_default.sidebarButton,
307
302
  "aria-label": t("open.sidebar.aria", { label }),
308
- onClick: openAside,
303
+ onClick: (event) => {
304
+ event.preventDefault();
305
+ event.stopPropagation();
306
+ openChildAside({
307
+ parentSessionId,
308
+ childSessionId: entry.id,
309
+ mode: entry.mode
310
+ });
311
+ closeCatalog();
312
+ },
309
313
  onKeyDown: (event) => {
310
314
  event.stopPropagation();
311
315
  },
@@ -314,7 +318,7 @@ window.__ModuleLoader__.load({
314
318
  })
315
319
  ]
316
320
  })]
317
- }), isExpanded && !knownLeaf && (0, react_jsx_runtime.jsx)("div", {
321
+ }), isExpanded && (0, react_jsx_runtime.jsx)("div", {
318
322
  role: "group",
319
323
  className: SubagentHeaderLineage_module_css_default.children,
320
324
  "aria-busy": childLoading || void 0,
@@ -354,14 +358,19 @@ window.__ModuleLoader__.load({
354
358
  const projections = useSessions((state) => state.projectionsBySession);
355
359
  const summaries = useSessions((state) => state.byId);
356
360
  const statuses = useSessionStatus((value) => value);
357
- const catalogs = (0, react.useMemo)(() => Object.fromEntries(Object.entries(projections).map(([id, snapshot]) => [id, {
358
- state: snapshot.state === "idle" ? snapshot.values.subagentCatalog === void 0 ? "loading" : "ready" : snapshot.state,
359
- error: snapshot.error,
360
- entries: (snapshot.values.subagentCatalog ?? []).map((entry) => ({
361
- ...entry,
362
- activity: (statuses.get(entry.id)?.running ?? summaries[entry.id]?.running) === true ? "running" : "inactive"
363
- }))
364
- }])), [
361
+ const catalogs = (0, react.useMemo)(() => {
362
+ return Object.fromEntries(Object.entries(projections).map(([id, snapshot]) => {
363
+ const projected = snapshot.values.subagentCatalog;
364
+ return [id, {
365
+ state: snapshot.state === "idle" ? projected === void 0 ? "loading" : "ready" : snapshot.state === "migration-required" && projected !== void 0 ? "ready" : snapshot.state,
366
+ error: snapshot.error,
367
+ entries: (projected ?? []).map((entry) => ({
368
+ ...entry,
369
+ activity: (statuses.get(entry.id)?.running ?? summaries[entry.id]?.running) === true ? "running" : "inactive"
370
+ }))
371
+ }];
372
+ }));
373
+ }, [
365
374
  projections,
366
375
  summaries,
367
376
  statuses
@@ -376,7 +385,7 @@ window.__ModuleLoader__.load({
376
385
  const hoverOpenTimer = (0, react.useRef)(void 0);
377
386
  const hoverCloseTimer = (0, react.useRef)(void 0);
378
387
  const pinnedRef = (0, react.useRef)(false);
379
- const currentEntry = currentSessionId === void 0 ? void 0 : catalog?.entries.find((entry) => entry.id === currentSessionId);
388
+ const currentEntry = currentSessionId === void 0 ? void 0 : projections[rootSessionId]?.values.subagentCatalog?.find((entry) => entry.id === currentSessionId);
380
389
  const switcherDisplayTitle = currentEntry !== void 0 ? currentEntry.label ?? currentEntry.id : displayTitle;
381
390
  const directChildren = catalog?.entries ?? [];
382
391
  const directCount = directChildren.length;
@@ -593,7 +602,7 @@ window.__ModuleLoader__.load({
593
602
  }
594
603
  /**
595
604
  * Session-header catalog action for root sessions: the descendant count and
596
- * its dropdown at the start of the header actions band. Child sessions render nothing
605
+ * its dropdown after the preset label in the header actions band. Child sessions render nothing
597
606
  * here — their breadcrumb switcher in the lineage slot owns the same
598
607
  * navigation.
599
608
  * @param props - Session standard props plus the catalog actions and translator.
@@ -622,6 +631,8 @@ window.__ModuleLoader__.load({
622
631
  const parentId = useSessions((state) => {
623
632
  if (address?.childSessionId === lineageSessionId) return address.parentSessionId;
624
633
  for (const [parentId, snapshot] of Object.entries(state.projectionsBySession)) if (snapshot.values.subagentCatalog?.some((entry) => entry.id === lineageSessionId)) return parentId;
634
+ const summary = state.byId[lineageSessionId];
635
+ return summary?.origin === "subagent" ? summary.parentId : void 0;
625
636
  });
626
637
  const shared = {
627
638
  useSessions,
@@ -639,11 +650,11 @@ window.__ModuleLoader__.load({
639
650
  displayTitle,
640
651
  ...openTitle === void 0 ? {} : { openTitle },
641
652
  ...shared
642
- }, lineageSessionId), openTitle === void 0 && (0, react_jsx_runtime.jsx)(CatalogDropdown, {
653
+ }, `switcher:${lineageSessionId}`), openTitle === void 0 && (0, react_jsx_runtime.jsx)(CatalogDropdown, {
643
654
  rootSessionId: lineageSessionId,
644
655
  variant: "count",
645
656
  ...shared
646
- }, lineageSessionId)] });
657
+ }, `children:${lineageSessionId}`)] });
647
658
  }
648
659
  //#endregion
649
660
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-subagent/src/client/SubagentReadOnlyComposer.module.css.mjs
@@ -849,7 +860,9 @@ window.__ModuleLoader__.load({
849
860
  "tokens.total": "{value} tok",
850
861
  "loading.label": "正在加载子智能体…",
851
862
  "load.error": "无法加载子智能体",
863
+ "catalog.migrationRequired": "需要迁移",
852
864
  "retry": "重试",
865
+ "mode.external": "外部任务",
853
866
  "mode.oneShot": "一次性",
854
867
  "mode.continuable": "可继续",
855
868
  "mode.unknown": "模式未知",
@@ -891,7 +904,9 @@ window.__ModuleLoader__.load({
891
904
  "tokens.total": "{value} tok",
892
905
  "loading.label": "Loading subagents…",
893
906
  "load.error": "Unable to load subagents",
907
+ "catalog.migrationRequired": "Migration required",
894
908
  "retry": "Retry",
909
+ "mode.external": "External task",
895
910
  "mode.oneShot": "one-shot",
896
911
  "mode.continuable": "continuable",
897
912
  "mode.unknown": "unknown mode",
@@ -968,7 +983,7 @@ window.__ModuleLoader__.load({
968
983
  ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
969
984
  name: "conversation.session.header.actions",
970
985
  id: "subagent-catalog",
971
- order: -30,
986
+ order: 10,
972
987
  locale: NS,
973
988
  inject: catalogActions
974
989
  }, SubagentCatalogAction));
@@ -14,7 +14,7 @@ export type SubagentHeaderLineageProps = PropsRuntime<'conversation.session.head
14
14
  export type SubagentCatalogActionProps = PropsRuntime<'conversation.session.header.actions'> & SubagentCatalogInjected & PropsLocale<typeof NS>;
15
15
  /**
16
16
  * Session-header catalog action for root sessions: the descendant count and
17
- * its dropdown at the start of the header actions band. Child sessions render nothing
17
+ * its dropdown after the preset label in the header actions band. Child sessions render nothing
18
18
  * here — their breadcrumb switcher in the lineage slot owns the same
19
19
  * navigation.
20
20
  * @param props - Session standard props plus the catalog actions and translator.
@@ -19,7 +19,9 @@ export declare const zh: {
19
19
  readonly 'tokens.total': "{value} tok";
20
20
  readonly 'loading.label': "正在加载子智能体…";
21
21
  readonly 'load.error': "无法加载子智能体";
22
+ readonly 'catalog.migrationRequired': "需要迁移";
22
23
  readonly retry: "重试";
24
+ readonly 'mode.external': "外部任务";
23
25
  readonly 'mode.oneShot': "一次性";
24
26
  readonly 'mode.continuable': "可继续";
25
27
  readonly 'mode.unknown': "模式未知";
package/locale/en.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "meta": {
3
+ "title": "ui-subagent"
4
+ }
5
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "子智能体会话界面",
4
+ "description": "查看和跳转子智能体会话,并支持继续对话和 @ 引用。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-subagent",
3
3
  "description": "Subagent conversation catalog, continuation routing UI, and '@' reference source",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -23,7 +23,8 @@
23
23
  "default": "./lib/client.js"
24
24
  },
25
25
  "./src/*": "./src/*",
26
- "./package.json": "./package.json"
26
+ "./package.json": "./package.json",
27
+ "./locale/*.json": "./locale/*.json"
27
28
  },
28
29
  "dsh": {
29
30
  "client": {
@@ -43,33 +44,32 @@
43
44
  },
44
45
  "license": "MIT",
45
46
  "peerDependencies": {
46
- "@deepseek-ai/cordis": "~4.0.5-alpha.1"
47
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2"
47
48
  },
48
49
  "devDependencies": {
49
- "@types/react": "~18.3.1",
50
- "@types/react-dom": "~18.3.0",
50
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.3",
51
+ "@deepseek-ai/dsh-client-resources": "0.2.1-alpha.3",
52
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.3",
53
+ "@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.3",
54
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.3",
55
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-alpha.3",
56
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.3",
57
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.3",
58
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.3",
59
+ "@deepseek-ai/dsh-token-meter": "0.2.1-alpha.3",
60
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
51
61
  "react": "^18.2.0",
52
62
  "react-dom": "^18.2.0",
53
- "@deepseek-ai/dsh-client-resources": "0.2.1-alpha.1",
54
- "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.1",
55
- "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.1",
56
- "@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.1",
57
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.1",
58
- "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-alpha.1",
59
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.1",
60
- "@deepseek-ai/dsh-subagent": "0.2.1-alpha.1",
61
- "@deepseek-ai/dsh-token-meter": "0.2.1-alpha.1",
62
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
63
- "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
64
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.1",
65
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
66
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.1",
67
- "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.1-alpha.1",
68
- "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-alpha.1",
69
- "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.1",
70
- "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.1"
63
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.3",
64
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.3",
65
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.3",
66
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.3",
67
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.1-alpha.3",
68
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.3",
69
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-alpha.3"
71
70
  },
72
71
  "files": [
72
+ "locale/*.json",
73
73
  "lib/index.js",
74
74
  "lib/client.js",
75
75
  "lib/types/**/*.d.ts"