@huanlin/dsh-plugin-ya-workspace-sidebar 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/lib/client.js +254 -86
- package/lib/client.js.map +1 -1
- package/lib/types/client/locales.d.ts +22 -2
- package/lib/types/client/model.d.ts +18 -2
- package/lib/types/client/settings.d.ts +20 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/package.json +38 -18
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://dshfind.com/zh/plugins/huanlinoto/dsh-plugin-ya-workspace-sidebar"><img src="https://dshfind.com/api/card/huanlinoto/dsh-plugin-ya-workspace-sidebar?lang=zh" alt="dsh-plugin-ya-workspace-sidebar card"></a>
|
|
3
|
+
</p>
|
|
4
4
|
|
|
5
5
|
# ya-workspace-sidebar
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session
|
|
11
|
+
DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session 二级菜单和面包屑导航;选中工作区的会话按本地日历日期分组(今天/昨天/更早),搜索、添加工作区、重命名、删除、Fork 与归档继续使用 DSH 原生 Host 能力。
|
|
12
12
|
|
|
13
13
|
## 运行
|
|
14
14
|
|
package/lib/client.js
CHANGED
|
@@ -15,7 +15,6 @@ window.__ModuleLoader__.load({
|
|
|
15
15
|
recent: "最近会话",
|
|
16
16
|
ungrouped: "未分组",
|
|
17
17
|
newSession: "新会话",
|
|
18
|
-
untitled: "未命名会话",
|
|
19
18
|
addWorkspace: "添加工作区",
|
|
20
19
|
addWorkspaceMenu: "添加工作区…",
|
|
21
20
|
search: "搜索会话",
|
|
@@ -34,6 +33,13 @@ window.__ModuleLoader__.load({
|
|
|
34
33
|
deleteDescription: "将把“{name}”从工作区列表中移除。文件夹与会话记录会保留。",
|
|
35
34
|
fork: "分叉会话",
|
|
36
35
|
archive: "归档会话",
|
|
36
|
+
archiveMode: "归档模式",
|
|
37
|
+
deleteMode: "删除模式",
|
|
38
|
+
deleteSession: "删除会话",
|
|
39
|
+
deleteSessionTitle: "删除会话",
|
|
40
|
+
deleteSessionConfirm: "确定要删除此会话吗?删除后将从列表中移除,此操作不可撤销。",
|
|
41
|
+
toggleActionMode: "切换归档/删除模式",
|
|
42
|
+
actionModeLabel: "会话操作",
|
|
37
43
|
cancel: "取消",
|
|
38
44
|
confirm: "确认",
|
|
39
45
|
retry: "重新选择",
|
|
@@ -51,7 +57,11 @@ window.__ModuleLoader__.load({
|
|
|
51
57
|
waiting: "等待交互",
|
|
52
58
|
completed: "已完成",
|
|
53
59
|
collapse: "折叠",
|
|
54
|
-
expand: "展开"
|
|
60
|
+
expand: "展开",
|
|
61
|
+
today: "今天",
|
|
62
|
+
yesterday: "昨天",
|
|
63
|
+
date: "{m}月{d}日",
|
|
64
|
+
dateYear: "{y}年{m}月{d}日"
|
|
55
65
|
};
|
|
56
66
|
const en = {
|
|
57
67
|
workspaces: "Workspaces",
|
|
@@ -59,7 +69,6 @@ window.__ModuleLoader__.load({
|
|
|
59
69
|
recent: "Recent Sessions",
|
|
60
70
|
ungrouped: "Ungrouped",
|
|
61
71
|
newSession: "New Session",
|
|
62
|
-
untitled: "Untitled session",
|
|
63
72
|
addWorkspace: "Add workspace",
|
|
64
73
|
addWorkspaceMenu: "Add workspace…",
|
|
65
74
|
search: "Search sessions",
|
|
@@ -78,6 +87,13 @@ window.__ModuleLoader__.load({
|
|
|
78
87
|
deleteDescription: "This removes “{name}” from the workspace list. The folder and session logs remain.",
|
|
79
88
|
fork: "Fork session",
|
|
80
89
|
archive: "Archive session",
|
|
90
|
+
archiveMode: "Archive mode",
|
|
91
|
+
deleteMode: "Delete mode",
|
|
92
|
+
deleteSession: "Delete session",
|
|
93
|
+
deleteSessionTitle: "Delete session",
|
|
94
|
+
deleteSessionConfirm: "Are you sure you want to delete this session? It will be removed from the list. This cannot be undone.",
|
|
95
|
+
toggleActionMode: "Toggle archive/delete mode",
|
|
96
|
+
actionModeLabel: "Session action",
|
|
81
97
|
cancel: "Cancel",
|
|
82
98
|
confirm: "Confirm",
|
|
83
99
|
retry: "Choose again",
|
|
@@ -95,7 +111,11 @@ window.__ModuleLoader__.load({
|
|
|
95
111
|
waiting: "Waiting for interaction",
|
|
96
112
|
completed: "Completed",
|
|
97
113
|
collapse: "Collapse",
|
|
98
|
-
expand: "Expand"
|
|
114
|
+
expand: "Expand",
|
|
115
|
+
today: "Today",
|
|
116
|
+
yesterday: "Yesterday",
|
|
117
|
+
date: "{m}/{d}",
|
|
118
|
+
dateYear: "{m}/{d}/{y}"
|
|
99
119
|
};
|
|
100
120
|
const NS = "ya-workspace-sidebar";
|
|
101
121
|
//#endregion
|
|
@@ -123,6 +143,7 @@ body[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish
|
|
|
123
143
|
.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }
|
|
124
144
|
.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }
|
|
125
145
|
.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }
|
|
146
|
+
.ya-date-group-label { height:26px; display:flex; align-items:center; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; }
|
|
126
147
|
.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }
|
|
127
148
|
.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
|
|
128
149
|
button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }
|
|
@@ -145,13 +166,13 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
145
166
|
.ya-warning { color:var(--dsw-alias-status-warning); }
|
|
146
167
|
.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }
|
|
147
168
|
.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }
|
|
148
|
-
.ya-drop-before::before, .ya-drop-after::after { content:''; position:absolute; left:8px; right:8px; height:2px; border-radius:2px; background:var(--dsw-alias-label-link); }
|
|
149
|
-
.ya-drop-before::before { top:-2px; } .ya-drop-after::after { bottom:-2px; }
|
|
150
169
|
.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }
|
|
151
170
|
.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }
|
|
152
171
|
.ya-rail .ya-search { justify-content:center; }
|
|
153
172
|
.ya-rail .ya-search-icon { cursor:pointer; color:var(--dsw-alias-label-primary); }
|
|
154
173
|
.ya-picker-error { color:var(--dsw-alias-status-error); white-space:pre-wrap; }
|
|
174
|
+
.ya-action-mode-toggle.ya-action-mode-delete { color:var(--dsw-alias-state-error-primary); }
|
|
175
|
+
.ya-action-mode-toggle.ya-action-mode-delete:hover { background:var(--dsw-alias-interactive-bg-hover-danger); }
|
|
155
176
|
@keyframes ya-slide-in-forward { from { opacity:0; transform:translateX(10px); } to { opacity:1; transform:translateX(0); } }
|
|
156
177
|
@keyframes ya-slide-in-backward { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:translateX(0); } }
|
|
157
178
|
.ya-level-enter-forward { animation:ya-slide-in-forward 180ms ease-out; }
|
|
@@ -307,7 +328,6 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
307
328
|
return {
|
|
308
329
|
id: summary.id,
|
|
309
330
|
title: summary.blank ? "New Session" : summary.displayTitle,
|
|
310
|
-
hasTitle: summary.title !== void 0,
|
|
311
331
|
blank: summary.blank,
|
|
312
332
|
running: summary.running,
|
|
313
333
|
...summary.pendingInteraction === void 0 ? {} : { pendingInteraction: summary.pendingInteraction },
|
|
@@ -380,6 +400,70 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
380
400
|
if (workspace === void 0) return [];
|
|
381
401
|
return workspace.sessionIds.map((id) => list.byId[id]).filter((summary) => summary !== void 0 && visible(summary, list.current, archived)).map((summary) => rowOf(summary, workspace.workspaceId, workspace.title));
|
|
382
402
|
}
|
|
403
|
+
/** Format a local calendar date as `YYYY-MM-DD` (locale-agnostic, no padding surprises). */
|
|
404
|
+
function localDateKey(year, month, day) {
|
|
405
|
+
return `${year}-${month < 9 ? `0${month + 1}` : `${month + 1}`}-${day < 10 ? `0${day}` : `${day}`}`;
|
|
406
|
+
}
|
|
407
|
+
/** Whole-day difference between two local calendar dates (a - b) using UTC midnight. */
|
|
408
|
+
function dayDiff(a, b) {
|
|
409
|
+
const msA = Date.UTC(a.year, a.month, a.day);
|
|
410
|
+
const msB = Date.UTC(b.year, b.month, b.day);
|
|
411
|
+
return Math.round((msA - msB) / 864e5);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Derive the selected real workspace's sessions grouped by local calendar date.
|
|
415
|
+
*
|
|
416
|
+
* - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
|
|
417
|
+
* - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
|
|
418
|
+
* - {@link visible} filter is reused (archived / subagent / blank visibility).
|
|
419
|
+
* - Future timestamps clamp to today's bucket (`dayOffset` 0).
|
|
420
|
+
* - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
|
|
421
|
+
*/
|
|
422
|
+
function deriveWorkspaceSessionGroups(key, list, workspaces, archivedSessionIds, now) {
|
|
423
|
+
if (key === "__ya_ungrouped__") return [];
|
|
424
|
+
const workspace = workspaces.find((item) => item.workspaceId === key);
|
|
425
|
+
if (workspace === void 0) return [];
|
|
426
|
+
const archived = new Set(archivedSessionIds);
|
|
427
|
+
const rows = workspace.sessionIds.map((id) => list.byId[id]).filter((summary) => summary !== void 0 && visible(summary, list.current, archived)).map((summary) => rowOf(summary, workspace.workspaceId, workspace.title));
|
|
428
|
+
if (rows.length === 0) return [];
|
|
429
|
+
const nowDate = new Date(now);
|
|
430
|
+
const today = {
|
|
431
|
+
year: nowDate.getFullYear(),
|
|
432
|
+
month: nowDate.getMonth(),
|
|
433
|
+
day: nowDate.getDate()
|
|
434
|
+
};
|
|
435
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
436
|
+
for (const row of rows) {
|
|
437
|
+
const ts = Math.min(row.updatedAt, now);
|
|
438
|
+
const d = new Date(ts);
|
|
439
|
+
const date = {
|
|
440
|
+
year: d.getFullYear(),
|
|
441
|
+
month: d.getMonth(),
|
|
442
|
+
day: d.getDate()
|
|
443
|
+
};
|
|
444
|
+
const dateKey = localDateKey(date.year, date.month, date.day);
|
|
445
|
+
let bucket = buckets.get(dateKey);
|
|
446
|
+
if (bucket === void 0) {
|
|
447
|
+
bucket = {
|
|
448
|
+
dayOffset: Math.max(0, dayDiff(today, date)),
|
|
449
|
+
rows: []
|
|
450
|
+
};
|
|
451
|
+
buckets.set(dateKey, bucket);
|
|
452
|
+
}
|
|
453
|
+
bucket.rows.push(row);
|
|
454
|
+
}
|
|
455
|
+
const groups = [];
|
|
456
|
+
for (const [dateKey, bucket] of buckets) {
|
|
457
|
+
bucket.rows.sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)));
|
|
458
|
+
groups.push({
|
|
459
|
+
dateKey,
|
|
460
|
+
dayOffset: bucket.dayOffset,
|
|
461
|
+
rows: bucket.rows
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
groups.sort((a, b) => a.dayOffset - b.dayOffset || a.dateKey.localeCompare(b.dateKey));
|
|
465
|
+
return groups;
|
|
466
|
+
}
|
|
383
467
|
/** Case-insensitive local title/workspace matching used beside Host content search. */
|
|
384
468
|
function localMatches(rows, query) {
|
|
385
469
|
const normalized = query.trim().toLocaleLowerCase();
|
|
@@ -387,6 +471,43 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
387
471
|
return rows.filter((row) => `${row.title}\n${row.workspaceTitle}`.toLocaleLowerCase().includes(normalized));
|
|
388
472
|
}
|
|
389
473
|
//#endregion
|
|
474
|
+
//#region src/client/settings.ts
|
|
475
|
+
const STORAGE_KEY = "ya-workspace-sidebar:action-mode";
|
|
476
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
477
|
+
let currentMode = loadMode();
|
|
478
|
+
/** Read the stored preference, falling back to `archive` on any failure. */
|
|
479
|
+
function loadMode() {
|
|
480
|
+
try {
|
|
481
|
+
return window.localStorage.getItem(STORAGE_KEY) === "delete" ? "delete" : "archive";
|
|
482
|
+
} catch {
|
|
483
|
+
return "archive";
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/** Persist the preference; silently ignores quota or privacy-mode failures. */
|
|
487
|
+
function persistMode(mode) {
|
|
488
|
+
try {
|
|
489
|
+
window.localStorage.setItem(STORAGE_KEY, mode);
|
|
490
|
+
} catch {}
|
|
491
|
+
}
|
|
492
|
+
/** Current action mode snapshot. */
|
|
493
|
+
function getActionMode() {
|
|
494
|
+
return currentMode;
|
|
495
|
+
}
|
|
496
|
+
/** Switch the action mode and notify subscribers. */
|
|
497
|
+
function setActionMode(mode) {
|
|
498
|
+
if (mode === currentMode) return;
|
|
499
|
+
currentMode = mode;
|
|
500
|
+
persistMode(mode);
|
|
501
|
+
for (const listener of [...listeners]) listener();
|
|
502
|
+
}
|
|
503
|
+
/** Subscribe to action mode changes; returns an unsubscribe disposer. */
|
|
504
|
+
function subscribeActionMode(listener) {
|
|
505
|
+
listeners.add(listener);
|
|
506
|
+
return () => {
|
|
507
|
+
listeners.delete(listener);
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
//#endregion
|
|
390
511
|
//#region src/client/WorkspaceSidebar.tsx
|
|
391
512
|
/** Two-level workspace/session browser with a persistent global recent block. */
|
|
392
513
|
const SEARCH_DEBOUNCE_MS = 250;
|
|
@@ -404,43 +525,43 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
404
525
|
if (diff < 525600 * minute) return t("months", { n: Math.floor(diff / (43200 * minute)) });
|
|
405
526
|
return t("years", { n: Math.floor(diff / (525600 * minute)) });
|
|
406
527
|
}
|
|
528
|
+
/** Format a date group's localized title from its dayOffset and `YYYY-MM-DD` key. */
|
|
529
|
+
function dateGroupLabel(group, now, t) {
|
|
530
|
+
if (group.dayOffset === 0) return t("today");
|
|
531
|
+
if (group.dayOffset === 1) return t("yesterday");
|
|
532
|
+
const parts = group.dateKey.split("-");
|
|
533
|
+
const year = Number(parts[0]);
|
|
534
|
+
const month = Number(parts[1]);
|
|
535
|
+
const day = Number(parts[2]);
|
|
536
|
+
if (year === new Date(now).getFullYear()) return t("date", {
|
|
537
|
+
m: month,
|
|
538
|
+
d: day
|
|
539
|
+
});
|
|
540
|
+
return t("dateYear", {
|
|
541
|
+
y: year,
|
|
542
|
+
m: month,
|
|
543
|
+
d: day
|
|
544
|
+
});
|
|
545
|
+
}
|
|
407
546
|
function SessionStatus({ row }) {
|
|
408
547
|
if (row.pendingInteraction !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
|
|
409
548
|
if (row.running) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "ongoing" });
|
|
410
549
|
if (row.completed) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "done" });
|
|
411
550
|
return null;
|
|
412
551
|
}
|
|
413
|
-
function
|
|
414
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
415
|
-
return event.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
416
|
-
}
|
|
417
|
-
function SessionItem({ row, current, now, open, rename, fork, archive, t, context, drag }) {
|
|
552
|
+
function SessionItem({ row, current, now, open, rename, fork, archive, t, context, actionMode }) {
|
|
418
553
|
const [menuOpen, setMenuOpen] = (0, react.useState)(false);
|
|
419
|
-
const title = row.blank ? t("newSession") : row.
|
|
554
|
+
const title = row.blank ? t("newSession") : row.title;
|
|
555
|
+
const isDelete = actionMode === "delete";
|
|
556
|
+
const actionLabel = isDelete ? t("deleteSession") : t("archive");
|
|
557
|
+
const actionIcon = isDelete ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 });
|
|
420
558
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
421
|
-
className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}
|
|
559
|
+
className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}`,
|
|
422
560
|
role: "treeitem",
|
|
423
561
|
"aria-selected": row.id === current,
|
|
424
|
-
draggable: drag !== void 0,
|
|
425
562
|
onClick: () => {
|
|
426
563
|
open(row.id);
|
|
427
564
|
},
|
|
428
|
-
onDragStart: drag === void 0 ? void 0 : (event) => {
|
|
429
|
-
event.dataTransfer.effectAllowed = "move";
|
|
430
|
-
drag.start();
|
|
431
|
-
},
|
|
432
|
-
onDragEnd: drag?.end,
|
|
433
|
-
onDragOver: drag === void 0 ? void 0 : (event) => {
|
|
434
|
-
if (!drag.active) return;
|
|
435
|
-
event.preventDefault();
|
|
436
|
-
event.dataTransfer.dropEffect = "move";
|
|
437
|
-
drag.hover(rowHalf(event));
|
|
438
|
-
},
|
|
439
|
-
onDrop: drag === void 0 ? void 0 : (event) => {
|
|
440
|
-
if (!drag.active) return;
|
|
441
|
-
event.preventDefault();
|
|
442
|
-
drag.drop(rowHalf(event));
|
|
443
|
-
},
|
|
444
565
|
children: [
|
|
445
566
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
446
567
|
className: "ya-status-slot",
|
|
@@ -482,8 +603,9 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
482
603
|
},
|
|
483
604
|
{
|
|
484
605
|
id: "archive",
|
|
485
|
-
label:
|
|
486
|
-
icon:
|
|
606
|
+
label: actionLabel,
|
|
607
|
+
icon: actionIcon,
|
|
608
|
+
danger: isDelete
|
|
487
609
|
}
|
|
488
610
|
],
|
|
489
611
|
onSelect: (id) => {
|
|
@@ -586,7 +708,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
586
708
|
}
|
|
587
709
|
/** Fill `sidebar.workspaces` with the replacement browser. */
|
|
588
710
|
function WorkspaceSidebar(props) {
|
|
589
|
-
const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession,
|
|
711
|
+
const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t } = props;
|
|
590
712
|
const sessions = useSessions((state) => state);
|
|
591
713
|
const workspaceState = useWorkspaces((state) => state);
|
|
592
714
|
const workspaces = workspaceState.items;
|
|
@@ -624,8 +746,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
624
746
|
if (selectedKey !== null && selectedKey !== "__ya_ungrouped__" && !workspaces.some((workspace) => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED);
|
|
625
747
|
}, [selectedKey, workspaces]);
|
|
626
748
|
const selectedWorkspace = selectedKey === null || selectedKey === "__ya_ungrouped__" ? void 0 : workspaces.find((workspace) => workspace.workspaceId === selectedKey);
|
|
627
|
-
const levelRows = selectedKey === null ? [] : deriveWorkspaceSessions(selectedKey, sessions, workspaces, archived);
|
|
628
749
|
const now = Date.now();
|
|
750
|
+
const levelGroups = (0, react.useMemo)(() => selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? deriveWorkspaceSessionGroups(selectedKey, sessions, workspaces, archived, now) : [], [
|
|
751
|
+
archived,
|
|
752
|
+
sessions,
|
|
753
|
+
workspaces,
|
|
754
|
+
selectedKey,
|
|
755
|
+
now
|
|
756
|
+
]);
|
|
757
|
+
const levelRows = selectedKey === "__ya_ungrouped__" ? deriveWorkspaceSessions(UNGROUPED, sessions, workspaces, archived) : [];
|
|
758
|
+
const levelEmpty = selectedKey === "__ya_ungrouped__" ? levelRows.length === 0 : levelGroups.every((g) => g.rows.length === 0);
|
|
629
759
|
const [query, setQuery] = (0, react.useState)("");
|
|
630
760
|
const normalizedQuery = sanitized(query).trim();
|
|
631
761
|
const [remote, setRemote] = (0, react.useState)({
|
|
@@ -696,7 +826,9 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
696
826
|
const [renameError, setRenameError] = (0, react.useState)(null);
|
|
697
827
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
698
828
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
|
|
699
|
-
const [
|
|
829
|
+
const [actionMode, setActionModeState] = (0, react.useState)(() => getActionMode());
|
|
830
|
+
const [sessionDeleteTarget, setSessionDeleteTarget] = (0, react.useState)(null);
|
|
831
|
+
(0, react.useEffect)(() => subscribeActionMode(() => setActionModeState(getActionMode())), []);
|
|
700
832
|
const beginWorkspaceRename = (row) => {
|
|
701
833
|
setWorkspaceRename(row);
|
|
702
834
|
setRenameDraft(row.title);
|
|
@@ -739,61 +871,54 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
739
871
|
});
|
|
740
872
|
};
|
|
741
873
|
const archive = (id) => {
|
|
874
|
+
if (actionMode === "delete") {
|
|
875
|
+
const row = allRows.find((candidate) => candidate.id === id) ?? levelRows.find((candidate) => candidate.id === id) ?? levelGroups.flatMap((g) => g.rows).find((candidate) => candidate.id === id) ?? recent.find((candidate) => candidate.id === id);
|
|
876
|
+
setSessionDeleteTarget(row ?? {
|
|
877
|
+
id,
|
|
878
|
+
title: "",
|
|
879
|
+
blank: false,
|
|
880
|
+
running: false,
|
|
881
|
+
completed: false,
|
|
882
|
+
updatedAt: 0,
|
|
883
|
+
workspaceKey: "__ya_ungrouped__",
|
|
884
|
+
workspaceTitle: ""
|
|
885
|
+
});
|
|
886
|
+
setRenameError(null);
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
742
889
|
archiveSession(id).catch((reason) => {
|
|
743
890
|
console.warn("session archive rejected:", reason);
|
|
744
891
|
});
|
|
745
892
|
};
|
|
893
|
+
const confirmSessionDelete = () => {
|
|
894
|
+
if (sessionDeleteTarget === null || busy) return;
|
|
895
|
+
setBusy(true);
|
|
896
|
+
archiveSession(sessionDeleteTarget.id).then(() => {
|
|
897
|
+
setSessionDeleteTarget(null);
|
|
898
|
+
}).catch((reason) => {
|
|
899
|
+
setRenameError(reason instanceof Error ? reason.message : String(reason));
|
|
900
|
+
}).finally(() => {
|
|
901
|
+
setBusy(false);
|
|
902
|
+
});
|
|
903
|
+
};
|
|
904
|
+
const toggleActionMode = () => {
|
|
905
|
+
setActionMode(actionMode === "archive" ? "delete" : "archive");
|
|
906
|
+
};
|
|
746
907
|
const fork = (id) => {
|
|
747
908
|
forkSession(id);
|
|
748
909
|
};
|
|
749
|
-
const sessionItem = (row, context = false,
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
context,
|
|
762
|
-
...draggable && selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? { drag: {
|
|
763
|
-
active: drag !== null,
|
|
764
|
-
marker,
|
|
765
|
-
start: () => {
|
|
766
|
-
setDrag({
|
|
767
|
-
id: row.id,
|
|
768
|
-
over: null
|
|
769
|
-
});
|
|
770
|
-
},
|
|
771
|
-
hover: (half) => {
|
|
772
|
-
setDrag((value) => value === null ? value : {
|
|
773
|
-
...value,
|
|
774
|
-
over: {
|
|
775
|
-
id: row.id,
|
|
776
|
-
half
|
|
777
|
-
}
|
|
778
|
-
});
|
|
779
|
-
},
|
|
780
|
-
drop: (half) => {
|
|
781
|
-
if (drag === null) return;
|
|
782
|
-
const anchor = half === "before" ? row.id : levelRows[(index ?? 0) + 1]?.id;
|
|
783
|
-
const sourceIndex = levelRows.findIndex((item) => item.id === drag.id);
|
|
784
|
-
const anchorIndex = anchor === void 0 ? levelRows.length : levelRows.findIndex((item) => item.id === anchor);
|
|
785
|
-
setDrag(null);
|
|
786
|
-
if (anchor === drag.id || sourceIndex === anchorIndex || sourceIndex + 1 === anchorIndex) return;
|
|
787
|
-
insertSessionBefore(selectedKey, drag.id, anchor).catch((reason) => {
|
|
788
|
-
console.warn("session reorder rejected:", reason);
|
|
789
|
-
});
|
|
790
|
-
},
|
|
791
|
-
end: () => {
|
|
792
|
-
setDrag(null);
|
|
793
|
-
}
|
|
794
|
-
} } : {}
|
|
795
|
-
}, row.id);
|
|
796
|
-
};
|
|
910
|
+
const sessionItem = (row, context = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionItem, {
|
|
911
|
+
row,
|
|
912
|
+
current: sessions.current,
|
|
913
|
+
now,
|
|
914
|
+
open,
|
|
915
|
+
rename: beginSessionRename,
|
|
916
|
+
fork,
|
|
917
|
+
archive,
|
|
918
|
+
t,
|
|
919
|
+
context,
|
|
920
|
+
actionMode
|
|
921
|
+
}, row.id);
|
|
797
922
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
798
923
|
"data-ya-workspace-sidebar": true,
|
|
799
924
|
className: wide ? "" : "ya-rail",
|
|
@@ -805,6 +930,18 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
805
930
|
className: "ya-section-title",
|
|
806
931
|
children: t("workspaces")
|
|
807
932
|
}),
|
|
933
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
934
|
+
type: "button",
|
|
935
|
+
className: `ya-icon-button ya-action-mode-toggle${actionMode === "delete" ? " ya-action-mode-delete" : ""}`,
|
|
936
|
+
"aria-label": t("toggleActionMode"),
|
|
937
|
+
"aria-pressed": actionMode === "delete",
|
|
938
|
+
title: actionMode === "delete" ? t("deleteMode") : t("archiveMode"),
|
|
939
|
+
onClick: (event) => {
|
|
940
|
+
event.stopPropagation();
|
|
941
|
+
toggleActionMode();
|
|
942
|
+
},
|
|
943
|
+
children: actionMode === "delete" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: wide ? 16 : 18 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: wide ? 16 : 18 })
|
|
944
|
+
}),
|
|
808
945
|
directoryFlowAvailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
809
946
|
ref: pickerAnchor,
|
|
810
947
|
type: "button",
|
|
@@ -970,12 +1107,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
970
1107
|
setRenameError(null);
|
|
971
1108
|
},
|
|
972
1109
|
t
|
|
973
|
-
}, row.key)) : levelRows.map((row
|
|
1110
|
+
}, row.key)) : selectedKey === "__ya_ungrouped__" ? levelRows.map((row) => sessionItem(row, false)) : levelGroups.flatMap((group) => [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1111
|
+
className: "ya-date-group-label",
|
|
1112
|
+
role: "separator",
|
|
1113
|
+
children: dateGroupLabel(group, now, t)
|
|
1114
|
+
}, `group-${group.dateKey}`), ...group.rows.map((row) => sessionItem(row, false))]),
|
|
974
1115
|
selectedKey === null && workspaceRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
975
1116
|
className: "ya-empty",
|
|
976
1117
|
children: t("noWorkspaces")
|
|
977
1118
|
}),
|
|
978
|
-
selectedKey !== null &&
|
|
1119
|
+
selectedKey !== null && levelEmpty && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
979
1120
|
className: "ya-empty",
|
|
980
1121
|
children: t("noSessions")
|
|
981
1122
|
})
|
|
@@ -1042,6 +1183,33 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
1042
1183
|
role: "alert",
|
|
1043
1184
|
children: renameError
|
|
1044
1185
|
})
|
|
1186
|
+
}),
|
|
1187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1188
|
+
open: sessionDeleteTarget !== null,
|
|
1189
|
+
onClose: () => {
|
|
1190
|
+
if (!busy) setSessionDeleteTarget(null);
|
|
1191
|
+
},
|
|
1192
|
+
closeLabel: t("cancel"),
|
|
1193
|
+
title: t("deleteSessionTitle"),
|
|
1194
|
+
description: t("deleteSessionConfirm"),
|
|
1195
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1196
|
+
variant: "outline",
|
|
1197
|
+
disabled: busy,
|
|
1198
|
+
onClick: () => {
|
|
1199
|
+
setSessionDeleteTarget(null);
|
|
1200
|
+
},
|
|
1201
|
+
children: t("cancel")
|
|
1202
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1203
|
+
variant: "outline",
|
|
1204
|
+
disabled: busy,
|
|
1205
|
+
onClick: confirmSessionDelete,
|
|
1206
|
+
children: t("deleteSession")
|
|
1207
|
+
})] }),
|
|
1208
|
+
children: renameError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1209
|
+
className: "ya-error",
|
|
1210
|
+
role: "alert",
|
|
1211
|
+
children: renameError
|
|
1212
|
+
})
|
|
1045
1213
|
})
|
|
1046
1214
|
]
|
|
1047
1215
|
});
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["useState","useCallback","IconPlusOutline16","IconFolderClose16","Menu","Modal","Button","StateDot","useState","Menu","IconEditOutline16","IconBranchOutline16","IconArchiveOutline20","IconEllipsisOutline16","IconFolderClose16","IconTrashOutline16","IconPlusOutline16","IconChevronRightOutline14","useMemo","useRef","IconProjectAddOutline16","IconSearchOutline16","IconCloseFill14","Modal","Button"],"sources":["../src/client/locales.ts","../src/client/styles.ts","../src/client/WorkspacePicker.tsx","../src/client/model.ts","../src/client/WorkspaceSidebar.tsx","../src/client/index.ts"],"sourcesContent":["/** Product copy for the replacement workspace browser. */\nexport const zh = {\n workspaces: '工作区',\n sessions: '会话',\n recent: '最近会话',\n ungrouped: '未分组',\n newSession: '新会话',\n untitled: '未命名会话',\n addWorkspace: '添加工作区',\n addWorkspaceMenu: '添加工作区…',\n search: '搜索会话',\n searchPlaceholder: '搜索名称、关键词…',\n clearSearch: '清除搜索',\n searching: '正在搜索会话历史…',\n searchUnavailable: '内容搜索暂不可用,仅显示名称匹配。',\n noMatches: '无匹配会话',\n noSessions: '暂无会话',\n noWorkspaces: '暂无工作区',\n loading: '正在加载工作区…',\n rename: '重命名',\n renameWorkspace: '重命名工作区',\n renameSession: '重命名会话',\n deleteWorkspace: '删除工作区',\n deleteDescription: '将把“{name}”从工作区列表中移除。文件夹与会话记录会保留。',\n fork: '分叉会话',\n archive: '归档会话',\n cancel: '取消',\n confirm: '确认',\n retry: '重新选择',\n folderError: '无法打开文件夹',\n workspaceName: '工作区名称',\n sessionName: '会话名称',\n count: '{n} 个会话',\n now: '刚刚',\n minutes: '{n}分钟',\n hours: '{n}小时',\n days: '{n}天',\n months: '{n}个月',\n years: '{n}年',\n running: '进行中',\n waiting: '等待交互',\n completed: '已完成',\n collapse: '折叠',\n expand: '展开',\n} satisfies Record<string, string>\n\nexport type YaWorkspaceKey = keyof typeof zh\n\nexport const en = {\n workspaces: 'Workspaces',\n sessions: 'Sessions',\n recent: 'Recent Sessions',\n ungrouped: 'Ungrouped',\n newSession: 'New Session',\n untitled: 'Untitled session',\n addWorkspace: 'Add workspace',\n addWorkspaceMenu: 'Add workspace…',\n search: 'Search sessions',\n searchPlaceholder: 'Search name, keywords...',\n clearSearch: 'Clear search',\n searching: 'Searching session history…',\n searchUnavailable: 'Content search is unavailable. Showing name matches.',\n noMatches: 'No matching sessions',\n noSessions: 'No sessions yet',\n noWorkspaces: 'No workspaces yet',\n loading: 'Loading workspaces…',\n rename: 'Rename',\n renameWorkspace: 'Rename workspace',\n renameSession: 'Rename session',\n deleteWorkspace: 'Delete workspace',\n deleteDescription: 'This removes “{name}” from the workspace list. The folder and session logs remain.',\n fork: 'Fork session',\n archive: 'Archive session',\n cancel: 'Cancel',\n confirm: 'Confirm',\n retry: 'Choose again',\n folderError: 'Couldn’t open folder',\n workspaceName: 'Workspace name',\n sessionName: 'Session name',\n count: '{n} sessions',\n now: 'now',\n minutes: '{n}min',\n hours: '{n}h',\n days: '{n}d',\n months: '{n}mo',\n years: '{n}y',\n running: 'Running',\n waiting: 'Waiting for interaction',\n completed: 'Completed',\n collapse: 'Collapse',\n expand: 'Expand',\n} satisfies Record<YaWorkspaceKey, string>\n\nexport const NS = 'ya-workspace-sidebar'\n","/** One scoped stylesheet injected for the lifetime of the client activation. */\nexport const CSS = `\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-drop-before::before, .ya-drop-after::after { content:''; position:absolute; left:8px; right:8px; height:2px; border-radius:2px; background:var(--dsw-alias-label-link); }\n.ya-drop-before::before { top:-2px; } .ya-drop-after::after { bottom:-2px; }\n.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }\n.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }\n.ya-rail .ya-search { justify-content:center; }\n.ya-rail .ya-search-icon { cursor:pointer; color:var(--dsw-alias-label-primary); }\n.ya-picker-error { color:var(--dsw-alias-status-error); white-space:pre-wrap; }\n@keyframes ya-slide-in-forward { from { opacity:0; transform:translateX(10px); } to { opacity:1; transform:translateX(0); } }\n@keyframes ya-slide-in-backward { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:translateX(0); } }\n.ya-level-enter-forward { animation:ya-slide-in-forward 180ms ease-out; }\n.ya-level-enter-backward { animation:ya-slide-in-backward 180ms ease-out; }\n`\n\n/** Install the stylesheet and return its disposer. */\nexport function installStyles(): () => void {\n const style = document.createElement('style')\n style.setAttribute('data-ya-workspace-sidebar-style', '')\n style.textContent = CSS\n document.head.appendChild(style)\n return () => { style.remove() }\n}\n","/** Existing-workspace menu plus composed directory-adoption flow. */\nimport type { ReactNode, RefObject } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport {\n Button, IconFolderClose16, IconPlusOutline16, Menu, Modal, type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n WorkspaceId, WorkspaceListState, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts'\n\nconst ADD = '::ya-add-workspace'\n\ninterface FlowProps {\n t: PickerProps['t']\n open: boolean\n anchorRef?: RefObject<HTMLElement | null>\n useWorkspaces: <S>(selector: (state: WorkspaceListState) => S) => S\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n useDirectoryFlow: SnapshotSelectorHook<boolean>\n renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode\n onPick: (workspaceId: WorkspaceId) => void\n onClose: () => void\n addOnly?: boolean\n side?: 'bottom' | 'top' | 'right'\n selectedId?: WorkspaceId\n}\n\n/** Render the workspace target menu and directory picking conversation. */\nexport function WorkspacePickFlow({\n t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow,\n renderDirectoryFlow, onPick, onClose, addOnly = false, side = 'bottom', selectedId,\n}: FlowProps) {\n const snapshot = useWorkspaces(state => state)\n const flowAvailable = useDirectoryFlow(value => value)\n const [flowOpen, setFlowOpen] = useState(false)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const getAnchorRect = useCallback(\n () => anchorRef?.current?.getBoundingClientRect() ?? null,\n [anchorRef],\n )\n useEffect(() => {\n if (flowOpen && !flowAvailable) setFlowOpen(false)\n }, [flowAvailable, flowOpen])\n\n const openFlow = useCallback(() => {\n onClose()\n setError(null)\n setFlowOpen(true)\n }, [onClose])\n const addEntries: MenuEntry[] = flowAvailable\n ? [{ id: ADD, label: t('addWorkspaceMenu'), icon: <IconPlusOutline16 size={16} />, disabled: flowOpen || busy }]\n : []\n const pinnedAdd = !addOnly && snapshot.items.length > 0\n const items: MenuEntry[] = pinnedAdd\n ? snapshot.items.map(workspace => ({\n id: workspace.workspaceId,\n label: workspace.title,\n icon: <IconFolderClose16 size={16} />,\n disabled: flowOpen || busy,\n }))\n : addEntries\n const settled = addOnly || snapshot.phase === 'ready'\n const onlyAdd = !pinnedAdd && settled && addEntries.length === 1\n useEffect(() => {\n if (open && onlyAdd && !flowOpen && !busy) openFlow()\n }, [busy, flowOpen, onlyAdd, open, openFlow])\n\n const owner: DirectoryFlowOwnerProps = {\n open: flowOpen,\n busy,\n onPicked: (path) => {\n setBusy(true)\n createWorkspace({ path }).then(workspace => {\n setFlowOpen(false)\n onPick(workspace.workspaceId)\n }).catch((reason: unknown) => {\n setFlowOpen(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n }).finally(() => { setBusy(false) })\n },\n onCancel: () => { setFlowOpen(false) },\n onError: (message) => { setFlowOpen(false); setError(message) },\n }\n\n return (\n <>\n <Menu\n open={open && !onlyAdd && items.length > 0}\n anchor={null}\n items={items}\n {...pinnedAdd ? { footer: addEntries } : {}}\n selectedId={selectedId}\n onSelect={(id) => { if (id === ADD) openFlow(); else onPick(id as WorkspaceId) }}\n onClose={onClose}\n side={side}\n portal\n getAnchorRect={getAnchorRect}\n />\n {open && !onlyAdd && snapshot.phase === 'pending' && <div className=\"ya-status\">{t('loading')}</div>}\n {renderDirectoryFlow(owner)}\n <Modal\n open={error !== null}\n onClose={() => { setError(null) }}\n closeLabel={t('cancel')}\n title={t('folderError')}\n footer={(\n <>\n <Button variant=\"outline\" onClick={() => { setError(null) }}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={!flowAvailable} onClick={openFlow}>{t('retry')}</Button>\n </>\n )}\n >\n <div className=\"ya-picker-error\" role=\"alert\">{error}</div>\n </Modal>\n </>\n )\n}\n\n/** Fill the conversation hero's workspace picker seat. */\nexport function WorkspacePicker({\n open, anchorRef, useWorkspaces, selectedId, onPick, onClose,\n createWorkspace, useDirectoryFlow, renderSlot, t,\n}: PickerProps) {\n return (\n <WorkspacePickFlow\n t={t}\n open={open}\n anchorRef={anchorRef}\n useWorkspaces={useWorkspaces}\n selectedId={selectedId}\n onPick={onPick}\n onClose={onClose}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('conversation.hero.workspace.directoryFlow', owner)}\n />\n )\n}\n","/** Pure sidebar projections shared by the browser and unit tests. */\nimport type {\n SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\n\n/** Navigation key for sessions not accounted to a real workspace. */\nexport const UNGROUPED = '__ya_ungrouped__' as const\n\n/** One sidebar session row. */\nexport interface SessionRow {\n id: SessionId\n title: string\n /** Whether the session has a durable log-backed title (summary.title !== undefined). */\n hasTitle: boolean\n blank: boolean\n running: boolean\n pendingInteraction?: SessionSummary['pendingInteraction']\n completed: boolean\n updatedAt: number\n workspaceKey: WorkspaceId | typeof UNGROUPED\n workspaceTitle: string\n}\n\n/** One first-level workspace row. */\nexport interface WorkspaceRow {\n key: WorkspaceId | typeof UNGROUPED\n title: string\n path?: string\n createdAt?: string\n count: number\n real: boolean\n}\n\nfunction visible(summary: SessionSummary, current: SessionId | undefined, archived: ReadonlySet<SessionId>): boolean {\n return summary.origin !== 'subagent'\n && !archived.has(summary.id)\n && (!summary.blank || summary.id === current)\n}\n\nfunction rowOf(\n summary: SessionSummary,\n workspaceKey: WorkspaceId | typeof UNGROUPED,\n workspaceTitle: string,\n): SessionRow {\n return {\n id: summary.id,\n title: summary.blank ? 'New Session' : summary.displayTitle,\n hasTitle: summary.title !== undefined,\n blank: summary.blank,\n running: summary.running,\n ...(summary.pendingInteraction === undefined ? {} : { pendingInteraction: summary.pendingInteraction }),\n completed: summary.completed === true,\n updatedAt: summary.updatedAt,\n workspaceKey,\n workspaceTitle,\n }\n}\n\nfunction ownerIndex(workspaces: readonly WorkspaceView[]): Map<SessionId, WorkspaceView> {\n const result = new Map<SessionId, WorkspaceView>()\n for (const workspace of workspaces) {\n for (const sessionId of workspace.sessionIds) result.set(sessionId, workspace)\n }\n return result\n}\n\n/** Resolve the first/second-level destination for one session. */\nexport function workspaceKeyForSession(\n sessionId: SessionId | undefined,\n workspaces: readonly WorkspaceView[],\n): WorkspaceId | typeof UNGROUPED | null {\n if (sessionId === undefined) return null\n return ownerIndex(workspaces).get(sessionId)?.workspaceId ?? UNGROUPED\n}\n\n/** Derive global recent sessions, newest first. */\nexport function deriveRecent(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n limit = 5,\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n const owners = ownerIndex(workspaces)\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .slice(0, limit)\n .map((summary) => {\n const workspace = owners.get(summary.id)\n return rowOf(summary, workspace?.workspaceId ?? UNGROUPED, workspace?.title ?? 'Ungrouped')\n })\n}\n\n/** Derive first-level real workspaces plus the virtual Ungrouped row. */\nexport function deriveWorkspaces(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): WorkspaceRow[] {\n const archived = new Set(archivedSessionIds)\n const accounted = new Set<SessionId>()\n const result = workspaces.map((workspace): WorkspaceRow => {\n let count = 0\n for (const id of workspace.sessionIds) {\n accounted.add(id)\n const summary = list.byId[id]\n if (summary !== undefined && visible(summary, list.current, archived)) count++\n }\n return {\n key: workspace.workspaceId,\n title: workspace.title,\n path: workspace.path,\n createdAt: workspace.createdAt,\n count,\n real: true,\n }\n })\n let ungrouped = 0\n for (const id of list.ids) {\n const summary = list.byId[id]\n if (summary !== undefined && !accounted.has(id) && visible(summary, list.current, archived)) ungrouped++\n }\n result.push({ key: UNGROUPED, title: 'Ungrouped', count: ungrouped, real: false })\n return result\n}\n\n/** Derive the selected workspace's sessions in its canonical order. */\nexport function deriveWorkspaceSessions(\n key: WorkspaceId | typeof UNGROUPED,\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n if (key === UNGROUPED) {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined\n && !accounted.has(summary.id)\n && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .map(summary => rowOf(summary, UNGROUPED, 'Ungrouped'))\n }\n const workspace = workspaces.find(item => item.workspaceId === key)\n if (workspace === undefined) return []\n return workspace.sessionIds\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .map(summary => rowOf(summary, workspace.workspaceId, workspace.title))\n}\n\n/** Case-insensitive local title/workspace matching used beside Host content search. */\nexport function localMatches(rows: readonly SessionRow[], query: string): SessionRow[] {\n const normalized = query.trim().toLocaleLowerCase()\n if (normalized === '') return []\n return rows.filter(row => `${row.title}\\n${row.workspaceTitle}`.toLocaleLowerCase().includes(normalized))\n}\n","/** Two-level workspace/session browser with a persistent global recent block. */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n Button, IconArchiveOutline20, IconBranchOutline16, IconChevronRightOutline14,\n IconCloseFill14, IconEditOutline16, IconEllipsisOutline16, IconFolderClose16,\n IconPlusOutline16, IconProjectAddOutline16, IconSearchOutline16, IconTrashOutline16,\n Menu, Modal, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { SessionId, WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SidebarProps } from './contract.ts'\nimport {\n deriveRecent, deriveWorkspaceSessions, deriveWorkspaces, localMatches,\n UNGROUPED, workspaceKeyForSession, type SessionRow, type WorkspaceRow,\n} from './model.ts'\nimport { WorkspacePickFlow } from './WorkspacePicker.tsx'\n\nconst SEARCH_DEBOUNCE_MS = 250\nconst SEARCH_MAX = 500\n\nfunction sanitized(value: string): string {\n return value.replaceAll('\\0', '').slice(0, SEARCH_MAX)\n}\n\nfunction relativeTime(updatedAt: number, now: number, t: SidebarProps['t']): string {\n const diff = Math.max(0, now - updatedAt)\n const minute = 60_000\n if (diff < minute) return t('now')\n if (diff < 60 * minute) return t('minutes', { n: Math.floor(diff / minute) })\n if (diff < 24 * 60 * minute) return t('hours', { n: Math.floor(diff / (60 * minute)) })\n if (diff < 30 * 24 * 60 * minute) return t('days', { n: Math.floor(diff / (24 * 60 * minute)) })\n if (diff < 365 * 24 * 60 * minute) return t('months', { n: Math.floor(diff / (30 * 24 * 60 * minute)) })\n return t('years', { n: Math.floor(diff / (365 * 24 * 60 * minute)) })\n}\n\nfunction SessionStatus({ row }: { row: SessionRow }) {\n if (row.pendingInteraction !== undefined) return <StateDot state=\"warning\" />\n if (row.running) return <StateDot state=\"ongoing\" />\n if (row.completed) return <StateDot state=\"done\" />\n return null\n}\n\ninterface SessionRowProps {\n row: SessionRow\n current: SessionId | undefined\n now: number\n open: (id: SessionId) => void\n rename: (row: SessionRow) => void\n fork: (id: SessionId) => void\n archive: (id: SessionId) => void\n t: SidebarProps['t']\n context?: boolean\n drag?: {\n active: boolean\n marker: 'before' | 'after' | null\n start: () => void\n hover: (half: 'before' | 'after') => void\n drop: (half: 'before' | 'after') => void\n end: () => void\n }\n}\n\nfunction rowHalf(event: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = event.currentTarget.getBoundingClientRect()\n return event.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\nfunction SessionItem({ row, current, now, open, rename, fork, archive, t, context, drag }: SessionRowProps) {\n const [menuOpen, setMenuOpen] = useState(false)\n const title = row.blank ? t('newSession') : row.hasTitle ? row.title : t('untitled')\n return (\n <div\n className={`ya-row${row.id === current ? ' ya-selected' : ''}${menuOpen ? ' ya-menu-open' : ''}${drag?.marker === 'before' ? ' ya-drop-before' : ''}${drag?.marker === 'after' ? ' ya-drop-after' : ''}`}\n role=\"treeitem\"\n aria-selected={row.id === current}\n draggable={drag !== undefined}\n onClick={() => { open(row.id) }}\n onDragStart={drag === undefined ? undefined : (event) => { event.dataTransfer.effectAllowed = 'move'; drag.start() }}\n onDragEnd={drag?.end}\n onDragOver={drag === undefined ? undefined : (event) => {\n if (!drag.active) return\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n drag.hover(rowHalf(event))\n }}\n onDrop={drag === undefined ? undefined : (event) => {\n if (!drag.active) return\n event.preventDefault()\n drag.drop(rowHalf(event))\n }}\n >\n <span className=\"ya-status-slot\"><SessionStatus row={row} /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{title}</span>\n {!row.blank && <span className=\"ya-row-meta ya-row-time\">{relativeTime(row.updatedAt, now, t)}</span>}\n </span>\n {context === true && <span className=\"ya-search-workspace\">{row.workspaceTitle}</span>}\n </span>\n {!row.blank && (\n <span className=\"ya-row-actions\">\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'fork', label: t('fork'), icon: <IconBranchOutline16 /> },\n { id: 'archive', label: t('archive'), icon: <IconArchiveOutline20 size={16} /> },\n ]}\n onSelect={(id) => {\n setMenuOpen(false)\n if (id === 'rename') rename(row)\n if (id === 'fork') fork(row.id)\n if (id === 'archive') archive(row.id)\n }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className=\"ya-icon-button\"\n aria-label={`${title} actions`}\n onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}\n >\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n </span>\n )}\n </div>\n )\n}\n\nfunction WorkspaceItem({ row, enter, create, rename, remove, t }: {\n row: WorkspaceRow\n enter: () => void\n create: () => void\n rename: () => void\n remove: () => void\n t: SidebarProps['t']\n}) {\n const [menuOpen, setMenuOpen] = useState(false)\n return (\n <div className={`ya-row ya-workspace-row${menuOpen ? ' ya-menu-open' : ''}`} role=\"treeitem\" onClick={enter} title={row.path}>\n <span className=\"ya-status-slot\"><IconFolderClose16 /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{row.real ? row.title : t('ungrouped')}</span>\n <span className=\"ya-row-meta\">{t('count', { n: row.count })}</span>\n </span>\n {row.path !== undefined && <span className=\"ya-workspace-path\">{row.path}</span>}\n </span>\n <span className=\"ya-row-actions\">\n {row.real && (\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'delete', label: t('deleteWorkspace'), icon: <IconTrashOutline16 />, danger: true },\n ]}\n onSelect={(id) => { setMenuOpen(false); if (id === 'rename') rename(); if (id === 'delete') remove() }}\n portal\n closeOnPointerLeave\n anchor={(\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}>\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n )}\n {row.real && (\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); create() }}>\n <IconPlusOutline16 />\n </button>\n )}\n </span>\n <IconChevronRightOutline14 />\n </div>\n )\n}\n\ninterface RemoteState {\n query: string\n status: 'idle' | 'loading' | 'ready' | 'error'\n items: readonly { sessionId: SessionId; snippet: string }[]\n hasMore: boolean\n}\n\n/** Fill `sidebar.workspaces` with the replacement browser. */\nexport function WorkspaceSidebar(props: SidebarProps) {\n const {\n wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions,\n searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace,\n archiveSession, insertSessionBefore, createWorkspace, useDirectoryFlow, renderSlot, t,\n } = props\n const sessions = useSessions(state => state)\n const workspaceState = useWorkspaces(state => state)\n const workspaces = workspaceState.items\n const archived = workspaceState.archivedSessionIds\n const directoryFlowAvailable = useDirectoryFlow(value => value)\n const allRows = useMemo(\n () => deriveRecent(sessions, workspaces, archived, Number.MAX_SAFE_INTEGER),\n [archived, sessions, workspaces],\n )\n const recent = allRows.slice(0, 5)\n const workspaceRows = useMemo(\n () => deriveWorkspaces(sessions, workspaces, archived),\n [archived, sessions, workspaces],\n )\n const [selectedKey, setSelectedKey] = useState<WorkspaceId | typeof UNGROUPED | null>(null)\n const [direction, setDirection] = useState<'forward' | 'backward'>('forward')\n const [hasMounted, setHasMounted] = useState(false)\n useEffect(() => { setHasMounted(true) }, [])\n const observedCurrent = useRef<SessionId | undefined>(undefined)\n const initialized = useRef(false)\n useEffect(() => {\n if (initialized.current && observedCurrent.current === sessions.current) return\n initialized.current = true\n observedCurrent.current = sessions.current\n if (sessions.current !== undefined) { setDirection('forward'); setSelectedKey(workspaceKeyForSession(sessions.current, workspaces)) }\n }, [sessions.current, workspaces])\n useEffect(() => {\n if (selectedKey !== null && selectedKey !== UNGROUPED\n && !workspaces.some(workspace => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED)\n }, [selectedKey, workspaces])\n const selectedWorkspace = selectedKey === null || selectedKey === UNGROUPED\n ? undefined\n : workspaces.find(workspace => workspace.workspaceId === selectedKey)\n const levelRows = selectedKey === null\n ? []\n : deriveWorkspaceSessions(selectedKey, sessions, workspaces, archived)\n const now = Date.now()\n\n const [query, setQuery] = useState('')\n const normalizedQuery = sanitized(query).trim()\n const [remote, setRemote] = useState<RemoteState>({ query: '', status: 'idle', items: [], hasMore: false })\n useEffect(() => {\n if (normalizedQuery === '') {\n setRemote({ query: '', status: 'idle', items: [], hasMore: false })\n return\n }\n const controller = new AbortController()\n setRemote({ query: normalizedQuery, status: 'loading', items: [], hasMore: false })\n const timer = window.setTimeout(() => {\n searchSessions(normalizedQuery, controller.signal).then(result => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'ready', items: result.items, hasMore: result.hasMore })\n }).catch(() => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'error', items: [], hasMore: false })\n })\n }, SEARCH_DEBOUNCE_MS)\n return () => { window.clearTimeout(timer); controller.abort() }\n }, [normalizedQuery, searchSessions])\n const searchRows = useMemo(() => {\n if (normalizedQuery === '') return []\n const byId = new Map(localMatches(allRows, normalizedQuery).map(row => [row.id, row]))\n if (remote.query === normalizedQuery) {\n for (const item of remote.items) {\n const row = allRows.find(candidate => candidate.id === item.sessionId)\n if (row !== undefined) byId.set(row.id, row)\n }\n }\n return [...byId.values()].slice(0, searchResultLimit)\n }, [allRows, normalizedQuery, remote, searchResultLimit])\n\n const [pickerOpen, setPickerOpen] = useState(false)\n const pickerAnchor = useRef<HTMLButtonElement>(null)\n const [recentCollapsed, setRecentCollapsed] = useState(false)\n const [workspaceRename, setWorkspaceRename] = useState<WorkspaceRow | null>(null)\n const [sessionRename, setSessionRename] = useState<SessionRow | null>(null)\n const [renameDraft, setRenameDraft] = useState('')\n const [renameError, setRenameError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [deleteTarget, setDeleteTarget] = useState<WorkspaceRow | null>(null)\n const [drag, setDrag] = useState<{ id: SessionId; over: { id: SessionId; half: 'before' | 'after' } | null } | null>(null)\n\n const beginWorkspaceRename = (row: WorkspaceRow) => { setWorkspaceRename(row); setRenameDraft(row.title); setRenameError(null) }\n const beginSessionRename = (row: SessionRow) => { setSessionRename(row); setRenameDraft(row.title); setRenameError(null) }\n const closeRename = () => { if (!busy) { setWorkspaceRename(null); setSessionRename(null); setRenameError(null) } }\n const commitRename = () => {\n const title = renameDraft.trim()\n if (title === '' || busy) return\n setBusy(true)\n const task = workspaceRename !== null && workspaceRename.key !== UNGROUPED\n ? renameWorkspace(workspaceRename.key, title)\n : sessionRename !== null ? renameSession(sessionRename.id, title) : Promise.resolve()\n task.then(() => { setWorkspaceRename(null); setSessionRename(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const confirmDelete = () => {\n if (deleteTarget === null || deleteTarget.key === UNGROUPED || busy) return\n setBusy(true)\n deleteWorkspace(deleteTarget.key).then(() => { setDeleteTarget(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const archive = (id: SessionId) => { archiveSession(id).catch(reason => { console.warn('session archive rejected:', reason) }) }\n const fork = (id: SessionId) => { forkSession(id) }\n\n const sessionItem = (row: SessionRow, context = false, index?: number) => {\n const draggable = selectedKey !== null && selectedKey !== UNGROUPED && index !== undefined\n const marker = drag?.over?.id === row.id ? drag.over.half : null\n return (\n <SessionItem\n key={row.id}\n row={row}\n current={sessions.current}\n now={now}\n open={open}\n rename={beginSessionRename}\n fork={fork}\n archive={archive}\n t={t}\n context={context}\n {...draggable && selectedKey !== null && selectedKey !== UNGROUPED ? {\n drag: {\n active: drag !== null,\n marker,\n start: () => { setDrag({ id: row.id, over: null }) },\n hover: (half: 'before' | 'after') => { setDrag(value => value === null ? value : { ...value, over: { id: row.id, half } }) },\n drop: (half: 'before' | 'after') => {\n if (drag === null) return\n const anchor = half === 'before' ? row.id : levelRows[(index ?? 0) + 1]?.id\n const sourceIndex = levelRows.findIndex(item => item.id === drag.id)\n const anchorIndex = anchor === undefined ? levelRows.length : levelRows.findIndex(item => item.id === anchor)\n setDrag(null)\n if (anchor === drag.id || sourceIndex === anchorIndex || sourceIndex + 1 === anchorIndex) return\n insertSessionBefore(selectedKey, drag.id, anchor).catch(reason => { console.warn('session reorder rejected:', reason) })\n },\n end: () => { setDrag(null) },\n },\n } : {}}\n />\n )\n }\n\n return (\n <div data-ya-workspace-sidebar className={wide ? '' : 'ya-rail'}>\n <div className=\"ya-section-header\">\n {wide && <span className=\"ya-section-title\">{t('workspaces')}</span>}\n {directoryFlowAvailable && (\n <button ref={pickerAnchor} type=\"button\" className=\"ya-icon-button\" aria-label={t('addWorkspace')} onClick={() => { setPickerOpen(value => !value) }}>\n <IconProjectAddOutline16 size={wide ? 16 : 18} />\n </button>\n )}\n <WorkspacePickFlow\n t={t}\n open={pickerOpen}\n anchorRef={pickerAnchor}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('sidebar.workspaces.directoryFlow', owner)}\n addOnly\n side=\"right\"\n onPick={(workspaceId) => { setPickerOpen(false); startSession(workspaceId) }}\n onClose={() => { setPickerOpen(false) }}\n />\n </div>\n\n <div className=\"ya-search\" onClick={() => { if (!wide) expandSidebar() }}>\n <button type=\"button\" className=\"ya-search-icon\" aria-label={t('search')}><IconSearchOutline16 size={wide ? 14 : 18} /></button>\n {wide && <input className=\"ya-search-input\" value={query} maxLength={SEARCH_MAX} placeholder={t('searchPlaceholder')} onChange={event => { setQuery(sanitized(event.target.value)) }} />}\n {wide && query !== '' && <button type=\"button\" className=\"ya-icon-button\" aria-label={t('clearSearch')} onClick={() => { setQuery('') }}><IconCloseFill14 /></button>}\n </div>\n\n {wide && (\n <div className=\"ya-body\">\n {normalizedQuery !== '' ? (\n <div className=\"ya-scroll\" role=\"tree\" aria-label={t('search')}>\n {searchRows.map(row => sessionItem(row, true))}\n {remote.status === 'loading' && <div className=\"ya-status\">{t('searching')}</div>}\n {remote.status === 'error' && <div className=\"ya-status ya-warning\">{t('searchUnavailable')}</div>}\n {remote.status !== 'loading' && searchRows.length === 0 && <div className=\"ya-empty\">{t('noMatches')}</div>}\n </div>\n ) : (\n <>\n <div className={`ya-recent${recentCollapsed ? ' ya-recent-collapsed' : ''}`}>\n <div className=\"ya-block-label\">\n <span>{t('recent')}</span>\n {recent.length > 0 && (\n <button\n type=\"button\"\n className={`ya-block-label-toggle${recentCollapsed ? ' ya-collapsed' : ''}`}\n aria-label={recentCollapsed ? t('expand') : t('collapse')}\n aria-expanded={!recentCollapsed}\n onClick={(event) => { event.stopPropagation(); setRecentCollapsed(value => !value) }}\n >\n <IconChevronRightOutline14 />\n </button>\n )}\n </div>\n <div className=\"ya-recent-list-wrap\">\n {recent.length === 0\n ? <div className=\"ya-empty\">{t('noSessions')}</div>\n : <div className=\"ya-recent-list\">{recent.map(row => sessionItem(row, true))}</div>\n }\n </div>\n </div>\n <div className=\"ya-breadcrumb\">\n {selectedKey === null ? (\n <span className=\"ya-crumb\">{t('workspaces')}</span>\n ) : (\n <>\n <button type=\"button\" className=\"ya-crumb\" onClick={() => { setDirection('backward'); setSelectedKey(null) }}>{t('workspaces')}</button>\n <IconChevronRightOutline14 />\n <span className=\"ya-crumb\">{selectedKey === UNGROUPED ? t('ungrouped') : selectedWorkspace?.title}</span>\n {selectedKey !== UNGROUPED && (\n <button type=\"button\" className=\"ya-icon-button\" aria-label={t('newSession')} onClick={() => { startSession(selectedKey) }}><IconPlusOutline16 /></button>\n )}\n </>\n )}\n </div>\n <div className=\"ya-scroll\" role=\"tree\" aria-label={selectedKey === null ? t('workspaces') : t('sessions')}>\n <div key={selectedKey ?? 'root'} className={hasMounted ? `ya-level-enter-${direction}` : undefined}>\n {selectedKey === null\n ? workspaceRows.map(row => (\n <WorkspaceItem\n key={row.key}\n row={row}\n enter={() => { setDirection('forward'); setSelectedKey(row.key) }}\n create={() => { if (row.key !== UNGROUPED) startSession(row.key) }}\n rename={() => { beginWorkspaceRename(row) }}\n remove={() => { setDeleteTarget(row); setRenameError(null) }}\n t={t}\n />\n ))\n : levelRows.map((row, index) => sessionItem(row, false, index))}\n {selectedKey === null && workspaceRows.length === 0 && <div className=\"ya-empty\">{t('noWorkspaces')}</div>}\n {selectedKey !== null && levelRows.length === 0 && <div className=\"ya-empty\">{t('noSessions')}</div>}\n </div>\n </div>\n </>\n )}\n </div>\n )}\n\n <Modal\n open={workspaceRename !== null || sessionRename !== null}\n onClose={closeRename}\n closeLabel={t('cancel')}\n title={workspaceRename !== null ? t('renameWorkspace') : t('renameSession')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={closeRename}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={busy || renameDraft.trim() === ''} onClick={commitRename}>{t('rename')}</Button>\n </>\n )}\n >\n <input className=\"ya-rename-input\" value={renameDraft} autoFocus disabled={busy} aria-label={workspaceRename !== null ? t('workspaceName') : t('sessionName')} onChange={event => { setRenameDraft(event.target.value); setRenameError(null) }} />\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={deleteTarget !== null}\n onClose={() => { if (!busy) setDeleteTarget(null) }}\n closeLabel={t('cancel')}\n title={t('deleteWorkspace')}\n description={deleteTarget === null ? undefined : t('deleteDescription', { name: deleteTarget.title })}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={() => { setDeleteTarget(null) }}>{t('cancel')}</Button>\n <Button variant=\"outline\" disabled={busy} onClick={confirmDelete}>{t('deleteWorkspace')}</Button>\n </>\n )}\n >\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n </div>\n )\n}\n","/** Client assembly for the replacement workspace sidebar and hero picker. */\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { PickerInjected, SidebarInjected } from './contract.ts'\nimport { en, NS, zh } from './locales.ts'\nimport { installStyles } from './styles.ts'\nimport { WorkspacePicker } from './WorkspacePicker.tsx'\nimport { WorkspaceSidebar } from './WorkspaceSidebar.tsx'\n\n/** Services required by both replacement client entries. */\nexport const inject = ['slots', 'sessions', 'workspaces', 'locale']\n\n/** Register the sidebar browser and conversation hero picker. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ya-workspace-sidebar: dictionaries')\n ctx.effect(installStyles, 'ya-workspace-sidebar: styles')\n\n const flowSource = (\n name: 'sidebar.workspaces.directoryFlow' | 'conversation.hero.workspace.directoryFlow',\n ): HostObservable<boolean> => ({\n getSnapshot: () => ctx.slots.entries(name).length > 0,\n subscribe: listener => ctx.slots.subscribe(name, listener),\n })\n const sidebarFlow = flowSource('sidebar.workspaces.directoryFlow')\n const pickerFlow = flowSource('conversation.hero.workspace.directoryFlow')\n const createWorkspace = (input: { path: string }) => ctx.workspaces.create(input)\n\n const searchSessions: SidebarInjected['searchSessions'] = async (query, signal) => {\n const result = await ctx.sessions.search(query, signal)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n }\n const sidebarInjected = (): SidebarInjected => ({\n startSession: workspaceId => { ctx.workspaces.startSession(workspaceId) },\n open: sessionId => { ctx.sessions.open(sessionId) },\n searchSessions,\n searchResultLimit: ctx.sessions.searchResultLimit,\n renameSession: async (sessionId, title) => {\n const session = ctx.sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error(`unknown session \"${sessionId}\"`)\n const result = await session.rename(title)\n if (!result.ok) throw new Error(result.error.message)\n },\n forkSession: sessionId => {\n ctx.sessions.fork({ sessionId, increaseTitle: true })\n .then(childId => { ctx.sessions.open(childId) })\n .catch(() => {})\n },\n renameWorkspace: async (workspaceId, title) => { await ctx.workspaces.rename(workspaceId, title) },\n deleteWorkspace: async workspaceId => { await ctx.workspaces.delete(workspaceId) },\n archiveSession: async sessionId => { await ctx.workspaces.archiveSession(sessionId) },\n insertSessionBefore: async (workspaceId, sessionId, beforeSessionId) => {\n await ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId)\n },\n createWorkspace,\n hooks: { directoryFlow: sidebarFlow },\n })\n const pickerInjected = (): PickerInjected => ({\n createWorkspace,\n hooks: { directoryFlow: pickerFlow },\n })\n\n ctx.slots.inject('sidebar.workspaces', () => ctx.slots.register({\n name: 'sidebar.workspaces',\n children: { 'sidebar.workspaces.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: sidebarInjected,\n locale: NS,\n }, WorkspaceSidebar))\n\n ctx.slots.inject('conversation.hero.workspace', () => ctx.slots.register({\n name: 'conversation.hero.workspace',\n children: { 'conversation.hero.workspace.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: pickerInjected,\n locale: NS,\n }, WorkspacePicker))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","useCallback","IconPlusOutline16","IconFolderClose16","Menu","Modal","Button","StateDot","useState","IconTrashOutline16","IconArchiveOutline20","Menu","IconEditOutline16","IconBranchOutline16","IconEllipsisOutline16","IconFolderClose16","IconPlusOutline16","IconChevronRightOutline14","useMemo","useRef","IconProjectAddOutline16","IconSearchOutline16","IconCloseFill14","Modal","Button"],"sources":["../src/client/locales.ts","../src/client/styles.ts","../src/client/WorkspacePicker.tsx","../src/client/model.ts","../src/client/settings.ts","../src/client/WorkspaceSidebar.tsx","../src/client/index.ts"],"sourcesContent":["/** Product copy for the replacement workspace browser. */\nexport const zh = {\n workspaces: '工作区',\n sessions: '会话',\n recent: '最近会话',\n ungrouped: '未分组',\n newSession: '新会话',\n addWorkspace: '添加工作区',\n addWorkspaceMenu: '添加工作区…',\n search: '搜索会话',\n searchPlaceholder: '搜索名称、关键词…',\n clearSearch: '清除搜索',\n searching: '正在搜索会话历史…',\n searchUnavailable: '内容搜索暂不可用,仅显示名称匹配。',\n noMatches: '无匹配会话',\n noSessions: '暂无会话',\n noWorkspaces: '暂无工作区',\n loading: '正在加载工作区…',\n rename: '重命名',\n renameWorkspace: '重命名工作区',\n renameSession: '重命名会话',\n deleteWorkspace: '删除工作区',\n deleteDescription: '将把“{name}”从工作区列表中移除。文件夹与会话记录会保留。',\n fork: '分叉会话',\n archive: '归档会话',\n archiveMode: '归档模式',\n deleteMode: '删除模式',\n deleteSession: '删除会话',\n deleteSessionTitle: '删除会话',\n deleteSessionConfirm: '确定要删除此会话吗?删除后将从列表中移除,此操作不可撤销。',\n toggleActionMode: '切换归档/删除模式',\n actionModeLabel: '会话操作',\n cancel: '取消',\n confirm: '确认',\n retry: '重新选择',\n folderError: '无法打开文件夹',\n workspaceName: '工作区名称',\n sessionName: '会话名称',\n count: '{n} 个会话',\n now: '刚刚',\n minutes: '{n}分钟',\n hours: '{n}小时',\n days: '{n}天',\n months: '{n}个月',\n years: '{n}年',\n running: '进行中',\n waiting: '等待交互',\n completed: '已完成',\n collapse: '折叠',\n expand: '展开',\n today: '今天',\n yesterday: '昨天',\n date: '{m}月{d}日',\n dateYear: '{y}年{m}月{d}日',\n} satisfies Record<string, string>\n\nexport type YaWorkspaceKey = keyof typeof zh\n\nexport const en = {\n workspaces: 'Workspaces',\n sessions: 'Sessions',\n recent: 'Recent Sessions',\n ungrouped: 'Ungrouped',\n newSession: 'New Session',\n addWorkspace: 'Add workspace',\n addWorkspaceMenu: 'Add workspace…',\n search: 'Search sessions',\n searchPlaceholder: 'Search name, keywords...',\n clearSearch: 'Clear search',\n searching: 'Searching session history…',\n searchUnavailable: 'Content search is unavailable. Showing name matches.',\n noMatches: 'No matching sessions',\n noSessions: 'No sessions yet',\n noWorkspaces: 'No workspaces yet',\n loading: 'Loading workspaces…',\n rename: 'Rename',\n renameWorkspace: 'Rename workspace',\n renameSession: 'Rename session',\n deleteWorkspace: 'Delete workspace',\n deleteDescription: 'This removes “{name}” from the workspace list. The folder and session logs remain.',\n fork: 'Fork session',\n archive: 'Archive session',\n archiveMode: 'Archive mode',\n deleteMode: 'Delete mode',\n deleteSession: 'Delete session',\n deleteSessionTitle: 'Delete session',\n deleteSessionConfirm: 'Are you sure you want to delete this session? It will be removed from the list. This cannot be undone.',\n toggleActionMode: 'Toggle archive/delete mode',\n actionModeLabel: 'Session action',\n cancel: 'Cancel',\n confirm: 'Confirm',\n retry: 'Choose again',\n folderError: 'Couldn’t open folder',\n workspaceName: 'Workspace name',\n sessionName: 'Session name',\n count: '{n} sessions',\n now: 'now',\n minutes: '{n}min',\n hours: '{n}h',\n days: '{n}d',\n months: '{n}mo',\n years: '{n}y',\n running: 'Running',\n waiting: 'Waiting for interaction',\n completed: 'Completed',\n collapse: 'Collapse',\n expand: 'Expand',\n today: 'Today',\n yesterday: 'Yesterday',\n date: '{m}/{d}',\n dateYear: '{m}/{d}/{y}',\n} satisfies Record<YaWorkspaceKey, string>\n\nexport const NS = 'ya-workspace-sidebar'\n","/** One scoped stylesheet injected for the lifetime of the client activation. */\nexport const CSS = `\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-date-group-label { height:26px; display:flex; align-items:center; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }\n.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }\n.ya-rail .ya-search { justify-content:center; }\n.ya-rail .ya-search-icon { cursor:pointer; color:var(--dsw-alias-label-primary); }\n.ya-picker-error { color:var(--dsw-alias-status-error); white-space:pre-wrap; }\n.ya-action-mode-toggle.ya-action-mode-delete { color:var(--dsw-alias-state-error-primary); }\n.ya-action-mode-toggle.ya-action-mode-delete:hover { background:var(--dsw-alias-interactive-bg-hover-danger); }\n@keyframes ya-slide-in-forward { from { opacity:0; transform:translateX(10px); } to { opacity:1; transform:translateX(0); } }\n@keyframes ya-slide-in-backward { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:translateX(0); } }\n.ya-level-enter-forward { animation:ya-slide-in-forward 180ms ease-out; }\n.ya-level-enter-backward { animation:ya-slide-in-backward 180ms ease-out; }\n`\n\n/** Install the stylesheet and return its disposer. */\nexport function installStyles(): () => void {\n const style = document.createElement('style')\n style.setAttribute('data-ya-workspace-sidebar-style', '')\n style.textContent = CSS\n document.head.appendChild(style)\n return () => { style.remove() }\n}\n","/** Existing-workspace menu plus composed directory-adoption flow. */\nimport type { ReactNode, RefObject } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport {\n Button, IconFolderClose16, IconPlusOutline16, Menu, Modal, type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n WorkspaceId, WorkspaceListState, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts'\n\nconst ADD = '::ya-add-workspace'\n\ninterface FlowProps {\n t: PickerProps['t']\n open: boolean\n anchorRef?: RefObject<HTMLElement | null>\n useWorkspaces: <S>(selector: (state: WorkspaceListState) => S) => S\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n useDirectoryFlow: SnapshotSelectorHook<boolean>\n renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode\n onPick: (workspaceId: WorkspaceId) => void\n onClose: () => void\n addOnly?: boolean\n side?: 'bottom' | 'top' | 'right'\n selectedId?: WorkspaceId\n}\n\n/** Render the workspace target menu and directory picking conversation. */\nexport function WorkspacePickFlow({\n t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow,\n renderDirectoryFlow, onPick, onClose, addOnly = false, side = 'bottom', selectedId,\n}: FlowProps) {\n const snapshot = useWorkspaces(state => state)\n const flowAvailable = useDirectoryFlow(value => value)\n const [flowOpen, setFlowOpen] = useState(false)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const getAnchorRect = useCallback(\n () => anchorRef?.current?.getBoundingClientRect() ?? null,\n [anchorRef],\n )\n useEffect(() => {\n if (flowOpen && !flowAvailable) setFlowOpen(false)\n }, [flowAvailable, flowOpen])\n\n const openFlow = useCallback(() => {\n onClose()\n setError(null)\n setFlowOpen(true)\n }, [onClose])\n const addEntries: MenuEntry[] = flowAvailable\n ? [{ id: ADD, label: t('addWorkspaceMenu'), icon: <IconPlusOutline16 size={16} />, disabled: flowOpen || busy }]\n : []\n const pinnedAdd = !addOnly && snapshot.items.length > 0\n const items: MenuEntry[] = pinnedAdd\n ? snapshot.items.map(workspace => ({\n id: workspace.workspaceId,\n label: workspace.title,\n icon: <IconFolderClose16 size={16} />,\n disabled: flowOpen || busy,\n }))\n : addEntries\n const settled = addOnly || snapshot.phase === 'ready'\n const onlyAdd = !pinnedAdd && settled && addEntries.length === 1\n useEffect(() => {\n if (open && onlyAdd && !flowOpen && !busy) openFlow()\n }, [busy, flowOpen, onlyAdd, open, openFlow])\n\n const owner: DirectoryFlowOwnerProps = {\n open: flowOpen,\n busy,\n onPicked: (path) => {\n setBusy(true)\n createWorkspace({ path }).then(workspace => {\n setFlowOpen(false)\n onPick(workspace.workspaceId)\n }).catch((reason: unknown) => {\n setFlowOpen(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n }).finally(() => { setBusy(false) })\n },\n onCancel: () => { setFlowOpen(false) },\n onError: (message) => { setFlowOpen(false); setError(message) },\n }\n\n return (\n <>\n <Menu\n open={open && !onlyAdd && items.length > 0}\n anchor={null}\n items={items}\n {...pinnedAdd ? { footer: addEntries } : {}}\n selectedId={selectedId}\n onSelect={(id) => { if (id === ADD) openFlow(); else onPick(id as WorkspaceId) }}\n onClose={onClose}\n side={side}\n portal\n getAnchorRect={getAnchorRect}\n />\n {open && !onlyAdd && snapshot.phase === 'pending' && <div className=\"ya-status\">{t('loading')}</div>}\n {renderDirectoryFlow(owner)}\n <Modal\n open={error !== null}\n onClose={() => { setError(null) }}\n closeLabel={t('cancel')}\n title={t('folderError')}\n footer={(\n <>\n <Button variant=\"outline\" onClick={() => { setError(null) }}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={!flowAvailable} onClick={openFlow}>{t('retry')}</Button>\n </>\n )}\n >\n <div className=\"ya-picker-error\" role=\"alert\">{error}</div>\n </Modal>\n </>\n )\n}\n\n/** Fill the conversation hero's workspace picker seat. */\nexport function WorkspacePicker({\n open, anchorRef, useWorkspaces, selectedId, onPick, onClose,\n createWorkspace, useDirectoryFlow, renderSlot, t,\n}: PickerProps) {\n return (\n <WorkspacePickFlow\n t={t}\n open={open}\n anchorRef={anchorRef}\n useWorkspaces={useWorkspaces}\n selectedId={selectedId}\n onPick={onPick}\n onClose={onClose}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('conversation.hero.workspace.directoryFlow', owner)}\n />\n )\n}\n","/** Pure sidebar projections shared by the browser and unit tests. */\nimport type {\n SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\n\n/** Navigation key for sessions not accounted to a real workspace. */\nexport const UNGROUPED = '__ya_ungrouped__' as const\n\n/** One sidebar session row. */\nexport interface SessionRow {\n id: SessionId\n title: string\n blank: boolean\n running: boolean\n pendingInteraction?: SessionSummary['pendingInteraction']\n completed: boolean\n updatedAt: number\n workspaceKey: WorkspaceId | typeof UNGROUPED\n workspaceTitle: string\n}\n\n/** One date-bucketed group of session rows for the real-workspace level. */\nexport interface SessionDateGroup {\n /** Local calendar date `YYYY-MM-DD`, stable key. */\n dateKey: string\n /** Days between today's local date and this group's local date (0=today, 1=yesterday, …). */\n dayOffset: number\n rows: SessionRow[]\n}\n\n/** One first-level workspace row. */\nexport interface WorkspaceRow {\n key: WorkspaceId | typeof UNGROUPED\n title: string\n path?: string\n createdAt?: string\n count: number\n real: boolean\n}\n\nfunction visible(summary: SessionSummary, current: SessionId | undefined, archived: ReadonlySet<SessionId>): boolean {\n return summary.origin !== 'subagent'\n && !archived.has(summary.id)\n && (!summary.blank || summary.id === current)\n}\n\nfunction rowOf(\n summary: SessionSummary,\n workspaceKey: WorkspaceId | typeof UNGROUPED,\n workspaceTitle: string,\n): SessionRow {\n return {\n id: summary.id,\n title: summary.blank ? 'New Session' : summary.displayTitle,\n blank: summary.blank,\n running: summary.running,\n ...(summary.pendingInteraction === undefined ? {} : { pendingInteraction: summary.pendingInteraction }),\n completed: summary.completed === true,\n updatedAt: summary.updatedAt,\n workspaceKey,\n workspaceTitle,\n }\n}\n\nfunction ownerIndex(workspaces: readonly WorkspaceView[]): Map<SessionId, WorkspaceView> {\n const result = new Map<SessionId, WorkspaceView>()\n for (const workspace of workspaces) {\n for (const sessionId of workspace.sessionIds) result.set(sessionId, workspace)\n }\n return result\n}\n\n/** Resolve the first/second-level destination for one session. */\nexport function workspaceKeyForSession(\n sessionId: SessionId | undefined,\n workspaces: readonly WorkspaceView[],\n): WorkspaceId | typeof UNGROUPED | null {\n if (sessionId === undefined) return null\n return ownerIndex(workspaces).get(sessionId)?.workspaceId ?? UNGROUPED\n}\n\n/** Derive global recent sessions, newest first. */\nexport function deriveRecent(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n limit = 5,\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n const owners = ownerIndex(workspaces)\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .slice(0, limit)\n .map((summary) => {\n const workspace = owners.get(summary.id)\n return rowOf(summary, workspace?.workspaceId ?? UNGROUPED, workspace?.title ?? 'Ungrouped')\n })\n}\n\n/** Derive first-level real workspaces plus the virtual Ungrouped row. */\nexport function deriveWorkspaces(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): WorkspaceRow[] {\n const archived = new Set(archivedSessionIds)\n const accounted = new Set<SessionId>()\n const result = workspaces.map((workspace): WorkspaceRow => {\n let count = 0\n for (const id of workspace.sessionIds) {\n accounted.add(id)\n const summary = list.byId[id]\n if (summary !== undefined && visible(summary, list.current, archived)) count++\n }\n return {\n key: workspace.workspaceId,\n title: workspace.title,\n path: workspace.path,\n createdAt: workspace.createdAt,\n count,\n real: true,\n }\n })\n let ungrouped = 0\n for (const id of list.ids) {\n const summary = list.byId[id]\n if (summary !== undefined && !accounted.has(id) && visible(summary, list.current, archived)) ungrouped++\n }\n result.push({ key: UNGROUPED, title: 'Ungrouped', count: ungrouped, real: false })\n return result\n}\n\n/** Derive the selected workspace's sessions in its canonical order. */\nexport function deriveWorkspaceSessions(\n key: WorkspaceId | typeof UNGROUPED,\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n if (key === UNGROUPED) {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined\n && !accounted.has(summary.id)\n && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .map(summary => rowOf(summary, UNGROUPED, 'Ungrouped'))\n }\n const workspace = workspaces.find(item => item.workspaceId === key)\n if (workspace === undefined) return []\n return workspace.sessionIds\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .map(summary => rowOf(summary, workspace.workspaceId, workspace.title))\n}\n\n/** Format a local calendar date as `YYYY-MM-DD` (locale-agnostic, no padding surprises). */\nfunction localDateKey(year: number, month: number, day: number): string {\n const mm = month < 9 ? `0${month + 1}` : `${month + 1}`\n const dd = day < 10 ? `0${day}` : `${day}`\n return `${year}-${mm}-${dd}`\n}\n\n/** Whole-day difference between two local calendar dates (a - b) using UTC midnight. */\nfunction dayDiff(a: { year: number; month: number; day: number }, b: { year: number; month: number; day: number }): number {\n const msA = Date.UTC(a.year, a.month, a.day)\n const msB = Date.UTC(b.year, b.month, b.day)\n return Math.round((msA - msB) / 86_400_000)\n}\n\n/**\n * Derive the selected real workspace's sessions grouped by local calendar date.\n *\n * - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.\n * - Groups are ordered by date descending; rows within a group by `updatedAt` descending.\n * - {@link visible} filter is reused (archived / subagent / blank visibility).\n * - Future timestamps clamp to today's bucket (`dayOffset` 0).\n * - `now` is the reference timestamp for \"today\"; pass `Date.now()` in production.\n */\nexport function deriveWorkspaceSessionGroups(\n key: WorkspaceId | typeof UNGROUPED,\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n now: number,\n): SessionDateGroup[] {\n if (key === UNGROUPED) return []\n const workspace = workspaces.find(item => item.workspaceId === key)\n if (workspace === undefined) return []\n const archived = new Set(archivedSessionIds)\n const rows = workspace.sessionIds\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .map(summary => rowOf(summary, workspace.workspaceId, workspace.title))\n if (rows.length === 0) return []\n\n const nowDate = new Date(now)\n const today = { year: nowDate.getFullYear(), month: nowDate.getMonth(), day: nowDate.getDate() }\n\n const buckets = new Map<string, { dayOffset: number; rows: SessionRow[] }>()\n for (const row of rows) {\n const ts = Math.min(row.updatedAt, now)\n const d = new Date(ts)\n const date = { year: d.getFullYear(), month: d.getMonth(), day: d.getDate() }\n const dateKey = localDateKey(date.year, date.month, date.day)\n let bucket = buckets.get(dateKey)\n if (bucket === undefined) {\n // dayOffset = today - date (positive for past dates). Future timestamps were\n // clamped to `now` above, so `date` never exceeds today; Math.max guards rounding noise.\n const offset = Math.max(0, dayDiff(today, date))\n bucket = { dayOffset: offset, rows: [] }\n buckets.set(dateKey, bucket)\n }\n bucket.rows.push(row)\n }\n\n const groups: SessionDateGroup[] = []\n for (const [dateKey, bucket] of buckets) {\n bucket.rows.sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n groups.push({ dateKey, dayOffset: bucket.dayOffset, rows: bucket.rows })\n }\n // Sort groups by date descending: newest date first = smallest dayOffset first.\n groups.sort((a, b) => a.dayOffset - b.dayOffset || a.dateKey.localeCompare(b.dateKey))\n return groups\n}\n\n/** Case-insensitive local title/workspace matching used beside Host content search. */\nexport function localMatches(rows: readonly SessionRow[], query: string): SessionRow[] {\n const normalized = query.trim().toLocaleLowerCase()\n if (normalized === '') return []\n return rows.filter(row => `${row.title}\\n${row.workspaceTitle}`.toLocaleLowerCase().includes(normalized))\n}\n","/**\n * Browser-local preference controlling whether the session row's destructive\n * action presents as Archive (default) or Delete. Delete mode renders the\n * row action red with a trash icon and gates the call behind a confirmation\n * modal; the underlying Host verb remains `archiveSession` (the only\n * session-level destructive API exposed by `ctx.workspaces`), which hides\n * the session from grouping surfaces while preserving its log.\n *\n * The preference is persisted to `localStorage` so it survives reloads and\n * remounts without host-side plumbing. Cross-device sync is intentionally\n * out of scope: this is a per-browser UX preference, not a deployment knob.\n */\n\n/** How the session row's destructive action presents and behaves. */\nexport type SessionActionMode = 'archive' | 'delete'\n\nconst STORAGE_KEY = 'ya-workspace-sidebar:action-mode'\n\nconst listeners = new Set<() => void>()\nlet currentMode: SessionActionMode = loadMode()\n\n/** Read the stored preference, falling back to `archive` on any failure. */\nfunction loadMode(): SessionActionMode {\n try {\n const value = window.localStorage.getItem(STORAGE_KEY)\n return value === 'delete' ? 'delete' : 'archive'\n } catch {\n return 'archive'\n }\n}\n\n/** Persist the preference; silently ignores quota or privacy-mode failures. */\nfunction persistMode(mode: SessionActionMode): void {\n try {\n window.localStorage.setItem(STORAGE_KEY, mode)\n } catch {\n // localStorage may be unavailable (private mode, quota exceeded); the\n // in-memory value still drives the current session.\n }\n}\n\n/** Current action mode snapshot. */\nexport function getActionMode(): SessionActionMode {\n return currentMode\n}\n\n/** Switch the action mode and notify subscribers. */\nexport function setActionMode(mode: SessionActionMode): void {\n if (mode === currentMode) return\n currentMode = mode\n persistMode(mode)\n for (const listener of [...listeners]) listener()\n}\n\n/** Subscribe to action mode changes; returns an unsubscribe disposer. */\nexport function subscribeActionMode(listener: () => void): () => void {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n}\n","/** Two-level workspace/session browser with a persistent global recent block. */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n Button, IconArchiveOutline20, IconBranchOutline16, IconChevronRightOutline14,\n IconCloseFill14, IconEditOutline16, IconEllipsisOutline16, IconFolderClose16,\n IconPlusOutline16, IconProjectAddOutline16, IconSearchOutline16, IconTrashOutline16,\n Menu, Modal, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { SessionId, WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SidebarProps } from './contract.ts'\nimport {\n deriveRecent, deriveWorkspaceSessionGroups, deriveWorkspaceSessions, deriveWorkspaces,\n localMatches, UNGROUPED, workspaceKeyForSession, type SessionDateGroup, type SessionRow,\n type WorkspaceRow,\n} from './model.ts'\nimport type { SessionActionMode } from './settings.ts'\nimport { getActionMode, setActionMode, subscribeActionMode } from './settings.ts'\nimport { WorkspacePickFlow } from './WorkspacePicker.tsx'\n\nconst SEARCH_DEBOUNCE_MS = 250\nconst SEARCH_MAX = 500\n\nfunction sanitized(value: string): string {\n return value.replaceAll('\\0', '').slice(0, SEARCH_MAX)\n}\n\nfunction relativeTime(updatedAt: number, now: number, t: SidebarProps['t']): string {\n const diff = Math.max(0, now - updatedAt)\n const minute = 60_000\n if (diff < minute) return t('now')\n if (diff < 60 * minute) return t('minutes', { n: Math.floor(diff / minute) })\n if (diff < 24 * 60 * minute) return t('hours', { n: Math.floor(diff / (60 * minute)) })\n if (diff < 30 * 24 * 60 * minute) return t('days', { n: Math.floor(diff / (24 * 60 * minute)) })\n if (diff < 365 * 24 * 60 * minute) return t('months', { n: Math.floor(diff / (30 * 24 * 60 * minute)) })\n return t('years', { n: Math.floor(diff / (365 * 24 * 60 * minute)) })\n}\n\n/** Format a date group's localized title from its dayOffset and `YYYY-MM-DD` key. */\nfunction dateGroupLabel(group: SessionDateGroup, now: number, t: SidebarProps['t']): string {\n if (group.dayOffset === 0) return t('today')\n if (group.dayOffset === 1) return t('yesterday')\n const parts = group.dateKey.split('-')\n const year = Number(parts[0])\n const month = Number(parts[1])\n const day = Number(parts[2])\n const nowDate = new Date(now)\n if (year === nowDate.getFullYear()) return t('date', { m: month, d: day })\n return t('dateYear', { y: year, m: month, d: day })\n}\n\nfunction SessionStatus({ row }: { row: SessionRow }) {\n if (row.pendingInteraction !== undefined) return <StateDot state=\"warning\" />\n if (row.running) return <StateDot state=\"ongoing\" />\n if (row.completed) return <StateDot state=\"done\" />\n return null\n}\n\ninterface SessionRowProps {\n row: SessionRow\n current: SessionId | undefined\n now: number\n open: (id: SessionId) => void\n rename: (row: SessionRow) => void\n fork: (id: SessionId) => void\n archive: (id: SessionId) => void\n t: SidebarProps['t']\n context?: boolean\n actionMode: SessionActionMode\n}\n\nfunction SessionItem({ row, current, now, open, rename, fork, archive, t, context, actionMode }: SessionRowProps) {\n const [menuOpen, setMenuOpen] = useState(false)\n const title = row.blank ? t('newSession') : row.title\n const isDelete = actionMode === 'delete'\n const actionLabel = isDelete ? t('deleteSession') : t('archive')\n const actionIcon = isDelete ? <IconTrashOutline16 /> : <IconArchiveOutline20 size={16} />\n return (\n <div\n className={`ya-row${row.id === current ? ' ya-selected' : ''}${menuOpen ? ' ya-menu-open' : ''}`}\n role=\"treeitem\"\n aria-selected={row.id === current}\n onClick={() => { open(row.id) }}\n >\n <span className=\"ya-status-slot\"><SessionStatus row={row} /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{title}</span>\n {!row.blank && <span className=\"ya-row-meta ya-row-time\">{relativeTime(row.updatedAt, now, t)}</span>}\n </span>\n {context === true && <span className=\"ya-search-workspace\">{row.workspaceTitle}</span>}\n </span>\n {!row.blank && (\n <span className=\"ya-row-actions\">\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'fork', label: t('fork'), icon: <IconBranchOutline16 /> },\n { id: 'archive', label: actionLabel, icon: actionIcon, danger: isDelete },\n ]}\n onSelect={(id) => {\n setMenuOpen(false)\n if (id === 'rename') rename(row)\n if (id === 'fork') fork(row.id)\n if (id === 'archive') archive(row.id)\n }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className=\"ya-icon-button\"\n aria-label={`${title} actions`}\n onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}\n >\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n </span>\n )}\n </div>\n )\n}\n\nfunction WorkspaceItem({ row, enter, create, rename, remove, t }: {\n row: WorkspaceRow\n enter: () => void\n create: () => void\n rename: () => void\n remove: () => void\n t: SidebarProps['t']\n}) {\n const [menuOpen, setMenuOpen] = useState(false)\n return (\n <div className={`ya-row ya-workspace-row${menuOpen ? ' ya-menu-open' : ''}`} role=\"treeitem\" onClick={enter} title={row.path}>\n <span className=\"ya-status-slot\"><IconFolderClose16 /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{row.real ? row.title : t('ungrouped')}</span>\n <span className=\"ya-row-meta\">{t('count', { n: row.count })}</span>\n </span>\n {row.path !== undefined && <span className=\"ya-workspace-path\">{row.path}</span>}\n </span>\n <span className=\"ya-row-actions\">\n {row.real && (\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'delete', label: t('deleteWorkspace'), icon: <IconTrashOutline16 />, danger: true },\n ]}\n onSelect={(id) => { setMenuOpen(false); if (id === 'rename') rename(); if (id === 'delete') remove() }}\n portal\n closeOnPointerLeave\n anchor={(\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}>\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n )}\n {row.real && (\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); create() }}>\n <IconPlusOutline16 />\n </button>\n )}\n </span>\n <IconChevronRightOutline14 />\n </div>\n )\n}\n\ninterface RemoteState {\n query: string\n status: 'idle' | 'loading' | 'ready' | 'error'\n items: readonly { sessionId: SessionId; snippet: string }[]\n hasMore: boolean\n}\n\n/** Fill `sidebar.workspaces` with the replacement browser. */\nexport function WorkspaceSidebar(props: SidebarProps) {\n const {\n wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions,\n searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace,\n archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t,\n } = props\n const sessions = useSessions(state => state)\n const workspaceState = useWorkspaces(state => state)\n const workspaces = workspaceState.items\n const archived = workspaceState.archivedSessionIds\n const directoryFlowAvailable = useDirectoryFlow(value => value)\n const allRows = useMemo(\n () => deriveRecent(sessions, workspaces, archived, Number.MAX_SAFE_INTEGER),\n [archived, sessions, workspaces],\n )\n const recent = allRows.slice(0, 5)\n const workspaceRows = useMemo(\n () => deriveWorkspaces(sessions, workspaces, archived),\n [archived, sessions, workspaces],\n )\n const [selectedKey, setSelectedKey] = useState<WorkspaceId | typeof UNGROUPED | null>(null)\n const [direction, setDirection] = useState<'forward' | 'backward'>('forward')\n const [hasMounted, setHasMounted] = useState(false)\n useEffect(() => { setHasMounted(true) }, [])\n const observedCurrent = useRef<SessionId | undefined>(undefined)\n const initialized = useRef(false)\n useEffect(() => {\n if (initialized.current && observedCurrent.current === sessions.current) return\n initialized.current = true\n observedCurrent.current = sessions.current\n if (sessions.current !== undefined) { setDirection('forward'); setSelectedKey(workspaceKeyForSession(sessions.current, workspaces)) }\n }, [sessions.current, workspaces])\n useEffect(() => {\n if (selectedKey !== null && selectedKey !== UNGROUPED\n && !workspaces.some(workspace => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED)\n }, [selectedKey, workspaces])\n const selectedWorkspace = selectedKey === null || selectedKey === UNGROUPED\n ? undefined\n : workspaces.find(workspace => workspace.workspaceId === selectedKey)\n const now = Date.now()\n // Real workspace level renders date-bucketed groups; Ungrouped keeps the flat recency view.\n const levelGroups = useMemo(\n () => selectedKey !== null && selectedKey !== UNGROUPED\n ? deriveWorkspaceSessionGroups(selectedKey, sessions, workspaces, archived, now)\n : [],\n [archived, sessions, workspaces, selectedKey, now],\n )\n const levelRows = selectedKey === UNGROUPED\n ? deriveWorkspaceSessions(UNGROUPED, sessions, workspaces, archived)\n : []\n const levelEmpty = selectedKey === UNGROUPED ? levelRows.length === 0 : levelGroups.every(g => g.rows.length === 0)\n\n const [query, setQuery] = useState('')\n const normalizedQuery = sanitized(query).trim()\n const [remote, setRemote] = useState<RemoteState>({ query: '', status: 'idle', items: [], hasMore: false })\n useEffect(() => {\n if (normalizedQuery === '') {\n setRemote({ query: '', status: 'idle', items: [], hasMore: false })\n return\n }\n const controller = new AbortController()\n setRemote({ query: normalizedQuery, status: 'loading', items: [], hasMore: false })\n const timer = window.setTimeout(() => {\n searchSessions(normalizedQuery, controller.signal).then(result => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'ready', items: result.items, hasMore: result.hasMore })\n }).catch(() => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'error', items: [], hasMore: false })\n })\n }, SEARCH_DEBOUNCE_MS)\n return () => { window.clearTimeout(timer); controller.abort() }\n }, [normalizedQuery, searchSessions])\n const searchRows = useMemo(() => {\n if (normalizedQuery === '') return []\n const byId = new Map(localMatches(allRows, normalizedQuery).map(row => [row.id, row]))\n if (remote.query === normalizedQuery) {\n for (const item of remote.items) {\n const row = allRows.find(candidate => candidate.id === item.sessionId)\n if (row !== undefined) byId.set(row.id, row)\n }\n }\n return [...byId.values()].slice(0, searchResultLimit)\n }, [allRows, normalizedQuery, remote, searchResultLimit])\n\n const [pickerOpen, setPickerOpen] = useState(false)\n const pickerAnchor = useRef<HTMLButtonElement>(null)\n const [recentCollapsed, setRecentCollapsed] = useState(false)\n const [workspaceRename, setWorkspaceRename] = useState<WorkspaceRow | null>(null)\n const [sessionRename, setSessionRename] = useState<SessionRow | null>(null)\n const [renameDraft, setRenameDraft] = useState('')\n const [renameError, setRenameError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [deleteTarget, setDeleteTarget] = useState<WorkspaceRow | null>(null)\n const [actionMode, setActionModeState] = useState<SessionActionMode>(() => getActionMode())\n const [sessionDeleteTarget, setSessionDeleteTarget] = useState<SessionRow | null>(null)\n\n useEffect(() => subscribeActionMode(() => setActionModeState(getActionMode())), [])\n\n const beginWorkspaceRename = (row: WorkspaceRow) => { setWorkspaceRename(row); setRenameDraft(row.title); setRenameError(null) }\n const beginSessionRename = (row: SessionRow) => { setSessionRename(row); setRenameDraft(row.title); setRenameError(null) }\n const closeRename = () => { if (!busy) { setWorkspaceRename(null); setSessionRename(null); setRenameError(null) } }\n const commitRename = () => {\n const title = renameDraft.trim()\n if (title === '' || busy) return\n setBusy(true)\n const task = workspaceRename !== null && workspaceRename.key !== UNGROUPED\n ? renameWorkspace(workspaceRename.key, title)\n : sessionRename !== null ? renameSession(sessionRename.id, title) : Promise.resolve()\n task.then(() => { setWorkspaceRename(null); setSessionRename(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const confirmDelete = () => {\n if (deleteTarget === null || deleteTarget.key === UNGROUPED || busy) return\n setBusy(true)\n deleteWorkspace(deleteTarget.key).then(() => { setDeleteTarget(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const archive = (id: SessionId) => {\n if (actionMode === 'delete') {\n const row = allRows.find(candidate => candidate.id === id)\n ?? levelRows.find(candidate => candidate.id === id)\n ?? levelGroups.flatMap(g => g.rows).find(candidate => candidate.id === id)\n ?? recent.find(candidate => candidate.id === id)\n setSessionDeleteTarget(row ?? { id, title: '', blank: false, running: false, completed: false, updatedAt: 0, workspaceKey: UNGROUPED, workspaceTitle: '' })\n setRenameError(null)\n return\n }\n archiveSession(id).catch(reason => { console.warn('session archive rejected:', reason) })\n }\n const confirmSessionDelete = () => {\n if (sessionDeleteTarget === null || busy) return\n setBusy(true)\n archiveSession(sessionDeleteTarget.id).then(() => { setSessionDeleteTarget(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const toggleActionMode = () => { setActionMode(actionMode === 'archive' ? 'delete' : 'archive') }\n const fork = (id: SessionId) => { forkSession(id) }\n\n const sessionItem = (row: SessionRow, context = false) => (\n <SessionItem\n key={row.id}\n row={row}\n current={sessions.current}\n now={now}\n open={open}\n rename={beginSessionRename}\n fork={fork}\n archive={archive}\n t={t}\n context={context}\n actionMode={actionMode}\n />\n )\n\n return (\n <div data-ya-workspace-sidebar className={wide ? '' : 'ya-rail'}>\n <div className=\"ya-section-header\">\n {wide && <span className=\"ya-section-title\">{t('workspaces')}</span>}\n <button\n type=\"button\"\n className={`ya-icon-button ya-action-mode-toggle${actionMode === 'delete' ? ' ya-action-mode-delete' : ''}`}\n aria-label={t('toggleActionMode')}\n aria-pressed={actionMode === 'delete'}\n title={actionMode === 'delete' ? t('deleteMode') : t('archiveMode')}\n onClick={(event) => { event.stopPropagation(); toggleActionMode() }}\n >\n {actionMode === 'delete' ? <IconTrashOutline16 size={wide ? 16 : 18} /> : <IconArchiveOutline20 size={wide ? 16 : 18} />}\n </button>\n {directoryFlowAvailable && (\n <button ref={pickerAnchor} type=\"button\" className=\"ya-icon-button\" aria-label={t('addWorkspace')} onClick={() => { setPickerOpen(value => !value) }}>\n <IconProjectAddOutline16 size={wide ? 16 : 18} />\n </button>\n )}\n <WorkspacePickFlow\n t={t}\n open={pickerOpen}\n anchorRef={pickerAnchor}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('sidebar.workspaces.directoryFlow', owner)}\n addOnly\n side=\"right\"\n onPick={(workspaceId) => { setPickerOpen(false); startSession(workspaceId) }}\n onClose={() => { setPickerOpen(false) }}\n />\n </div>\n\n <div className=\"ya-search\" onClick={() => { if (!wide) expandSidebar() }}>\n <button type=\"button\" className=\"ya-search-icon\" aria-label={t('search')}><IconSearchOutline16 size={wide ? 14 : 18} /></button>\n {wide && <input className=\"ya-search-input\" value={query} maxLength={SEARCH_MAX} placeholder={t('searchPlaceholder')} onChange={event => { setQuery(sanitized(event.target.value)) }} />}\n {wide && query !== '' && <button type=\"button\" className=\"ya-icon-button\" aria-label={t('clearSearch')} onClick={() => { setQuery('') }}><IconCloseFill14 /></button>}\n </div>\n\n {wide && (\n <div className=\"ya-body\">\n {normalizedQuery !== '' ? (\n <div className=\"ya-scroll\" role=\"tree\" aria-label={t('search')}>\n {searchRows.map(row => sessionItem(row, true))}\n {remote.status === 'loading' && <div className=\"ya-status\">{t('searching')}</div>}\n {remote.status === 'error' && <div className=\"ya-status ya-warning\">{t('searchUnavailable')}</div>}\n {remote.status !== 'loading' && searchRows.length === 0 && <div className=\"ya-empty\">{t('noMatches')}</div>}\n </div>\n ) : (\n <>\n <div className={`ya-recent${recentCollapsed ? ' ya-recent-collapsed' : ''}`}>\n <div className=\"ya-block-label\">\n <span>{t('recent')}</span>\n {recent.length > 0 && (\n <button\n type=\"button\"\n className={`ya-block-label-toggle${recentCollapsed ? ' ya-collapsed' : ''}`}\n aria-label={recentCollapsed ? t('expand') : t('collapse')}\n aria-expanded={!recentCollapsed}\n onClick={(event) => { event.stopPropagation(); setRecentCollapsed(value => !value) }}\n >\n <IconChevronRightOutline14 />\n </button>\n )}\n </div>\n <div className=\"ya-recent-list-wrap\">\n {recent.length === 0\n ? <div className=\"ya-empty\">{t('noSessions')}</div>\n : <div className=\"ya-recent-list\">{recent.map(row => sessionItem(row, true))}</div>\n }\n </div>\n </div>\n <div className=\"ya-breadcrumb\">\n {selectedKey === null ? (\n <span className=\"ya-crumb\">{t('workspaces')}</span>\n ) : (\n <>\n <button type=\"button\" className=\"ya-crumb\" onClick={() => { setDirection('backward'); setSelectedKey(null) }}>{t('workspaces')}</button>\n <IconChevronRightOutline14 />\n <span className=\"ya-crumb\">{selectedKey === UNGROUPED ? t('ungrouped') : selectedWorkspace?.title}</span>\n {selectedKey !== UNGROUPED && (\n <button type=\"button\" className=\"ya-icon-button\" aria-label={t('newSession')} onClick={() => { startSession(selectedKey) }}><IconPlusOutline16 /></button>\n )}\n </>\n )}\n </div>\n <div className=\"ya-scroll\" role=\"tree\" aria-label={selectedKey === null ? t('workspaces') : t('sessions')}>\n <div key={selectedKey ?? 'root'} className={hasMounted ? `ya-level-enter-${direction}` : undefined}>\n {selectedKey === null\n ? workspaceRows.map(row => (\n <WorkspaceItem\n key={row.key}\n row={row}\n enter={() => { setDirection('forward'); setSelectedKey(row.key) }}\n create={() => { if (row.key !== UNGROUPED) startSession(row.key) }}\n rename={() => { beginWorkspaceRename(row) }}\n remove={() => { setDeleteTarget(row); setRenameError(null) }}\n t={t}\n />\n ))\n : selectedKey === UNGROUPED\n ? levelRows.map(row => sessionItem(row, false))\n : levelGroups.flatMap(group => [\n <div key={`group-${group.dateKey}`} className=\"ya-date-group-label\" role=\"separator\">\n {dateGroupLabel(group, now, t)}\n </div>,\n ...group.rows.map(row => sessionItem(row, false)),\n ])}\n {selectedKey === null && workspaceRows.length === 0 && <div className=\"ya-empty\">{t('noWorkspaces')}</div>}\n {selectedKey !== null && levelEmpty && <div className=\"ya-empty\">{t('noSessions')}</div>}\n </div>\n </div>\n </>\n )}\n </div>\n )}\n\n <Modal\n open={workspaceRename !== null || sessionRename !== null}\n onClose={closeRename}\n closeLabel={t('cancel')}\n title={workspaceRename !== null ? t('renameWorkspace') : t('renameSession')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={closeRename}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={busy || renameDraft.trim() === ''} onClick={commitRename}>{t('rename')}</Button>\n </>\n )}\n >\n <input className=\"ya-rename-input\" value={renameDraft} autoFocus disabled={busy} aria-label={workspaceRename !== null ? t('workspaceName') : t('sessionName')} onChange={event => { setRenameDraft(event.target.value); setRenameError(null) }} />\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={deleteTarget !== null}\n onClose={() => { if (!busy) setDeleteTarget(null) }}\n closeLabel={t('cancel')}\n title={t('deleteWorkspace')}\n description={deleteTarget === null ? undefined : t('deleteDescription', { name: deleteTarget.title })}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={() => { setDeleteTarget(null) }}>{t('cancel')}</Button>\n <Button variant=\"outline\" disabled={busy} onClick={confirmDelete}>{t('deleteWorkspace')}</Button>\n </>\n )}\n >\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={sessionDeleteTarget !== null}\n onClose={() => { if (!busy) setSessionDeleteTarget(null) }}\n closeLabel={t('cancel')}\n title={t('deleteSessionTitle')}\n description={t('deleteSessionConfirm')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={() => { setSessionDeleteTarget(null) }}>{t('cancel')}</Button>\n <Button variant=\"outline\" disabled={busy} onClick={confirmSessionDelete}>{t('deleteSession')}</Button>\n </>\n )}\n >\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n </div>\n )\n}\n","/** Client assembly for the replacement workspace sidebar and hero picker. */\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { PickerInjected, SidebarInjected } from './contract.ts'\nimport { en, NS, zh } from './locales.ts'\nimport { installStyles } from './styles.ts'\nimport { WorkspacePicker } from './WorkspacePicker.tsx'\nimport { WorkspaceSidebar } from './WorkspaceSidebar.tsx'\n\n/** Services required by both replacement client entries. */\nexport const inject = ['slots', 'sessions', 'workspaces', 'locale']\n\n/** Register the sidebar browser and conversation hero picker. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ya-workspace-sidebar: dictionaries')\n ctx.effect(installStyles, 'ya-workspace-sidebar: styles')\n\n const flowSource = (\n name: 'sidebar.workspaces.directoryFlow' | 'conversation.hero.workspace.directoryFlow',\n ): HostObservable<boolean> => ({\n getSnapshot: () => ctx.slots.entries(name).length > 0,\n subscribe: listener => ctx.slots.subscribe(name, listener),\n })\n const sidebarFlow = flowSource('sidebar.workspaces.directoryFlow')\n const pickerFlow = flowSource('conversation.hero.workspace.directoryFlow')\n const createWorkspace = (input: { path: string }) => ctx.workspaces.create(input)\n\n const searchSessions: SidebarInjected['searchSessions'] = async (query, signal) => {\n const result = await ctx.sessions.search(query, signal)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n }\n const sidebarInjected = (): SidebarInjected => ({\n startSession: workspaceId => { ctx.workspaces.startSession(workspaceId) },\n open: sessionId => { ctx.sessions.open(sessionId) },\n searchSessions,\n searchResultLimit: ctx.sessions.searchResultLimit,\n renameSession: async (sessionId, title) => {\n const session = ctx.sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error(`unknown session \"${sessionId}\"`)\n const result = await session.rename(title)\n if (!result.ok) throw new Error(result.error.message)\n },\n forkSession: sessionId => {\n ctx.sessions.fork({ sessionId, increaseTitle: true })\n .then(childId => { ctx.sessions.open(childId) })\n .catch(() => {})\n },\n renameWorkspace: async (workspaceId, title) => { await ctx.workspaces.rename(workspaceId, title) },\n deleteWorkspace: async workspaceId => { await ctx.workspaces.delete(workspaceId) },\n archiveSession: async sessionId => { await ctx.workspaces.archiveSession(sessionId) },\n insertSessionBefore: async (workspaceId, sessionId, beforeSessionId) => {\n await ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId)\n },\n createWorkspace,\n hooks: { directoryFlow: sidebarFlow },\n })\n const pickerInjected = (): PickerInjected => ({\n createWorkspace,\n hooks: { directoryFlow: pickerFlow },\n })\n\n ctx.slots.inject('sidebar.workspaces', () => ctx.slots.register({\n name: 'sidebar.workspaces',\n children: { 'sidebar.workspaces.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: sidebarInjected,\n locale: NS,\n }, WorkspaceSidebar))\n\n ctx.slots.inject('conversation.hero.workspace', () => ctx.slots.register({\n name: 'conversation.hero.workspace',\n children: { 'conversation.hero.workspace.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: pickerInjected,\n locale: NS,\n }, WorkspacePicker))\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,6 @@ export declare const zh: {
|
|
|
5
5
|
recent: string;
|
|
6
6
|
ungrouped: string;
|
|
7
7
|
newSession: string;
|
|
8
|
-
untitled: string;
|
|
9
8
|
addWorkspace: string;
|
|
10
9
|
addWorkspaceMenu: string;
|
|
11
10
|
search: string;
|
|
@@ -24,6 +23,13 @@ export declare const zh: {
|
|
|
24
23
|
deleteDescription: string;
|
|
25
24
|
fork: string;
|
|
26
25
|
archive: string;
|
|
26
|
+
archiveMode: string;
|
|
27
|
+
deleteMode: string;
|
|
28
|
+
deleteSession: string;
|
|
29
|
+
deleteSessionTitle: string;
|
|
30
|
+
deleteSessionConfirm: string;
|
|
31
|
+
toggleActionMode: string;
|
|
32
|
+
actionModeLabel: string;
|
|
27
33
|
cancel: string;
|
|
28
34
|
confirm: string;
|
|
29
35
|
retry: string;
|
|
@@ -42,6 +48,10 @@ export declare const zh: {
|
|
|
42
48
|
completed: string;
|
|
43
49
|
collapse: string;
|
|
44
50
|
expand: string;
|
|
51
|
+
today: string;
|
|
52
|
+
yesterday: string;
|
|
53
|
+
date: string;
|
|
54
|
+
dateYear: string;
|
|
45
55
|
};
|
|
46
56
|
export type YaWorkspaceKey = keyof typeof zh;
|
|
47
57
|
export declare const en: {
|
|
@@ -50,7 +60,6 @@ export declare const en: {
|
|
|
50
60
|
recent: string;
|
|
51
61
|
ungrouped: string;
|
|
52
62
|
newSession: string;
|
|
53
|
-
untitled: string;
|
|
54
63
|
addWorkspace: string;
|
|
55
64
|
addWorkspaceMenu: string;
|
|
56
65
|
search: string;
|
|
@@ -69,6 +78,13 @@ export declare const en: {
|
|
|
69
78
|
deleteDescription: string;
|
|
70
79
|
fork: string;
|
|
71
80
|
archive: string;
|
|
81
|
+
archiveMode: string;
|
|
82
|
+
deleteMode: string;
|
|
83
|
+
deleteSession: string;
|
|
84
|
+
deleteSessionTitle: string;
|
|
85
|
+
deleteSessionConfirm: string;
|
|
86
|
+
toggleActionMode: string;
|
|
87
|
+
actionModeLabel: string;
|
|
72
88
|
cancel: string;
|
|
73
89
|
confirm: string;
|
|
74
90
|
retry: string;
|
|
@@ -87,5 +103,9 @@ export declare const en: {
|
|
|
87
103
|
completed: string;
|
|
88
104
|
collapse: string;
|
|
89
105
|
expand: string;
|
|
106
|
+
today: string;
|
|
107
|
+
yesterday: string;
|
|
108
|
+
date: string;
|
|
109
|
+
dateYear: string;
|
|
90
110
|
};
|
|
91
111
|
export declare const NS = "ya-workspace-sidebar";
|
|
@@ -6,8 +6,6 @@ export declare const UNGROUPED: "__ya_ungrouped__";
|
|
|
6
6
|
export interface SessionRow {
|
|
7
7
|
id: SessionId;
|
|
8
8
|
title: string;
|
|
9
|
-
/** Whether the session has a durable log-backed title (summary.title !== undefined). */
|
|
10
|
-
hasTitle: boolean;
|
|
11
9
|
blank: boolean;
|
|
12
10
|
running: boolean;
|
|
13
11
|
pendingInteraction?: SessionSummary['pendingInteraction'];
|
|
@@ -16,6 +14,14 @@ export interface SessionRow {
|
|
|
16
14
|
workspaceKey: WorkspaceId | typeof UNGROUPED;
|
|
17
15
|
workspaceTitle: string;
|
|
18
16
|
}
|
|
17
|
+
/** One date-bucketed group of session rows for the real-workspace level. */
|
|
18
|
+
export interface SessionDateGroup {
|
|
19
|
+
/** Local calendar date `YYYY-MM-DD`, stable key. */
|
|
20
|
+
dateKey: string;
|
|
21
|
+
/** Days between today's local date and this group's local date (0=today, 1=yesterday, …). */
|
|
22
|
+
dayOffset: number;
|
|
23
|
+
rows: SessionRow[];
|
|
24
|
+
}
|
|
19
25
|
/** One first-level workspace row. */
|
|
20
26
|
export interface WorkspaceRow {
|
|
21
27
|
key: WorkspaceId | typeof UNGROUPED;
|
|
@@ -33,5 +39,15 @@ export declare function deriveRecent(list: SessionListState, workspaces: readonl
|
|
|
33
39
|
export declare function deriveWorkspaces(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): WorkspaceRow[];
|
|
34
40
|
/** Derive the selected workspace's sessions in its canonical order. */
|
|
35
41
|
export declare function deriveWorkspaceSessions(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): SessionRow[];
|
|
42
|
+
/**
|
|
43
|
+
* Derive the selected real workspace's sessions grouped by local calendar date.
|
|
44
|
+
*
|
|
45
|
+
* - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
|
|
46
|
+
* - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
|
|
47
|
+
* - {@link visible} filter is reused (archived / subagent / blank visibility).
|
|
48
|
+
* - Future timestamps clamp to today's bucket (`dayOffset` 0).
|
|
49
|
+
* - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
|
|
50
|
+
*/
|
|
51
|
+
export declare function deriveWorkspaceSessionGroups(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], now: number): SessionDateGroup[];
|
|
36
52
|
/** Case-insensitive local title/workspace matching used beside Host content search. */
|
|
37
53
|
export declare function localMatches(rows: readonly SessionRow[], query: string): SessionRow[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-local preference controlling whether the session row's destructive
|
|
3
|
+
* action presents as Archive (default) or Delete. Delete mode renders the
|
|
4
|
+
* row action red with a trash icon and gates the call behind a confirmation
|
|
5
|
+
* modal; the underlying Host verb remains `archiveSession` (the only
|
|
6
|
+
* session-level destructive API exposed by `ctx.workspaces`), which hides
|
|
7
|
+
* the session from grouping surfaces while preserving its log.
|
|
8
|
+
*
|
|
9
|
+
* The preference is persisted to `localStorage` so it survives reloads and
|
|
10
|
+
* remounts without host-side plumbing. Cross-device sync is intentionally
|
|
11
|
+
* out of scope: this is a per-browser UX preference, not a deployment knob.
|
|
12
|
+
*/
|
|
13
|
+
/** How the session row's destructive action presents and behaves. */
|
|
14
|
+
export type SessionActionMode = 'archive' | 'delete';
|
|
15
|
+
/** Current action mode snapshot. */
|
|
16
|
+
export declare function getActionMode(): SessionActionMode;
|
|
17
|
+
/** Switch the action mode and notify subscribers. */
|
|
18
|
+
export declare function setActionMode(mode: SessionActionMode): void;
|
|
19
|
+
/** Subscribe to action mode changes; returns an unsubscribe disposer. */
|
|
20
|
+
export declare function subscribeActionMode(listener: () => void): () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** One scoped stylesheet injected for the lifetime of the client activation. */
|
|
2
|
-
export declare const CSS = "\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-
|
|
2
|
+
export declare const CSS = "\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-date-group-label { height:26px; display:flex; align-items:center; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }\n.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }\n.ya-rail .ya-search { justify-content:center; }\n.ya-rail .ya-search-icon { cursor:pointer; color:var(--dsw-alias-label-primary); }\n.ya-picker-error { color:var(--dsw-alias-status-error); white-space:pre-wrap; }\n.ya-action-mode-toggle.ya-action-mode-delete { color:var(--dsw-alias-state-error-primary); }\n.ya-action-mode-toggle.ya-action-mode-delete:hover { background:var(--dsw-alias-interactive-bg-hover-danger); }\n@keyframes ya-slide-in-forward { from { opacity:0; transform:translateX(10px); } to { opacity:1; transform:translateX(0); } }\n@keyframes ya-slide-in-backward { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:translateX(0); } }\n.ya-level-enter-forward { animation:ya-slide-in-forward 180ms ease-out; }\n.ya-level-enter-backward { animation:ya-slide-in-backward 180ms ease-out; }\n";
|
|
3
3
|
/** Install the stylesheet and return its disposer. */
|
|
4
4
|
export declare function installStyles(): () => void;
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huanlin/dsh-plugin-ya-workspace-sidebar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"keywords": [
|
|
7
|
+
"keywords": [
|
|
8
|
+
"dsh-plugin"
|
|
9
|
+
],
|
|
8
10
|
"description": "Two-level DSH workspace sidebar with global recent sessions and breadcrumb navigation.",
|
|
9
11
|
"type": "module",
|
|
10
12
|
"license": "AGPL-3.0",
|
|
@@ -46,12 +48,6 @@
|
|
|
46
48
|
"platform": "web"
|
|
47
49
|
}
|
|
48
50
|
},
|
|
49
|
-
"scripts": {
|
|
50
|
-
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
51
|
-
"test": "vitest run",
|
|
52
|
-
"build": "tsdown -c tsdown.config.ts && tsc -p tsconfig.json",
|
|
53
|
-
"bundle:client": "tsdown -c tsdown.config.ts"
|
|
54
|
-
},
|
|
55
51
|
"peerDependencies": {
|
|
56
52
|
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.1",
|
|
57
53
|
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
|
|
@@ -64,15 +60,33 @@
|
|
|
64
60
|
"react": "^18.2.0"
|
|
65
61
|
},
|
|
66
62
|
"peerDependenciesMeta": {
|
|
67
|
-
"@deepseek-ai/dsh-client-locale": {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"@deepseek-ai/dsh-client-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
64
|
+
"optional": true
|
|
65
|
+
},
|
|
66
|
+
"@deepseek-ai/dsh-client-runtime": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-conversation": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-primitives": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-sidebar": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-slots": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"@deepseek-ai/dsh-invariants": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"cordis": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"react": {
|
|
88
|
+
"optional": true
|
|
89
|
+
}
|
|
76
90
|
},
|
|
77
91
|
"devDependencies": {
|
|
78
92
|
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.1",
|
|
@@ -93,5 +107,11 @@
|
|
|
93
107
|
},
|
|
94
108
|
"engines": {
|
|
95
109
|
"node": ">=22.0.0"
|
|
110
|
+
},
|
|
111
|
+
"scripts": {
|
|
112
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
113
|
+
"test": "vitest run",
|
|
114
|
+
"build": "tsdown -c tsdown.config.ts && tsc -p tsconfig.json",
|
|
115
|
+
"bundle:client": "tsdown -c tsdown.config.ts"
|
|
96
116
|
}
|
|
97
|
-
}
|
|
117
|
+
}
|