@deepseek-ai/dsh-client-ui-sidebar 0.1.1-rc.2 → 0.1.2-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-sidebar/README.md
5
- README.md: b924c2e6d18217d9689b7c21137321856e14da2e
6
- README.zh.md: 214a2727243d6d9151e31cfcfbc0bdb886c2fcdf
5
+ README.md: 64f75a46a7e372fcf96cdd0594ef694ee2c59bce
6
+ README.zh.md: 16708765480bdb5c4190a67e85bc7f5aad48fad0
package/README.md CHANGED
@@ -1,26 +1,79 @@
1
+ ---
2
+ description: "Sidebar shell plugin for the dsh web client: brand row, New Session action, collapse control, scroll-aware region seat, and bottom-pinned Settings seat."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-sidebar
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Sidebar shell plugin: the brand row, New Session action, layout-owned collapse control, scroll-aware region seat, and bottom-pinned Settings seat. [ui-workspace](../ui-workspace/README.md) owns the Workspace and Session browser rendered into `sidebar.workspaces`; this package neither derives its rows nor owns its view preferences. Collapse into the layout-owned 56px rail remains presentation-local. Contract: the [slot system standard](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md).
10
+ ## Summary
11
+
12
+ `dsh-client-ui-sidebar` is the sidebar shell of the dsh web client: users see the brand row, start new sessions, collapse into the layout-owned 56px rail, and reach Settings from the bottom-pinned seat, while the scroll-aware region seat hosts the Workspace and Session browser. The Workspace and Session browser rendered into `sidebar.workspaces` belongs to ui-workspace; this package neither derives its rows nor owns its view preferences. A deployment package can replace the brand mark or name without replacing the New Session control or the rail geometry, and New Session starts the runtime's page-local frontend Session Intent against the explicit, current, or most recently active Workspace. Collapse into the layout-owned 56px rail remains presentation-local.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ The sidebar is the navigation shell: users see the brand, start new sessions, collapse the rail, and reach Settings. Feature plugins fill its seats — ui-workspace fills `sidebar.workspaces`, ui-settings registers the trigger row and settings panel at `sidebar.settings`.
29
+
30
+ ### Brand and New Session
31
+
32
+ The expanded brand row renders `sidebar.brand.mark` and `sidebar.brand.name` as independent single slots; the collapsed rail renders the same mark slot. Without occupants, the shell uses the fish mark and a localized local-build label. A complete build stacks a code badge below the label as `version[-commit][-dirty]`, using `DSH_CLIENT_VERSION`, the optional 7-character `DSH_CLIENT_COMMIT_HASH`, and `DSH_CLIENT_GIT_DIRTY=true`; missing version metadata omits the badge. New Session targets the explicit Workspace used by a scoped action, otherwise the current Session's Workspace, otherwise the most recently active Workspace; when none exists it clears into the blank New Session page.
33
+
34
+ ### Collapse behavior
35
+
36
+ During a live collapse, the expanded content fades out at its current width, the upper controls share one fade and leftward translation into the 56px rail, and the layout's column slide ends the motion. A page that starts collapsed renders the rail statically, and reduced-motion mode disables both transitions. The bottom-pinned `sidebar.settings` control shares the fade timing but has no horizontal translation.
37
+
38
+ ### Scrollbars
39
+
40
+ Scrollbars in the column are a pointer affordance: the shell rebinds the scrollbar indirection to `transparent` whenever the pointer is outside the column and keeps the thumb drawn for 2s after the pointer leaves, so a list nobody is pointing at carries no bar. The reservation that keeps rows from moving belongs to the scrolling region (ui-workspace), so revealing a thumb never reflows.
6
41
 
7
- The expanded brand row renders `sidebar.brand.mark` and `sidebar.brand.name` as independent single slots, while the collapsed rail renders the same mark slot. Without occupants, the shell uses the fish mark and a `DSH Local Build` label carrying the build's 7-character `DSH_CLIENT_COMMIT_HASH` badge. A deployment package can replace either value without replacing the New Session control or rail geometry; declaration-aware `slots.inject()` lets such a package activate before or after the sidebar.
42
+ -----
8
43
 
9
- New Session starts the runtime's page-local frontend Session Intent. The runtime targets the explicit Workspace used by a scoped action, otherwise the current Session's Workspace, otherwise the most recently active Workspace; when none exists it clears into the blank New Session page. Workspace-specific controls and the shared picker belong to ui-workspace.
44
+ <a id="understand-the-implementation"></a>
45
+ ## Understand the implementation
10
46
 
11
- `SidebarRootComponentProps` composes the layout owner share, the global `useSessions` and `useWorkspaces` hooks, the declared brand, `sidebar.workspaces`, and `sidebar.settings` child slots, and injected `startSession` plus sidebar-toggle callbacks. There is no plugin store.
47
+ <details>
48
+ <summary>Implementation internals — click to expand</summary>
12
49
 
13
- During a live collapse, the shell holds the expanded content at its current width while it fades out for 150ms. The four upper controls—the shell toggle and New Session plus add and search rendered through `sidebar.workspaces`—then share one 150ms fade and 49px leftward translation into the 56px rail, ending with the layout's 300ms column slide; every 36px control box follows the same path to the rail's 10px left inset. The bottom-pinned `sidebar.settings` control shares the fade timing but has no horizontal translation. A page that starts collapsed renders the rail statically, and reduced-motion mode disables both transitions.
50
+ The shell is pure composition: `SidebarRootComponentProps` composes the layout owner share, the global `useSessions` and `useWorkspaces` hooks, the declared brand, the `sidebar.workspaces` and `sidebar.settings` child slots, and injected `startSession` plus sidebar-toggle callbacks. There is no plugin store.
14
51
 
15
- Scrollbars in the column are a pointer affordance: the shell rebinds ui-theme's [scrollbar indirection](../ui-theme/README.md) to `transparent` whenever the pointer is outside it, and keeps the thumb drawn for 2s after the pointer leaves, so a list nobody is pointing at carries no bar. The reservation that keeps rows from moving belongs to the scrolling region ([ui-workspace](../ui-workspace/README.md)), so revealing a thumb never reflows.
52
+ ### Slot discipline
16
53
 
17
- The foot is the `sidebar.settings` seat: the sidebar renders only the bottom-pinned layout slot and shares its column state (`wide`); ui-settings registers the trigger row and settings panel there.
54
+ Declaration-aware `slots.inject()` lets a replacing package activate before or after the sidebar. The foot is the `sidebar.settings` seat: the sidebar renders only the bottom-pinned layout slot and shares its column state (`wide`). The `/client` exports are the plugin body (`apply`/`inject`) plus the contract types only; SidebarRoot, the row components, and the tree derivation remain package-internal behind the slot registration.
18
55
 
19
- The `/client` exports are the plugin body (`apply`/`inject`) plus the contract types only; SidebarRoot, the row components, and the tree derivation remain package-internal behind the slot registration.
56
+ </details>
20
57
 
58
+ -----
59
+
60
+ <a id="further-exploration"></a>
61
+ ## Further Exploration
62
+
63
+ These pages cover the surfaces that fill the shell's seats and the composition model.
64
+
65
+ - [ui-workspace](../ui-workspace/README.md) — the Workspace and Session browser rendered into `sidebar.workspaces`.
66
+ - [ui-settings](../ui-settings/README.md) — the settings domain base registering the trigger row at `sidebar.settings`.
67
+ - [ui-layout](../ui-layout/README.md) — the layout owner whose rail and column state the collapse uses.
68
+ - [ui-theme](../ui-theme/README.md) — the scrollbar token indirection the shell rebinds.
69
+ - [Slot system standard](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md) — the composition model behind the seats.
70
+
71
+ -----
72
+
73
+ <a id="model-experience"></a>
21
74
  ## Model Experience
22
75
 
23
- None, as the sidebar renders the browser session list; nothing here reaches a model request.
76
+ None, as the package is a browser-side UI plugin layer that registers nothing model-facing.
24
77
 
25
78
  #### KV Cache effect
26
79
 
@@ -28,6 +81,21 @@ None; this package neither assembles nor sends a provider request.
28
81
 
29
82
  ## Known Limitations and Deferred Work
30
83
 
31
- - **Session state-dot rendering is owned by [ui-workspace](../ui-workspace/README.md)** — no done/error notification sources are available.
32
- - **Workspace browser behavior is composition-owned** — grouping, ordering, search, and row state belong to [ui-workspace](../ui-workspace/README.md), not this shell.
84
+ <a id="known-limitations-and-deferred-work"></a>
85
+
86
+
87
+ These limits define what the shell owns versus what its occupants own; they are current package constraints.
88
+
89
+ - **Session state-dot rendering is owned by ui-workspace** — no done/error notification sources are available to this shell.
90
+ - **Workspace browser behavior is composition-owned** — grouping, ordering, search, and row state belong to ui-workspace, not this shell.
33
91
  - **"New task completed" unread marking is local viewing state** — completion-time > last-seen never reaches the host.
92
+
93
+ <a id="dev-note"></a>
94
+ ### Dev Note
95
+
96
+ <details>
97
+ <summary>Working context for maintainers — click to expand</summary>
98
+
99
+ None.
100
+
101
+ </details>
package/README.zh.md CHANGED
@@ -1,33 +1,101 @@
1
+ ---
2
+ description: "dsh Web 客户端的侧边栏外壳插件:品牌行、New Session 操作、折叠控件、可感知滚动的区域席位与底部固定的 Settings 席位。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-sidebar
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 侧边栏外壳插件:负责品牌行、New Session 操作、布局持有的折叠控件、可感知滚动的区域 seat,以及固定在底部的 Settings seat。[ui-workspace](../ui-workspace/README.zh.md) 持有渲染到 `sidebar.workspaces` 的 Workspace 与 Session 浏览器;本包既不派生其中的行,也不持有其视图偏好。折叠到布局拥有的 56px 轨道仍属于本地呈现行为。约定:[slot 系统标准](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.zh.md)。
10
+ ## 概述
11
+
12
+ `dsh-client-ui-sidebar` 是 dsh Web 客户端的侧边栏外壳:用户看到品牌行、启动新会话、折叠进布局拥有的 56px 轨道,并从底部固定的席位进入 Settings;可感知滚动的区域席位承载 Workspace 与 Session 浏览器。渲染到 `sidebar.workspaces` 的 Workspace 与 Session 浏览器归 ui-workspace 所有;本包既不派生其中的行,也不持有其视图偏好。部署包可以单独替换品牌标记或名称,而无须替换 New Session 控件或轨道几何;New Session 会针对显式指定、当前或最近活跃的 Workspace 启动运行时的页面局部前端 Session Intent。折叠到布局拥有的 56px 轨道仍属于本地呈现行为。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 侧边栏是导航外壳:用户看到品牌、启动新会话、折叠轨道并到达 Settings。功能插件填充它的席位——ui-workspace 填充 `sidebar.workspaces`,ui-settings 在 `sidebar.settings` 注册触发行与设置面板。
29
+
30
+ ### 品牌与 New Session
31
+
32
+ 展开的品牌行把 `sidebar.brand.mark` 与 `sidebar.brand.name` 渲染为两个独立的 single slot;收起轨道则渲染同一个 mark slot。没有占位者时,外壳使用鱼形标记和本地化的本地构建标签。完整构建会在标签下方显示代码徽标;该徽标使用 `DSH_CLIENT_VERSION`、可选的 7 位 `DSH_CLIENT_COMMIT_HASH` 与 `DSH_CLIENT_GIT_DIRTY=true` 组装成 `version[-commit][-dirty]`;缺少版本元数据时不显示徽标。New Session 优先使用作用域操作明确指定的 Workspace,否则使用当前 Session 所属 Workspace,再否则使用最近活跃 Workspace;一个 Workspace 都没有时则清空选择,进入空白 New Session 页面。
33
+
34
+ ### 折叠行为
35
+
36
+ 实时收起时,展开内容在当前宽度淡出,上方控件共用一次淡入并左移进入 56px 轨道,由布局的栏滑动结束整段动画。页面初始即为收起状态时会静态渲染轨道;减少动态效果模式会禁用两段过渡。固定在底部的 `sidebar.settings` 控件只共用淡入时序,不发生横向位移。
37
+
38
+ ### 滚动条
39
+
40
+ 栏内的滚动条是一种指针可供性:只要指针不在栏内,外壳就把滚动条间接层重新绑定为 `transparent`;指针离开后滑块再保留 2 秒,因此没人指向的列表不会带着滚动条。避免行位移的空间预留属于滚动区域本身(ui-workspace),所以显示滑块不会引起重排。
6
41
 
7
- 展开的品牌行把 `sidebar.brand.mark` 与 `sidebar.brand.name` 渲染为两个独立的 single slot,收起轨道则渲染同一个 mark slot。没有占位者时,外壳使用鱼形标记,以及带有构建期 7 位 `DSH_CLIENT_COMMIT_HASH` 徽标的 `DSH Local Build` 标签。部署包可以单独替换任一值,而无须替换 New Session 控件或轨道几何;声明感知的 `slots.inject()` 让这种包无论先于还是后于侧边栏激活都能生效。
42
+ -----
8
43
 
9
- New Session 会启动运行时的页面局部前端 Session Intent。运行时优先使用作用域操作明确指定的 Workspace,否则使用当前 Session 所属 Workspace,再否则使用最近活跃 Workspace;一个 Workspace 都没有时则清空选择,进入空白 New Session 页面。Workspace 专属控件与共享选择器由 ui-workspace 持有。
44
+ <a id="understand-the-implementation"></a>
45
+ ## 理解实现
10
46
 
11
- `SidebarRootComponentProps` 组合布局 owner share、全局 `useSessions` 和 `useWorkspaces` 钩子、已声明的品牌、`sidebar.workspaces` 与 `sidebar.settings` 子 slot,以及注入的 `startSession` 与侧边栏切换回调。这里没有插件 store。
47
+ <details>
48
+ <summary>实现细节——点击展开</summary>
12
49
 
13
- 实时收起时,外壳会把展开内容固定在当前宽度,并用 150ms 将其淡出。随后,上方四个控件——外壳的侧栏切换与新建会话,以及通过 `sidebar.workspaces` 渲染的添加和搜索——共用一次 150ms 的淡入和 49px 左移,在布局的 300ms 栏滑动结束时一起进入 56px 轨道;每个 36px 控件盒都会沿同一条路径到达轨道左侧 10px 的内边距。固定在底部的 `sidebar.settings` 控件只共用淡入时序,不发生横向位移。页面初始即为收起状态时会静态渲染轨道;减少动态效果模式会禁用两段过渡。
50
+ 外壳是纯组合:`SidebarRootComponentProps` 组合布局 owner share、全局 `useSessions` 与 `useWorkspaces` 钩子、已声明的品牌、`sidebar.workspaces` `sidebar.settings` 子 slot,以及注入的 `startSession` 与侧边栏切换回调。这里没有插件 store。
14
51
 
15
- 栏内的滚动条是一种指针可供性:只要指针不在栏内,外壳就把 ui-theme 的[滚动条间接层](../ui-theme/README.zh.md)重新绑定为 `transparent`;指针离开后滑块再保留 2 秒,因此没人指向的列表不会带着滚动条。避免行位移的空间预留属于滚动区域本身([ui-workspace](../ui-workspace/README.zh.md)),所以显示滑块不会引起重排。
52
+ ### Slot 纪律
16
53
 
17
- 页脚承载 `sidebar.settings`:侧边栏只渲染固定在底部的布局 slot,并共享其栏状态(`wide`);ui-settings 在此注册触发行和设置面板。
54
+ 声明感知的 `slots.inject()` 让替换包无论先于还是后于侧边栏激活都能生效。页脚承载 `sidebar.settings` 席位:侧边栏只渲染固定在底部的布局 slot,并共享其栏状态(`wide`)。`/client` 导出接口只包含插件主体(`apply`/`inject`)及约定类型;SidebarRoot、行组件与树派生仍由 slot 注册封装在包内。
18
55
 
19
- `/client` 导出表层只包含插件主体(`apply`/`inject`)及约定类型;SidebarRoot、行组件和树派生仍由 slot 注册封装在包内。
56
+ </details>
20
57
 
58
+ -----
59
+
60
+ <a id="further-exploration"></a>
61
+ ## 进一步探索
62
+
63
+ 以下页面覆盖填充外壳席位的各个界面与组合模型。
64
+
65
+ - [ui-workspace](../ui-workspace/README.zh.md)——渲染到 `sidebar.workspaces` 的 Workspace 与 Session 浏览器。
66
+ - [ui-settings](../ui-settings/README.zh.md)——在 `sidebar.settings` 注册触发行与设置面板的设置领域底座。
67
+ - [ui-layout](../ui-layout/README.zh.md)——折叠所使用轨道与栏状态的布局 owner。
68
+ - [ui-theme](../ui-theme/README.zh.md)——外壳所重新绑定的滚动条 token 间接层。
69
+ - [slot 系统标准](../../../.agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.zh.md)——席位背后的组合模型。
70
+
71
+ -----
72
+
73
+ <a id="model-experience"></a>
21
74
  ## 模型体验
22
75
 
23
- 无。侧边栏渲染浏览器会话列表;这里没有任何内容进入模型请求。
76
+ 无。该包是浏览器端 UI 插件层,不注册任何面向模型的内容。
24
77
 
25
78
  #### KV Cache 影响
26
79
 
27
- 无;该包(package)既不组装也不发送提供方请求。
80
+ 无;该包既不组装也不发送提供方请求。
81
+
82
+ ## 已知限制与延期工作
28
83
 
29
- ## 已知限制与暂缓事项
84
+ <a id="known-limitations-and-deferred-work"></a>
30
85
 
31
- - **Session 状态点渲染由 [ui-workspace](../ui-workspace/README.zh.md) 持有**:没有可用的 done/error 通知数据源。
32
- - **Workspace 浏览行为由组合持有**:分组、排序、搜索与行状态都属于 [ui-workspace](../ui-workspace/README.zh.md),不属于此外壳。
86
+
87
+ 这些限制定义外壳拥有什么、其占位方拥有什么;它们是当前包约束。
88
+
89
+ - **Session 状态点渲染由 ui-workspace 持有**:本外壳没有可用的 done/error 通知数据源。
90
+ - **Workspace 浏览行为由组合持有**:分组、排序、搜索与行状态都属于 ui-workspace,不属于此外壳。
33
91
  - **「New task completed」未读标记是本地查看状态**:完成时间 > 上次查看时间这一事实永远不会到达宿主。
92
+
93
+ <a id="dev-note"></a>
94
+ ### 开发备注
95
+
96
+ <details>
97
+ <summary>维护者的工作上下文——点击展开</summary>
98
+
99
+ 无。
100
+
101
+ </details>
package/lib/client.js CHANGED
@@ -23,7 +23,7 @@ window.__ModuleLoader__.load({
23
23
  }
24
24
  //#endregion
25
25
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-sidebar/src/client/SidebarRoot.module.css.mjs
26
- const css = ".hHd-Xa_root{--dsh-sidebar-inline-padding:12px;height:100%;padding:6px var(--dsh-sidebar-inline-padding);box-sizing:border-box;background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex-direction:column;font-size:14px;display:flex}.hHd-Xa_root.hHd-Xa_collapsed{padding:18px 10px 6px}.hHd-Xa_root.hHd-Xa_quietBars{--dsh-scrollbar-thumb:transparent;--dsh-scrollbar-thumb-hover:transparent}.hHd-Xa_fading>*{opacity:0;transition:opacity .15s var(--ds-ease-in-out)}.hHd-Xa_wide{animation:hHd-Xa_wide-in .2s var(--ds-ease-in-out)}@keyframes hHd-Xa_wide-in{0%{opacity:0}}.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_regionArea{animation:hHd-Xa_rail-in .15s var(--ds-ease-in-out) backwards}.hHd-Xa_railIn .hHd-Xa_footArea{animation:hHd-Xa_rail-fade-in .15s var(--ds-ease-in-out) backwards}@keyframes hHd-Xa_rail-in{0%{opacity:0;transform:translate(49px)}}@keyframes hHd-Xa_rail-fade-in{0%{opacity:0}}.hHd-Xa_logoRow{box-sizing:border-box;flex:none;justify-content:flex-end;align-items:center;gap:8px;height:60px;margin-bottom:8px;padding:8px 0 8px 4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_logoRow{justify-content:flex-start;height:36px;margin-bottom:12px;padding:0}.hHd-Xa_brand{min-width:0;color:inherit;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;padding:0;display:inline-flex;overflow:hidden}.hHd-Xa_brandIdentity{align-items:center;gap:8px;min-width:0;height:24px;display:inline-flex}.hHd-Xa_brandMark{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_brandName{letter-spacing:.04em;align-items:center;gap:6px;min-width:0;height:24px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.hHd-Xa_fallbackBrandName{letter-spacing:0;white-space:nowrap;font-size:17px}.hHd-Xa_iconButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.hHd-Xa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_collapsed .hHd-Xa_iconButton{width:36px;height:36px}.hHd-Xa_collapsed .hHd-Xa_toggle .hHd-Xa_panelIcon{display:none}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_panelIcon{display:inline}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_railMark{display:none}.hHd-Xa_railMark{justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_collapsed .hHd-Xa_iconButton{color:var(--dsw-alias-label-primary)}.hHd-Xa_buildRevision{height:16px;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code);border-radius:3px;align-items:center;padding:0 4px;font-size:8px;font-weight:500;line-height:16px;display:inline-flex}.hHd-Xa_newSession{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);height:38px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:12px;flex:none;justify-content:center;align-items:center;gap:6px;margin:0 2px 8px;padding:8px 16px;font-size:14px;font-weight:500;line-height:22px;display:flex;overflow:hidden}.hHd-Xa_newSession:hover{background:var(--dsw-alias-button-floating-hover)}.hHd-Xa_collapsed .hHd-Xa_newSession{background:0 0;border-color:#0000;align-self:flex-start;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.hHd-Xa_collapsed .hHd-Xa_newSession:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_newSessionLabel{white-space:nowrap;max-width:200px;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_newSessionLabel{max-width:0}.hHd-Xa_regionArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-sidebar-inline-padding));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_regionArea{margin-left:0;margin-right:0;padding-left:0}.hHd-Xa_footArea{flex-direction:column;flex:none;display:flex}.hHd-Xa_settingsArea,.hHd-Xa_footerActions{flex:none;width:100%;min-width:0}.hHd-Xa_footerActions{display:flex}.hHd-Xa_collapsed .hHd-Xa_footArea{align-items:center}.hHd-Xa_collapsed .hHd-Xa_settingsArea,.hHd-Xa_collapsed .hHd-Xa_footerActions{justify-content:center;width:auto;display:flex}@media (prefers-reduced-motion:reduce){.hHd-Xa_wide,.hHd-Xa_fading>*,.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_footArea,.hHd-Xa_railIn .hHd-Xa_regionArea{transition:none;animation:none}}";
26
+ const css = ".hHd-Xa_root{--dsh-sidebar-inline-padding:12px;height:100%;padding:6px var(--dsh-sidebar-inline-padding);box-sizing:border-box;background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex-direction:column;font-size:14px;display:flex}.hHd-Xa_root.hHd-Xa_collapsed{padding:18px 10px 6px}.hHd-Xa_root.hHd-Xa_quietBars{--dsh-scrollbar-thumb:transparent;--dsh-scrollbar-thumb-hover:transparent}.hHd-Xa_fading>*{opacity:0;transition:opacity .15s var(--ds-ease-in-out)}.hHd-Xa_wide{animation:hHd-Xa_wide-in .2s var(--ds-ease-in-out)}@keyframes hHd-Xa_wide-in{0%{opacity:0}}.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_regionArea{animation:hHd-Xa_rail-in .15s var(--ds-ease-in-out) backwards}.hHd-Xa_railIn .hHd-Xa_footArea{animation:hHd-Xa_rail-fade-in .15s var(--ds-ease-in-out) backwards}@keyframes hHd-Xa_rail-in{0%{opacity:0;transform:translate(49px)}}@keyframes hHd-Xa_rail-fade-in{0%{opacity:0}}.hHd-Xa_logoRow{box-sizing:border-box;flex:none;justify-content:flex-end;align-items:center;gap:8px;height:60px;margin-bottom:8px;padding:8px 0 8px 4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_logoRow{justify-content:flex-start;height:36px;margin-bottom:12px;padding:0}.hHd-Xa_brand{min-width:0;color:inherit;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;padding:0;display:inline-flex;overflow:hidden}.hHd-Xa_brandIdentity{align-items:center;gap:8px;min-width:0;height:24px;display:inline-flex}.hHd-Xa_brandMark{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_brandName{letter-spacing:.04em;align-items:center;gap:6px;min-width:0;height:24px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.hHd-Xa_fallbackBrandName{letter-spacing:0;white-space:nowrap;font-size:17px}.hHd-Xa_localBuildBrand{white-space:nowrap;flex-direction:column;flex:none;justify-content:center;align-items:flex-start;gap:1px;height:24px;display:inline-flex}.hHd-Xa_localBuildTitle{letter-spacing:0;font-size:12px;line-height:13px}.hHd-Xa_iconButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.hHd-Xa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_collapsed .hHd-Xa_iconButton{width:36px;height:36px}.hHd-Xa_collapsed .hHd-Xa_toggle .hHd-Xa_panelIcon{display:none}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_panelIcon{display:inline}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_railMark{display:none}.hHd-Xa_railMark{justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_collapsed .hHd-Xa_iconButton{color:var(--dsw-alias-label-primary)}.hHd-Xa_buildVersion{height:10px;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code);white-space:nowrap;border-radius:2px;flex:none;align-items:center;padding:0 3px;font-size:6px;font-weight:500;line-height:10px;display:inline-flex}.hHd-Xa_newSession{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);height:38px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:12px;flex:none;justify-content:center;align-items:center;gap:6px;margin:0 2px 8px;padding:8px 16px;font-size:14px;font-weight:500;line-height:22px;display:flex;overflow:hidden}.hHd-Xa_newSession:hover{background:var(--dsw-alias-button-floating-hover)}.hHd-Xa_collapsed .hHd-Xa_newSession{background:0 0;border-color:#0000;align-self:flex-start;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.hHd-Xa_collapsed .hHd-Xa_newSession:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_newSessionLabel{white-space:nowrap;max-width:200px;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_newSessionLabel{max-width:0}.hHd-Xa_regionArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-sidebar-inline-padding));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_regionArea{margin-left:0;margin-right:0;padding-left:0}.hHd-Xa_footArea{flex-direction:column;flex:none;display:flex}.hHd-Xa_settingsArea,.hHd-Xa_footerActions{flex:none;width:100%;min-width:0}.hHd-Xa_footerActions{display:flex}.hHd-Xa_collapsed .hHd-Xa_footArea{align-items:center}.hHd-Xa_collapsed .hHd-Xa_settingsArea,.hHd-Xa_collapsed .hHd-Xa_footerActions{justify-content:center;width:auto;display:flex}@media (prefers-reduced-motion:reduce){.hHd-Xa_wide,.hHd-Xa_fading>*,.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_footArea,.hHd-Xa_railIn .hHd-Xa_regionArea{transition:none;animation:none}}";
27
27
  const tagId = "@deepseek-ai/dsh-client-ui-sidebar/SidebarRoot.module.css";
28
28
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
29
29
  const tag = document.createElement("style");
@@ -37,13 +37,15 @@ window.__ModuleLoader__.load({
37
37
  "brandIdentity": "hHd-Xa_brandIdentity",
38
38
  "brandMark": "hHd-Xa_brandMark",
39
39
  "brandName": "hHd-Xa_brandName",
40
- "buildRevision": "hHd-Xa_buildRevision",
40
+ "buildVersion": "hHd-Xa_buildVersion",
41
41
  "collapsed": "hHd-Xa_collapsed",
42
42
  "fading": "hHd-Xa_fading",
43
43
  "fallbackBrandName": "hHd-Xa_fallbackBrandName",
44
44
  "footArea": "hHd-Xa_footArea",
45
45
  "footerActions": "hHd-Xa_footerActions",
46
46
  "iconButton": "hHd-Xa_iconButton",
47
+ "localBuildBrand": "hHd-Xa_localBuildBrand",
48
+ "localBuildTitle": "hHd-Xa_localBuildTitle",
47
49
  "logoRow": "hHd-Xa_logoRow",
48
50
  "newSession": "hHd-Xa_newSession",
49
51
  "newSessionLabel": "hHd-Xa_newSessionLabel",
@@ -88,6 +90,10 @@ window.__ModuleLoader__.load({
88
90
  * edge — on the way to the conversation, or around a portalled menu.
89
91
  */
90
92
  const SCROLLBAR_LINGER_MS = 2e3;
93
+ /** Format complete-build metadata for the local brand badge. */
94
+ function localBuildVersion() {
95
+ return `0.1.2-alpha.2-76ae850` + ({}.DSH_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "");
96
+ }
91
97
  /**
92
98
  * Render the sidebar column shell.
93
99
  * @param props - composed slot props (runtime share + injected callbacks, contract/slots.ts).
@@ -141,6 +147,7 @@ window.__ModuleLoader__.load({
141
147
  cancelLinger();
142
148
  };
143
149
  }, [pointerInside]);
150
+ const buildVersion = localBuildVersion();
144
151
  return (0, react_jsx_runtime.jsxs)("div", {
145
152
  ref: column,
146
153
  className: clsx(SidebarRoot_module_css_default.root, !wide && SidebarRoot_module_css_default.collapsed, !wide && everWide.current && SidebarRoot_module_css_default.railIn, collapsed && wide && SidebarRoot_module_css_default.fading, !pointerInside && SidebarRoot_module_css_default.quietBars),
@@ -170,13 +177,19 @@ window.__ModuleLoader__.load({
170
177
  children: renderSlot("sidebar.brand.mark", { size: 24 }, { fallback: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, { size: 24 }) })
171
178
  }), (0, react_jsx_runtime.jsx)("span", {
172
179
  className: SidebarRoot_module_css_default.brandName,
173
- children: renderSlot("sidebar.brand.name", {}, { fallback: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
180
+ children: renderSlot("sidebar.brand.name", {}, { fallback: buildVersion === void 0 ? (0, react_jsx_runtime.jsx)("span", {
174
181
  className: SidebarRoot_module_css_default.fallbackBrandName,
175
- children: "DSH Local Build"
176
- }), (0, react_jsx_runtime.jsx)("span", {
177
- className: SidebarRoot_module_css_default.buildRevision,
178
- children: "29b22c5"
179
- })] }) })
182
+ children: t("brand.localBuild")
183
+ }) : (0, react_jsx_runtime.jsxs)("span", {
184
+ className: SidebarRoot_module_css_default.localBuildBrand,
185
+ children: [(0, react_jsx_runtime.jsx)("span", {
186
+ className: SidebarRoot_module_css_default.localBuildTitle,
187
+ children: t("brand.localBuild")
188
+ }), (0, react_jsx_runtime.jsx)("span", {
189
+ className: SidebarRoot_module_css_default.buildVersion,
190
+ children: buildVersion
191
+ })]
192
+ }) })
180
193
  })]
181
194
  })
182
195
  }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
@@ -264,21 +277,21 @@ window.__ModuleLoader__.load({
264
277
  const inject = [
265
278
  "slots",
266
279
  "layout",
267
- "sessions",
268
- "workspaces",
280
+ "uiWorkspace",
269
281
  "locale"
270
282
  ];
271
283
  /** Registers the sidebar shell and its service callbacks.
272
284
  * @param ctx - Client root context.
273
285
  */
274
286
  function apply(ctx) {
287
+ const workspaceNavigation = ctx.get("uiWorkspace");
275
288
  ctx.effect(() => ctx.locale.register(NS, {
276
289
  zh,
277
290
  en
278
291
  }), "ui-sidebar: dictionaries");
279
292
  const injectProps = () => ({
280
293
  startSession: (workspaceId) => {
281
- ctx.workspaces.startSession(workspaceId);
294
+ workspaceNavigation.startSession(workspaceId);
282
295
  },
283
296
  toggleSidebar: () => {
284
297
  ctx.layout.toggleSidebar();
@@ -8,7 +8,7 @@
8
8
  * actions in `sidebar.footer.action`.
9
9
  */
10
10
  import type { PropsLocale, PropsRenderSlots, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
11
- import type { WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client';
11
+ import type { WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/client';
12
12
  declare module '@deepseek-ai/dsh-client-ui-slots' {
13
13
  interface SlotMap {
14
14
  /**
@@ -1,5 +1,5 @@
1
1
  /** Registers the sidebar shell into the layout-owned slot. */
2
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
2
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
3
3
  import { type SidebarKey } from './locales.ts';
4
4
  export type { SidebarBrandMarkOwnerProps, SidebarBrandNameOwnerProps, SidebarFooterActionOwnerProps, SidebarRootComponentProps, SidebarRootInjected, SidebarSectionOwnerProps, SidebarSettingsOwnerProps, } from './contract/slots.ts';
5
5
  export type { SidebarKey } from './locales.ts';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-sidebar",
3
3
  "description": "Sidebar plugin: session multi-level tree, search, grouping, state dots",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,8 +32,11 @@
32
32
  "dsh": {
33
33
  "client": {
34
34
  "inject": [
35
- "@deepseek-ai/dsh-client-runtime",
35
+ "@deepseek-ai/dsh-api-workspace-controller",
36
+ "@deepseek-ai/dsh-client-ui-renderer",
36
37
  "@deepseek-ai/dsh-client-ui-layout",
38
+ "@deepseek-ai/dsh-client-ui-session",
39
+ "@deepseek-ai/dsh-client-ui-workspace",
37
40
  "@deepseek-ai/dsh-client-locale"
38
41
  ],
39
42
  "platform": "web"
@@ -44,23 +47,22 @@
44
47
  "clsx": "^2.0.0"
45
48
  },
46
49
  "peerDependencies": {
47
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
48
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
50
- "@deepseek-ai/cordis": "^4.0.1",
51
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2"
50
+ "@deepseek-ai/cordis": "^4.0.2"
52
51
  },
53
52
  "devDependencies": {
54
53
  "@types/react": "~18.3.1",
55
54
  "react": "^18.2.0",
56
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
57
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
58
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.1-rc.2",
59
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2",
60
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
61
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
62
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
63
- "@deepseek-ai/cordis": "^4.0.1"
55
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.1.2-alpha.2",
56
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.2",
57
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.2-alpha.2",
58
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.2-alpha.2",
59
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
60
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
61
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
62
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.2-alpha.2",
63
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.2-alpha.2",
64
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
65
+ "@deepseek-ai/cordis": "^4.0.2"
64
66
  },
65
67
  "files": [
66
68
  "lib/index.js",