@deepseek-ai/dsh-client-ui-workspace 0.1.7-alpha.2 → 0.1.7-rc.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/lib/client.js CHANGED
@@ -20,228 +20,188 @@ window.__ModuleLoader__.load({
20
20
  */
21
21
  const menuOpenStateFactory = (_standard, state) => () => state;
22
22
  //#endregion
23
- //#region lib/types/client/locales.js
23
+ //#region lib/types/client/shortcuts.js
24
24
  /**
25
- * `workspace` namespace dictionaries: the browsing region (section header,
26
- * search, tree rows, dialogs) and the pick/add flow. Runtime failure
27
- * messages (wire error strings) pass through untranslated by policy.
25
+ * Create the private browser request source shared by commands and controls.
26
+ * @returns observable state and its complete mutation callbacks.
28
27
  */
29
- /** Simplified Chinese dictionary (the key-set source of truth). */
30
- const zh = {
31
- "defaultWorkspace.failed": "无法创建默认工作区,请通过“选择工作区”选择文件夹",
32
- "defaultWorkspace.title": "默认工作区",
33
- "group.ungrouped": "未分组",
34
- "session.new": "新会话",
35
- "section.workspaces": "工作区",
36
- "section.sessions": "会话",
37
- "viewOptions.label": "视图选项",
38
- "groupBy.label": "分组方式",
39
- "groupBy.workspace": "按工作区",
40
- "groupBy.workspaceTree": "按工作区树",
41
- "groupBy.flat": "单列表",
42
- "orderBy.label": "排序方式",
43
- "orderBy.manual": "手动排序",
44
- "orderBy.updated": "最近更新",
45
- "filterBy.label": "筛选会话",
46
- "viewOptions.showArchived": "显示已归档",
47
- "viewOptions.onlyArchived": "仅显示已归档",
48
- "sessions.expand": "展开其余 {n} 个会话",
49
- "sessions.collapse": "收起",
50
- "empty.none": "暂无会话",
51
- "empty.noMatches": "无匹配结果",
52
- "workspace.add": "添加工作区",
53
- "search.sessions.aria": "搜索会话",
54
- "search.placeholder": "搜索会话名称",
55
- "search.clear": "清除搜索",
56
- "search.results.aria": "搜索结果",
57
- "search.pending": "正在搜索会话历史…",
58
- "search.noMatches": "无匹配会话",
59
- "search.hasMore": "仅显示前 {n} 条结果,请缩小搜索范围。",
60
- "menu.addWorkspace": "添加工作区…",
61
- "picker.loading": "正在加载工作区…",
62
- "conflict.named": "已存在名为“{name}”的工作区。",
63
- "folderError.title": "无法打开文件夹",
64
- "folderError.retry": "重新选择",
65
- "rename": "重命名",
66
- "rename.workspace.title": "重命名工作区",
67
- "rename.session.title": "重命名会话",
68
- "field.workspaceName": "工作区名称",
69
- "field.sessionName": "会话名称",
70
- "delete.workspace": "删除工作区",
71
- "delete.desc": "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",
72
- "delete.pending": "正在删除工作区…",
73
- "menu.fork": "分叉会话",
74
- "menu.archiveSession": "归档会话",
75
- "menu.unarchiveSession": "取消归档",
76
- "menu.pinSession": "置顶会话",
77
- "menu.unpinSession": "取消置顶",
78
- "row.archived": "已归档",
79
- "row.pinned": "已置顶",
80
- "toast.archivedNotOpenable": "已归档对话暂时无法查看,请取消归档后查看",
81
- "toast.archived": "会话已归档,可",
82
- "toast.stoppedAndArchived": "已停止并归档,可",
83
- "archive.confirm.title": "停止并归档此会话?",
84
- "archive.confirm.desc": "“{title}”仍有正在进行的工作。归档会先停止这些工作;之后可在侧栏“显示已归档”中恢复会话,被停止的工作不会自动继续。",
85
- "archive.confirm.activity": "将被停止的工作",
86
- "archive.confirm.turn": "进行中的回合",
87
- "archive.confirm.subagents.one": "{n} 个运行中的子代理:{names}",
88
- "archive.confirm.subagents.other": "{n} 个运行中的子代理:{names}",
89
- "archive.confirm.jobs.one": "{n} 个后台任务:{names}",
90
- "archive.confirm.jobs.other": "{n} 个后台任务:{names}",
91
- "archive.confirm.schedules.one": "{n} 条定时提醒:{names}",
92
- "archive.confirm.schedules.other": "{n} 条定时提醒:{names}",
93
- "archive.confirm.other.one": "{n} 项其他工作({kind})",
94
- "archive.confirm.other.other": "{n} 项其他工作({kind})",
95
- "archive.confirm.listSeparator": "、",
96
- "archive.confirm.action": "停止并归档",
97
- "archive.confirm.pending": "正在停止并归档…",
98
- "toast.archivedUndo": "撤销",
99
- "toast.archivedOr": "或",
100
- "toast.archivedFilter": "筛选已归档会话",
101
- "toast.pinFailed": "置顶失败,请稍后重试",
102
- "toast.unpinFailed": "取消置顶失败,请稍后重试",
103
- "toast.createFailed": "新建会话失败:{message}",
104
- "sessions.count.one": "{n} 个会话",
105
- "sessions.count.other": "{n} 个会话",
106
- "actions.workspace.aria": "工作区“{name}”的操作",
107
- "actions.session.aria": "会话“{name}”的操作",
108
- "actions.archive": "归档会话",
109
- "actions.unarchive": "取消归档",
110
- "actions.pin": "置顶会话",
111
- "actions.unpin": "取消置顶",
112
- "actions.newSession": "新会话",
113
- "actions.newSession.aria": "在“{name}”中新建会话",
114
- "status.running": "进行中",
115
- "status.subagentsRunning.one": "{n} 个子代理运行中",
116
- "status.subagentsRunning.other": "{n} 个子代理运行中",
117
- "status.idle": "空闲",
118
- "status.waitingApproval": "等待审批",
119
- "status.planReview": "计划待审",
120
- "status.waitingAnswer": "等待回答",
121
- "status.compact.approval": "待审批",
122
- "status.compact.planReview": "计划待审",
123
- "status.compact.answer": "待回答",
124
- "status.completed": "已完成",
125
- "schedule.active": "有活动定时任务",
126
- "hover.created": "创建于 {time}",
127
- "hover.copied": "已复制",
128
- "date.ymd": "{y}年{m}月{d}日",
129
- "time.now": "刚刚",
130
- "time.minutes": "{n}分钟",
131
- "time.hours": "{n}小时",
132
- "time.days": "{n}天",
133
- "time.months": "{n}个月",
134
- "time.years": "{n}年",
135
- "time.ago": "{t}前"
136
- };
137
- /** English dictionary, checked complete against the zh key set. */
138
- const en = {
139
- "defaultWorkspace.failed": "Unable to create default workspace. Use Choose workspace to select a folder.",
140
- "defaultWorkspace.title": "Default workspace",
141
- "group.ungrouped": "Ungrouped",
142
- "session.new": "New Session",
143
- "section.workspaces": "Workspaces",
144
- "section.sessions": "Sessions",
145
- "viewOptions.label": "View options",
146
- "groupBy.label": "Group by",
147
- "groupBy.workspace": "WorkSpace",
148
- "groupBy.workspaceTree": "Workspace Tree",
149
- "groupBy.flat": "In one list",
150
- "orderBy.label": "Order by",
151
- "orderBy.manual": "Manual",
152
- "orderBy.updated": "Last updated",
153
- "filterBy.label": "Filter sessions",
154
- "viewOptions.showArchived": "Show archived",
155
- "viewOptions.onlyArchived": "Archived only",
156
- "sessions.expand": "Show {n} more sessions",
157
- "sessions.collapse": "Show less",
158
- "empty.none": "No sessions yet",
159
- "empty.noMatches": "No matches",
160
- "workspace.add": "Add workspace",
161
- "search.sessions.aria": "Search sessions",
162
- "search.placeholder": "Search session names",
163
- "search.clear": "Clear search",
164
- "search.results.aria": "Search results",
165
- "search.pending": "Searching session history…",
166
- "search.noMatches": "No matching sessions",
167
- "search.hasMore": "Showing the first {n} results. Narrow your search.",
168
- "menu.addWorkspace": "Add workspace…",
169
- "picker.loading": "Loading workspaces…",
170
- "conflict.named": "A workspace named “{name}” already exists.",
171
- "folderError.title": "Couldn’t open folder",
172
- "folderError.retry": "Choose again",
173
- "rename": "Rename",
174
- "rename.workspace.title": "Rename workspace",
175
- "rename.session.title": "Rename session",
176
- "field.workspaceName": "Workspace name",
177
- "field.sessionName": "Session name",
178
- "delete.workspace": "Delete workspace",
179
- "delete.desc": "This removes “{name}” from the workspace list. The folder and session logs will be kept. Its sessions will appear under Ungrouped.",
180
- "delete.pending": "Deleting workspace…",
181
- "menu.fork": "Fork session",
182
- "menu.archiveSession": "Archive session",
183
- "menu.unarchiveSession": "Unarchive session",
184
- "menu.pinSession": "Pin session",
185
- "menu.unpinSession": "Unpin session",
186
- "row.archived": "Archived",
187
- "row.pinned": "Pinned",
188
- "toast.archivedNotOpenable": "Archived sessions cannot be opened. Unarchive it to view.",
189
- "toast.archived": "Session archived. You can ",
190
- "toast.stoppedAndArchived": "Session stopped and archived. You can ",
191
- "archive.confirm.title": "Stop and archive this session?",
192
- "archive.confirm.desc": "“{title}” still has work in progress. Archiving stops it first; you can restore the session later from “Show archived” in the sidebar, and the stopped work will not resume on its own.",
193
- "archive.confirm.activity": "Work that will be stopped",
194
- "archive.confirm.turn": "The turn in progress",
195
- "archive.confirm.subagents.one": "{n} running subagent: {names}",
196
- "archive.confirm.subagents.other": "{n} running subagents: {names}",
197
- "archive.confirm.jobs.one": "{n} background job: {names}",
198
- "archive.confirm.jobs.other": "{n} background jobs: {names}",
199
- "archive.confirm.schedules.one": "{n} scheduled reminder: {names}",
200
- "archive.confirm.schedules.other": "{n} scheduled reminders: {names}",
201
- "archive.confirm.other.one": "{n} other item of work ({kind})",
202
- "archive.confirm.other.other": "{n} other items of work ({kind})",
203
- "archive.confirm.listSeparator": ", ",
204
- "archive.confirm.action": "Stop and archive",
205
- "archive.confirm.pending": "Stopping and archiving…",
206
- "toast.archivedUndo": "undo",
207
- "toast.archivedOr": " or ",
208
- "toast.archivedFilter": "filter archived sessions",
209
- "toast.pinFailed": "Pin failed. Try again later.",
210
- "toast.unpinFailed": "Unpin failed. Try again later.",
211
- "toast.createFailed": "New session failed: {message}",
212
- "sessions.count.one": "{n} session",
213
- "sessions.count.other": "{n} sessions",
214
- "actions.workspace.aria": "Workspace actions for {name}",
215
- "actions.session.aria": "Session actions for {name}",
216
- "actions.archive": "Archive",
217
- "actions.unarchive": "Unarchive",
218
- "actions.pin": "Pin",
219
- "actions.unpin": "Unpin",
220
- "actions.newSession": "New session",
221
- "actions.newSession.aria": "New session in {name}",
222
- "status.running": "Running",
223
- "status.subagentsRunning.one": "{n} subagent running",
224
- "status.subagentsRunning.other": "{n} subagents running",
225
- "status.idle": "Idle",
226
- "status.waitingApproval": "Waiting for approval",
227
- "status.planReview": "Plan awaiting review",
228
- "status.waitingAnswer": "Waiting for answer",
229
- "status.compact.approval": "Approval",
230
- "status.compact.planReview": "Plan review",
231
- "status.compact.answer": "Answer",
232
- "status.completed": "Completed",
233
- "schedule.active": "Has active scheduled task",
234
- "hover.created": "Created {time}",
235
- "hover.copied": "Copied",
236
- "date.ymd": "{y}-{m}-{d}",
237
- "time.now": "now",
238
- "time.minutes": "{n}min",
239
- "time.hours": "{n}h",
240
- "time.days": "{n}d",
241
- "time.months": "{n}mo",
242
- "time.years": "{n}y",
243
- "time.ago": "{t} ago"
244
- };
28
+ function createWorkspaceShortcutControls() {
29
+ const state = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
30
+ searchRequest: 0,
31
+ addRequested: false,
32
+ directoryBusy: false,
33
+ renameTarget: null,
34
+ forkError: null
35
+ });
36
+ let forkErrorSeq = 0;
37
+ return {
38
+ state,
39
+ search: () => {
40
+ state.set({
41
+ ...state.getSnapshot(),
42
+ searchRequest: state.getSnapshot().searchRequest + 1
43
+ });
44
+ },
45
+ add: () => {
46
+ state.set(state.getSnapshot().directoryBusy ? state.getSnapshot() : {
47
+ ...state.getSnapshot(),
48
+ addRequested: true
49
+ });
50
+ },
51
+ closeAdd: () => {
52
+ state.set({
53
+ ...state.getSnapshot(),
54
+ addRequested: false
55
+ });
56
+ },
57
+ directoryBusy: (busy) => {
58
+ state.set({
59
+ ...state.getSnapshot(),
60
+ directoryBusy: busy
61
+ });
62
+ },
63
+ rename: (sessionId, currentTitle) => {
64
+ state.set({
65
+ ...state.getSnapshot(),
66
+ renameTarget: {
67
+ sessionId,
68
+ currentTitle
69
+ }
70
+ });
71
+ },
72
+ closeRename: () => {
73
+ state.set({
74
+ ...state.getSnapshot(),
75
+ renameTarget: null
76
+ });
77
+ },
78
+ forkFailed: (reason) => {
79
+ forkErrorSeq += 1;
80
+ state.set({
81
+ ...state.getSnapshot(),
82
+ forkError: {
83
+ reason,
84
+ seq: forkErrorSeq
85
+ }
86
+ });
87
+ },
88
+ dismissForkError: () => {
89
+ state.set({
90
+ ...state.getSnapshot(),
91
+ forkError: null
92
+ });
93
+ }
94
+ };
95
+ }
96
+ /**
97
+ * Register navigation commands against the existing workspace owner.
98
+ * @param ctx - plugin context with the shortcut, locale, and model services.
99
+ * @param navigation - session creation and forking from the pointer controls' navigation service.
100
+ * @param controls - browser-owned opening requests.
101
+ * @param archiveSession - shared archive action, including running-work confirmation and notices.
102
+ */
103
+ function installWorkspaceShortcuts(ctx, navigation, controls, archiveSession) {
104
+ const t = ctx.locale.bind("workspace");
105
+ const current = () => Object.values(ctx.sessions.list.getSnapshot().byId).find((row) => (row.retainedBy.mainView ?? 0) > 0);
106
+ const addReason = () => ctx.slots.entries("sidebar.workspaces.directoryFlow").length === 0 ? t("shortcut.noPicker") : controls.state.getSnapshot().directoryBusy ? t("shortcut.directoryBusy") : null;
107
+ const register = (id, label, aliases, code, modifiers, webModifiers, resolve) => {
108
+ ctx.effect(() => ctx.shortcuts.register({
109
+ id,
110
+ label,
111
+ aliases,
112
+ defaults: {
113
+ "desktop:macos": {
114
+ code,
115
+ modifiers
116
+ },
117
+ "desktop:windows": {
118
+ code,
119
+ modifiers
120
+ },
121
+ "desktop:linux": {
122
+ code,
123
+ modifiers
124
+ },
125
+ "web:macos": {
126
+ code,
127
+ modifiers: webModifiers
128
+ },
129
+ "web:windows": {
130
+ code,
131
+ modifiers: webModifiers
132
+ }
133
+ },
134
+ regions: ["page", "editable"],
135
+ modals: [],
136
+ resolve
137
+ }), `ui-workspace: ${id}`);
138
+ };
139
+ register("session.new", () => t("session.new"), ["new session", "new chat"], "KeyN", ["primary"], ["primary", "alt"], () => ({
140
+ status: "handled",
141
+ run: () => {
142
+ navigation.startSession();
143
+ }
144
+ }));
145
+ register("session.search", () => t("search.sessions.aria"), ["search sessions"], "KeyK", ["primary"], ["primary", "alt"], () => ({
146
+ status: "handled",
147
+ run: controls.search
148
+ }));
149
+ register("workspace.add", () => t("workspace.add"), ["add workspace", "open folder"], "KeyO", ["primary"], ["primary", "alt"], () => {
150
+ const reason = addReason();
151
+ return reason === null ? {
152
+ status: "handled",
153
+ run: controls.add
154
+ } : {
155
+ status: "blocked",
156
+ reason
157
+ };
158
+ });
159
+ register("session.rename", () => t("rename.session.title"), ["rename session"], "KeyR", ["primary", "alt"], ["primary", "shift"], () => {
160
+ const target = current();
161
+ return target === void 0 ? {
162
+ status: "blocked",
163
+ reason: t("shortcut.noSession")
164
+ } : {
165
+ status: "handled",
166
+ run: () => {
167
+ controls.rename(target.id, target.displayTitle);
168
+ }
169
+ };
170
+ });
171
+ register("session.fork", () => t("menu.fork"), ["fork session"], "KeyF", ["primary", "alt"], ["primary", "shift"], () => {
172
+ const target = current();
173
+ if (target === void 0) return {
174
+ status: "blocked",
175
+ reason: t("shortcut.noSession")
176
+ };
177
+ if (target.blank) return {
178
+ status: "blocked",
179
+ reason: t("shortcut.noCompletedTurn")
180
+ };
181
+ return {
182
+ status: "handled",
183
+ run: () => {
184
+ navigation.forkSession(target.id).catch((error) => {
185
+ const unavailable = error instanceof Error && error.name === "SessionForkError" && error.rpcError.code === "session/fork-unavailable";
186
+ controls.forkFailed(unavailable ? "unavailable" : "failed");
187
+ if (!unavailable) console.warn("session fork rejected:", error);
188
+ });
189
+ }
190
+ };
191
+ });
192
+ register("session.archive", () => t("menu.archiveSession"), ["archive session"], "KeyA", ["primary", "shift"], ["primary", "alt"], () => {
193
+ const target = current();
194
+ return target === void 0 ? {
195
+ status: "blocked",
196
+ reason: t("shortcut.noSession")
197
+ } : {
198
+ status: "handled",
199
+ run: () => {
200
+ archiveSession(target.id);
201
+ }
202
+ };
203
+ });
204
+ }
245
205
  //#endregion
246
206
  //#region ../../util/values/src/index.ts
247
207
  /**
@@ -429,10 +389,6 @@ window.__ModuleLoader__.load({
429
389
  function sessionTitle(session) {
430
390
  return session.blank ? "" : session.displayTitle;
431
391
  }
432
- /** The list projection alone owns the best-effort active-Schedule indicator. */
433
- function hasActiveSchedule(session) {
434
- return (session.projectionValues?.schedule?.length ?? 0) > 0;
435
- }
436
392
  /** Build one group without projecting session lineage into presentation. */
437
393
  function buildGroup(key, workspaceId, cwd, createdAt, label, members) {
438
394
  return {
@@ -472,6 +428,7 @@ window.__ModuleLoader__.load({
472
428
  if (!sessionVisible(summary, current, archived, archivedFilter)) continue;
473
429
  members.push(summary);
474
430
  }
431
+ if (archivedFilter === "only" && members.length === 0) continue;
475
432
  groups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members));
476
433
  }
477
434
  const stray = list.ids.map((id) => list.byId[id]).filter((s) => s !== void 0 && !accounted.has(s.id) && sessionVisible(s, current, archived, archivedFilter));
@@ -500,7 +457,6 @@ window.__ModuleLoader__.load({
500
457
  running: status?.running ?? s.running,
501
458
  runningSubagentCount: runningChildCount(list, s.id, statuses),
502
459
  completed: status?.completionUnread === true,
503
- hasActiveSchedule: hasActiveSchedule(s),
504
460
  pinned: !archived.has(s.id) && pinned.has(s.id),
505
461
  archived: archived.has(s.id),
506
462
  updatedAt: s.updatedAt,
@@ -510,8 +466,9 @@ window.__ModuleLoader__.load({
510
466
  /**
511
467
  * Derive the workspace browser groups with every session as a top-level row.
512
468
  *
513
- * Every group shows; sessions populate under expanded groups with pinned rows
514
- * leading in the selected local order. Blank sessions are
469
+ * Every group shows, except that the archived-only filter drops groups
470
+ * without visible members; sessions populate under expanded groups with
471
+ * pinned rows leading in the selected local order. Blank sessions are
515
472
  * excluded except for the selected provisional New Session row; archived
516
473
  * sessions keep their slots and appear per the archived filter. Content
517
474
  * search lives outside this derivation (see {@link deriveSearchResults}).
@@ -646,7 +603,6 @@ window.__ModuleLoader__.load({
646
603
  runningSubagentCount: runningChildCount(list, summary.id, statuses),
647
604
  ...pendingInteraction === void 0 ? {} : { pendingInteraction },
648
605
  completed: status?.completionUnread === true,
649
- hasActiveSchedule: hasActiveSchedule(summary),
650
606
  archived: archived.has(summary.id),
651
607
  ...match === void 0 ? {} : { snippet: match.snippet }
652
608
  };
@@ -988,13 +944,8 @@ window.__ModuleLoader__.load({
988
944
  if (sessionId !== void 0 && !navigation.aborted) this.replaceMain(sessionId, navigation, "preserve");
989
945
  }
990
946
  async initializeDefaultWorkspace(signal) {
991
- const language = this.ctx.locale.getSnapshot().active.toLowerCase().split("-")[0];
992
- const title = (language === "zh" ? zh : en)["defaultWorkspace.title"];
993
947
  try {
994
- return await this.workspaces.initializeDefault({
995
- directoryName: language === "zh" || language === "en" ? title : "default-workspace",
996
- title
997
- }, signal);
948
+ return await this.workspaces.initializeDefault(signal);
998
949
  } catch (_error) {
999
950
  if (!signal.aborted) this.notify({ kind: "defaultWorkspaceFailed" });
1000
951
  return;
@@ -1089,9 +1040,22 @@ window.__ModuleLoader__.load({
1089
1040
  for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
1090
1041
  return n;
1091
1042
  }
1043
+ /**
1044
+ * The text one Workspace is labeled with. A Workspace still carrying the
1045
+ * automatic first-use title reads as the caller's localized default name; every
1046
+ * other title reads verbatim in every language. A title the user typed as
1047
+ * exactly {@link DEFAULT_WORKSPACE_DIRECTORY} is labeled as the default too;
1048
+ * nothing else depends on the distinction.
1049
+ * @param title - stored Workspace title.
1050
+ * @param localizedDefault - the default Workspace name in the active language.
1051
+ * @returns the title to display.
1052
+ */
1053
+ function workspaceDisplayTitle(title, localizedDefault) {
1054
+ return title === "default-workspace" ? localizedDefault : title;
1055
+ }
1092
1056
  //#endregion
1093
1057
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-workspace/src/client/rows/Rows.module.css.mjs
1094
- const css$3 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{padding:0 8px;cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:6px;padding-inline-start:calc(8px + var(--dsh-workspace-indent,0px));display:flex}.YDXeBa_projectRow:hover,.YDXeBa_sessionRow:hover,.YDXeBa_sessionRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultRow{box-sizing:border-box;cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;flex-direction:column;align-items:stretch;padding:4px 8px;display:flex}.YDXeBa_searchResultRow:hover,.YDXeBa_searchResultRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultHeading{align-items:center;min-width:0;display:flex}.YDXeBa_searchResultTitle{text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:0;margin-left:4px;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_searchResultMeta{align-items:center;gap:6px;min-width:0;margin-left:20px;display:flex}.YDXeBa_searchResultWorkspace,.YDXeBa_searchResultSnippet{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.YDXeBa_searchResultWorkspace{max-width:40%;color:var(--dsw-alias-label-tertiary);flex:none}.YDXeBa_searchResultSnippet{min-width:0;color:var(--dsw-alias-label-secondary);flex:1}.YDXeBa_projectRow{box-sizing:border-box;align-items:center;height:34px}.YDXeBa_projectRow .YDXeBa_rowActions{height:20px}.YDXeBa_sessionRow{gap:0;height:32px}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_flatSessionRowWithoutStatus .YDXeBa_title{margin-left:0}.YDXeBa_slot{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.YDXeBa_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.YDXeBa_folderActive{color:var(--dsw-alias-state-business-primary)}.YDXeBa_projectRow .YDXeBa_chevron{display:none}.YDXeBa_projectRow:hover .YDXeBa_chevron{display:inline-flex}.YDXeBa_projectRow:hover .YDXeBa_folder{display:none}.YDXeBa_arrow{transition:transform .15s var(--ds-ease-in-out)}.YDXeBa_arrowOpen{transform:rotate(90deg)}.YDXeBa_projectText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.YDXeBa_title{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_renameInput{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;border-radius:4px;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled]{mask-image:linear-gradient(90deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-clipped]{mask-image:linear-gradient(270deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled][data-clipped]{mask-image:linear-gradient(90deg,#0000,#000 12px calc(100% - 12px),#0000)}.YDXeBa_meta{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow:hidden}.YDXeBa_time{color:var(--dsw-alias-label-caption);flex:none;font-size:10px;line-height:16px}.YDXeBa_scheduleIndicator{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;margin-right:6px;display:inline-flex}.YDXeBa_searchScheduleIndicator{margin-left:4px;margin-right:0}.YDXeBa_pinIndicator{width:16px;height:20px;color:var(--dsw-alias-label-caption);flex:none;justify-content:center;align-items:center;margin-left:6px;display:inline-flex}.YDXeBa_sessionRow.YDXeBa_archived .YDXeBa_title,.YDXeBa_sessionRow.YDXeBa_archived .YDXeBa_time,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultTitle,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultWorkspace,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultSnippet{color:var(--dsw-alias-label-caption)}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:10px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_searchResultRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_searchResultHeading .YDXeBa_rowActions{margin-left:auto}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time,.YDXeBa_sessionRow:hover .YDXeBa_pinIndicator,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_pinIndicator{display:none}@media (hover:hover){.YDXeBa_sessionRow:hover .YDXeBa_title,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_title{text-overflow:clip}}.YDXeBa_projectRow.YDXeBa_menuOpen,.YDXeBa_sessionRow.YDXeBa_menuOpen{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_sessionRow.YDXeBa_dropBefore,.YDXeBa_sessionRow.YDXeBa_dropAfter{position:relative}.YDXeBa_sessionRow.YDXeBa_dropBefore:before,.YDXeBa_sessionRow.YDXeBa_dropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.YDXeBa_sessionRow.YDXeBa_dropBefore:before{top:-7px}.YDXeBa_sessionRow.YDXeBa_dropAfter:after{bottom:-7px}.YDXeBa_hoverContent{flex-direction:column;gap:8px;display:flex}.YDXeBa_hoverTitle{color:#fff;overflow-wrap:break-word;font-size:14px;line-height:20px}.YDXeBa_hoverPath{color:#cfd3d6;word-break:break-all;font-size:12px;line-height:16px}.YDXeBa_hoverTime{color:#cfd3d6;font-size:12px;line-height:16px}.YDXeBa_hoverStatus{color:#adb2b8;align-items:center;gap:8px;font-size:12px;line-height:20px;display:flex}.YDXeBa_hoverArchived svg{flex-shrink:0;margin:0 -4px}.YDXeBa_iconButton{cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.YDXeBa_iconButton:hover{color:var(--dsw-alias-label-primary)}.YDXeBa_chevron{color:var(--dsw-alias-label-caption)}@media (prefers-reduced-motion:reduce){.YDXeBa_arrow{transition:none;animation:none}}";
1058
+ const css$3 = ".YDXeBa_projectRow,.YDXeBa_sessionRow{border-radius:var(--dsw-radius-md);padding:0 8px;cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);align-items:center;gap:6px;padding-inline-start:calc(8px + var(--dsh-workspace-indent,0px));display:flex}.YDXeBa_projectRow:hover,.YDXeBa_sessionRow:hover,.YDXeBa_sessionRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultRow{box-sizing:border-box;border-radius:var(--dsw-radius-lg);cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;flex-direction:column;align-items:stretch;padding:4px 8px;display:flex}.YDXeBa_searchResultRow:hover,.YDXeBa_searchResultRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultHeading{align-items:center;min-width:0;display:flex}.YDXeBa_searchResultTitle{text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:0;margin-left:4px;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_searchResultMeta{align-items:center;gap:6px;min-width:0;margin-left:20px;display:flex}.YDXeBa_searchResultWorkspace,.YDXeBa_searchResultSnippet{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.YDXeBa_searchResultWorkspace{max-width:40%;color:var(--dsw-alias-label-tertiary);flex:none}.YDXeBa_searchResultWorkspace:only-child{max-width:100%}.YDXeBa_searchResultSnippet{min-width:0;color:var(--dsw-alias-label-secondary);flex:1}.YDXeBa_projectRow{box-sizing:border-box;align-items:center;height:34px}.YDXeBa_projectRow .YDXeBa_rowActions{height:20px}.YDXeBa_sessionRow{gap:0;height:32px}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_slot{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.YDXeBa_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.YDXeBa_folderActive{color:var(--dsw-alias-state-business-primary)}.YDXeBa_projectRow .YDXeBa_chevron{display:none}.YDXeBa_projectRow:hover .YDXeBa_chevron{display:inline-flex}.YDXeBa_projectRow:hover .YDXeBa_folder{display:none}.YDXeBa_arrow{transition:transform .15s var(--ds-ease-in-out)}.YDXeBa_arrowOpen{transform:rotate(90deg)}.YDXeBa_projectText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.YDXeBa_title{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_renameInput{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled]{mask-image:linear-gradient(90deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-clipped]{mask-image:linear-gradient(270deg,#0000,#000 12px)}.YDXeBa_sessionRow .YDXeBa_title[data-scrolled][data-clipped]{mask-image:linear-gradient(90deg,#0000,#000 12px calc(100% - 12px),#0000)}.YDXeBa_meta{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow:hidden}.YDXeBa_time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:16px}.YDXeBa_pinIndicator{width:16px;height:20px;color:var(--dsw-alias-label-caption);flex:none;justify-content:center;align-items:center;margin-left:6px;display:inline-flex}.YDXeBa_sessionRow.YDXeBa_archived .YDXeBa_title,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultTitle,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultWorkspace,.YDXeBa_searchResultRow.YDXeBa_archived .YDXeBa_searchResultSnippet{color:var(--dsw-alias-label-caption)}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:10px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_searchResultRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_searchResultHeading .YDXeBa_rowActions{margin-left:auto}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time,.YDXeBa_sessionRow:hover .YDXeBa_pinIndicator,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_pinIndicator{display:none}@media (hover:hover){.YDXeBa_sessionRow:hover .YDXeBa_title,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_title{text-overflow:clip}}.YDXeBa_projectRow.YDXeBa_menuOpen,.YDXeBa_sessionRow.YDXeBa_menuOpen{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_sessionRow.YDXeBa_dropBefore,.YDXeBa_sessionRow.YDXeBa_dropAfter{position:relative}.YDXeBa_sessionRow.YDXeBa_dropBefore:before,.YDXeBa_sessionRow.YDXeBa_dropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.YDXeBa_sessionRow.YDXeBa_dropBefore:before{top:-7px}.YDXeBa_sessionRow.YDXeBa_dropAfter:after{bottom:-7px}.YDXeBa_hoverContent{flex-direction:column;gap:8px;display:flex}.YDXeBa_hoverTitle{color:#fff;overflow-wrap:break-word;font-size:14px;line-height:20px}.YDXeBa_hoverPath{color:#cfd3d6;word-break:break-all;font-size:12px;line-height:16px}.YDXeBa_hoverTime{color:#cfd3d6;font-size:12px;line-height:16px}.YDXeBa_hoverStatus{color:#adb2b8;align-items:center;gap:8px;font-size:12px;line-height:20px;display:flex}.YDXeBa_hoverArchived svg{flex-shrink:0;margin:0 -4px}.YDXeBa_iconButton{border-radius:var(--dsw-radius-xs);cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.YDXeBa_iconButton:hover{color:var(--dsw-alias-label-primary)}.YDXeBa_chevron{color:var(--dsw-alias-label-caption)}@media (prefers-reduced-motion:reduce){.YDXeBa_arrow{transition:none;animation:none}}";
1095
1059
  const tagId$3 = "@deepseek-ai/dsh-client-ui-workspace/Rows.module.css";
1096
1060
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1097
1061
  const tag = document.createElement("style");
@@ -1108,7 +1072,6 @@ window.__ModuleLoader__.load({
1108
1072
  "dot": "YDXeBa_dot",
1109
1073
  "dropAfter": "YDXeBa_dropAfter",
1110
1074
  "dropBefore": "YDXeBa_dropBefore",
1111
- "flatSessionRowWithoutStatus": "YDXeBa_flatSessionRowWithoutStatus",
1112
1075
  "folder": "YDXeBa_folder",
1113
1076
  "folderActive": "YDXeBa_folderActive",
1114
1077
  "hoverArchived": "YDXeBa_hoverArchived",
@@ -1125,14 +1088,12 @@ window.__ModuleLoader__.load({
1125
1088
  "projectText": "YDXeBa_projectText",
1126
1089
  "renameInput": "YDXeBa_renameInput",
1127
1090
  "rowActions": "YDXeBa_rowActions",
1128
- "scheduleIndicator": "YDXeBa_scheduleIndicator",
1129
1091
  "searchResultHeading": "YDXeBa_searchResultHeading",
1130
1092
  "searchResultMeta": "YDXeBa_searchResultMeta",
1131
1093
  "searchResultRow": "YDXeBa_searchResultRow",
1132
1094
  "searchResultSnippet": "YDXeBa_searchResultSnippet",
1133
1095
  "searchResultTitle": "YDXeBa_searchResultTitle",
1134
1096
  "searchResultWorkspace": "YDXeBa_searchResultWorkspace",
1135
- "searchScheduleIndicator": "YDXeBa_searchScheduleIndicator",
1136
1097
  "selected": "YDXeBa_selected",
1137
1098
  "sessionRow": "YDXeBa_sessionRow",
1138
1099
  "slot": "YDXeBa_slot",
@@ -1303,7 +1264,7 @@ window.__ModuleLoader__.load({
1303
1264
  * @param props.t - the browser root's locale seat.
1304
1265
  * @returns the row element.
1305
1266
  */
1306
- function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, t }) {
1267
+ function ProjectRowItem({ group, containsCurrentDescendant = false, onToggle, onCreate, actions, drag, home, newShortcut, t }) {
1307
1268
  const row = group;
1308
1269
  const label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;
1309
1270
  const active = containsCurrentDescendant || group.expanded && group.containsCurrent;
@@ -1376,12 +1337,14 @@ window.__ModuleLoader__.load({
1376
1337
  })
1377
1338
  }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
1378
1339
  label: t("actions.newSession"),
1340
+ shortcutKeys: newShortcut?.keys,
1379
1341
  side: "bottom",
1380
1342
  align: "end",
1381
1343
  delayMs: 500,
1382
1344
  children: (0, react_jsx_runtime.jsx)("button", {
1383
1345
  type: "button",
1384
1346
  className: Rows_module_css_default.iconButton,
1347
+ "aria-keyshortcuts": newShortcut?.aria,
1385
1348
  "aria-label": t("actions.newSession.aria", { name: label }),
1386
1349
  onClick: (e) => {
1387
1350
  e.stopPropagation();
@@ -1474,17 +1437,6 @@ window.__ModuleLoader__.load({
1474
1437
  children: status.label
1475
1438
  }, status.label))] });
1476
1439
  }
1477
- /** Non-interactive active-Schedule marker; the enclosing row remains the only action. */
1478
- function ActiveScheduleIndicator({ t, search = false }) {
1479
- const label = t("schedule.active");
1480
- return (0, react_jsx_runtime.jsx)("span", {
1481
- className: clsx(Rows_module_css_default.scheduleIndicator, search && Rows_module_css_default.searchScheduleIndicator),
1482
- role: "img",
1483
- "aria-label": label,
1484
- title: label,
1485
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconAlarmClockOutlineRegular, {})
1486
- });
1487
- }
1488
1440
  /** Non-interactive pinned-row marker; the enclosing row remains the only action. */
1489
1441
  function PinnedIndicator({ t }) {
1490
1442
  const label = t("row.pinned");
@@ -1496,8 +1448,12 @@ window.__ModuleLoader__.load({
1496
1448
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPinFillRegular, { size: 14 })
1497
1449
  });
1498
1450
  }
1499
- /** Hover-card body: full title, relative time, and every relevant live status. */
1500
- function SessionHoverContent({ node, now, t }) {
1451
+ /**
1452
+ * Hover-card body: full title, relative time, the Session's own scheduled-task
1453
+ * section, and every relevant live status. The task section sits above the
1454
+ * status lines so they stay the card's trailing status line.
1455
+ */
1456
+ function SessionHoverContent({ node, now, renderSlot, t }) {
1501
1457
  const statuses = sessionStatuses(node, t).filter((status) => !(node.archived && (status.state === "done" || status.state === "idle")));
1502
1458
  return (0, react_jsx_runtime.jsxs)("div", {
1503
1459
  className: Rows_module_css_default.hoverContent,
@@ -1510,6 +1466,7 @@ window.__ModuleLoader__.load({
1510
1466
  className: Rows_module_css_default.hoverTime,
1511
1467
  children: hoverTimeLabel(node.updatedAt, now, t)
1512
1468
  }),
1469
+ renderSlot("sidebar.session.row.hover", { sessionId: node.id }),
1513
1470
  statuses.map((status) => (0, react_jsx_runtime.jsxs)("div", {
1514
1471
  className: Rows_module_css_default.hoverStatus,
1515
1472
  children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: status.state }), (0, react_jsx_runtime.jsx)("span", { children: status.label })]
@@ -1556,10 +1513,6 @@ window.__ModuleLoader__.load({
1556
1513
  className: Rows_module_css_default.searchResultTitle,
1557
1514
  children: result.title
1558
1515
  }),
1559
- result.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, {
1560
- t,
1561
- search: true
1562
- }),
1563
1516
  result.archived && (0, react_jsx_runtime.jsx)("span", {
1564
1517
  className: Rows_module_css_default.rowActions,
1565
1518
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
@@ -1593,22 +1546,26 @@ window.__ModuleLoader__.load({
1593
1546
  });
1594
1547
  }
1595
1548
  /**
1596
- * One top-level 34px session row: status dot (pending user interaction outranks
1597
- * own or descendant activity), title, relative time or compact pending label,
1598
- * and the row actions menu.
1549
+ * One top-level 32px session row: leading 16px cell (status dot, or the
1550
+ * leading seat while the row's primary state is idle), title, relative time or
1551
+ * compact pending label, and the row actions menu. A row that owns a state dot
1552
+ * keeps that cell and renders no seat, so an ambient automation mark never
1553
+ * appears beside the row's own state dot. An archived row keeps the cell blank:
1554
+ * neither marker renders there, and its live status stays on the hover card.
1599
1555
  * @param props.node - derived session node.
1600
1556
  * @param props.currentId - selected session id (row highlight).
1601
1557
  * @param props.now - epoch ms for relative-time formatting.
1602
1558
  * @param props.onOpen - open a session by id.
1603
1559
  * @param props.onRenameRequest - open the rename dialog from a title double-click (id + current title).
1604
- * @param props.renderSlot - render the row's `sidebar.workspaces.session.menu.item` and `sidebar.workspaces.session.row.action` lists.
1560
+ * @param props.renderSlot - child-seat renderer for the row's action lists
1561
+ * (`sidebar.workspaces.session.menu.item` / `sidebar.workspaces.session.row.action`),
1562
+ * its leading decoration, and its hover-card section.
1605
1563
  * @param props.onReveal - scroll this row into view after search navigation, then acknowledge it.
1606
1564
  * @param props.drag - optional row-drag target wiring; blank rows cannot start a drag.
1607
- * @param props.flat - omit the empty status slot in the hierarchy-free flat list.
1608
1565
  * @param props.t - the browser root's locale seat.
1609
1566
  * @returns the session row.
1610
1567
  */
1611
- function SessionNodeItem({ node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag, flat = false, t }) {
1568
+ function SessionNodeItem({ node, currentId, now, onOpen, onRenameRequest, renderSlot, onReveal, drag, t }) {
1612
1569
  const row = node;
1613
1570
  const title = displayTitle(node, t);
1614
1571
  const selected = node.id === currentId;
@@ -1630,7 +1587,7 @@ window.__ModuleLoader__.load({
1630
1587
  anchor: (0, react_jsx_runtime.jsxs)("div", {
1631
1588
  ref: rowRef,
1632
1589
  "data-row-key": `session:${node.id}`,
1633
- className: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived, flat && !showStatus && Rows_module_css_default.flatSessionRowWithoutStatus, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),
1590
+ className: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),
1634
1591
  role: "treeitem",
1635
1592
  "aria-selected": selected,
1636
1593
  "aria-description": row.archived ? t("toast.archivedNotOpenable") : void 0,
@@ -1658,9 +1615,9 @@ window.__ModuleLoader__.load({
1658
1615
  drag.drop(rowHalf(e));
1659
1616
  },
1660
1617
  children: [
1661
- (!flat || showStatus) && (0, react_jsx_runtime.jsx)("span", {
1618
+ (0, react_jsx_runtime.jsx)("span", {
1662
1619
  className: Rows_module_css_default.slot,
1663
- children: !row.archived && showStatus && (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses })
1620
+ children: !row.archived && !row.blank && (showStatus ? (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses }) : renderSlot("sidebar.session.row.leading", { sessionId: node.id }))
1664
1621
  }),
1665
1622
  (0, react_jsx_runtime.jsx)("span", {
1666
1623
  ref: titleRef,
@@ -1671,7 +1628,6 @@ window.__ModuleLoader__.load({
1671
1628
  },
1672
1629
  children: title
1673
1630
  }),
1674
- row.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, { t }),
1675
1631
  !row.blank && (0, react_jsx_runtime.jsx)("span", {
1676
1632
  className: Rows_module_css_default.time,
1677
1633
  "aria-hidden": primaryStatus.trailingLabel === void 0 ? void 0 : true,
@@ -1713,6 +1669,7 @@ window.__ModuleLoader__.load({
1713
1669
  content: (0, react_jsx_runtime.jsx)(SessionHoverContent, {
1714
1670
  node,
1715
1671
  now,
1672
+ renderSlot,
1716
1673
  t
1717
1674
  }),
1718
1675
  openDelayMs: 800,
@@ -1922,7 +1879,7 @@ window.__ModuleLoader__.load({
1922
1879
  * @param props - owner-controlled flow props.
1923
1880
  * @returns menu + dialog elements.
1924
1881
  */
1925
- function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly = false, side = "bottom", selectedId }) {
1882
+ function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly = false, onBusyChange, side = "bottom", selectedId }) {
1926
1883
  const workspaceSnapshot = useWorkspaces((state) => state);
1927
1884
  const workspaces = workspaceSnapshot.items;
1928
1885
  const getAnchorRect = (0, react.useCallback)(() => anchorRef?.current?.getBoundingClientRect() ?? null, [anchorRef]);
@@ -1931,6 +1888,9 @@ window.__ModuleLoader__.load({
1931
1888
  const [flowOpen, setFlowOpen] = (0, react.useState)(false);
1932
1889
  const [pickingFolder, setPickingFolder] = (0, react.useState)(false);
1933
1890
  const flowBusy = flowOpen || pickingFolder;
1891
+ (0, react.useEffect)(() => {
1892
+ onBusyChange?.(flowBusy);
1893
+ }, [flowBusy, onBusyChange]);
1934
1894
  const flowAvailable = useDirectoryFlow((occupied) => occupied);
1935
1895
  (0, react.useEffect)(() => {
1936
1896
  if (flowOpen && !flowAvailable) setFlowOpen(false);
@@ -1944,7 +1904,7 @@ window.__ModuleLoader__.load({
1944
1904
  const pinAdd = !addOnly && workspaces.length > 0;
1945
1905
  const items = pinAdd ? workspaces.map((workspace) => ({
1946
1906
  id: workspace.workspaceId,
1947
- label: workspace.title,
1907
+ label: workspaceDisplayTitle(workspace.title, t("workspace.defaultName")),
1948
1908
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }),
1949
1909
  disabled: flowBusy
1950
1910
  })) : addEntries;
@@ -2070,7 +2030,7 @@ window.__ModuleLoader__.load({
2070
2030
  }
2071
2031
  //#endregion
2072
2032
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-workspace/src/client/rows/WorkspaceBrowser.module.css.mjs
2073
- const css = ".bhn1Oq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;min-height:0;padding-right:var(--dsh-session-list-edge-inset);flex-direction:column;flex:1;display:flex}.bhn1Oq_root.bhn1Oq_rail{padding-right:0}.bhn1Oq_iconButton{corner-shape:round;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}.bhn1Oq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_viewOptionsMenu{min-width:200px}.bhn1Oq_sectionHeader{box-sizing:border-box;height:36px;color:var(--dsw-alias-label-tertiary);border-radius:12px;flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;display:flex;overflow:hidden}.bhn1Oq_root:not(.bhn1Oq_rail) .bhn1Oq_sectionHeader{margin-top:2px;margin-right:-4px}.bhn1Oq_sectionLabel{white-space:nowrap;opacity:1;visibility:visible;min-width:0;max-width:45%;transition:max-width .18s var(--ds-ease-in-out), margin-right .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;line-height:20px;overflow:hidden}.bhn1Oq_sectionLabelHidden{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transition-delay:0s,0s,0s,0s,.18s;transform:translate(-4px)}.bhn1Oq_searchSlot{box-sizing:border-box;min-width:0;max-width:28px;transition:max-width .18s var(--ds-ease-in-out), padding-left .18s var(--ds-ease-in-out);flex:1;align-items:center;margin-left:auto;padding-left:0;display:flex}.bhn1Oq_searchSlotExpanded{max-width:100%;padding-left:0}.bhn1Oq_headerActions{opacity:1;visibility:visible;max-width:60px;transition:max-width .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;align-items:center;gap:4px;display:flex;overflow:hidden}.bhn1Oq_headerActionsHidden{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transition-delay:0s,0s,0s,.18s;transform:translate(4px)}.bhn1Oq_search{box-sizing:border-box;corner-shape:round;cursor:text;width:100%;height:28px;color:var(--dsw-alias-label-secondary);transition:width .18s var(--ds-ease-in-out), padding .18s var(--ds-ease-in-out), border-color .18s var(--ds-ease-in-out), background-color .18s var(--ds-ease-in-out);background:0 0;border:none;border-radius:50%;flex:none;align-items:center;gap:0;margin:0;padding:0;display:flex;overflow:hidden}.bhn1Oq_searchExpanded{border:.5px solid var(--dsw-alias-border-l4);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;border-radius:10px;margin-inline:-2px;padding:0 4px 0 0}.bhn1Oq_searchButton{corner-shape:round;cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_searchExpanded .bhn1Oq_searchButton{width:28px;height:30px}.bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_searchExpanded .bhn1Oq_searchButton:hover{background:0 0}.bhn1Oq_searchInput{opacity:0;pointer-events:none;width:0;min-width:0;color:var(--dsw-alias-label-primary);transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;font-size:13px;line-height:18px}.bhn1Oq_searchExpanded .bhn1Oq_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.bhn1Oq_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.bhn1Oq_clearButton{corner-shape:round;cursor:pointer;width:24px;height:24px;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}.bhn1Oq_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_rail .bhn1Oq_sectionHeader{justify-content:flex-start;gap:0;margin-bottom:12px;padding-left:0}.bhn1Oq_rail .bhn1Oq_headerActions{max-width:none}.bhn1Oq_rail .bhn1Oq_iconButton{width:36px;height:36px;color:var(--dsw-alias-label-primary);border-radius:12px}.bhn1Oq_rail .bhn1Oq_search{background:0 0;border-color:#0000;border-radius:12px;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.bhn1Oq_rail .bhn1Oq_searchButton{width:36px;height:36px;color:var(--dsw-alias-label-primary);border-radius:12px}.bhn1Oq_rail .bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:visible}.bhn1Oq_rail .bhn1Oq_listArea{margin-left:0;margin-right:0;padding-left:0}.bhn1Oq_treeBody{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.bhn1Oq_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}[data-platform=darwin] .bhn1Oq_fade{display:none}.bhn1Oq_wide{animation:bhn1Oq_wide-in .2s var(--ds-ease-in-out)}@keyframes bhn1Oq_wide-in{0%{opacity:0}}.bhn1Oq_list{min-height:0;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;flex:1;padding-bottom:16px;overflow-y:auto}.bhn1Oq_flatList>*+*,.bhn1Oq_searchTree>[role=treeitem]+[role=treeitem],.bhn1Oq_groupSection>*+*{margin-top:2px}.bhn1Oq_searchStatus{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.bhn1Oq_skeletonRow{box-sizing:border-box;align-items:flex-start;gap:8px;min-height:48px;padding:6px 8px 7px;display:flex}.bhn1Oq_skeletonDot{corner-shape:round;border-radius:50%;flex:none;width:16px;height:16px}.bhn1Oq_skeletonBars{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{background:var(--dsw-alias-bg-skeleton);animation:2s cubic-bezier(.36,0,.64,1) infinite bhn1Oq_search-skeleton}.bhn1Oq_skeletonBar{border-radius:4px;width:65%;height:16px}.bhn1Oq_skeletonBarWide{width:90%;height:13px}@keyframes bhn1Oq_search-skeleton{0%{opacity:1}40%{opacity:.6}80%,to{opacity:1}}.bhn1Oq_groupSection{position:relative}.bhn1Oq_groupSection+.bhn1Oq_groupSection{margin-top:4px}.bhn1Oq_listTopDropIndicator,.bhn1Oq_workspaceDropBefore:before,.bhn1Oq_workspaceDropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:0}.bhn1Oq_listTopDropIndicator{top:-8px;left:0;right:var(--dsh-session-list-edge-inset)}.bhn1Oq_listTopDropActive>.bhn1Oq_workspaceDropBefore:first-child:before{display:none}.bhn1Oq_workspaceDropBefore:before{top:-8px}.bhn1Oq_workspaceDropAfter:after{bottom:-8px}.bhn1Oq_sessionOverflowButton{width:100%;height:28px;padding:0 12px 0 calc(28px + var(--dsh-workspace-indent,0px));cursor:pointer;text-align:left;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:8px;font-size:12px}.bhn1Oq_groupSection>.bhn1Oq_sessionOverflowButton{margin-top:0}.bhn1Oq_sessionOverflowButton:hover{color:var(--dsw-alias-label-secondary);background:0 0}.bhn1Oq_empty{color:var(--dsw-alias-label-tertiary);padding:16px 12px;font-size:13px}.bhn1Oq_renameInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:22px;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.bhn1Oq_renameInput:disabled{color:var(--dsw-alias-label-dimmed)}.bhn1Oq_renameError{color:var(--dsw-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}.bhn1Oq_deleteAction:not(:disabled){color:var(--dsw-alias-state-error-primary)}.bhn1Oq_deleteStatus{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.bhn1Oq_archiveActivity{color:var(--dsw-alias-label-primary);margin:0 0 8px;padding-left:18px;font-size:13px;line-height:20px}.bhn1Oq_archiveActivity li{overflow-wrap:anywhere}@media (prefers-reduced-motion:reduce){.bhn1Oq_wide,.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{animation:none}.bhn1Oq_search,.bhn1Oq_sectionLabel,.bhn1Oq_searchSlot,.bhn1Oq_searchInput,.bhn1Oq_headerActions{transition:none}}";
2033
+ const css = ".bhn1Oq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;min-height:0;padding-right:var(--dsh-session-list-edge-inset);flex-direction:column;flex:1;display:flex}.bhn1Oq_root.bhn1Oq_rail{padding-right:0}.bhn1Oq_iconButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_iconButton:focus-visible,.bhn1Oq_searchButton:focus-visible,.bhn1Oq_clearButton:focus-visible{outline:var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.bhn1Oq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_viewOptionsMenu{min-width:200px}.bhn1Oq_sectionHeader{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;display:flex;overflow:hidden}.bhn1Oq_root:not(.bhn1Oq_rail) .bhn1Oq_sectionHeader{margin-top:2px;margin-right:-4px}.bhn1Oq_sectionLabel{white-space:nowrap;opacity:1;visibility:visible;min-width:0;max-width:45%;transition:max-width .18s var(--ds-ease-in-out), margin-right .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;line-height:20px;overflow:hidden}.bhn1Oq_sectionLabelHidden{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transition-delay:0s,0s,0s,0s,.18s;transform:translate(-4px)}.bhn1Oq_searchSlot{box-sizing:border-box;min-width:0;max-width:28px;transition:max-width .18s var(--ds-ease-in-out), padding-left .18s var(--ds-ease-in-out);flex:1;align-items:center;margin-left:auto;padding-left:0;display:flex}.bhn1Oq_searchSlotExpanded{max-width:100%;padding-left:0}.bhn1Oq_headerActions{opacity:1;visibility:visible;max-width:60px;transition:max-width .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;align-items:center;gap:4px;display:flex;overflow:hidden}.bhn1Oq_headerActionsHidden{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transition-delay:0s,0s,0s,.18s;transform:translate(4px)}.bhn1Oq_search{box-sizing:border-box;border-radius:var(--dsw-radius-sm);cursor:text;width:100%;height:28px;color:var(--dsw-alias-label-secondary);transition:width .18s var(--ds-ease-in-out), padding .18s var(--ds-ease-in-out), border-color .18s var(--ds-ease-in-out), background-color .18s var(--ds-ease-in-out);background:0 0;border:none;flex:none;align-items:center;gap:0;margin:0;padding:0;display:flex;overflow:hidden}.bhn1Oq_searchExpanded{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;margin-inline:-2px;padding:0 4px 0 0}.bhn1Oq_searchButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_searchExpanded .bhn1Oq_searchButton{width:28px;height:30px}.bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_searchExpanded .bhn1Oq_searchButton:hover{background:0 0}.bhn1Oq_searchInput{opacity:0;pointer-events:none;width:0;min-width:0;color:var(--dsw-alias-label-primary);transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;font-size:13px;line-height:18px}.bhn1Oq_searchExpanded .bhn1Oq_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.bhn1Oq_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.bhn1Oq_clearButton{border-radius:var(--dsw-radius-sm);cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bhn1Oq_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_rail .bhn1Oq_sectionHeader{justify-content:flex-start;gap:0;margin-bottom:12px;padding-left:0}.bhn1Oq_rail .bhn1Oq_headerActions{max-width:none}.bhn1Oq_rail .bhn1Oq_iconButton{border-radius:var(--dsw-radius-md);width:36px;height:36px;color:var(--dsw-alias-label-primary)}.bhn1Oq_rail .bhn1Oq_search{border-radius:var(--dsw-radius-md);background:0 0;border-color:#0000;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.bhn1Oq_rail .bhn1Oq_searchButton{border-radius:var(--dsw-radius-md);width:36px;height:36px;color:var(--dsw-alias-label-primary)}.bhn1Oq_rail .bhn1Oq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.bhn1Oq_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:visible}.bhn1Oq_rail .bhn1Oq_listArea{margin-left:0;margin-right:0;padding-left:0}.bhn1Oq_treeBody{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.bhn1Oq_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}[data-platform=darwin] .bhn1Oq_fade{display:none}.bhn1Oq_wide{animation:bhn1Oq_wide-in .2s var(--ds-ease-in-out)}@keyframes bhn1Oq_wide-in{0%{opacity:0}}.bhn1Oq_list{min-height:0;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;flex:1;padding-bottom:16px;overflow-y:auto}.bhn1Oq_flatList>*+*,.bhn1Oq_searchTree>[role=treeitem]+[role=treeitem],.bhn1Oq_groupSection>*+*{margin-top:2px}.bhn1Oq_searchStatus{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.bhn1Oq_skeletonRow{box-sizing:border-box;align-items:flex-start;gap:8px;min-height:48px;padding:6px 8px 7px;display:flex}.bhn1Oq_skeletonDot{corner-shape:round;border-radius:50%;flex:none;width:16px;height:16px}.bhn1Oq_skeletonBars{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{background:var(--dsw-alias-bg-skeleton);animation:2s cubic-bezier(.36,0,.64,1) infinite bhn1Oq_search-skeleton}.bhn1Oq_skeletonBar{border-radius:var(--dsw-radius-xs);width:65%;height:16px}.bhn1Oq_skeletonBarWide{width:90%;height:13px}@keyframes bhn1Oq_search-skeleton{0%{opacity:1}40%{opacity:.6}80%,to{opacity:1}}.bhn1Oq_groupSection{position:relative}.bhn1Oq_groupSection+.bhn1Oq_groupSection{margin-top:4px}.bhn1Oq_listTopDropIndicator,.bhn1Oq_workspaceDropBefore:before,.bhn1Oq_workspaceDropAfter:after{content:\"\";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:0}.bhn1Oq_listTopDropIndicator{top:-8px;left:0;right:var(--dsh-session-list-edge-inset)}.bhn1Oq_listTopDropActive>.bhn1Oq_workspaceDropBefore:first-child:before{display:none}.bhn1Oq_workspaceDropBefore:before{top:-8px}.bhn1Oq_workspaceDropAfter:after{bottom:-8px}.bhn1Oq_sessionOverflowButton{border-radius:var(--dsw-radius-sm);width:100%;height:28px;padding:0 12px 0 calc(28px + var(--dsh-workspace-indent,0px));cursor:pointer;text-align:left;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;font-size:12px}.bhn1Oq_groupSection>.bhn1Oq_sessionOverflowButton{margin-top:0}.bhn1Oq_sessionOverflowButton:hover{color:var(--dsw-alias-label-secondary);background:0 0}.bhn1Oq_empty{color:var(--dsw-alias-label-tertiary);padding:16px 12px;font-size:13px}.bhn1Oq_emptyState{color:var(--dsw-alias-label-tertiary);flex-direction:column;align-items:center;gap:8px;margin-top:80px;padding:0 12px;font-size:13px;line-height:20px;display:flex}.bhn1Oq_emptyState>svg{color:var(--dsw-alias-label-caption);margin-bottom:4px}.bhn1Oq_emptyAction{cursor:pointer;color:var(--dsw-alias-link);background:0 0;border:none;padding:0;font-size:13px;line-height:20px}.bhn1Oq_renameInput{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-lg);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.bhn1Oq_renameInput:disabled{color:var(--dsw-alias-label-dimmed)}.bhn1Oq_renameError{color:var(--dsw-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}.bhn1Oq_deleteAction:not(:disabled){color:var(--dsw-alias-state-error-primary)}.bhn1Oq_deleteStatus{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.bhn1Oq_archiveActivity{color:var(--dsw-alias-label-primary);margin:0 0 8px;padding-left:18px;font-size:13px;line-height:20px}.bhn1Oq_archiveActivity li{overflow-wrap:anywhere}@media (prefers-reduced-motion:reduce){.bhn1Oq_wide,.bhn1Oq_skeletonDot,.bhn1Oq_skeletonBar{animation:none}.bhn1Oq_search,.bhn1Oq_sectionLabel,.bhn1Oq_searchSlot,.bhn1Oq_searchInput,.bhn1Oq_headerActions{transition:none}}";
2074
2034
  const tagId = "@deepseek-ai/dsh-client-ui-workspace/WorkspaceBrowser.module.css";
2075
2035
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
2076
2036
  const tag = document.createElement("style");
@@ -2085,6 +2045,8 @@ window.__ModuleLoader__.load({
2085
2045
  "deleteAction": "bhn1Oq_deleteAction",
2086
2046
  "deleteStatus": "bhn1Oq_deleteStatus",
2087
2047
  "empty": "bhn1Oq_empty",
2048
+ "emptyAction": "bhn1Oq_emptyAction",
2049
+ "emptyState": "bhn1Oq_emptyState",
2088
2050
  "fade": "bhn1Oq_fade",
2089
2051
  "flatList": "bhn1Oq_flatList",
2090
2052
  "groupSection": "bhn1Oq_groupSection",
@@ -2257,10 +2219,15 @@ window.__ModuleLoader__.load({
2257
2219
  id: "filter-by",
2258
2220
  text: t("filterBy.label")
2259
2221
  },
2222
+ {
2223
+ id: "hide-archived",
2224
+ label: t("viewOptions.hideArchived"),
2225
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOffOutlineRegular, {})
2226
+ },
2260
2227
  {
2261
2228
  id: "show-archived",
2262
2229
  label: t("viewOptions.showArchived"),
2263
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, {})
2230
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, {})
2264
2231
  },
2265
2232
  {
2266
2233
  id: "only-archived",
@@ -2271,14 +2238,18 @@ window.__ModuleLoader__.load({
2271
2238
  selectedIds: [
2272
2239
  groupBy,
2273
2240
  orderBy,
2274
- ...archivedFilter === "show" ? ["show-archived"] : [],
2275
- ...archivedFilter === "only" ? ["only-archived"] : []
2241
+ {
2242
+ default: "hide-archived",
2243
+ show: "show-archived",
2244
+ only: "only-archived"
2245
+ }[archivedFilter]
2276
2246
  ],
2277
2247
  onSelect: (id) => {
2278
2248
  if (id === "workspace" || id === "workspace-tree" || id === "flat") onGroupPick(id);
2279
2249
  else if (id === "manual" || id === "updated") onOrderPick(id);
2280
- else if (id === "show-archived") onArchivedFilterPick(archivedFilter === "show" ? "default" : "show");
2281
- else if (id === "only-archived") onArchivedFilterPick(archivedFilter === "only" ? "default" : "only");
2250
+ else if (id === "hide-archived") onArchivedFilterPick("default");
2251
+ else if (id === "show-archived") onArchivedFilterPick("show");
2252
+ else if (id === "only-archived") onArchivedFilterPick("only");
2282
2253
  setOpen(false);
2283
2254
  },
2284
2255
  align: "end",
@@ -2320,8 +2291,26 @@ window.__ModuleLoader__.load({
2320
2291
  const rect = e.currentTarget.getBoundingClientRect();
2321
2292
  return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
2322
2293
  }
2294
+ /** The list-empty placeholder — a glyph over the text; the archived-only view names its filter and offers the way back. */
2295
+ function EmptySessions({ rowState, onLeaveArchivedOnly, t }) {
2296
+ const archivedOnly = rowState.archivedFilter === "only";
2297
+ return (0, react_jsx_runtime.jsxs)("div", {
2298
+ className: WorkspaceBrowser_module_css_default.emptyState,
2299
+ "data-row-key": "empty",
2300
+ children: [
2301
+ archivedOnly ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: 24 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, { size: 24 }),
2302
+ (0, react_jsx_runtime.jsx)("div", { children: archivedOnly ? t("empty.noneArchived") : t("empty.none") }),
2303
+ archivedOnly && (0, react_jsx_runtime.jsx)("button", {
2304
+ type: "button",
2305
+ className: WorkspaceBrowser_module_css_default.emptyAction,
2306
+ onClick: onLeaveArchivedOnly,
2307
+ children: t("empty.viewOthers")
2308
+ })
2309
+ ]
2310
+ });
2311
+ }
2323
2312
  /** The scrolling session tree; unmounting drops the sessions subscription and local row limits. */
2324
- function SessionTree({ list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds, rowState, workspaceReady, animationResetKey, usePanelInfo, onRenameRequest, onDeleteRequest, onSessionRenameRequest, renderSlot, insertWorkspaceBefore, nestWorkspaces, groupExpansion, setGroupExpanded, setSessionOrder, home, t, revealSessionId, onSessionRevealed }) {
2313
+ function SessionTree({ list, useSessionStatus, startSession, open, workspaces, ungroupedSessionIds, rowState, onLeaveArchivedOnly, workspaceReady, animationResetKey, usePanelInfo, onRenameRequest, onDeleteRequest, onSessionRenameRequest, renderSlot, insertWorkspaceBefore, nestWorkspaces, groupExpansion, setGroupExpanded, setSessionOrder, home, t, revealSessionId, onSessionRevealed, shortcuts }) {
2325
2314
  const panelActive = usePanelInfo((info) => info.activePanelId !== null);
2326
2315
  const statuses = useSessionStatus((s) => s);
2327
2316
  const current = panelActive ? void 0 : Object.values(list.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
@@ -2430,9 +2419,11 @@ window.__ModuleLoader__.load({
2430
2419
  });
2431
2420
  };
2432
2421
  const childrenByParent = (0, react.useMemo)(() => {
2422
+ const rendered = new Set(groups.map((group) => group.key));
2433
2423
  const children = /* @__PURE__ */ new Map();
2434
2424
  for (const group of groups) {
2435
- const parent = parents.get(group.key);
2425
+ let parent = parents.get(group.key);
2426
+ while (parent !== void 0 && !rendered.has(parent)) parent = parents.get(parent);
2436
2427
  const siblings = children.get(parent);
2437
2428
  if (siblings === void 0) children.set(parent, [group]);
2438
2429
  else siblings.push(group);
@@ -2513,6 +2504,7 @@ window.__ModuleLoader__.load({
2513
2504
  },
2514
2505
  children: [
2515
2506
  (0, react_jsx_runtime.jsx)(ProjectRowItem, {
2507
+ newShortcut: shortcuts.find((row) => row.id === "session.new"),
2516
2508
  group,
2517
2509
  containsCurrentDescendant: currentAncestors.has(group.key),
2518
2510
  home,
@@ -2630,10 +2622,10 @@ window.__ModuleLoader__.load({
2630
2622
  rowKeys,
2631
2623
  ready: list.phase === "ready" && workspaceReady && !nativeDragActive,
2632
2624
  resetKey: JSON.stringify([animationResetKey, sessionLimits]),
2633
- children: [groups.length === 0 && (0, react_jsx_runtime.jsx)("div", {
2634
- className: WorkspaceBrowser_module_css_default.empty,
2635
- "data-row-key": "empty",
2636
- children: t("empty.none")
2625
+ children: [groups.length === 0 && (0, react_jsx_runtime.jsx)(EmptySessions, {
2626
+ rowState,
2627
+ onLeaveArchivedOnly,
2628
+ t
2637
2629
  }), groupRows]
2638
2630
  }),
2639
2631
  (0, react_jsx_runtime.jsx)("span", { className: WorkspaceBrowser_module_css_default.fade })
@@ -2641,7 +2633,7 @@ window.__ModuleLoader__.load({
2641
2633
  });
2642
2634
  }
2643
2635
  /** The flat "In one list" body: every session is one draggable top-level row. */
2644
- function FlatList({ list, sessionIds, rowState, useSessionStatus, open, onSessionRenameRequest, renderSlot, usePanelInfo, setSessionOrder, workspaceReady, animationResetKey, revealSessionId, onSessionRevealed, t }) {
2636
+ function FlatList({ list, sessionIds, rowState, onLeaveArchivedOnly, useSessionStatus, open, onSessionRenameRequest, usePanelInfo, setSessionOrder, workspaceReady, animationResetKey, revealSessionId, onSessionRevealed, renderSlot, t }) {
2645
2637
  const panelActive = usePanelInfo((info) => info.activePanelId !== null);
2646
2638
  const statuses = useSessionStatus((s) => s);
2647
2639
  const rows = (0, react.useMemo)(() => deriveFlat(list, sessionIds, rowState, statuses), [
@@ -2670,10 +2662,10 @@ window.__ModuleLoader__.load({
2670
2662
  rowKeys: rows.length === 0 ? ["empty"] : rows.map((row) => `session:${row.id}`),
2671
2663
  ready: list.phase === "ready" && workspaceReady && drag === null,
2672
2664
  resetKey: animationResetKey,
2673
- children: [rows.length === 0 && (0, react_jsx_runtime.jsx)("div", {
2674
- className: WorkspaceBrowser_module_css_default.empty,
2675
- "data-row-key": "empty",
2676
- children: t("empty.none")
2665
+ children: [rows.length === 0 && (0, react_jsx_runtime.jsx)(EmptySessions, {
2666
+ rowState,
2667
+ onLeaveArchivedOnly,
2668
+ t
2677
2669
  }), rows.map((node) => {
2678
2670
  const active = drag !== null && drag.pinned === node.pinned;
2679
2671
  const normalizeHalf = (half) => node.blank ? "after" : half;
@@ -2687,7 +2679,6 @@ window.__ModuleLoader__.load({
2687
2679
  onReveal: node.id === revealSessionId ? () => {
2688
2680
  onSessionRevealed(node.id);
2689
2681
  } : void 0,
2690
- flat: true,
2691
2682
  drag: {
2692
2683
  start: () => {
2693
2684
  dropCommitted.current = false;
@@ -2796,10 +2787,19 @@ window.__ModuleLoader__.load({
2796
2787
  * @param props - composed slot props (shell owner share + store + injected actions).
2797
2788
  * @returns the region element tree.
2798
2789
  */
2799
- function WorkspaceBrowser({ wide, usePanelInfo, expandSidebar, useSessions, useSessionStatus, useWorkspaces, useStore, actions, startSession, open, requestSessionRename, notifyArchivedNotOpenable, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, unarchiveSession, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostInfo, renderSlot, t }) {
2790
+ function WorkspaceBrowser({ wide, usePanelInfo, expandSidebar, useSessions, useSessionStatus, useWorkspaces, useStore, actions, startSession, open, requestSessionRename, notifyArchivedNotOpenable, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, unarchiveSession, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, useHostInfo, useShortcuts, useWorkspaceShortcuts, requestSearch, requestAddWorkspace, closeAddWorkspace, setDirectoryBusy, dismissForkError, renderSlot, t }) {
2800
2791
  const home = useHostInfo((info) => info.home);
2792
+ const shortcuts = useShortcuts((rows) => rows);
2793
+ const searchShortcut = shortcuts.find((row) => row.id === "session.search");
2794
+ const addShortcut = shortcuts.find((row) => row.id === "workspace.add");
2795
+ const shortcutState = useWorkspaceShortcuts((state) => state);
2801
2796
  const list = useSessions((state) => state);
2802
- const workspaces = useWorkspaces((state) => state.items);
2797
+ const storedWorkspaces = useWorkspaces((state) => state.items);
2798
+ const defaultWorkspaceName = t("workspace.defaultName");
2799
+ const workspaces = (0, react.useMemo)(() => storedWorkspaces.map((workspace) => ({
2800
+ ...workspace,
2801
+ title: workspaceDisplayTitle(workspace.title, defaultWorkspaceName)
2802
+ })), [storedWorkspaces, defaultWorkspaceName]);
2803
2803
  const workspacePhase = useWorkspaces((state) => state.phase);
2804
2804
  const workspaceStreamState = useWorkspaces((state) => state.state);
2805
2805
  const archivedSessionIds = useWorkspaces((state) => state.archivedSessionIds);
@@ -2817,6 +2817,9 @@ window.__ModuleLoader__.load({
2817
2817
  }
2818
2818
  open(sessionId);
2819
2819
  };
2820
+ const leaveArchivedOnly = () => {
2821
+ actions.setArchivedFilter("default");
2822
+ };
2820
2823
  const workspaceReady = workspacePhase === "ready" && workspaceStreamState !== "loading";
2821
2824
  const mainSessionId = Object.values(list.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
2822
2825
  const currentBlank = mainSessionId !== void 0 && list.byId[mainSessionId]?.blank === true ? mainSessionId : void 0;
@@ -2936,7 +2939,7 @@ window.__ModuleLoader__.load({
2936
2939
  });
2937
2940
  const searchRoot = (0, react.useRef)(null);
2938
2941
  const searchInput = (0, react.useRef)(null);
2939
- const [wsPickerOpen, setWsPickerOpen] = (0, react.useState)(false);
2942
+ const wsPickerOpen = shortcutState.addRequested;
2940
2943
  const wsPlusRef = (0, react.useRef)(null);
2941
2944
  const composingRef = (0, react.useRef)(false);
2942
2945
  const openSearchResult = (sessionId) => {
@@ -2967,6 +2970,15 @@ window.__ModuleLoader__.load({
2967
2970
  };
2968
2971
  }
2969
2972
  }, [wide, searchOnExpand]);
2973
+ (0, react.useEffect)(() => {
2974
+ if (shortcutState.searchRequest === 0) return;
2975
+ closeAddWorkspace();
2976
+ setSearchExpanded(true);
2977
+ if (!wide) {
2978
+ setSearchOnExpand(true);
2979
+ expandSidebar();
2980
+ } else searchInput.current?.focus({ preventScroll: true });
2981
+ }, [shortcutState.searchRequest]);
2970
2982
  (0, react.useEffect)(() => {
2971
2983
  if (!wide || !searchExpanded || searchOnExpand) return;
2972
2984
  searchInput.current?.focus({ preventScroll: true });
@@ -3039,8 +3051,8 @@ window.__ModuleLoader__.load({
3039
3051
  const [renaming, setRenaming] = (0, react.useState)(false);
3040
3052
  const [renameError, setRenameError] = (0, react.useState)(null);
3041
3053
  const renameTrimmed = renameDraft.trim();
3042
- const renameDuplicate = renameTarget !== null && renameTrimmed !== "" && renameTrimmed !== renameTarget.currentTitle && workspaces.some((w) => w.title === renameTrimmed);
3043
- const renameBlocked = renaming || renameTrimmed === "" || renameTarget === null || renameTrimmed === renameTarget.currentTitle || renameDuplicate;
3054
+ const renameDuplicate = renameTarget !== null && renameTrimmed !== "" && workspaces.some((w) => w.workspaceId !== renameTarget.workspaceId && w.title === renameTrimmed);
3055
+ const renameBlocked = renaming || renameTrimmed === "" || renameTarget === null || renameTrimmed === renameTarget.storedTitle || renameDuplicate;
3044
3056
  const closeRename = () => {
3045
3057
  if (renaming) return;
3046
3058
  setRenameTarget(null);
@@ -3107,13 +3119,14 @@ window.__ModuleLoader__.load({
3107
3119
  ref: searchRoot,
3108
3120
  className: clsx(WorkspaceBrowser_module_css_default.search, searchExpanded && WorkspaceBrowser_module_css_default.searchExpanded),
3109
3121
  onClick: () => {
3110
- setWsPickerOpen(false);
3122
+ closeAddWorkspace();
3111
3123
  setSearchExpanded(true);
3112
3124
  searchInput.current?.focus();
3113
3125
  },
3114
3126
  children: [
3115
3127
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
3116
3128
  label: t("search"),
3129
+ shortcutKeys: searchShortcut?.keys,
3117
3130
  side: "bottom",
3118
3131
  delayMs: 500,
3119
3132
  disabled: searchExpanded,
@@ -3121,10 +3134,10 @@ window.__ModuleLoader__.load({
3121
3134
  type: "button",
3122
3135
  className: WorkspaceBrowser_module_css_default.searchButton,
3123
3136
  "aria-label": t("search.sessions.aria"),
3137
+ "aria-keyshortcuts": searchShortcut?.aria,
3124
3138
  "aria-expanded": searchExpanded,
3125
3139
  onClick: () => {
3126
- setWsPickerOpen(false);
3127
- setSearchExpanded(true);
3140
+ requestSearch();
3128
3141
  },
3129
3142
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: searchExpanded ? 11 : 14 })
3130
3143
  })
@@ -3174,6 +3187,7 @@ window.__ModuleLoader__.load({
3174
3187
  t
3175
3188
  }), directoryFlowAvailable && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
3176
3189
  label: t("workspace.add"),
3190
+ shortcutKeys: addShortcut?.keys,
3177
3191
  side: "bottom",
3178
3192
  delayMs: 500,
3179
3193
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -3181,8 +3195,9 @@ window.__ModuleLoader__.load({
3181
3195
  type: "button",
3182
3196
  className: WorkspaceBrowser_module_css_default.iconButton,
3183
3197
  "aria-label": t("workspace.add"),
3198
+ "aria-keyshortcuts": addShortcut?.aria,
3184
3199
  onClick: () => {
3185
- setWsPickerOpen((v) => !v);
3200
+ requestAddWorkspace();
3186
3201
  },
3187
3202
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconProjectAddOutlineRegular, { size: wide ? 16 : 18 })
3188
3203
  })
@@ -3197,13 +3212,14 @@ window.__ModuleLoader__.load({
3197
3212
  useDirectoryFlow,
3198
3213
  renderDirectoryFlow: (owner) => renderSlot("sidebar.workspaces.directoryFlow", owner),
3199
3214
  addOnly: true,
3215
+ onBusyChange: setDirectoryBusy,
3200
3216
  side: "right",
3201
3217
  onPick: (workspaceId) => {
3202
- setWsPickerOpen(false);
3218
+ closeAddWorkspace();
3203
3219
  startSession(workspaceId);
3204
3220
  },
3205
3221
  onClose: () => {
3206
- setWsPickerOpen(false);
3222
+ closeAddWorkspace();
3207
3223
  }
3208
3224
  })
3209
3225
  ]
@@ -3212,14 +3228,14 @@ window.__ModuleLoader__.load({
3212
3228
  className: WorkspaceBrowser_module_css_default.search,
3213
3229
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
3214
3230
  label: t("search"),
3231
+ shortcutKeys: searchShortcut?.keys,
3215
3232
  children: (0, react_jsx_runtime.jsx)("button", {
3216
3233
  type: "button",
3217
3234
  className: WorkspaceBrowser_module_css_default.searchButton,
3218
3235
  "aria-label": t("search.sessions.aria"),
3236
+ "aria-keyshortcuts": searchShortcut?.aria,
3219
3237
  onClick: () => {
3220
- setSearchExpanded(true);
3221
- setSearchOnExpand(true);
3222
- expandSidebar();
3238
+ requestSearch();
3223
3239
  },
3224
3240
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: 18 })
3225
3241
  })
@@ -3245,6 +3261,7 @@ window.__ModuleLoader__.load({
3245
3261
  list,
3246
3262
  sessionIds: orderedFlatSessionIds,
3247
3263
  rowState,
3264
+ onLeaveArchivedOnly: leaveArchivedOnly,
3248
3265
  workspaceReady,
3249
3266
  animationResetKey: `${groupBy}/${orderBy}/${archivedFilter}`,
3250
3267
  useSessionStatus,
@@ -3258,6 +3275,7 @@ window.__ModuleLoader__.load({
3258
3275
  }) : (0, react_jsx_runtime.jsx)(SessionTree, {
3259
3276
  usePanelInfo,
3260
3277
  list,
3278
+ shortcuts,
3261
3279
  useSessionStatus,
3262
3280
  onSessionRenameRequest: requestSessionRename,
3263
3281
  renderSlot,
@@ -3270,6 +3288,7 @@ window.__ModuleLoader__.load({
3270
3288
  setGroupExpanded: actions.setGroupExpanded,
3271
3289
  setSessionOrder: saveSessionOrder,
3272
3290
  rowState,
3291
+ onLeaveArchivedOnly: leaveArchivedOnly,
3273
3292
  startSession,
3274
3293
  open: guardedOpen,
3275
3294
  insertWorkspaceBefore,
@@ -3277,12 +3296,12 @@ window.__ModuleLoader__.load({
3277
3296
  onSessionRevealed: acknowledgeSessionReveal,
3278
3297
  home,
3279
3298
  t,
3280
- onRenameRequest: (workspaceId, currentTitle) => {
3299
+ onRenameRequest: (workspaceId, displayTitle) => {
3281
3300
  setRenameTarget({
3282
3301
  workspaceId,
3283
- currentTitle
3302
+ storedTitle: storedWorkspaces.find((w) => w.workspaceId === workspaceId)?.title ?? displayTitle
3284
3303
  });
3285
- setRenameDraft(currentTitle);
3304
+ setRenameDraft(displayTitle);
3286
3305
  setRenameError(null);
3287
3306
  },
3288
3307
  onDeleteRequest: (workspaceId, title) => {
@@ -3315,7 +3334,7 @@ window.__ModuleLoader__.load({
3315
3334
  className: WorkspaceBrowser_module_css_default.renameInput,
3316
3335
  value: renameDraft,
3317
3336
  "aria-label": t("field.workspaceName"),
3318
- autoFocus: true,
3337
+ "data-modal-autofocus": true,
3319
3338
  disabled: renaming,
3320
3339
  onFocus: (e) => {
3321
3340
  e.target.select();
@@ -3376,7 +3395,11 @@ window.__ModuleLoader__.load({
3376
3395
  role: "alert",
3377
3396
  children: deleteError
3378
3397
  })]
3379
- })
3398
+ }),
3399
+ shortcutState.forkError !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
3400
+ text: t(shortcutState.forkError.reason === "unavailable" ? "shortcut.noCompletedTurn" : "shortcut.forkFailed"),
3401
+ onDone: dismissForkError
3402
+ }, shortcutState.forkError.seq)
3380
3403
  ]
3381
3404
  });
3382
3405
  }
@@ -3395,10 +3418,12 @@ window.__ModuleLoader__.load({
3395
3418
  * @param props - owner share, the archive share, and the menu open state.
3396
3419
  * @returns the row.
3397
3420
  */
3398
- function ArchiveSessionMenuItem({ sessionId, useArchived, useMenuOpenState, archiveSession, unarchiveSession, t }) {
3421
+ function ArchiveSessionMenuItem({ sessionId, useArchived, useMenuOpenState, useShortcuts, archiveSession, unarchiveSession, t }) {
3399
3422
  const [, setMenuOpen] = useMenuOpenState();
3423
+ const shortcut = useShortcuts((rows) => rows.find((row) => row.id === "session.archive"));
3400
3424
  const archived = useArchived((set) => set.has(sessionId));
3401
3425
  return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
3426
+ shortcut: archived ? void 0 : shortcut,
3402
3427
  icon: archived ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUnarchiveOutlineRegular, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutlineRegular, { size: 14 }),
3403
3428
  onSelect: () => {
3404
3429
  setMenuOpen(false);
@@ -3568,9 +3593,10 @@ window.__ModuleLoader__.load({
3568
3593
  * @param props - owner share, menu open state, and the fork share.
3569
3594
  * @returns the row.
3570
3595
  */
3571
- function ForkSessionMenuItem({ sessionId, useMenuOpenState, forkSession, t }) {
3596
+ function ForkSessionMenuItem({ sessionId, useMenuOpenState, useShortcuts, forkSession, t }) {
3572
3597
  const [, setMenuOpen] = useMenuOpenState();
3573
3598
  return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
3599
+ shortcut: useShortcuts((rows) => rows.find((row) => row.id === "session.fork")),
3574
3600
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, {}),
3575
3601
  onSelect: () => {
3576
3602
  setMenuOpen(false);
@@ -3653,9 +3679,10 @@ window.__ModuleLoader__.load({
3653
3679
  * @param props - owner share, menu open state, and the rename share.
3654
3680
  * @returns the row.
3655
3681
  */
3656
- function RenameSessionMenuItem({ sessionId, displayTitle, useMenuOpenState, requestSessionRename, t }) {
3682
+ function RenameSessionMenuItem({ sessionId, displayTitle, useMenuOpenState, useShortcuts, requestSessionRename, t }) {
3657
3683
  const [, setMenuOpen] = useMenuOpenState();
3658
3684
  return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MenuItemButton, {
3685
+ shortcut: useShortcuts((rows) => rows.find((row) => row.id === "session.rename")),
3659
3686
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, {}),
3660
3687
  onSelect: () => {
3661
3688
  setMenuOpen(false);
@@ -3727,7 +3754,7 @@ window.__ModuleLoader__.load({
3727
3754
  className: WorkspaceBrowser_module_css_default.renameInput,
3728
3755
  value: draft,
3729
3756
  "aria-label": t("field.sessionName"),
3730
- autoFocus: true,
3757
+ "data-modal-autofocus": true,
3731
3758
  disabled: renaming,
3732
3759
  onFocus: (e) => {
3733
3760
  e.target.select();
@@ -3769,14 +3796,16 @@ window.__ModuleLoader__.load({
3769
3796
  const LONG_TOAST_HOLD_MS = 6e3;
3770
3797
  /**
3771
3798
  * Render the current notice: the archived and stopped-and-archived notices
3772
- * with their undo and show-archived actions on a 6 s hold, a refused Session
3773
- * creation with the Host's reason on the same hold, or a plain warning for a
3774
- * failed pin, an archived row that was clicked, or default Workspace creation.
3775
- * @param props - the notice hook, its dismissal, the two archived-notice actions, and the locale seat.
3799
+ * with their undo action — plus the show-archived action while archived rows
3800
+ * are hidden — on a 6 s hold, a refused Session creation with the Host's
3801
+ * reason on the same hold, or a plain warning for a failed pin, an archived
3802
+ * row that was clicked, or default Workspace creation.
3803
+ * @param props - the notice hook, the shared viewing store, the notice dismissal, the two archived-notice actions, and the locale seat.
3776
3804
  * @returns the notice on display, or null.
3777
3805
  */
3778
- function RowActionToast({ useToast, dismissToast, undoArchive, showArchived, t }) {
3806
+ function RowActionToast({ useToast, useStore, dismissToast, undoArchive, showArchived, t }) {
3779
3807
  const toast = useToast((current) => current);
3808
+ const archivedRowsVisible = useStore((state) => (state.archivedFilter ?? "default") !== "default");
3780
3809
  if (toast === null) return null;
3781
3810
  if (toast.kind === "archived" || toast.kind === "stoppedAndArchived") {
3782
3811
  const { sessionId } = toast;
@@ -3790,14 +3819,14 @@ window.__ModuleLoader__.load({
3790
3819
  dismissToast();
3791
3820
  undoArchive(sessionId);
3792
3821
  }
3793
- }, {
3822
+ }, ...archivedRowsVisible ? [] : [{
3794
3823
  prefix: t("toast.archivedOr"),
3795
3824
  label: t("toast.archivedFilter"),
3796
3825
  onClick: () => {
3797
3826
  dismissToast();
3798
3827
  showArchived();
3799
3828
  }
3800
- }],
3829
+ }]],
3801
3830
  onDone: dismissToast
3802
3831
  }, `toast-${String(toast.seq)}`);
3803
3832
  }
@@ -3825,6 +3854,241 @@ window.__ModuleLoader__.load({
3825
3854
  }
3826
3855
  }
3827
3856
  //#endregion
3857
+ //#region lib/types/client/locales.js
3858
+ /**
3859
+ * `workspace` namespace dictionaries: the browsing region (section header,
3860
+ * search, tree rows, dialogs) and the pick/add flow. Runtime failure
3861
+ * messages (wire error strings) pass through untranslated by policy.
3862
+ */
3863
+ /** Simplified Chinese dictionary (the key-set source of truth). */
3864
+ const zh = {
3865
+ "defaultWorkspace.failed": "无法创建默认工作区,请通过“选择工作区”选择文件夹",
3866
+ "group.ungrouped": "未分组",
3867
+ "session.new": "新会话",
3868
+ "shortcut.noSession": "请先选择一个会话",
3869
+ "shortcut.noPicker": "目录选择器不可用",
3870
+ "shortcut.directoryBusy": "正在选择或添加工作区",
3871
+ "shortcut.noCompletedTurn": "当前会话没有已结束的轮次",
3872
+ "shortcut.forkFailed": "无法分叉会话,请重试",
3873
+ "section.workspaces": "工作区",
3874
+ "section.sessions": "会话",
3875
+ "viewOptions.label": "视图选项",
3876
+ "groupBy.label": "分组方式",
3877
+ "groupBy.workspace": "按工作区",
3878
+ "groupBy.workspaceTree": "按工作区树",
3879
+ "groupBy.flat": "单列表",
3880
+ "orderBy.label": "排序方式",
3881
+ "orderBy.manual": "手动排序",
3882
+ "orderBy.updated": "最近更新",
3883
+ "filterBy.label": "筛选会话",
3884
+ "viewOptions.hideArchived": "隐藏已归档",
3885
+ "viewOptions.showArchived": "全部对话(显示已归档)",
3886
+ "viewOptions.onlyArchived": "仅显示已归档",
3887
+ "sessions.expand": "展开其余 {n} 个会话",
3888
+ "sessions.collapse": "收起",
3889
+ "empty.none": "暂无会话",
3890
+ "empty.noneArchived": "暂无已归档会话",
3891
+ "empty.viewOthers": "查看其他会话",
3892
+ "empty.noMatches": "无匹配结果",
3893
+ "workspace.add": "添加工作区",
3894
+ "search.sessions.aria": "搜索会话",
3895
+ "search.placeholder": "搜索会话名称",
3896
+ "search.clear": "清除搜索",
3897
+ "search.results.aria": "搜索结果",
3898
+ "search.pending": "正在搜索会话历史…",
3899
+ "search.noMatches": "无匹配会话",
3900
+ "search.hasMore": "仅显示前 {n} 条结果,请缩小搜索范围。",
3901
+ "menu.addWorkspace": "添加工作区…",
3902
+ "picker.loading": "正在加载工作区…",
3903
+ "conflict.named": "已存在名为“{name}”的工作区。",
3904
+ "folderError.title": "无法打开文件夹",
3905
+ "folderError.retry": "重新选择",
3906
+ "rename": "重命名",
3907
+ "rename.workspace.title": "重命名工作区",
3908
+ "rename.session.title": "重命名会话",
3909
+ "field.workspaceName": "工作区名称",
3910
+ "field.sessionName": "会话名称",
3911
+ "delete.workspace": "删除工作区",
3912
+ "delete.desc": "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",
3913
+ "delete.pending": "正在删除工作区…",
3914
+ "menu.fork": "分叉会话",
3915
+ "menu.archiveSession": "归档会话",
3916
+ "menu.unarchiveSession": "取消归档",
3917
+ "menu.pinSession": "置顶会话",
3918
+ "menu.unpinSession": "取消置顶",
3919
+ "row.archived": "已归档",
3920
+ "row.pinned": "已置顶",
3921
+ "toast.archivedNotOpenable": "已归档对话暂时无法查看,请取消归档后查看",
3922
+ "toast.archived": "会话已归档,可",
3923
+ "toast.stoppedAndArchived": "已停止并归档,可",
3924
+ "archive.confirm.title": "停止并归档此会话?",
3925
+ "archive.confirm.desc": "“{title}”仍有正在进行的工作。归档会先停止这些工作;之后可在侧栏筛选“全部对话(显示已归档)”中恢复会话,被停止的工作不会自动继续。",
3926
+ "archive.confirm.activity": "将被停止的工作",
3927
+ "archive.confirm.turn": "进行中的回合",
3928
+ "archive.confirm.subagents.one": "{n} 个运行中的子智能体:{names}",
3929
+ "archive.confirm.subagents.other": "{n} 个运行中的子智能体:{names}",
3930
+ "archive.confirm.jobs.one": "{n} 个后台任务:{names}",
3931
+ "archive.confirm.jobs.other": "{n} 个后台任务:{names}",
3932
+ "archive.confirm.schedules.one": "{n} 条定时提醒:{names}",
3933
+ "archive.confirm.schedules.other": "{n} 条定时提醒:{names}",
3934
+ "archive.confirm.other.one": "{n} 项其他工作({kind})",
3935
+ "archive.confirm.other.other": "{n} 项其他工作({kind})",
3936
+ "archive.confirm.listSeparator": "、",
3937
+ "archive.confirm.action": "停止并归档",
3938
+ "archive.confirm.pending": "正在停止并归档…",
3939
+ "toast.archivedUndo": "撤销",
3940
+ "toast.archivedOr": "或",
3941
+ "toast.archivedFilter": "筛选已归档会话",
3942
+ "toast.pinFailed": "置顶失败,请稍后重试",
3943
+ "toast.unpinFailed": "取消置顶失败,请稍后重试",
3944
+ "toast.createFailed": "新建会话失败:{message}",
3945
+ "sessions.count.one": "{n} 个会话",
3946
+ "sessions.count.other": "{n} 个会话",
3947
+ "actions.workspace.aria": "工作区“{name}”的操作",
3948
+ "actions.session.aria": "会话“{name}”的操作",
3949
+ "actions.archive": "归档会话",
3950
+ "actions.unarchive": "取消归档",
3951
+ "actions.pin": "置顶会话",
3952
+ "actions.unpin": "取消置顶",
3953
+ "actions.newSession": "新会话",
3954
+ "actions.newSession.aria": "在“{name}”中新建会话",
3955
+ "status.running": "进行中",
3956
+ "status.subagentsRunning.one": "{n} 个子智能体运行中",
3957
+ "status.subagentsRunning.other": "{n} 个子智能体运行中",
3958
+ "status.idle": "空闲",
3959
+ "status.waitingApproval": "等待审批",
3960
+ "status.planReview": "计划待审",
3961
+ "status.waitingAnswer": "等待回答",
3962
+ "status.compact.approval": "待审批",
3963
+ "status.compact.planReview": "计划待审",
3964
+ "status.compact.answer": "待回答",
3965
+ "status.completed": "已完成",
3966
+ "hover.created": "创建于 {time}",
3967
+ "hover.copied": "已复制",
3968
+ "date.ymd": "{y}年{m}月{d}日",
3969
+ "time.now": "刚刚",
3970
+ "time.minutes": "{n}分钟",
3971
+ "time.hours": "{n}小时",
3972
+ "time.days": "{n}天",
3973
+ "time.months": "{n}个月",
3974
+ "time.years": "{n}年",
3975
+ "time.ago": "{t}前"
3976
+ };
3977
+ /** English dictionary, checked complete against the zh key set. */
3978
+ const en = {
3979
+ "defaultWorkspace.failed": "Unable to create default workspace. Use Choose workspace to select a folder.",
3980
+ "group.ungrouped": "Ungrouped",
3981
+ "session.new": "New Session",
3982
+ "shortcut.noSession": "Select a session first",
3983
+ "shortcut.noPicker": "Directory picker unavailable",
3984
+ "shortcut.directoryBusy": "Selecting or adding a workspace",
3985
+ "shortcut.noCompletedTurn": "This session has no completed turn",
3986
+ "shortcut.forkFailed": "Could not fork the session. Try again.",
3987
+ "section.workspaces": "Workspaces",
3988
+ "section.sessions": "Sessions",
3989
+ "viewOptions.label": "View options",
3990
+ "groupBy.label": "Group by",
3991
+ "groupBy.workspace": "WorkSpace",
3992
+ "groupBy.workspaceTree": "Workspace Tree",
3993
+ "groupBy.flat": "In one list",
3994
+ "orderBy.label": "Order by",
3995
+ "orderBy.manual": "Manual",
3996
+ "orderBy.updated": "Last updated",
3997
+ "filterBy.label": "Filter sessions",
3998
+ "viewOptions.hideArchived": "Hide archived",
3999
+ "viewOptions.showArchived": "All conversations (show archived)",
4000
+ "viewOptions.onlyArchived": "Archived only",
4001
+ "sessions.expand": "Show {n} more sessions",
4002
+ "sessions.collapse": "Show less",
4003
+ "empty.none": "No sessions yet",
4004
+ "empty.noneArchived": "No archived sessions yet",
4005
+ "empty.viewOthers": "View other sessions",
4006
+ "empty.noMatches": "No matches",
4007
+ "workspace.add": "Add workspace",
4008
+ "search.sessions.aria": "Search sessions",
4009
+ "search.placeholder": "Search session names",
4010
+ "search.clear": "Clear search",
4011
+ "search.results.aria": "Search results",
4012
+ "search.pending": "Searching session history…",
4013
+ "search.noMatches": "No matching sessions",
4014
+ "search.hasMore": "Showing the first {n} results. Narrow your search.",
4015
+ "menu.addWorkspace": "Add workspace…",
4016
+ "picker.loading": "Loading workspaces…",
4017
+ "conflict.named": "A workspace named “{name}” already exists.",
4018
+ "folderError.title": "Couldn’t open folder",
4019
+ "folderError.retry": "Choose again",
4020
+ "rename": "Rename",
4021
+ "rename.workspace.title": "Rename workspace",
4022
+ "rename.session.title": "Rename session",
4023
+ "field.workspaceName": "Workspace name",
4024
+ "field.sessionName": "Session name",
4025
+ "delete.workspace": "Delete workspace",
4026
+ "delete.desc": "This removes “{name}” from the workspace list. The folder and session logs will be kept. Its sessions will appear under Ungrouped.",
4027
+ "delete.pending": "Deleting workspace…",
4028
+ "menu.fork": "Fork session",
4029
+ "menu.archiveSession": "Archive session",
4030
+ "menu.unarchiveSession": "Unarchive session",
4031
+ "menu.pinSession": "Pin session",
4032
+ "menu.unpinSession": "Unpin session",
4033
+ "row.archived": "Archived",
4034
+ "row.pinned": "Pinned",
4035
+ "toast.archivedNotOpenable": "Archived sessions cannot be opened. Unarchive it to view.",
4036
+ "toast.archived": "Session archived. You can ",
4037
+ "toast.stoppedAndArchived": "Session stopped and archived. You can ",
4038
+ "archive.confirm.title": "Stop and archive this session?",
4039
+ "archive.confirm.desc": "“{title}” still has work in progress. Archiving stops it first; you can restore the session later from the “All conversations (show archived)” filter in the sidebar, and the stopped work will not resume on its own.",
4040
+ "archive.confirm.activity": "Work that will be stopped",
4041
+ "archive.confirm.turn": "The turn in progress",
4042
+ "archive.confirm.subagents.one": "{n} running subagent: {names}",
4043
+ "archive.confirm.subagents.other": "{n} running subagents: {names}",
4044
+ "archive.confirm.jobs.one": "{n} background job: {names}",
4045
+ "archive.confirm.jobs.other": "{n} background jobs: {names}",
4046
+ "archive.confirm.schedules.one": "{n} scheduled reminder: {names}",
4047
+ "archive.confirm.schedules.other": "{n} scheduled reminders: {names}",
4048
+ "archive.confirm.other.one": "{n} other item of work ({kind})",
4049
+ "archive.confirm.other.other": "{n} other items of work ({kind})",
4050
+ "archive.confirm.listSeparator": ", ",
4051
+ "archive.confirm.action": "Stop and archive",
4052
+ "archive.confirm.pending": "Stopping and archiving…",
4053
+ "toast.archivedUndo": "undo",
4054
+ "toast.archivedOr": " or ",
4055
+ "toast.archivedFilter": "filter archived sessions",
4056
+ "toast.pinFailed": "Pin failed. Try again later.",
4057
+ "toast.unpinFailed": "Unpin failed. Try again later.",
4058
+ "toast.createFailed": "New session failed: {message}",
4059
+ "sessions.count.one": "{n} session",
4060
+ "sessions.count.other": "{n} sessions",
4061
+ "actions.workspace.aria": "Workspace actions for {name}",
4062
+ "actions.session.aria": "Session actions for {name}",
4063
+ "actions.archive": "Archive",
4064
+ "actions.unarchive": "Unarchive",
4065
+ "actions.pin": "Pin",
4066
+ "actions.unpin": "Unpin",
4067
+ "actions.newSession": "New session",
4068
+ "actions.newSession.aria": "New session in {name}",
4069
+ "status.running": "Running",
4070
+ "status.subagentsRunning.one": "{n} subagent running",
4071
+ "status.subagentsRunning.other": "{n} subagents running",
4072
+ "status.idle": "Idle",
4073
+ "status.waitingApproval": "Waiting for approval",
4074
+ "status.planReview": "Plan awaiting review",
4075
+ "status.waitingAnswer": "Waiting for answer",
4076
+ "status.compact.approval": "Approval",
4077
+ "status.compact.planReview": "Plan review",
4078
+ "status.compact.answer": "Answer",
4079
+ "status.completed": "Completed",
4080
+ "hover.created": "Created {time}",
4081
+ "hover.copied": "Copied",
4082
+ "date.ymd": "{y}-{m}-{d}",
4083
+ "time.now": "now",
4084
+ "time.minutes": "{n}min",
4085
+ "time.hours": "{n}h",
4086
+ "time.days": "{n}d",
4087
+ "time.months": "{n}mo",
4088
+ "time.years": "{n}y",
4089
+ "time.ago": "{t} ago"
4090
+ };
4091
+ //#endregion
3828
4092
  //#region lib/types/client/index.js
3829
4093
  /** Dictionary namespace owned by this plugin. */
3830
4094
  const NS = "workspace";
@@ -3843,7 +4107,8 @@ window.__ModuleLoader__.load({
3843
4107
  "locale",
3844
4108
  "remote",
3845
4109
  "remote.directoryPicker",
3846
- "layout"
4110
+ "layout",
4111
+ "shortcuts"
3847
4112
  ];
3848
4113
  /**
3849
4114
  * Register the browser and picker once their slot declarations are on the
@@ -3874,6 +4139,7 @@ window.__ModuleLoader__.load({
3874
4139
  zh,
3875
4140
  en
3876
4141
  }), "ui-workspace: dictionaries");
4142
+ const shortcutControls = createWorkspaceShortcutControls();
3877
4143
  const searchSessions = async (query, signal) => {
3878
4144
  const result = await sessions.search(query, signal);
3879
4145
  if (!result.ok) throw new Error(result.error.message);
@@ -3894,14 +4160,9 @@ window.__ModuleLoader__.load({
3894
4160
  };
3895
4161
  const pinnedSet = derive(workspaces.list, (snapshot) => new Set(snapshot.pinnedSessionIds));
3896
4162
  const archivedSet = derive(workspaces.list, (snapshot) => new Set(snapshot.archivedSessionIds));
3897
- const renameRequest = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(null);
4163
+ const renameRequest = derive(shortcutControls.state, (state) => state.renameTarget);
3898
4164
  const archiveRequest = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(null);
3899
- const requestSessionRename = (sessionId, currentTitle) => {
3900
- renameRequest.set({
3901
- sessionId,
3902
- currentTitle
3903
- });
3904
- };
4165
+ const requestSessionRename = shortcutControls.rename;
3905
4166
  const unarchiveSession = (sessionId) => {
3906
4167
  uiWorkspace.unarchiveSession(sessionId).catch((reason) => {
3907
4168
  console.warn("session unarchive rejected:", reason);
@@ -3951,6 +4212,7 @@ window.__ModuleLoader__.load({
3951
4212
  },
3952
4213
  unarchiveSession
3953
4214
  });
4215
+ installWorkspaceShortcuts(ctx, uiWorkspace, shortcutControls, archiveInjected().archiveSession);
3954
4216
  const archiveConfirmInjected = () => ({
3955
4217
  hooks: { archiveRequest },
3956
4218
  settleSessionArchive: () => {
@@ -3970,9 +4232,7 @@ window.__ModuleLoader__.load({
3970
4232
  const renameInjected = () => ({ requestSessionRename });
3971
4233
  const renameDialogInjected = () => ({
3972
4234
  hooks: { renameRequest },
3973
- settleSessionRename: () => {
3974
- renameRequest.set(null);
3975
- },
4235
+ settleSessionRename: shortcutControls.closeRename,
3976
4236
  renameSession
3977
4237
  });
3978
4238
  const rowToastInjected = () => ({
@@ -4009,9 +4269,16 @@ window.__ModuleLoader__.load({
4009
4269
  await uiWorkspace.unarchiveSession(sessionId);
4010
4270
  },
4011
4271
  createWorkspace: (input) => workspaces.create(input),
4272
+ requestSearch: shortcutControls.search,
4273
+ requestAddWorkspace: shortcutControls.add,
4274
+ closeAddWorkspace: shortcutControls.closeAdd,
4275
+ setDirectoryBusy: shortcutControls.directoryBusy,
4276
+ dismissForkError: shortcutControls.dismissForkError,
4012
4277
  hooks: {
4013
4278
  directoryFlow: browserFlowSource,
4014
- hostInfo
4279
+ hostInfo,
4280
+ workspaceShortcuts: shortcutControls.state,
4281
+ shortcuts: ctx.shortcuts.catalog
4015
4282
  }
4016
4283
  });
4017
4284
  const pickerInjected = () => ({
@@ -4028,11 +4295,22 @@ window.__ModuleLoader__.load({
4028
4295
  "sidebar.workspaces.session.menu.item": {
4029
4296
  kind: "list",
4030
4297
  scope: "root",
4031
- inject: { hooks: { menuOpenState: menuOpenStateFactory } }
4298
+ inject: { hooks: {
4299
+ menuOpenState: menuOpenStateFactory,
4300
+ shortcuts: ctx.shortcuts.catalog
4301
+ } }
4032
4302
  },
4033
4303
  "sidebar.workspaces.session.row.action": {
4034
4304
  kind: "list",
4035
4305
  scope: "root"
4306
+ },
4307
+ "sidebar.session.row.leading": {
4308
+ kind: "list",
4309
+ scope: "root"
4310
+ },
4311
+ "sidebar.session.row.hover": {
4312
+ kind: "list",
4313
+ scope: "root"
4036
4314
  }
4037
4315
  },
4038
4316
  store: viewStore,
@@ -4102,6 +4380,7 @@ window.__ModuleLoader__.load({
4102
4380
  name: "shell.overlay",
4103
4381
  id: "workspace.row-toast",
4104
4382
  locale: NS,
4383
+ store: viewStore,
4105
4384
  inject: rowToastInjected
4106
4385
  }, RowActionToast);
4107
4386
  });