@deepseek-ai/dsh-client-ui-subagent 0.1.6-alpha.1 → 0.1.6-alpha.2

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
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-subagent/README.md
5
- README.md: f4c6da14e5cf3788f2ea0c40902b2dc07558ec7c
6
- README.zh.md: d96b6dfcaadd02514dc65d74a3a1f266a98f1f3c
5
+ README.md: d0dadc79f552c28c5fea20a23a91c25a24e8ed61
6
+ README.zh.md: 295206ace11baf67112db17b5bda10a52b80d9aa
package/README.md CHANGED
@@ -25,7 +25,9 @@ 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 and, when the session has subagent descendants, appends a `/` count trigger before the header's action row; the trigger opens the descendant catalog, counts the complete subagent-only lineage, stops at ordinary forks, and shows ongoing activity when any counted descendant is running. Select any depth to open that child's conversation with its exact `{parentSessionId, childSessionId, mode}` address.
28
+ The session header keeps the current session title as the lineage breadcrumb and, when the session has subagent descendants, appends a `/` count trigger before the header's action row; the trigger opens the descendant catalog, counts the complete subagent-only lineage, stops at ordinary forks, and shows ongoing activity when any counted descendant is running. 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.
29
+
30
+ This package registers the `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` resource and builtin Sidebar tab type. The resource refreshes the direct-parent catalog before it retains the child `SessionReference`, 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.
29
31
 
30
32
  ### Browsing the tree
31
33
 
package/README.zh.md CHANGED
@@ -25,7 +25,9 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 会话页头保留当前会话 title 作为谱系面包屑,并在会话存在 subagent 后代时,于页头操作行之前追加 `/` 数量触发器;触发器打开后代目录,统计仅含 subagent 的完整谱系、在普通 fork 处停止,并在任一计入统计的后代处于 `running` 时显示活动仍在进行。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话。
28
+ 会话页头保留当前会话 title 作为谱系面包屑,并在会话存在 subagent 后代时,于页头操作行之前追加 `/` 数量触发器;触发器打开后代目录,统计仅含 subagent 的完整谱系、在普通 fork 处停止,并在任一计入统计的后代处于 `running` 时显示活动仍在进行。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话;也可以使用行尾箭头在右侧 Sidebar 打开同一地址,并在空间允许时优先使用独立分栏。
29
+
30
+ 本包注册 `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` 资源与 builtin Sidebar tab 类型。资源先刷新直接 parent 目录,再保留 child 的 `SessionReference`,并在 tab 记录关闭时释放 reference。tab 通过 `sidebar.chat.conversation` 渲染共享 `conversation.content` Factory,把局部 View 固定为 Chat,并省略主 Conversation 的 Header 与宽度控制。
29
31
 
30
32
  ### 浏览目录
31
33
 
package/lib/client.js CHANGED
@@ -9,13 +9,13 @@ 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$1 = ".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{min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;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_separator{color:var(--dsw-alias-label-caption);font-size:14px;line-height:20px}.ZKlsPq_activitySlot{flex:none;width:10px;height:10px;display:inline-flex}.ZKlsPq_trigger:hover,.ZKlsPq_trigger:focus-visible{color:var(--dsw-alias-label-secondary)}.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;background:var(--dsw-specific-menu);--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);border-radius:20px;flex-direction:column;padding:4px;display:flex;position:fixed;overflow:auto}.ZKlsPq_node{min-width:0;position:relative}.ZKlsPq_menu>.ZKlsPq_node{margin-left:-3px}.ZKlsPq_row{box-sizing:border-box;width:100%;min-height:50px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:8px;outline:none;align-items:flex-start;gap:8px;padding:7px 8px 7px 11px;font-size:13px;line-height:18px;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:8px;flex:1;align-self:stretch;align-items:flex-start;gap:8px;min-width:0;margin:-7px -8px;padding:7px 8px;display:flex}.ZKlsPq_row>[data-state],.ZKlsPq_clickarea>[data-state]{margin-top:4px}.ZKlsPq_disabled{color:var(--dsw-alias-label-dimmed);cursor:not-allowed}.ZKlsPq_disabled:hover{background:0 0}.ZKlsPq_loadingRow{cursor:default}.ZKlsPq_disclosure,.ZKlsPq_disclosureSpace{flex:none;width:14px;height:18px}.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: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:11px;line-height:16px}.ZKlsPq_metrics{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;flex:none;grid-template-rows:18px 16px;display:grid}.ZKlsPq_metricToken{grid-row:1;line-height:18px}.ZKlsPq_metricDuration{grid-row:2}.ZKlsPq_children{margin-left:18px;padding-left:4px;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:26px;top:-26px}.ZKlsPq_children[aria-busy=true]:before{content:none}.ZKlsPq_children>.ZKlsPq_node:before{top:0;bottom:0;left:-4px}.ZKlsPq_children>.ZKlsPq_node:last-child:before{height:17px;bottom:auto}.ZKlsPq_children>.ZKlsPq_node>.ZKlsPq_row:before{content:\"\";border-top:.5px solid var(--dsw-alias-border-l2);width:14px;position:absolute;top:16px;left:-4px}.ZKlsPq_notice,.ZKlsPq_error{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.ZKlsPq_error{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:12px;display:flex}.ZKlsPq_refresh{color:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;align-items:center;gap:4px;padding:4px 6px;display:inline-flex}.ZKlsPq_refresh:hover{background:var(--dsw-alias-interactive-bg-hover)}";
13
- const tagId$1 = "@deepseek-ai/dsh-client-ui-subagent/SubagentHeaderLineage.module.css";
14
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
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{min-height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;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_separator{color:var(--dsw-alias-label-caption);font-size:14px;line-height:20px}.ZKlsPq_activitySlot{flex:none;width:10px;height:10px;display:inline-flex}.ZKlsPq_trigger:hover,.ZKlsPq_trigger:focus-visible{color:var(--dsw-alias-label-secondary)}.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;background:var(--dsw-specific-menu);--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);border-radius:20px;flex-direction:column;padding:4px;display:flex;position:fixed;overflow:auto}.ZKlsPq_node{min-width:0;position:relative}.ZKlsPq_menu>.ZKlsPq_node{margin-left:-3px}.ZKlsPq_row{box-sizing:border-box;width:100%;min-height:50px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:8px;outline:none;align-items:flex-start;gap:8px;padding:7px 8px 7px 11px;font-size:13px;line-height:18px;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:8px;flex:1;align-self:stretch;align-items:flex-start;gap:8px;min-width:0;margin:-7px -8px;padding:7px 8px;display:flex}.ZKlsPq_row>[data-state],.ZKlsPq_clickarea>[data-state]{margin-top:4px}.ZKlsPq_disabled{color:var(--dsw-alias-label-dimmed);cursor:not-allowed}.ZKlsPq_disabled:hover{background:0 0}.ZKlsPq_loadingRow{cursor:default}.ZKlsPq_disclosure,.ZKlsPq_disclosureSpace{flex:none;width:14px;height:18px}.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: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:11px;line-height:16px}.ZKlsPq_metrics{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;flex:none;grid-template-rows:18px 16px;display:grid}.ZKlsPq_metricToken{grid-row:1;line-height:18px}.ZKlsPq_metricDuration{grid-row:2}.ZKlsPq_sidebarButton{corner-shape:round;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:50%;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:18px;padding-left:4px;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:26px;top:-26px}.ZKlsPq_children[aria-busy=true]:before{content:none}.ZKlsPq_children>.ZKlsPq_node:before{top:0;bottom:0;left:-4px}.ZKlsPq_children>.ZKlsPq_node:last-child:before{height:17px;bottom:auto}.ZKlsPq_children>.ZKlsPq_node>.ZKlsPq_row:before{content:\"\";border-top:.5px solid var(--dsw-alias-border-l2);width:14px;position:absolute;top:16px;left:-4px}.ZKlsPq_notice,.ZKlsPq_error{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.ZKlsPq_error{color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:12px;display:flex}.ZKlsPq_refresh{color:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;align-items:center;gap:4px;padding:4px 6px;display:inline-flex}.ZKlsPq_refresh:hover{background:var(--dsw-alias-interactive-bg-hover)}";
13
+ const tagId$2 = "@deepseek-ai/dsh-client-ui-subagent/SubagentHeaderLineage.module.css";
14
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
15
15
  const tag = document.createElement("style");
16
16
  tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-subagent";
17
- tag.dataset.pluginCss = tagId$1;
18
- tag.textContent = css$1;
17
+ tag.dataset.pluginCss = tagId$2;
18
+ tag.textContent = css$2;
19
19
  document.head.appendChild(tag);
20
20
  }
21
21
  var SubagentHeaderLineage_module_css_default = {
@@ -42,6 +42,7 @@ window.__ModuleLoader__.load({
42
42
  "root": "ZKlsPq_root",
43
43
  "row": "ZKlsPq_row",
44
44
  "separator": "ZKlsPq_separator",
45
+ "sidebarButton": "ZKlsPq_sidebarButton",
45
46
  "summary": "ZKlsPq_summary",
46
47
  "switcherRoot": "ZKlsPq_switcherRoot",
47
48
  "switcherTitle": "ZKlsPq_switcherTitle",
@@ -220,7 +221,7 @@ window.__ModuleLoader__.load({
220
221
  }, summary.id));
221
222
  }
222
223
  /** Render one catalog level and recurse only through explicitly expanded rows. */
223
- function CatalogRows({ parentSessionId, currentSessionId, catalog, catalogs, summaries, expanded, level, now, openChild, refresh, toggleBranch, closeCatalog, t }) {
224
+ function CatalogRows({ parentSessionId, currentSessionId, catalog, catalogs, summaries, expanded, level, now, openChild, openChildAside, refresh, toggleBranch, closeCatalog, t }) {
224
225
  const emptyLoading = catalog.state === "loading" && catalog.entries.length === 0;
225
226
  const reserveDisclosure = catalog.entries.some((entry) => entry.kind === "child" && entry.hasChildren);
226
227
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
@@ -300,6 +301,16 @@ window.__ModuleLoader__.load({
300
301
  });
301
302
  closeCatalog();
302
303
  };
304
+ const openAside = (event) => {
305
+ event.preventDefault();
306
+ event.stopPropagation();
307
+ openChildAside({
308
+ parentSessionId,
309
+ childSessionId: entry.id,
310
+ mode: entry.mode
311
+ });
312
+ closeCatalog();
313
+ };
303
314
  const handleKey = (event) => {
304
315
  if (event.key === "Enter" || event.key === " ") {
305
316
  event.preventDefault();
@@ -363,6 +374,17 @@ window.__ModuleLoader__.load({
363
374
  title: t("duration.exactTitle", { duration: durationMetric.exact }),
364
375
  children: durationMetric.compact
365
376
  })]
377
+ }),
378
+ !isCurrent && (0, react_jsx_runtime.jsx)("button", {
379
+ type: "button",
380
+ className: SubagentHeaderLineage_module_css_default.sidebarButton,
381
+ "aria-label": t("open.sidebar", { label }),
382
+ title: t("open.sidebar", { label }),
383
+ onClick: openAside,
384
+ onKeyDown: (event) => {
385
+ event.stopPropagation();
386
+ },
387
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
366
388
  })
367
389
  ]
368
390
  })]
@@ -385,6 +407,7 @@ window.__ModuleLoader__.load({
385
407
  level: level + 1,
386
408
  now,
387
409
  openChild,
410
+ openChildAside,
388
411
  refresh,
389
412
  toggleBranch,
390
413
  closeCatalog,
@@ -406,7 +429,7 @@ window.__ModuleLoader__.load({
406
429
  };
407
430
  }
408
431
  /** One trigger-plus-tree dropdown over the catalog rooted at `rootSessionId`. */
409
- function CatalogDropdown({ rootSessionId, currentSessionId, displayTitle, openTitle, variant, separator = false, useSessions, openChild, refresh, setCatalogOpen, t }) {
432
+ function CatalogDropdown({ rootSessionId, currentSessionId, displayTitle, openTitle, variant, separator = false, useSessions, openChild, openChildAside, refresh, setCatalogOpen, t }) {
410
433
  const ancestorSwitcher = variant === "switcher" && openTitle !== void 0;
411
434
  const catalogs = useSessions((state) => state.subagentsByParent);
412
435
  const summaries = useSessions((state) => state.byId);
@@ -648,6 +671,7 @@ window.__ModuleLoader__.load({
648
671
  level: 1,
649
672
  now,
650
673
  openChild,
674
+ openChildAside,
651
675
  refresh,
652
676
  toggleBranch,
653
677
  closeCatalog: () => {
@@ -664,7 +688,7 @@ window.__ModuleLoader__.load({
664
688
  * @param props - Breadcrumb title, session standard props, and catalog actions.
665
689
  * @returns An ordinary-title descendant count, or a title-and-chevron sibling switcher.
666
690
  */
667
- function SubagentHeaderLineage({ lineageSessionId, displayTitle, openTitle, useSessions, openChild, refresh, setCatalogOpen, t }) {
691
+ function SubagentHeaderLineage({ lineageSessionId, displayTitle, openTitle, useSessions, openChild, openChildAside, refresh, setCatalogOpen, t }) {
668
692
  const parentId = useSessions((state) => {
669
693
  const summary = state.byId[lineageSessionId];
670
694
  return summary?.origin === "subagent" ? summary.parentId : void 0;
@@ -672,6 +696,7 @@ window.__ModuleLoader__.load({
672
696
  const shared = {
673
697
  useSessions,
674
698
  openChild,
699
+ openChildAside,
675
700
  refresh,
676
701
  setCatalogOpen,
677
702
  t
@@ -697,13 +722,13 @@ window.__ModuleLoader__.load({
697
722
  }
698
723
  //#endregion
699
724
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-subagent/src/client/SubagentReadOnlyComposer.module.css.mjs
700
- const css = ".XJ7liG_frame{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-1);min-height:54px;color:var(--dsw-alias-label-tertiary);border-radius:14px;justify-content:center;align-items:center;gap:8px;margin:0 24px 20px;padding:10px 16px;font-size:13px;line-height:20px;display:flex}.XJ7liG_frame strong{color:var(--dsw-alias-label-primary);font-weight:510}";
701
- const tagId = "@deepseek-ai/dsh-client-ui-subagent/SubagentReadOnlyComposer.module.css";
702
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
725
+ const css$1 = ".XJ7liG_frame{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-1);min-height:54px;color:var(--dsw-alias-label-tertiary);border-radius:14px;justify-content:center;align-items:center;gap:8px;margin:0 24px 20px;padding:10px 16px;font-size:13px;line-height:20px;display:flex}.XJ7liG_frame strong{color:var(--dsw-alias-label-primary);font-weight:510}";
726
+ const tagId$1 = "@deepseek-ai/dsh-client-ui-subagent/SubagentReadOnlyComposer.module.css";
727
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
703
728
  const tag = document.createElement("style");
704
729
  tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-subagent";
705
- tag.dataset.pluginCss = tagId;
706
- tag.textContent = css;
730
+ tag.dataset.pluginCss = tagId$1;
731
+ tag.textContent = css$1;
707
732
  document.head.appendChild(tag);
708
733
  }
709
734
  var SubagentReadOnlyComposer_module_css_default = { "frame": "XJ7liG_frame" };
@@ -723,6 +748,162 @@ window.__ModuleLoader__.load({
723
748
  });
724
749
  }
725
750
  //#endregion
751
+ //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-subagent/src/client/sidebar-chat/SidebarChat.module.css.mjs
752
+ const css = ".olTFqa_root{width:100%;min-width:0;height:100%;min-height:0;display:flex}";
753
+ const tagId = "@deepseek-ai/dsh-client-ui-subagent/SidebarChat.module.css";
754
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
755
+ const tag = document.createElement("style");
756
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-subagent";
757
+ tag.dataset.pluginCss = tagId;
758
+ tag.textContent = css;
759
+ document.head.appendChild(tag);
760
+ }
761
+ var SidebarChat_module_css_default = { "root": "olTFqa_root" };
762
+ //#endregion
763
+ //#region lib/types/client/sidebar-chat/index.js
764
+ /** Stable implementation identity for the Sidebar tab body. */
765
+ const SUBAGENT_CHAT_ID = "@deepseek-ai/dsh-client-ui-subagent";
766
+ /** Resource-address prefix for an embedded Session chat. */
767
+ const SUBAGENT_CHAT_ADDRESS = "dsh-resource://subagentchat/session/";
768
+ /**
769
+ * Address one subagent Session together with the routing facts needed to restore it.
770
+ * @param address - durable direct-parent subagent address.
771
+ * @returns canonical Sidebar resource address.
772
+ */
773
+ function subagentChatAddress(address) {
774
+ const query = new URLSearchParams({
775
+ parent: address.parentSessionId,
776
+ mode: address.mode
777
+ });
778
+ return `${SUBAGENT_CHAT_ADDRESS}${encodeURIComponent(address.childSessionId)}?${query}`;
779
+ }
780
+ /**
781
+ * Parse one canonical Sidebar chat resource address.
782
+ * @param value - possible chat resource address.
783
+ * @returns the encoded direct-parent address, or undefined for another or malformed resource.
784
+ */
785
+ function parseSubagentChatAddress(value) {
786
+ let url;
787
+ try {
788
+ url = new URL(value);
789
+ } catch (_invalidUrl) {
790
+ return;
791
+ }
792
+ if (url.protocol !== "dsh-resource:" || url.hostname.toLowerCase() !== "subagentchat") return void 0;
793
+ const parts = url.pathname.split("/").filter(Boolean);
794
+ if (parts.length !== 2 || parts[0] !== "session") return void 0;
795
+ const parentSessionId = url.searchParams.get("parent");
796
+ const mode = url.searchParams.get("mode");
797
+ if (parentSessionId === null || parentSessionId === "" || mode !== "one-shot" && mode !== "continuable") return;
798
+ try {
799
+ return {
800
+ parentSessionId,
801
+ childSessionId: decodeURIComponent(parts[1]),
802
+ mode
803
+ };
804
+ } catch (_invalidEncoding) {
805
+ return;
806
+ }
807
+ }
808
+ function waitForAbort(signal) {
809
+ if (signal.aborted) return Promise.resolve();
810
+ return new Promise((resolve) => {
811
+ signal.addEventListener("abort", () => {
812
+ resolve();
813
+ }, { once: true });
814
+ });
815
+ }
816
+ function isAbortRequested(signal) {
817
+ return signal.aborted;
818
+ }
819
+ function subagentChatResourceProvider(sessions) {
820
+ return {
821
+ protocol: "subagentchat",
822
+ async *open(resourceAddress, { signal }) {
823
+ const address = parseSubagentChatAddress(resourceAddress);
824
+ if (address === void 0) throw new Error(`ui-subagent: invalid chat resource address "${resourceAddress}"`);
825
+ if (isAbortRequested(signal)) return;
826
+ await sessions.refreshSubagents(address.parentSessionId);
827
+ if (isAbortRequested(signal)) return;
828
+ const reference = sessions.retain(address, {
829
+ source: "sidebarChat",
830
+ signal
831
+ });
832
+ try {
833
+ yield {
834
+ ok: true,
835
+ value: {
836
+ address,
837
+ reference
838
+ }
839
+ };
840
+ await waitForAbort(signal);
841
+ } finally {
842
+ reference.release();
843
+ }
844
+ }
845
+ };
846
+ }
847
+ /** Fixed Chat selection used by an embedded Conversation occurrence. */
848
+ function FixedChatConversationView(props) {
849
+ return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.renderSlot("conversation.session", { view: "chat" }) });
850
+ }
851
+ /** Render the shared Conversation content for one explicitly provided child Session. */
852
+ function ConversationSlotPanel({ sessionId, useSession, useConversation, useSessions, renderFactorySlot }) {
853
+ const session = useSession((value) => value);
854
+ const shellPhase = useConversation((value) => value).activeTargets.size > 0 || !session.blank && !session.awaitingFirstTurn || session.running ? "active" : session.promptAttempted ? "engaging" : "blank";
855
+ const summaryBlank = useSessions((state) => state.byId[sessionId]?.blank);
856
+ const parentAvailabilityPending = session.subagent?.address.mode === "continuable" && session.subagent.parentAvailable === void 0;
857
+ const settling = shellPhase === "blank" && session.openState === "loading" && summaryBlank !== true || parentAvailabilityPending;
858
+ const hero = shellPhase === "blank" && (session.openState === "open" || summaryBlank === true);
859
+ return renderFactorySlot("conversation.content", {
860
+ variant: "embedded",
861
+ phase: settling ? "settling" : hero ? "hero" : "active",
862
+ hero
863
+ }, { slots: { views: FixedChatConversationView } });
864
+ }
865
+ /** Bind a chat resource's child reference around its Conversation slot. */
866
+ function SidebarChatTab({ useResource, useTabInfo, SessionProvider, renderSlot }) {
867
+ const { tab } = useTabInfo();
868
+ const resource = useResource(tab.contentId);
869
+ return (0, react_jsx_runtime.jsx)("div", {
870
+ className: SidebarChat_module_css_default.root,
871
+ "data-sidebar-chat": "",
872
+ children: resource.value === void 0 ? null : (0, react_jsx_runtime.jsx)(SessionProvider, {
873
+ session: resource.value.reference,
874
+ children: renderSlot("sidebar.chat.conversation", {})
875
+ })
876
+ });
877
+ }
878
+ /**
879
+ * Register the chat resource owner and its right-Sidebar presentation.
880
+ * @param ctx - Client root carrying Sessions, resources, Slots, and Sidebar registries.
881
+ * @param t - Chat namespace translator used for fallback tab titles.
882
+ */
883
+ function registerSidebarChat(ctx, t) {
884
+ ctx.effect(() => ctx.resources.register(subagentChatResourceProvider(ctx.sessions)), "ui-subagent: Sidebar chat resources");
885
+ ctx.effect(() => ctx.sidebarRightTabs.register({
886
+ id: SUBAGENT_CHAT_ID,
887
+ kind: "subagentchat",
888
+ patterns: [`${SUBAGENT_CHAT_ADDRESS}**`],
889
+ priority: "builtin",
890
+ canOpen: (address) => parseSubagentChatAddress(address) !== void 0,
891
+ title: (address) => {
892
+ const child = parseSubagentChatAddress(address)?.childSessionId;
893
+ return child === void 0 ? t("sidebar.chat") : ctx.sessions.list.getSnapshot().byId[child]?.projectionValues?.subagent?.label ?? child;
894
+ }
895
+ }), "ui-subagent: Sidebar chat type");
896
+ ctx.effect(() => ctx.slots.inject("sidebar.right.pane.tab", () => ctx.slots.register({
897
+ name: "sidebar.right.pane.tab",
898
+ key: SUBAGENT_CHAT_ID,
899
+ children: { "sidebar.chat.conversation": {
900
+ kind: "single",
901
+ scope: "session"
902
+ } }
903
+ }, SidebarChatTab)), "ui-subagent: Sidebar chat body");
904
+ ctx.effect(() => ctx.slots.inject("sidebar.chat.conversation", () => ctx.slots.register({ name: "sidebar.chat.conversation" }, ConversationSlotPanel)), "ui-subagent: Sidebar Conversation");
905
+ }
906
+ //#endregion
726
907
  //#region lib/types/client/locales.js
727
908
  /** `subagent` namespace dictionaries. */
728
909
  /** Dictionary namespace owned by this plugin. */
@@ -762,6 +943,8 @@ window.__ModuleLoader__.load({
762
943
  "count.running.other": "{count} 个子代理,正在运行",
763
944
  "switcher.aria": "切换子代理:{title}",
764
945
  "tree.aria": "子代理会话",
946
+ "open.sidebar": "在侧边栏打开 {label}",
947
+ "sidebar.chat": "聊天",
765
948
  "readonly.oneShot.title": "一次性子代理记录",
766
949
  "readonly.title": "此子代理暂时只读",
767
950
  "readonly.oneShot.body": "一次性任务不支持后续消息,可在这里查看完整执行记录。",
@@ -802,6 +985,8 @@ window.__ModuleLoader__.load({
802
985
  "count.running.other": "{count} subagents running",
803
986
  "switcher.aria": "Switch subagent: {title}",
804
987
  "tree.aria": "Subagent sessions",
988
+ "open.sidebar": "Open {label} in sidebar",
989
+ "sidebar.chat": "Chat",
805
990
  "readonly.oneShot.title": "One-shot subagent record",
806
991
  "readonly.title": "This subagent is read-only for now",
807
992
  "readonly.oneShot.body": "One-shot tasks do not accept follow-ups; review the full execution record here.",
@@ -809,11 +994,13 @@ window.__ModuleLoader__.load({
809
994
  };
810
995
  //#endregion
811
996
  //#region lib/types/client/index.js
812
- /** Required services for conversation slots and session navigation. */
997
+ /** Required services for subagent presentation and navigation. */
813
998
  const inject = [
814
999
  "sessions",
1000
+ "uiWorkspace",
815
1001
  "slots",
816
- "locale"
1002
+ "locale",
1003
+ "sidebarRight"
817
1004
  ];
818
1005
  /** Claim the composer for one-shot history or an unavailable continuation owner. */
819
1006
  function selectReadOnlySubagent(owner) {
@@ -832,10 +1019,19 @@ window.__ModuleLoader__.load({
832
1019
  zh,
833
1020
  en
834
1021
  }), "ui-subagent: dictionaries");
1022
+ ctx.inject(["resources", "sidebarRightTabs"], (scope) => {
1023
+ registerSidebarChat(scope, ctx.locale.bind(NS));
1024
+ });
835
1025
  const sessions = ctx.sessions;
836
1026
  const catalogActions = (_parentSessionId) => ({
837
1027
  openChild(address) {
838
- sessions.openSubagent(address);
1028
+ ctx.uiWorkspace.openSession(address);
1029
+ },
1030
+ openChildAside(address) {
1031
+ ctx.sidebarRight.openResource(subagentChatAddress(address), {
1032
+ kind: "subagentchat",
1033
+ preferNewPane: true
1034
+ });
839
1035
  },
840
1036
  refresh(parentSessionId) {
841
1037
  sessions.refreshSubagents(parentSessionId);
@@ -5,6 +5,7 @@ import { NS } from './locales.ts';
5
5
  /** Business actions supplied by the slot registration. */
6
6
  export interface SubagentCatalogInjected {
7
7
  openChild: (address: SubagentAddress) => void;
8
+ openChildAside: (address: SubagentAddress) => void;
8
9
  refresh: (parentSessionId: SessionId) => void;
9
10
  setCatalogOpen: (parentSessionId: SessionId, open: boolean) => void;
10
11
  }
@@ -15,5 +16,5 @@ export type SubagentHeaderLineageProps = PropsRuntime<'conversation.session.head
15
16
  * @param props - Breadcrumb title, session standard props, and catalog actions.
16
17
  * @returns An ordinary-title descendant count, or a title-and-chevron sibling switcher.
17
18
  */
18
- export declare function SubagentHeaderLineage({ lineageSessionId, displayTitle, openTitle, useSessions, openChild, refresh, setCatalogOpen, t, }: SubagentHeaderLineageProps): import("react").JSX.Element;
19
+ export declare function SubagentHeaderLineage({ lineageSessionId, displayTitle, openTitle, useSessions, openChild, openChildAside, refresh, setCatalogOpen, t, }: SubagentHeaderLineageProps): import("react").JSX.Element;
19
20
  //# sourceMappingURL=SubagentHeaderLineage.d.ts.map
@@ -9,7 +9,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
9
9
  }
10
10
  export type { SubagentCatalogInjected, SubagentHeaderLineageProps, } from './SubagentHeaderLineage.tsx';
11
11
  export type { SubagentReadOnlyComposerProps, SubagentReadOnlyMatch, } from './SubagentReadOnlyComposer.tsx';
12
- /** Required services for conversation slots and session navigation. */
12
+ /** Required services for subagent presentation and navigation. */
13
13
  export declare const inject: string[];
14
14
  /**
15
15
  * Client plugin body: register the subagent catalog and read-only composer seats.
@@ -36,6 +36,8 @@ export declare const zh: {
36
36
  readonly 'count.running.other': "{count} 个子代理,正在运行";
37
37
  readonly 'switcher.aria': "切换子代理:{title}";
38
38
  readonly 'tree.aria': "子代理会话";
39
+ readonly 'open.sidebar': "在侧边栏打开 {label}";
40
+ readonly 'sidebar.chat': "聊天";
39
41
  readonly 'readonly.oneShot.title': "一次性子代理记录";
40
42
  readonly 'readonly.title': "此子代理暂时只读";
41
43
  readonly 'readonly.oneShot.body': "一次性任务不支持后续消息,可在这里查看完整执行记录。";
@@ -0,0 +1,62 @@
1
+ /** Right-Sidebar presentation of an existing subagent Conversation. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ import type { SessionReference } from '@deepseek-ai/dsh-api-session-controller/client';
4
+ import type { ConversationViewsProps } from '@deepseek-ai/dsh-client-ui-conversation/client';
5
+ import type { PropsRenderFactories, PropsRenderSlots, PropsRuntime, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
6
+ import type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client';
7
+ import type { NS } from '../locales.ts';
8
+ /** Stable implementation identity for the Sidebar tab body. */
9
+ export declare const SUBAGENT_CHAT_ID = "@deepseek-ai/dsh-client-ui-subagent";
10
+ /** Resource-address prefix for an embedded Session chat. */
11
+ export declare const SUBAGENT_CHAT_ADDRESS = "dsh-resource://subagentchat/session/";
12
+ /** Value retained by one live chat resource occurrence. */
13
+ export interface SubagentChatResource {
14
+ readonly address: SubagentAddress;
15
+ readonly reference: SessionReference;
16
+ }
17
+ declare module '@deepseek-ai/dsh-api-session-controller/client' {
18
+ interface SessionReferenceSourceMap {
19
+ sidebarChat: unknown;
20
+ }
21
+ }
22
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
23
+ interface ResourceProtocolMap {
24
+ subagentchat: SubagentChatResource;
25
+ }
26
+ interface SlotMap {
27
+ /** Session-scoped Conversation occurrence hosted by one Sidebar chat tab. */
28
+ 'sidebar.chat.conversation': {
29
+ kind: 'single';
30
+ scope: 'session';
31
+ };
32
+ }
33
+ }
34
+ /**
35
+ * Address one subagent Session together with the routing facts needed to restore it.
36
+ * @param address - durable direct-parent subagent address.
37
+ * @returns canonical Sidebar resource address.
38
+ */
39
+ export declare function subagentChatAddress(address: SubagentAddress): string;
40
+ /**
41
+ * Parse one canonical Sidebar chat resource address.
42
+ * @param value - possible chat resource address.
43
+ * @returns the encoded direct-parent address, or undefined for another or malformed resource.
44
+ */
45
+ export declare function parseSubagentChatAddress(value: string): SubagentAddress | undefined;
46
+ /** Fixed Chat selection used by an embedded Conversation occurrence. */
47
+ export declare function FixedChatConversationView(props: ConversationViewsProps): import("react").JSX.Element;
48
+ /** Props supplied to the child-Session Conversation host. */
49
+ export type ConversationSlotPanelProps = PropsRuntime<'sidebar.chat.conversation'> & PropsRenderFactories;
50
+ /** Render the shared Conversation content for one explicitly provided child Session. */
51
+ export declare function ConversationSlotPanel({ sessionId, useSession, useConversation, useSessions, renderFactorySlot, }: ConversationSlotPanelProps): import("react").ReactNode;
52
+ /** Props supplied to the parent-Session Sidebar tab body. */
53
+ export type SidebarChatTabProps = PropsRuntime<'sidebar.right.pane.tab'> & PropsRenderSlots<'sidebar.chat.conversation'>;
54
+ /** Bind a chat resource's child reference around its Conversation slot. */
55
+ export declare function SidebarChatTab({ useResource, useTabInfo, SessionProvider, renderSlot }: SidebarChatTabProps): import("react").JSX.Element;
56
+ /**
57
+ * Register the chat resource owner and its right-Sidebar presentation.
58
+ * @param ctx - Client root carrying Sessions, resources, Slots, and Sidebar registries.
59
+ * @param t - Chat namespace translator used for fallback tab titles.
60
+ */
61
+ export declare function registerSidebarChat(ctx: Context, t: TranslateNS<typeof NS>): void;
62
+ //# sourceMappingURL=index.d.ts.map
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.1.6-alpha.1",
4
+ "version": "0.1.6-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,9 +30,13 @@
30
30
  "inject": [
31
31
  "@deepseek-ai/dsh-api-session-controller",
32
32
  "@deepseek-ai/dsh-client-locale",
33
+ "@deepseek-ai/dsh-client-resources",
34
+ "@deepseek-ai/dsh-client-ui-chat",
33
35
  "@deepseek-ai/dsh-client-ui-conversation",
34
36
  "@deepseek-ai/dsh-client-ui-primitives",
35
- "@deepseek-ai/dsh-client-ui-input-trigger"
37
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
38
+ "@deepseek-ai/dsh-client-ui-input-trigger",
39
+ "@deepseek-ai/dsh-client-ui-workspace"
36
40
  ],
37
41
  "platform": "web"
38
42
  }
@@ -46,20 +50,24 @@
46
50
  "@types/react-dom": "~18.3.0",
47
51
  "react": "^18.2.0",
48
52
  "react-dom": "^18.2.0",
49
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.6-alpha.1",
50
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.6-alpha.1",
51
- "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.1",
52
- "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.6-alpha.1",
53
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.1",
54
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
55
- "@deepseek-ai/dsh-subagent": "^0.1.6-alpha.1",
56
- "@deepseek-ai/dsh-token-meter": "^0.1.6-alpha.1",
53
+ "@deepseek-ai/dsh-client-resources": "^0.1.6-alpha.2",
54
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.6-alpha.2",
55
+ "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.2",
56
+ "@deepseek-ai/dsh-client-ui-chat": "^0.1.6-alpha.2",
57
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.6-alpha.2",
58
+ "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.6-alpha.2",
59
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.2",
60
+ "@deepseek-ai/dsh-subagent": "^0.1.6-alpha.2",
61
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.2",
62
+ "@deepseek-ai/dsh-token-meter": "^0.1.6-alpha.2",
57
63
  "@deepseek-ai/cordis": "^4.0.2",
58
- "@deepseek-ai/dsh-api-session-controller": "^0.1.6-alpha.1",
59
- "@deepseek-ai/dsh-client-connection": "^0.1.6-alpha.1",
60
- "@deepseek-ai/dsh-session": "^0.1.6-alpha.1",
61
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.1",
62
- "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.1"
64
+ "@deepseek-ai/dsh-client-connection": "^0.1.6-alpha.2",
65
+ "@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
66
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.2",
67
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.6-alpha.2",
68
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.2",
69
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.6-alpha.2",
70
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.6-alpha.2"
63
71
  },
64
72
  "files": [
65
73
  "lib/index.js",