@huanlin/dsh-plugin-ya-workspace-sidebar 0.1.0 → 0.2.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 +12 -2
- package/lib/client.js +126 -81
- package/lib/client.js.map +1 -1
- package/lib/types/client/WorkspacePicker.d.ts +26 -0
- package/lib/types/client/WorkspaceSidebar.d.ts +3 -0
- package/lib/types/client/contract.d.ts +68 -0
- package/lib/types/client/index.d.ts +5 -0
- package/lib/types/client/locales.d.ts +99 -0
- package/lib/types/client/model.d.ts +55 -0
- package/lib/types/client/styles.d.ts +4 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/invariant.d.ts +12 -0
- package/package.json +38 -18
package/README.md
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
+
[](https://dshfind.com/zh/plugins/huanlinoto/dsh-plugin-ya-workspace-sidebar?ref=badge)
|
|
2
|
+
|
|
3
|
+
> 📌 本插件已收录于 [dshfind](https://dshfind.com/zh) 插件超市,点击上方徽章直达主页。
|
|
4
|
+
|
|
1
5
|
# ya-workspace-sidebar
|
|
2
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/@huanlin/dsh-plugin-ya-workspace-sidebar)
|
|
8
|
+
|
|
3
9
|

|
|
4
10
|
|
|
5
|
-
DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session
|
|
11
|
+
DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session 二级菜单和面包屑导航;选中工作区的会话按本地日历日期分组(今天/昨天/更早),搜索、添加工作区、重命名、删除、Fork 与归档继续使用 DSH 原生 Host 能力。
|
|
6
12
|
|
|
7
13
|
## 运行
|
|
8
14
|
|
|
9
|
-
插件采用 bundle 形式,`cordis.patch.yml` 会禁用官方 `ui-workspace` 并插入 `@huanlin/dsh-plugin-ya-workspace-sidebar
|
|
15
|
+
插件采用 bundle 形式,`cordis.patch.yml` 会禁用官方 `ui-workspace` 并插入 `@huanlin/dsh-plugin-ya-workspace-sidebar`。安装:
|
|
10
16
|
|
|
11
17
|
```powershell
|
|
18
|
+
# 从 npm 安装(推荐):
|
|
19
|
+
dsh plugin --profile web add @huanlin/dsh-plugin-ya-workspace-sidebar
|
|
20
|
+
|
|
21
|
+
# 本地开发(热更新):
|
|
12
22
|
dsh plugin --profile web add "link:D:/Projects/deepseek-harness/ya-workspace-sidebar"
|
|
13
23
|
```
|
|
14
24
|
|
package/lib/client.js
CHANGED
|
@@ -15,6 +15,7 @@ window.__ModuleLoader__.load({
|
|
|
15
15
|
recent: "最近会话",
|
|
16
16
|
ungrouped: "未分组",
|
|
17
17
|
newSession: "新会话",
|
|
18
|
+
untitled: "未命名会话",
|
|
18
19
|
addWorkspace: "添加工作区",
|
|
19
20
|
addWorkspaceMenu: "添加工作区…",
|
|
20
21
|
search: "搜索会话",
|
|
@@ -50,7 +51,11 @@ window.__ModuleLoader__.load({
|
|
|
50
51
|
waiting: "等待交互",
|
|
51
52
|
completed: "已完成",
|
|
52
53
|
collapse: "折叠",
|
|
53
|
-
expand: "展开"
|
|
54
|
+
expand: "展开",
|
|
55
|
+
today: "今天",
|
|
56
|
+
yesterday: "昨天",
|
|
57
|
+
date: "{m}月{d}日",
|
|
58
|
+
dateYear: "{y}年{m}月{d}日"
|
|
54
59
|
};
|
|
55
60
|
const en = {
|
|
56
61
|
workspaces: "Workspaces",
|
|
@@ -58,6 +63,7 @@ window.__ModuleLoader__.load({
|
|
|
58
63
|
recent: "Recent Sessions",
|
|
59
64
|
ungrouped: "Ungrouped",
|
|
60
65
|
newSession: "New Session",
|
|
66
|
+
untitled: "Untitled session",
|
|
61
67
|
addWorkspace: "Add workspace",
|
|
62
68
|
addWorkspaceMenu: "Add workspace…",
|
|
63
69
|
search: "Search sessions",
|
|
@@ -93,7 +99,11 @@ window.__ModuleLoader__.load({
|
|
|
93
99
|
waiting: "Waiting for interaction",
|
|
94
100
|
completed: "Completed",
|
|
95
101
|
collapse: "Collapse",
|
|
96
|
-
expand: "Expand"
|
|
102
|
+
expand: "Expand",
|
|
103
|
+
today: "Today",
|
|
104
|
+
yesterday: "Yesterday",
|
|
105
|
+
date: "{m}/{d}",
|
|
106
|
+
dateYear: "{m}/{d}/{y}"
|
|
97
107
|
};
|
|
98
108
|
const NS = "ya-workspace-sidebar";
|
|
99
109
|
//#endregion
|
|
@@ -121,6 +131,7 @@ body[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish
|
|
|
121
131
|
.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; }
|
|
122
132
|
.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }
|
|
123
133
|
.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }
|
|
134
|
+
.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; }
|
|
124
135
|
.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; }
|
|
125
136
|
.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; }
|
|
126
137
|
button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }
|
|
@@ -143,8 +154,6 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
143
154
|
.ya-warning { color:var(--dsw-alias-status-warning); }
|
|
144
155
|
.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; }
|
|
145
156
|
.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }
|
|
146
|
-
.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); }
|
|
147
|
-
.ya-drop-before::before { top:-2px; } .ya-drop-after::after { bottom:-2px; }
|
|
148
157
|
.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }
|
|
149
158
|
.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }
|
|
150
159
|
.ya-rail .ya-search { justify-content:center; }
|
|
@@ -305,6 +314,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
305
314
|
return {
|
|
306
315
|
id: summary.id,
|
|
307
316
|
title: summary.blank ? "New Session" : summary.displayTitle,
|
|
317
|
+
hasTitle: summary.title !== void 0,
|
|
308
318
|
blank: summary.blank,
|
|
309
319
|
running: summary.running,
|
|
310
320
|
...summary.pendingInteraction === void 0 ? {} : { pendingInteraction: summary.pendingInteraction },
|
|
@@ -377,6 +387,70 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
377
387
|
if (workspace === void 0) return [];
|
|
378
388
|
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));
|
|
379
389
|
}
|
|
390
|
+
/** Format a local calendar date as `YYYY-MM-DD` (locale-agnostic, no padding surprises). */
|
|
391
|
+
function localDateKey(year, month, day) {
|
|
392
|
+
return `${year}-${month < 9 ? `0${month + 1}` : `${month + 1}`}-${day < 10 ? `0${day}` : `${day}`}`;
|
|
393
|
+
}
|
|
394
|
+
/** Whole-day difference between two local calendar dates (a - b) using UTC midnight. */
|
|
395
|
+
function dayDiff(a, b) {
|
|
396
|
+
const msA = Date.UTC(a.year, a.month, a.day);
|
|
397
|
+
const msB = Date.UTC(b.year, b.month, b.day);
|
|
398
|
+
return Math.round((msA - msB) / 864e5);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Derive the selected real workspace's sessions grouped by local calendar date.
|
|
402
|
+
*
|
|
403
|
+
* - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
|
|
404
|
+
* - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
|
|
405
|
+
* - {@link visible} filter is reused (archived / subagent / blank visibility).
|
|
406
|
+
* - Future timestamps clamp to today's bucket (`dayOffset` 0).
|
|
407
|
+
* - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
|
|
408
|
+
*/
|
|
409
|
+
function deriveWorkspaceSessionGroups(key, list, workspaces, archivedSessionIds, now) {
|
|
410
|
+
if (key === "__ya_ungrouped__") return [];
|
|
411
|
+
const workspace = workspaces.find((item) => item.workspaceId === key);
|
|
412
|
+
if (workspace === void 0) return [];
|
|
413
|
+
const archived = new Set(archivedSessionIds);
|
|
414
|
+
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));
|
|
415
|
+
if (rows.length === 0) return [];
|
|
416
|
+
const nowDate = new Date(now);
|
|
417
|
+
const today = {
|
|
418
|
+
year: nowDate.getFullYear(),
|
|
419
|
+
month: nowDate.getMonth(),
|
|
420
|
+
day: nowDate.getDate()
|
|
421
|
+
};
|
|
422
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
423
|
+
for (const row of rows) {
|
|
424
|
+
const ts = Math.min(row.updatedAt, now);
|
|
425
|
+
const d = new Date(ts);
|
|
426
|
+
const date = {
|
|
427
|
+
year: d.getFullYear(),
|
|
428
|
+
month: d.getMonth(),
|
|
429
|
+
day: d.getDate()
|
|
430
|
+
};
|
|
431
|
+
const dateKey = localDateKey(date.year, date.month, date.day);
|
|
432
|
+
let bucket = buckets.get(dateKey);
|
|
433
|
+
if (bucket === void 0) {
|
|
434
|
+
bucket = {
|
|
435
|
+
dayOffset: Math.max(0, dayDiff(today, date)),
|
|
436
|
+
rows: []
|
|
437
|
+
};
|
|
438
|
+
buckets.set(dateKey, bucket);
|
|
439
|
+
}
|
|
440
|
+
bucket.rows.push(row);
|
|
441
|
+
}
|
|
442
|
+
const groups = [];
|
|
443
|
+
for (const [dateKey, bucket] of buckets) {
|
|
444
|
+
bucket.rows.sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)));
|
|
445
|
+
groups.push({
|
|
446
|
+
dateKey,
|
|
447
|
+
dayOffset: bucket.dayOffset,
|
|
448
|
+
rows: bucket.rows
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
groups.sort((a, b) => a.dayOffset - b.dayOffset || a.dateKey.localeCompare(b.dateKey));
|
|
452
|
+
return groups;
|
|
453
|
+
}
|
|
380
454
|
/** Case-insensitive local title/workspace matching used beside Host content search. */
|
|
381
455
|
function localMatches(rows, query) {
|
|
382
456
|
const normalized = query.trim().toLocaleLowerCase();
|
|
@@ -401,43 +475,40 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
401
475
|
if (diff < 525600 * minute) return t("months", { n: Math.floor(diff / (43200 * minute)) });
|
|
402
476
|
return t("years", { n: Math.floor(diff / (525600 * minute)) });
|
|
403
477
|
}
|
|
478
|
+
/** Format a date group's localized title from its dayOffset and `YYYY-MM-DD` key. */
|
|
479
|
+
function dateGroupLabel(group, now, t) {
|
|
480
|
+
if (group.dayOffset === 0) return t("today");
|
|
481
|
+
if (group.dayOffset === 1) return t("yesterday");
|
|
482
|
+
const parts = group.dateKey.split("-");
|
|
483
|
+
const year = Number(parts[0]);
|
|
484
|
+
const month = Number(parts[1]);
|
|
485
|
+
const day = Number(parts[2]);
|
|
486
|
+
if (year === new Date(now).getFullYear()) return t("date", {
|
|
487
|
+
m: month,
|
|
488
|
+
d: day
|
|
489
|
+
});
|
|
490
|
+
return t("dateYear", {
|
|
491
|
+
y: year,
|
|
492
|
+
m: month,
|
|
493
|
+
d: day
|
|
494
|
+
});
|
|
495
|
+
}
|
|
404
496
|
function SessionStatus({ row }) {
|
|
405
497
|
if (row.pendingInteraction !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
|
|
406
498
|
if (row.running) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "ongoing" });
|
|
407
499
|
if (row.completed) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "done" });
|
|
408
500
|
return null;
|
|
409
501
|
}
|
|
410
|
-
function
|
|
411
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
412
|
-
return event.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
413
|
-
}
|
|
414
|
-
function SessionItem({ row, current, now, open, rename, fork, archive, t, context, drag }) {
|
|
502
|
+
function SessionItem({ row, current, now, open, rename, fork, archive, t, context }) {
|
|
415
503
|
const [menuOpen, setMenuOpen] = (0, react.useState)(false);
|
|
416
|
-
const title = row.blank ? t("newSession") : row.title;
|
|
504
|
+
const title = row.blank ? t("newSession") : row.hasTitle ? row.title : t("untitled");
|
|
417
505
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
418
|
-
className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}
|
|
506
|
+
className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}`,
|
|
419
507
|
role: "treeitem",
|
|
420
508
|
"aria-selected": row.id === current,
|
|
421
|
-
draggable: drag !== void 0,
|
|
422
509
|
onClick: () => {
|
|
423
510
|
open(row.id);
|
|
424
511
|
},
|
|
425
|
-
onDragStart: drag === void 0 ? void 0 : (event) => {
|
|
426
|
-
event.dataTransfer.effectAllowed = "move";
|
|
427
|
-
drag.start();
|
|
428
|
-
},
|
|
429
|
-
onDragEnd: drag?.end,
|
|
430
|
-
onDragOver: drag === void 0 ? void 0 : (event) => {
|
|
431
|
-
if (!drag.active) return;
|
|
432
|
-
event.preventDefault();
|
|
433
|
-
event.dataTransfer.dropEffect = "move";
|
|
434
|
-
drag.hover(rowHalf(event));
|
|
435
|
-
},
|
|
436
|
-
onDrop: drag === void 0 ? void 0 : (event) => {
|
|
437
|
-
if (!drag.active) return;
|
|
438
|
-
event.preventDefault();
|
|
439
|
-
drag.drop(rowHalf(event));
|
|
440
|
-
},
|
|
441
512
|
children: [
|
|
442
513
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
443
514
|
className: "ya-status-slot",
|
|
@@ -583,7 +654,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
583
654
|
}
|
|
584
655
|
/** Fill `sidebar.workspaces` with the replacement browser. */
|
|
585
656
|
function WorkspaceSidebar(props) {
|
|
586
|
-
const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession,
|
|
657
|
+
const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t } = props;
|
|
587
658
|
const sessions = useSessions((state) => state);
|
|
588
659
|
const workspaceState = useWorkspaces((state) => state);
|
|
589
660
|
const workspaces = workspaceState.items;
|
|
@@ -621,8 +692,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
621
692
|
if (selectedKey !== null && selectedKey !== "__ya_ungrouped__" && !workspaces.some((workspace) => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED);
|
|
622
693
|
}, [selectedKey, workspaces]);
|
|
623
694
|
const selectedWorkspace = selectedKey === null || selectedKey === "__ya_ungrouped__" ? void 0 : workspaces.find((workspace) => workspace.workspaceId === selectedKey);
|
|
624
|
-
const levelRows = selectedKey === null ? [] : deriveWorkspaceSessions(selectedKey, sessions, workspaces, archived);
|
|
625
695
|
const now = Date.now();
|
|
696
|
+
const levelGroups = (0, react.useMemo)(() => selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? deriveWorkspaceSessionGroups(selectedKey, sessions, workspaces, archived, now) : [], [
|
|
697
|
+
archived,
|
|
698
|
+
sessions,
|
|
699
|
+
workspaces,
|
|
700
|
+
selectedKey,
|
|
701
|
+
now
|
|
702
|
+
]);
|
|
703
|
+
const levelRows = selectedKey === "__ya_ungrouped__" ? deriveWorkspaceSessions(UNGROUPED, sessions, workspaces, archived) : [];
|
|
704
|
+
const levelEmpty = selectedKey === "__ya_ungrouped__" ? levelRows.length === 0 : levelGroups.every((g) => g.rows.length === 0);
|
|
626
705
|
const [query, setQuery] = (0, react.useState)("");
|
|
627
706
|
const normalizedQuery = sanitized(query).trim();
|
|
628
707
|
const [remote, setRemote] = (0, react.useState)({
|
|
@@ -693,7 +772,6 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
693
772
|
const [renameError, setRenameError] = (0, react.useState)(null);
|
|
694
773
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
695
774
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
|
|
696
|
-
const [drag, setDrag] = (0, react.useState)(null);
|
|
697
775
|
const beginWorkspaceRename = (row) => {
|
|
698
776
|
setWorkspaceRename(row);
|
|
699
777
|
setRenameDraft(row.title);
|
|
@@ -743,54 +821,17 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
743
821
|
const fork = (id) => {
|
|
744
822
|
forkSession(id);
|
|
745
823
|
};
|
|
746
|
-
const sessionItem = (row, context = false,
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
t,
|
|
758
|
-
context,
|
|
759
|
-
...draggable && selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? { drag: {
|
|
760
|
-
active: drag !== null,
|
|
761
|
-
marker,
|
|
762
|
-
start: () => {
|
|
763
|
-
setDrag({
|
|
764
|
-
id: row.id,
|
|
765
|
-
over: null
|
|
766
|
-
});
|
|
767
|
-
},
|
|
768
|
-
hover: (half) => {
|
|
769
|
-
setDrag((value) => value === null ? value : {
|
|
770
|
-
...value,
|
|
771
|
-
over: {
|
|
772
|
-
id: row.id,
|
|
773
|
-
half
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
|
-
},
|
|
777
|
-
drop: (half) => {
|
|
778
|
-
if (drag === null) return;
|
|
779
|
-
const anchor = half === "before" ? row.id : levelRows[(index ?? 0) + 1]?.id;
|
|
780
|
-
const sourceIndex = levelRows.findIndex((item) => item.id === drag.id);
|
|
781
|
-
const anchorIndex = anchor === void 0 ? levelRows.length : levelRows.findIndex((item) => item.id === anchor);
|
|
782
|
-
setDrag(null);
|
|
783
|
-
if (anchor === drag.id || sourceIndex === anchorIndex || sourceIndex + 1 === anchorIndex) return;
|
|
784
|
-
insertSessionBefore(selectedKey, drag.id, anchor).catch((reason) => {
|
|
785
|
-
console.warn("session reorder rejected:", reason);
|
|
786
|
-
});
|
|
787
|
-
},
|
|
788
|
-
end: () => {
|
|
789
|
-
setDrag(null);
|
|
790
|
-
}
|
|
791
|
-
} } : {}
|
|
792
|
-
}, row.id);
|
|
793
|
-
};
|
|
824
|
+
const sessionItem = (row, context = false) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionItem, {
|
|
825
|
+
row,
|
|
826
|
+
current: sessions.current,
|
|
827
|
+
now,
|
|
828
|
+
open,
|
|
829
|
+
rename: beginSessionRename,
|
|
830
|
+
fork,
|
|
831
|
+
archive,
|
|
832
|
+
t,
|
|
833
|
+
context
|
|
834
|
+
}, row.id);
|
|
794
835
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
795
836
|
"data-ya-workspace-sidebar": true,
|
|
796
837
|
className: wide ? "" : "ya-rail",
|
|
@@ -967,12 +1008,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
|
|
|
967
1008
|
setRenameError(null);
|
|
968
1009
|
},
|
|
969
1010
|
t
|
|
970
|
-
}, row.key)) : levelRows.map((row
|
|
1011
|
+
}, row.key)) : selectedKey === "__ya_ungrouped__" ? levelRows.map((row) => sessionItem(row, false)) : levelGroups.flatMap((group) => [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1012
|
+
className: "ya-date-group-label",
|
|
1013
|
+
role: "separator",
|
|
1014
|
+
children: dateGroupLabel(group, now, t)
|
|
1015
|
+
}, `group-${group.dateKey}`), ...group.rows.map((row) => sessionItem(row, false))]),
|
|
971
1016
|
selectedKey === null && workspaceRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
972
1017
|
className: "ya-empty",
|
|
973
1018
|
children: t("noWorkspaces")
|
|
974
1019
|
}),
|
|
975
|
-
selectedKey !== null &&
|
|
1020
|
+
selectedKey !== null && levelEmpty && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
976
1021
|
className: "ya-empty",
|
|
977
1022
|
children: t("noSessions")
|
|
978
1023
|
})
|
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 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 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 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 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.title\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":";;;;;;;;;;;EACA,MAAa,KAAK;GAChB,YAAY;GACZ,UAAU;GACV,QAAQ;GACR,WAAW;GACX,YAAY;GACZ,cAAc;GACd,kBAAkB;GAClB,QAAQ;GACR,mBAAmB;GACnB,aAAa;GACb,WAAW;GACX,mBAAmB;GACnB,WAAW;GACX,YAAY;GACZ,cAAc;GACd,SAAS;GACT,QAAQ;GACR,iBAAiB;GACjB,eAAe;GACf,iBAAiB;GACjB,mBAAmB;GACnB,MAAM;GACN,SAAS;GACT,QAAQ;GACR,SAAS;GACT,OAAO;GACP,aAAa;GACb,eAAe;GACf,aAAa;GACb,OAAO;GACP,KAAK;GACL,SAAS;GACT,OAAO;GACP,MAAM;GACN,QAAQ;GACR,OAAO;GACP,SAAS;GACT,SAAS;GACT,WAAW;GACX,UAAU;GACV,QAAQ;EACV;EAIA,MAAa,KAAK;GAChB,YAAY;GACZ,UAAU;GACV,QAAQ;GACR,WAAW;GACX,YAAY;GACZ,cAAc;GACd,kBAAkB;GAClB,QAAQ;GACR,mBAAmB;GACnB,aAAa;GACb,WAAW;GACX,mBAAmB;GACnB,WAAW;GACX,YAAY;GACZ,cAAc;GACd,SAAS;GACT,QAAQ;GACR,iBAAiB;GACjB,eAAe;GACf,iBAAiB;GACjB,mBAAmB;GACnB,MAAM;GACN,SAAS;GACT,QAAQ;GACR,SAAS;GACT,OAAO;GACP,aAAa;GACb,eAAe;GACf,aAAa;GACb,OAAO;GACP,KAAK;GACL,SAAS;GACT,OAAO;GACP,MAAM;GACN,QAAQ;GACR,OAAO;GACP,SAAS;GACT,SAAS;GACT,WAAW;GACX,UAAU;GACV,QAAQ;EACV;EAEA,MAAa,KAAK;;;;EC1FlB,MAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0DnB,SAAgB,gBAA4B;GAC1C,MAAM,QAAQ,SAAS,cAAc,OAAO;GAC5C,MAAM,aAAa,mCAAmC,EAAE;GACxD,MAAM,cAAc;GACpB,SAAS,KAAK,YAAY,KAAK;GAC/B,aAAa;IAAE,MAAM,OAAO;GAAE;EAChC;;;ECrDA,MAAM,MAAM;;EAkBZ,SAAgB,kBAAkB,EAChC,GAAG,MAAM,WAAW,eAAe,iBAAiB,kBACpD,qBAAqB,QAAQ,SAAS,UAAU,OAAO,OAAO,UAAU,cAC5D;GACZ,MAAM,WAAW,eAAc,UAAS,KAAK;GAC7C,MAAM,gBAAgB,kBAAiB,UAAS,KAAK;GACrD,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,KAAK;GAC9C,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAwB,IAAI;GACtD,MAAM,iBAAA,GAAgBC,MAAAA,YAAAA,OACd,WAAW,SAAS,sBAAsB,KAAK,MACrD,CAAC,SAAS,CACZ;GACA,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,YAAY,CAAC,eAAe,YAAY,KAAK;GACnD,GAAG,CAAC,eAAe,QAAQ,CAAC;GAE5B,MAAM,YAAA,GAAWA,MAAAA,YAAAA,OAAkB;IACjC,QAAQ;IACR,SAAS,IAAI;IACb,YAAY,IAAI;GAClB,GAAG,CAAC,OAAO,CAAC;GACZ,MAAM,aAA0B,gBAC5B,CAAC;IAAE,IAAI;IAAK,OAAO,EAAE,kBAAkB;IAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,EAAmB,MAAM,GAAK,CAAA;IAAG,UAAU,YAAY;GAAK,CAAC,IAC7G,CAAC;GACL,MAAM,YAAY,CAAC,WAAW,SAAS,MAAM,SAAS;GACtD,MAAM,QAAqB,YACvB,SAAS,MAAM,KAAI,eAAc;IACjC,IAAI,UAAU;IACd,OAAO,UAAU;IACjB,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,EAAmB,MAAM,GAAK,CAAA;IACpC,UAAU,YAAY;GACxB,EAAE,IACA;GACJ,MAAM,UAAU,WAAW,SAAS,UAAU;GAC9C,MAAM,UAAU,CAAC,aAAa,WAAW,WAAW,WAAW;GAC/D,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,QAAQ,WAAW,CAAC,YAAY,CAAC,MAAM,SAAS;GACtD,GAAG;IAAC;IAAM;IAAU;IAAS;IAAM;GAAQ,CAAC;GAE5C,MAAM,QAAiC;IACrC,MAAM;IACN;IACA,WAAW,SAAS;KAClB,QAAQ,IAAI;KACZ,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAC,MAAK,cAAa;MAC1C,YAAY,KAAK;MACjB,OAAO,UAAU,WAAW;KAC9B,CAAC,CAAC,CAAC,OAAO,WAAoB;MAC5B,YAAY,KAAK;MACjB,SAAS,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM,CAAC;KACpE,CAAC,CAAC,CAAC,cAAc;MAAE,QAAQ,KAAK;KAAE,CAAC;IACrC;IACA,gBAAgB;KAAE,YAAY,KAAK;IAAE;IACrC,UAAU,YAAY;KAAE,YAAY,KAAK;KAAG,SAAS,OAAO;IAAE;GAChE;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;IACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,MAAD;KACE,MAAM,QAAQ,CAAC,WAAW,MAAM,SAAS;KACzC,QAAQ;KACD;KACP,GAAI,YAAY,EAAE,QAAQ,WAAW,IAAI,CAAC;KAC9B;KACZ,WAAW,OAAO;MAAE,IAAI,OAAO,KAAK,SAAS;WAAQ,OAAO,EAAiB;KAAE;KACtE;KACH;KACN,QAAA;KACe;IAChB,CAAA;IACA,QAAQ,CAAC,WAAW,SAAS,UAAU,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KAAa,UAAA,EAAE,SAAS;IAAO,CAAA;IAClG,oBAAoB,KAAK;IAC1B,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;KACE,MAAM,UAAU;KAChB,eAAe;MAAE,SAAS,IAAI;KAAE;KAChC,YAAY,EAAE,QAAQ;KACtB,OAAO,EAAE,aAAa;KACtB,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,QAAD;MAAQ,SAAQ;MAAU,eAAe;OAAE,SAAS,IAAI;MAAE;MAAI,UAAA,EAAE,QAAQ;KAAU,CAAA,GAClF,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;MAAQ,SAAQ;MAAU,UAAU,CAAC;MAAe,SAAS;MAAW,UAAA,EAAE,OAAO;KAAU,CAAA,CAC3F,EAAA,CAAA;KAGJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAkB,MAAK;MAAS,UAAA;KAAW,CAAA;IACrD,CAAA;GACP,EAAA,CAAA;EAEN;;EAGA,SAAgB,gBAAgB,EAC9B,MAAM,WAAW,eAAe,YAAY,QAAQ,SACpD,iBAAiB,kBAAkB,YAAY,KACjC;GACd,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,mBAAD;IACK;IACG;IACK;IACI;IACH;IACJ;IACC;IACQ;IACC;IAClB,sBAAqB,UAAS,WAAW,6CAA6C,KAAK;GAC5F,CAAA;EAEL;;;;ECtIA,MAAa,YAAY;EAyBzB,SAAS,QAAQ,SAAyB,SAAgC,UAA2C;GACnH,OAAO,QAAQ,WAAW,cACrB,CAAC,SAAS,IAAI,QAAQ,EAAE,MACvB,CAAC,QAAQ,SAAS,QAAQ,OAAO;EACzC;EAEA,SAAS,MACP,SACA,cACA,gBACY;GACZ,OAAO;IACL,IAAI,QAAQ;IACZ,OAAO,QAAQ,QAAQ,gBAAgB,QAAQ;IAC/C,OAAO,QAAQ;IACf,SAAS,QAAQ;IACjB,GAAI,QAAQ,uBAAuB,KAAA,IAAY,CAAC,IAAI,EAAE,oBAAoB,QAAQ,mBAAmB;IACrG,WAAW,QAAQ,cAAc;IACjC,WAAW,QAAQ;IACnB;IACA;GACF;EACF;EAEA,SAAS,WAAW,YAAqE;GACvF,MAAM,yBAAS,IAAI,IAA8B;GACjD,KAAK,MAAM,aAAa,YACtB,KAAK,MAAM,aAAa,UAAU,YAAY,OAAO,IAAI,WAAW,SAAS;GAE/E,OAAO;EACT;;EAGA,SAAgB,uBACd,WACA,YACuC;GACvC,IAAI,cAAc,KAAA,GAAW,OAAO;GACpC,OAAO,WAAW,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,EAAE,eAAA;EAChD;;EAGA,SAAgB,aACd,MACA,YACA,oBACA,QAAQ,GACM;GACd,MAAM,WAAW,IAAI,IAAI,kBAAkB;GAC3C,MAAM,SAAS,WAAW,UAAU;GACpC,OAAO,KAAK,IACT,KAAI,OAAM,KAAK,KAAK,GAAG,CAAC,CACxB,QAAQ,YAAuC,YAAY,KAAA,KAAa,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,CAAC,CACjH,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,aAAa,OAAO,EAAE,EAAE,CAAC,CAAC,cAAc,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CACrF,MAAM,GAAG,KAAK,CAAC,CACf,KAAK,YAAY;IAChB,MAAM,YAAY,OAAO,IAAI,QAAQ,EAAE;IACvC,OAAO,MAAM,SAAS,WAAW,eAAA,oBAA0B,WAAW,SAAS,WAAW;GAC5F,CAAC;EACL;;EAGA,SAAgB,iBACd,MACA,YACA,oBACgB;GAChB,MAAM,WAAW,IAAI,IAAI,kBAAkB;GAC3C,MAAM,4BAAY,IAAI,IAAe;GACrC,MAAM,SAAS,WAAW,KAAK,cAA4B;IACzD,IAAI,QAAQ;IACZ,KAAK,MAAM,MAAM,UAAU,YAAY;KACrC,UAAU,IAAI,EAAE;KAChB,MAAM,UAAU,KAAK,KAAK;KAC1B,IAAI,YAAY,KAAA,KAAa,QAAQ,SAAS,KAAK,SAAS,QAAQ,GAAG;IACzE;IACA,OAAO;KACL,KAAK,UAAU;KACf,OAAO,UAAU;KACjB,MAAM,UAAU;KAChB,WAAW,UAAU;KACrB;KACA,MAAM;IACR;GACF,CAAC;GACD,IAAI,YAAY;GAChB,KAAK,MAAM,MAAM,KAAK,KAAK;IACzB,MAAM,UAAU,KAAK,KAAK;IAC1B,IAAI,YAAY,KAAA,KAAa,CAAC,UAAU,IAAI,EAAE,KAAK,QAAQ,SAAS,KAAK,SAAS,QAAQ,GAAG;GAC/F;GACA,OAAO,KAAK;IAAE,KAAK;IAAW,OAAO;IAAa,OAAO;IAAW,MAAM;GAAM,CAAC;GACjF,OAAO;EACT;;EAGA,SAAgB,wBACd,KACA,MACA,YACA,oBACc;GACd,MAAM,WAAW,IAAI,IAAI,kBAAkB;GAC3C,IAAI,QAAA,oBAAmB;IACrB,MAAM,YAAY,IAAI,IAAI,WAAW,SAAQ,cAAa,UAAU,UAAU,CAAC;IAC/E,OAAO,KAAK,IACT,KAAI,OAAM,KAAK,KAAK,GAAG,CAAC,CACxB,QAAQ,YAAuC,YAAY,KAAA,KACvD,CAAC,UAAU,IAAI,QAAQ,EAAE,KACzB,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,CAAC,CAC7C,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,aAAa,OAAO,EAAE,EAAE,CAAC,CAAC,cAAc,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CACrF,KAAI,YAAW,MAAM,SAAS,WAAW,WAAW,CAAC;GAC1D;GACA,MAAM,YAAY,WAAW,MAAK,SAAQ,KAAK,gBAAgB,GAAG;GAClE,IAAI,cAAc,KAAA,GAAW,OAAO,CAAC;GACrC,OAAO,UAAU,WACd,KAAI,OAAM,KAAK,KAAK,GAAG,CAAC,CACxB,QAAQ,YAAuC,YAAY,KAAA,KAAa,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,CAAC,CACjH,KAAI,YAAW,MAAM,SAAS,UAAU,aAAa,UAAU,KAAK,CAAC;EAC1E;;EAGA,SAAgB,aAAa,MAA6B,OAA6B;GACrF,MAAM,aAAa,MAAM,KAAK,CAAC,CAAC,kBAAkB;GAClD,IAAI,eAAe,IAAI,OAAO,CAAC;GAC/B,OAAO,KAAK,QAAO,QAAO,GAAG,IAAI,MAAM,IAAI,IAAI,iBAAiB,kBAAkB,CAAC,CAAC,SAAS,UAAU,CAAC;EAC1G;;;;EC5IA,MAAM,qBAAqB;EAC3B,MAAM,aAAa;EAEnB,SAAS,UAAU,OAAuB;GACxC,OAAO,MAAM,WAAW,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,UAAU;EACvD;EAEA,SAAS,aAAa,WAAmB,KAAa,GAA8B;GAClF,MAAM,OAAO,KAAK,IAAI,GAAG,MAAM,SAAS;GACxC,MAAM,SAAS;GACf,IAAI,OAAO,QAAQ,OAAO,EAAE,KAAK;GACjC,IAAI,OAAO,KAAK,QAAQ,OAAO,EAAE,WAAW,EAAE,GAAG,KAAK,MAAM,OAAO,MAAM,EAAE,CAAC;GAC5E,IAAI,OAAO,OAAU,QAAQ,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,MAAM,QAAQ,KAAK,OAAO,EAAE,CAAC;GACtF,IAAI,OAAO,QAAe,QAAQ,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,MAAM,QAAQ,OAAU,OAAO,EAAE,CAAC;GAC/F,IAAI,OAAO,SAAgB,QAAQ,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,MAAM,QAAQ,QAAe,OAAO,EAAE,CAAC;GACvG,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,MAAM,QAAQ,SAAgB,OAAO,EAAE,CAAC;EACtE;EAEA,SAAS,cAAc,EAAE,OAA4B;GACnD,IAAI,IAAI,uBAAuB,KAAA,GAAW,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD,EAAU,OAAM,UAAW,CAAA;GAC5E,IAAI,IAAI,SAAS,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,UAAD,EAAU,OAAM,UAAW,CAAA;GACnD,IAAI,IAAI,WAAW,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,UAAD,EAAU,OAAM,OAAQ,CAAA;GAClD,OAAO;EACT;EAsBA,SAAS,QAAQ,OAA4E;GAC3F,MAAM,OAAO,MAAM,cAAc,sBAAsB;GACvD,OAAO,MAAM,UAAU,KAAK,MAAM,KAAK,SAAS,IAAI,WAAW;EACjE;EAEA,SAAS,YAAY,EAAE,KAAK,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,GAAG,SAAS,QAAyB;GAC1G,MAAM,CAAC,UAAU,gBAAA,GAAeC,MAAAA,SAAAA,CAAS,KAAK;GAC9C,MAAM,QAAQ,IAAI,QAAQ,EAAE,YAAY,IAAI,IAAI;GAChD,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,WAAW,SAAS,IAAI,OAAO,UAAU,iBAAiB,KAAK,WAAW,kBAAkB,KAAK,MAAM,WAAW,WAAW,oBAAoB,KAAK,MAAM,WAAW,UAAU,mBAAmB;IACpM,MAAK;IACL,iBAAe,IAAI,OAAO;IAC1B,WAAW,SAAS,KAAA;IACpB,eAAe;KAAE,KAAK,IAAI,EAAE;IAAE;IAC9B,aAAa,SAAS,KAAA,IAAY,KAAA,KAAa,UAAU;KAAE,MAAM,aAAa,gBAAgB;KAAQ,KAAK,MAAM;IAAE;IACnH,WAAW,MAAM;IACjB,YAAY,SAAS,KAAA,IAAY,KAAA,KAAa,UAAU;KACtD,IAAI,CAAC,KAAK,QAAQ;KAClB,MAAM,eAAe;KACrB,MAAM,aAAa,aAAa;KAChC,KAAK,MAAM,QAAQ,KAAK,CAAC;IAC3B;IACA,QAAQ,SAAS,KAAA,IAAY,KAAA,KAAa,UAAU;KAClD,IAAI,CAAC,KAAK,QAAQ;KAClB,MAAM,eAAe;KACrB,KAAK,KAAK,QAAQ,KAAK,CAAC;IAC1B;IAlBF,UAAA;KAoBE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAiB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,eAAD,EAAoB,IAAM,CAAA;KAAO,CAAA;KAClE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;OAAM,WAAU;OAAhB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAgB,UAAA;OAAY,CAAA,GAC3C,CAAC,IAAI,SAAS,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAA2B,UAAA,aAAa,IAAI,WAAW,KAAK,CAAC;OAAQ,CAAA,CAChG;MACL,CAAA,GAAA,YAAY,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAAuB,UAAA,IAAI;MAAqB,CAAA,CACjF;;KACL,CAAC,IAAI,SACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MACd,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,MAAD;OACE,MAAM;OACN,eAAe;QAAE,YAAY,KAAK;OAAE;OACpC,OAAO;QACL;SAAE,IAAI;SAAU,OAAO,EAAE,QAAQ;SAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,CAAoB,CAAA;QAAE;QAChE;SAAE,IAAI;SAAQ,OAAO,EAAE,MAAM;SAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,qBAAD,CAAsB,CAAA;QAAE;QAC9D;SAAE,IAAI;SAAW,OAAO,EAAE,SAAS;SAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,sBAAD,EAAsB,MAAM,GAAK,CAAA;QAAE;OACjF;OACA,WAAW,OAAO;QAChB,YAAY,KAAK;QACjB,IAAI,OAAO,UAAU,OAAO,GAAG;QAC/B,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAE;QAC9B,IAAI,OAAO,WAAW,QAAQ,IAAI,EAAE;OACtC;OACA,QAAA;OACA,qBAAA;OACA,QACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAU;QACV,cAAY,GAAG,MAAM;QACrB,UAAU,UAAU;SAAE,MAAM,gBAAgB;SAAG,aAAY,UAAS,CAAC,KAAK;QAAE;QAE5E,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,uBAAD,CAAwB,CAAA;OAClB,CAAA;MAEX,CAAA;KACG,CAAA;IAEL;;EAET;EAEA,SAAS,cAAc,EAAE,KAAK,OAAO,QAAQ,QAAQ,QAAQ,KAO1D;GACD,MAAM,CAAC,UAAU,gBAAA,GAAeL,MAAAA,SAAAA,CAAS,KAAK;GAC9C,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAW,0BAA0B,WAAW,kBAAkB;IAAM,MAAK;IAAW,SAAS;IAAO,OAAO,IAAI;IAAxH,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAiB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACM,sCAAAA,mBAAD,CAAoB,CAAA;KAAO,CAAA;KAC5D,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;OAAM,WAAU;OAAhB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAgB,UAAA,IAAI,OAAO,IAAI,QAAQ,EAAE,WAAW;OAAQ,CAAA,GAC5E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAe,UAAA,EAAE,SAAS,EAAE,GAAG,IAAI,MAAM,CAAC;OAAQ,CAAA,CAC9D;MACL,CAAA,GAAA,IAAI,SAAS,KAAA,KAAa,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAAqB,UAAA,IAAI;MAAW,CAAA,CAC3E;;KACN,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACG,IAAI,QACH,iBAAA,GAAA,kBAAA,IAAA,CAACL,sCAAAA,MAAD;OACE,MAAM;OACN,eAAe;QAAE,YAAY,KAAK;OAAE;OACpC,OAAO,CACL;QAAE,IAAI;QAAU,OAAO,EAAE,QAAQ;QAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,CAAoB,CAAA;OAAE,GAChE;QAAE,IAAI;QAAU,OAAO,EAAE,iBAAiB;QAAG,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACK,sCAAAA,oBAAD,CAAqB,CAAA;QAAG,QAAQ;OAAK,CAC1F;OACA,WAAW,OAAO;QAAE,YAAY,KAAK;QAAG,IAAI,OAAO,UAAU,OAAO;QAAG,IAAI,OAAO,UAAU,OAAO;OAAE;OACrG,QAAA;OACA,qBAAA;OACA,QACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAiB,UAAU,UAAU;SAAE,MAAM,gBAAgB;SAAG,aAAY,UAAS,CAAC,KAAK;QAAE;QAC3H,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACF,sCAAAA,uBAAD,CAAwB,CAAA;OAClB,CAAA;MAEX,CAAA,GAEF,IAAI,QACH,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,MAAK;OAAS,WAAU;OAAiB,UAAU,UAAU;QAAE,MAAM,gBAAgB;QAAG,OAAO;OAAE;OACvG,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACG,sCAAAA,mBAAD,CAAoB,CAAA;MACd,CAAA,CAEN;;KACN,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,2BAAD,CAA4B,CAAA;IACzB;;EAET;;EAUA,SAAgB,iBAAiB,OAAqB;GACpD,MAAM,EACJ,MAAM,eAAe,aAAa,eAAe,cAAc,MAAM,gBACrE,mBAAmB,eAAe,aAAa,iBAAiB,iBAChE,gBAAgB,qBAAqB,iBAAiB,kBAAkB,YAAY,MAClF;GACJ,MAAM,WAAW,aAAY,UAAS,KAAK;GAC3C,MAAM,iBAAiB,eAAc,UAAS,KAAK;GACnD,MAAM,aAAa,eAAe;GAClC,MAAM,WAAW,eAAe;GAChC,MAAM,yBAAyB,kBAAiB,UAAS,KAAK;GAC9D,MAAM,WAAA,GAAUC,MAAAA,QAAAA,OACR,aAAa,UAAU,YAAY,UAAU,OAAO,gBAAgB,GAC1E;IAAC;IAAU;IAAU;GAAU,CACjC;GACA,MAAM,SAAS,QAAQ,MAAM,GAAG,CAAC;GACjC,MAAM,iBAAA,GAAgBA,MAAAA,QAAAA,OACd,iBAAiB,UAAU,YAAY,QAAQ,GACrD;IAAC;IAAU;IAAU;GAAU,CACjC;GACA,MAAM,CAAC,aAAa,mBAAA,GAAkBV,MAAAA,SAAAA,CAAgD,IAAI;GAC1F,MAAM,CAAC,WAAW,iBAAA,GAAgBA,MAAAA,SAAAA,CAAiC,SAAS;GAC5E,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,KAAK;GAClD,CAAA,GAAA,MAAA,UAAA,OAAgB;IAAE,cAAc,IAAI;GAAE,GAAG,CAAC,CAAC;GAC3C,MAAM,mBAAA,GAAkBW,MAAAA,OAAAA,CAA8B,KAAA,CAAS;GAC/D,MAAM,eAAA,GAAcA,MAAAA,OAAAA,CAAO,KAAK;GAChC,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,YAAY,WAAW,gBAAgB,YAAY,SAAS,SAAS;IACzE,YAAY,UAAU;IACtB,gBAAgB,UAAU,SAAS;IACnC,IAAI,SAAS,YAAY,KAAA,GAAW;KAAE,aAAa,SAAS;KAAG,eAAe,uBAAuB,SAAS,SAAS,UAAU,CAAC;IAAE;GACtI,GAAG,CAAC,SAAS,SAAS,UAAU,CAAC;GACjC,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,gBAAgB,QAAQ,gBAAA,sBACvB,CAAC,WAAW,MAAK,cAAa,UAAU,gBAAgB,WAAW,GAAG,eAAe,SAAS;GACrG,GAAG,CAAC,aAAa,UAAU,CAAC;GAC5B,MAAM,oBAAoB,gBAAgB,QAAQ,gBAAA,qBAC9C,KAAA,IACA,WAAW,MAAK,cAAa,UAAU,gBAAgB,WAAW;GACtE,MAAM,YAAY,gBAAgB,OAC9B,CAAC,IACD,wBAAwB,aAAa,UAAU,YAAY,QAAQ;GACvE,MAAM,MAAM,KAAK,IAAI;GAErB,MAAM,CAAC,OAAO,aAAA,GAAYX,MAAAA,SAAAA,CAAS,EAAE;GACrC,MAAM,kBAAkB,UAAU,KAAK,CAAC,CAAC,KAAK;GAC9C,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAsB;IAAE,OAAO;IAAI,QAAQ;IAAQ,OAAO,CAAC;IAAG,SAAS;GAAM,CAAC;GAC1G,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,oBAAoB,IAAI;KAC1B,UAAU;MAAE,OAAO;MAAI,QAAQ;MAAQ,OAAO,CAAC;MAAG,SAAS;KAAM,CAAC;KAClE;IACF;IACA,MAAM,aAAa,IAAI,gBAAgB;IACvC,UAAU;KAAE,OAAO;KAAiB,QAAQ;KAAW,OAAO,CAAC;KAAG,SAAS;IAAM,CAAC;IAClF,MAAM,QAAQ,OAAO,iBAAiB;KACpC,eAAe,iBAAiB,WAAW,MAAM,CAAC,CAAC,MAAK,WAAU;MAChE,IAAI,CAAC,WAAW,OAAO,SAAS,UAAU;OAAE,OAAO;OAAiB,QAAQ;OAAS,OAAO,OAAO;OAAO,SAAS,OAAO;MAAQ,CAAC;KACrI,CAAC,CAAC,CAAC,YAAY;MACb,IAAI,CAAC,WAAW,OAAO,SAAS,UAAU;OAAE,OAAO;OAAiB,QAAQ;OAAS,OAAO,CAAC;OAAG,SAAS;MAAM,CAAC;KAClH,CAAC;IACH,GAAG,kBAAkB;IACrB,aAAa;KAAE,OAAO,aAAa,KAAK;KAAG,WAAW,MAAM;IAAE;GAChE,GAAG,CAAC,iBAAiB,cAAc,CAAC;GACpC,MAAM,cAAA,GAAaU,MAAAA,QAAAA,OAAc;IAC/B,IAAI,oBAAoB,IAAI,OAAO,CAAC;IACpC,MAAM,OAAO,IAAI,IAAI,aAAa,SAAS,eAAe,CAAC,CAAC,KAAI,QAAO,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IACrF,IAAI,OAAO,UAAU,iBACnB,KAAK,MAAM,QAAQ,OAAO,OAAO;KAC/B,MAAM,MAAM,QAAQ,MAAK,cAAa,UAAU,OAAO,KAAK,SAAS;KACrE,IAAI,QAAQ,KAAA,GAAW,KAAK,IAAI,IAAI,IAAI,GAAG;IAC7C;IAEF,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,iBAAiB;GACtD,GAAG;IAAC;IAAS;IAAiB;IAAQ;GAAiB,CAAC;GAExD,MAAM,CAAC,YAAY,kBAAA,GAAiBV,MAAAA,SAAAA,CAAS,KAAK;GAClD,MAAM,gBAAA,GAAeW,MAAAA,OAAAA,CAA0B,IAAI;GACnD,MAAM,CAAC,iBAAiB,uBAAA,GAAsBX,MAAAA,SAAAA,CAAS,KAAK;GAC5D,MAAM,CAAC,iBAAiB,uBAAA,GAAsBA,MAAAA,SAAAA,CAA8B,IAAI;GAChF,MAAM,CAAC,eAAe,qBAAA,GAAoBA,MAAAA,SAAAA,CAA4B,IAAI;GAC1E,MAAM,CAAC,aAAa,mBAAA,GAAkBA,MAAAA,SAAAA,CAAS,EAAE;GACjD,MAAM,CAAC,aAAa,mBAAA,GAAkBA,MAAAA,SAAAA,CAAwB,IAAI;GAClE,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,CAAC,cAAc,oBAAA,GAAmBA,MAAAA,SAAAA,CAA8B,IAAI;GAC1E,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAA6F,IAAI;GAEzH,MAAM,wBAAwB,QAAsB;IAAE,mBAAmB,GAAG;IAAG,eAAe,IAAI,KAAK;IAAG,eAAe,IAAI;GAAE;GAC/H,MAAM,sBAAsB,QAAoB;IAAE,iBAAiB,GAAG;IAAG,eAAe,IAAI,KAAK;IAAG,eAAe,IAAI;GAAE;GACzH,MAAM,oBAAoB;IAAE,IAAI,CAAC,MAAM;KAAE,mBAAmB,IAAI;KAAG,iBAAiB,IAAI;KAAG,eAAe,IAAI;IAAE;GAAE;GAClH,MAAM,qBAAqB;IACzB,MAAM,QAAQ,YAAY,KAAK;IAC/B,IAAI,UAAU,MAAM,MAAM;IAC1B,QAAQ,IAAI;IAIZ,CAHa,oBAAoB,QAAQ,gBAAgB,QAAA,qBACrD,gBAAgB,gBAAgB,KAAK,KAAK,IAC1C,kBAAkB,OAAO,cAAc,cAAc,IAAI,KAAK,IAAI,QAAQ,QAAQ,EAAA,CACjF,WAAW;KAAE,mBAAmB,IAAI;KAAG,iBAAiB,IAAI;IAAE,CAAC,CAAC,CAClE,OAAO,WAAoB;KAAE,eAAe,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM,CAAC;IAAE,CAAC,CAAC,CACzG,cAAc;KAAE,QAAQ,KAAK;IAAE,CAAC;GACrC;GACA,MAAM,sBAAsB;IAC1B,IAAI,iBAAiB,QAAQ,aAAa,QAAA,sBAAqB,MAAM;IACrE,QAAQ,IAAI;IACZ,gBAAgB,aAAa,GAAG,CAAC,CAAC,WAAW;KAAE,gBAAgB,IAAI;IAAE,CAAC,CAAC,CACpE,OAAO,WAAoB;KAAE,eAAe,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM,CAAC;IAAE,CAAC,CAAC,CACzG,cAAc;KAAE,QAAQ,KAAK;IAAE,CAAC;GACrC;GACA,MAAM,WAAW,OAAkB;IAAE,eAAe,EAAE,CAAC,CAAC,OAAM,WAAU;KAAE,QAAQ,KAAK,6BAA6B,MAAM;IAAE,CAAC;GAAE;GAC/H,MAAM,QAAQ,OAAkB;IAAE,YAAY,EAAE;GAAE;GAElD,MAAM,eAAe,KAAiB,UAAU,OAAO,UAAmB;IACxE,MAAM,YAAY,gBAAgB,QAAQ,gBAAA,sBAA6B,UAAU,KAAA;IACjF,MAAM,SAAS,MAAM,MAAM,OAAO,IAAI,KAAK,KAAK,KAAK,OAAO;IAC5D,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;KAEO;KACL,SAAS,SAAS;KACb;KACC;KACN,QAAQ;KACF;KACG;KACN;KACM;KACT,GAAI,aAAa,gBAAgB,QAAQ,gBAAA,qBAA4B,EACnE,MAAM;MACJ,QAAQ,SAAS;MACjB;MACA,aAAa;OAAE,QAAQ;QAAE,IAAI,IAAI;QAAI,MAAM;OAAK,CAAC;MAAE;MACnD,QAAQ,SAA6B;OAAE,SAAQ,UAAS,UAAU,OAAO,QAAQ;QAAE,GAAG;QAAO,MAAM;SAAE,IAAI,IAAI;SAAI;QAAK;OAAE,CAAC;MAAE;MAC3H,OAAO,SAA6B;OAClC,IAAI,SAAS,MAAM;OACnB,MAAM,SAAS,SAAS,WAAW,IAAI,KAAK,WAAW,SAAS,KAAK,EAAE,EAAE;OACzE,MAAM,cAAc,UAAU,WAAU,SAAQ,KAAK,OAAO,KAAK,EAAE;OACnE,MAAM,cAAc,WAAW,KAAA,IAAY,UAAU,SAAS,UAAU,WAAU,SAAQ,KAAK,OAAO,MAAM;OAC5G,QAAQ,IAAI;OACZ,IAAI,WAAW,KAAK,MAAM,gBAAgB,eAAe,cAAc,MAAM,aAAa;OAC1F,oBAAoB,aAAa,KAAK,IAAI,MAAM,CAAC,CAAC,OAAM,WAAU;QAAE,QAAQ,KAAK,6BAA6B,MAAM;OAAE,CAAC;MACzH;MACA,WAAW;OAAE,QAAQ,IAAI;MAAE;KAC7B,EACF,IAAI,CAAC;IACN,GA5BM,IAAI,EA4BV;GAEL;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,6BAAA;IAA0B,WAAW,OAAO,KAAK;IAAtD,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACG,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAoB,UAAA,EAAE,YAAY;OAAQ,CAAA;OAClE,0BACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,KAAK;QAAc,MAAK;QAAS,WAAU;QAAiB,cAAY,EAAE,cAAc;QAAG,eAAe;SAAE,eAAc,UAAS,CAAC,KAAK;QAAE;QACjJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACY,sCAAAA,yBAAD,EAAyB,MAAM,OAAO,KAAK,GAAK,CAAA;OAC1C,CAAA;OAEV,iBAAA,GAAA,kBAAA,IAAA,CAAC,mBAAD;QACK;QACH,MAAM;QACN,WAAW;QACI;QACE;QACC;QAClB,sBAAqB,UAAS,WAAW,oCAAoC,KAAK;QAClF,SAAA;QACA,MAAK;QACL,SAAS,gBAAgB;SAAE,cAAc,KAAK;SAAG,aAAa,WAAW;QAAE;QAC3E,eAAe;SAAE,cAAc,KAAK;QAAE;OACvC,CAAA;MACE;;KAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAY,eAAe;OAAE,IAAI,CAAC,MAAM,cAAc;MAAE;MAAvE,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAiB,cAAY,EAAE,QAAQ;QAAG,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,qBAAD,EAAqB,MAAM,OAAO,KAAK,GAAK,CAAA;OAAS,CAAA;OAC9H,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QAAO,WAAU;QAAkB,OAAO;QAAO,WAAW;QAAY,aAAa,EAAE,mBAAmB;QAAG,WAAU,UAAS;SAAE,SAAS,UAAU,MAAM,OAAO,KAAK,CAAC;QAAE;OAAI,CAAA;OACtL,QAAQ,UAAU,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAiB,cAAY,EAAE,aAAa;QAAG,eAAe;SAAE,SAAS,EAAE;QAAE;QAAG,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,iBAAD,CAAkB,CAAA;OAAS,CAAA;MACjK;;KAEJ,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MACZ,UAAA,oBAAoB,KACnB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAU;OAAY,MAAK;OAAO,cAAY,EAAE,QAAQ;OAA7D,UAAA;QACG,WAAW,KAAI,QAAO,YAAY,KAAK,IAAI,CAAC;QAC5C,OAAO,WAAW,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAa,UAAA,EAAE,WAAW;QAAO,CAAA;QAC/E,OAAO,WAAW,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAwB,UAAA,EAAE,mBAAmB;QAAO,CAAA;QAChG,OAAO,WAAW,aAAa,WAAW,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAY,UAAA,EAAE,WAAW;QAAO,CAAA;OACvG;MAEL,CAAA,IAAA,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAW,YAAY,kBAAkB,yBAAyB;QAAvE,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,QAAQ,EAAQ,CAAA,GACxB,OAAO,SAAS,KACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UACE,MAAK;UACL,WAAW,wBAAwB,kBAAkB,kBAAkB;UACvE,cAAY,kBAAkB,EAAE,QAAQ,IAAI,EAAE,UAAU;UACxD,iBAAe,CAAC;UAChB,UAAU,UAAU;WAAE,MAAM,gBAAgB;WAAG,oBAAmB,UAAS,CAAC,KAAK;UAAE;UAEnF,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACL,sCAAAA,2BAAD,CAA4B,CAAA;SACtB,CAAA,CAEP;QACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SACZ,UAAA,OAAO,WAAW,IACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAAY,UAAA,EAAE,YAAY;SAAO,CAAA,IAChD,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAAkB,UAAA,OAAO,KAAI,QAAO,YAAY,KAAK,IAAI,CAAC;SAAO,CAAA;QAEjF,CAAA,CACF;;OACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QACZ,UAAA,gBAAgB,OACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAU;SAAY,UAAA,EAAE,YAAY;QAAQ,CAAA,IAElD,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;SACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UAAQ,MAAK;UAAS,WAAU;UAAW,eAAe;WAAE,aAAa,UAAU;WAAG,eAAe,IAAI;UAAE;UAAI,UAAA,EAAE,YAAY;SAAU,CAAA;SACvI,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,2BAAD,CAA4B,CAAA;SAC5B,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAU;UAAY,UAAA,gBAAA,qBAA4B,EAAE,WAAW,IAAI,mBAAmB;SAAY,CAAA;SACvG,gBAAA,sBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;UAAQ,MAAK;UAAS,WAAU;UAAiB,cAAY,EAAE,YAAY;UAAG,eAAe;WAAE,aAAa,WAAW;UAAE;UAAG,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACD,sCAAAA,mBAAD,CAAoB,CAAA;SAAS,CAAA;QAE3J,EAAA,CAAA;OAED,CAAA;OACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAY,MAAK;QAAO,cAAY,gBAAgB,OAAO,EAAE,YAAY,IAAI,EAAE,UAAU;QACtG,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAiC,WAAW,aAAa,kBAAkB,cAAc,KAAA;SAAzF,UAAA;UACG,gBAAgB,OACb,cAAc,KAAI,QAClB,iBAAA,GAAA,kBAAA,IAAA,CAAC,eAAD;WAEO;WACL,aAAa;YAAE,aAAa,SAAS;YAAG,eAAe,IAAI,GAAG;WAAE;WAChE,cAAc;YAAE,IAAI,IAAI,QAAA,oBAAmB,aAAa,IAAI,GAAG;WAAE;WACjE,cAAc;YAAE,qBAAqB,GAAG;WAAE;WAC1C,cAAc;YAAE,gBAAgB,GAAG;YAAG,eAAe,IAAI;WAAE;WACxD;UACJ,GAPM,IAAI,GAOV,CACF,IACC,UAAU,KAAK,KAAK,UAAU,YAAY,KAAK,OAAO,KAAK,CAAC;UAC/D,gBAAgB,QAAQ,cAAc,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WAAY,UAAA,EAAE,cAAc;UAAO,CAAA;UACxG,gBAAgB,QAAQ,UAAU,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WAAY,UAAA,EAAE,YAAY;UAAO,CAAA;SAChG;QAhBK,GAAA,eAAe,MAgBpB;OACF,CAAA;MACL,EAAA,CAAA;KAED,CAAA;KAGP,iBAAA,GAAA,kBAAA,KAAA,CAACO,sCAAAA,OAAD;MACE,MAAM,oBAAoB,QAAQ,kBAAkB;MACpD,SAAS;MACT,YAAY,EAAE,QAAQ;MACtB,OAAO,oBAAoB,OAAO,EAAE,iBAAiB,IAAI,EAAE,eAAe;MAC1E,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,QAAD;OAAQ,SAAQ;OAAU,UAAU;OAAM,SAAS;OAAc,UAAA,EAAE,QAAQ;MAAU,CAAA,GACrF,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;OAAQ,SAAQ;OAAU,UAAU,QAAQ,YAAY,KAAK,MAAM;OAAI,SAAS;OAAe,UAAA,EAAE,QAAQ;MAAU,CAAA,CACnH,EAAA,CAAA;MATN,UAAA,CAYE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;OAAO,WAAU;OAAkB,OAAO;OAAa,WAAA;OAAU,UAAU;OAAM,cAAY,oBAAoB,OAAO,EAAE,eAAe,IAAI,EAAE,aAAa;OAAG,WAAU,UAAS;QAAE,eAAe,MAAM,OAAO,KAAK;QAAG,eAAe,IAAI;OAAE;MAAI,CAAA,GAChP,gBAAgB,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAW,MAAK;OAAS,UAAA;MAAiB,CAAA,CAC7E;;KAEP,iBAAA,GAAA,kBAAA,IAAA,CAACD,sCAAAA,OAAD;MACE,MAAM,iBAAiB;MACvB,eAAe;OAAE,IAAI,CAAC,MAAM,gBAAgB,IAAI;MAAE;MAClD,YAAY,EAAE,QAAQ;MACtB,OAAO,EAAE,iBAAiB;MAC1B,aAAa,iBAAiB,OAAO,KAAA,IAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,MAAM,CAAC;MACpG,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,QAAD;OAAQ,SAAQ;OAAU,UAAU;OAAM,eAAe;QAAE,gBAAgB,IAAI;OAAE;OAAI,UAAA,EAAE,QAAQ;MAAU,CAAA,GACzG,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;OAAQ,SAAQ;OAAU,UAAU;OAAM,SAAS;OAAgB,UAAA,EAAE,iBAAiB;MAAU,CAAA,CAChG,EAAA,CAAA;MAGH,UAAA,gBAAgB,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAW,MAAK;OAAS,UAAA;MAAiB,CAAA;KAC7E,CAAA;IACJ;;EAET;;;;EC1cA,MAAa,SAAS;GAAC;GAAS;GAAY;GAAc;EAAQ;;EAGlE,SAAgB,MAAM,KAA0B;GAC9C,IAAI,aAAa,IAAI,OAAO,SAAS,IAAI;IAAE;IAAI;GAAG,CAAC,GAAG,oCAAoC;GAC1F,IAAI,OAAO,eAAe,8BAA8B;GAExD,MAAM,cACJ,UAC6B;IAC7B,mBAAmB,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC,SAAS;IACpD,YAAW,aAAY,IAAI,MAAM,UAAU,MAAM,QAAQ;GAC3D;GACA,MAAM,cAAc,WAAW,kCAAkC;GACjE,MAAM,aAAa,WAAW,2CAA2C;GACzE,MAAM,mBAAmB,UAA4B,IAAI,WAAW,OAAO,KAAK;GAEhF,MAAM,iBAAoD,OAAO,OAAO,WAAW;IACjF,MAAM,SAAS,MAAM,IAAI,SAAS,OAAO,OAAO,MAAM;IACtD,IAAI,CAAC,OAAO,IAAI,MAAM,IAAI,MAAM,OAAO,MAAM,OAAO;IACpD,OAAO,OAAO;GAChB;GACA,MAAM,yBAA0C;IAC9C,eAAc,gBAAe;KAAE,IAAI,WAAW,aAAa,WAAW;IAAE;IACxE,OAAM,cAAa;KAAE,IAAI,SAAS,KAAK,SAAS;IAAE;IAClD;IACA,mBAAmB,IAAI,SAAS;IAChC,eAAe,OAAO,WAAW,UAAU;KACzC,MAAM,UAAU,IAAI,SAAS,QAAQ,SAAS,CAAC,EAAE;KACjD,IAAI,YAAY,KAAA,GAAW,MAAM,IAAI,MAAM,oBAAoB,UAAU,EAAE;KAC3E,MAAM,SAAS,MAAM,QAAQ,OAAO,KAAK;KACzC,IAAI,CAAC,OAAO,IAAI,MAAM,IAAI,MAAM,OAAO,MAAM,OAAO;IACtD;IACA,cAAa,cAAa;KACxB,IAAI,SAAS,KAAK;MAAE;MAAW,eAAe;KAAK,CAAC,CAAC,CAClD,MAAK,YAAW;MAAE,IAAI,SAAS,KAAK,OAAO;KAAE,CAAC,CAAC,CAC/C,YAAY,CAAC,CAAC;IACnB;IACA,iBAAiB,OAAO,aAAa,UAAU;KAAE,MAAM,IAAI,WAAW,OAAO,aAAa,KAAK;IAAE;IACjG,iBAAiB,OAAM,gBAAe;KAAE,MAAM,IAAI,WAAW,OAAO,WAAW;IAAE;IACjF,gBAAgB,OAAM,cAAa;KAAE,MAAM,IAAI,WAAW,eAAe,SAAS;IAAE;IACpF,qBAAqB,OAAO,aAAa,WAAW,oBAAoB;KACtE,MAAM,IAAI,WAAW,oBAAoB,aAAa,WAAW,eAAe;IAClF;IACA;IACA,OAAO,EAAE,eAAe,YAAY;GACtC;GACA,MAAM,wBAAwC;IAC5C;IACA,OAAO,EAAE,eAAe,WAAW;GACrC;GAEA,IAAI,MAAM,OAAO,4BAA4B,IAAI,MAAM,SAAS;IAC9D,MAAM;IACN,UAAU,EAAE,oCAAoC;KAAE,MAAM;KAAU,OAAO;IAAO,EAAE;IAClF,QAAQ;IACR,QAAQ;GACV,GAAG,gBAAgB,CAAC;GAEpB,IAAI,MAAM,OAAO,qCAAqC,IAAI,MAAM,SAAS;IACvE,MAAM;IACN,UAAU,EAAE,6CAA6C;KAAE,MAAM;KAAU,OAAO;IAAO,EAAE;IAC3F,QAAQ;IACR,QAAQ;GACV,GAAG,eAAe,CAAC;EACrB"}
|
|
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 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 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 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@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 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 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/** 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","/** 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 { 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}\n\nfunction SessionItem({ row, current, now, open, rename, fork, archive, t, context }: 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' : ''}`}\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: 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, 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\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) => (\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 />\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 : 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 </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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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Existing-workspace menu plus composed directory-adoption flow. */
|
|
2
|
+
import type { ReactNode, RefObject } from 'react';
|
|
3
|
+
import type { WorkspaceId, WorkspaceListState, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
|
+
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
|
|
5
|
+
import type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts';
|
|
6
|
+
interface FlowProps {
|
|
7
|
+
t: PickerProps['t'];
|
|
8
|
+
open: boolean;
|
|
9
|
+
anchorRef?: RefObject<HTMLElement | null>;
|
|
10
|
+
useWorkspaces: <S>(selector: (state: WorkspaceListState) => S) => S;
|
|
11
|
+
createWorkspace: (input: {
|
|
12
|
+
path: string;
|
|
13
|
+
}) => Promise<WorkspaceView>;
|
|
14
|
+
useDirectoryFlow: SnapshotSelectorHook<boolean>;
|
|
15
|
+
renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode;
|
|
16
|
+
onPick: (workspaceId: WorkspaceId) => void;
|
|
17
|
+
onClose: () => void;
|
|
18
|
+
addOnly?: boolean;
|
|
19
|
+
side?: 'bottom' | 'top' | 'right';
|
|
20
|
+
selectedId?: WorkspaceId;
|
|
21
|
+
}
|
|
22
|
+
/** Render the workspace target menu and directory picking conversation. */
|
|
23
|
+
export declare function WorkspacePickFlow({ t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow, renderDirectoryFlow, onPick, onClose, addOnly, side, selectedId, }: FlowProps): import("react").JSX.Element;
|
|
24
|
+
/** Fill the conversation hero's workspace picker seat. */
|
|
25
|
+
export declare function WorkspacePicker({ open, anchorRef, useWorkspaces, selectedId, onPick, onClose, createWorkspace, useDirectoryFlow, renderSlot, t, }: PickerProps): import("react").JSX.Element;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** Slot contracts and injected Host actions for ya-workspace-sidebar. */
|
|
2
|
+
import type { HostObservable, PropsLocale, PropsRenderSlots, PropsRuntime, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { SessionId, SessionSearchResultItem, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
|
+
import type { YaWorkspaceKey } from './locales.ts';
|
|
5
|
+
/** Directory-picker conversation owned by each trigger surface. */
|
|
6
|
+
export interface DirectoryFlowOwnerProps {
|
|
7
|
+
open: boolean;
|
|
8
|
+
busy: boolean;
|
|
9
|
+
onPicked: (path: string) => void;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
onError: (message: string) => void;
|
|
12
|
+
}
|
|
13
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
14
|
+
interface SlotMap {
|
|
15
|
+
'sidebar.workspaces.directoryFlow': {
|
|
16
|
+
kind: 'single';
|
|
17
|
+
scope: 'root';
|
|
18
|
+
owner: DirectoryFlowOwnerProps;
|
|
19
|
+
};
|
|
20
|
+
'conversation.hero.workspace.directoryFlow': {
|
|
21
|
+
kind: 'single';
|
|
22
|
+
scope: 'root';
|
|
23
|
+
owner: DirectoryFlowOwnerProps;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
interface LocaleNamespaceMap {
|
|
27
|
+
'ya-workspace-sidebar': YaWorkspaceKey;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Shared directory-flow occupancy source. */
|
|
31
|
+
export interface DirectoryInjected {
|
|
32
|
+
hooks: {
|
|
33
|
+
directoryFlow: HostObservable<boolean>;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Browser-private Host operations. */
|
|
37
|
+
export type SidebarInjected = DirectoryInjected & {
|
|
38
|
+
startSession: (workspaceId?: WorkspaceId) => void;
|
|
39
|
+
open: (sessionId: SessionId) => void;
|
|
40
|
+
searchSessions: (query: string, signal: AbortSignal) => Promise<{
|
|
41
|
+
items: readonly SessionSearchResultItem[];
|
|
42
|
+
hasMore: boolean;
|
|
43
|
+
}>;
|
|
44
|
+
searchResultLimit: number;
|
|
45
|
+
renameSession: (sessionId: SessionId, title: string) => Promise<void>;
|
|
46
|
+
forkSession: (sessionId: SessionId) => void;
|
|
47
|
+
renameWorkspace: (workspaceId: WorkspaceId, title: string) => Promise<void>;
|
|
48
|
+
deleteWorkspace: (workspaceId: WorkspaceId) => Promise<void>;
|
|
49
|
+
archiveSession: (sessionId: SessionId) => Promise<void>;
|
|
50
|
+
insertSessionBefore: (workspaceId: WorkspaceId, sessionId: SessionId, beforeSessionId?: SessionId) => Promise<void>;
|
|
51
|
+
createWorkspace: (input: {
|
|
52
|
+
path: string;
|
|
53
|
+
}) => Promise<WorkspaceView>;
|
|
54
|
+
};
|
|
55
|
+
/** Full sidebar component props. */
|
|
56
|
+
export type SidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsRenderSlots<'sidebar.workspaces.directoryFlow'> & Omit<SidebarInjected, 'hooks'> & {
|
|
57
|
+
useDirectoryFlow: SnapshotSelectorHook<boolean>;
|
|
58
|
+
} & PropsLocale<'ya-workspace-sidebar'>;
|
|
59
|
+
/** Conversation hero picker operations. */
|
|
60
|
+
export type PickerInjected = DirectoryInjected & {
|
|
61
|
+
createWorkspace: (input: {
|
|
62
|
+
path: string;
|
|
63
|
+
}) => Promise<WorkspaceView>;
|
|
64
|
+
};
|
|
65
|
+
/** Full conversation hero picker props. */
|
|
66
|
+
export type PickerProps = PropsRuntime<'conversation.hero.workspace'> & PropsRenderSlots<'conversation.hero.workspace.directoryFlow'> & Omit<PickerInjected, 'hooks'> & {
|
|
67
|
+
useDirectoryFlow: SnapshotSelectorHook<boolean>;
|
|
68
|
+
} & PropsLocale<'ya-workspace-sidebar'>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
2
|
+
/** Services required by both replacement client entries. */
|
|
3
|
+
export declare const inject: string[];
|
|
4
|
+
/** Register the sidebar browser and conversation hero picker. */
|
|
5
|
+
export declare function apply(ctx: ClientContext): void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/** Product copy for the replacement workspace browser. */
|
|
2
|
+
export declare const zh: {
|
|
3
|
+
workspaces: string;
|
|
4
|
+
sessions: string;
|
|
5
|
+
recent: string;
|
|
6
|
+
ungrouped: string;
|
|
7
|
+
newSession: string;
|
|
8
|
+
untitled: string;
|
|
9
|
+
addWorkspace: string;
|
|
10
|
+
addWorkspaceMenu: string;
|
|
11
|
+
search: string;
|
|
12
|
+
searchPlaceholder: string;
|
|
13
|
+
clearSearch: string;
|
|
14
|
+
searching: string;
|
|
15
|
+
searchUnavailable: string;
|
|
16
|
+
noMatches: string;
|
|
17
|
+
noSessions: string;
|
|
18
|
+
noWorkspaces: string;
|
|
19
|
+
loading: string;
|
|
20
|
+
rename: string;
|
|
21
|
+
renameWorkspace: string;
|
|
22
|
+
renameSession: string;
|
|
23
|
+
deleteWorkspace: string;
|
|
24
|
+
deleteDescription: string;
|
|
25
|
+
fork: string;
|
|
26
|
+
archive: string;
|
|
27
|
+
cancel: string;
|
|
28
|
+
confirm: string;
|
|
29
|
+
retry: string;
|
|
30
|
+
folderError: string;
|
|
31
|
+
workspaceName: string;
|
|
32
|
+
sessionName: string;
|
|
33
|
+
count: string;
|
|
34
|
+
now: string;
|
|
35
|
+
minutes: string;
|
|
36
|
+
hours: string;
|
|
37
|
+
days: string;
|
|
38
|
+
months: string;
|
|
39
|
+
years: string;
|
|
40
|
+
running: string;
|
|
41
|
+
waiting: string;
|
|
42
|
+
completed: string;
|
|
43
|
+
collapse: string;
|
|
44
|
+
expand: string;
|
|
45
|
+
today: string;
|
|
46
|
+
yesterday: string;
|
|
47
|
+
date: string;
|
|
48
|
+
dateYear: string;
|
|
49
|
+
};
|
|
50
|
+
export type YaWorkspaceKey = keyof typeof zh;
|
|
51
|
+
export declare const en: {
|
|
52
|
+
workspaces: string;
|
|
53
|
+
sessions: string;
|
|
54
|
+
recent: string;
|
|
55
|
+
ungrouped: string;
|
|
56
|
+
newSession: string;
|
|
57
|
+
untitled: string;
|
|
58
|
+
addWorkspace: string;
|
|
59
|
+
addWorkspaceMenu: string;
|
|
60
|
+
search: string;
|
|
61
|
+
searchPlaceholder: string;
|
|
62
|
+
clearSearch: string;
|
|
63
|
+
searching: string;
|
|
64
|
+
searchUnavailable: string;
|
|
65
|
+
noMatches: string;
|
|
66
|
+
noSessions: string;
|
|
67
|
+
noWorkspaces: string;
|
|
68
|
+
loading: string;
|
|
69
|
+
rename: string;
|
|
70
|
+
renameWorkspace: string;
|
|
71
|
+
renameSession: string;
|
|
72
|
+
deleteWorkspace: string;
|
|
73
|
+
deleteDescription: string;
|
|
74
|
+
fork: string;
|
|
75
|
+
archive: string;
|
|
76
|
+
cancel: string;
|
|
77
|
+
confirm: string;
|
|
78
|
+
retry: string;
|
|
79
|
+
folderError: string;
|
|
80
|
+
workspaceName: string;
|
|
81
|
+
sessionName: string;
|
|
82
|
+
count: string;
|
|
83
|
+
now: string;
|
|
84
|
+
minutes: string;
|
|
85
|
+
hours: string;
|
|
86
|
+
days: string;
|
|
87
|
+
months: string;
|
|
88
|
+
years: string;
|
|
89
|
+
running: string;
|
|
90
|
+
waiting: string;
|
|
91
|
+
completed: string;
|
|
92
|
+
collapse: string;
|
|
93
|
+
expand: string;
|
|
94
|
+
today: string;
|
|
95
|
+
yesterday: string;
|
|
96
|
+
date: string;
|
|
97
|
+
dateYear: string;
|
|
98
|
+
};
|
|
99
|
+
export declare const NS = "ya-workspace-sidebar";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Pure sidebar projections shared by the browser and unit tests. */
|
|
2
|
+
import type { SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
|
|
3
|
+
/** Navigation key for sessions not accounted to a real workspace. */
|
|
4
|
+
export declare const UNGROUPED: "__ya_ungrouped__";
|
|
5
|
+
/** One sidebar session row. */
|
|
6
|
+
export interface SessionRow {
|
|
7
|
+
id: SessionId;
|
|
8
|
+
title: string;
|
|
9
|
+
/** Whether the session has a durable log-backed title (summary.title !== undefined). */
|
|
10
|
+
hasTitle: boolean;
|
|
11
|
+
blank: boolean;
|
|
12
|
+
running: boolean;
|
|
13
|
+
pendingInteraction?: SessionSummary['pendingInteraction'];
|
|
14
|
+
completed: boolean;
|
|
15
|
+
updatedAt: number;
|
|
16
|
+
workspaceKey: WorkspaceId | typeof UNGROUPED;
|
|
17
|
+
workspaceTitle: string;
|
|
18
|
+
}
|
|
19
|
+
/** One date-bucketed group of session rows for the real-workspace level. */
|
|
20
|
+
export interface SessionDateGroup {
|
|
21
|
+
/** Local calendar date `YYYY-MM-DD`, stable key. */
|
|
22
|
+
dateKey: string;
|
|
23
|
+
/** Days between today's local date and this group's local date (0=today, 1=yesterday, …). */
|
|
24
|
+
dayOffset: number;
|
|
25
|
+
rows: SessionRow[];
|
|
26
|
+
}
|
|
27
|
+
/** One first-level workspace row. */
|
|
28
|
+
export interface WorkspaceRow {
|
|
29
|
+
key: WorkspaceId | typeof UNGROUPED;
|
|
30
|
+
title: string;
|
|
31
|
+
path?: string;
|
|
32
|
+
createdAt?: string;
|
|
33
|
+
count: number;
|
|
34
|
+
real: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** Resolve the first/second-level destination for one session. */
|
|
37
|
+
export declare function workspaceKeyForSession(sessionId: SessionId | undefined, workspaces: readonly WorkspaceView[]): WorkspaceId | typeof UNGROUPED | null;
|
|
38
|
+
/** Derive global recent sessions, newest first. */
|
|
39
|
+
export declare function deriveRecent(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], limit?: number): SessionRow[];
|
|
40
|
+
/** Derive first-level real workspaces plus the virtual Ungrouped row. */
|
|
41
|
+
export declare function deriveWorkspaces(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): WorkspaceRow[];
|
|
42
|
+
/** Derive the selected workspace's sessions in its canonical order. */
|
|
43
|
+
export declare function deriveWorkspaceSessions(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): SessionRow[];
|
|
44
|
+
/**
|
|
45
|
+
* Derive the selected real workspace's sessions grouped by local calendar date.
|
|
46
|
+
*
|
|
47
|
+
* - Only real workspaces: `Ungrouped` falls back to {@link deriveWorkspaceSessions}.
|
|
48
|
+
* - Groups are ordered by date descending; rows within a group by `updatedAt` descending.
|
|
49
|
+
* - {@link visible} filter is reused (archived / subagent / blank visibility).
|
|
50
|
+
* - Future timestamps clamp to today's bucket (`dayOffset` 0).
|
|
51
|
+
* - `now` is the reference timestamp for "today"; pass `Date.now()` in production.
|
|
52
|
+
*/
|
|
53
|
+
export declare function deriveWorkspaceSessionGroups(key: WorkspaceId | typeof UNGROUPED, list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[], now: number): SessionDateGroup[];
|
|
54
|
+
/** Case-insensitive local title/workspace matching used beside Host content search. */
|
|
55
|
+
export declare function localMatches(rows: readonly SessionRow[], query: string): SessionRow[];
|
|
@@ -0,0 +1,4 @@
|
|
|
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-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@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
|
+
/** Install the stylesheet and return its disposer. */
|
|
4
|
+
export declare function installStyles(): () => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Package invariant companion for ya-workspace-sidebar. */
|
|
2
|
+
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants';
|
|
3
|
+
export declare const name = "ya-workspace-sidebar-invariant";
|
|
4
|
+
export declare const inject: string[];
|
|
5
|
+
interface InvariantContext {
|
|
6
|
+
invariants: {
|
|
7
|
+
register: (name: string, installer: InvariantInstaller) => () => void;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Register package ownership with the invariant service. */
|
|
11
|
+
export declare const apply: (ctx: InvariantContext) => Promise<() => void>;
|
|
12
|
+
export {};
|
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.2.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
|
+
}
|