dsh-session-manager 0.6.4 → 0.7.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/lib/client.js CHANGED
@@ -174,8 +174,8 @@ function isTopmostDialog(z) {
174
174
  "menu.delete": "删除会话…",
175
175
  "menu.move": "移动到工作区…",
176
176
  "menu.manage": "打开会话管理…",
177
- "footer.aria": "会话管理",
178
- "footer.label": "会话管理",
177
+ "footer.aria": "会话与工作区",
178
+ "footer.label": "会话与工作区",
179
179
  "panel.title": "会话管理",
180
180
  "panel.github.title": "欢迎Star和提交Issue",
181
181
  "panel.update.title": "检查更新",
@@ -229,6 +229,8 @@ function isTopmostDialog(z) {
229
229
  "panel.sort.updated-asc": "最早更新",
230
230
  "panel.sort.created-desc": "最新创建",
231
231
  "panel.sort.created-asc": "最早创建",
232
+ "panel.sort.name-asc": "名称升序",
233
+ "panel.sort.name-desc": "名称降序",
232
234
  "panel.count": "显示 {shown} / {total} 个会话",
233
235
  "panel.reset": "重置筛选",
234
236
  "panel.empty.filtered": "没有匹配的会话,请调整搜索或筛选条件",
@@ -238,6 +240,9 @@ function isTopmostDialog(z) {
238
240
  "panel.empty": "暂无会话",
239
241
  "panel.empty.archived": "归档为空",
240
242
  "panel.archived": "已归档",
243
+ "panel.workspaceArchived": "工作区已归档",
244
+ "notice.workspaceReAdded": "工作区已恢复显示,但旧会话继续归档",
245
+ "error.workspaceArchived": "所属工作区已归档,无法取消归档该会话。请先在工作区管理中恢复工作区。",
241
246
  "panel.running": "运行中",
242
247
  "panel.current": "当前",
243
248
  "panel.session.new": "新建会话",
@@ -273,9 +278,34 @@ function isTopmostDialog(z) {
273
278
  "error.operation": "操作失败:{message}",
274
279
  "workspace.default": "默认工作区",
275
280
  "workspace.sessions": "{count} 个会话",
281
+ "panel.tab.sessions": "会话管理",
282
+ "panel.tab.workspaces": "工作区管理",
283
+ "workspace.search": "搜索工作区名称或路径",
284
+ "workspace.filter.all": "全部",
285
+ "workspace.filter.active": "未归档",
286
+ "workspace.filter.archived": "已归档",
287
+ "workspace.sort.updated-desc": "最近更新",
288
+ "workspace.sort.updated-asc": "最早更新",
289
+ "workspace.sort.name-asc": "名称升序",
290
+ "workspace.sort.name-desc": "名称降序",
291
+ "workspace.bulk.archive": "归档",
292
+ "workspace.bulk.unarchive": "取消归档",
293
+ "workspace.count": "显示 {shown} / {total} 个工作区",
294
+ "workspace.reset": "重置筛选",
295
+ "workspace.empty.filtered": "没有匹配的工作区,请调整搜索或筛选条件",
296
+ "workspace.empty": "暂无工作区",
297
+ "workspace.badge.archived": "已归档",
298
+ "workspace.lastUpdated": "最近更新:{time}",
299
+ "workspace.switch.active": "已在原生侧边栏显示(点击归档隐藏)",
300
+ "workspace.switch.archived": "已在原生侧边栏隐藏(点击恢复显示)",
301
+ "workspace.switch.aria": "工作区显示开关:{name}",
302
+ "workspace.archive.confirm.title": "归档工作区",
303
+ "workspace.archive.confirm.desc": "确认归档工作区「{name}」?此操作将同时归档该工作区下的 {count} 个未归档会话并在原生侧边栏隐藏该工作区。",
304
+ "workspace.archive.failed": "归档工作区失败:{message}",
305
+ "workspace.unarchive.failed": "恢复工作区失败:{message}",
276
306
  "bulk.title": "批量管理",
277
307
  "bulk.selectedFiltered": "已选 {selected} / {filtered} 项",
278
- "bulk.selectAllFiltered": "全选当前筛选",
308
+ "bulk.selectAllFiltered": "全选筛选",
279
309
  "bulk.clear": "清空选择",
280
310
  "bulk.archive": "归档",
281
311
  "bulk.unarchive": "取消归档",
@@ -412,8 +442,8 @@ function isTopmostDialog(z) {
412
442
  "menu.delete": "Delete session…",
413
443
  "menu.move": "Move to workspace…",
414
444
  "menu.manage": "Open session manager…",
415
- "footer.aria": "Session manager",
416
- "footer.label": "Sessions",
445
+ "footer.aria": "Sessions & Workspaces",
446
+ "footer.label": "Sessions & Workspaces",
417
447
  "panel.title": "Session manager",
418
448
  "panel.github.title": "Star the project or open an issue",
419
449
  "panel.update.title": "Check for updates",
@@ -467,6 +497,8 @@ function isTopmostDialog(z) {
467
497
  "panel.sort.updated-asc": "Least recently updated",
468
498
  "panel.sort.created-desc": "Newest created",
469
499
  "panel.sort.created-asc": "Oldest created",
500
+ "panel.sort.name-asc": "Name (A-Z)",
501
+ "panel.sort.name-desc": "Name (Z-A)",
470
502
  "panel.count": "Showing {shown} / {total} sessions",
471
503
  "panel.reset": "Reset filters",
472
504
  "panel.empty.filtered": "No matching sessions. Adjust your search or filters.",
@@ -543,6 +575,9 @@ function isTopmostDialog(z) {
543
575
  "panel.empty": "No sessions",
544
576
  "panel.empty.archived": "No archived sessions",
545
577
  "panel.archived": "Archived",
578
+ "panel.workspaceArchived": "Workspace Archived",
579
+ "notice.workspaceReAdded": "Workspace restored to view, but previous sessions remain archived.",
580
+ "error.workspaceArchived": "The workspace for this session is archived. Please restore the workspace in Workspace Management first.",
546
581
  "panel.running": "Running",
547
582
  "panel.current": "Current",
548
583
  "panel.session.new": "New session",
@@ -577,7 +612,52 @@ function isTopmostDialog(z) {
577
612
  "busy.processing": "Working…",
578
613
  "error.operation": "Operation failed: {message}",
579
614
  "workspace.default": "Default workspace",
580
- "workspace.sessions": "{count} sessions"
615
+ "workspace.sessions": "{count} sessions",
616
+ "panel.tab.sessions": "Sessions",
617
+ "panel.tab.workspaces": "Workspaces",
618
+ "workspace.search": "Search by name or path",
619
+ "workspace.filter.all": "All",
620
+ "workspace.filter.active": "Active",
621
+ "workspace.filter.archived": "Archived",
622
+ "workspace.sort.updated-desc": "Recently updated",
623
+ "workspace.sort.updated-asc": "Earliest updated",
624
+ "workspace.sort.name-asc": "Name (A-Z)",
625
+ "workspace.sort.name-desc": "Name (Z-A)",
626
+ "workspace.bulk.archive": "Archive",
627
+ "workspace.bulk.unarchive": "Unarchive",
628
+ "workspace.count": "Showing {shown} / {total} workspaces",
629
+ "workspace.reset": "Reset filters",
630
+ "workspace.empty.filtered": "No matching workspaces",
631
+ "workspace.empty": "No workspaces",
632
+ "workspace.badge.archived": "Archived",
633
+ "workspace.lastUpdated": "Updated: {time}",
634
+ "workspace.switch.active": "Shown in sidebar (click to archive)",
635
+ "workspace.switch.archived": "Hidden from sidebar (click to restore)",
636
+ "workspace.switch.aria": "Workspace visibility toggle: {name}",
637
+ "workspace.archive.confirm.title": "Archive Workspace",
638
+ "workspace.archive.confirm.desc": "Archive workspace \"{name}\"? This will also archive {count} active sessions in this workspace and hide it from the sidebar.",
639
+ "workspace.archive.failed": "Failed to archive workspace: {message}",
640
+ "workspace.unarchive.failed": "Failed to restore workspace: {message}"
641
+ };
642
+
643
+ const smTranslate = (k, vars) => {
644
+ const lang = (typeof window !== "undefined" && window.__smActiveLanguage) || "zh";
645
+ const dict = lang === "en" ? (en[k] || zh[k] || k) : (zh[k] || en[k] || k);
646
+ if (!vars || typeof dict !== "string") return dict;
647
+ return dict.replace(/\{(\w+)\}/g, (_, key) => vars[key] !== undefined ? vars[key] : "{" + key + "}");
648
+ };
649
+
650
+ const showNotice = (msg) => {
651
+ if (!msg) return;
652
+ try {
653
+ if (activeClientCtx?.notifications?.info && typeof activeClientCtx.notifications.info === "function") {
654
+ activeClientCtx.notifications.info(msg);
655
+ return;
656
+ }
657
+ } catch (_) {}
658
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
659
+ window.alert(msg);
660
+ }
581
661
  };
582
662
 
583
663
  const css = [
@@ -593,10 +673,15 @@ function isTopmostDialog(z) {
593
673
  ".sm-footerBtn svg{flex:none}",
594
674
  ".sm-panel{display:flex;flex-direction:column;gap:10px;min-height:280px;max-height:min(70vh,640px);min-width:480px}",
595
675
  ".sm-filter{display:flex;gap:4px;flex-wrap:wrap}",
596
- ".sm-filterBtn{cursor:pointer;display:inline-flex;align-items:center;color:var(--dsw-alias-label-secondary);background:0 0;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;height:28px;padding:3px 10px;font-size:12px;line-height:18px;white-space:nowrap;box-sizing:border-box}",
597
- ".sm-filterBtn:hover{background:var(--dsw-alias-interactive-bg-hover)}",
676
+ ".sm-filterBtn{cursor:pointer;display:inline-flex;align-items:center;color:var(--dsw-alias-label-secondary);background:0 0;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;height:28px;padding:3px 10px;font-size:12px;line-height:18px;white-space:nowrap;box-sizing:border-box;transition:all .15s ease}",
677
+ ".sm-filterBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}",
678
+ ".sm-filterBtn:disabled{opacity:.4;cursor:not-allowed}",
598
679
  ".sm-filterBtn.sm-on{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform);border-color:transparent}",
599
- ".sm-list{display:flex;flex-direction:column;gap:4px;min-height:0;overflow:auto;flex:1}",
680
+ ".sm-list{display:flex;flex-direction:column;gap:4px;min-height:0;overflow:auto;flex:1;scrollbar-gutter:stable}",
681
+ ".sm-list::-webkit-scrollbar{width:6px;height:6px}",
682
+ ".sm-list::-webkit-scrollbar-track{background:transparent}",
683
+ ".sm-list::-webkit-scrollbar-thumb{background:var(--dsw-alias-scrollbar-bg-l1,rgba(128,128,128,.2));border-radius:999px}",
684
+ ".sm-list::-webkit-scrollbar-thumb:hover{background:var(--dsw-alias-scrollbar-hover-l1,rgba(128,128,128,.35))}",
600
685
  ".sm-row{box-sizing:border-box;display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}",
601
686
  ".sm-row:hover{background:var(--dsw-alias-interactive-bg-hover)}",
602
687
  ".sm-rowCurrent{border-color:var(--dsw-alias-state-business-primary,var(--dsw-alias-label-secondary))}",
@@ -607,6 +692,7 @@ function isTopmostDialog(z) {
607
692
  ".sm-rowActions{display:flex;gap:4px;flex:none;flex-wrap:wrap;justify-content:flex-end}",
608
693
  ".sm-badge{flex:none;border-radius:999px;padding:0 6px;font-size:10px;line-height:16px}",
609
694
  ".sm-badgeArchived{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-markdown-tag)}",
695
+ ".sm-badgeWorkspaceArchived{color:var(--dsw-alias-state-warn-label,#dd8629);background:var(--dsw-alias-state-warn-tertiary,#fef5e7)}",
610
696
  ".sm-badgeRunning{color:var(--dsw-alias-state-warn-label,#dd8629);background:var(--dsw-alias-state-warn-tertiary,#fef5e7)}",
611
697
  ".sm-badgeCurrent{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-markdown-tag)}",
612
698
  // The former .sm-danger / .sm-dangerText rules were removed: no element
@@ -628,7 +714,7 @@ function isTopmostDialog(z) {
628
714
  ".sm-moveItemSelected{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-tertiary)}",
629
715
  ".sm-moveItemName{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}",
630
716
  ".sm-moveItemMeta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.sm-panelModal{width:760px;max-width:92vw}.sm-panelModal .sm-rowActions{flex-wrap:wrap;justify-content:flex-end}.sm-headerMenu{position:absolute;right:0;top:100%;margin-top:4px;z-index:100005;display:flex;flex-direction:column;min-width:140px;padding:4px;background:var(--dsw-alias-bg-layer-2,#fff);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;box-shadow:0 4px 16px rgba(0,0,0,.15)}.sm-headerMenuItem{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:0 0;border:0;border-radius:6px;color:var(--dsw-alias-label-primary,#111);cursor:pointer;padding:6px 10px;font-size:13px;line-height:18px;white-space:nowrap}.sm-headerMenuItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.sm-headerMenuItem:disabled{opacity:.5;cursor:not-allowed}.sm-headerMenuItem .sm-headerBtnIcon{width:20px;min-width:20px;text-align:center;flex-shrink:0}.sm-headerMenuItemDanger{color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-headerMenuItemDanger:hover{background:var(--dsw-alias-interactive-bg-hover-danger)}.sm-headerMenuUltraOnly{display:none!important}.sm-headerBtn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:32px;height:32px;box-sizing:border-box;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-button-floating-fill,#fff);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;padding:0 10px;font-size:13px;line-height:1;white-space:nowrap;transition:background .15s,color .15s,border-color .15s;flex-shrink:0}.sm-headerBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l1)}.sm-headerBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}.sm-headerBtn svg{width:16px;height:16px;display:block;margin:auto;flex-shrink:0}.sm-migratePanel{display:flex;flex-direction:column;gap:14px;min-width:480px}.sm-migrateRow{display:flex;flex-direction:column;gap:8px}.sm-migrateRow>label{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px;font-weight:500}.sm-migrateChips{display:flex;flex-wrap:wrap;gap:6px}.sm-migrateChip{padding:6px 12px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:transparent;cursor:pointer;font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary);white-space:nowrap}.sm-migrateChip:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-migrateChip:disabled{opacity:.5;cursor:not-allowed}.sm-migrateChipOn{background:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary)}.sm-migrateEmpty{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.sm-migratePreview{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}.sm-migrateWarn{padding:10px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 30%,transparent);border-radius:8px;background:var(--dsw-alias-state-warn-tertiary,#fef5e7);color:var(--dsw-alias-label-secondary);font-size:13px;line-height:18px}.sm-migrateList{max-height:200px;overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.sm-headerBtnDanger{background:var(--dsw-alias-button-floating-fill,#fff);color:var(--dsw-alias-state-error-primary,#d92d20);border-color:var(--dsw-alias-state-error-primary,#d92d20);font-weight:500}.sm-headerBtnDanger:hover:not(:disabled){background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-header{display:inline-flex;align-items:center;gap:6px;flex-wrap:nowrap}.sm-headerSecondaryActions{display:inline-flex;align-items:center;gap:6px;flex-wrap:nowrap}.sm-headerCompactMenu{display:none;position:relative}.sm-headerCompactMenu.sm-headerCompactMenuOpen{position:relative;z-index:100004}.sm-headerCompactMenuBtn{width:32px;min-width:32px;height:32px;padding:0;justify-content:center;font-size:16px;line-height:1}.sm-headerBtnIcon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:14px;line-height:1;vertical-align:middle;flex-shrink:0}.sm-headerBtn.sm-markIcon{width:32px;min-width:32px;height:32px;padding:0;justify-content:center}.sm-headerBtn.sm-markIcon .sm-headerBtnIcon{width:16px;height:16px;font-size:15px;line-height:1}.sm-headerCompactMenuBtn .sm-headerBtnIcon{width:16px;height:16px;font-size:16px;line-height:1}.sm-annotationToggleOpen{position:relative;z-index:100004}.sm-headerBtnActive{background:var(--dsw-alias-button-ghost-active-fill);color:var(--dsw-alias-label-primary)}@container (max-width:1000px){.sm-headerBtn{width:32px;min-width:32px;height:32px;padding:0;justify-content:center}.sm-headerBtnLabel,.sm-priorityText,.sm-priorityBadge{display:none}.sm-headerBtn.sm-headerBtn-withBadge{width:auto;min-width:32px;padding:0 6px}}@container (max-width:520px){.sm-headerSecondaryActions,.sm-headerSecondaryAction{display:none!important}.sm-headerCompactMenu{display:inline-flex}}@container (max-width:420px){.sm-header>:not(.sm-headerCompactMenu){display:none!important}.sm-header .sm-headerBtn:not(.sm-headerCompactMenuBtn){display:none!important}.sm-headerCompactMenu{display:inline-flex!important}.sm-headerMenu{right:auto!important;left:0!important}.sm-headerMenuUltraOnly{display:flex!important}}",
631
- ".sm-panelDialog{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:600px;max-width:calc(100vw - 32px);max-height:560px;height:auto;box-sizing:border-box;display:flex;flex-direction:column;gap:0;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);overflow:hidden;z-index:1020}.sm-panelDialog .sm-nativeDialogHeader{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;min-height:46px;box-sizing:border-box}.sm-panelDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;min-width:0;max-width:calc(100% - 140px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;pointer-events:auto;z-index:0}.sm-panelDialog .sm-nativeDialogHeaderActions{display:flex;align-items:center;gap:6px;flex:none;position:relative;z-index:1;margin-left:auto}.sm-nativeDialogFooter,.sm-bulkDialog .sm-nativeDialogFooter,.sm-confirmDialog .sm-nativeDialogFooter,.sm-migrateDialog .sm-nativeDialogFooter{display:flex;padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-panelDialog .sm-panel{display:flex;flex-direction:column;gap:6px;min-height:0;flex:1 1 auto;overflow:auto;padding:8px 12px}.sm-panelDialog .sm-list{display:flex;flex-direction:column;gap:2px;flex:1 1 auto;min-height:0;overflow:auto}.sm-panelDialog .sm-row{display:flex;align-items:center;gap:8px;padding:6px 10px;min-height:36px;border:1px solid transparent;border-radius:8px;background:transparent;flex-shrink:0}.sm-panelDialog .sm-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.sm-panelDialog .sm-rowCurrent{background:var(--dsw-alias-bg-module-platform);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-panelDialog .sm-rowMain{display:flex;align-items:stretch!important;gap:8px;min-width:0;flex:1 1 auto;overflow:visible;text-align:left!important}.sm-panelDialog .sm-rowTitle{min-width:0;flex:1 1 0%;width:100%;align-self:stretch;display:flex;align-items:center;justify-content:flex-start;gap:6px;font-size:12px;line-height:16px;overflow:hidden;text-align:left!important;direction:ltr!important;unicode-bidi:plaintext}.sm-confirmDialog{z-index:10000}.sm-confirmDialog.sm-nativeDialogLayer{position:fixed;left:calc(50vw + 184px);top:calc(50vh - 90px);width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:calc(50vh - 90px) auto auto calc(50vw + 308px)}.sm-confirmDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-confirmDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:auto;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:flex;flex-direction:column;box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);padding:0;overflow:hidden;animation:sm-confirmPop .14s ease-out}.sm-confirmDialog .sm-nativeDialogHeader{position:relative;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-confirmDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-confirmDialog .sm-nativeDialogBody{padding:10px 16px;display:flex;flex-direction:column;gap:8px;min-height:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-confirmDialog .sm-nativeDialogDescription{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);white-space:pre-wrap}.sm-confirmDialog .sm-warn{display:flex;align-items:flex-start;gap:8px;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 8%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 25%,transparent);border-radius:8px;padding:8px 10px;margin-top:0}.sm-confirmDialog .sm-nativeDialogFooter{padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-confirmDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary);text-align:center}.sm-confirmDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-migrateDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-updateDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-bulkDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-panelDialog .sm-nativeDialogCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-confirmDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-confirmDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}@keyframes sm-confirmPop{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.sm-confirmDialog.sm-nativeDialog{padding:0;width:auto;max-width:none}.sm-panelDialog .sm-rowTitle>span:first-child{display:block;min-width:0;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;flex:1 1 auto;width:auto;text-align:left!important;direction:ltr!important;unicode-bidi:plaintext}.sm-panelDialog .sm-rowMeta{display:none}.sm-panelDialog .sm-rowActions{display:flex;gap:2px;flex:none;justify-content:flex-end}.sm-panelDialog .sm-rowActions .sm-rowBtn{min-height:22px;padding:0 7px;font-size:11px;line-height:18px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap}.sm-rowBtn.sm-markIcon{padding:0 6px;font-size:13px;line-height:18px}.sm-panelDialog .sm-rowActions .sm-rowBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.sm-panelDialog .sm-rowActions .sm-rowBtnDanger{color:var(--dsw-alias-state-error-primary)}.sm-panelDialog .sm-rowActions .sm-rowBtnDanger:hover{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.sm-panelDialog .sm-filter{flex:none;padding:6px 12px 4px;gap:4px;display:flex;flex-wrap:wrap}.sm-panelDialog .sm-filterBtn{min-height:24px;padding:2px 10px;font-size:11px;line-height:16px;border-radius:4px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}.sm-panelDialog .sm-filterBtn.sm-on{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}.sm-panelDialog .sm-badge{font-size:10px;line-height:14px;padding:0 5px;border-radius:6px;flex:none}.sm-panelDialog .sm-error{padding:6px 10px;margin:0;font-size:12px;line-height:16px}.sm-panelDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:center}.sm-panelDialog .sm-nativeDialogCancel{background:transparent}.sm-panelDialog .sm-nativeDialogConfirm,.sm-annotationDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-panelDialog .sm-nativeDialogConfirm:hover:not(:disabled),.sm-annotationDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-confirmDialog .sm-nativeDialogDanger,.sm-migrateDialog .sm-nativeDialogDanger,.sm-bulkDialog .sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-confirmDialog .sm-nativeDialogDanger:hover:not(:disabled),.sm-migrateDialog .sm-nativeDialogDanger:hover:not(:disabled),.sm-bulkDialog .sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-panelDialog .sm-empty{padding:18px 0;font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center}.sm-panelDialog .sm-footError{font-size:11px;color:var(--dsw-alias-state-error-primary);margin-right:auto;line-height:20px}.sm-panelDialog .sm-moveLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.sm-migrateDialog .sm-nativeDialogFooter{flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-migrateDialog .sm-migrateChip{cursor:pointer;pointer-events:auto;position:relative;z-index:1}.sm-migrateDialog .sm-migrateChip[disabled]{opacity:.5;cursor:not-allowed}.sm-migrateDialog.sm-nativeDialogLayer{position:fixed;left:50vw;top:auto;bottom:48px;transform:translateX(-50%);width:min(560px,calc(100vw - 32px));max-height:none;display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:auto;z-index:10001}.sm-migrateDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-migrateDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:360px;max-width:calc(100vw - 32px);max-height:min(70vh,520px);box-sizing:border-box;background-color:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.45);overflow:hidden;padding:0;display:flex;flex-direction:column;gap:0}.sm-migrateDialog{position:fixed;left:50vw;top:auto;bottom:48px;transform:translateX(-50%);width:min(560px,calc(100vw - 32px));max-height:min(70vh,520px);box-sizing:border-box;display:flex;flex-direction:column;gap:0;background-color:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.45);overflow:hidden;z-index:10001}.sm-migrateDialog .sm-nativeDialogHeader{padding:12px 18px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-migrateDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;color:var(--dsw-alias-label-primary,#111);text-align:center;width:auto;max-width:calc(100% - 36px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-migrateDialog .sm-migratePanel{padding:12px 18px;display:flex;flex-direction:column;gap:14px}.sm-migrateDialog .sm-nativeDialogBody{padding:0}.sm-migrateDialog .sm-nativeDialogFooter{padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0;gap:8px}.sm-migrateDialog .sm-migrateRow>label{color:var(--dsw-alias-label-secondary,#444)}.sm-migrateDialog .sm-migrateChip{padding:6px 12px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2,#ddd);background-color:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-primary,#111);font-size:13px;line-height:18px;cursor:pointer;pointer-events:auto;position:relative;z-index:1;white-space:nowrap}.sm-migrateDialog .sm-migrateChip:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover,#e8e8e8)}.sm-migrateDialog .sm-migrateChipOn{background-color:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-migrateDialog .sm-migrateChip.sm-migrateChipOn:hover:not(:disabled){background-color:var(--dsw-alias-button-info-hover,#4576f0);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-button-info-hover,#4576f0);filter:none}.sm-migrateDialog .sm-migrateChipOn:hover:not(:disabled){filter:brightness(.92)}.sm-migrateDialog .sm-migrateChip[disabled]{opacity:.5;cursor:not-allowed}.sm-migrateDialog .sm-migrateEmpty{color:var(--dsw-alias-label-tertiary,#888)}.sm-migrateDialog .sm-migratePreview{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;background-color:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);font-size:13px;line-height:18px}.sm-migrateDialog .sm-migrateWarn{padding:10px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 30%,transparent);border-radius:8px;background-color:var(--dsw-alias-state-warn-tertiary,#fef5e7);color:var(--dsw-alias-label-secondary,#444);font-size:13px;line-height:18px}.sm-migrateDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background-color:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-migrateDialog .sm-nativeDialogButton:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover,#e8e8e8)}.sm-migrateDialog .sm-nativeDialogConfirm{background-color:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-migrateDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}",
717
+ ".sm-panelDialog{position:fixed;inset:0;margin:auto;transform:none;width:680px;max-width:calc(100vw - 32px);height:560px;max-height:calc(100vh - 32px);box-sizing:border-box;display:flex;flex-direction:column;gap:0;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);overflow:hidden;z-index:1020}.sm-panelDialog .sm-nativeDialogHeader{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;min-height:46px;box-sizing:border-box}.sm-panelDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;min-width:0;max-width:calc(100% - 140px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;pointer-events:auto;z-index:0}.sm-panelDialog .sm-nativeDialogHeaderActions{display:flex;align-items:center;gap:6px;flex:none;position:relative;z-index:1;margin-left:auto}.sm-nativeDialogFooter,.sm-bulkDialog .sm-nativeDialogFooter,.sm-confirmDialog .sm-nativeDialogFooter,.sm-migrateDialog .sm-nativeDialogFooter{display:flex;padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-panelDialog .sm-panel{display:flex;flex-direction:column;gap:6px;min-height:0;flex:1 1 auto;overflow:auto;padding:8px 12px}.sm-panelDialog .sm-list{display:flex;flex-direction:column;gap:2px;flex:1 1 auto;min-height:0;overflow:auto;scrollbar-gutter:stable}.sm-panelDialog .sm-row{display:flex;align-items:center;gap:8px;padding:6px 10px;min-height:36px;border:1px solid transparent;border-radius:8px;background:transparent;flex-shrink:0;transition:background .12s ease,border-color .12s ease}.sm-panelDialog .sm-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.sm-panelDialog .sm-rowCurrent{background:var(--dsw-alias-bg-module-platform);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-panelDialog .sm-rowMain{display:flex;align-items:stretch!important;gap:8px;min-width:0;flex:1 1 auto;overflow:visible;text-align:left!important}.sm-panelDialog .sm-rowTitle{min-width:0;flex:1 1 0%;width:100%;align-self:stretch;display:flex;align-items:center;justify-content:flex-start;gap:6px;font-size:12px;line-height:16px;overflow:hidden;text-align:left!important;direction:ltr!important;unicode-bidi:plaintext}.sm-confirmDialog{z-index:10000}.sm-confirmDialog.sm-nativeDialogLayer{position:fixed;left:calc(50vw + 184px);top:calc(50vh - 90px);width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:calc(50vh - 90px) auto auto calc(50vw + 308px)}.sm-confirmDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-confirmDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:auto;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:flex;flex-direction:column;box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);padding:0;overflow:hidden;animation:sm-confirmPop .14s ease-out}.sm-confirmDialog .sm-nativeDialogHeader{position:relative;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-confirmDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-confirmDialog .sm-nativeDialogBody{padding:10px 16px;display:flex;flex-direction:column;gap:8px;min-height:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-confirmDialog .sm-nativeDialogDescription{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);white-space:pre-wrap}.sm-confirmDialog .sm-warn{display:flex;align-items:flex-start;gap:8px;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 8%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 25%,transparent);border-radius:8px;padding:8px 10px;margin-top:0}.sm-confirmDialog .sm-nativeDialogFooter{padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-confirmDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary);text-align:center}.sm-confirmDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-migrateDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-updateDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-bulkDialog .sm-nativeDialogCancel:hover:not(:disabled),.sm-panelDialog .sm-nativeDialogCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-confirmDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-confirmDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}@keyframes sm-confirmPop{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.sm-confirmDialog.sm-nativeDialog{padding:0;width:auto;max-width:none}.sm-panelDialog .sm-rowTitle>span:first-child{display:block;min-width:0;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;flex:1 1 auto;width:auto;text-align:left!important;direction:ltr!important;unicode-bidi:plaintext}.sm-panelDialog .sm-rowMeta{display:none}.sm-panelDialog .sm-rowActions{display:flex;gap:2px;flex:none;justify-content:flex-end}.sm-panelDialog .sm-rowActions .sm-rowBtn{min-height:22px;padding:0 7px;font-size:11px;line-height:18px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap}.sm-rowBtn.sm-markIcon{padding:0 6px;font-size:13px;line-height:18px}.sm-panelDialog .sm-rowActions .sm-rowBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.sm-panelDialog .sm-rowActions .sm-rowBtnDanger{color:var(--dsw-alias-state-error-primary)}.sm-panelDialog .sm-rowActions .sm-rowBtnDanger:hover{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.sm-panelDialog .sm-filter{flex:none;padding:6px 12px 4px;gap:4px;display:flex;flex-wrap:wrap}.sm-panelDialog .sm-filterBtn{height:28px;min-height:28px;padding:3px 10px;font-size:12px;line-height:18px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;box-sizing:border-box;white-space:nowrap;flex-shrink:0;transition:all .15s ease}.sm-panelDialog .sm-filterBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-panelDialog .sm-filterBtn:disabled{opacity:.4;cursor:not-allowed}.sm-panelDialog .sm-filterBtn.sm-on{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}.sm-panelDialog .sm-badge{font-size:10px;line-height:14px;padding:0 5px;border-radius:6px;flex:none}.sm-panelDialog .sm-error{padding:6px 10px;margin:0;font-size:12px;line-height:16px}.sm-panelDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:center}.sm-panelDialog .sm-nativeDialogCancel{background:transparent}.sm-panelDialog .sm-nativeDialogConfirm,.sm-annotationDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-panelDialog .sm-nativeDialogConfirm:hover:not(:disabled),.sm-annotationDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-confirmDialog .sm-nativeDialogDanger,.sm-migrateDialog .sm-nativeDialogDanger,.sm-bulkDialog .sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-confirmDialog .sm-nativeDialogDanger:hover:not(:disabled),.sm-migrateDialog .sm-nativeDialogDanger:hover:not(:disabled),.sm-bulkDialog .sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-panelDialog .sm-empty{padding:18px 0;font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center}.sm-panelDialog .sm-footError{font-size:11px;color:var(--dsw-alias-state-error-primary);margin-right:auto;line-height:20px}.sm-panelDialog .sm-moveLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.sm-migrateDialog .sm-nativeDialogFooter{flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0}.sm-migrateDialog .sm-migrateChip{cursor:pointer;pointer-events:auto;position:relative;z-index:1}.sm-migrateDialog .sm-migrateChip[disabled]{opacity:.5;cursor:not-allowed}.sm-migrateDialog.sm-nativeDialogLayer{position:fixed;left:50vw;top:auto;bottom:48px;transform:translateX(-50%);width:min(560px,calc(100vw - 32px));max-height:none;display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:auto;z-index:10001}.sm-migrateDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-migrateDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:360px;max-width:calc(100vw - 32px);max-height:min(70vh,520px);box-sizing:border-box;background-color:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.45);overflow:hidden;padding:0;display:flex;flex-direction:column;gap:0}.sm-migrateDialog{position:fixed;left:50vw;top:auto;bottom:48px;transform:translateX(-50%);width:min(560px,calc(100vw - 32px));max-height:min(70vh,520px);box-sizing:border-box;display:flex;flex-direction:column;gap:0;background-color:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.45);overflow:hidden;z-index:10001}.sm-migrateDialog .sm-nativeDialogHeader{padding:12px 18px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-migrateDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;color:var(--dsw-alias-label-primary,#111);text-align:center;width:auto;max-width:calc(100% - 36px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-migrateDialog .sm-migratePanel{padding:12px 18px;display:flex;flex-direction:column;gap:14px}.sm-migrateDialog .sm-nativeDialogBody{padding:0}.sm-migrateDialog .sm-nativeDialogFooter{padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:6px;margin-top:0;gap:8px}.sm-migrateDialog .sm-migrateRow>label{color:var(--dsw-alias-label-secondary,#444)}.sm-migrateDialog .sm-migrateChip{padding:6px 12px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2,#ddd);background-color:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-primary,#111);font-size:13px;line-height:18px;cursor:pointer;pointer-events:auto;position:relative;z-index:1;white-space:nowrap}.sm-migrateDialog .sm-migrateChip:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover,#e8e8e8)}.sm-migrateDialog .sm-migrateChipOn{background-color:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-migrateDialog .sm-migrateChip.sm-migrateChipOn:hover:not(:disabled){background-color:var(--dsw-alias-button-info-hover,#4576f0);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-button-info-hover,#4576f0);filter:none}.sm-migrateDialog .sm-migrateChipOn:hover:not(:disabled){filter:brightness(.92)}.sm-migrateDialog .sm-migrateChip[disabled]{opacity:.5;cursor:not-allowed}.sm-migrateDialog .sm-migrateEmpty{color:var(--dsw-alias-label-tertiary,#888)}.sm-migrateDialog .sm-migratePreview{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;background-color:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);font-size:13px;line-height:18px}.sm-migrateDialog .sm-migrateWarn{padding:10px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 30%,transparent);border-radius:8px;background-color:var(--dsw-alias-state-warn-tertiary,#fef5e7);color:var(--dsw-alias-label-secondary,#444);font-size:13px;line-height:18px}.sm-migrateDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background-color:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-migrateDialog .sm-nativeDialogButton:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover,#e8e8e8)}.sm-migrateDialog .sm-nativeDialogConfirm{background-color:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-migrateDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}",
632
718
  // The .sm-tooltip rule below deliberately keeps !important: it targets
633
719
  // DSH's Tooltip primitive (used through renderTip), which ships its own
634
720
  // inline styles, so a plugin rule cannot win on specificity alone
@@ -640,7 +726,7 @@ function isTopmostDialog(z) {
640
726
  // applied). Tooltip visibility is governed by the layering contract
641
727
  // above, not by this rule; it is kept as the scoped replacement for the
642
728
  // unscoped selector Issue #21 removed.
643
- ".sm-panelHeaderClose{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;min-height:26px;padding:0;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary,#555);cursor:pointer;flex:none;box-sizing:border-box;outline:none}.sm-panelHeaderClose:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderClose svg{display:block;width:14px;height:14px;margin:auto}.sm-panelHeaderGithub{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:6px;color:var(--dsw-alias-label-secondary,#555);text-decoration:none;flex:none;transition:background .15s,color .15s;cursor:pointer}.sm-panelHeaderGithub:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderGithub svg{display:block;width:16px;height:16px;fill:currentColor}.sm-panelHeaderLeft{display:flex;align-items:center;gap:4px;flex:none;position:relative;z-index:1}.sm-panelHeaderWhale{display:inline-flex;align-items:center;justify-content:center;position:relative;width:26px;height:26px;border-radius:6px;color:var(--dsw-alias-label-secondary,#555);text-decoration:none;flex:none;transition:background .15s,color .15s;cursor:pointer}.sm-panelHeaderWhale:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderWhale svg{display:block;width:16px;height:16px;margin:auto}.sm-panelHeaderWhale .sm-updateDot{position:absolute;top:2px;right:2px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-state-error-primary,#e53e3e);border:1.5px solid var(--dsw-alias-bg-layer-1,#fff)}.sm-panelHeaderWhale .sm-updateSpinner{position:absolute;inset:2px;border:2px solid transparent;border-top-color:var(--dsw-alias-state-business-primary,#356ae6);border-radius:50%;animation:sm-spin .8s linear infinite}@keyframes sm-spin{to{transform:rotate(360deg)}}.sm-updateDialogLayer{display:flex!important;align-items:center!important;justify-content:center!important;position:fixed;inset:0;padding:16px;box-sizing:border-box;background:transparent;border:0;box-shadow:none;z-index:10010;pointer-events:none}.sm-updateDialogLayer .sm-nativeDialog{position:relative;width:380px;max-width:calc(100vw - 32px);box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);overflow:hidden;animation:sm-confirmPop .14s ease-out;pointer-events:auto}.sm-updateDialog .sm-nativeDialogHeader{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;min-height:46px;box-sizing:border-box}.sm-updateDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:15px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 80px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;z-index:0}.sm-updateDialog .sm-nativeDialogHeader .sm-panelHeaderClose{position:relative;z-index:1;margin-left:auto}.sm-updateDialog .sm-nativeDialogBody{padding:14px 16px;display:flex;flex-direction:column;gap:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111)}.sm-updateDialog .sm-nativeDialogFooter{display:flex;padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:8px;margin-top:0}.sm-updateDialog .sm-nativeDialogFooter .sm-nativeDialogConfirm:only-child{margin-left:auto}.sm-updateDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-updateDialog .sm-nativeDialogButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-updateDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-updateDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-updateVersionGrid{display:grid;grid-template-columns:auto 1fr;gap:6px 12px;padding:12px;background:var(--dsw-alias-bg-layer-2,#fff);border:1px solid var(--dsw-alias-border-l2,#eee);border-radius:8px;font-size:13px;line-height:20px}.sm-updateVersionLabel{color:var(--dsw-alias-label-secondary,#666);font-weight:500}.sm-updateVersionValue{color:var(--dsw-alias-label-primary,#111);font-family:monospace;font-size:13px}.sm-updateStatusBox{margin-top:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111)}.sm-updateStatusBox.sm-warn{color:var(--dsw-alias-state-warn-label,#dd8629);background:var(--dsw-alias-state-warn-tertiary,#fef5e7);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 25%,transparent)}.sm-updateStatusBox.sm-error{color:var(--dsw-alias-state-error-primary,#ec1313);background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 8%,transparent);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 22%,transparent)}.sm-updateStatusBox.sm-success{color:var(--dsw-alias-state-success-primary,#22c55e);background:var(--dsw-alias-state-success-tertiary,#e6faed);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 25%,transparent)}.sm-settingsCard{background:var(--sm-dialog-surface);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;padding:16px 20px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111);box-sizing:border-box;width:100%}.sm-settingsHeader{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee)}.sm-settingsTitle{margin:0;font-size:16px;line-height:22px;font-weight:600;display:flex;align-items:center;gap:8px}.sm-settingsTag{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-secondary,#666);font-family:monospace}.sm-settingsSection{margin-top:14px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#eee)}.sm-settingsSectionTitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-secondary,#666);margin-bottom:8px;text-transform:uppercase;letter-spacing:.5px}.sm-settingsRow{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:32px}.sm-settingsActions{display:flex;align-items:center;gap:8px;margin-top:10px}.sm-settingsLink{color:var(--dsw-alias-state-business-primary,#356ae6);text-decoration:none}.sm-settingsLink:hover{text-decoration:underline}.sm-settingsCheckbox{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.sm-settingsSelect{min-height:28px;padding:3px 8px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:6px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);cursor:pointer;outline:none}.sm-panelHeaderClose:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderClose:disabled{opacity:.5;cursor:not-allowed}.sm-migrateCurrent{padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;background:var(--dsw-alias-bg-layer-2,#fff);font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary,#111)}.sm-migrateConfirmLayer.sm-confirmDialog.sm-nativeDialogLayer{width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);inset:calc(50vh - 90px) auto auto calc(50vw + 308px)}.sm-migrateConfirmLayer.sm-confirmDialog.sm-nativeDialogLayer .sm-migrateDialog{position:relative;left:auto;top:auto;bottom:auto;transform:none;width:100%;max-width:calc(100vw - 32px);max-height:min(70vh,calc(100vh - 32px));z-index:auto;display:flex;flex-direction:column;overflow:hidden}.sm-migrateConfirmLayer .sm-migratePanel{min-width:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-migrateConfirmLayer .sm-nativeDialogButton.sm-nativeDialogConfirm:hover:not(:disabled){background-color:var(--dsw-alias-button-info-hover,#4576f0);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-button-info-hover,#4576f0);filter:none}.sm-settingsSectionHeader{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.sm-settingsSectionHeader .sm-settingsSectionTitle{margin-bottom:0}.sm-settingsVersionActions{display:flex;align-items:center;gap:8px}.sm-settingsCheckBtn{min-height:26px;padding:2px 12px;font-size:12px;line-height:18px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,#ddd);background:transparent;color:var(--dsw-alias-label-primary,#111);cursor:pointer;white-space:nowrap}.sm-settingsCheckBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-settingsRowInline{justify-content:flex-start;flex-wrap:wrap;gap:8px;align-items:center}.sm-settingsBadgeLink{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,#ddd);background:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-secondary,#555);font-size:12px;line-height:18px;text-decoration:none;cursor:pointer;transition:all .15s}.sm-settingsBadgeLink:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-state-business-primary,#356ae6);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-settingsBadgeLink svg{flex:none}.sm-tooltip{z-index:1100!important;box-shadow:none!important;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.15))!important;filter:none!important}",
729
+ ".sm-panelHeaderClose{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;min-height:26px;padding:0;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary,#555);cursor:pointer;flex:none;box-sizing:border-box;outline:none}.sm-panelHeaderClose:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderClose svg{display:block;width:14px;height:14px;margin:auto}.sm-panelHeaderGithub{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:6px;color:var(--dsw-alias-label-secondary,#555);text-decoration:none;flex:none;transition:background .15s,color .15s;cursor:pointer}.sm-panelHeaderGithub:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderGithub svg{display:block;width:16px;height:16px;fill:currentColor}.sm-panelHeaderLeft{display:flex;align-items:center;gap:4px;flex:none;position:relative;z-index:1}.sm-panelHeaderWhale{display:inline-flex;align-items:center;justify-content:center;position:relative;width:26px;height:26px;border-radius:6px;color:var(--dsw-alias-label-secondary,#555);text-decoration:none;flex:none;transition:background .15s,color .15s;cursor:pointer}.sm-panelHeaderWhale:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderWhale svg{display:block;width:16px;height:16px;margin:auto}.sm-panelHeaderWhale .sm-updateDot{position:absolute;top:2px;right:2px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-state-error-primary,#e53e3e);border:1.5px solid var(--dsw-alias-bg-layer-1,#fff)}.sm-panelHeaderWhale .sm-updateSpinner{position:absolute;inset:2px;border:2px solid transparent;border-top-color:var(--dsw-alias-state-business-primary,#356ae6);border-radius:50%;animation:sm-spin .8s linear infinite}@keyframes sm-spin{to{transform:rotate(360deg)}}.sm-updateDialogLayer{display:flex!important;align-items:center!important;justify-content:center!important;position:fixed;inset:0;padding:16px;box-sizing:border-box;background:transparent;border:0;box-shadow:none;z-index:10010;pointer-events:none}.sm-updateDialogLayer .sm-nativeDialog{position:relative;width:380px;max-width:calc(100vw - 32px);box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);overflow:hidden;animation:sm-confirmPop .14s ease-out;pointer-events:auto}.sm-updateDialog .sm-nativeDialogHeader{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;min-height:46px;box-sizing:border-box}.sm-updateDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:15px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 80px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;z-index:0}.sm-updateDialog .sm-nativeDialogHeader .sm-panelHeaderClose{position:relative;z-index:1;margin-left:auto}.sm-updateDialog .sm-nativeDialogBody{padding:14px 16px;display:flex;flex-direction:column;gap:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111)}.sm-updateDialog .sm-nativeDialogFooter{display:flex;padding:10px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee);flex:none;flex-wrap:wrap;justify-content:space-between;gap:8px;margin-top:0}.sm-updateDialog .sm-nativeDialogFooter .sm-nativeDialogConfirm:only-child{margin-left:auto}.sm-updateDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-updateDialog .sm-nativeDialogButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-updateDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-updateDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-updateVersionGrid{display:grid;grid-template-columns:auto 1fr;gap:6px 12px;padding:12px;background:var(--dsw-alias-bg-layer-2,#fff);border:1px solid var(--dsw-alias-border-l2,#eee);border-radius:8px;font-size:13px;line-height:20px}.sm-updateVersionLabel{color:var(--dsw-alias-label-secondary,#666);font-weight:500}.sm-updateVersionValue{color:var(--dsw-alias-label-primary,#111);font-family:monospace;font-size:13px}.sm-updateStatusBox{margin-top:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111)}.sm-updateStatusBox.sm-warn{color:var(--dsw-alias-state-warn-label,#dd8629);background:var(--dsw-alias-state-warn-tertiary,#fef5e7);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 25%,transparent)}.sm-updateStatusBox.sm-error{color:var(--dsw-alias-state-error-primary,#ec1313);background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 8%,transparent);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary,#ec1313) 22%,transparent)}.sm-updateStatusBox.sm-success{color:var(--dsw-alias-state-success-primary,#22c55e);background:var(--dsw-alias-state-success-tertiary,#e6faed);padding:8px 10px;border-radius:6px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 25%,transparent)}.sm-settingsCard{background:var(--sm-dialog-surface);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;padding:16px 20px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111);box-sizing:border-box;width:100%}.sm-settingsHeader{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee)}.sm-settingsTitle{margin:0;font-size:16px;line-height:22px;font-weight:600;display:flex;align-items:center;gap:8px}.sm-settingsTag{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-secondary,#666);font-family:monospace}.sm-settingsSection{margin-top:14px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2,#eee)}.sm-settingsSectionTitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-secondary,#666);margin-bottom:8px;text-transform:uppercase;letter-spacing:.5px}.sm-settingsRow{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:32px}.sm-settingsActions{display:flex;align-items:center;gap:8px;margin-top:10px}.sm-settingsLink{color:var(--dsw-alias-state-business-primary,#356ae6);text-decoration:none}.sm-settingsLink:hover{text-decoration:underline}.sm-settingsCheckbox{display:inline-flex;align-items:center;gap:6px;cursor:pointer}.sm-settingsSelect{min-height:28px;height:28px;font-size:12px;line-height:20px;padding:3px 26px 3px 10px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);cursor:pointer}.sm-panelHeaderClose:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-label-primary,#111)}.sm-panelHeaderClose:disabled{opacity:.5;cursor:not-allowed}.sm-migrateCurrent{padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;background:var(--dsw-alias-bg-layer-2,#fff);font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary,#111)}.sm-migrateConfirmLayer.sm-confirmDialog.sm-nativeDialogLayer{width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);inset:calc(50vh - 90px) auto auto calc(50vw + 308px)}.sm-migrateConfirmLayer.sm-confirmDialog.sm-nativeDialogLayer .sm-migrateDialog{position:relative;left:auto;top:auto;bottom:auto;transform:none;width:100%;max-width:calc(100vw - 32px);max-height:min(70vh,calc(100vh - 32px));z-index:auto;display:flex;flex-direction:column;overflow:hidden}.sm-migrateConfirmLayer .sm-migratePanel{min-width:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-migrateConfirmLayer .sm-nativeDialogButton.sm-nativeDialogConfirm:hover:not(:disabled){background-color:var(--dsw-alias-button-info-hover,#4576f0);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-button-info-hover,#4576f0);filter:none}.sm-settingsSectionHeader{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.sm-settingsSectionHeader .sm-settingsSectionTitle{margin-bottom:0}.sm-settingsVersionActions{display:flex;align-items:center;gap:8px}.sm-settingsCheckBtn{min-height:26px;padding:2px 12px;font-size:12px;line-height:18px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,#ddd);background:transparent;color:var(--dsw-alias-label-primary,#111);cursor:pointer;white-space:nowrap}.sm-settingsCheckBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.sm-settingsRowInline{justify-content:flex-start;flex-wrap:wrap;gap:8px;align-items:center}.sm-settingsBadgeLink{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,#ddd);background:var(--dsw-alias-markdown-tag,#f1f3f5);color:var(--dsw-alias-label-secondary,#555);font-size:12px;line-height:18px;text-decoration:none;cursor:pointer;transition:all .15s}.sm-settingsBadgeLink:hover{background:var(--dsw-alias-interactive-bg-hover,#eee);color:var(--dsw-alias-state-business-primary,#356ae6);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-settingsBadgeLink svg{flex:none}.sm-tooltip{z-index:1100!important;box-shadow:none!important;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.15))!important;filter:none!important}",
644
730
 
645
731
  // Issue #23 — dialog opacity.
646
732
  //
@@ -703,12 +789,18 @@ function isTopmostDialog(z) {
703
789
  "[data-sm-theme=dark] .sm-nativeDialog,[data-sm-theme=dark] .sm-panelDialog,[data-sm-theme=dark] .sm-migrateDialog,[data-sm-theme=dark] .sm-settingsCard{--sm-dialog-surface-fallback:#1f1f23}",
704
790
  ".sm-panelDialog{max-height:min(640px,calc(100vh - 32px))}.sm-panelDialog .sm-panel{min-width:0;overflow:hidden}",
705
791
  ".sm-panelTools{display:flex;flex-direction:column;gap:8px;flex:none;padding:2px 0 6px}",
706
- ".sm-queryInput,.sm-viewSelect{box-sizing:border-box;width:100%;min-width:0;height:32px;padding:5px 9px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:7px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);font:inherit;font-size:12px;line-height:20px}",
707
- ".sm-queryInput::placeholder{color:var(--dsw-alias-label-tertiary,#888)}.sm-queryInput:focus-visible,.sm-viewSelect:focus-visible,.sm-resetFilters:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#356ae6);outline-offset:2px}.sm-viewSelect:disabled{opacity:.6;cursor:wait}",
708
- ".sm-panelSelects{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.sm-panelSelects .sm-viewField>span{display:none}.sm-panelSelects .sm-viewField .sm-viewSelect{font-size:11px;padding:4px 7px;height:28px;line-height:18px}.sm-viewField{display:flex;flex-direction:column;gap:3px;min-width:0;color:var(--dsw-alias-label-secondary,#666);font-size:11px;line-height:16px}",
709
- ".sm-filterBar{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap}.sm-resultSummary{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary,#888)}.sm-resetFilters{padding:2px 0;border:0;background:none;color:var(--dsw-alias-state-business-primary,#356ae6);font:inherit;cursor:pointer}.sm-resetFilters:hover{text-decoration:underline}.sm-workspaceNotice{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--dsw-alias-label-secondary,#666)}",
792
+ ".sm-queryInput,.sm-viewSelect{box-sizing:border-box;width:100%;min-width:0;height:32px;padding:5px 9px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);font:inherit;font-size:12px;line-height:20px;transition:border-color .15s ease,box-shadow .15s ease}",
793
+ ".sm-viewSelect,.sm-settingsSelect,.sm-wsSortSelect,.sm-prioritySelectInline,.sm-panelDialog select,.sm-nativeDialog select,.sm-settingsCard select{box-sizing:border-box!important;appearance:none;-webkit-appearance:none;-moz-appearance:none;border:1px solid var(--dsw-alias-border-l2,#ddd)!important;border-radius:8px!important;background-color:var(--dsw-alias-bg-layer-2,#fff)!important;color:var(--dsw-alias-label-primary,#111)!important;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\")!important;background-repeat:no-repeat!important;background-position:right 8px center!important;background-size:10px 10px!important;padding-right:26px!important;cursor:pointer!important;outline:none!important;font:inherit;transition:border-color .15s ease,box-shadow .15s ease!important}",
794
+ ".sm-viewSelect:hover:not(:disabled),.sm-settingsSelect:hover:not(:disabled),.sm-wsSortSelect:hover:not(:disabled),.sm-prioritySelectInline:hover:not(:disabled),.sm-panelDialog select:hover:not(:disabled),.sm-nativeDialog select:hover:not(:disabled),.sm-settingsCard select:hover:not(:disabled){border-color:var(--dsw-alias-border-l1,#aaa)!important}",
795
+ ".sm-queryInput::placeholder{color:var(--dsw-alias-label-tertiary,#888)}.sm-queryInput:focus-visible,.sm-viewSelect:focus-visible,.sm-settingsSelect:focus-visible,.sm-wsSortSelect:focus-visible,.sm-prioritySelectInline:focus-visible,.sm-panelDialog select:focus-visible,.sm-nativeDialog select:focus-visible,.sm-settingsCard select:focus-visible,.sm-resetFilters:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#356ae6)!important;outline-offset:1px!important}.sm-viewSelect:disabled,.sm-settingsSelect:disabled,.sm-wsSortSelect:disabled,.sm-prioritySelectInline:disabled,.sm-panelDialog select:disabled,.sm-nativeDialog select:disabled,.sm-settingsCard select:disabled{opacity:.5!important;cursor:not-allowed!important}",
796
+ ".sm-selectExpanded{border-color:var(--dsw-alias-state-business-primary,#356ae6)!important;box-shadow:0 0 0 1px var(--dsw-alias-state-business-primary,#356ae6)!important;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23356ae6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E\")!important}",
797
+ ".sm-customSelectMenu{position:fixed;z-index:100030;box-sizing:border-box;min-width:120px;max-height:260px;overflow-y:auto;overflow-x:hidden;padding:4px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2,#fff));border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;box-shadow:none!important;font-family:inherit;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary,#111);user-select:none;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l1,var(--dsw-alias-border-l1,rgba(128,128,128,.3))) transparent}.sm-customSelectMenu-dropUp{box-shadow:none!important}.sm-customSelectOption{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px;border-radius:6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary,#111);cursor:pointer;white-space:nowrap;user-select:none;transition:background-color .1s ease,color .1s ease}.sm-customSelectOption:hover:not(.sm-customSelectOptionDisabled){background-color:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.05))}.sm-customSelectOptionSelected{background-color:var(--dsw-alias-interactive-bg-active,rgba(53,106,230,.08));color:var(--dsw-alias-state-business-primary,#356ae6);font-weight:500}.sm-customSelectOptionDisabled{opacity:.45;cursor:not-allowed;color:var(--dsw-alias-label-tertiary,#888)!important}.sm-customSelectOptionLabel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 auto}.sm-customSelectOptionCheck{font-size:11px;font-weight:bold;color:var(--dsw-alias-state-business-primary,#356ae6);margin-left:6px;flex-shrink:0}",
798
+ ".sm-wsSortSelect,.sm-prioritySelectInline,.sm-panelSelects .sm-viewSelect{pointer-events:none!important}",
799
+ ".sm-wsSortField,.sm-annotationPriority,.sm-viewField,.sm-moveSection,.sm-settingsRow{cursor:pointer}",
800
+ ".sm-panelSelects{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.sm-panelSelects .sm-viewField>span{display:none}.sm-panelSelects .sm-viewField .sm-viewSelect{font-size:11px;padding:4px 24px 4px 8px;height:28px;line-height:18px;background-position:right 6px center}.sm-viewField{display:flex;flex-direction:column;gap:3px;min-width:0;color:var(--dsw-alias-label-secondary,#666);font-size:11px;line-height:16px}.sm-wsSortField{display:inline-flex;margin:0;vertical-align:middle}.sm-wsSortSelect{height:28px;font-size:11px;padding:3px 24px 3px 8px;width:auto;min-width:120px;border-radius:8px;line-height:18px;background-position:right 6px center;cursor:pointer}",
801
+ ".sm-filterBar{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap}.sm-resultSummary{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;height:20px;min-height:20px;max-height:20px;line-height:20px;font-size:11px;color:var(--dsw-alias-label-tertiary,#888);box-sizing:border-box}.sm-resetFilters{padding:0 4px;height:20px;line-height:20px;border:0;background:none;color:var(--dsw-alias-state-business-primary,#356ae6);font:inherit;font-size:11px;cursor:pointer;display:inline-flex;align-items:center;white-space:nowrap;border-radius:4px;box-sizing:border-box}.sm-resetFilters:hover{text-decoration:underline}.sm-workspaceNotice{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--dsw-alias-label-secondary,#666)}",
710
802
  "@media(max-width:540px){.sm-panelSelects{grid-template-columns:minmax(0,1fr)}.sm-panelDialog .sm-row{height:auto;min-height:36px;flex-shrink:0;flex-wrap:wrap;padding:6px 8px}.sm-panelDialog .sm-rowMain{flex-basis:100%}.sm-panelDialog .sm-rowActions{width:100%;min-width:0;flex:1 1 100%;justify-content:flex-start}}",
711
- ".sm-panelDialog:not(.sm-annotationSurface){width:680px}.sm-panelDialog .sm-row{flex-shrink:0;padding:5px 8px}.sm-panelDialog .sm-rowMain{flex:1 1 200px;flex-direction:column;gap:4px}.sm-panelDialog .sm-rowActions{max-width:100%}.sm-rowSecondary{display:flex;flex-wrap:nowrap;align-items:center;gap:6px;min-width:0;line-height:18px}.sm-rowBadges{display:flex;align-items:center;gap:5px;min-width:0;flex:1 1 auto;flex-wrap:wrap;font-size:11px;line-height:18px}.sm-rowMeta{color:var(--dsw-alias-label-tertiary,#888);font-size:11px;line-height:18px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:none}.sm-rowAnnotations{display:flex;align-items:center;gap:5px;min-width:0;font-size:10px;line-height:16px}",
803
+ ".sm-panelDialog:not(.sm-annotationSurface){position:fixed;inset:0;margin:auto;transform:none;width:680px;height:560px;max-height:calc(100vh - 32px)}.sm-panelDialog .sm-row{flex-shrink:0;padding:5px 8px}.sm-panelDialog .sm-rowMain{flex:1 1 200px;flex-direction:column;gap:4px}.sm-panelDialog .sm-rowActions{max-width:100%}.sm-rowSecondary{display:flex;flex-wrap:nowrap;align-items:center;gap:6px;min-width:0;line-height:18px}.sm-rowBadges{display:flex;align-items:center;gap:5px;min-width:0;flex:1 1 auto;flex-wrap:wrap;font-size:11px;line-height:18px}.sm-rowMeta{color:var(--dsw-alias-label-tertiary,#888);font-size:11px;line-height:18px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:none}.sm-rowAnnotations{display:flex;align-items:center;gap:5px;min-width:0;font-size:10px;line-height:16px}",
712
804
  // .sm-markIcon.sm-markOn keeps !important because the generic
713
805
  // `.sm-panelDialog .sm-rowActions .sm-rowBtn` colour rule (3 classes)
714
806
  // outranks this 2-class selector; it overrides the plugin's own rule,
@@ -730,7 +822,7 @@ function isTopmostDialog(z) {
730
822
  // 1000..1100 gap -- the panel at 1020 and this overlay root at 1050 --
731
823
  // and everything portaled into this root is relative to its context.
732
824
  "#dsh-session-manager-overlay-root{position:fixed!important;inset:0!important;width:100%!important;height:100%!important;z-index:1050!important;pointer-events:none!important;overflow:visible!important}.sm-annotationDialog.sm-nativeDialogLayer{position:fixed;display:block;pointer-events:none;z-index:100002;background:transparent}.sm-annotationDialog .sm-nativeDialogBackdrop{display:none}.sm-annotationDialog.sm-annotationDialog-anchored.sm-nativeDialogLayer,.sm-confirmDialog.sm-confirmDialog-anchored.sm-nativeDialogLayer,.sm-bulkDialog.sm-bulkDialog-anchored.sm-nativeDialogLayer{inset:auto;background:transparent}.sm-annotationDialog.sm-confirmDialog.sm-nativeDialogLayer:not(.sm-annotationDialog-anchored){inset:50% auto auto calc(50vw + 308px);transform:translateY(-50%);max-height:calc(100vh - 32px)}.sm-panelDialog.sm-annotationSurface{position:absolute;width:360px;max-height:min(680px,calc(100vh - 32px));pointer-events:auto;z-index:100003;box-shadow:0 16px 48px rgba(0,0,0,.25)}.sm-panelDialog.sm-annotationSurface.sm-annotationSurface-anchored{position:relative;transform:none;left:auto;top:auto;margin:0}.sm-annotationCloseHint{margin:0 16px 8px;font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary)}",
733
- ".sm-annotationBody{padding:14px 16px;display:flex;flex-direction:column;gap:12px;min-height:0;overflow:auto;flex:1 1 auto}.sm-annotationTarget{font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary,#666)}.sm-annotationChecks{display:grid;grid-template-columns:auto 1fr;column-gap:14px;row-gap:4px;align-items:center;font-size:13px}.sm-annotationChecks>label{display:flex;gap:6px;align-items:center;cursor:pointer}.sm-annotationChecks .sm-annotationPriority{display:inline-flex;align-items:center;gap:6px;font-size:13px;line-height:18px;color:inherit}.sm-annotationChecks .sm-prioritySelectInline{height:24px;padding:2px 6px;font-size:12px;line-height:18px;min-width:104px;width:auto;border-radius:6px;color:var(--dsw-alias-label-primary,#111)}.sm-annotationChecks>small{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary,#888);justify-self:start}.sm-annotationHint,.sm-annotationBody small{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary,#888)}",
825
+ ".sm-annotationBody{padding:14px 16px;display:flex;flex-direction:column;gap:12px;min-height:0;overflow:auto;flex:1 1 auto}.sm-annotationTarget{font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary,#666)}.sm-annotationChecks{display:grid;grid-template-columns:auto 1fr;column-gap:14px;row-gap:4px;align-items:center;font-size:13px}.sm-annotationChecks>label{display:flex;gap:6px;align-items:center;cursor:pointer}.sm-annotationChecks .sm-annotationPriority{display:inline-flex;align-items:center;gap:6px;font-size:13px;line-height:18px;color:inherit}.sm-annotationChecks .sm-prioritySelectInline{height:26px;padding:2px 24px 2px 8px;font-size:12px;line-height:18px;min-width:104px;width:auto;border-radius:8px!important;background-position:right 6px center!important;color:var(--dsw-alias-label-primary,#111)}.sm-annotationChecks>small{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary,#888);justify-self:start}.sm-annotationHint,.sm-annotationBody small{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary,#888)}",
734
826
  ".sm-noteInput{box-sizing:border-box;width:100%;min-height:60px;resize:vertical;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:7px;padding:8px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#111);font:inherit;font-size:13px;line-height:19px}.sm-noteInput:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#356ae6);outline-offset:2px}.sm-markConflict{display:flex;flex-direction:column;gap:5px;font-size:12px;padding:8px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:6px}.sm-fieldWithClear .sm-fieldRow{position:relative;display:flex;align-items:flex-start;gap:4px}.sm-fieldRow .sm-queryInput{flex:1 1 auto;min-width:0}.sm-fieldRowNote{align-items:stretch}.sm-fieldClear{position:absolute;top:5px;right:6px;width:22px;height:22px;border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;border-radius:4px;font-size:14px;line-height:18px;display:inline-flex;align-items:center;justify-content:center;padding:0}.sm-fieldClear:hover,.sm-fieldClear:focus-visible{color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover);outline:none}.sm-fieldClearNote{top:6px}.sm-importGroup{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-top:1px solid var(--dsw-alias-border-l2,#eee)}.sm-importGroupHeader{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:20px}.sm-importLabel{color:var(--dsw-alias-label-secondary,#666);font-size:11px;line-height:16px}.sm-importGroupButtons{display:flex;align-items:center;gap:6px;flex:none}.sm-importBtn{cursor:pointer;color:var(--dsw-alias-label-primary,#111);background:transparent;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;text-align:center}.sm-importBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.sm-importBtn:disabled{opacity:.5;cursor:not-allowed}.sm-importStatus{margin:0;padding:8px 10px;font-size:12px;line-height:18px;background:var(--dsw-alias-state-business-tertiary,rgba(53,106,230,.08));color:var(--dsw-alias-label-secondary);border-radius:6px;white-space:pre-wrap;word-break:break-word}",
735
827
  ".sm-bulkBar{box-sizing:border-box;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));align-items:stretch;gap:6px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:10px;background:var(--dsw-alias-bg-layer-2,#fff)}.sm-bulkBar .sm-bulkSummary{grid-column:1/-1;color:var(--dsw-alias-label-primary,#111);font-size:12px;line-height:18px;font-weight:500;margin:0 0 2px}",
736
828
  ".sm-bulkSummary{color:var(--dsw-alias-label-primary,#111);font-size:12px;line-height:18px;font-weight:500}",
@@ -746,7 +838,7 @@ function isTopmostDialog(z) {
746
838
  ".sm-bulkRowCheckbox input{width:14px;height:14px;cursor:pointer;margin:0}",
747
839
  ".sm-bulkRowCheckbox input:disabled{cursor:not-allowed}",
748
840
  ".sm-rowBulkSelected{border-color:var(--dsw-alias-state-business-primary,#356ae6);background:var(--dsw-alias-state-business-tertiary,rgba(53,106,230,.06))}",
749
- ".sm-bulkDialog.sm-nativeDialogLayer{position:fixed;left:calc(50vw + 184px);top:calc(50vh - 90px);width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:calc(50vh - 90px) auto auto calc(50vw + 308px);z-index:10002}.sm-bulkDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-bulkDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:auto;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:flex;flex-direction:column;box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);padding:0;overflow:hidden;animation:sm-confirmPop .14s ease-out}.sm-bulkDialog .sm-nativeDialogHeader{padding:10px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-bulkDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-bulkDialog .sm-nativeDialogBody{padding:12px 16px;display:flex;flex-direction:column;gap:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111);min-height:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-bulkDialog .sm-nativeDialogFooter{padding:10px 16px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:6px}.sm-bulkDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-bulkDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-bulkDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-bulkDialog .sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-bulkDialog .sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-bulkDialog .sm-nativeDialog select.sm-viewSelect{font-size:13px;line-height:20px;height:32px;padding:5px 9px}",
841
+ ".sm-bulkDialog.sm-nativeDialogLayer{position:fixed;left:calc(50vw + 184px);top:calc(50vh - 90px);width:360px;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:block;align-items:initial;justify-content:initial;box-sizing:border-box;background:transparent;border:0;box-shadow:none;padding:0;inset:calc(50vh - 90px) auto auto calc(50vw + 308px);z-index:10002}.sm-bulkDialog.sm-nativeDialogLayer .sm-nativeDialogBackdrop{display:none}.sm-bulkDialog.sm-nativeDialogLayer .sm-nativeDialog{position:relative;left:auto;top:auto;transform:none;width:auto;max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);display:flex;flex-direction:column;box-sizing:border-box;background:var(--sm-dialog-fill);color:var(--dsw-alias-label-primary,#111);border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);padding:0;overflow:hidden;animation:sm-confirmPop .14s ease-out}.sm-bulkDialog .sm-nativeDialogHeader{padding:10px 16px;border-bottom:1px solid var(--dsw-alias-border-l2,#eee);flex:none;position:relative;display:flex;align-items:center;justify-content:center;min-height:44px;box-sizing:border-box}.sm-bulkDialog .sm-nativeDialogTitle{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:14px;line-height:20px;font-weight:600;text-align:center;width:auto;max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sm-bulkDialog .sm-nativeDialogBody{padding:12px 16px;display:flex;flex-direction:column;gap:10px;font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111);min-height:0;max-height:calc(100vh - 120px);overflow-y:auto}.sm-bulkDialog .sm-nativeDialogFooter{padding:10px 16px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:6px}.sm-bulkDialog .sm-nativeDialogButton{min-height:28px;padding:3px 14px;font-size:12px;line-height:20px;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;cursor:pointer;background:transparent;color:var(--dsw-alias-label-primary,#111);text-align:center}.sm-bulkDialog .sm-nativeDialogConfirm{background:var(--dsw-alias-state-business-primary,#356ae6);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-business-primary,#356ae6)}.sm-bulkDialog .sm-nativeDialogConfirm:hover:not(:disabled){filter:brightness(.94)}.sm-bulkDialog .sm-nativeDialogDanger{background:var(--dsw-alias-state-error-primary,#d92d20);color:var(--dsw-alias-label-primary-foreground,#fff);border-color:var(--dsw-alias-state-error-primary,#d92d20)}.sm-bulkDialog .sm-nativeDialogDanger:hover:not(:disabled){filter:brightness(.92)}.sm-bulkDialog .sm-nativeDialog select.sm-viewSelect{font-size:13px;line-height:20px;height:32px;padding:5px 26px 5px 10px}",
750
842
  ".sm-bulkDialog .sm-nativeDialog{width:100%;max-height:min(640px,calc(100vh - 32px))}",
751
843
  ".sm-bulkDialogBody{display:flex;flex-direction:column;gap:12px;min-height:0}",
752
844
  ".sm-bulkDialogSummary{font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary,#111)}",
@@ -772,6 +864,28 @@ function isTopmostDialog(z) {
772
864
  ".sm-overlayLayer{position:fixed;inset:0;pointer-events:none}",
773
865
  ".sm-overlayLayer>*{pointer-events:auto}",
774
866
  ".sm-overlayBackdrop{position:fixed;inset:0;background:transparent;pointer-events:auto}",
867
+ ".sm-panelNav{display:inline-flex;align-items:center;background:var(--dsw-alias-bg-layer-2,rgba(128,128,128,0.12));border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;padding:2px;gap:2px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:0}",
868
+ ".sm-panelNavTab{border:0;background:transparent;color:var(--dsw-alias-label-secondary,#666);font-size:13px;line-height:20px;font-weight:500;padding:2px 14px;border-radius:6px;cursor:pointer;transition:all .15s ease;white-space:nowrap;outline:none}",
869
+ ".sm-panelNavTab:hover:not(:disabled){color:var(--dsw-alias-label-primary,#111)}",
870
+ ".sm-panelNavTab.sm-on{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#111);box-shadow:0 1px 3px rgba(0,0,0,0.12),0 1px 2px rgba(0,0,0,0.06);font-weight:600}",
871
+ ".sm-switch{position:relative;width:38px;height:22px;flex:0 0 38px;min-width:38px;min-height:22px;max-width:38px;max-height:22px;padding:0;border-radius:11px;border:1px solid var(--dsw-alias-border-l2,#ddd);background:var(--dsw-alias-bg-layer-2,rgba(128,128,128,0.25));cursor:pointer;transition:background .2s cubic-bezier(0.4,0,0.2,1),border-color .2s cubic-bezier(0.4,0,0.2,1);box-sizing:border-box;display:inline-flex;align-items:center;overflow:hidden}",
872
+ ".sm-switch:hover:not(:disabled){border-color:var(--dsw-alias-border-l1,#bbb)}",
873
+ ".sm-switch.sm-switchChecked{background:var(--dsw-alias-state-business-primary,#356ae6);border-color:var(--dsw-alias-state-business-primary,#356ae6)}",
874
+ ".sm-switch:disabled{opacity:0.4;cursor:not-allowed}",
875
+ ".sm-switchThumb{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-switch-thumb,#ffffff);transition:left 0.2s cubic-bezier(0.4,0,0.2,1);box-shadow:0 1px 3px rgba(0,0,0,0.22);display:flex;align-items:center;justify-content:center}",
876
+ ".sm-switchChecked .sm-switchThumb{left:18px}",
877
+ ".sm-switchSpinner{width:10px;height:10px;border:1.5px solid transparent;border-top-color:var(--dsw-alias-state-business-primary,#356ae6);border-radius:50%;animation:sm-spin 0.7s linear infinite}",
878
+ ".sm-rowArchived{opacity:0.72}",
879
+ ".sm-workspaceRowActions{display:flex;align-items:center;justify-content:flex-end;flex:0 0 44px;min-width:44px;max-width:44px}",
880
+ ".sm-workspaceRow .sm-rowMeta{display:block!important}",
881
+ ".sm-wsFilters{display:flex;flex-wrap:wrap;align-items:center;gap:6px;width:100%;min-width:0;box-sizing:border-box}",
882
+ ".sm-wsFilters .sm-markFiltersGroup{display:flex;flex-wrap:wrap;align-items:center;gap:6px}",
883
+ ".sm-wsFilters .sm-markFiltersSpacer{flex:1 1 auto;min-width:8px}",
884
+ ".sm-wsFilters .sm-wsSortSelect{height:28px;min-height:28px;font-size:11px;padding:3px 24px 3px 8px;line-height:18px;width:auto;min-width:120px;border-radius:8px;box-sizing:border-box;background-position:right 6px center;cursor:pointer}",
885
+ ".sm-wsSortSelect-en{min-width:138px}",
886
+ ".sm-wsFiltersBulk{display:flex;flex-wrap:wrap;align-items:center;gap:6px}",
887
+ "@media(max-width:720px){.sm-wsFilters .sm-markFiltersSpacer{display:none}.sm-wsFilters .sm-wsFiltersBulk{width:100%}}",
888
+ ".sm-visuallyHidden{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}",
775
889
  "@media(max-width:720px){.sm-panelSelects{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.sm-panelDialog .sm-row{flex-wrap:wrap}.sm-panelDialog .sm-rowMain{flex-basis:100%}.sm-panelDialog .sm-rowActions{width:100%;min-width:0;flex:1 1 100%;justify-content:flex-start}}@media(max-width:540px){.sm-panelSelects{grid-template-columns:minmax(0,1fr)}}",
776
890
  ].join("");
777
891
 
@@ -1368,6 +1482,885 @@ function isTopmostDialog(z) {
1368
1482
  return { sessionId, status: "success", via: "endpoint" };
1369
1483
  }
1370
1484
 
1485
+ const WORKSPACE_ARCHIVE_STORAGE_KEY = "dsh-session-manager-workspace-archive-v1";
1486
+ const WORKSPACE_ARCHIVE_LEGACY_KEY = "dsh-workspace-hide.hidden.v2";
1487
+ const WORKSPACE_MODEL_MARK = "__dshSmWorkspaceModel";
1488
+ const WORKSPACE_CREATE_MARK = "__dshSmWorkspaceCreate";
1489
+ const WORKSPACE_ORIGINAL_CREATE = "__dshSmWorkspaceOrigCreate";
1490
+ const UI_CONNECT_MARK = "__dshSmUiConnect";
1491
+ const UI_ORIGINAL_CONNECT = "__dshSmUiOrigConnect";
1492
+
1493
+ const pathKey = (value) => {
1494
+ if (typeof value !== "string" || value === "") return "";
1495
+ const path = value.replace(/\\/g, "/").replace(/\/+$/, "") || "/";
1496
+ return /^[a-z]:(?:\/|$)/i.test(path) || path.startsWith("//") ? path.toLowerCase() : path;
1497
+ };
1498
+
1499
+ const workspaceArchiveStore = (() => {
1500
+ const archives = new Map();
1501
+ const busyWorkspaces = new Set();
1502
+ const listeners = new Set();
1503
+ let version = 0;
1504
+ let readRaw = null;
1505
+ let viewCache = null;
1506
+ let viewRaw = null;
1507
+ let viewVersion = -1;
1508
+
1509
+ const isId = v => typeof v === "string" && v !== "";
1510
+
1511
+ function loadLocal() {
1512
+ try {
1513
+ if (typeof localStorage === "undefined") return;
1514
+ const text = localStorage.getItem(WORKSPACE_ARCHIVE_STORAGE_KEY);
1515
+ if (text) {
1516
+ const parsed = JSON.parse(text);
1517
+ if (parsed && typeof parsed.archives === "object" && !Array.isArray(parsed.archives)) {
1518
+ for (const [wsId, rec] of Object.entries(parsed.archives)) {
1519
+ if (!isId(wsId) || !rec) continue;
1520
+ archives.set(wsId, {
1521
+ workspaceId: wsId,
1522
+ archived: rec.archived === true,
1523
+ archivedAt: typeof rec.archivedAt === "number" ? rec.archivedAt : Date.now(),
1524
+ sessionIds: Array.isArray(rec.sessionIds) ? rec.sessionIds.filter(isId) : [],
1525
+ pending: Array.isArray(rec.pending) ? rec.pending.filter(isId) : []
1526
+ });
1527
+ }
1528
+ return;
1529
+ }
1530
+ }
1531
+ const legacy = localStorage.getItem(WORKSPACE_ARCHIVE_LEGACY_KEY);
1532
+ if (legacy) {
1533
+ const parsed = JSON.parse(legacy);
1534
+ if (parsed && typeof parsed.hidden === "object" && !Array.isArray(parsed.hidden)) {
1535
+ for (const [wsId, ids] of Object.entries(parsed.hidden)) {
1536
+ if (!isId(wsId)) continue;
1537
+ archives.set(wsId, {
1538
+ workspaceId: wsId,
1539
+ archived: true,
1540
+ archivedAt: Date.now(),
1541
+ sessionIds: Array.isArray(ids) ? ids.filter(isId) : [],
1542
+ pending: []
1543
+ });
1544
+ }
1545
+ saveLocal();
1546
+ }
1547
+ }
1548
+ } catch (_) {}
1549
+ }
1550
+
1551
+ function saveLocal() {
1552
+ try {
1553
+ if (typeof localStorage === "undefined") return;
1554
+ const obj = {};
1555
+ for (const [wsId, rec] of archives) {
1556
+ if (rec.archived === true || (Array.isArray(rec.pending) && rec.pending.length > 0) || (Array.isArray(rec.sessionIds) && rec.sessionIds.length > 0)) {
1557
+ obj[wsId] = {
1558
+ workspaceId: wsId,
1559
+ archived: rec.archived === true,
1560
+ archivedAt: rec.archivedAt,
1561
+ sessionIds: rec.sessionIds,
1562
+ pending: rec.pending
1563
+ };
1564
+ }
1565
+ }
1566
+ localStorage.setItem(WORKSPACE_ARCHIVE_STORAGE_KEY, JSON.stringify({ version: 1, archives: obj }));
1567
+ } catch (_) {}
1568
+ }
1569
+
1570
+ const EMPTY_WORKSPACES_SNAPSHOT = Object.freeze({ items: Object.freeze([]) });
1571
+ let snapshotCache = { archives, version, busyWorkspaces };
1572
+
1573
+ loadLocal();
1574
+
1575
+ function notify() {
1576
+ version += 1;
1577
+ snapshotCache = { archives, version, busyWorkspaces };
1578
+ viewCache = null;
1579
+ viewRaw = null;
1580
+ viewVersion = -1;
1581
+ for (const listener of [...listeners]) {
1582
+ try { listener(); } catch (_) {}
1583
+ }
1584
+ }
1585
+
1586
+ function rawSnapshot() {
1587
+ if (typeof readRaw === "function") {
1588
+ try { return readRaw() ?? EMPTY_WORKSPACES_SNAPSHOT; } catch (_) {}
1589
+ }
1590
+ return EMPTY_WORKSPACES_SNAPSHOT;
1591
+ }
1592
+
1593
+ function getViewSnapshot() {
1594
+ const raw = rawSnapshot();
1595
+ if (viewCache !== null && viewRaw === raw && viewVersion === version) {
1596
+ return viewCache;
1597
+ }
1598
+ viewRaw = raw;
1599
+ viewVersion = version;
1600
+
1601
+ const items = Array.isArray(raw?.items) ? raw.items : [];
1602
+ const baseArchived = Array.isArray(raw?.archivedSessionIds) ? raw.archivedSessionIds : [];
1603
+
1604
+ const hasArchived = [...archives.values()].some(r => r.archived === true);
1605
+ if (!hasArchived) {
1606
+ viewCache = raw;
1607
+ return viewCache;
1608
+ }
1609
+
1610
+ const visible = items.filter(item => {
1611
+ const rec = archives.get(item.workspaceId || item.id);
1612
+ return !rec || rec.archived !== true;
1613
+ });
1614
+
1615
+ const archivedSet = new Set(baseArchived);
1616
+ let changed = false;
1617
+
1618
+ for (const item of items) {
1619
+ const wsId = item.workspaceId || item.id;
1620
+ const rec = archives.get(wsId);
1621
+ if (rec && rec.archived === true) {
1622
+ const sids = Array.isArray(item.sessionIds) ? item.sessionIds : [];
1623
+ for (const sid of sids) {
1624
+ if (!archivedSet.has(sid)) {
1625
+ archivedSet.add(sid);
1626
+ changed = true;
1627
+ }
1628
+ }
1629
+ }
1630
+ }
1631
+ for (const rec of archives.values()) {
1632
+ if (rec.archived === true && Array.isArray(rec.sessionIds)) {
1633
+ for (const sid of rec.sessionIds) {
1634
+ if (!archivedSet.has(sid)) {
1635
+ archivedSet.add(sid);
1636
+ changed = true;
1637
+ }
1638
+ }
1639
+ }
1640
+ }
1641
+
1642
+ const finalArchived = changed ? [...archivedSet] : baseArchived;
1643
+ viewCache = (visible.length === items.length && finalArchived === baseArchived)
1644
+ ? raw
1645
+ : { ...raw, items: visible, archivedSessionIds: finalArchived };
1646
+ return viewCache;
1647
+ }
1648
+
1649
+ function revealWorkspace(wsId, options = {}) {
1650
+ if (!isId(wsId)) return null;
1651
+ const existing = archives.get(wsId);
1652
+ if (!existing || existing.archived !== true) return null;
1653
+ const record = {
1654
+ ...existing,
1655
+ workspaceId: wsId,
1656
+ archived: false,
1657
+ sessionIds: Array.isArray(existing.sessionIds) ? [...existing.sessionIds] : [],
1658
+ pending: Array.isArray(existing.pending) ? [...existing.pending] : []
1659
+ };
1660
+ archives.set(wsId, record);
1661
+ saveLocal();
1662
+ notify();
1663
+ try {
1664
+ callApi("/workspace-unarchive", { workspaceId: wsId, retainSessionIds: true }).catch(() => {});
1665
+ } catch (_) {}
1666
+ if (options && options.silent === false) {
1667
+ const msg = smTranslate("notice.workspaceReAdded");
1668
+ showNotice(msg);
1669
+ }
1670
+ return record;
1671
+ }
1672
+
1673
+ function installWorkspaceCreate(workspacesService) {
1674
+ if (!workspacesService || typeof workspacesService.create !== "function") return null;
1675
+
1676
+ let originalCreate = workspacesService[WORKSPACE_ORIGINAL_CREATE] || workspacesService.create;
1677
+ while (originalCreate && (originalCreate.__dshSmWrapper || originalCreate[WORKSPACE_CREATE_MARK])) {
1678
+ if (originalCreate.__dshSmUnderlying) originalCreate = originalCreate.__dshSmUnderlying;
1679
+ else break;
1680
+ }
1681
+ workspacesService[WORKSPACE_ORIGINAL_CREATE] = originalCreate;
1682
+
1683
+ const wrappedCreate = async function (...args) {
1684
+ const options = args[0];
1685
+ const targetPath = typeof options === "string" ? options : (options && typeof options.path === "string" ? options.path : "");
1686
+ let knownArchivedId = null;
1687
+ if (targetPath) {
1688
+ const raw = rawSnapshot();
1689
+ const items = Array.isArray(raw?.items) ? raw.items : [];
1690
+ const match = items.find(item => item.path && pathKey(item.path) === pathKey(targetPath));
1691
+ if (match) {
1692
+ const id = match.workspaceId || match.id;
1693
+ if (id && archives.get(id)?.archived === true) {
1694
+ knownArchivedId = id;
1695
+ revealWorkspace(id, { silent: false });
1696
+ }
1697
+ }
1698
+ }
1699
+
1700
+ const res = await originalCreate.apply(this, args);
1701
+
1702
+ const createdId = typeof res === "string" ? res : (res && (res.id || res.workspaceId));
1703
+ const targetId = createdId || knownArchivedId;
1704
+ if (targetId && archives.get(targetId)?.archived === true) {
1705
+ revealWorkspace(targetId, { silent: false });
1706
+ }
1707
+
1708
+ return res;
1709
+ };
1710
+ wrappedCreate.__dshSmWrapper = true;
1711
+ wrappedCreate.__dshSmUnderlying = originalCreate;
1712
+
1713
+ const ownCreate = Object.getOwnPropertyDescriptor(workspacesService, "create");
1714
+ try {
1715
+ workspacesService.create = wrappedCreate;
1716
+ Object.defineProperty(workspacesService, WORKSPACE_CREATE_MARK, { value: true, configurable: true, writable: true });
1717
+ } catch (err) {
1718
+ console.warn("[session-manager] Failed to wrap workspaces.create:", err);
1719
+ return null;
1720
+ }
1721
+
1722
+ return function dispose() {
1723
+ try {
1724
+ if (workspacesService.create === wrappedCreate) {
1725
+ if (ownCreate !== undefined) Object.defineProperty(workspacesService, "create", ownCreate);
1726
+ else workspacesService.create = originalCreate;
1727
+ }
1728
+ delete workspacesService[WORKSPACE_CREATE_MARK];
1729
+ delete workspacesService[WORKSPACE_ORIGINAL_CREATE];
1730
+ } catch (_) {}
1731
+ };
1732
+ }
1733
+
1734
+ function installConnectWorkspace(uiWorkspaceService) {
1735
+ if (!uiWorkspaceService || typeof uiWorkspaceService.connectWorkspace !== "function") return null;
1736
+
1737
+ let originalConnect = uiWorkspaceService[UI_ORIGINAL_CONNECT] || uiWorkspaceService.connectWorkspace;
1738
+ while (originalConnect && (originalConnect.__dshSmWrapper || originalConnect[UI_CONNECT_MARK])) {
1739
+ if (originalConnect.__dshSmUnderlying) originalConnect = originalConnect.__dshSmUnderlying;
1740
+ else break;
1741
+ }
1742
+ uiWorkspaceService[UI_ORIGINAL_CONNECT] = originalConnect;
1743
+
1744
+ const wrappedConnect = async function (workspaceId, ...rest) {
1745
+ if (typeof workspaceId === "string" && archives.get(workspaceId)?.archived === true) {
1746
+ revealWorkspace(workspaceId, { silent: true });
1747
+ }
1748
+ return await originalConnect.call(this, workspaceId, ...rest);
1749
+ };
1750
+ wrappedConnect.__dshSmWrapper = true;
1751
+ wrappedConnect.__dshSmUnderlying = originalConnect;
1752
+
1753
+ const ownConnect = Object.getOwnPropertyDescriptor(uiWorkspaceService, "connectWorkspace");
1754
+ try {
1755
+ uiWorkspaceService.connectWorkspace = wrappedConnect;
1756
+ Object.defineProperty(uiWorkspaceService, UI_CONNECT_MARK, { value: true, configurable: true, writable: true });
1757
+ } catch (err) {
1758
+ console.warn("[session-manager] Failed to wrap uiWorkspace.connectWorkspace:", err);
1759
+ return null;
1760
+ }
1761
+
1762
+ return function dispose() {
1763
+ try {
1764
+ if (uiWorkspaceService.connectWorkspace === wrappedConnect) {
1765
+ if (ownConnect !== undefined) Object.defineProperty(uiWorkspaceService, "connectWorkspace", ownConnect);
1766
+ else uiWorkspaceService.connectWorkspace = originalConnect;
1767
+ }
1768
+ delete uiWorkspaceService[UI_CONNECT_MARK];
1769
+ delete uiWorkspaceService[UI_ORIGINAL_CONNECT];
1770
+ } catch (_) {}
1771
+ };
1772
+ }
1773
+
1774
+ return {
1775
+ getSnapshot: () => snapshotCache,
1776
+ getVersion: () => version,
1777
+ subscribe(listener) {
1778
+ listeners.add(listener);
1779
+ return () => listeners.delete(listener);
1780
+ },
1781
+ isArchived(wsId) {
1782
+ const rec = archives.get(wsId);
1783
+ return rec ? rec.archived === true : false;
1784
+ },
1785
+ isBusy(wsId) {
1786
+ return busyWorkspaces.has(wsId);
1787
+ },
1788
+ getRecord(wsId) {
1789
+ return archives.get(wsId) || null;
1790
+ },
1791
+ getAllRecords() {
1792
+ return archives;
1793
+ },
1794
+ rawSnapshot,
1795
+ getViewSnapshot,
1796
+ setReadRaw(fn) {
1797
+ readRaw = fn;
1798
+ },
1799
+ notify,
1800
+ syncFromHost(hostArchives) {
1801
+ if (!hostArchives || typeof hostArchives !== "object" || Array.isArray(hostArchives)) return;
1802
+ let changed = false;
1803
+ for (const [wsId, rec] of Object.entries(hostArchives)) {
1804
+ if (!isId(wsId) || !rec) continue;
1805
+ const existing = archives.get(wsId);
1806
+ if (!existing || existing.archived !== (rec.archived === true) || existing.sessionIds?.length !== (rec.sessionIds || []).length) {
1807
+ archives.set(wsId, {
1808
+ workspaceId: wsId,
1809
+ archived: rec.archived === true,
1810
+ archivedAt: typeof rec.archivedAt === "number" ? rec.archivedAt : Date.now(),
1811
+ sessionIds: Array.isArray(rec.sessionIds) ? rec.sessionIds.filter(isId) : [],
1812
+ pending: Array.isArray(rec.pending) ? rec.pending.filter(isId) : []
1813
+ });
1814
+ changed = true;
1815
+ }
1816
+ }
1817
+ if (changed) {
1818
+ saveLocal();
1819
+ notify();
1820
+ }
1821
+ },
1822
+ markBusy(wsId, busy) {
1823
+ if (busy) busyWorkspaces.add(wsId);
1824
+ else busyWorkspaces.delete(wsId);
1825
+ notify();
1826
+ },
1827
+ saveArchiveRecord(wsId, record) {
1828
+ archives.set(wsId, record);
1829
+ saveLocal();
1830
+ notify();
1831
+ },
1832
+ removeArchiveRecord(wsId) {
1833
+ archives.delete(wsId);
1834
+ saveLocal();
1835
+ notify();
1836
+ },
1837
+ revealWorkspace,
1838
+ installWorkspaceCreate,
1839
+ installConnectWorkspace,
1840
+ installWorkspaceModel(model) {
1841
+ if (!model || model[WORKSPACE_MODEL_MARK] === true) return null;
1842
+ const originalGetSnapshot = model.getSnapshot;
1843
+ const originalSubscribe = model.subscribe;
1844
+ if (typeof originalGetSnapshot !== "function" || typeof originalSubscribe !== "function") return null;
1845
+
1846
+ readRaw = () => {
1847
+ try { return originalGetSnapshot.call(model); }
1848
+ catch (err) { console.warn("[session-manager] Failed to read raw workspaces snapshot:", err); return { items: [] }; }
1849
+ };
1850
+
1851
+ const wrappedGetSnapshot = function () {
1852
+ return getViewSnapshot();
1853
+ };
1854
+ const wrappedSubscribe = function (listener) {
1855
+ const off = originalSubscribe.call(model, listener);
1856
+ listeners.add(listener);
1857
+ return () => {
1858
+ listeners.delete(listener);
1859
+ if (typeof off === "function") off();
1860
+ };
1861
+ };
1862
+
1863
+ const ownGetSnapshot = Object.getOwnPropertyDescriptor(model, "getSnapshot");
1864
+ const ownSubscribe = Object.getOwnPropertyDescriptor(model, "subscribe");
1865
+
1866
+ try {
1867
+ model.getSnapshot = wrappedGetSnapshot;
1868
+ model.subscribe = wrappedSubscribe;
1869
+ Object.defineProperty(model, WORKSPACE_MODEL_MARK, { value: true, configurable: true });
1870
+ } catch (err) {
1871
+ console.warn("[session-manager] Failed to wrap workspaces.list:", err);
1872
+ return null;
1873
+ }
1874
+
1875
+ return function dispose() {
1876
+ try {
1877
+ if (model.getSnapshot === wrappedGetSnapshot) {
1878
+ if (ownGetSnapshot !== undefined) Object.defineProperty(model, "getSnapshot", ownGetSnapshot);
1879
+ else delete model.getSnapshot;
1880
+ }
1881
+ if (model.subscribe === wrappedSubscribe) {
1882
+ if (ownSubscribe !== undefined) Object.defineProperty(model, "subscribe", ownSubscribe);
1883
+ else delete model.subscribe;
1884
+ }
1885
+ if (model[WORKSPACE_MODEL_MARK] === true) delete model[WORKSPACE_MODEL_MARK];
1886
+ } catch (_) {}
1887
+ listeners.clear();
1888
+ viewCache = null;
1889
+ viewRaw = null;
1890
+ viewVersion = -1;
1891
+ };
1892
+ }
1893
+ };
1894
+ })();
1895
+
1896
+ if (typeof window !== "undefined") {
1897
+ window.revealWorkspace = (id, opts) => workspaceArchiveStore.revealWorkspace(id, opts);
1898
+ }
1899
+ if (typeof globalThis !== "undefined") {
1900
+ globalThis.revealWorkspace = (id, opts) => workspaceArchiveStore.revealWorkspace(id, opts);
1901
+ }
1902
+
1903
+ const SM_SELECT_SELECTOR = ".sm-viewSelect, .sm-settingsSelect, .sm-wsSortSelect, .sm-prioritySelectInline, .sm-panelDialog select, .sm-nativeDialog select, .sm-settingsCard select";
1904
+
1905
+ let activeCustomSelect = null;
1906
+ let activeCustomMenu = null;
1907
+
1908
+ function closeCustomSelect() {
1909
+ if (activeCustomMenu) {
1910
+ try { activeCustomMenu.remove(); } catch (_) {}
1911
+ activeCustomMenu = null;
1912
+ }
1913
+ if (typeof document !== "undefined") {
1914
+ try {
1915
+ const oldMenus = document.querySelectorAll(".sm-customSelectMenu");
1916
+ for (let i = 0; i < oldMenus.length; i++) {
1917
+ try { oldMenus[i].remove(); } catch (_) {}
1918
+ }
1919
+ } catch (_) {}
1920
+ }
1921
+ if (activeCustomSelect) {
1922
+ try { activeCustomSelect.classList.remove("sm-selectExpanded"); } catch (_) {}
1923
+ activeCustomSelect = null;
1924
+ }
1925
+ }
1926
+
1927
+ function applyCustomSelection(select, val) {
1928
+ closeCustomSelect();
1929
+ if (!select) return;
1930
+ if (select.value !== val) {
1931
+ try {
1932
+ const descriptor = Object.getOwnPropertyDescriptor(window.HTMLSelectElement?.prototype || {}, "value");
1933
+ if (descriptor && descriptor.set) {
1934
+ descriptor.set.call(select, val);
1935
+ } else {
1936
+ select.value = val;
1937
+ }
1938
+ } catch (_) {
1939
+ select.value = val;
1940
+ }
1941
+ try {
1942
+ const Evt = typeof Event !== "undefined" ? Event : (typeof window !== "undefined" ? window.Event : null);
1943
+ if (Evt) {
1944
+ select.dispatchEvent(new Evt("input", { bubbles: true }));
1945
+ select.dispatchEvent(new Evt("change", { bubbles: true }));
1946
+ } else if (typeof select.dispatchEvent === "function") {
1947
+ select.dispatchEvent({ type: "input", bubbles: true });
1948
+ select.dispatchEvent({ type: "change", bubbles: true });
1949
+ }
1950
+ } catch (_) {
1951
+ try {
1952
+ select.dispatchEvent({ type: "input", bubbles: true });
1953
+ select.dispatchEvent({ type: "change", bubbles: true });
1954
+ } catch (_) {}
1955
+ }
1956
+ try {
1957
+ const key = Object.keys(select).find(k => k.startsWith("__reactProps") || k.startsWith("__reactEventHandlers"));
1958
+ if (key && typeof select[key]?.onChange === "function") {
1959
+ select[key].onChange({ target: select, currentTarget: select });
1960
+ }
1961
+ } catch (_) {}
1962
+ }
1963
+ }
1964
+
1965
+ function openCustomSelect(select) {
1966
+ if (!select || select.disabled) return;
1967
+ if (activeCustomSelect === select && activeCustomMenu) {
1968
+ closeCustomSelect();
1969
+ return;
1970
+ }
1971
+ closeCustomSelect();
1972
+
1973
+ const options = Array.from(select.options || []);
1974
+ if (options.length === 0) return;
1975
+
1976
+ const doc = select.ownerDocument || (typeof document !== "undefined" ? document : null);
1977
+ if (!doc || !doc.body) return;
1978
+
1979
+ activeCustomSelect = select;
1980
+ select.classList.add("sm-selectExpanded");
1981
+
1982
+ const menu = doc.createElement("div");
1983
+ menu.className = "sm-customSelectMenu";
1984
+ menu.setAttribute("role", "listbox");
1985
+ const ariaLabel = select.getAttribute("aria-label");
1986
+ if (ariaLabel) menu.setAttribute("aria-label", ariaLabel);
1987
+
1988
+ try {
1989
+ const theme = doc.documentElement?.getAttribute?.("data-sm-theme") || (doc.body?.getAttribute?.("data-ds-dark-theme") === "true" ? "dark" : null);
1990
+ if (theme && typeof menu.setAttribute === "function") menu.setAttribute("data-sm-theme", theme);
1991
+ const cs = typeof window !== "undefined" && typeof window.getComputedStyle === "function" ? window.getComputedStyle(select) : null;
1992
+ if (cs) {
1993
+ if (cs.colorScheme) menu.style.colorScheme = cs.colorScheme;
1994
+ if (cs.fontFamily) menu.style.fontFamily = cs.fontFamily;
1995
+ }
1996
+ } catch (_) {}
1997
+
1998
+ options.forEach((opt) => {
1999
+ const item = doc.createElement("div");
2000
+ const isSelected = opt.value === select.value || opt.selected;
2001
+ item.className = "sm-customSelectOption" +
2002
+ (isSelected ? " sm-customSelectOptionSelected" : "") +
2003
+ (opt.disabled ? " sm-customSelectOptionDisabled" : "");
2004
+ item.setAttribute("role", "option");
2005
+ item.setAttribute("aria-selected", isSelected ? "true" : "false");
2006
+ item.title = opt.title || opt.text || opt.label || opt.value || "";
2007
+
2008
+ const labelSpan = doc.createElement("span");
2009
+ labelSpan.className = "sm-customSelectOptionLabel";
2010
+ labelSpan.textContent = opt.text || opt.label || opt.value;
2011
+ if (typeof item.appendChild === "function") {
2012
+ item.appendChild(labelSpan);
2013
+ } else if (item.children && Array.isArray(item.children)) {
2014
+ item.children.push(labelSpan);
2015
+ }
2016
+
2017
+ if (isSelected) {
2018
+ const checkSpan = doc.createElement("span");
2019
+ checkSpan.className = "sm-customSelectOptionCheck";
2020
+ checkSpan.textContent = "✓";
2021
+ if (typeof item.appendChild === "function") {
2022
+ item.appendChild(checkSpan);
2023
+ } else if (item.children && Array.isArray(item.children)) {
2024
+ item.children.push(checkSpan);
2025
+ }
2026
+ }
2027
+
2028
+ const handleOptClick = (e) => {
2029
+ if (e && e.preventDefault) e.preventDefault();
2030
+ if (e && e.stopPropagation) e.stopPropagation();
2031
+ if (opt.disabled) return;
2032
+ applyCustomSelection(select, opt.value);
2033
+ };
2034
+ if (typeof item.addEventListener === "function") {
2035
+ item.addEventListener("mousedown", handleOptClick);
2036
+ } else {
2037
+ item.onmousedown = handleOptClick;
2038
+ }
2039
+
2040
+ if (typeof menu.appendChild === "function") {
2041
+ menu.appendChild(item);
2042
+ } else if (menu.children && Array.isArray(menu.children)) {
2043
+ menu.children.push(item);
2044
+ }
2045
+ });
2046
+
2047
+ if (typeof doc.body?.appendChild === "function") {
2048
+ doc.body.appendChild(menu);
2049
+ }
2050
+ activeCustomMenu = menu;
2051
+
2052
+ const rect = select.getBoundingClientRect();
2053
+ const spaceBelow = (typeof window !== "undefined" ? window.innerHeight : 800) - rect.bottom;
2054
+ const spaceAbove = rect.top;
2055
+ const estimatedHeight = Math.min(260, Math.max(36, options.length * 30 + 8));
2056
+ const dropUp = spaceBelow < estimatedHeight && spaceAbove > spaceBelow;
2057
+
2058
+ if (dropUp) {
2059
+ menu.style.bottom = ((typeof window !== "undefined" ? window.innerHeight : 800) - rect.top + 4) + "px";
2060
+ menu.style.top = "auto";
2061
+ menu.classList.add("sm-customSelectMenu-dropUp");
2062
+ } else {
2063
+ menu.style.top = (rect.bottom + 4) + "px";
2064
+ menu.style.bottom = "auto";
2065
+ }
2066
+
2067
+ const selectWidth = rect.width;
2068
+ if (selectWidth > 0) {
2069
+ menu.style.width = selectWidth + "px";
2070
+ menu.style.minWidth = selectWidth + "px";
2071
+ menu.style.maxWidth = selectWidth + "px";
2072
+ menu.style.boxSizing = "border-box";
2073
+ } else {
2074
+ menu.style.minWidth = "120px";
2075
+ }
2076
+ const spaceRight = (typeof window !== "undefined" ? window.innerWidth : 1200) - rect.left;
2077
+ if (spaceRight < 220 && rect.right > 220) {
2078
+ menu.style.right = ((typeof window !== "undefined" ? window.innerWidth : 1200) - rect.right) + "px";
2079
+ menu.style.left = "auto";
2080
+ } else {
2081
+ menu.style.left = rect.left + "px";
2082
+ menu.style.right = "auto";
2083
+ }
2084
+
2085
+ const selectedEl = typeof menu.querySelector === "function" ? menu.querySelector(".sm-customSelectOptionSelected") : null;
2086
+ if (selectedEl && typeof selectedEl.scrollIntoView === "function") {
2087
+ selectedEl.scrollIntoView({ block: "nearest" });
2088
+ }
2089
+ }
2090
+
2091
+ function installCustomDropdownInterceptor() {
2092
+ if (typeof document === "undefined" || typeof document.addEventListener !== "function") {
2093
+ return () => {};
2094
+ }
2095
+
2096
+ if (typeof window !== "undefined" && typeof window.__dshSmDropdownInterceptorOff === "function") {
2097
+ try { window.__dshSmDropdownInterceptorOff(); } catch (_) {}
2098
+ }
2099
+
2100
+ const onMouseDown = (e) => {
2101
+ if (activeCustomMenu && activeCustomMenu.contains(e.target)) return;
2102
+ if (e.target?.closest?.("button, input, textarea, a")) return;
2103
+
2104
+ let select = null;
2105
+ if (e.target?.matches?.("select")) {
2106
+ select = e.target;
2107
+ } else if (e.target?.closest?.("select")) {
2108
+ select = e.target.closest("select");
2109
+ } else {
2110
+ const container = e.target?.closest?.(".sm-wsSortField, .sm-annotationPriority, .sm-viewField, .sm-moveSection, .sm-settingsRow, .sm-customSelectWrapper");
2111
+ if (container) {
2112
+ select = container.querySelector("select");
2113
+ } else {
2114
+ const nearest = e.target?.closest?.(SM_SELECT_SELECTOR);
2115
+ if (nearest && nearest.tagName === "SELECT") {
2116
+ select = nearest;
2117
+ }
2118
+ }
2119
+ }
2120
+
2121
+ if (select && select.tagName === "SELECT") {
2122
+ e.preventDefault();
2123
+ e.stopPropagation();
2124
+ if (select.disabled) return;
2125
+ try { select.focus(); } catch (_) {}
2126
+ openCustomSelect(select);
2127
+ return;
2128
+ }
2129
+
2130
+ if (activeCustomMenu) {
2131
+ closeCustomSelect();
2132
+ }
2133
+ };
2134
+
2135
+ const onClick = (e) => {
2136
+ if (e.target?.closest?.("button, input, textarea, a")) return;
2137
+ let select = null;
2138
+ if (e.target?.matches?.("select")) {
2139
+ select = e.target;
2140
+ } else {
2141
+ const container = e.target?.closest?.(".sm-wsSortField, .sm-annotationPriority, .sm-viewField, .sm-moveSection, .sm-settingsRow, .sm-customSelectWrapper");
2142
+ if (container) select = container.querySelector("select");
2143
+ }
2144
+ if (select && select.tagName === "SELECT") {
2145
+ e.preventDefault();
2146
+ e.stopPropagation();
2147
+ }
2148
+ };
2149
+
2150
+ const onKeyDown = (e) => {
2151
+ if (e.key === "Escape") {
2152
+ if (activeCustomMenu) {
2153
+ e.preventDefault();
2154
+ e.stopPropagation();
2155
+ closeCustomSelect();
2156
+ }
2157
+ return;
2158
+ }
2159
+
2160
+ const focused = document.activeElement;
2161
+ const targetSelect = activeCustomSelect || (focused?.matches?.(SM_SELECT_SELECTOR) ? focused : null) || (focused?.closest?.(".sm-wsSortField, .sm-annotationPriority, .sm-viewField, .sm-moveSection, .sm-settingsRow")?.querySelector("select"));
2162
+ if (!targetSelect || targetSelect.tagName !== "SELECT") return;
2163
+
2164
+ if (e.key === "Enter" || e.key === " ") {
2165
+ if (!activeCustomMenu) {
2166
+ e.preventDefault();
2167
+ e.stopPropagation();
2168
+ openCustomSelect(targetSelect);
2169
+ } else {
2170
+ e.preventDefault();
2171
+ e.stopPropagation();
2172
+ closeCustomSelect();
2173
+ }
2174
+ } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
2175
+ e.preventDefault();
2176
+ e.stopPropagation();
2177
+ const opts = Array.from(targetSelect.options || []).filter(o => !o.disabled);
2178
+ if (opts.length === 0) return;
2179
+ const currentIdx = opts.findIndex(o => o.value === targetSelect.value);
2180
+ const step = e.key === "ArrowDown" ? 1 : -1;
2181
+ const nextIdx = (currentIdx + step + opts.length) % opts.length;
2182
+ applyCustomSelection(targetSelect, opts[nextIdx].value);
2183
+ openCustomSelect(targetSelect);
2184
+ }
2185
+ };
2186
+
2187
+ const onResizeOrScroll = () => {
2188
+ if (activeCustomMenu) closeCustomSelect();
2189
+ };
2190
+
2191
+ document.addEventListener("mousedown", onMouseDown, true);
2192
+ document.addEventListener("click", onClick, true);
2193
+ document.addEventListener("keydown", onKeyDown, true);
2194
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
2195
+ window.addEventListener("resize", onResizeOrScroll, { passive: true });
2196
+ window.addEventListener("scroll", onResizeOrScroll, { passive: true, capture: true });
2197
+ }
2198
+
2199
+ const dispose = function dispose() {
2200
+ closeCustomSelect();
2201
+ document.removeEventListener("mousedown", onMouseDown, true);
2202
+ document.removeEventListener("click", onClick, true);
2203
+ document.removeEventListener("keydown", onKeyDown, true);
2204
+ if (typeof window !== "undefined" && typeof window.removeEventListener === "function") {
2205
+ window.removeEventListener("resize", onResizeOrScroll);
2206
+ window.removeEventListener("scroll", onResizeOrScroll, true);
2207
+ }
2208
+ if (typeof window !== "undefined" && window.__dshSmDropdownInterceptorOff === dispose) {
2209
+ window.__dshSmDropdownInterceptorOff = null;
2210
+ }
2211
+ };
2212
+ if (typeof window !== "undefined") {
2213
+ window.__dshSmDropdownInterceptorOff = dispose;
2214
+ }
2215
+ return dispose;
2216
+ }
2217
+
2218
+ async function executeArchiveWorkspace(workspaceId, { allWorkspaces, t } = {}) {
2219
+ if (workspaceArchiveStore.isBusy(workspaceId)) return false;
2220
+ const raw = workspaceArchiveStore.rawSnapshot();
2221
+ const rawItems = Array.isArray(raw?.items) ? raw.items : [];
2222
+ const rawItem = rawItems.find(w => (w.workspaceId || w.id) === workspaceId);
2223
+ const ws = (Array.isArray(allWorkspaces) ? allWorkspaces.find(w => w.id === workspaceId) : null) || rawItem;
2224
+ if (!ws) return false;
2225
+
2226
+ const hostArchivedSet = new Set(Array.isArray(raw?.archivedSessionIds) ? raw.archivedSessionIds : []);
2227
+ const allSessionIds = Array.isArray(ws.sessionIds) ? ws.sessionIds : [];
2228
+ const toArchive = allSessionIds.filter(id => !hostArchivedSet.has(id));
2229
+
2230
+ workspaceArchiveStore.markBusy(workspaceId, true);
2231
+ const succeeded = [];
2232
+ let failureError = null;
2233
+
2234
+ try {
2235
+ for (const sid of toArchive) {
2236
+ try {
2237
+ await runArchiveCommand("archive", sid, { stopActivity: false });
2238
+ succeeded.push(sid);
2239
+ } catch (err) {
2240
+ failureError = err;
2241
+ break;
2242
+ }
2243
+ }
2244
+
2245
+ if (failureError) {
2246
+ // Rollback: unarchive whatever we archived in this run
2247
+ for (const sid of succeeded) {
2248
+ try { await runArchiveCommand("unarchive", sid); } catch (_) {}
2249
+ }
2250
+ const msg = failureError?.message || String(failureError);
2251
+ const alertMsg = (t ? t("workspace.archive.failed", { message: msg }) : "归档工作区失败:{message}").replace("{message}", msg);
2252
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
2253
+ window.alert(alertMsg);
2254
+ }
2255
+ return false;
2256
+ }
2257
+
2258
+ const prevRecord = workspaceArchiveStore.getRecord(workspaceId);
2259
+ const combinedSessionIds = Array.from(new Set([...(prevRecord?.sessionIds || []), ...succeeded]));
2260
+ const record = {
2261
+ workspaceId,
2262
+ archived: true,
2263
+ archivedAt: Date.now(),
2264
+ sessionIds: combinedSessionIds,
2265
+ pending: []
2266
+ };
2267
+ workspaceArchiveStore.saveArchiveRecord(workspaceId, record);
2268
+ try {
2269
+ await callApi("/workspace-archive", record);
2270
+ } catch (e) {
2271
+ console.warn("[session-manager] Failed to persist workspace archive to host:", e);
2272
+ }
2273
+
2274
+ const currentId = activeClientCtx?.sessions?.list?.getSnapshot?.()?.current
2275
+ || activeClientCtx?.uiWorkspace?.mainReference?.sessionId;
2276
+ if (currentId && toArchive.includes(currentId)) {
2277
+ try {
2278
+ activeClientCtx?.uiWorkspace?.clearMain?.();
2279
+ } catch (_) {}
2280
+ }
2281
+
2282
+ try { await activeClientCtx?.sessions?.refresh?.(); } catch (_) {}
2283
+ try { await activeClientCtx?.workspaces?.refresh?.(); } catch (_) {}
2284
+ return true;
2285
+ } finally {
2286
+ workspaceArchiveStore.markBusy(workspaceId, false);
2287
+ }
2288
+ }
2289
+
2290
+ async function executeUnarchiveWorkspace(workspaceId, { t } = {}) {
2291
+ if (workspaceArchiveStore.isBusy(workspaceId)) return false;
2292
+ const record = workspaceArchiveStore.getRecord(workspaceId);
2293
+ workspaceArchiveStore.markBusy(workspaceId, true);
2294
+ try {
2295
+ const raw = workspaceArchiveStore.rawSnapshot();
2296
+ const hostArchivedSet = new Set(Array.isArray(raw?.archivedSessionIds) ? raw.archivedSessionIds : []);
2297
+ const idsToRestore = [...(record?.sessionIds || []), ...(record?.pending || [])];
2298
+ const failed = [];
2299
+
2300
+ for (const sid of idsToRestore) {
2301
+ if (!hostArchivedSet.has(sid)) continue;
2302
+ try {
2303
+ await runArchiveCommand("unarchive", sid);
2304
+ } catch (err) {
2305
+ failed.push(sid);
2306
+ }
2307
+ }
2308
+
2309
+ if (failed.length > 0) {
2310
+ const updatedRecord = {
2311
+ ...(record || { workspaceId }),
2312
+ archived: true,
2313
+ pending: failed
2314
+ };
2315
+ workspaceArchiveStore.saveArchiveRecord(workspaceId, updatedRecord);
2316
+ try {
2317
+ await callApi("/workspace-archive", updatedRecord);
2318
+ } catch (_) {}
2319
+ const msg = (t ? t("workspace.unarchive.failed", { message: failed.length + " 个会话恢复失败" }) : "恢复工作区失败:{message}").replace("{message}", failed.length + " 个会话恢复失败");
2320
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
2321
+ window.alert(msg);
2322
+ }
2323
+ return false;
2324
+ }
2325
+
2326
+ workspaceArchiveStore.removeArchiveRecord(workspaceId);
2327
+ try {
2328
+ await callApi("/workspace-unarchive", { workspaceId });
2329
+ } catch (_) {}
2330
+
2331
+ try { await activeClientCtx?.sessions?.refresh?.(); } catch (_) {}
2332
+ try { await activeClientCtx?.workspaces?.refresh?.(); } catch (_) {}
2333
+ return true;
2334
+ } finally {
2335
+ workspaceArchiveStore.markBusy(workspaceId, false);
2336
+ }
2337
+ }
2338
+
2339
+ function SmSwitch(props) {
2340
+ const checked = props.checked === true;
2341
+ const disabled = props.disabled === true;
2342
+ const loading = props.loading === true;
2343
+ const onChange = typeof props.onChange === "function" ? props.onChange : () => {};
2344
+ return h("button", {
2345
+ type: "button",
2346
+ role: "switch",
2347
+ className: "sm-switch" + (checked ? " sm-switchChecked" : "") + (loading ? " sm-switchLoading" : ""),
2348
+ "aria-checked": checked,
2349
+ "aria-label": props.ariaLabel,
2350
+ disabled: disabled || loading,
2351
+ onClick: (e) => {
2352
+ if (e && typeof e.stopPropagation === "function") e.stopPropagation();
2353
+ if (disabled || loading) return;
2354
+ if (typeof props.onClick === "function") props.onClick(e);
2355
+ else onChange(!checked);
2356
+ }
2357
+ },
2358
+ h("span", { className: "sm-switchThumb" },
2359
+ loading ? h("span", { className: "sm-switchSpinner" }) : null
2360
+ )
2361
+ );
2362
+ }
2363
+
1371
2364
  const EMPTY_ANNOTATION = Object.freeze({ favorite: false, reviewLater: false, tags: Object.freeze([]), note: "", priority: 3, revision: 0 });
1372
2365
  const validAnnotation = value => value && typeof value.favorite === "boolean" && typeof value.reviewLater === "boolean" && Array.isArray(value.tags) && value.tags.every(tag => typeof tag === "string") && typeof value.note === "string" && (value.priority === null || Number.isInteger(value.priority) && value.priority >= 1 && value.priority <= 5) && Number.isSafeInteger(value.revision) && value.revision >= 0;
1373
2366
  const annotationOf = (state, id) => Object.hasOwn(state.entries, id) ? state.entries[id] : EMPTY_ANNOTATION;
@@ -2582,7 +3575,7 @@ function isTopmostDialog(z) {
2582
3575
  ));
2583
3576
  }
2584
3577
 
2585
- const CURRENT_VERSION = "0.6.4";
3578
+ const CURRENT_VERSION = "0.7.0";
2586
3579
 
2587
3580
  function compareSemver(v1, v2) {
2588
3581
  if (typeof v1 !== "string" || typeof v2 !== "string") return 0;
@@ -2886,13 +3879,8 @@ function isTopmostDialog(z) {
2886
3879
  const lastBatchContext = { action: null, ids: [] };
2887
3880
 
2888
3881
  const DEFAULT_SORT = "updated-desc";
2889
- const SORT_ORDERS = ["updated-desc", "updated-asc", "created-desc", "created-asc", "priority"];
3882
+ const SORT_ORDERS = ["updated-desc", "updated-asc", "created-desc", "created-asc", "name-asc", "name-desc", "priority"];
2890
3883
  const workspaceValue = (id) => "workspace:" + id;
2891
- const pathKey = (value) => {
2892
- if (typeof value !== "string" || value === "") return "";
2893
- const path = value.replace(/\\/g, "/").replace(/\/+$/, "") || "/";
2894
- return /^[a-z]:(?:\/|$)/i.test(path) || path.startsWith("//") ? path.toLowerCase() : path;
2895
- };
2896
3884
  const sessionTime = (value) => {
2897
3885
  if (typeof value !== "number" && typeof value !== "string") return null;
2898
3886
  if (typeof value === "string" && value.trim() === "") return null;
@@ -2926,17 +3914,33 @@ function isTopmostDialog(z) {
2926
3914
  };
2927
3915
 
2928
3916
  function SessionManagerPanel(props) {
2929
- const t = props.t;
3917
+ const t = typeof props.t === "function" ? props.t : (k => k);
2930
3918
  const open = props.open;
2931
3919
  const onClose = props.onClose;
2932
- const useSessions = props.useSessions;
2933
- const useWorkspaces = props.useWorkspaces;
2934
3920
  const onOpen = props.onOpen;
2935
3921
  const onArchive = props.onArchive;
2936
3922
  const onUnarchive = props.onUnarchive;
2937
3923
  const onRemove = props.onRemove;
2938
3924
  const onMove = props.onMove;
2939
3925
  const onMigrate = props.onMigrate;
3926
+ const defaultUseSessions = (selector = s => s) => {
3927
+ const model = activeClientCtx?.sessions?.list;
3928
+ return useSyncExternalStore(
3929
+ (cb) => (model?.subscribe ? model.subscribe(cb) : () => {}),
3930
+ () => (model?.getSnapshot ? selector(model.getSnapshot()) : selector({ ids: [], byId: {} })),
3931
+ () => (model?.getSnapshot ? selector(model.getSnapshot()) : selector({ ids: [], byId: {} }))
3932
+ );
3933
+ };
3934
+ const defaultUseWorkspaces = (selector = s => s) => {
3935
+ const model = activeClientCtx?.workspaces?.list;
3936
+ return useSyncExternalStore(
3937
+ (cb) => (model?.subscribe ? model.subscribe(cb) : () => {}),
3938
+ () => (model?.getSnapshot ? selector(model.getSnapshot()) : selector({ items: [] })),
3939
+ () => (model?.getSnapshot ? selector(model.getSnapshot()) : selector({ items: [] }))
3940
+ );
3941
+ };
3942
+ const useSessions = typeof props.useSessions === "function" ? props.useSessions : defaultUseSessions;
3943
+ const useWorkspaces = typeof props.useWorkspaces === "function" ? props.useWorkspaces : defaultUseWorkspaces;
2940
3944
  const annotations = useAnnotations(true);
2941
3945
  const marksReady = annotations.loaded && !annotations.error;
2942
3946
  const updateState = useSyncExternalStore(
@@ -2950,9 +3954,22 @@ function isTopmostDialog(z) {
2950
3954
  const [priorityFilter, setPriorityFilter] = useState("all");
2951
3955
  const [annotationFor, setAnnotationFor] = useState(null);
2952
3956
  const [annotationAnchor, setAnnotationAnchor] = useState(null);
2953
- const list = useSessions((s) => s);
2954
- const workspaceSnapshot = useWorkspaces((s) => s);
3957
+ const list = (typeof useSessions === "function" ? useSessions((s) => s) : null) || { ids: [], byId: {} };
3958
+ const workspaceSnapshot = (typeof useWorkspaces === "function" ? useWorkspaces((s) => s) : null) || { items: [] };
2955
3959
  const archivedIds = workspaceSnapshot.archivedSessionIds || [];
3960
+ const [panelTab, setPanelTab] = useState("sessions");
3961
+ const [wsQuery, setWsQuery] = useState("");
3962
+ const [wsFilter, setWsFilter] = useState("all");
3963
+ const [wsSort, setWsSort] = useState("updated-desc");
3964
+ const [wsSelectedIds, setWsSelectedIds] = useState(() => new Set());
3965
+ const [wsSelectModeEnabled, setWsSelectModeEnabled] = useState(false);
3966
+ const [wsBulkBusy, setWsBulkBusy] = useState(false);
3967
+ const [wsLastClickedRank, setWsLastClickedRank] = useState(null);
3968
+ const archiveVersion = useSyncExternalStore(
3969
+ (cb) => workspaceArchiveStore.subscribe(cb),
3970
+ () => workspaceArchiveStore.getVersion(),
3971
+ () => workspaceArchiveStore.getVersion()
3972
+ );
2956
3973
  const [filter, setFilter] = useState("all");
2957
3974
  const [query, setQuery] = useState("");
2958
3975
  const [workspaceFilter, setWorkspaceFilter] = useState("all");
@@ -2964,12 +3981,14 @@ function isTopmostDialog(z) {
2964
3981
  const [confirmFor, setConfirmFor] = useState(null);
2965
3982
  const [workspaces, setWorkspaces] = useState([]);
2966
3983
  const [createdTimes, setCreatedTimes] = useState({});
3984
+ const [updatedTimes, setUpdatedTimes] = useState({});
2967
3985
  const [workspacesLoading, setWorkspacesLoading] = useState(true);
2968
3986
  const [workspacesError, setWorkspacesError] = useState(null);
2969
3987
  const [workspaceRefresh, setWorkspaceRefresh] = useState(0);
2970
3988
  const [migrating, setMigrating] = useState(false);
2971
3989
  const [migrateFor, setMigrateFor] = useState(null);
2972
- const sessionMembershipKey = useMemo(() => [...list.ids].sort().join("\0"), [list.ids]);
3990
+ const sessionMembershipKey = useMemo(() => (Array.isArray(list?.ids) ? [...list.ids].sort().join("\0") : ""), [list?.ids]);
3991
+ let isSessionWorkspaceArchived = () => false;
2973
3992
  // ----- Bulk-action selection state -----
2974
3993
  const [selectedIds, setSelectedIds] = useState(() => new Set());
2975
3994
  const [lastClickedRank, setLastClickedRank] = useState(null);
@@ -2997,6 +4016,10 @@ function isTopmostDialog(z) {
2997
4016
  setBulkPresetOptions([]);
2998
4017
  setBulkBusy(false);
2999
4018
  setSelectModeEnabled(false);
4019
+ setWsSelectedIds(new Set());
4020
+ setWsSelectModeEnabled(false);
4021
+ setWsBulkBusy(false);
4022
+ setWsLastClickedRank(null);
3000
4023
  }
3001
4024
  }, [open]);
3002
4025
  const toggleSelectMode = () => {
@@ -3111,6 +4134,15 @@ function isTopmostDialog(z) {
3111
4134
  if (ids.length === 0) return;
3112
4135
  if (ids.length > 200) { setError(t("bulk.error.tooMany")); return; }
3113
4136
  const sessions = selectedSessions;
4137
+ if (action === "unarchive") {
4138
+ const hasBlocked = sessions.some(s => isSessionWorkspaceArchived(s));
4139
+ if (hasBlocked) {
4140
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
4141
+ window.alert(t("error.workspaceArchived"));
4142
+ }
4143
+ return;
4144
+ }
4145
+ }
3114
4146
  const resolvedLabel = actionLabel || ({
3115
4147
  archive: t("bulk.archive"), unarchive: t("bulk.unarchive"), delete: t("bulk.delete"),
3116
4148
  move: t("bulk.move"), "preset-migrate": t("bulk.presetMigrate"),
@@ -3213,15 +4245,20 @@ function isTopmostDialog(z) {
3213
4245
  if (!open) return;
3214
4246
  let alive = true;
3215
4247
  const controller = new AbortController();
3216
- setWorkspacesLoading(true);
4248
+ if (workspaces.length === 0) setWorkspacesLoading(true);
3217
4249
  setWorkspacesError(null);
3218
4250
  fetchApi("/workspaces", { signal: controller.signal }).then((data) => {
3219
4251
  if (!data?.ok || !Array.isArray(data.result?.workspaces)) throw new Error(data?.error || "Invalid workspace response");
3220
4252
  const next = data.result.workspaces.filter(workspace => workspace && typeof workspace.id === "string");
3221
4253
  if (!alive) return;
4254
+ if (data.result.workspaceArchives) {
4255
+ workspaceArchiveStore.syncFromHost(data.result.workspaceArchives);
4256
+ }
3222
4257
  setWorkspaces(next);
3223
4258
  const times = data.result.sessionCreatedAt;
3224
4259
  setCreatedTimes(times && typeof times === "object" && !Array.isArray(times) ? times : {});
4260
+ const updated = data.result.sessionUpdatedAt;
4261
+ setUpdatedTimes(updated && typeof updated === "object" && !Array.isArray(updated) ? updated : {});
3225
4262
  setWorkspaceFilter(value => value.startsWith("workspace:") && !next.some(workspace => workspaceValue(workspace.id) === value) ? "all" : value);
3226
4263
  }).catch(error => {
3227
4264
  if (alive) setWorkspacesError(error instanceof Error ? error.message : String(error));
@@ -3242,8 +4279,26 @@ function isTopmostDialog(z) {
3242
4279
  }, [open]);
3243
4280
  const archived = useMemo(() => new Set(archivedIds), [archivedIds]);
3244
4281
  const workspaceIndex = useMemo(() => indexWorkspaces(workspaces), [workspaces]);
3245
- const allRows = useMemo(() => list.ids.map(id => list.byId[id])
3246
- .filter(session => session != null && session.origin !== "subagent" && (!session.blank || session.id === list.current)), [list]);
4282
+ isSessionWorkspaceArchived = (session) => {
4283
+ if (!session) return false;
4284
+ if (session.workspaceId && workspaceArchiveStore.isArchived(session.workspaceId)) return true;
4285
+ const memberships = rowWorkspaces(session, workspaceIndex);
4286
+ for (const wsId of memberships) {
4287
+ if (workspaceArchiveStore.isArchived(wsId)) return true;
4288
+ }
4289
+ for (const [, rec] of workspaceArchiveStore.getAllRecords()) {
4290
+ if (rec.archived === true && Array.isArray(rec.sessionIds) && rec.sessionIds.includes(session.id)) {
4291
+ return true;
4292
+ }
4293
+ }
4294
+ return false;
4295
+ };
4296
+ const allRows = useMemo(() => {
4297
+ const ids = Array.isArray(list?.ids) ? list.ids : [];
4298
+ const byId = list?.byId || {};
4299
+ return ids.map(id => byId[id])
4300
+ .filter(session => session != null && session.origin !== "subagent" && (!session.blank || session.id === list?.current));
4301
+ }, [list]);
3247
4302
  const availableTags = useMemo(() => {
3248
4303
  const tags = new Map();
3249
4304
  for (const session of allRows) for (const tag of annotationOf(annotations, session.id).tags) if (!tags.has(tag.toLowerCase())) tags.set(tag.toLowerCase(), tag);
@@ -3273,6 +4328,16 @@ function isTopmostDialog(z) {
3273
4328
  }
3274
4329
  return true;
3275
4330
  });
4331
+ if (sortOrder.startsWith("name-")) {
4332
+ const dir = sortOrder === "name-asc" ? 1 : -1;
4333
+ const nameOf = s => (s.blank ? t("panel.session.new") : (s.displayTitle || s.id || "")).toLowerCase();
4334
+ return selected.map((session, rank) => ({ session, rank, name: nameOf(session) }))
4335
+ .sort((a, b) => {
4336
+ const cmp = a.name.localeCompare(b.name);
4337
+ return cmp !== 0 ? dir * cmp : a.rank - b.rank;
4338
+ })
4339
+ .map(item => item.session);
4340
+ }
3276
4341
  const field = sortOrder.startsWith("created-") ? "createdAt" : "updatedAt";
3277
4342
  const direction = sortOrder === "priority" || sortOrder.endsWith("-asc") ? 1 : -1;
3278
4343
  // Sort a derived array only. Equal timestamps preserve source order;
@@ -3308,8 +4373,6 @@ function isTopmostDialog(z) {
3308
4373
  }, [currentFilterIds]);
3309
4374
  const creationTimeUnavailable = sortOrder.startsWith("created-") && allRows.length > 0
3310
4375
  && !allRows.some(session => (sessionTime(session.createdAt) ?? sessionTime(createdTimes[session.id])) !== null);
3311
- const hasViewChanges = onlyFavorite || onlyReview || tagFilter !== "all" || priorityFilter !== "all" || query !== "" || filter !== "all" || workspaceFilter !== "all" || sortOrder !== DEFAULT_SORT;
3312
- const resetView = () => { setQuery(""); setFilter("all"); setWorkspaceFilter("all"); setSortOrder(DEFAULT_SORT); setOnlyFavorite(false); setOnlyReview(false); setTagFilter("all"); setPriorityFilter("all"); };
3313
4376
  const runRow = async (sessionId, fn) => {
3314
4377
  if (busyId !== null) return;
3315
4378
  setBusyId(sessionId);
@@ -3329,12 +4392,24 @@ function isTopmostDialog(z) {
3329
4392
  "aria-pressed": filter === id,
3330
4393
  onClick: () => setFilter(id)
3331
4394
  }, label);
4395
+ const hasViewChanges = query !== "" || filter !== "all" || workspaceFilter !== "all" || sortOrder !== DEFAULT_SORT || onlyFavorite || onlyReview || tagFilter !== "all" || priorityFilter !== "all";
4396
+ const resetView = () => {
4397
+ setQuery("");
4398
+ setFilter("all");
4399
+ setWorkspaceFilter("all");
4400
+ setSortOrder(DEFAULT_SORT);
4401
+ setOnlyFavorite(false);
4402
+ setOnlyReview(false);
4403
+ setTagFilter("all");
4404
+ setPriorityFilter("all");
4405
+ };
3332
4406
  const renderRow = (s, rank) => {
3333
4407
  const isArchived = archived.has(s.id);
3334
4408
  const isCurrent = s.id === list.current;
3335
4409
  const busy = busyId === s.id;
3336
4410
  const mark = annotationOf(annotations, s.id);
3337
4411
  const isSelected = selectedIds.has(s.id);
4412
+ const isWsArchived = isSessionWorkspaceArchived(s);
3338
4413
  const checkbox = (selectedIds.size === 0 && !selectModeEnabled)
3339
4414
  ? null
3340
4415
  : h("label", { className: "sm-bulkRowCheckbox", onClick: (e) => e.stopPropagation() },
@@ -3355,6 +4430,7 @@ function isTopmostDialog(z) {
3355
4430
  h("div", { className: "sm-rowMain" },
3356
4431
  h("div", { className: "sm-rowTitle" },
3357
4432
  h("span", null, s.blank ? t("panel.session.new") : (s.displayTitle || s.id)),
4433
+ isWsArchived ? h("span", { className: "sm-badge sm-badgeWorkspaceArchived" }, t("panel.workspaceArchived")) : null,
3358
4434
  isArchived ? h("span", { className: "sm-badge sm-badgeArchived" }, t("panel.archived")) : null,
3359
4435
  s.running ? h("span", { className: "sm-badge sm-badgeRunning" }, t("panel.running")) : null,
3360
4436
  isCurrent ? h("span", { className: "sm-badge sm-badgeCurrent" }, t("panel.current")) : null
@@ -3368,8 +4444,8 @@ function isTopmostDialog(z) {
3368
4444
  ),
3369
4445
  h("div", { className: "sm-rowMeta" }, shortPath(s.cwd) + (s.cwd ? " · " : "") + formatRelative(s.updatedAt, now)),
3370
4446
  h("div", { className: "sm-rowActions" },
3371
- h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => { if (isArchived) { /* DSH refuses to surface an archived session as the current view: clicking "Open" on an archived row flashes an empty chat panel and bounces back to "no session selected". Unarchive first, then open. (issue #17.4) */ runRow(s.id, async () => { await onUnarchive(s.id); await onOpen(s.id); }); } else { onOpen(s.id); } } }, t("row.open")),
3372
- h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => runRow(s.id, () => isArchived ? onUnarchive(s.id) : onArchive(s.id)) }, t(isArchived ? "row.unarchive" : "row.archive")),
4447
+ h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => { if (isArchived) { if (isWsArchived) { if (typeof window !== "undefined" && typeof window.alert === "function") { window.alert(t("error.workspaceArchived")); } return; } /* DSH refuses to surface an archived session as the current view: clicking "Open" on an archived row flashes an empty chat panel and bounces back to "no session selected". Unarchive first, then open. (issue #17.4) */ runRow(s.id, async () => { await onUnarchive(s.id); await onOpen(s.id); }); } else { onOpen(s.id); } } }, t("row.open")),
4448
+ h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => runRow(s.id, () => { if (isArchived) { if (isWsArchived) { if (typeof window !== "undefined" && typeof window.alert === "function") { window.alert(t("error.workspaceArchived")); } return; } return onUnarchive(s.id); } return onArchive(s.id); }) }, t(isArchived ? "row.unarchive" : "row.archive")),
3373
4449
  annotationButtons(s.id, s.displayTitle || s.id, t, annotations, "sm-rowBtn", patch => runRow(s.id, () => annotationStore.save(s.id, patch)), () => { setAnnotationAnchor(null); setAnnotationFor(current => current?.id === s.id ? null : s); }, busy),
3374
4450
  h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => { if (moveFor && moveFor.id === s.id) setMoveFor(null); else setMoveFor(s); } }, t("row.move")),
3375
4451
  h("button", { type: "button", className: "sm-rowBtn", disabled: busy, onClick: () => { if (migrateFor && migrateFor.id === s.id) setMigrateFor(null); else setMigrateFor(s); } }, t("row.migrate")),
@@ -3382,8 +4458,261 @@ function isTopmostDialog(z) {
3382
4458
  const rowsList = rows.length === 0
3383
4459
  ? h("div", { className: "sm-empty" }, allRows.length > 0 ? t("panel.empty.filtered") : filter === "archived" ? t("panel.empty.archived") : t("panel.empty"))
3384
4460
  : h("div", { className: "sm-list" }, rows.map((s, i) => renderRow(s, i)));
4461
+
4462
+ const allWorkspaceRows = useMemo(() => {
4463
+ const byId = list?.byId || {};
4464
+ return workspaces.map(ws => {
4465
+ const sids = Array.isArray(ws.sessionIds) ? ws.sessionIds : [];
4466
+ let latestSessionTime = null;
4467
+ for (const sid of sids) {
4468
+ const s = byId[sid];
4469
+ const rawTime = s ? (s.updatedAt ?? s.lastModified ?? s.mtime ?? s.createdAt) : null;
4470
+ const st = sessionTime(rawTime) ?? sessionTime(updatedTimes[sid]) ?? sessionTime(createdTimes[sid]);
4471
+ if (st !== null) {
4472
+ if (latestSessionTime === null || st > latestSessionTime) {
4473
+ latestSessionTime = st;
4474
+ }
4475
+ }
4476
+ }
4477
+ const wsSelfTime = sessionTime(ws.updatedAt) ?? sessionTime(ws.createdAt);
4478
+ const resolvedTime = latestSessionTime !== null ? latestSessionTime : wsSelfTime;
4479
+ return {
4480
+ ...ws,
4481
+ latestUpdatedAt: resolvedTime
4482
+ };
4483
+ });
4484
+ }, [workspaces, list?.byId, updatedTimes, createdTimes]);
4485
+
4486
+ const filteredWorkspaceRows = useMemo(() => {
4487
+ const needle = wsQuery.trim().toLowerCase();
4488
+ const selected = allWorkspaceRows.filter(ws => {
4489
+ const isArchived = workspaceArchiveStore.isArchived(ws.id);
4490
+ if (wsFilter === "active" && isArchived) return false;
4491
+ if (wsFilter === "archived" && !isArchived) return false;
4492
+ if (needle) {
4493
+ const title = ws.title || ws.name || ws.id;
4494
+ const path = ws.path || "";
4495
+ const matchesTitle = title.toLowerCase().includes(needle);
4496
+ const matchesPath = path.toLowerCase().includes(needle);
4497
+ const matchesId = ws.id.toLowerCase().includes(needle);
4498
+ if (!matchesTitle && !matchesPath && !matchesId) return false;
4499
+ }
4500
+ return true;
4501
+ });
4502
+
4503
+ if (wsSort.startsWith("name-")) {
4504
+ const dir = wsSort === "name-asc" ? 1 : -1;
4505
+ return selected.map((ws, rank) => {
4506
+ const name = (ws.title || ws.name || ws.id || "").toLowerCase();
4507
+ return { ws, rank, name };
4508
+ }).sort((a, b) => {
4509
+ const cmp = a.name.localeCompare(b.name);
4510
+ return cmp !== 0 ? dir * cmp : a.rank - b.rank;
4511
+ }).map(item => item.ws);
4512
+ }
4513
+
4514
+ const direction = wsSort === "updated-asc" ? 1 : -1;
4515
+ return selected.map((ws, rank) => ({ ws, rank, time: ws.latestUpdatedAt }))
4516
+ .sort((a, b) => {
4517
+ if (a.time === b.time) return a.rank - b.rank;
4518
+ if (a.time === null) return 1;
4519
+ if (b.time === null) return -1;
4520
+ return direction * (a.time - b.time);
4521
+ })
4522
+ .map(item => item.ws);
4523
+ }, [allWorkspaceRows, wsQuery, wsFilter, wsSort, archiveVersion]);
4524
+
4525
+ const currentWsFilterIds = useMemo(() => filteredWorkspaceRows.map(ws => ws.id), [filteredWorkspaceRows]);
4526
+ useEffect(() => {
4527
+ const allowed = new Set(currentWsFilterIds);
4528
+ setWsSelectedIds(prev => {
4529
+ let changed = false;
4530
+ const next = new Set();
4531
+ for (const id of prev) if (allowed.has(id)) next.add(id); else changed = true;
4532
+ return changed ? next : prev;
4533
+ });
4534
+ }, [currentWsFilterIds]);
4535
+
4536
+ const toggleWsSelectMode = () => {
4537
+ if (wsSelectModeEnabled) {
4538
+ setWsSelectModeEnabled(false);
4539
+ setWsSelectedIds(new Set());
4540
+ setWsLastClickedRank(null);
4541
+ } else {
4542
+ setWsSelectModeEnabled(true);
4543
+ }
4544
+ };
4545
+
4546
+ const toggleWsSelect = (id, isRange, rank) => {
4547
+ if (wsBulkBusy) return;
4548
+ setWsSelectedIds(prev => {
4549
+ const next = new Set(prev);
4550
+ if (isRange && wsLastClickedRank !== null && typeof rank === "number") {
4551
+ const low = Math.min(wsLastClickedRank, rank);
4552
+ const high = Math.max(wsLastClickedRank, rank);
4553
+ for (let i = low; i <= high; i++) {
4554
+ const row = filteredWorkspaceRows[i];
4555
+ if (row) next.add(row.id);
4556
+ }
4557
+ } else {
4558
+ if (next.has(id)) next.delete(id); else next.add(id);
4559
+ }
4560
+ return next;
4561
+ });
4562
+ setWsLastClickedRank(rank);
4563
+ };
4564
+
4565
+ const onWsBulkSelectAll = () => {
4566
+ setWsSelectModeEnabled(true);
4567
+ setWsSelectedIds(new Set(filteredWorkspaceRows.map(ws => ws.id)));
4568
+ };
4569
+
4570
+ const onWsBulkClear = () => {
4571
+ setWsSelectedIds(new Set());
4572
+ setWsLastClickedRank(null);
4573
+ };
4574
+
4575
+ const onWsBulkArchive = async () => {
4576
+ if (wsBulkBusy || !wsSelectModeEnabled || wsSelectedIds.size === 0) return;
4577
+ const targetWs = workspaces.filter(ws => wsSelectedIds.has(ws.id) && !workspaceArchiveStore.isArchived(ws.id));
4578
+ if (targetWs.length === 0) return;
4579
+
4580
+ const hostArchivedSet = new Set(workspaceSnapshot.archivedSessionIds || []);
4581
+ for (const ws of targetWs) {
4582
+ const toArchive = (ws.sessionIds || []).filter(id => !hostArchivedSet.has(id));
4583
+ const runningSession = toArchive.map(id => list.byId[id]).find(s => s && s.running);
4584
+ if (runningSession) {
4585
+ const rTitle = runningSession.displayTitle || runningSession.id;
4586
+ const wsTitle = ws.title || ws.name || ws.id;
4587
+ const msg = (t("confirm.delete.running") || "该会话正在运行,无法归档。") + " (" + wsTitle + ": " + rTitle + ")";
4588
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
4589
+ window.alert(msg);
4590
+ }
4591
+ return;
4592
+ }
4593
+ }
4594
+
4595
+ setWsBulkBusy(true);
4596
+ try {
4597
+ for (const ws of targetWs) {
4598
+ await executeArchiveWorkspace(ws.id, { allWorkspaces: workspaces, t });
4599
+ }
4600
+ setWsSelectedIds(new Set());
4601
+ } catch (err) {
4602
+ setError(err?.message || String(err));
4603
+ } finally {
4604
+ setWsBulkBusy(false);
4605
+ }
4606
+ };
4607
+
4608
+ const onWsBulkUnarchive = async () => {
4609
+ if (wsBulkBusy || !wsSelectModeEnabled || wsSelectedIds.size === 0) return;
4610
+ const targetWs = workspaces.filter(ws => wsSelectedIds.has(ws.id) && workspaceArchiveStore.isArchived(ws.id));
4611
+ if (targetWs.length === 0) return;
4612
+
4613
+ setWsBulkBusy(true);
4614
+ try {
4615
+ for (const ws of targetWs) {
4616
+ await executeUnarchiveWorkspace(ws.id, { t });
4617
+ }
4618
+ setWsSelectedIds(new Set());
4619
+ } catch (err) {
4620
+ setError(err?.message || String(err));
4621
+ } finally {
4622
+ setWsBulkBusy(false);
4623
+ }
4624
+ };
4625
+
4626
+ const hasWsViewChanges = wsQuery !== "" || wsFilter !== "all" || wsSort !== "updated-desc";
4627
+ const resetWsView = () => { setWsQuery(""); setWsFilter("all"); setWsSort("updated-desc"); };
4628
+ const wsIsEn = typeof t === "function" && (t("workspace.filter.all") === "All" || t("marks.favorite") === "Favorite");
4629
+
4630
+ const renderWorkspaceRow = (ws, rank) => {
4631
+ const isArchived = workspaceArchiveStore.isArchived(ws.id);
4632
+ const isBusy = workspaceArchiveStore.isBusy(ws.id);
4633
+ const title = ws.title || ws.name || ws.id;
4634
+ const path = ws.path || "";
4635
+ const sessionCount = Array.isArray(ws.sessionIds) ? ws.sessionIds.length : 0;
4636
+ const timeFormatted = ws.latestUpdatedAt !== null
4637
+ ? t("workspace.lastUpdated", { time: formatRelative(ws.latestUpdatedAt, now) })
4638
+ : "—";
4639
+
4640
+ const isWsSelected = wsSelectedIds.has(ws.id);
4641
+ const checkbox = (wsSelectedIds.size === 0 && !wsSelectModeEnabled)
4642
+ ? null
4643
+ : h("label", { className: "sm-bulkRowCheckbox", onClick: (e) => e.stopPropagation() },
4644
+ h("input", {
4645
+ type: "checkbox",
4646
+ checked: isWsSelected,
4647
+ disabled: isBusy || wsBulkBusy,
4648
+ "aria-label": t("bulk.checkbox.aria", { title: title }),
4649
+ onChange: (e) => toggleWsSelect(ws.id, e.shiftKey === true, rank)
4650
+ })
4651
+ );
4652
+
4653
+ const handleToggleArchive = (e) => {
4654
+ if (e && typeof e.stopPropagation === "function") e.stopPropagation();
4655
+ if (isBusy || wsBulkBusy) return;
4656
+ if (!isArchived) {
4657
+ const hostArchivedSet = new Set(workspaceSnapshot.archivedSessionIds || []);
4658
+ const toArchive = (ws.sessionIds || []).filter(id => !hostArchivedSet.has(id));
4659
+ const runningSession = toArchive.map(id => list.byId[id]).find(s => s && s.running);
4660
+ if (runningSession) {
4661
+ const rTitle = runningSession.displayTitle || runningSession.id;
4662
+ const msg = (t("confirm.delete.running") || "该会话正在运行,无法归档。") + " (" + rTitle + ")";
4663
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
4664
+ window.alert(msg);
4665
+ }
4666
+ return;
4667
+ }
4668
+ void executeArchiveWorkspace(ws.id, { allWorkspaces: workspaces, t });
4669
+ } else {
4670
+ void executeUnarchiveWorkspace(ws.id, { t });
4671
+ }
4672
+ };
4673
+
4674
+ const switchNode = h(SmSwitch, {
4675
+ role: "switch",
4676
+ "aria-checked": !isArchived,
4677
+ checked: !isArchived,
4678
+ loading: isBusy,
4679
+ disabled: isBusy || wsBulkBusy,
4680
+ ariaLabel: t("workspace.switch.aria", { name: title }),
4681
+ onClick: handleToggleArchive,
4682
+ onChange: handleToggleArchive
4683
+ });
4684
+
4685
+ return h("div", {
4686
+ key: ws.id,
4687
+ "data-workspace-id": ws.id,
4688
+ className: "sm-row sm-workspaceRow" + (isArchived ? " sm-rowArchived" : "") + (isWsSelected ? " sm-rowBulkSelected" : "")
4689
+ },
4690
+ h("div", { className: "sm-rowCheckboxSlot" + ((wsSelectedIds.size > 0 || wsSelectModeEnabled) ? " sm-rowCheckboxSlot-visible" : "") }, checkbox),
4691
+ h("div", { className: "sm-rowMain" },
4692
+ h("div", { className: "sm-rowTitle" },
4693
+ h("span", null, title),
4694
+ isArchived ? h("span", { className: "sm-badge sm-badgeArchived" }, t("workspace.badge.archived")) : null
4695
+ ),
4696
+ h("div", { className: "sm-rowSecondary" },
4697
+ h("div", { className: "sm-rowMeta" },
4698
+ (path ? (shortPath(path) + " · ") : "") +
4699
+ t("workspace.sessions", { count: sessionCount }) +
4700
+ " · " +
4701
+ timeFormatted
4702
+ )
4703
+ )
4704
+ ),
4705
+ h("div", { className: "sm-rowActions sm-workspaceRowActions" },
4706
+ switchNode
4707
+ )
4708
+ );
4709
+ };
4710
+ const workspaceRowsList = filteredWorkspaceRows.length === 0
4711
+ ? h("div", { className: "sm-empty" }, allWorkspaceRows.length > 0 ? t("workspace.empty.filtered") : t("workspace.empty"))
4712
+ : h("div", { className: "sm-list" }, filteredWorkspaceRows.map((ws, rank) => renderWorkspaceRow(ws, rank)));
4713
+
3385
4714
  const onPanelClose = () => {
3386
- if (busyId !== null) return;
4715
+ if (busyId !== null || wsBulkBusy) return;
3387
4716
  setConfirmFor(null);
3388
4717
  setMoveFor(null);
3389
4718
  setMigrateFor(null);
@@ -3398,7 +4727,7 @@ function isTopmostDialog(z) {
3398
4727
  // returns early when any inner dialog is open so the child
3399
4728
  // dialog's own window listener gets the first shot at Esc.
3400
4729
  const escStateRef = useRef({});
3401
- escStateRef.current = { busyId, confirmFor, moveFor, migrateFor, annotationFor, onPanelClose };
4730
+ escStateRef.current = { busyId, confirmFor, moveFor, migrateFor, annotationFor, wsBulkBusy, onPanelClose };
3402
4731
  useEffect(() => {
3403
4732
  if (!open) return;
3404
4733
  const handler = (e) => {
@@ -3406,7 +4735,7 @@ function isTopmostDialog(z) {
3406
4735
  if (e.defaultPrevented) return;
3407
4736
  if (e.isComposing || e.keyCode === 229) return;
3408
4737
  const s = escStateRef.current;
3409
- if (s.busyId !== null) return;
4738
+ if (s.busyId !== null || s.wsBulkBusy) return;
3410
4739
  if (s.confirmFor || s.moveFor || s.migrateFor || s.annotationFor || (activeDialogZStack && activeDialogZStack.length > 0)) return;
3411
4740
  e.preventDefault();
3412
4741
  e.stopPropagation();
@@ -3509,106 +4838,235 @@ function isTopmostDialog(z) {
3509
4838
  updateState.status === "checking" ? h("span", { className: "sm-updateSpinner", "aria-hidden": "true" }) : null
3510
4839
  )),
3511
4840
  ),
3512
- h("h2", { id: "sm-panel-dialog-title", className: "sm-nativeDialogTitle" }, t("panel.title")),
4841
+ h("h2", { id: "sm-panel-dialog-title", className: "sm-nativeDialogTitle sm-visuallyHidden" }, t("panel.title")),
4842
+ h("nav", { className: "sm-panelNav", "aria-label": t("panel.tab.sessions") || "页面切换" },
4843
+ h("button", {
4844
+ type: "button",
4845
+ role: "tab",
4846
+ "aria-selected": panelTab === "sessions",
4847
+ className: "sm-panelNavTab" + (panelTab === "sessions" ? " sm-on" : ""),
4848
+ onClick: () => setPanelTab("sessions")
4849
+ }, t("panel.tab.sessions")),
4850
+ h("button", {
4851
+ type: "button",
4852
+ role: "tab",
4853
+ "aria-selected": panelTab === "workspaces",
4854
+ className: "sm-panelNavTab" + (panelTab === "workspaces" ? " sm-on" : ""),
4855
+ onClick: () => setPanelTab("workspaces")
4856
+ }, t("panel.tab.workspaces"))
4857
+ ),
3513
4858
  h("div", { className: "sm-nativeDialogHeaderActions" },
3514
4859
  renderTip(t("panel.close") || "关闭", h("button", {
3515
4860
  type: "button",
3516
4861
  className: "sm-panelHeaderClose",
3517
- disabled: busyId !== null || migrating,
4862
+ disabled: busyId !== null || migrating || wsBulkBusy,
3518
4863
  onClick: onPanelClose,
3519
4864
  "aria-label": t("panel.close")
3520
4865
  }, h(CloseIcon, { size: 14 })))
3521
4866
  )
3522
4867
  ),
3523
4868
  h("div", { className: "sm-panel" },
3524
- h("div", { className: "sm-panelTools" },
3525
- h("input", {
3526
- type: "search", className: "sm-queryInput", value: query,
3527
- placeholder: t("panel.search"), "aria-label": t("panel.search"), autoComplete: "off",
3528
- onChange: event => setQuery(event.target.value)
3529
- }),
3530
- h("div", { className: "sm-panelSelects" },
3531
- h("label", { className: "sm-viewField" },
3532
- h("span", null, t("panel.workspace")),
3533
- h("select", {
3534
- className: "sm-viewSelect", "aria-label": t("panel.workspace"), value: workspaceFilter,
3535
- disabled: workspacesLoading || workspacesError !== null,
3536
- onChange: event => setWorkspaceFilter(event.target.value)
3537
- },
3538
- h("option", { value: "all" }, t("panel.workspace.all")),
3539
- h("option", { value: "ungrouped" }, t("panel.workspace.ungrouped")),
3540
- workspaces.map(workspace => h("option", { key: workspace.id, value: workspaceValue(workspace.id), title: workspace.path || workspace.id }, workspace.title || workspace.name || workspace.id))
4869
+ panelTab === "workspaces" ? h(React.Fragment, null,
4870
+ h("div", { className: "sm-panelTools" },
4871
+ h("input", {
4872
+ type: "search", className: "sm-queryInput", value: wsQuery,
4873
+ placeholder: t("workspace.search"), "aria-label": t("workspace.search"), autoComplete: "off",
4874
+ onChange: event => setWsQuery(event.target.value)
4875
+ }),
4876
+ h("div", { className: "sm-markFilters sm-wsFilters" },
4877
+ h("div", { className: "sm-markFiltersGroup" },
4878
+ h("button", {
4879
+ type: "button", key: "all",
4880
+ className: "sm-filterBtn" + (wsFilter === "all" ? " sm-on" : ""),
4881
+ "aria-pressed": wsFilter === "all",
4882
+ onClick: () => setWsFilter("all")
4883
+ }, t("workspace.filter.all")),
4884
+ h("button", {
4885
+ type: "button", key: "active",
4886
+ className: "sm-filterBtn" + (wsFilter === "active" ? " sm-on" : ""),
4887
+ "aria-pressed": wsFilter === "active",
4888
+ onClick: () => setWsFilter("active")
4889
+ }, t("workspace.filter.active")),
4890
+ h("button", {
4891
+ type: "button", key: "archived",
4892
+ className: "sm-filterBtn" + (wsFilter === "archived" ? " sm-on" : ""),
4893
+ "aria-pressed": wsFilter === "archived",
4894
+ onClick: () => setWsFilter("archived")
4895
+ }, t("workspace.filter.archived")),
4896
+ h("div", { className: "sm-viewField sm-wsSortField" },
4897
+ h("select", {
4898
+ className: "sm-viewSelect sm-wsSortSelect" + (wsIsEn ? " sm-wsSortSelect-en" : ""), "aria-label": t("panel.sort"), value: wsSort,
4899
+ onMouseDown: e => e.stopPropagation(),
4900
+ onClick: e => e.stopPropagation(),
4901
+ onChange: event => setWsSort(event.target.value)
4902
+ },
4903
+ h("option", { value: "updated-desc" }, t("workspace.sort.updated-desc")),
4904
+ h("option", { value: "updated-asc" }, t("workspace.sort.updated-asc")),
4905
+ h("option", { value: "name-asc" }, t("workspace.sort.name-asc")),
4906
+ h("option", { value: "name-desc" }, t("workspace.sort.name-desc"))
4907
+ )
4908
+ )
4909
+ ),
4910
+ h("div", { className: "sm-markFiltersSpacer" }),
4911
+ h("div", { className: "sm-markFiltersGroup sm-wsFiltersBulk" },
4912
+ h("button", {
4913
+ type: "button",
4914
+ className: "sm-filterBtn" + (wsSelectModeEnabled ? " sm-on" : ""),
4915
+ disabled: busyId !== null || migrating || wsBulkBusy,
4916
+ "aria-pressed": wsSelectModeEnabled,
4917
+ "aria-label": t(wsSelectModeEnabled ? "panel.selectMode.exit" : "panel.selectMode.aria"),
4918
+ onClick: toggleWsSelectMode
4919
+ }, wsSelectModeEnabled ? t("panel.selectMode.exit") : t("panel.selectMode")),
4920
+ h("button", {
4921
+ type: "button",
4922
+ className: "sm-filterBtn sm-bulkSelectBtn",
4923
+ disabled: filteredWorkspaceRows.length === 0 || wsSelectedIds.size === filteredWorkspaceRows.length || wsBulkBusy,
4924
+ onClick: onWsBulkSelectAll,
4925
+ "aria-label": t("bulk.selectAllFiltered")
4926
+ }, t("bulk.selectAllFiltered")),
4927
+ h("button", {
4928
+ type: "button",
4929
+ className: "sm-filterBtn sm-bulkSelectBtn",
4930
+ disabled: wsSelectedIds.size === 0 || wsBulkBusy,
4931
+ onClick: onWsBulkClear,
4932
+ "aria-label": t("bulk.clear")
4933
+ }, t("bulk.clear")),
4934
+ h("button", {
4935
+ type: "button",
4936
+ className: "sm-filterBtn",
4937
+ disabled: !wsSelectModeEnabled || wsSelectedIds.size === 0 || wsBulkBusy,
4938
+ onClick: onWsBulkArchive,
4939
+ "aria-label": t("workspace.bulk.archive")
4940
+ }, t("workspace.bulk.archive")),
4941
+ h("button", {
4942
+ type: "button",
4943
+ className: "sm-filterBtn",
4944
+ disabled: !wsSelectModeEnabled || wsSelectedIds.size === 0 || wsBulkBusy,
4945
+ onClick: onWsBulkUnarchive,
4946
+ "aria-label": t("workspace.bulk.unarchive")
4947
+ }, t("workspace.bulk.unarchive"))
3541
4948
  )
3542
4949
  ),
3543
- h("label", { className: "sm-viewField" },
3544
- h("span", null, t("panel.sort")),
3545
- h("select", {
3546
- className: "sm-viewSelect", "aria-label": t("panel.sort"), value: sortOrder,
3547
- onChange: event => setSortOrder(event.target.value)
3548
- }, SORT_ORDERS.map(value => h("option", { key: value, value, disabled: value === "priority" && !marksReady }, t(value === "priority" ? "marks.sort" : "panel.sort." + value))))
4950
+ h("div", { className: "sm-resultSummary" },
4951
+ h("span", { role: "status", "aria-live": "polite", "aria-atomic": "true" },
4952
+ (wsSelectModeEnabled || wsSelectedIds.size > 0)
4953
+ ? t("bulk.selectedFiltered", { selected: wsSelectedIds.size, filtered: filteredWorkspaceRows.length })
4954
+ : t("workspace.count", { shown: filteredWorkspaceRows.length, total: allWorkspaceRows.length })
4955
+ ),
4956
+ hasWsViewChanges ? h("button", { type: "button", className: "sm-resetFilters", onClick: resetWsView }, t("workspace.reset")) : null
3549
4957
  ),
3550
- h("label", { className: "sm-viewField" },
3551
- h("span", null, t("marks.tags")),
3552
- h("select", { className: "sm-viewSelect", "aria-label": t("marks.filter.tags"), value: tagFilter, disabled: !marksReady, onChange: e => setTagFilter(e.target.value) },
3553
- h("option", { value: "all" }, t("marks.tags.all")), h("option", { value: "none" }, t("marks.tags.none")),
3554
- availableTags.map(([key, tag]) => h("option", { key, value: "tag:" + key }, tag)),
3555
- tagFilter.startsWith("tag:") && !availableTags.some(([key]) => "tag:" + key === tagFilter) ? h("option", { value: tagFilter }, t("marks.tags.missing", { tag: tagFilter.slice(4) })) : null
4958
+ (workspacesLoading && workspaces.length === 0) ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("panel.workspace.loading")) : null,
4959
+ workspacesError ? h("div", { className: "sm-workspaceNotice", role: "alert" },
4960
+ h("span", null, t("panel.workspace.error", { message: workspacesError })),
4961
+ h("button", { type: "button", className: "sm-resetFilters", onClick: () => setWorkspaceRefresh(value => value + 1) }, t("panel.workspace.retry"))
4962
+ ) : null
4963
+ ),
4964
+ error ? h("div", { className: "sm-error", role: "alert" }, t("error.operation", { message: error })) : null,
4965
+ workspaceRowsList
4966
+ ) : h(React.Fragment, null,
4967
+ h("div", { className: "sm-panelTools" },
4968
+ h("input", {
4969
+ type: "search", className: "sm-queryInput", value: query,
4970
+ placeholder: t("panel.search"), "aria-label": t("panel.search"), autoComplete: "off",
4971
+ onChange: event => setQuery(event.target.value)
4972
+ }),
4973
+ h("div", { className: "sm-panelSelects" },
4974
+ h("div", { className: "sm-viewField" },
4975
+ h("span", null, t("panel.workspace")),
4976
+ h("select", {
4977
+ className: "sm-viewSelect", "aria-label": t("panel.workspace"), value: workspaceFilter,
4978
+ disabled: workspacesLoading || workspacesError !== null,
4979
+ onMouseDown: e => e.stopPropagation(),
4980
+ onClick: e => e.stopPropagation(),
4981
+ onChange: event => setWorkspaceFilter(event.target.value)
4982
+ },
4983
+ h("option", { value: "all" }, t("panel.workspace.all")),
4984
+ h("option", { value: "ungrouped" }, t("panel.workspace.ungrouped")),
4985
+ workspaces.map(workspace => h("option", { key: workspace.id, value: workspaceValue(workspace.id), title: workspace.path || workspace.id }, workspace.title || workspace.name || workspace.id))
4986
+ )
4987
+ ),
4988
+ h("div", { className: "sm-viewField" },
4989
+ h("span", null, t("panel.sort")),
4990
+ h("select", {
4991
+ className: "sm-viewSelect", "aria-label": t("panel.sort"), value: sortOrder,
4992
+ onMouseDown: e => e.stopPropagation(),
4993
+ onClick: e => e.stopPropagation(),
4994
+ onChange: event => setSortOrder(event.target.value)
4995
+ }, SORT_ORDERS.map(value => h("option", { key: value, value, disabled: value === "priority" && !marksReady }, t(value === "priority" ? "marks.sort" : "panel.sort." + value))))
4996
+ ),
4997
+ h("div", { className: "sm-viewField" },
4998
+ h("span", null, t("marks.tags")),
4999
+ h("select", {
5000
+ className: "sm-viewSelect", "aria-label": t("marks.filter.tags"), value: tagFilter, disabled: !marksReady,
5001
+ onMouseDown: e => e.stopPropagation(),
5002
+ onClick: e => e.stopPropagation(),
5003
+ onChange: e => setTagFilter(e.target.value)
5004
+ },
5005
+ h("option", { value: "all" }, t("marks.tags.all")), h("option", { value: "none" }, t("marks.tags.none")),
5006
+ availableTags.map(([key, tag]) => h("option", { key, value: "tag:" + key }, tag)),
5007
+ tagFilter.startsWith("tag:") && !availableTags.some(([key]) => "tag:" + key === tagFilter) ? h("option", { value: tagFilter }, t("marks.tags.missing", { tag: tagFilter.slice(4) })) : null
5008
+ )
5009
+ ),
5010
+ h("div", { className: "sm-viewField" },
5011
+ h("span", null, t("marks.priority")),
5012
+ h("select", {
5013
+ className: "sm-viewSelect", "aria-label": t("marks.filter.priority"), value: priorityFilter, disabled: !marksReady,
5014
+ onMouseDown: e => e.stopPropagation(),
5015
+ onClick: e => e.stopPropagation(),
5016
+ onChange: e => setPriorityFilter(e.target.value)
5017
+ },
5018
+ h("option", { value: "all" }, t("marks.priority.all")),
5019
+ [1,2,3,4,5].map(value => h("option", { key: value, value: String(value) }, t("marks.priority." + value)))
5020
+ )
3556
5021
  )
3557
5022
  ),
3558
- h("label", { className: "sm-viewField" },
3559
- h("span", null, t("marks.priority")),
3560
- h("select", { className: "sm-viewSelect", "aria-label": t("marks.filter.priority"), value: priorityFilter, disabled: !marksReady, onChange: e => setPriorityFilter(e.target.value) },
3561
- h("option", { value: "all" }, t("marks.priority.all")),
3562
- [1,2,3,4,5].map(value => h("option", { key: value, value: String(value) }, t("marks.priority." + value)))
5023
+ h("div", { className: "sm-markFilters" },
5024
+ h("div", { className: "sm-markFiltersGroup" },
5025
+ filterBtn("all", t("panel.filter.all")),
5026
+ filterBtn("active", t("panel.filter.active")),
5027
+ filterBtn("archived", t("panel.filter.archived")),
5028
+ h("button", { type: "button", className: "sm-filterBtn sm-markFilterToggle" + (onlyFavorite ? " sm-on" : ""), "aria-label": t("marks.filter.favorite.aria"), "aria-pressed": onlyFavorite, disabled: !marksReady, onClick: () => setOnlyFavorite(value => !value) }, "★ " + t("marks.filter.favorite")),
5029
+ h("button", { type: "button", className: "sm-filterBtn sm-markFilterToggle" + (onlyReview ? " sm-on" : ""), "aria-label": t("marks.filter.review.aria"), "aria-pressed": onlyReview, disabled: !marksReady, onClick: () => setOnlyReview(value => !value) }, "◷ " + t("marks.filter.review"))
5030
+ ),
5031
+ h("div", { className: "sm-markFiltersSpacer" }),
5032
+ h("div", { className: "sm-markFiltersGroup" },
5033
+ h("button", {
5034
+ type: "button",
5035
+ className: "sm-filterBtn" + (selectModeEnabled ? " sm-on" : ""),
5036
+ disabled: busyId !== null || migrating,
5037
+ "aria-pressed": selectModeEnabled,
5038
+ "aria-label": t(selectModeEnabled ? "panel.selectMode.active.aria" : "panel.selectMode.aria"),
5039
+ onClick: toggleSelectMode
5040
+ }, selectModeEnabled ? t("panel.selectMode.exit") : t("panel.selectMode")),
5041
+ h("button", { type: "button", className: "sm-filterBtn sm-bulkSelectBtn", disabled: rows.length === 0 || rows.length === selectedIds.size || bulkBusy, onClick: onBulkSelectAll, "aria-label": t("bulk.selectAllFiltered") }, t("bulk.selectAllFiltered")),
5042
+ h("button", { type: "button", className: "sm-filterBtn sm-bulkSelectBtn", disabled: selectedIds.size === 0 || bulkBusy, onClick: onBulkClear, "aria-label": t("bulk.clear") }, t("bulk.clear"))
3563
5043
  )
3564
- )
3565
- ),
3566
- h("div", { className: "sm-markFilters" },
3567
- h("div", { className: "sm-markFiltersGroup" },
3568
- filterBtn("all", t("panel.filter.all")),
3569
- filterBtn("active", t("panel.filter.active")),
3570
- filterBtn("archived", t("panel.filter.archived")),
3571
- h("button", { type: "button", className: "sm-filterBtn sm-markFilterToggle" + (onlyFavorite ? " sm-on" : ""), "aria-label": t("marks.filter.favorite.aria"), "aria-pressed": onlyFavorite, disabled: !marksReady, onClick: () => setOnlyFavorite(value => !value) }, "★ " + t("marks.filter.favorite")),
3572
- h("button", { type: "button", className: "sm-filterBtn sm-markFilterToggle" + (onlyReview ? " sm-on" : ""), "aria-label": t("marks.filter.review.aria"), "aria-pressed": onlyReview, disabled: !marksReady, onClick: () => setOnlyReview(value => !value) }, "◷ " + t("marks.filter.review"))
3573
5044
  ),
3574
- h("div", { className: "sm-markFiltersSpacer" }),
3575
- h("div", { className: "sm-markFiltersGroup" },
3576
- h("button", {
3577
- type: "button",
3578
- className: "sm-filterBtn" + (selectModeEnabled ? " sm-on" : ""),
3579
- disabled: busyId !== null || migrating,
3580
- "aria-pressed": selectModeEnabled,
3581
- "aria-label": t(selectModeEnabled ? "panel.selectMode.active.aria" : "panel.selectMode.aria"),
3582
- onClick: toggleSelectMode
3583
- }, selectModeEnabled ? t("panel.selectMode.exit") : t("panel.selectMode")),
3584
- h("button", { type: "button", className: "sm-filterBtn sm-bulkSelectBtn", disabled: rows.length === 0 || rows.length === selectedIds.size || bulkBusy, onClick: onBulkSelectAll, "aria-label": t("bulk.selectAllFiltered") }, t("bulk.selectAllFiltered")),
3585
- h("button", { type: "button", className: "sm-filterBtn sm-bulkSelectBtn", disabled: selectedIds.size === 0 || bulkBusy, onClick: onBulkClear, "aria-label": t("bulk.clear") }, t("bulk.clear"))
3586
- )
3587
- ),
3588
- h("div", { className: "sm-resultSummary" },
3589
- h("span", { role: "status", "aria-live": "polite", "aria-atomic": "true" }, t("panel.count", { shown: rows.length, total: allRows.length })),
3590
- hasViewChanges ? h("button", { type: "button", className: "sm-resetFilters", onClick: resetView }, t("panel.reset")) : null
5045
+ h("div", { className: "sm-resultSummary" },
5046
+ h("span", { role: "status", "aria-live": "polite", "aria-atomic": "true" }, t("panel.count", { shown: rows.length, total: allRows.length })),
5047
+ hasViewChanges ? h("button", { type: "button", className: "sm-resetFilters", onClick: resetView }, t("panel.reset")) : null
5048
+ ),
5049
+ annotations.loading && !annotations.loaded ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("marks.loading")) : null,
5050
+ annotations.error ? h("div", { className: "sm-workspaceNotice", role: "alert" }, t("marks.error", { message: annotations.error }), h("button", { type: "button", className: "sm-resetFilters", onClick: () => annotationStore.load(true) }, t("marks.retry"))) : null,
5051
+ creationTimeUnavailable && !(workspacesLoading && workspaces.length === 0) ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("panel.sort.unavailable")) : null,
5052
+ (workspacesLoading && workspaces.length === 0) ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("panel.workspace.loading")) : null,
5053
+ workspacesError ? h("div", { className: "sm-workspaceNotice", role: "alert" },
5054
+ h("span", null, t("panel.workspace.error", { message: workspacesError })),
5055
+ h("button", { type: "button", className: "sm-resetFilters", onClick: () => setWorkspaceRefresh(value => value + 1) }, t("panel.workspace.retry"))
5056
+ ) : null
3591
5057
  ),
3592
- annotations.loading && !annotations.loaded ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("marks.loading")) : null,
3593
- annotations.error ? h("div", { className: "sm-workspaceNotice", role: "alert" }, t("marks.error", { message: annotations.error }), h("button", { type: "button", className: "sm-resetFilters", onClick: () => annotationStore.load(true) }, t("marks.retry"))) : null,
3594
- creationTimeUnavailable && !workspacesLoading ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("panel.sort.unavailable")) : null,
3595
- workspacesLoading ? h("div", { className: "sm-workspaceNotice", role: "status" }, t("panel.workspace.loading")) : null,
3596
- workspacesError ? h("div", { className: "sm-workspaceNotice", role: "alert" },
3597
- h("span", null, t("panel.workspace.error", { message: workspacesError })),
3598
- h("button", { type: "button", className: "sm-resetFilters", onClick: () => setWorkspaceRefresh(value => value + 1) }, t("panel.workspace.retry"))
3599
- ) : null
3600
- ),
3601
- error ? h("div", { className: "sm-error", role: "alert" }, t("error.operation", { message: error })) : null,
3602
- (selectedIds.size > 0 || selectModeEnabled) ? h(BulkActionBar, {
3603
- t, selectedCount: selectedIds.size, filteredCount: rows.length, busy: bulkBusy,
3604
- onSelectAll: onBulkSelectAll, onClear: onBulkClear,
3605
- onAction: onBulkAction,
3606
- onOpenTagDialog: onBulkTagsAdd,
3607
- onOpenPriorityDialog: onBulkPriority,
3608
- onOpenMoveDialog: onBulkMove,
3609
- onOpenPresetDialog: onBulkPreset
3610
- }) : null,
3611
- rowsList
5058
+ error ? h("div", { className: "sm-error", role: "alert" }, t("error.operation", { message: error })) : null,
5059
+ (selectedIds.size > 0 || selectModeEnabled) ? h(BulkActionBar, {
5060
+ t, selectedCount: selectedIds.size, filteredCount: rows.length, busy: bulkBusy,
5061
+ onSelectAll: onBulkSelectAll, onClear: onBulkClear,
5062
+ onAction: onBulkAction,
5063
+ onOpenTagDialog: onBulkTagsAdd,
5064
+ onOpenPriorityDialog: onBulkPriority,
5065
+ onOpenMoveDialog: onBulkMove,
5066
+ onOpenPresetDialog: onBulkPreset
5067
+ }) : null,
5068
+ rowsList
5069
+ )
3612
5070
  )
3613
5071
  )
3614
5072
  )));
@@ -3771,10 +5229,11 @@ function isTopmostDialog(z) {
3771
5229
  onCancel: () => setBulkPresetDraft(null),
3772
5230
  onApply: onBulkPresetApply
3773
5231
  }) : null;
5232
+ const workspaceArchiveConfirmDialog = null;
3774
5233
  // Bulk dialogs are portaled into the overlay root like every other
3775
5234
  // dialog, so their static z-index (10002) only orders them inside that
3776
5235
  // context; the root's own 1050 keeps them below DSH's 1100 tooltip tier.
3777
- return h(React.Fragment, null, panelModal, annotationDialog, moveDialog, deleteDialog, migrateDialog, bulkPreviewDialog, bulkProgressDialog, bulkResultDialog, bulkTagDialog, bulkPriorityDialog, bulkMoveDialog, bulkPresetDialog);
5236
+ return h(React.Fragment, null, panelModal, annotationDialog, moveDialog, deleteDialog, migrateDialog, bulkPreviewDialog, bulkProgressDialog, bulkResultDialog, bulkTagDialog, bulkPriorityDialog, bulkMoveDialog, bulkPresetDialog, workspaceArchiveConfirmDialog);
3778
5237
  }
3779
5238
 
3780
5239
  function HeaderAction(props) {
@@ -4185,36 +5644,55 @@ function isTopmostDialog(z) {
4185
5644
  }
4186
5645
 
4187
5646
  class SafePanel extends React.Component {
4188
- constructor(p) { super(p); this.state = { failed: false }; }
4189
- static getDerivedStateFromError() { return { failed: true }; }
5647
+ constructor(p) { super(p); this.state = { failed: false, error: null }; }
5648
+ static getDerivedStateFromError(error) { return { failed: true, error }; }
4190
5649
  componentDidCatch(error) { try { console.error("[dsh-session-manager] SessionManagerPanel crashed:", error); } catch (_) {} }
4191
5650
  render() {
4192
- if (this.state.failed) return null;
5651
+ if (this.state.failed) {
5652
+ const t = typeof this.props.t === "function" ? this.props.t : (k => k);
5653
+ const errorOverlay = renderInOverlay(h("div", { className: "sm-overlayLayer" },
5654
+ h("div", { className: "sm-nativeDialogLayer" },
5655
+ h("div", { className: "sm-nativeDialog sm-panelDialog", style: { padding: "20px" } },
5656
+ h("h3", null, t("panel.title") || "会话管理"),
5657
+ h("div", { className: "sm-error" }, "面板加载出错: " + (this.state.error?.message || String(this.state.error))),
5658
+ h("button", {
5659
+ type: "button",
5660
+ className: "sm-resetFilters",
5661
+ onClick: () => {
5662
+ this.setState({ failed: false, error: null });
5663
+ try { this.props.panelStore.set(false); } catch (_) {}
5664
+ }
5665
+ }, t("confirm.cancel") || "关闭")
5666
+ )
5667
+ )
5668
+ ));
5669
+ return errorOverlay;
5670
+ }
4193
5671
  return h(SessionManagerPanel, {
4194
5672
  open: true,
4195
5673
  onClose: () => { try { this.props.panelStore.set(false); } catch (_) {} },
4196
- useSessions: this.props.useSessions,
4197
- useWorkspaces: this.props.useWorkspaces,
5674
+ useSessions: this.props.useSessions || this.props.props?.useSessions,
5675
+ useWorkspaces: this.props.useWorkspaces || this.props.props?.useWorkspaces,
4198
5676
  t: this.props.t,
4199
5677
  // Bulk operations need to refresh ctx.sessions.list and the
4200
5678
  // workspace projection after /batch mutates disk state so the
4201
5679
  // panel reflects the new layout.
4202
5680
  onRefreshAfterBulk: async (...args) => {
4203
- try { await this.props.props.onBulkRefresh?.(...args); } catch (_) { /* ignore */ }
5681
+ try { await this.props.props?.onBulkRefresh?.(...args); } catch (_) { /* ignore */ }
4204
5682
  },
4205
- onOpen: (id) => { try { this.props.panelStore.set(false); this.props.props.onOpen(id); } catch (_) {} },
4206
- onArchive: this.props.props.onArchive,
4207
- onUnarchive: this.props.props.onUnarchive,
4208
- onRemove: this.props.props.onRemove,
4209
- onMove: this.props.props.onMove,
4210
- onMigrate: this.props.props.onMigrate
5683
+ onOpen: (id) => { try { this.props.panelStore.set(false); this.props.props?.onOpen?.(id); } catch (_) {} },
5684
+ onArchive: this.props.props?.onArchive,
5685
+ onUnarchive: this.props.props?.onUnarchive,
5686
+ onRemove: this.props.props?.onRemove,
5687
+ onMove: this.props.props?.onMove,
5688
+ onMigrate: this.props.props?.onMigrate
4211
5689
  });
4212
5690
  }
4213
5691
  }
4214
5692
 
4215
5693
  function FooterAction(props) {
4216
- const t = props.t;
4217
- const onOpenPanel = props.onOpenPanel;
5694
+ const t = typeof props.t === "function" ? props.t : (k => k);
5695
+ const onOpenPanel = typeof props.onOpenPanel === "function" ? props.onOpenPanel : () => panelStore.toggle();
4218
5696
  // props.wide comes from SidebarRoot via SidebarFooterActionOwnerProps.
4219
5697
  // When the sidebar is collapsed into the 56px rail, render a 36x36
4220
5698
  // icon-only button so the Chinese label does not word-wrap vertically
@@ -4245,6 +5723,7 @@ function isTopmostDialog(z) {
4245
5723
  wide ? h("span", { className: "sm-footerBtn-label" }, t("footer.label")) : null
4246
5724
  ),
4247
5725
  open ? h(SafePanel, {
5726
+ key: "sm-safe-panel",
4248
5727
  panelStore: panelStore,
4249
5728
  props: props,
4250
5729
  t: t,
@@ -4535,7 +6014,7 @@ function isTopmostDialog(z) {
4535
6014
  h("div", { className: "sm-settingsRow" },
4536
6015
  h("span", null, t("settings.registry")),
4537
6016
  h("select", {
4538
- className: "sm-settingsSelect",
6017
+ className: "sm-settingsSelect sm-viewSelect",
4539
6018
  value: currentRegistry,
4540
6019
  onChange: onRegistryChange,
4541
6020
  "aria-label": t("settings.registry")
@@ -4691,6 +6170,15 @@ function isTopmostDialog(z) {
4691
6170
  await runArchiveCommand("archive", sessionId);
4692
6171
  },
4693
6172
  onUnarchive: async (sessionId) => {
6173
+ for (const [, rec] of workspaceArchiveStore.getAllRecords()) {
6174
+ if (rec.archived === true && Array.isArray(rec.sessionIds) && rec.sessionIds.includes(sessionId)) {
6175
+ if (typeof window !== "undefined" && typeof window.alert === "function") {
6176
+ const msg = (typeof t === "function" ? t("error.workspaceArchived") : null) || "所属工作区已归档,无法取消归档该会话。请先在工作区管理中恢复工作区。";
6177
+ window.alert(msg);
6178
+ }
6179
+ return;
6180
+ }
6181
+ }
4694
6182
  // DSH ships the inverse command in 0.2.x; the old assumption that only
4695
6183
  // archive existed is what made unarchive bypass client state.
4696
6184
  await runArchiveCommand("unarchive", sessionId);
@@ -4771,6 +6259,16 @@ function isTopmostDialog(z) {
4771
6259
  }
4772
6260
  }
4773
6261
  },
6262
+ useSessions: (selector = s => s) => useSyncExternalStore(
6263
+ (cb) => (ctx.sessions?.list?.subscribe ? ctx.sessions.list.subscribe(cb) : () => {}),
6264
+ () => (ctx.sessions?.list?.getSnapshot ? selector(ctx.sessions.list.getSnapshot()) : selector({ ids: [], byId: {} })),
6265
+ () => (ctx.sessions?.list?.getSnapshot ? selector(ctx.sessions.list.getSnapshot()) : selector({ ids: [], byId: {} }))
6266
+ ),
6267
+ useWorkspaces: (selector = s => s) => useSyncExternalStore(
6268
+ (cb) => (ctx.workspaces?.list?.subscribe ? ctx.workspaces.list.subscribe(cb) : () => {}),
6269
+ () => (ctx.workspaces?.list?.getSnapshot ? selector(ctx.workspaces.list.getSnapshot()) : selector({ items: [] })),
6270
+ () => (ctx.workspaces?.list?.getSnapshot ? selector(ctx.workspaces.list.getSnapshot()) : selector({ items: [] }))
6271
+ ),
4774
6272
  });
4775
6273
  ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
4776
6274
  name: "conversation.session.header.actions",
@@ -4832,6 +6330,34 @@ function isTopmostDialog(z) {
4832
6330
  };
4833
6331
  }, "session-manager: auto update check");
4834
6332
 
6333
+ ctx.effect(() => {
6334
+ const disposes = [];
6335
+ if (ctx.workspaces?.list) {
6336
+ const d = workspaceArchiveStore.installWorkspaceModel(ctx.workspaces.list);
6337
+ if (typeof d === "function") disposes.push(d);
6338
+ }
6339
+ if (ctx.workspaces) {
6340
+ const d = workspaceArchiveStore.installWorkspaceCreate(ctx.workspaces);
6341
+ if (typeof d === "function") disposes.push(d);
6342
+ }
6343
+ if (ctx.uiWorkspace) {
6344
+ const d = workspaceArchiveStore.installConnectWorkspace(ctx.uiWorkspace);
6345
+ if (typeof d === "function") disposes.push(d);
6346
+ }
6347
+ return () => {
6348
+ for (const d of disposes) {
6349
+ try { d(); } catch (_) {}
6350
+ }
6351
+ };
6352
+ }, "session-manager: workspace sidebar hide");
6353
+
6354
+ ctx.effect(() => {
6355
+ const off = installCustomDropdownInterceptor();
6356
+ return () => {
6357
+ try { if (typeof off === "function") off(); } catch (_) {}
6358
+ };
6359
+ }, "session-manager: custom select popups");
6360
+
4835
6361
  // Keep <html data-sm-theme> in step with DSH through the official theme
4836
6362
  // event. ui-layout's ThemePresenter subscribes to the same event and
4837
6363
  // writes documentElement.colorScheme plus body[data-ds-dark-theme], so
@@ -4863,6 +6389,14 @@ function isTopmostDialog(z) {
4863
6389
  exports.CloseIcon = CloseIcon;
4864
6390
  exports.StarIcon = StarIcon;
4865
6391
  exports.IssueIcon = IssueIcon;
6392
+ exports.workspaceArchiveStore = workspaceArchiveStore;
6393
+ exports.SmSwitch = SmSwitch;
6394
+ exports.executeArchiveWorkspace = executeArchiveWorkspace;
6395
+ exports.executeUnarchiveWorkspace = executeUnarchiveWorkspace;
6396
+ exports.openCustomSelect = openCustomSelect;
6397
+ exports.closeCustomSelect = closeCustomSelect;
6398
+ exports.installCustomDropdownInterceptor = installCustomDropdownInterceptor;
6399
+ exports.SM_SELECT_SELECTOR = SM_SELECT_SELECTOR;
4866
6400
  return module.exports;
4867
6401
  }
4868
6402
  });