@huanlin/dsh-plugin-ya-workspace-sidebar 0.1.1 → 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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ![cover](assets/cover.webp)
10
10
 
11
- DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session 二级菜单和面包屑导航;搜索、添加工作区、重命名、删除、Fork、归档与拖拽排序继续使用 DSH 原生 Host 能力。
11
+ DSH Web 工作区侧栏替代插件。顶部固定展示 5 条全局最近会话,下方使用 Workspace → Session 二级菜单和面包屑导航;选中工作区的会话按本地日历日期分组(今天/昨天/更早),搜索、添加工作区、重命名、删除、Fork 与归档继续使用 DSH 原生 Host 能力。
12
12
 
13
13
  ## 运行
14
14
 
package/lib/client.js CHANGED
@@ -51,7 +51,11 @@ window.__ModuleLoader__.load({
51
51
  waiting: "等待交互",
52
52
  completed: "已完成",
53
53
  collapse: "折叠",
54
- expand: "展开"
54
+ expand: "展开",
55
+ today: "今天",
56
+ yesterday: "昨天",
57
+ date: "{m}月{d}日",
58
+ dateYear: "{y}年{m}月{d}日"
55
59
  };
56
60
  const en = {
57
61
  workspaces: "Workspaces",
@@ -95,7 +99,11 @@ window.__ModuleLoader__.load({
95
99
  waiting: "Waiting for interaction",
96
100
  completed: "Completed",
97
101
  collapse: "Collapse",
98
- expand: "Expand"
102
+ expand: "Expand",
103
+ today: "Today",
104
+ yesterday: "Yesterday",
105
+ date: "{m}/{d}",
106
+ dateYear: "{m}/{d}/{y}"
99
107
  };
100
108
  const NS = "ya-workspace-sidebar";
101
109
  //#endregion
@@ -123,6 +131,7 @@ body[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish
123
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; }
124
132
  .ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }
125
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; }
126
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; }
127
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; }
128
137
  button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }
@@ -145,8 +154,6 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
145
154
  .ya-warning { color:var(--dsw-alias-status-warning); }
146
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; }
147
156
  .ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }
148
- .ya-drop-before::before, .ya-drop-after::after { content:''; position:absolute; left:8px; right:8px; height:2px; border-radius:2px; background:var(--dsw-alias-label-link); }
149
- .ya-drop-before::before { top:-2px; } .ya-drop-after::after { bottom:-2px; }
150
157
  .ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }
151
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; }
152
159
  .ya-rail .ya-search { justify-content:center; }
@@ -380,6 +387,70 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
380
387
  if (workspace === void 0) return [];
381
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));
382
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
+ }
383
454
  /** Case-insensitive local title/workspace matching used beside Host content search. */
384
455
  function localMatches(rows, query) {
385
456
  const normalized = query.trim().toLocaleLowerCase();
@@ -404,43 +475,40 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
404
475
  if (diff < 525600 * minute) return t("months", { n: Math.floor(diff / (43200 * minute)) });
405
476
  return t("years", { n: Math.floor(diff / (525600 * minute)) });
406
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
+ }
407
496
  function SessionStatus({ row }) {
408
497
  if (row.pendingInteraction !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
409
498
  if (row.running) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "ongoing" });
410
499
  if (row.completed) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "done" });
411
500
  return null;
412
501
  }
413
- function rowHalf(event) {
414
- const rect = event.currentTarget.getBoundingClientRect();
415
- return event.clientY < rect.top + rect.height / 2 ? "before" : "after";
416
- }
417
- function SessionItem({ row, current, now, open, rename, fork, archive, t, context, drag }) {
502
+ function SessionItem({ row, current, now, open, rename, fork, archive, t, context }) {
418
503
  const [menuOpen, setMenuOpen] = (0, react.useState)(false);
419
504
  const title = row.blank ? t("newSession") : row.hasTitle ? row.title : t("untitled");
420
505
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
421
- className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}${drag?.marker === "before" ? " ya-drop-before" : ""}${drag?.marker === "after" ? " ya-drop-after" : ""}`,
506
+ className: `ya-row${row.id === current ? " ya-selected" : ""}${menuOpen ? " ya-menu-open" : ""}`,
422
507
  role: "treeitem",
423
508
  "aria-selected": row.id === current,
424
- draggable: drag !== void 0,
425
509
  onClick: () => {
426
510
  open(row.id);
427
511
  },
428
- onDragStart: drag === void 0 ? void 0 : (event) => {
429
- event.dataTransfer.effectAllowed = "move";
430
- drag.start();
431
- },
432
- onDragEnd: drag?.end,
433
- onDragOver: drag === void 0 ? void 0 : (event) => {
434
- if (!drag.active) return;
435
- event.preventDefault();
436
- event.dataTransfer.dropEffect = "move";
437
- drag.hover(rowHalf(event));
438
- },
439
- onDrop: drag === void 0 ? void 0 : (event) => {
440
- if (!drag.active) return;
441
- event.preventDefault();
442
- drag.drop(rowHalf(event));
443
- },
444
512
  children: [
445
513
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
446
514
  className: "ya-status-slot",
@@ -586,7 +654,7 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
586
654
  }
587
655
  /** Fill `sidebar.workspaces` with the replacement browser. */
588
656
  function WorkspaceSidebar(props) {
589
- const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, insertSessionBefore, createWorkspace, useDirectoryFlow, renderSlot, t } = props;
657
+ const { wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions, searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace, archiveSession, createWorkspace, useDirectoryFlow, renderSlot, t } = props;
590
658
  const sessions = useSessions((state) => state);
591
659
  const workspaceState = useWorkspaces((state) => state);
592
660
  const workspaces = workspaceState.items;
@@ -624,8 +692,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
624
692
  if (selectedKey !== null && selectedKey !== "__ya_ungrouped__" && !workspaces.some((workspace) => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED);
625
693
  }, [selectedKey, workspaces]);
626
694
  const selectedWorkspace = selectedKey === null || selectedKey === "__ya_ungrouped__" ? void 0 : workspaces.find((workspace) => workspace.workspaceId === selectedKey);
627
- const levelRows = selectedKey === null ? [] : deriveWorkspaceSessions(selectedKey, sessions, workspaces, archived);
628
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);
629
705
  const [query, setQuery] = (0, react.useState)("");
630
706
  const normalizedQuery = sanitized(query).trim();
631
707
  const [remote, setRemote] = (0, react.useState)({
@@ -696,7 +772,6 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
696
772
  const [renameError, setRenameError] = (0, react.useState)(null);
697
773
  const [busy, setBusy] = (0, react.useState)(false);
698
774
  const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
699
- const [drag, setDrag] = (0, react.useState)(null);
700
775
  const beginWorkspaceRename = (row) => {
701
776
  setWorkspaceRename(row);
702
777
  setRenameDraft(row.title);
@@ -746,54 +821,17 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
746
821
  const fork = (id) => {
747
822
  forkSession(id);
748
823
  };
749
- const sessionItem = (row, context = false, index) => {
750
- const draggable = selectedKey !== null && selectedKey !== "__ya_ungrouped__" && index !== void 0;
751
- const marker = drag?.over?.id === row.id ? drag.over.half : null;
752
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionItem, {
753
- row,
754
- current: sessions.current,
755
- now,
756
- open,
757
- rename: beginSessionRename,
758
- fork,
759
- archive,
760
- t,
761
- context,
762
- ...draggable && selectedKey !== null && selectedKey !== "__ya_ungrouped__" ? { drag: {
763
- active: drag !== null,
764
- marker,
765
- start: () => {
766
- setDrag({
767
- id: row.id,
768
- over: null
769
- });
770
- },
771
- hover: (half) => {
772
- setDrag((value) => value === null ? value : {
773
- ...value,
774
- over: {
775
- id: row.id,
776
- half
777
- }
778
- });
779
- },
780
- drop: (half) => {
781
- if (drag === null) return;
782
- const anchor = half === "before" ? row.id : levelRows[(index ?? 0) + 1]?.id;
783
- const sourceIndex = levelRows.findIndex((item) => item.id === drag.id);
784
- const anchorIndex = anchor === void 0 ? levelRows.length : levelRows.findIndex((item) => item.id === anchor);
785
- setDrag(null);
786
- if (anchor === drag.id || sourceIndex === anchorIndex || sourceIndex + 1 === anchorIndex) return;
787
- insertSessionBefore(selectedKey, drag.id, anchor).catch((reason) => {
788
- console.warn("session reorder rejected:", reason);
789
- });
790
- },
791
- end: () => {
792
- setDrag(null);
793
- }
794
- } } : {}
795
- }, row.id);
796
- };
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);
797
835
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
798
836
  "data-ya-workspace-sidebar": true,
799
837
  className: wide ? "" : "ya-rail",
@@ -970,12 +1008,16 @@ button.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:
970
1008
  setRenameError(null);
971
1009
  },
972
1010
  t
973
- }, row.key)) : levelRows.map((row, index) => sessionItem(row, false, index)),
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))]),
974
1016
  selectedKey === null && workspaceRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
975
1017
  className: "ya-empty",
976
1018
  children: t("noWorkspaces")
977
1019
  }),
978
- selectedKey !== null && levelRows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1020
+ selectedKey !== null && levelEmpty && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
979
1021
  className: "ya-empty",
980
1022
  children: t("noSessions")
981
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 untitled: '未命名会话',\n addWorkspace: '添加工作区',\n addWorkspaceMenu: '添加工作区…',\n search: '搜索会话',\n searchPlaceholder: '搜索名称、关键词…',\n clearSearch: '清除搜索',\n searching: '正在搜索会话历史…',\n searchUnavailable: '内容搜索暂不可用,仅显示名称匹配。',\n noMatches: '无匹配会话',\n noSessions: '暂无会话',\n noWorkspaces: '暂无工作区',\n loading: '正在加载工作区…',\n rename: '重命名',\n renameWorkspace: '重命名工作区',\n renameSession: '重命名会话',\n deleteWorkspace: '删除工作区',\n deleteDescription: '将把“{name}”从工作区列表中移除。文件夹与会话记录会保留。',\n fork: '分叉会话',\n archive: '归档会话',\n cancel: '取消',\n confirm: '确认',\n retry: '重新选择',\n folderError: '无法打开文件夹',\n workspaceName: '工作区名称',\n sessionName: '会话名称',\n count: '{n} 个会话',\n now: '刚刚',\n minutes: '{n}分钟',\n hours: '{n}小时',\n days: '{n}天',\n months: '{n}个月',\n years: '{n}年',\n running: '进行中',\n waiting: '等待交互',\n completed: '已完成',\n collapse: '折叠',\n expand: '展开',\n} satisfies Record<string, string>\n\nexport type YaWorkspaceKey = keyof typeof zh\n\nexport const en = {\n workspaces: 'Workspaces',\n sessions: 'Sessions',\n recent: 'Recent Sessions',\n ungrouped: 'Ungrouped',\n newSession: 'New Session',\n untitled: 'Untitled session',\n addWorkspace: 'Add workspace',\n addWorkspaceMenu: 'Add workspace…',\n search: 'Search sessions',\n searchPlaceholder: 'Search name, keywords...',\n clearSearch: 'Clear search',\n searching: 'Searching session history…',\n searchUnavailable: 'Content search is unavailable. Showing name matches.',\n noMatches: 'No matching sessions',\n noSessions: 'No sessions yet',\n noWorkspaces: 'No workspaces yet',\n loading: 'Loading workspaces…',\n rename: 'Rename',\n renameWorkspace: 'Rename workspace',\n renameSession: 'Rename session',\n deleteWorkspace: 'Delete workspace',\n deleteDescription: 'This removes “{name}” from the workspace list. The folder and session logs remain.',\n fork: 'Fork session',\n archive: 'Archive session',\n cancel: 'Cancel',\n confirm: 'Confirm',\n retry: 'Choose again',\n folderError: 'Couldn’t open folder',\n workspaceName: 'Workspace name',\n sessionName: 'Session name',\n count: '{n} sessions',\n now: 'now',\n minutes: '{n}min',\n hours: '{n}h',\n days: '{n}d',\n months: '{n}mo',\n years: '{n}y',\n running: 'Running',\n waiting: 'Waiting for interaction',\n completed: 'Completed',\n collapse: 'Collapse',\n expand: 'Expand',\n} satisfies Record<YaWorkspaceKey, string>\n\nexport const NS = 'ya-workspace-sidebar'\n","/** One scoped stylesheet injected for the lifetime of the client activation. */\nexport const CSS = `\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-drop-before::before, .ya-drop-after::after { content:''; position:absolute; left:8px; right:8px; height:2px; border-radius:2px; background:var(--dsw-alias-label-link); }\n.ya-drop-before::before { top:-2px; } .ya-drop-after::after { bottom:-2px; }\n.ya-rail .ya-section-header { padding-left:0; margin-bottom:12px; }\n.ya-rail .ya-icon-button, .ya-rail .ya-search { width:36px; height:36px; padding:0; margin:0 0 12px; border-color:transparent; background:transparent; }\n.ya-rail .ya-search { justify-content:center; }\n.ya-rail .ya-search-icon { cursor:pointer; color:var(--dsw-alias-label-primary); }\n.ya-picker-error { color:var(--dsw-alias-status-error); white-space:pre-wrap; }\n@keyframes ya-slide-in-forward { from { opacity:0; transform:translateX(10px); } to { opacity:1; transform:translateX(0); } }\n@keyframes ya-slide-in-backward { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:translateX(0); } }\n.ya-level-enter-forward { animation:ya-slide-in-forward 180ms ease-out; }\n.ya-level-enter-backward { animation:ya-slide-in-backward 180ms ease-out; }\n`\n\n/** Install the stylesheet and return its disposer. */\nexport function installStyles(): () => void {\n const style = document.createElement('style')\n style.setAttribute('data-ya-workspace-sidebar-style', '')\n style.textContent = CSS\n document.head.appendChild(style)\n return () => { style.remove() }\n}\n","/** Existing-workspace menu plus composed directory-adoption flow. */\nimport type { ReactNode, RefObject } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport {\n Button, IconFolderClose16, IconPlusOutline16, Menu, Modal, type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n WorkspaceId, WorkspaceListState, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { DirectoryFlowOwnerProps, PickerProps } from './contract.ts'\n\nconst ADD = '::ya-add-workspace'\n\ninterface FlowProps {\n t: PickerProps['t']\n open: boolean\n anchorRef?: RefObject<HTMLElement | null>\n useWorkspaces: <S>(selector: (state: WorkspaceListState) => S) => S\n createWorkspace: (input: { path: string }) => Promise<WorkspaceView>\n useDirectoryFlow: SnapshotSelectorHook<boolean>\n renderDirectoryFlow: (owner: DirectoryFlowOwnerProps) => ReactNode\n onPick: (workspaceId: WorkspaceId) => void\n onClose: () => void\n addOnly?: boolean\n side?: 'bottom' | 'top' | 'right'\n selectedId?: WorkspaceId\n}\n\n/** Render the workspace target menu and directory picking conversation. */\nexport function WorkspacePickFlow({\n t, open, anchorRef, useWorkspaces, createWorkspace, useDirectoryFlow,\n renderDirectoryFlow, onPick, onClose, addOnly = false, side = 'bottom', selectedId,\n}: FlowProps) {\n const snapshot = useWorkspaces(state => state)\n const flowAvailable = useDirectoryFlow(value => value)\n const [flowOpen, setFlowOpen] = useState(false)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const getAnchorRect = useCallback(\n () => anchorRef?.current?.getBoundingClientRect() ?? null,\n [anchorRef],\n )\n useEffect(() => {\n if (flowOpen && !flowAvailable) setFlowOpen(false)\n }, [flowAvailable, flowOpen])\n\n const openFlow = useCallback(() => {\n onClose()\n setError(null)\n setFlowOpen(true)\n }, [onClose])\n const addEntries: MenuEntry[] = flowAvailable\n ? [{ id: ADD, label: t('addWorkspaceMenu'), icon: <IconPlusOutline16 size={16} />, disabled: flowOpen || busy }]\n : []\n const pinnedAdd = !addOnly && snapshot.items.length > 0\n const items: MenuEntry[] = pinnedAdd\n ? snapshot.items.map(workspace => ({\n id: workspace.workspaceId,\n label: workspace.title,\n icon: <IconFolderClose16 size={16} />,\n disabled: flowOpen || busy,\n }))\n : addEntries\n const settled = addOnly || snapshot.phase === 'ready'\n const onlyAdd = !pinnedAdd && settled && addEntries.length === 1\n useEffect(() => {\n if (open && onlyAdd && !flowOpen && !busy) openFlow()\n }, [busy, flowOpen, onlyAdd, open, openFlow])\n\n const owner: DirectoryFlowOwnerProps = {\n open: flowOpen,\n busy,\n onPicked: (path) => {\n setBusy(true)\n createWorkspace({ path }).then(workspace => {\n setFlowOpen(false)\n onPick(workspace.workspaceId)\n }).catch((reason: unknown) => {\n setFlowOpen(false)\n setError(reason instanceof Error ? reason.message : String(reason))\n }).finally(() => { setBusy(false) })\n },\n onCancel: () => { setFlowOpen(false) },\n onError: (message) => { setFlowOpen(false); setError(message) },\n }\n\n return (\n <>\n <Menu\n open={open && !onlyAdd && items.length > 0}\n anchor={null}\n items={items}\n {...pinnedAdd ? { footer: addEntries } : {}}\n selectedId={selectedId}\n onSelect={(id) => { if (id === ADD) openFlow(); else onPick(id as WorkspaceId) }}\n onClose={onClose}\n side={side}\n portal\n getAnchorRect={getAnchorRect}\n />\n {open && !onlyAdd && snapshot.phase === 'pending' && <div className=\"ya-status\">{t('loading')}</div>}\n {renderDirectoryFlow(owner)}\n <Modal\n open={error !== null}\n onClose={() => { setError(null) }}\n closeLabel={t('cancel')}\n title={t('folderError')}\n footer={(\n <>\n <Button variant=\"outline\" onClick={() => { setError(null) }}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={!flowAvailable} onClick={openFlow}>{t('retry')}</Button>\n </>\n )}\n >\n <div className=\"ya-picker-error\" role=\"alert\">{error}</div>\n </Modal>\n </>\n )\n}\n\n/** Fill the conversation hero's workspace picker seat. */\nexport function WorkspacePicker({\n open, anchorRef, useWorkspaces, selectedId, onPick, onClose,\n createWorkspace, useDirectoryFlow, renderSlot, t,\n}: PickerProps) {\n return (\n <WorkspacePickFlow\n t={t}\n open={open}\n anchorRef={anchorRef}\n useWorkspaces={useWorkspaces}\n selectedId={selectedId}\n onPick={onPick}\n onClose={onClose}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('conversation.hero.workspace.directoryFlow', owner)}\n />\n )\n}\n","/** Pure sidebar projections shared by the browser and unit tests. */\nimport type {\n SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView,\n} from '@deepseek-ai/dsh-client-runtime/client'\n\n/** Navigation key for sessions not accounted to a real workspace. */\nexport const UNGROUPED = '__ya_ungrouped__' as const\n\n/** One sidebar session row. */\nexport interface SessionRow {\n id: SessionId\n title: string\n /** Whether the session has a durable log-backed title (summary.title !== undefined). */\n hasTitle: boolean\n blank: boolean\n running: boolean\n pendingInteraction?: SessionSummary['pendingInteraction']\n completed: boolean\n updatedAt: number\n workspaceKey: WorkspaceId | typeof UNGROUPED\n workspaceTitle: string\n}\n\n/** One first-level workspace row. */\nexport interface WorkspaceRow {\n key: WorkspaceId | typeof UNGROUPED\n title: string\n path?: string\n createdAt?: string\n count: number\n real: boolean\n}\n\nfunction visible(summary: SessionSummary, current: SessionId | undefined, archived: ReadonlySet<SessionId>): boolean {\n return summary.origin !== 'subagent'\n && !archived.has(summary.id)\n && (!summary.blank || summary.id === current)\n}\n\nfunction rowOf(\n summary: SessionSummary,\n workspaceKey: WorkspaceId | typeof UNGROUPED,\n workspaceTitle: string,\n): SessionRow {\n return {\n id: summary.id,\n title: summary.blank ? 'New Session' : summary.displayTitle,\n hasTitle: summary.title !== undefined,\n blank: summary.blank,\n running: summary.running,\n ...(summary.pendingInteraction === undefined ? {} : { pendingInteraction: summary.pendingInteraction }),\n completed: summary.completed === true,\n updatedAt: summary.updatedAt,\n workspaceKey,\n workspaceTitle,\n }\n}\n\nfunction ownerIndex(workspaces: readonly WorkspaceView[]): Map<SessionId, WorkspaceView> {\n const result = new Map<SessionId, WorkspaceView>()\n for (const workspace of workspaces) {\n for (const sessionId of workspace.sessionIds) result.set(sessionId, workspace)\n }\n return result\n}\n\n/** Resolve the first/second-level destination for one session. */\nexport function workspaceKeyForSession(\n sessionId: SessionId | undefined,\n workspaces: readonly WorkspaceView[],\n): WorkspaceId | typeof UNGROUPED | null {\n if (sessionId === undefined) return null\n return ownerIndex(workspaces).get(sessionId)?.workspaceId ?? UNGROUPED\n}\n\n/** Derive global recent sessions, newest first. */\nexport function deriveRecent(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n limit = 5,\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n const owners = ownerIndex(workspaces)\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .slice(0, limit)\n .map((summary) => {\n const workspace = owners.get(summary.id)\n return rowOf(summary, workspace?.workspaceId ?? UNGROUPED, workspace?.title ?? 'Ungrouped')\n })\n}\n\n/** Derive first-level real workspaces plus the virtual Ungrouped row. */\nexport function deriveWorkspaces(\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): WorkspaceRow[] {\n const archived = new Set(archivedSessionIds)\n const accounted = new Set<SessionId>()\n const result = workspaces.map((workspace): WorkspaceRow => {\n let count = 0\n for (const id of workspace.sessionIds) {\n accounted.add(id)\n const summary = list.byId[id]\n if (summary !== undefined && visible(summary, list.current, archived)) count++\n }\n return {\n key: workspace.workspaceId,\n title: workspace.title,\n path: workspace.path,\n createdAt: workspace.createdAt,\n count,\n real: true,\n }\n })\n let ungrouped = 0\n for (const id of list.ids) {\n const summary = list.byId[id]\n if (summary !== undefined && !accounted.has(id) && visible(summary, list.current, archived)) ungrouped++\n }\n result.push({ key: UNGROUPED, title: 'Ungrouped', count: ungrouped, real: false })\n return result\n}\n\n/** Derive the selected workspace's sessions in its canonical order. */\nexport function deriveWorkspaceSessions(\n key: WorkspaceId | typeof UNGROUPED,\n list: SessionListState,\n workspaces: readonly WorkspaceView[],\n archivedSessionIds: readonly SessionId[],\n): SessionRow[] {\n const archived = new Set(archivedSessionIds)\n if (key === UNGROUPED) {\n const accounted = new Set(workspaces.flatMap(workspace => workspace.sessionIds))\n return list.ids\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined\n && !accounted.has(summary.id)\n && visible(summary, list.current, archived))\n .sort((a, b) => b.updatedAt - a.updatedAt || String(a.id).localeCompare(String(b.id)))\n .map(summary => rowOf(summary, UNGROUPED, 'Ungrouped'))\n }\n const workspace = workspaces.find(item => item.workspaceId === key)\n if (workspace === undefined) return []\n return workspace.sessionIds\n .map(id => list.byId[id])\n .filter((summary): summary is SessionSummary => summary !== undefined && visible(summary, list.current, archived))\n .map(summary => rowOf(summary, workspace.workspaceId, workspace.title))\n}\n\n/** Case-insensitive local title/workspace matching used beside Host content search. */\nexport function localMatches(rows: readonly SessionRow[], query: string): SessionRow[] {\n const normalized = query.trim().toLocaleLowerCase()\n if (normalized === '') return []\n return rows.filter(row => `${row.title}\\n${row.workspaceTitle}`.toLocaleLowerCase().includes(normalized))\n}\n","/** Two-level workspace/session browser with a persistent global recent block. */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n Button, IconArchiveOutline20, IconBranchOutline16, IconChevronRightOutline14,\n IconCloseFill14, IconEditOutline16, IconEllipsisOutline16, IconFolderClose16,\n IconPlusOutline16, IconProjectAddOutline16, IconSearchOutline16, IconTrashOutline16,\n Menu, Modal, StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { SessionId, WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SidebarProps } from './contract.ts'\nimport {\n deriveRecent, deriveWorkspaceSessions, deriveWorkspaces, localMatches,\n UNGROUPED, workspaceKeyForSession, type SessionRow, type WorkspaceRow,\n} from './model.ts'\nimport { WorkspacePickFlow } from './WorkspacePicker.tsx'\n\nconst SEARCH_DEBOUNCE_MS = 250\nconst SEARCH_MAX = 500\n\nfunction sanitized(value: string): string {\n return value.replaceAll('\\0', '').slice(0, SEARCH_MAX)\n}\n\nfunction relativeTime(updatedAt: number, now: number, t: SidebarProps['t']): string {\n const diff = Math.max(0, now - updatedAt)\n const minute = 60_000\n if (diff < minute) return t('now')\n if (diff < 60 * minute) return t('minutes', { n: Math.floor(diff / minute) })\n if (diff < 24 * 60 * minute) return t('hours', { n: Math.floor(diff / (60 * minute)) })\n if (diff < 30 * 24 * 60 * minute) return t('days', { n: Math.floor(diff / (24 * 60 * minute)) })\n if (diff < 365 * 24 * 60 * minute) return t('months', { n: Math.floor(diff / (30 * 24 * 60 * minute)) })\n return t('years', { n: Math.floor(diff / (365 * 24 * 60 * minute)) })\n}\n\nfunction SessionStatus({ row }: { row: SessionRow }) {\n if (row.pendingInteraction !== undefined) return <StateDot state=\"warning\" />\n if (row.running) return <StateDot state=\"ongoing\" />\n if (row.completed) return <StateDot state=\"done\" />\n return null\n}\n\ninterface SessionRowProps {\n row: SessionRow\n current: SessionId | undefined\n now: number\n open: (id: SessionId) => void\n rename: (row: SessionRow) => void\n fork: (id: SessionId) => void\n archive: (id: SessionId) => void\n t: SidebarProps['t']\n context?: boolean\n drag?: {\n active: boolean\n marker: 'before' | 'after' | null\n start: () => void\n hover: (half: 'before' | 'after') => void\n drop: (half: 'before' | 'after') => void\n end: () => void\n }\n}\n\nfunction rowHalf(event: { clientY: number; currentTarget: HTMLElement }): 'before' | 'after' {\n const rect = event.currentTarget.getBoundingClientRect()\n return event.clientY < rect.top + rect.height / 2 ? 'before' : 'after'\n}\n\nfunction SessionItem({ row, current, now, open, rename, fork, archive, t, context, drag }: SessionRowProps) {\n const [menuOpen, setMenuOpen] = useState(false)\n const title = row.blank ? t('newSession') : row.hasTitle ? row.title : t('untitled')\n return (\n <div\n className={`ya-row${row.id === current ? ' ya-selected' : ''}${menuOpen ? ' ya-menu-open' : ''}${drag?.marker === 'before' ? ' ya-drop-before' : ''}${drag?.marker === 'after' ? ' ya-drop-after' : ''}`}\n role=\"treeitem\"\n aria-selected={row.id === current}\n draggable={drag !== undefined}\n onClick={() => { open(row.id) }}\n onDragStart={drag === undefined ? undefined : (event) => { event.dataTransfer.effectAllowed = 'move'; drag.start() }}\n onDragEnd={drag?.end}\n onDragOver={drag === undefined ? undefined : (event) => {\n if (!drag.active) return\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n drag.hover(rowHalf(event))\n }}\n onDrop={drag === undefined ? undefined : (event) => {\n if (!drag.active) return\n event.preventDefault()\n drag.drop(rowHalf(event))\n }}\n >\n <span className=\"ya-status-slot\"><SessionStatus row={row} /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{title}</span>\n {!row.blank && <span className=\"ya-row-meta ya-row-time\">{relativeTime(row.updatedAt, now, t)}</span>}\n </span>\n {context === true && <span className=\"ya-search-workspace\">{row.workspaceTitle}</span>}\n </span>\n {!row.blank && (\n <span className=\"ya-row-actions\">\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'fork', label: t('fork'), icon: <IconBranchOutline16 /> },\n { id: 'archive', label: t('archive'), icon: <IconArchiveOutline20 size={16} /> },\n ]}\n onSelect={(id) => {\n setMenuOpen(false)\n if (id === 'rename') rename(row)\n if (id === 'fork') fork(row.id)\n if (id === 'archive') archive(row.id)\n }}\n portal\n closeOnPointerLeave\n anchor={(\n <button\n type=\"button\"\n className=\"ya-icon-button\"\n aria-label={`${title} actions`}\n onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}\n >\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n </span>\n )}\n </div>\n )\n}\n\nfunction WorkspaceItem({ row, enter, create, rename, remove, t }: {\n row: WorkspaceRow\n enter: () => void\n create: () => void\n rename: () => void\n remove: () => void\n t: SidebarProps['t']\n}) {\n const [menuOpen, setMenuOpen] = useState(false)\n return (\n <div className={`ya-row ya-workspace-row${menuOpen ? ' ya-menu-open' : ''}`} role=\"treeitem\" onClick={enter} title={row.path}>\n <span className=\"ya-status-slot\"><IconFolderClose16 /></span>\n <span className=\"ya-row-main\">\n <span className=\"ya-row-line\">\n <span className=\"ya-row-title\">{row.real ? row.title : t('ungrouped')}</span>\n <span className=\"ya-row-meta\">{t('count', { n: row.count })}</span>\n </span>\n {row.path !== undefined && <span className=\"ya-workspace-path\">{row.path}</span>}\n </span>\n <span className=\"ya-row-actions\">\n {row.real && (\n <Menu\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={[\n { id: 'rename', label: t('rename'), icon: <IconEditOutline16 /> },\n { id: 'delete', label: t('deleteWorkspace'), icon: <IconTrashOutline16 />, danger: true },\n ]}\n onSelect={(id) => { setMenuOpen(false); if (id === 'rename') rename(); if (id === 'delete') remove() }}\n portal\n closeOnPointerLeave\n anchor={(\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); setMenuOpen(value => !value) }}>\n <IconEllipsisOutline16 />\n </button>\n )}\n />\n )}\n {row.real && (\n <button type=\"button\" className=\"ya-icon-button\" onClick={(event) => { event.stopPropagation(); create() }}>\n <IconPlusOutline16 />\n </button>\n )}\n </span>\n <IconChevronRightOutline14 />\n </div>\n )\n}\n\ninterface RemoteState {\n query: string\n status: 'idle' | 'loading' | 'ready' | 'error'\n items: readonly { sessionId: SessionId; snippet: string }[]\n hasMore: boolean\n}\n\n/** Fill `sidebar.workspaces` with the replacement browser. */\nexport function WorkspaceSidebar(props: SidebarProps) {\n const {\n wide, expandSidebar, useSessions, useWorkspaces, startSession, open, searchSessions,\n searchResultLimit, renameSession, forkSession, renameWorkspace, deleteWorkspace,\n archiveSession, insertSessionBefore, createWorkspace, useDirectoryFlow, renderSlot, t,\n } = props\n const sessions = useSessions(state => state)\n const workspaceState = useWorkspaces(state => state)\n const workspaces = workspaceState.items\n const archived = workspaceState.archivedSessionIds\n const directoryFlowAvailable = useDirectoryFlow(value => value)\n const allRows = useMemo(\n () => deriveRecent(sessions, workspaces, archived, Number.MAX_SAFE_INTEGER),\n [archived, sessions, workspaces],\n )\n const recent = allRows.slice(0, 5)\n const workspaceRows = useMemo(\n () => deriveWorkspaces(sessions, workspaces, archived),\n [archived, sessions, workspaces],\n )\n const [selectedKey, setSelectedKey] = useState<WorkspaceId | typeof UNGROUPED | null>(null)\n const [direction, setDirection] = useState<'forward' | 'backward'>('forward')\n const [hasMounted, setHasMounted] = useState(false)\n useEffect(() => { setHasMounted(true) }, [])\n const observedCurrent = useRef<SessionId | undefined>(undefined)\n const initialized = useRef(false)\n useEffect(() => {\n if (initialized.current && observedCurrent.current === sessions.current) return\n initialized.current = true\n observedCurrent.current = sessions.current\n if (sessions.current !== undefined) { setDirection('forward'); setSelectedKey(workspaceKeyForSession(sessions.current, workspaces)) }\n }, [sessions.current, workspaces])\n useEffect(() => {\n if (selectedKey !== null && selectedKey !== UNGROUPED\n && !workspaces.some(workspace => workspace.workspaceId === selectedKey)) setSelectedKey(UNGROUPED)\n }, [selectedKey, workspaces])\n const selectedWorkspace = selectedKey === null || selectedKey === UNGROUPED\n ? undefined\n : workspaces.find(workspace => workspace.workspaceId === selectedKey)\n const levelRows = selectedKey === null\n ? []\n : deriveWorkspaceSessions(selectedKey, sessions, workspaces, archived)\n const now = Date.now()\n\n const [query, setQuery] = useState('')\n const normalizedQuery = sanitized(query).trim()\n const [remote, setRemote] = useState<RemoteState>({ query: '', status: 'idle', items: [], hasMore: false })\n useEffect(() => {\n if (normalizedQuery === '') {\n setRemote({ query: '', status: 'idle', items: [], hasMore: false })\n return\n }\n const controller = new AbortController()\n setRemote({ query: normalizedQuery, status: 'loading', items: [], hasMore: false })\n const timer = window.setTimeout(() => {\n searchSessions(normalizedQuery, controller.signal).then(result => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'ready', items: result.items, hasMore: result.hasMore })\n }).catch(() => {\n if (!controller.signal.aborted) setRemote({ query: normalizedQuery, status: 'error', items: [], hasMore: false })\n })\n }, SEARCH_DEBOUNCE_MS)\n return () => { window.clearTimeout(timer); controller.abort() }\n }, [normalizedQuery, searchSessions])\n const searchRows = useMemo(() => {\n if (normalizedQuery === '') return []\n const byId = new Map(localMatches(allRows, normalizedQuery).map(row => [row.id, row]))\n if (remote.query === normalizedQuery) {\n for (const item of remote.items) {\n const row = allRows.find(candidate => candidate.id === item.sessionId)\n if (row !== undefined) byId.set(row.id, row)\n }\n }\n return [...byId.values()].slice(0, searchResultLimit)\n }, [allRows, normalizedQuery, remote, searchResultLimit])\n\n const [pickerOpen, setPickerOpen] = useState(false)\n const pickerAnchor = useRef<HTMLButtonElement>(null)\n const [recentCollapsed, setRecentCollapsed] = useState(false)\n const [workspaceRename, setWorkspaceRename] = useState<WorkspaceRow | null>(null)\n const [sessionRename, setSessionRename] = useState<SessionRow | null>(null)\n const [renameDraft, setRenameDraft] = useState('')\n const [renameError, setRenameError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [deleteTarget, setDeleteTarget] = useState<WorkspaceRow | null>(null)\n const [drag, setDrag] = useState<{ id: SessionId; over: { id: SessionId; half: 'before' | 'after' } | null } | null>(null)\n\n const beginWorkspaceRename = (row: WorkspaceRow) => { setWorkspaceRename(row); setRenameDraft(row.title); setRenameError(null) }\n const beginSessionRename = (row: SessionRow) => { setSessionRename(row); setRenameDraft(row.title); setRenameError(null) }\n const closeRename = () => { if (!busy) { setWorkspaceRename(null); setSessionRename(null); setRenameError(null) } }\n const commitRename = () => {\n const title = renameDraft.trim()\n if (title === '' || busy) return\n setBusy(true)\n const task = workspaceRename !== null && workspaceRename.key !== UNGROUPED\n ? renameWorkspace(workspaceRename.key, title)\n : sessionRename !== null ? renameSession(sessionRename.id, title) : Promise.resolve()\n task.then(() => { setWorkspaceRename(null); setSessionRename(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const confirmDelete = () => {\n if (deleteTarget === null || deleteTarget.key === UNGROUPED || busy) return\n setBusy(true)\n deleteWorkspace(deleteTarget.key).then(() => { setDeleteTarget(null) })\n .catch((reason: unknown) => { setRenameError(reason instanceof Error ? reason.message : String(reason)) })\n .finally(() => { setBusy(false) })\n }\n const archive = (id: SessionId) => { archiveSession(id).catch(reason => { console.warn('session archive rejected:', reason) }) }\n const fork = (id: SessionId) => { forkSession(id) }\n\n const sessionItem = (row: SessionRow, context = false, index?: number) => {\n const draggable = selectedKey !== null && selectedKey !== UNGROUPED && index !== undefined\n const marker = drag?.over?.id === row.id ? drag.over.half : null\n return (\n <SessionItem\n key={row.id}\n row={row}\n current={sessions.current}\n now={now}\n open={open}\n rename={beginSessionRename}\n fork={fork}\n archive={archive}\n t={t}\n context={context}\n {...draggable && selectedKey !== null && selectedKey !== UNGROUPED ? {\n drag: {\n active: drag !== null,\n marker,\n start: () => { setDrag({ id: row.id, over: null }) },\n hover: (half: 'before' | 'after') => { setDrag(value => value === null ? value : { ...value, over: { id: row.id, half } }) },\n drop: (half: 'before' | 'after') => {\n if (drag === null) return\n const anchor = half === 'before' ? row.id : levelRows[(index ?? 0) + 1]?.id\n const sourceIndex = levelRows.findIndex(item => item.id === drag.id)\n const anchorIndex = anchor === undefined ? levelRows.length : levelRows.findIndex(item => item.id === anchor)\n setDrag(null)\n if (anchor === drag.id || sourceIndex === anchorIndex || sourceIndex + 1 === anchorIndex) return\n insertSessionBefore(selectedKey, drag.id, anchor).catch(reason => { console.warn('session reorder rejected:', reason) })\n },\n end: () => { setDrag(null) },\n },\n } : {}}\n />\n )\n }\n\n return (\n <div data-ya-workspace-sidebar className={wide ? '' : 'ya-rail'}>\n <div className=\"ya-section-header\">\n {wide && <span className=\"ya-section-title\">{t('workspaces')}</span>}\n {directoryFlowAvailable && (\n <button ref={pickerAnchor} type=\"button\" className=\"ya-icon-button\" aria-label={t('addWorkspace')} onClick={() => { setPickerOpen(value => !value) }}>\n <IconProjectAddOutline16 size={wide ? 16 : 18} />\n </button>\n )}\n <WorkspacePickFlow\n t={t}\n open={pickerOpen}\n anchorRef={pickerAnchor}\n useWorkspaces={useWorkspaces}\n createWorkspace={createWorkspace}\n useDirectoryFlow={useDirectoryFlow}\n renderDirectoryFlow={owner => renderSlot('sidebar.workspaces.directoryFlow', owner)}\n addOnly\n side=\"right\"\n onPick={(workspaceId) => { setPickerOpen(false); startSession(workspaceId) }}\n onClose={() => { setPickerOpen(false) }}\n />\n </div>\n\n <div className=\"ya-search\" onClick={() => { if (!wide) expandSidebar() }}>\n <button type=\"button\" className=\"ya-search-icon\" aria-label={t('search')}><IconSearchOutline16 size={wide ? 14 : 18} /></button>\n {wide && <input className=\"ya-search-input\" value={query} maxLength={SEARCH_MAX} placeholder={t('searchPlaceholder')} onChange={event => { setQuery(sanitized(event.target.value)) }} />}\n {wide && query !== '' && <button type=\"button\" className=\"ya-icon-button\" aria-label={t('clearSearch')} onClick={() => { setQuery('') }}><IconCloseFill14 /></button>}\n </div>\n\n {wide && (\n <div className=\"ya-body\">\n {normalizedQuery !== '' ? (\n <div className=\"ya-scroll\" role=\"tree\" aria-label={t('search')}>\n {searchRows.map(row => sessionItem(row, true))}\n {remote.status === 'loading' && <div className=\"ya-status\">{t('searching')}</div>}\n {remote.status === 'error' && <div className=\"ya-status ya-warning\">{t('searchUnavailable')}</div>}\n {remote.status !== 'loading' && searchRows.length === 0 && <div className=\"ya-empty\">{t('noMatches')}</div>}\n </div>\n ) : (\n <>\n <div className={`ya-recent${recentCollapsed ? ' ya-recent-collapsed' : ''}`}>\n <div className=\"ya-block-label\">\n <span>{t('recent')}</span>\n {recent.length > 0 && (\n <button\n type=\"button\"\n className={`ya-block-label-toggle${recentCollapsed ? ' ya-collapsed' : ''}`}\n aria-label={recentCollapsed ? t('expand') : t('collapse')}\n aria-expanded={!recentCollapsed}\n onClick={(event) => { event.stopPropagation(); setRecentCollapsed(value => !value) }}\n >\n <IconChevronRightOutline14 />\n </button>\n )}\n </div>\n <div className=\"ya-recent-list-wrap\">\n {recent.length === 0\n ? <div className=\"ya-empty\">{t('noSessions')}</div>\n : <div className=\"ya-recent-list\">{recent.map(row => sessionItem(row, true))}</div>\n }\n </div>\n </div>\n <div className=\"ya-breadcrumb\">\n {selectedKey === null ? (\n <span className=\"ya-crumb\">{t('workspaces')}</span>\n ) : (\n <>\n <button type=\"button\" className=\"ya-crumb\" onClick={() => { setDirection('backward'); setSelectedKey(null) }}>{t('workspaces')}</button>\n <IconChevronRightOutline14 />\n <span className=\"ya-crumb\">{selectedKey === UNGROUPED ? t('ungrouped') : selectedWorkspace?.title}</span>\n {selectedKey !== UNGROUPED && (\n <button type=\"button\" className=\"ya-icon-button\" aria-label={t('newSession')} onClick={() => { startSession(selectedKey) }}><IconPlusOutline16 /></button>\n )}\n </>\n )}\n </div>\n <div className=\"ya-scroll\" role=\"tree\" aria-label={selectedKey === null ? t('workspaces') : t('sessions')}>\n <div key={selectedKey ?? 'root'} className={hasMounted ? `ya-level-enter-${direction}` : undefined}>\n {selectedKey === null\n ? workspaceRows.map(row => (\n <WorkspaceItem\n key={row.key}\n row={row}\n enter={() => { setDirection('forward'); setSelectedKey(row.key) }}\n create={() => { if (row.key !== UNGROUPED) startSession(row.key) }}\n rename={() => { beginWorkspaceRename(row) }}\n remove={() => { setDeleteTarget(row); setRenameError(null) }}\n t={t}\n />\n ))\n : levelRows.map((row, index) => sessionItem(row, false, index))}\n {selectedKey === null && workspaceRows.length === 0 && <div className=\"ya-empty\">{t('noWorkspaces')}</div>}\n {selectedKey !== null && levelRows.length === 0 && <div className=\"ya-empty\">{t('noSessions')}</div>}\n </div>\n </div>\n </>\n )}\n </div>\n )}\n\n <Modal\n open={workspaceRename !== null || sessionRename !== null}\n onClose={closeRename}\n closeLabel={t('cancel')}\n title={workspaceRename !== null ? t('renameWorkspace') : t('renameSession')}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={closeRename}>{t('cancel')}</Button>\n <Button variant=\"primary\" disabled={busy || renameDraft.trim() === ''} onClick={commitRename}>{t('rename')}</Button>\n </>\n )}\n >\n <input className=\"ya-rename-input\" value={renameDraft} autoFocus disabled={busy} aria-label={workspaceRename !== null ? t('workspaceName') : t('sessionName')} onChange={event => { setRenameDraft(event.target.value); setRenameError(null) }} />\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n\n <Modal\n open={deleteTarget !== null}\n onClose={() => { if (!busy) setDeleteTarget(null) }}\n closeLabel={t('cancel')}\n title={t('deleteWorkspace')}\n description={deleteTarget === null ? undefined : t('deleteDescription', { name: deleteTarget.title })}\n footer={(\n <>\n <Button variant=\"outline\" disabled={busy} onClick={() => { setDeleteTarget(null) }}>{t('cancel')}</Button>\n <Button variant=\"outline\" disabled={busy} onClick={confirmDelete}>{t('deleteWorkspace')}</Button>\n </>\n )}\n >\n {renameError !== null && <div className=\"ya-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n </div>\n )\n}\n","/** Client assembly for the replacement workspace sidebar and hero picker. */\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { PickerInjected, SidebarInjected } from './contract.ts'\nimport { en, NS, zh } from './locales.ts'\nimport { installStyles } from './styles.ts'\nimport { WorkspacePicker } from './WorkspacePicker.tsx'\nimport { WorkspaceSidebar } from './WorkspaceSidebar.tsx'\n\n/** Services required by both replacement client entries. */\nexport const inject = ['slots', 'sessions', 'workspaces', 'locale']\n\n/** Register the sidebar browser and conversation hero picker. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ya-workspace-sidebar: dictionaries')\n ctx.effect(installStyles, 'ya-workspace-sidebar: styles')\n\n const flowSource = (\n name: 'sidebar.workspaces.directoryFlow' | 'conversation.hero.workspace.directoryFlow',\n ): HostObservable<boolean> => ({\n getSnapshot: () => ctx.slots.entries(name).length > 0,\n subscribe: listener => ctx.slots.subscribe(name, listener),\n })\n const sidebarFlow = flowSource('sidebar.workspaces.directoryFlow')\n const pickerFlow = flowSource('conversation.hero.workspace.directoryFlow')\n const createWorkspace = (input: { path: string }) => ctx.workspaces.create(input)\n\n const searchSessions: SidebarInjected['searchSessions'] = async (query, signal) => {\n const result = await ctx.sessions.search(query, signal)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n }\n const sidebarInjected = (): SidebarInjected => ({\n startSession: workspaceId => { ctx.workspaces.startSession(workspaceId) },\n open: sessionId => { ctx.sessions.open(sessionId) },\n searchSessions,\n searchResultLimit: ctx.sessions.searchResultLimit,\n renameSession: async (sessionId, title) => {\n const session = ctx.sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error(`unknown session \"${sessionId}\"`)\n const result = await session.rename(title)\n if (!result.ok) throw new Error(result.error.message)\n },\n forkSession: sessionId => {\n ctx.sessions.fork({ sessionId, increaseTitle: true })\n .then(childId => { ctx.sessions.open(childId) })\n .catch(() => {})\n },\n renameWorkspace: async (workspaceId, title) => { await ctx.workspaces.rename(workspaceId, title) },\n deleteWorkspace: async workspaceId => { await ctx.workspaces.delete(workspaceId) },\n archiveSession: async sessionId => { await ctx.workspaces.archiveSession(sessionId) },\n insertSessionBefore: async (workspaceId, sessionId, beforeSessionId) => {\n await ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId)\n },\n createWorkspace,\n hooks: { directoryFlow: sidebarFlow },\n })\n const pickerInjected = (): PickerInjected => ({\n createWorkspace,\n hooks: { directoryFlow: pickerFlow },\n })\n\n ctx.slots.inject('sidebar.workspaces', () => ctx.slots.register({\n name: 'sidebar.workspaces',\n children: { 'sidebar.workspaces.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: sidebarInjected,\n locale: NS,\n }, WorkspaceSidebar))\n\n ctx.slots.inject('conversation.hero.workspace', () => ctx.slots.register({\n name: 'conversation.hero.workspace',\n children: { 'conversation.hero.workspace.directoryFlow': { kind: 'single', scope: 'root' } },\n inject: pickerInjected,\n locale: NS,\n }, WorkspacePicker))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useState","useCallback","IconPlusOutline16","IconFolderClose16","Menu","Modal","Button","StateDot","useState","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":";;;;;;;;;;;EACA,MAAa,KAAK;GAChB,YAAY;GACZ,UAAU;GACV,QAAQ;GACR,WAAW;GACX,YAAY;GACZ,UAAU;GACV,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;GACR,OAAO;GACP,WAAW;GACX,MAAM;GACN,UAAU;EACZ;EAIA,MAAa,KAAK;GAChB,YAAY;GACZ,UAAU;GACV,QAAQ;GACR,WAAW;GACX,YAAY;GACZ,UAAU;GACV,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;GACR,OAAO;GACP,WAAW;GACX,MAAM;GACN,UAAU;EACZ;EAEA,MAAa,KAAK;;;;ECpGlB,MAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDnB,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;;;ECpDA,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;EAoCzB,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,UAAU,QAAQ,UAAU,KAAA;IAC5B,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,SAAS,aAAa,MAAc,OAAe,KAAqB;GAGtE,OAAO,GAAG,KAAK,GAFJ,QAAQ,IAAI,IAAI,QAAQ,MAAM,GAAG,QAAQ,IAE/B,GADV,MAAM,KAAK,IAAI,QAAQ,GAAG;EAEvC;;EAGA,SAAS,QAAQ,GAAiD,GAAyD;GACzH,MAAM,MAAM,KAAK,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG;GAC3C,MAAM,MAAM,KAAK,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG;GAC3C,OAAO,KAAK,OAAO,MAAM,OAAO,KAAU;EAC5C;;;;;;;;;;EAWA,SAAgB,6BACd,KACA,MACA,YACA,oBACA,KACoB;GACpB,IAAI,QAAA,oBAAmB,OAAO,CAAC;GAC/B,MAAM,YAAY,WAAW,MAAK,SAAQ,KAAK,gBAAgB,GAAG;GAClE,IAAI,cAAc,KAAA,GAAW,OAAO,CAAC;GACrC,MAAM,WAAW,IAAI,IAAI,kBAAkB;GAC3C,MAAM,OAAO,UAAU,WACpB,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;GACxE,IAAI,KAAK,WAAW,GAAG,OAAO,CAAC;GAE/B,MAAM,UAAU,IAAI,KAAK,GAAG;GAC5B,MAAM,QAAQ;IAAE,MAAM,QAAQ,YAAY;IAAG,OAAO,QAAQ,SAAS;IAAG,KAAK,QAAQ,QAAQ;GAAE;GAE/F,MAAM,0BAAU,IAAI,IAAuD;GAC3E,KAAK,MAAM,OAAO,MAAM;IACtB,MAAM,KAAK,KAAK,IAAI,IAAI,WAAW,GAAG;IACtC,MAAM,IAAI,IAAI,KAAK,EAAE;IACrB,MAAM,OAAO;KAAE,MAAM,EAAE,YAAY;KAAG,OAAO,EAAE,SAAS;KAAG,KAAK,EAAE,QAAQ;IAAE;IAC5E,MAAM,UAAU,aAAa,KAAK,MAAM,KAAK,OAAO,KAAK,GAAG;IAC5D,IAAI,SAAS,QAAQ,IAAI,OAAO;IAChC,IAAI,WAAW,KAAA,GAAW;KAIxB,SAAS;MAAE,WADI,KAAK,IAAI,GAAG,QAAQ,OAAO,IAAI,CACnB;MAAG,MAAM,CAAC;KAAE;KACvC,QAAQ,IAAI,SAAS,MAAM;IAC7B;IACA,OAAO,KAAK,KAAK,GAAG;GACtB;GAEA,MAAM,SAA6B,CAAC;GACpC,KAAK,MAAM,CAAC,SAAS,WAAW,SAAS;IACvC,OAAO,KAAK,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,aAAa,OAAO,EAAE,EAAE,CAAC,CAAC,cAAc,OAAO,EAAE,EAAE,CAAC,CAAC;IAChG,OAAO,KAAK;KAAE;KAAS,WAAW,OAAO;KAAW,MAAM,OAAO;IAAK,CAAC;GACzE;GAEA,OAAO,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAC;GACrF,OAAO;EACT;;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;;;;EC7NA,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;;EAGA,SAAS,eAAe,OAAyB,KAAa,GAA8B;GAC1F,IAAI,MAAM,cAAc,GAAG,OAAO,EAAE,OAAO;GAC3C,IAAI,MAAM,cAAc,GAAG,OAAO,EAAE,WAAW;GAC/C,MAAM,QAAQ,MAAM,QAAQ,MAAM,GAAG;GACrC,MAAM,OAAO,OAAO,MAAM,EAAE;GAC5B,MAAM,QAAQ,OAAO,MAAM,EAAE;GAC7B,MAAM,MAAM,OAAO,MAAM,EAAE;GAE3B,IAAI,SAAS,IADO,KAAK,GACN,CAAC,CAAC,YAAY,GAAG,OAAO,EAAE,QAAQ;IAAE,GAAG;IAAO,GAAG;GAAI,CAAC;GACzE,OAAO,EAAE,YAAY;IAAE,GAAG;IAAM,GAAG;IAAO,GAAG;GAAI,CAAC;EACpD;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;EAcA,SAAS,YAAY,EAAE,KAAK,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,GAAG,WAA4B;GACpG,MAAM,CAAC,UAAU,gBAAA,GAAeC,MAAAA,SAAAA,CAAS,KAAK;GAC9C,MAAM,QAAQ,IAAI,QAAQ,EAAE,YAAY,IAAI,IAAI,WAAW,IAAI,QAAQ,EAAE,UAAU;GACnF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,WAAW,SAAS,IAAI,OAAO,UAAU,iBAAiB,KAAK,WAAW,kBAAkB;IAC5F,MAAK;IACL,iBAAe,IAAI,OAAO;IAC1B,eAAe;KAAE,KAAK,IAAI,EAAE;IAAE;IAJhC,UAAA;KAME,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,iBAAiB,kBAAkB,YAAY,MAC7D;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,MAAM,KAAK,IAAI;GAErB,MAAM,eAAA,GAAcD,MAAAA,QAAAA,OACZ,gBAAgB,QAAQ,gBAAA,qBAC1B,6BAA6B,aAAa,UAAU,YAAY,UAAU,GAAG,IAC7E,CAAC,GACL;IAAC;IAAU;IAAU;IAAY;IAAa;GAAG,CACnD;GACA,MAAM,YAAY,gBAAA,qBACd,wBAAwB,WAAW,UAAU,YAAY,QAAQ,IACjE,CAAC;GACL,MAAM,aAAa,gBAAA,qBAA4B,UAAU,WAAW,IAAI,YAAY,OAAM,MAAK,EAAE,KAAK,WAAW,CAAC;GAElH,MAAM,CAAC,OAAO,aAAA,GAAYV,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;GAE1E,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,UAC9C,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;IAEO;IACL,SAAS,SAAS;IACb;IACC;IACN,QAAQ;IACF;IACG;IACN;IACM;GACV,GAVM,IAAI,EAUV;GAGH,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,gBAAA,qBACE,UAAU,KAAI,QAAO,YAAY,KAAK,KAAK,CAAC,IAC5C,YAAY,SAAQ,UAAS,CAC7B,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAoC,WAAU;WAAsB,MAAK;WACtE,UAAA,eAAe,OAAO,KAAK,CAAC;UAC1B,GAFK,SAAS,MAAM,SAEpB,GACL,GAAG,MAAM,KAAK,KAAI,QAAO,YAAY,KAAK,KAAK,CAAC,CAClD,CAAC;UACJ,gBAAgB,QAAQ,cAAc,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WAAY,UAAA,EAAE,cAAc;UAAO,CAAA;UACxG,gBAAgB,QAAQ,cAAc,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WAAY,UAAA,EAAE,YAAY;UAAO,CAAA;SACpF;QAvBK,GAAA,eAAe,MAuBpB;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;;;;ECrbA,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"}
@@ -42,6 +42,10 @@ export declare const zh: {
42
42
  completed: string;
43
43
  collapse: string;
44
44
  expand: string;
45
+ today: string;
46
+ yesterday: string;
47
+ date: string;
48
+ dateYear: string;
45
49
  };
46
50
  export type YaWorkspaceKey = keyof typeof zh;
47
51
  export declare const en: {
@@ -87,5 +91,9 @@ export declare const en: {
87
91
  completed: string;
88
92
  collapse: string;
89
93
  expand: string;
94
+ today: string;
95
+ yesterday: string;
96
+ date: string;
97
+ dateYear: string;
90
98
  };
91
99
  export declare const NS = "ya-workspace-sidebar";
@@ -16,6 +16,14 @@ export interface SessionRow {
16
16
  workspaceKey: WorkspaceId | typeof UNGROUPED;
17
17
  workspaceTitle: string;
18
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
+ }
19
27
  /** One first-level workspace row. */
20
28
  export interface WorkspaceRow {
21
29
  key: WorkspaceId | typeof UNGROUPED;
@@ -33,5 +41,15 @@ export declare function deriveRecent(list: SessionListState, workspaces: readonl
33
41
  export declare function deriveWorkspaces(list: SessionListState, workspaces: readonly WorkspaceView[], archivedSessionIds: readonly SessionId[]): WorkspaceRow[];
34
42
  /** Derive the selected workspace's sessions in its canonical order. */
35
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[];
36
54
  /** Case-insensitive local title/workspace matching used beside Host content search. */
37
55
  export declare function localMatches(rows: readonly SessionRow[], query: string): SessionRow[];
@@ -1,4 +1,4 @@
1
1
  /** One scoped stylesheet injected for the lifetime of the client activation. */
2
- export declare const CSS = "\n[data-ya-workspace-sidebar] { flex:1; min-height:0; display:flex; flex-direction:column; box-sizing:border-box; padding-right:var(--dsh-sidebar-inline-padding); color:var(--dsw-alias-label-primary); }\n[data-ya-workspace-sidebar].ya-rail { padding-right:0; }\n.ya-section-header { flex:none; height:36px; display:flex; align-items:center; justify-content:flex-end; gap:4px; padding-left:12px; margin-bottom:4px; box-sizing:border-box; color:var(--dsw-alias-label-tertiary); }\n.ya-section-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }\n.ya-icon-button { flex:none; width:28px; height:28px; border:0; border-radius:50%; padding:0; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-secondary); background:transparent; cursor:pointer; }\n.ya-icon-button:hover { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-search { flex:none; height:38px; margin:0 2px 10px; padding:0 14px; display:flex; align-items:center; gap:8px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:24px; background:var(--dsw-static-neutral-bluish-75); color:var(--dsw-alias-label-caption); }\nbody[data-ds-dark-theme] .ya-search { background:var(--dsw-static-neutral-bluish-900); }\n.ya-search-input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--dsw-alias-label-primary); font:inherit; font-size:14px; }\n.ya-search-input::placeholder { color:var(--dsw-alias-label-tertiary); }\n.ya-search-icon { flex:none; display:inline-flex; border:0; padding:0; color:inherit; background:transparent; }\n.ya-body { flex:1; min-height:0; display:flex; flex-direction:column; overflow:hidden; margin-right:calc(-1 * var(--dsh-sidebar-inline-padding)); padding-right:var(--dsh-sidebar-inline-padding); }\n.ya-recent { flex:none; padding-bottom:8px; border-bottom:1px solid var(--dsw-alias-border-l2); }\n.ya-recent-collapsed { padding-bottom:0; border-bottom-color:transparent; }\n.ya-recent-list-wrap { display:grid; grid-template-rows:1fr; transition:grid-template-rows 220ms ease-out; }\n.ya-recent-collapsed .ya-recent-list-wrap { grid-template-rows:0fr; }\n.ya-recent-list { display:flex; flex-direction:column; overflow:hidden; min-height:0; }\n.ya-block-label { height:26px; display:flex; align-items:center; gap:2px; padding:0 8px; color:var(--dsw-alias-label-tertiary); font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; }\n.ya-block-label-toggle { flex:none; width:20px; height:20px; margin-left:auto; border:0; border-radius:6px; padding:0; display:inline-flex; align-items:center; justify-content:center; background:transparent; color:var(--dsw-alias-label-tertiary); cursor:pointer; transition:transform 180ms ease-out; }\n.ya-block-label-toggle:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-secondary); }\n.ya-block-label-toggle.ya-collapsed { transform:rotate(-90deg); }\n.ya-breadcrumb { flex:none; height:34px; display:flex; align-items:center; gap:2px; padding:0 6px; color:var(--dsw-alias-label-tertiary); font-size:13px; }\n.ya-crumb { border:0; padding:4px 3px; border-radius:6px; background:transparent; color:inherit; font:inherit; cursor:default; min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\nbutton.ya-crumb:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); cursor:pointer; }\n.ya-scroll { flex:1; min-height:0; overflow-y:auto; padding-bottom:12px; }\n.ya-row { position:relative; min-height:34px; display:flex; align-items:center; gap:6px; margin:1px 0; padding:0 7px; border-radius:9px; box-sizing:border-box; color:var(--dsw-alias-label-primary); cursor:pointer; user-select:none; }\n.ya-row:hover, .ya-row.ya-menu-open { background:var(--dsw-alias-interactive-bg-hover); }\n.ya-row.ya-selected { background:var(--dsw-alias-interactive-bg-selected); }\n.ya-workspace-row { min-height:40px; }\n.ya-row-main { flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }\n.ya-row-line { display:flex; align-items:center; min-width:0; gap:6px; }\n.ya-row-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; line-height:18px; }\n.ya-row-meta { flex:none; color:var(--dsw-alias-label-tertiary); font-size:11px; white-space:nowrap; }\n.ya-workspace-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dsw-alias-label-tertiary); font-size:11px; line-height:15px; }\n.ya-row-actions { flex:none; display:flex; align-items:center; gap:2px; opacity:0; pointer-events:none; transition:opacity 120ms ease-out; }\n.ya-row:hover .ya-row-actions, .ya-menu-open .ya-row-actions { opacity:1; pointer-events:auto; }\n.ya-status-slot { flex:none; width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; color:var(--dsw-alias-label-tertiary); }\n.ya-recent .ya-row { min-height:31px; }\n.ya-search-workspace { color:var(--dsw-alias-label-tertiary); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n.ya-empty, .ya-status { padding:18px 10px; color:var(--dsw-alias-label-tertiary); text-align:center; font-size:13px; }\n.ya-warning { color:var(--dsw-alias-status-warning); }\n.ya-rename-input { width:100%; height:38px; box-sizing:border-box; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; padding:0 11px; background:transparent; color:var(--dsw-alias-label-primary); outline:none; }\n.ya-error { margin-top:8px; color:var(--dsw-alias-status-error); font-size:12px; }\n.ya-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";
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
3
  /** Install the stylesheet and return its disposer. */
4
4
  export declare function installStyles(): () => void;
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@huanlin/dsh-plugin-ya-workspace-sidebar",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "keywords": ["dsh-plugin"],
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": { "optional": true },
68
- "@deepseek-ai/dsh-client-runtime": { "optional": true },
69
- "@deepseek-ai/dsh-client-ui-conversation": { "optional": true },
70
- "@deepseek-ai/dsh-client-ui-primitives": { "optional": true },
71
- "@deepseek-ai/dsh-client-ui-sidebar": { "optional": true },
72
- "@deepseek-ai/dsh-client-ui-slots": { "optional": true },
73
- "@deepseek-ai/dsh-invariants": { "optional": true },
74
- "cordis": { "optional": true },
75
- "react": { "optional": true }
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
+ }