dsh-sessions-manager 3.2.1

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 ADDED
@@ -0,0 +1,1582 @@
1
+ window.__ModuleLoader__.load({ id: 'dsh-sessions-manager', factory: (require) => { var module = { exports: {} }; var exports = module.exports;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/client/index.jsx
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ apply: () => apply,
34
+ inject: () => inject
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_react = __toESM(require("react"), 1);
38
+ var import_jsx_runtime = require("react/jsx-runtime");
39
+ var inject = ["slots"];
40
+ var PANEL_PREFS_KEY = "dsm-panel-prefs-v1";
41
+ function loadPanelPrefs() {
42
+ try {
43
+ return JSON.parse(localStorage.getItem(PANEL_PREFS_KEY) || "{}") || {};
44
+ } catch (e) {
45
+ return {};
46
+ }
47
+ }
48
+ var CSS = `
49
+ .archv{--dsm-radius-tag:4px;display:flex;flex-direction:column;gap:4px;max-width:800px;padding:8px 2px 28px}
50
+ .archv-head{display:flex;align-items:center;gap:10px;margin:0 0 2px}
51
+ .archv-title{font-size:16px;font-weight:650;color:var(--dsw-alias-label-primary);letter-spacing:-0.01em;margin:0}
52
+ .archv-count{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:1px 8px;flex:none}
53
+ .archv-sub{font-size:12px;line-height:1.55;color:var(--dsw-alias-label-tertiary);margin:0 0 12px;max-width:64ch}
54
+ .archv-err{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);border-radius:10px;color:var(--dsw-alias-state-error-primary);font-size:12px;margin-bottom:10px}
55
+ .archv-errretry{appearance:none;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:transparent;color:inherit;border-radius:8px;padding:4px 10px;font-size:11px;cursor:pointer;flex:none}
56
+ .sess-filter{display:flex;align-items:center;gap:6px;margin:0 0 12px}
57
+ .sess-fbtn{appearance:none;min-height:30px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:999px;font-size:12px;font-weight:500;cursor:pointer}
58
+ .sess-fbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
59
+ .sess-fbtn-on{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}
60
+ .sess-tools{display:grid;grid-template-columns:minmax(180px,1fr) minmax(140px,.7fr) minmax(130px,.55fr);gap:8px;margin:0 0 8px}
61
+ .sess-field{display:flex;flex-direction:column;gap:5px;min-width:0}
62
+ .sess-field label{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary)}
63
+ .sess-field input,.sess-field select{box-sizing:border-box;width:100%;min-height:36px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font:inherit;font-size:12px}
64
+ .sess-results{font-size:11px;color:var(--dsw-alias-label-tertiary);margin:0 0 4px}
65
+ .archv button:focus-visible,.archv input:focus-visible,.archv select:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
66
+ .sess-batch{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 2px 4px;margin-bottom:4px}
67
+ .sess-btntext{font-size:12px;color:var(--dsw-alias-label-tertiary);flex:none}
68
+ .archv-list{display:flex;flex-direction:column;gap:8px}
69
+ .archv-card{display:flex;flex-direction:column;align-items:stretch;gap:0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-fill-elevated);transition:border-color .15s ease,background-color .15s ease}
70
+ .archv-card:hover{border-color:var(--dsw-alias-border-l4)}
71
+ .archv-card-exp{border-color:var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-1)}
72
+ .archv-row{display:flex;align-items:center;gap:14px;width:100%;min-width:0}
73
+ .archv-main{min-width:0;display:flex;flex-direction:column;gap:4px}
74
+ .archv-name{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
75
+ .archv-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}
76
+ .archv-wtag{display:inline-flex;align-items:center;gap:4px;max-width:100%;font-size:11px;font-weight:500;line-height:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-tag);padding:3px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
77
+ .archv-wgone{border-style:dashed;color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}
78
+ .archv-active{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent)}
79
+ .archv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}
80
+ .archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}
81
+ .archv-dot{color:var(--dsw-alias-border-l3);flex:none}
82
+ .archv-check{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);flex:none;cursor:pointer}
83
+ .archv-body{flex:1;min-width:0;display:flex;align-items:center;gap:12px}
84
+ .archv-actions{display:flex;gap:8px;flex:none;flex-wrap:nowrap;justify-content:flex-end}
85
+ .archv-btn{appearance:none;min-height:32px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:9px;font-size:12px;font-weight:500;cursor:pointer;white-space:nowrap;display:inline-flex;align-items:center;justify-content:center;gap:6px;text-align:center;transition:background-color .15s ease,border-color .15s ease,color .15s ease}
86
+ .archv-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
87
+ .archv-btn:disabled{opacity:.5;cursor:default}
88
+ .archv-del{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent)}
89
+ .archv-del:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}
90
+ .archv-go{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 45%,transparent)}
91
+ .archv-go:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent);color:var(--dsw-alias-state-business-primary)}
92
+ .archv-empty{display:flex;align-items:center;gap:10px;padding:20px 14px;border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
93
+ .archv-skel{display:flex;flex-direction:column;gap:8px}
94
+ .archv-skel-card{height:58px;border-radius:12px;background:var(--dsw-alias-fill-subtle);position:relative;overflow:hidden}
95
+ .archv-skel-card::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--dsw-alias-fill-elevated) 75%,transparent),transparent);animation:archv-shimmer 1.4s infinite}
96
+ .archv-status{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:60;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);padding:9px 16px;border-radius:999px;font-size:12px;box-shadow:0 8px 24px rgb(0 0 0/.18);display:flex;align-items:center;gap:8px;animation:archv-pop .18s ease-out;max-width:min(90vw,420px)}
97
+ .archv-spin{width:12px;height:12px;border:2px solid color-mix(in srgb,var(--dsw-alias-label-secondary) 35%,transparent);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;animation:archv-rot .8s linear infinite;flex:none}
98
+ @keyframes archv-shimmer{100%{transform:translateX(100%)}}
99
+ @keyframes archv-rot{to{transform:rotate(360deg)}}
100
+ @keyframes archv-pop{from{opacity:0;transform:translateX(-50%) translateY(10px)}}
101
+ @media (prefers-reduced-motion:reduce){.archv-skel-card::after{animation:none}.archv-card,.archv-btn{transition:none}.archv-status,.archv-spin{animation:none}}
102
+ @media (max-width:640px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}.sess-tools{grid-template-columns:1fr}.sess-fbtn,.archv-btn{min-height:40px}}
103
+ .mv-sheet{width:100%;box-sizing:border-box;display:flex;flex-direction:column;gap:12px;margin-top:12px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-fill-subtle)}
104
+ .mv-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
105
+ .mv-sheet-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}
106
+ .mv-sheet-close{appearance:none;width:26px;height:26px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:7px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1}
107
+ .mv-sheet-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
108
+ .mv-seg{display:flex;gap:2px;padding:2px;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;width:100%}
109
+ .mv-segbtn{appearance:none;flex:1;min-height:30px;padding:0 12px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px}
110
+ .mv-segbtn:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
111
+ .mv-segbtn-on{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);box-shadow:0 1px 2px rgb(0 0 0/.08)}
112
+ .mv-field{display:flex;flex-direction:column;gap:6px}
113
+ .mv-field label.mv-field-label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}
114
+ .mv-field select,.mv-field input[type=text]{box-sizing:border-box;appearance:none;width:100%;min-height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font-size:12px;font-family:inherit}
115
+ .mv-field select:focus-visible,.mv-field input[type=text]:focus-visible,.mv-sheet-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}
116
+ .mv-browse-row{display:flex;align-items:center;gap:8px}
117
+ .mv-browse-row input[type=text]{flex:1;min-width:0}
118
+ .mv-foot{display:flex;justify-content:flex-end;align-items:center;gap:8px;margin-top:2px}
119
+ @media (max-width:640px){.archv-row{flex-wrap:wrap}.mv-sheet{padding:12px}}
120
+ .dtl-sheet{margin-top:12px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-fill-subtle)}
121
+ .dtl-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
122
+ .dtl-sheet-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}
123
+ .dtl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:8px;margin-top:10px}
124
+ .dtl-cell{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-fill-elevated);min-width:0}
125
+ .dtl-k{font-size:11px;color:var(--dsw-alias-label-tertiary)}
126
+ .dtl-v{font-size:12px;color:var(--dsw-alias-label-primary);word-break:break-all}
127
+ .dtl-sec{margin-top:12px}
128
+ .dtl-sec-t{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);text-transform:uppercase;letter-spacing:.03em;margin-bottom:6px}
129
+ .dtl-tags{display:flex;flex-wrap:wrap;gap:6px}
130
+ .dtl-tag{display:inline-flex;font-size:11px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-tag);padding:2px 8px}
131
+ .dtl-list{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:3px;font-size:11.5px;color:var(--dsw-alias-label-secondary)}
132
+ .dtl-list code,.dtl-paths code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;color:var(--dsw-alias-label-primary);word-break:break-all}
133
+ .dtl-filetool{color:var(--dsw-alias-label-tertiary)}
134
+ .dtl-paths{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--dsw-alias-label-secondary);word-break:break-all}
135
+ .more-wrap{position:relative;flex:none}
136
+ .more-btn{appearance:none;width:28px;height:28px;border:none;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}
137
+ .more-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
138
+ .more-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:60;min-width:160px;padding:5px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l3);border-radius:10px;box-shadow:0 10px 32px rgb(0 0 0/.24);display:flex;flex-direction:column;gap:1px}
139
+ .more-item{appearance:none;display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border:none;background:transparent;color:var(--dsw-alias-label-primary);border-radius:7px;font-size:12.5px;cursor:pointer;white-space:nowrap;text-align:left}
140
+ .more-item:hover{background:var(--dsw-alias-interactive-bg-hover)}
141
+ .more-item-danger{color:var(--dsw-alias-state-error-primary)}
142
+ .more-item-danger:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}
143
+ .dlg-backdrop{position:fixed;inset:0;z-index:80;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;padding:16px}
144
+ .dlg{width:min(420px,92vw);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l3);border-radius:14px;padding:18px;box-shadow:0 16px 48px rgb(0 0 0/.28);display:flex;flex-direction:column;gap:12px}
145
+ .dlg-title{font-size:15px;font-weight:650;color:var(--dsw-alias-label-primary);margin:0}
146
+ .dlg-text{font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary);margin:0;word-break:break-all}
147
+ .dlg-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:2px}
148
+ `;
149
+ function fmtDate(iso) {
150
+ if (!iso) return null;
151
+ const d = new Date(iso);
152
+ if (isNaN(d.getTime())) return null;
153
+ try {
154
+ return new Intl.DateTimeFormat("zh-CN", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }).format(d);
155
+ } catch {
156
+ return String(iso);
157
+ }
158
+ }
159
+ function fmtBytes(n) {
160
+ if (!n && n !== 0) return null;
161
+ if (n < 1024) return `${n} B`;
162
+ const units = ["KB", "MB", "GB", "TB"];
163
+ let v = n;
164
+ let u = -1;
165
+ do {
166
+ v /= 1024;
167
+ u++;
168
+ } while (v >= 1024 && u < units.length - 1);
169
+ return `${v >= 100 ? v.toFixed(0) : v.toFixed(1)} ${units[u]}`;
170
+ }
171
+ function pathName(p) {
172
+ if (!p) return null;
173
+ const parts = String(p).replace(/\\+$/, "").split(/[/\\]/);
174
+ return parts[parts.length - 1] || p;
175
+ }
176
+ async function postJSON(path, body) {
177
+ const res = await fetch(path, {
178
+ method: "POST",
179
+ headers: { "content-type": "application/json", accept: "application/json" },
180
+ body: JSON.stringify(body || {})
181
+ });
182
+ const data = await res.json().catch(() => null);
183
+ if (!res.ok || !data) throw new Error(data && (data.error || data.message) || `request failed (${res.status})`);
184
+ return data;
185
+ }
186
+ var NAV_CSS = `
187
+ [data-dsh-nav-sessions] > svg:first-child { display: none; }
188
+ [data-dsh-nav-sessions]::before {
189
+ content: ''; flex: none; width: 16px; height: 16px; background: currentColor;
190
+ -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E") center / contain no-repeat;
191
+ mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E") center / contain no-repeat;
192
+ }
193
+ `;
194
+ function markSettingsNav() {
195
+ const LABEL = "\u4F1A\u8BDD\u7BA1\u7406";
196
+ let disposed = false;
197
+ const sync = () => {
198
+ if (disposed) return;
199
+ const buttons = document.querySelectorAll('[role="dialog"] nav button');
200
+ for (const b of buttons) {
201
+ const t = (b.textContent || "").trim();
202
+ if (t === LABEL) b.setAttribute("data-dsh-nav-sessions", "");
203
+ else b.removeAttribute("data-dsh-nav-sessions");
204
+ }
205
+ };
206
+ sync();
207
+ const obs = new MutationObserver(sync);
208
+ obs.observe(document.body, { childList: true, subtree: true, characterData: true });
209
+ return () => {
210
+ disposed = true;
211
+ obs.disconnect();
212
+ document.querySelectorAll("[data-dsh-nav-sessions]").forEach((e) => e.removeAttribute("data-dsh-nav-sessions"));
213
+ };
214
+ }
215
+ function installSettingsNavIcons(ctx) {
216
+ const styleEl = document.createElement("style");
217
+ styleEl.textContent = NAV_CSS;
218
+ document.head.appendChild(styleEl);
219
+ const dispose = markSettingsNav();
220
+ ctx.effect(() => () => {
221
+ dispose();
222
+ if (styleEl.parentNode) styleEl.parentNode.removeChild(styleEl);
223
+ });
224
+ }
225
+ function SessionPanel({ workspacesSvc }) {
226
+ const [sessions, setSessions] = (0, import_react.useState)(null);
227
+ const [workspaces, setWorkspaces] = (0, import_react.useState)([]);
228
+ const initialPrefs = (0, import_react.useRef)(loadPanelPrefs()).current;
229
+ const [filter, setFilter] = (0, import_react.useState)(() => ["all", "active", "archived", "trash"].includes(initialPrefs.filter) ? initialPrefs.filter : "all");
230
+ const [query, setQuery] = (0, import_react.useState)("");
231
+ const [workspaceFilter, setWorkspaceFilter] = (0, import_react.useState)(() => initialPrefs.workspaceFilter || "all");
232
+ const [sortBy, setSortBy] = (0, import_react.useState)(() => ["newest", "oldest", "title"].includes(initialPrefs.sortBy) ? initialPrefs.sortBy : "newest");
233
+ const [selected, setSelected] = (0, import_react.useState)({});
234
+ const [delTarget, setDelTarget] = (0, import_react.useState)(null);
235
+ const [confirmBatch, setConfirmBatch] = (0, import_react.useState)(false);
236
+ const [busy, setBusy] = (0, import_react.useState)(null);
237
+ const [openMove, setOpenMove] = (0, import_react.useState)(null);
238
+ const [moveMode, setMoveMode] = (0, import_react.useState)("existing");
239
+ const [targetWs, setTargetWs] = (0, import_react.useState)("");
240
+ const [newPath, setNewPath] = (0, import_react.useState)("");
241
+ const [error, setError] = (0, import_react.useState)(null);
242
+ const [toast, setToast] = (0, import_react.useState)(null);
243
+ const [picking, setPicking] = (0, import_react.useState)(false);
244
+ const [trash, setTrash] = (0, import_react.useState)([]);
245
+ const [trashBusy, setTrashBusy] = (0, import_react.useState)(null);
246
+ const [trashSettings, setTrashSettings] = (0, import_react.useState)({ retentionDays: 0 });
247
+ const [trashCheck, setTrashCheck] = (0, import_react.useState)(null);
248
+ const [purgeTarget, setPurgeTarget] = (0, import_react.useState)(null);
249
+ const [details, setDetails] = (0, import_react.useState)({});
250
+ const [openDetails, setOpenDetails] = (0, import_react.useState)(null);
251
+ const [detailsLoading, setDetailsLoading] = (0, import_react.useState)(null);
252
+ const [openMenu, setOpenMenu] = (0, import_react.useState)(null);
253
+ const timer = (0, import_react.useRef)(null);
254
+ const menuRef = (0, import_react.useRef)(null);
255
+ const dialogRef = (0, import_react.useRef)(null);
256
+ const showToast = (msg) => {
257
+ if (timer.current) clearTimeout(timer.current);
258
+ setToast(msg);
259
+ timer.current = setTimeout(() => setToast(null), 2400);
260
+ };
261
+ const refresh = () => {
262
+ setError(null);
263
+ Promise.all([
264
+ postJSON("/archived-sessions/sessions", {}),
265
+ postJSON("/archived-sessions/workspaces", {})
266
+ ]).then(([s, works]) => {
267
+ const purged = dsmLoadPurged();
268
+ const visible = (s.items || []).filter((x) => !purged.has(String(x.sessionId)));
269
+ setSessions(visible);
270
+ setWorkspaces(works.items || []);
271
+ setSelected({});
272
+ setDelTarget(null);
273
+ setConfirmBatch(false);
274
+ if (!targetWs && works.items && works.items.length) setTargetWs(works.items[0].workspaceId);
275
+ loadTrash();
276
+ }).catch((e) => setError(String(e && e.message || e)));
277
+ };
278
+ (0, import_react.useEffect)(() => {
279
+ refresh();
280
+ return () => {
281
+ if (timer.current) clearTimeout(timer.current);
282
+ };
283
+ }, []);
284
+ (0, import_react.useEffect)(() => {
285
+ try {
286
+ localStorage.setItem(PANEL_PREFS_KEY, JSON.stringify({ filter, workspaceFilter, sortBy }));
287
+ } catch (e) {
288
+ }
289
+ }, [filter, workspaceFilter, sortBy]);
290
+ (0, import_react.useEffect)(() => {
291
+ if (openMenu === null) return;
292
+ const onDown = (e) => {
293
+ if (menuRef.current && !menuRef.current.contains(e.target)) setOpenMenu(null);
294
+ };
295
+ const onKey = (e) => {
296
+ if (e.key === "Escape") setOpenMenu(null);
297
+ };
298
+ document.addEventListener("mousedown", onDown);
299
+ document.addEventListener("keydown", onKey);
300
+ return () => {
301
+ document.removeEventListener("mousedown", onDown);
302
+ document.removeEventListener("keydown", onKey);
303
+ };
304
+ }, [openMenu]);
305
+ (0, import_react.useEffect)(() => {
306
+ if (!delTarget && !purgeTarget) return;
307
+ const previous = document.activeElement;
308
+ const onKey = (e) => {
309
+ if (e.key === "Escape") {
310
+ setDelTarget(null);
311
+ setPurgeTarget(null);
312
+ }
313
+ };
314
+ document.addEventListener("keydown", onKey);
315
+ requestAnimationFrame(() => dialogRef.current && dialogRef.current.querySelector("button")?.focus());
316
+ return () => {
317
+ document.removeEventListener("keydown", onKey);
318
+ if (previous && typeof previous.focus === "function") previous.focus();
319
+ };
320
+ }, [delTarget, purgeTarget]);
321
+ const wsPath = (id) => {
322
+ const w = workspaces.find((x) => x.workspaceId === id);
323
+ return w ? w.path : "";
324
+ };
325
+ const archivedList = sessions ? sessions.filter((x) => x.archived) : [];
326
+ const activeList = sessions ? sessions.filter((x) => !x.archived) : [];
327
+ const list = (0, import_react.useMemo)(() => {
328
+ if (filter === "trash") return [];
329
+ const base = filter === "archived" ? archivedList : filter === "active" ? activeList : sessions || [];
330
+ const needle = query.trim().toLocaleLowerCase();
331
+ const filtered = base.filter((item) => {
332
+ if (workspaceFilter !== "all" && (item.workspacePath || "") !== workspaceFilter) return false;
333
+ if (!needle) return true;
334
+ return [item.title, item.sessionId, item.workspaceTitle, item.workspacePath].some((value) => String(value || "").toLocaleLowerCase().includes(needle));
335
+ });
336
+ return [...filtered].sort((a, b) => {
337
+ if (sortBy === "oldest") return Number(a.createdAt || 0) - Number(b.createdAt || 0);
338
+ if (sortBy === "title") return String(a.title || "").localeCompare(String(b.title || ""), "zh-CN");
339
+ return Number(b.createdAt || 0) - Number(a.createdAt || 0);
340
+ });
341
+ }, [sessions, filter, query, workspaceFilter, sortBy]);
342
+ const selIds = Object.keys(selected).filter((k) => selected[k]);
343
+ const toggle = (id) => setSelected((s) => ({ ...s, [id]: !s[id] }));
344
+ const clearSel = () => setSelected({});
345
+ const selectAll = () => {
346
+ const o = {};
347
+ list.forEach((x) => {
348
+ o[x.sessionId] = true;
349
+ });
350
+ setSelected(o);
351
+ };
352
+ const act = (action, it) => {
353
+ if (busy) return;
354
+ setBusy(it.sessionId);
355
+ postJSON("/archived-sessions/" + action, { sessionId: it.sessionId }).then(() => {
356
+ setBusy(null);
357
+ const n = it.title || it.sessionId;
358
+ showToast(action === "archive" ? `\u5DF2\u5F52\u6863\u300C${n}\u300D` : `\u5DF2\u6062\u590D\u300C${n}\u300D`);
359
+ refresh();
360
+ }).catch((e) => {
361
+ setBusy(null);
362
+ setError(String(e && e.message || e));
363
+ });
364
+ };
365
+ const doDeleteConfirmed = () => {
366
+ if (!delTarget || busy) return;
367
+ setBusy(delTarget.sessionId);
368
+ postJSON("/archived-sessions/delete", { sessionId: delTarget.sessionId }).then(() => {
369
+ setBusy(null);
370
+ const n = delTarget.title || delTarget.sessionId;
371
+ showToast(`\u5DF2\u5220\u9664 ${n}\uFF08\u5DF2\u79FB\u5165\u56DE\u6536\u7AD9\uFF09`);
372
+ setDelTarget(null);
373
+ refresh();
374
+ }).catch((e) => {
375
+ setBusy(null);
376
+ setDelTarget(null);
377
+ setError(String(e && e.message || e));
378
+ });
379
+ };
380
+ const loadTrash = () => {
381
+ postJSON("/archived-sessions/trash/list", {}).then((r) => {
382
+ setTrash(r.items || []);
383
+ setTrashSettings(r.settings || { retentionDays: 0 });
384
+ }).catch(() => {
385
+ });
386
+ };
387
+ const updateRetention = (days) => {
388
+ setTrashBusy("__settings");
389
+ postJSON("/archived-sessions/trash/settings", { retentionDays: Number(days) }).then((r) => {
390
+ setTrashBusy(null);
391
+ setTrashSettings(r.settings);
392
+ showToast("\u5DF2\u66F4\u65B0\u81EA\u52A8\u6E05\u7406\u7B56\u7565");
393
+ }).catch((e) => {
394
+ setTrashBusy(null);
395
+ setError(String(e && e.message || e));
396
+ });
397
+ };
398
+ const verifyTrash = () => {
399
+ setTrashBusy("__verify");
400
+ postJSON("/archived-sessions/trash/verify", {}).then((r) => {
401
+ setTrashBusy(null);
402
+ setTrashCheck(r);
403
+ showToast(r.missing ? `\u53D1\u73B0 ${r.missing} \u6761\u65E5\u5FD7\u7F3A\u5931` : "\u56DE\u6536\u7AD9\u6821\u9A8C\u901A\u8FC7");
404
+ }).catch((e) => {
405
+ setTrashBusy(null);
406
+ setError(String(e && e.message || e));
407
+ });
408
+ };
409
+ const restoreTrash = (sid) => {
410
+ if (trashBusy) return;
411
+ setTrashBusy(sid);
412
+ postJSON("/archived-sessions/trash/restore", { sessionId: sid }).then(() => {
413
+ setTrashBusy(null);
414
+ showToast("\u5DF2\u6062\u590D\u4F1A\u8BDD");
415
+ loadTrash();
416
+ refresh();
417
+ }).catch((e) => {
418
+ setTrashBusy(null);
419
+ setError(String(e && e.message || e));
420
+ });
421
+ };
422
+ const purgeTrash = (sid) => {
423
+ if (trashBusy) return;
424
+ setTrashBusy(sid);
425
+ postJSON("/archived-sessions/trash/purge", { sessionId: sid }).then(() => {
426
+ setTrashBusy(null);
427
+ showToast("\u5DF2\u5F7B\u5E95\u5220\u9664");
428
+ dsmMarkPurged([sid]);
429
+ dsmLoadTrashIds();
430
+ loadTrash();
431
+ }).catch((e) => {
432
+ setTrashBusy(null);
433
+ setError(String(e && e.message || e));
434
+ });
435
+ };
436
+ const purgeAllTrash = () => {
437
+ if (trashBusy || !trash.length) return;
438
+ setTrashBusy("__all");
439
+ const all = trash.map((t) => t.sessionId);
440
+ postJSON("/archived-sessions/trash/purge-many", { sessionIds: all }).then((result) => {
441
+ setTrashBusy(null);
442
+ const rows = result.results || [];
443
+ const succeeded = rows.filter((item) => item.ok).map((item) => item.sessionId);
444
+ const failed = rows.filter((item) => !item.ok);
445
+ if (succeeded.length) dsmMarkPurged(succeeded);
446
+ dsmLoadTrashIds();
447
+ loadTrash();
448
+ if (failed.length) {
449
+ const first = failed[0];
450
+ setError(`\u6E05\u7406\u5B8C\u6210 ${succeeded.length} \u6761\uFF0C\u5931\u8D25 ${failed.length} \u6761\uFF1A${first.error || first.sessionId}`);
451
+ } else showToast("\u5DF2\u6E05\u7A7A\u56DE\u6536\u7AD9");
452
+ }).catch((e) => {
453
+ setTrashBusy(null);
454
+ setError(String(e && e.message || e));
455
+ });
456
+ };
457
+ const doMove = (it) => {
458
+ const targetPath = moveMode === "new" ? newPath.trim() : wsPath(targetWs);
459
+ if (!targetPath) {
460
+ setError("\u8BF7\u9009\u62E9\u5DF2\u6709\u5DE5\u4F5C\u533A\u6216\u8F93\u5165\u65B0\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84");
461
+ return;
462
+ }
463
+ setBusy(it.sessionId);
464
+ setError(null);
465
+ postJSON("/archived-sessions/move", { sessionId: it.sessionId, targetPath }).then((r) => {
466
+ setBusy(null);
467
+ setOpenMove(null);
468
+ setMoveMode("existing");
469
+ setNewPath("");
470
+ showToast(`\u5DF2\u628A\u300C${it.title || it.sessionId}\u300D\u79FB\u5230 ${r.workspaceTitle || targetPath}`);
471
+ refresh();
472
+ }).catch((e) => {
473
+ setBusy(null);
474
+ setError(String(e && e.message || e));
475
+ });
476
+ };
477
+ const doBatch = (action) => {
478
+ if (!selIds.length || busy) return;
479
+ if (action === "delete-many") {
480
+ if (!confirmBatch) {
481
+ setConfirmBatch(true);
482
+ return;
483
+ }
484
+ setConfirmBatch(false);
485
+ }
486
+ setBusy("__batch__");
487
+ postJSON("/archived-sessions/" + action, { sessionIds: selIds }).then((r) => {
488
+ setBusy(null);
489
+ const n = r && (r.archived || r.restored || r.deleted) || selIds.length;
490
+ showToast(`\u5DF2\u5904\u7406 ${n} \u4E2A\u4F1A\u8BDD`);
491
+ refresh();
492
+ }).catch((e) => {
493
+ setBusy(null);
494
+ setConfirmBatch(false);
495
+ setError(String(e && e.message || e));
496
+ });
497
+ };
498
+ const openMoveFor = (it) => {
499
+ if (openMove === it.sessionId) {
500
+ setOpenMove(null);
501
+ return;
502
+ }
503
+ setTargetWs(workspaces.length ? targetWs || workspaces[0].workspaceId : "");
504
+ setMoveMode("existing");
505
+ setNewPath("");
506
+ setOpenMove(it.sessionId);
507
+ };
508
+ const pickDirectory = async () => {
509
+ if (!workspacesSvc || picking) return;
510
+ setPicking(true);
511
+ try {
512
+ const p = await workspacesSvc.pickDirectory();
513
+ if (p) {
514
+ setNewPath(p);
515
+ setMoveMode("new");
516
+ }
517
+ } catch (e) {
518
+ setError(String(e && e.message || e));
519
+ } finally {
520
+ setPicking(false);
521
+ }
522
+ };
523
+ const toggleDetails = (it) => {
524
+ if (openDetails === it.sessionId) {
525
+ setOpenDetails(null);
526
+ return;
527
+ }
528
+ if (details[it.sessionId]) {
529
+ setOpenDetails(it.sessionId);
530
+ return;
531
+ }
532
+ setDetailsLoading(it.sessionId);
533
+ postJSON("/archived-sessions/details", { sessionId: it.sessionId }).then((d) => {
534
+ setDetails((m) => ({ ...m, [it.sessionId]: d }));
535
+ setDetailsLoading(null);
536
+ setOpenDetails(it.sessionId);
537
+ }).catch((e) => {
538
+ setDetailsLoading(null);
539
+ setError(String(e && e.message || e));
540
+ });
541
+ };
542
+ const workspaceTag = (it) => {
543
+ if (it.hasWorkspace && it.workspaceGone) {
544
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "archv-wtag archv-wgone", title: (it.workspacePath || "") + "\uFF08\u539F\u5DE5\u4F5C\u533A\u5DF2\u5220\u9664\uFF09", children: [
545
+ "\u5DE5\u4F5C\u533A\u5DF2\u5220 \xB7 ",
546
+ pathName(it.workspacePath) || "?"
547
+ ] });
548
+ }
549
+ const wName = it.workspaceTitle || pathName(it.workspacePath);
550
+ if (wName) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", title: it.workspacePath || "", children: wName });
551
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", children: "\u672A\u5206\u7EC4" });
552
+ };
553
+ const runMenu = (id, it) => {
554
+ setOpenMenu(null);
555
+ if (id === "restore") act("restore", it);
556
+ else if (id === "archive") act("archive", it);
557
+ else if (id === "delete") setDelTarget(it);
558
+ else if (id === "move") openMoveFor(it);
559
+ else if (id === "details") toggleDetails(it);
560
+ };
561
+ const rowMenu = (it) => {
562
+ const items = it.archived ? [
563
+ ["restore", "\u6062\u590D"],
564
+ ["move", openMove === it.sessionId ? "\u6536\u8D77\u79FB\u52A8" : "\u79FB\u52A8"],
565
+ ["details", openDetails === it.sessionId ? "\u6536\u8D77\u8BE6\u60C5" : "\u8BE6\u60C5"],
566
+ ["delete", "\u5220\u9664"]
567
+ ] : [["archive", "\u5F52\u6863"], ["move", "\u79FB\u52A8"], ["details", "\u8BE6\u60C5"], ["delete", "\u5220\u9664"]];
568
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: openMenu === it.sessionId ? menuRef : null, className: "more-wrap", children: [
569
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
570
+ "button",
571
+ {
572
+ type: "button",
573
+ className: "more-btn",
574
+ "aria-label": "\u66F4\u591A\u64CD\u4F5C",
575
+ "aria-haspopup": "true",
576
+ "aria-expanded": openMenu === it.sessionId,
577
+ onClick: (e) => {
578
+ e.stopPropagation();
579
+ setOpenMenu(openMenu === it.sessionId ? null : it.sessionId);
580
+ },
581
+ children: "\u22EF"
582
+ }
583
+ ),
584
+ openMenu === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "more-menu", role: "menu", children: items.map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
585
+ "button",
586
+ {
587
+ type: "button",
588
+ role: "menuitem",
589
+ className: "more-item" + (id === "delete" ? " more-item-danger" : ""),
590
+ onClick: () => runMenu(id, it),
591
+ children: label
592
+ },
593
+ id
594
+ )) })
595
+ ] });
596
+ };
597
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv", role: "region", "aria-label": "\u4F1A\u8BDD\u7BA1\u7406", children: [
598
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: CSS }),
599
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-head", children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "archv-title", children: "\u4F1A\u8BDD\u7BA1\u7406" }),
601
+ sessions !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-count", "aria-label": `${sessions.length} \u4E2A\u4F1A\u8BDD`, children: sessions.length })
602
+ ] }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "archv-sub", children: "\u7EDF\u4E00\u7BA1\u7406\u5168\u90E8\u4F1A\u8BDD\uFF1A\u5F52\u6863 / \u6062\u590D / \u79FB\u52A8\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A / \u4F1A\u8BDD\u8BE6\u60C5 / \u6279\u91CF\u64CD\u4F5C\uFF0C\u5220\u9664\u4F1A\u5148\u8FDB\u5165\u56DE\u6536\u7AD9\uFF0C\u53EF\u5728\u56DE\u6536\u7AD9\u5185\u6062\u590D\u6216\u5F7B\u5E95\u6E05\u7406\u3002" }),
604
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-err", role: "alert", children: [
605
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: error }),
606
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-errretry", onClick: refresh, children: "\u91CD\u8BD5" })
607
+ ] }),
608
+ sessions === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel", "aria-label": "\u52A0\u8F7D\u4E2D", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel-card" }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
609
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-filter", role: "tablist", "aria-label": "\u4F1A\u8BDD\u7B5B\u9009", children: [
610
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "all", className: "sess-fbtn" + (filter === "all" ? " sess-fbtn-on" : ""), onClick: () => {
611
+ setFilter("all");
612
+ clearSel();
613
+ setConfirmBatch(false);
614
+ }, children: [
615
+ "\u5168\u90E8 (",
616
+ sessions.length,
617
+ ")"
618
+ ] }),
619
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "active", className: "sess-fbtn" + (filter === "active" ? " sess-fbtn-on" : ""), onClick: () => {
620
+ setFilter("active");
621
+ clearSel();
622
+ setConfirmBatch(false);
623
+ }, children: [
624
+ "\u6D3B\u52A8 (",
625
+ activeList.length,
626
+ ")"
627
+ ] }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "archived", className: "sess-fbtn" + (filter === "archived" ? " sess-fbtn-on" : ""), onClick: () => {
629
+ setFilter("archived");
630
+ clearSel();
631
+ setConfirmBatch(false);
632
+ }, children: [
633
+ "\u5DF2\u5F52\u6863 (",
634
+ archivedList.length,
635
+ ")"
636
+ ] }),
637
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "trash", className: "sess-fbtn" + (filter === "trash" ? " sess-fbtn-on" : ""), onClick: () => {
638
+ setFilter("trash");
639
+ clearSel();
640
+ setConfirmBatch(false);
641
+ }, children: [
642
+ "\u56DE\u6536\u7AD9 (",
643
+ trash.length,
644
+ ")"
645
+ ] })
646
+ ] }),
647
+ filter !== "trash" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
648
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-tools", "aria-label": "\u67E5\u627E\u548C\u6574\u7406\u4F1A\u8BDD", children: [
649
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
650
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-search", children: "\u641C\u7D22\u4F1A\u8BDD" }),
651
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { id: "dsm-search", type: "search", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "\u6807\u9898\u3001\u4F1A\u8BDD ID \u6216\u5DE5\u4F5C\u533A" })
652
+ ] }),
653
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
654
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-workspace-filter", children: "\u5DE5\u4F5C\u533A" }),
655
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-workspace-filter", value: workspaceFilter, onChange: (e) => setWorkspaceFilter(e.target.value), children: [
656
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "all", children: "\u5168\u90E8\u5DE5\u4F5C\u533A" }),
657
+ workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: w.path, children: w.title }, w.workspaceId))
658
+ ] })
659
+ ] }),
660
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
661
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-sort", children: "\u6392\u5E8F" }),
662
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-sort", value: sortBy, onChange: (e) => setSortBy(e.target.value), children: [
663
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "newest", children: "\u6700\u65B0\u521B\u5EFA" }),
664
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "oldest", children: "\u6700\u65E9\u521B\u5EFA" }),
665
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "title", children: "\u6807\u9898 A\u2013Z" })
666
+ ] })
667
+ ] })
668
+ ] }),
669
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-results", role: "status", children: [
670
+ "\u663E\u793A ",
671
+ list.length,
672
+ " \u4E2A\u4F1A\u8BDD",
673
+ query || workspaceFilter !== "all" ? `\uFF0C\u5171 ${filter === "archived" ? archivedList.length : filter === "active" ? activeList.length : sessions.length} \u4E2A` : ""
674
+ ] })
675
+ ] }),
676
+ filter !== "trash" && list.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-batch", children: [
677
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sess-btntext", children: selIds.length ? `\u5DF2\u9009 ${selIds.length} \u9879` : filter === "archived" ? `\u5171 ${archivedList.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD` : `\u5171 ${sessions.length} \u4E2A\u4F1A\u8BDD\uFF08\u6D3B\u52A8 ${activeList.length} / \u5DF2\u5F52\u6863 ${archivedList.length}\uFF09` }),
678
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: list.length === 0, onClick: selectAll, children: "\u5168\u9009" }),
679
+ selIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
680
+ filter === "archived" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
681
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => doBatch("restore-many"), children: "\u6062\u590D\u6240\u9009" }),
682
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, onClick: () => doBatch("delete-many"), children: confirmBatch ? "\u786E\u8BA4\u5220\u9664\u6240\u9009?" : "\u5220\u9664\u6240\u9009" })
683
+ ] }),
684
+ filter !== "archived" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => doBatch("archive-many"), children: "\u5F52\u6863\u6240\u9009" }),
685
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: clearSel, children: "\u53D6\u6D88\u9009\u62E9" })
686
+ ] })
687
+ ] }),
688
+ filter !== "trash" && list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-empty", children: query || workspaceFilter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u4F1A\u8BDD\u3002\u8BF7\u8C03\u6574\u641C\u7D22\u8BCD\u6216\u5DE5\u4F5C\u533A\u7B5B\u9009\u3002" : filter === "archived" ? "\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u201C\u5168\u90E8\u201D\u91CC\u9009\u4E2D\u4F1A\u8BDD\u70B9\u201C\u5F52\u6863\u201D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002" : filter === "active" ? "\u76EE\u524D\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD\u3002" : "\u6682\u65E0\u53EF\u7BA1\u7406\u7684\u4F1A\u8BDD\u3002" }) : filter !== "trash" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-list", role: "list", children: list.map((it) => {
689
+ const date = fmtDate(it.createdAt);
690
+ const expanded = openMove === it.sessionId;
691
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-card" + (expanded ? " archv-card-exp" : ""), role: "listitem", children: [
692
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-row", children: [
693
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
694
+ "input",
695
+ {
696
+ type: "checkbox",
697
+ className: "archv-check",
698
+ checked: !!selected[it.sessionId],
699
+ onChange: () => toggle(it.sessionId),
700
+ "aria-label": "\u9009\u62E9 " + (it.title || it.sessionId)
701
+ }
702
+ ),
703
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-body", children: [
704
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-main", children: [
705
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
706
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-meta", children: [
707
+ it.archived ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag archv-wgone", children: "\u5DF2\u5F52\u6863" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag archv-active", children: "\u6D3B\u52A8" }),
708
+ workspaceTag(it),
709
+ date && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
710
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-dot", children: "\xB7" }),
711
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-date", children: date })
712
+ ] }),
713
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-id", children: it.sessionId })
714
+ ] })
715
+ ] }),
716
+ rowMenu(it)
717
+ ] })
718
+ ] }),
719
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", role: "region", "aria-label": "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A", children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
721
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mv-sheet-title", children: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A" }),
722
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-sheet-close", "aria-label": "\u5173\u95ED", onClick: () => setOpenMove(null), children: "\xD7" })
723
+ ] }),
724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-seg", role: "tablist", children: [
725
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", role: "tab", "aria-selected": moveMode === "existing", className: "mv-segbtn" + (moveMode === "existing" ? " mv-segbtn-on" : ""), onClick: () => setMoveMode("existing"), children: "\u5DF2\u6709\u5DE5\u4F5C\u533A" }),
726
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", role: "tab", "aria-selected": moveMode === "new", className: "mv-segbtn" + (moveMode === "new" ? " mv-segbtn-on" : ""), onClick: () => setMoveMode("new"), children: "\u65B0\u5EFA\u76EE\u5F55" })
727
+ ] }),
728
+ moveMode === "existing" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
729
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "mv-target-ws", children: "\u76EE\u6807\u5DE5\u4F5C\u533A" }),
730
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "mv-target-ws", value: targetWs, onChange: (e) => setTargetWs(e.target.value), children: [
731
+ workspaces.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\uFF08\u6682\u65E0\u5DE5\u4F5C\u533A\uFF09" }),
732
+ workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: w.workspaceId, children: [
733
+ w.title,
734
+ " \xB7 ",
735
+ w.path
736
+ ] }, w.workspaceId))
737
+ ] })
738
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
739
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "mv-new-path", children: "\u65B0\u5DE5\u4F5C\u533A\u76EE\u5F55\u8DEF\u5F84" }),
740
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-browse-row", children: [
741
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
742
+ "input",
743
+ {
744
+ id: "mv-new-path",
745
+ type: "text",
746
+ value: newPath,
747
+ onChange: (e) => setNewPath(e.target.value),
748
+ placeholder: "\u4F8B\u5982 /Users/you/Projects/demo \u6216 ~/demo"
749
+ }
750
+ ),
751
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
752
+ "button",
753
+ {
754
+ type: "button",
755
+ className: "archv-btn",
756
+ onClick: pickDirectory,
757
+ disabled: busy !== null || picking || !workspacesSvc,
758
+ title: !workspacesSvc ? "\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9" : "\u6253\u5F00\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9\u7A97\u53E3",
759
+ children: picking ? "\u9009\u62E9\u4E2D\u2026" : "\u6D4F\u89C8\u2026"
760
+ }
761
+ )
762
+ ] })
763
+ ] }),
764
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-foot", children: [
765
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: () => setOpenMove(null), children: "\u53D6\u6D88" }),
766
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "archv-btn archv-go", disabled: busy !== null, onClick: () => doMove(it), children: [
767
+ busy === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-spin", "aria-hidden": "true" }),
768
+ "\u786E\u8BA4\u79FB\u52A8"
769
+ ] })
770
+ ] })
771
+ ] }),
772
+ openDetails === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sheet", role: "region", "aria-label": "\u4F1A\u8BDD\u8BE6\u60C5", children: [
773
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sheet-head", children: [
774
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "dtl-sheet-title", children: "\u4F1A\u8BDD\u8BE6\u60C5" }),
775
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-sheet-close", "aria-label": "\u5173\u95ED\u8BE6\u60C5", onClick: () => setOpenDetails(null), children: "\xD7" })
776
+ ] }),
777
+ detailsLoading === it.sessionId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel", "aria-label": "\u52A0\u8F7D\u4E2D", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel-card" }, i)) }) : (() => {
778
+ const d = details[it.sessionId];
779
+ if (!d) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-paths", children: "\u6682\u65E0\u8BE6\u60C5" });
780
+ const st = d.stats || {};
781
+ const tools = st.toolCounts ? Object.entries(st.toolCounts).sort((a, b) => b[1] - a[1]).slice(0, 10) : [];
782
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
783
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-grid", children: [
784
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
785
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u78C1\u76D8\u5360\u7528" }),
786
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-v", children: fmtBytes(d.sizeBytes) || "\u2014" })
787
+ ] }),
788
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
789
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u8F6E\u6B21 / \u6B65\u9AA4" }),
790
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dtl-v", children: [
791
+ st.turns ?? 0,
792
+ " / ",
793
+ st.steps ?? 0
794
+ ] })
795
+ ] }),
796
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u7528\u6237 / \u52A9\u624B" }),
798
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dtl-v", children: [
799
+ st.userMessages ?? 0,
800
+ " / ",
801
+ st.assistantMessages ?? 0
802
+ ] })
803
+ ] }),
804
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
805
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u5DE5\u5177\u8C03\u7528" }),
806
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-v", children: st.toolCalls ?? 0 })
807
+ ] }),
808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
809
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u56FE\u7247\u9644\u4EF6" }),
810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-v", children: st.attachments ?? 0 })
811
+ ] }),
812
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-cell", children: [
813
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dtl-k", children: "\u521B\u5EFA / \u66F4\u65B0" }),
814
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dtl-v", children: [
815
+ fmtDate(d.createdAt) || "\u2014",
816
+ " \xB7 ",
817
+ fmtDate(d.updatedAt) || "\u2014"
818
+ ] })
819
+ ] })
820
+ ] }),
821
+ tools.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u5DE5\u5177\u4F7F\u7528" }),
823
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-tags", children: tools.map(([t, c]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dtl-tag", children: [
824
+ t,
825
+ " \xD7",
826
+ c
827
+ ] }, t)) })
828
+ ] }),
829
+ st.fetches && st.fetches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
830
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u641C\u7D22 / \u6293\u53D6" }),
831
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dtl-list", children: st.fetches.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
832
+ f.tool,
833
+ f.query ? ` \u300C${f.query}\u300D` : ""
834
+ ] }, i)) })
835
+ ] }),
836
+ d.files && d.files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
837
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec-t", children: [
838
+ "\u5199\u8FC7\u7684\u6587\u4EF6\uFF08",
839
+ d.files.length,
840
+ "\uFF09"
841
+ ] }),
842
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dtl-list", children: d.files.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
843
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: f.path }),
844
+ " ",
845
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dtl-filetool", children: [
846
+ "(",
847
+ f.tool,
848
+ ")"
849
+ ] })
850
+ ] }, i)) })
851
+ ] }),
852
+ d.lineage && (d.lineage.parentSessionId || d.lineage.children && d.lineage.children.length > 0 || d.lineage.subagents && d.lineage.subagents.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
853
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u8840\u7EDF" }),
854
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-paths", children: [
855
+ d.lineage.parentSessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
856
+ "\u7236\u4F1A\u8BDD: ",
857
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: d.lineage.parentSessionId })
858
+ ] }),
859
+ d.lineage.children && d.lineage.children.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
860
+ "\u5B50\u4F1A\u8BDD (",
861
+ d.lineage.children.length,
862
+ "): ",
863
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: d.lineage.children.join(", ") })
864
+ ] }),
865
+ d.lineage.subagents && d.lineage.subagents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
866
+ "\u5B50\u4EE3\u7406 (",
867
+ d.lineage.subagents.length,
868
+ "): ",
869
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: d.lineage.subagents.join(", ") })
870
+ ] })
871
+ ] })
872
+ ] })
873
+ ] });
874
+ })()
875
+ ] })
876
+ ] }, it.sessionId);
877
+ }) }) : null
878
+ ] }),
879
+ toast && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-status", role: "status", children: toast }),
880
+ delTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dlg-backdrop", onClick: () => setDelTarget(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: dialogRef, className: "dlg", role: "alertdialog", "aria-modal": "true", "aria-label": "\u5220\u9664\u4F1A\u8BDD", onClick: (e) => e.stopPropagation(), children: [
881
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "dlg-title", children: "\u5220\u9664\u4F1A\u8BDD" }),
882
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "dlg-text", children: [
883
+ "\u786E\u8BA4\u5220\u9664\u300C",
884
+ delTarget.title || delTarget.sessionId,
885
+ "\u300D\uFF1F\u5C06\u79FB\u5165\u56DE\u6536\u7AD9\uFF0C\u53EF\u5728\u672C\u9875\u5E95\u90E8\u300C\u56DE\u6536\u7AD9\u300D\u4E2D\u6062\u590D\u6216\u5F7B\u5E95\u5220\u9664\u3002"
886
+ ] }),
887
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dlg-actions", children: [
888
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => setDelTarget(null), children: "\u53D6\u6D88" }),
889
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, onClick: doDeleteConfirmed, children: "\u79FB\u5165\u56DE\u6536\u7AD9" })
890
+ ] })
891
+ ] }) }),
892
+ filter === "trash" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "dsm-trash", "aria-label": "\u56DE\u6536\u7AD9", children: [
893
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-trash-h", children: [
894
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u56DE\u6536\u7AD9" }),
895
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-trash-count", children: trash.length ? `\uFF08${trash.length} \u4E2A\u5F85\u6E05\u7406\uFF09` : "\uFF08\u7A7A\uFF09" })
896
+ ] }),
897
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-tools", children: [
898
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
899
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-retention", children: "\u81EA\u52A8\u6E05\u7406" }),
900
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-retention", value: trashSettings.retentionDays || 0, disabled: trashBusy !== null, onChange: (e) => updateRetention(e.target.value), children: [
901
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "0", children: "\u4E0D\u81EA\u52A8\u6E05\u7406" }),
902
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "7", children: "\u4FDD\u7559 7 \u5929" }),
903
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "30", children: "\u4FDD\u7559 30 \u5929" }),
904
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "90", children: "\u4FDD\u7559 90 \u5929" })
905
+ ] })
906
+ ] }),
907
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
908
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u6570\u636E\u68C0\u67E5" }),
909
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: trashBusy !== null, onClick: verifyTrash, children: trashBusy === "__verify" ? "\u6821\u9A8C\u4E2D\u2026" : "\u6821\u9A8C\u65E5\u5FD7\u5B8C\u6574\u6027" })
910
+ ] }),
911
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
912
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "\u6C38\u4E45\u6E05\u7406" }),
913
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: trashBusy !== null || !trash.length, onClick: () => setPurgeTarget("__all"), children: "\u6E05\u7A7A\u56DE\u6536\u7AD9" })
914
+ ] })
915
+ ] }),
916
+ trashCheck && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: trashCheck.missing ? "archv-err" : "archv-empty", role: "status", children: [
917
+ "\u6821\u9A8C\u5B8C\u6210\uFF1A",
918
+ trashCheck.healthy,
919
+ " \u6761\u6B63\u5E38\uFF0C",
920
+ trashCheck.missing,
921
+ " \u6761\u65E5\u5FD7\u7F3A\u5931\u3002"
922
+ ] }),
923
+ trash.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-trash-empty", children: "\u56DE\u6536\u7AD9\u4E3A\u7A7A\u3002\u5220\u9664\u7684\u4F1A\u8BDD\u4F1A\u5148\u8FDB\u5165\u8FD9\u91CC\uFF0C\u53EF\u6062\u590D\u6216\u5F7B\u5E95\u5220\u9664\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-trash-list", children: trash.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-trash-row", children: [
924
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-trash-name", title: t.sessionId, children: t.title || t.sessionId }),
925
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-trash-date", children: fmtDate(t.deletedAt) }),
926
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-trash-actions", children: [
927
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: trashBusy !== null, onClick: () => restoreTrash(t.sessionId), children: "\u6062\u590D" }),
928
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: trashBusy !== null, onClick: () => setPurgeTarget(t.sessionId), children: "\u5F7B\u5E95\u5220\u9664" })
929
+ ] })
930
+ ] }, t.sessionId)) })
931
+ ] }),
932
+ purgeTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dlg-backdrop", onClick: () => setPurgeTarget(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: dialogRef, className: "dlg", role: "alertdialog", "aria-modal": "true", "aria-labelledby": "dsm-purge-title", onClick: (e) => e.stopPropagation(), children: [
933
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { id: "dsm-purge-title", className: "dlg-title", children: [
934
+ "\u6C38\u4E45\u5220\u9664",
935
+ purgeTarget === "__all" ? "\u5168\u90E8\u56DE\u6536\u7AD9\u4F1A\u8BDD" : "\u8FD9\u4E2A\u4F1A\u8BDD",
936
+ "\uFF1F"
937
+ ] }),
938
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dlg-text", children: "\u6B64\u64CD\u4F5C\u4F1A\u7269\u7406\u5220\u9664\u65E5\u5FD7\uFF0C\u65E0\u6CD5\u6062\u590D\u3002\u5F52\u6863\u3001\u7B5B\u9009\u548C\u91CD\u65B0\u5B89\u88C5\u63D2\u4EF6\u90FD\u4E0D\u80FD\u627E\u56DE\u8FD9\u4E9B\u6570\u636E\u3002" }),
939
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dlg-actions", children: [
940
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: () => setPurgeTarget(null), children: "\u53D6\u6D88" }),
941
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", onClick: () => {
942
+ const target = purgeTarget;
943
+ setPurgeTarget(null);
944
+ target === "__all" ? purgeAllTrash() : purgeTrash(target);
945
+ }, children: "\u786E\u8BA4\u6C38\u4E45\u5220\u9664" })
946
+ ] })
947
+ ] }) })
948
+ ] });
949
+ }
950
+ var SIDEBAR_AUG_CSS = `
951
+ .dsm-backdrop{position:fixed;inset:0;z-index:2147483600;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;padding:16px}
952
+ .dsm-dlg{width:min(420px,92vw);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l3);border-radius:14px;padding:18px;box-shadow:0 16px 48px rgb(0 0 0/.28);display:flex;flex-direction:column;gap:12px}
953
+ .dsm-title{font-size:15px;font-weight:650;color:var(--dsw-alias-label-primary);margin:0}
954
+ .dsm-text{font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary);margin:0;word-break:break-all}
955
+ .dsm-body{display:flex;flex-direction:column;gap:4px;max-height:280px;overflow:auto}
956
+ .dsm-loading,.dsm-empty{font-size:12px;color:var(--dsw-alias-label-tertiary);padding:4px 2px}
957
+ .dsm-err{font-size:12px;color:var(--dsw-alias-state-error-primary);padding:4px 2px}
958
+ .dsm-opt{appearance:none;display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;padding:9px 11px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);border-radius:9px;font-size:12.5px;cursor:pointer;text-align:left}
959
+ .dsm-opt:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l4)}
960
+ .dsm-opt:disabled{opacity:.55;cursor:default}
961
+ .dsm-opt-cur{border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 45%,transparent);color:var(--dsw-alias-state-business-primary)}
962
+ .dsm-opt-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}
963
+ .dsm-opt-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none;margin-left:8px}
964
+ .dsm-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:2px}
965
+ .dsm-btn{appearance:none;min-height:32px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:9px;font-size:12px;font-weight:500;cursor:pointer}
966
+ .dsm-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
967
+ .dsm-del{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent)}
968
+ .dsm-del:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}
969
+ .dsm-toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:2147483601;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);padding:9px 16px;border-radius:999px;font-size:12px;box-shadow:0 8px 24px rgb(0 0 0/.18);max-width:min(90vw,420px)}
970
+ .dsm-sub{position:fixed;z-index:1100;box-sizing:border-box;min-width:190px;max-width:320px;padding:4px;display:flex;flex-direction:column;gap:0;background:var(--dsw-specific-menu);border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;box-shadow:var(--dsw-shadow-lv3)}
971
+ .dsm-sub-loading,.dsm-sub-empty{font-size:12px;color:var(--dsw-alias-label-tertiary);padding:6px 10px}
972
+ .dsm-sub-err{font-size:12px;color:var(--dsw-alias-state-error-primary);padding:6px 10px}
973
+ .dsm-sub-item{display:flex;align-items:center;gap:8px;width:100%;min-height:36px;padding:6px 10px;border:none;border-radius:8px;background:transparent;cursor:pointer;font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary);text-align:left}
974
+ .dsm-sub-item:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
975
+ .dsm-sub-item:disabled{opacity:.5;cursor:default}
976
+ .dsm-sub-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
977
+ .dsm-sub-cur{font-size:11px;color:var(--dsw-alias-state-business-primary);flex:none;margin-left:8px}
978
+ .dsm-dot{position:absolute;left:6px;top:50%;transform:translateY(-50%);width:8px;height:8px;border-radius:50%;box-sizing:border-box;cursor:pointer;pointer-events:auto;z-index:1}
979
+ .dsm-dot-unread-manual{background:var(--dsw-alias-state-business-primary)}
980
+ .dsm-dot-waiting{background:var(--dsw-alias-state-warning-primary)}
981
+ .dsm-dot-unread{background:var(--dsw-alias-state-success-primary)}
982
+ .dsm-drag-source{opacity:.48}
983
+ .dsm-drop-target{position:relative;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent)!important;outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px;border-radius:8px}
984
+ .dsm-drop-target::after{content:'\u79FB\u52A8\u5230\u8FD9\u91CC';position:absolute;right:8px;top:50%;transform:translateY(-50%);padding:1px 6px;border-radius:4px;background:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-inverted);font-size:10px;font-weight:600;line-height:16px;pointer-events:none}
985
+ .dsm-drag-busy{cursor:progress!important}
986
+ .dsm-trash{margin-top:18px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px}
987
+ .dsm-trash-h{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
988
+ .dsm-trash-h h3{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}
989
+ .dsm-trash-count{font-size:11px;color:var(--dsw-alias-label-tertiary)}
990
+ .dsm-trash-list{display:flex;flex-direction:column;gap:6px;max-height:260px;overflow:auto}
991
+ .dsm-trash-row{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-fill-elevated)}
992
+ .dsm-trash-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;color:var(--dsw-alias-label-primary)}
993
+ .dsm-trash-date{font-size:11px;color:var(--dsw-alias-label-tertiary);flex:none;white-space:nowrap}
994
+ .dsm-trash-actions{display:flex;gap:6px;flex:none}.dsm-trash-actions .archv-btn{min-width:72px}
995
+ .dsm-trash-empty{font-size:12px;color:var(--dsw-alias-label-tertiary);padding:6px 2px}
996
+ `;
997
+ var DSM_KEY_MANUAL = "dsm-manual-unread-v1";
998
+ var dsmManualUnread = null;
999
+ var dsmRepaintDots = null;
1000
+ function dsmLoadManual() {
1001
+ if (dsmManualUnread) return dsmManualUnread;
1002
+ try {
1003
+ dsmManualUnread = new Set(JSON.parse(localStorage.getItem(DSM_KEY_MANUAL) || "[]"));
1004
+ } catch (e) {
1005
+ dsmManualUnread = /* @__PURE__ */ new Set();
1006
+ }
1007
+ return dsmManualUnread;
1008
+ }
1009
+ function dsmSaveManual() {
1010
+ try {
1011
+ localStorage.setItem(DSM_KEY_MANUAL, JSON.stringify([...dsmLoadManual()]));
1012
+ } catch (e) {
1013
+ }
1014
+ }
1015
+ function dsmToggleManual(id) {
1016
+ const s = dsmLoadManual();
1017
+ if (s.has(id)) s.delete(id);
1018
+ else s.add(id);
1019
+ dsmSaveManual();
1020
+ if (dsmRepaintDots) dsmRepaintDots();
1021
+ }
1022
+ var dsmTrashIds = null;
1023
+ var dsmServerPurgedIds = /* @__PURE__ */ new Set();
1024
+ var dsmAuthoritativeTitles = /* @__PURE__ */ new Map();
1025
+ var dsmTrashTick = 0;
1026
+ async function dsmLoadTrashIds() {
1027
+ try {
1028
+ const r = await postJSON("/archived-sessions/sidebar-state", {});
1029
+ dsmTrashIds = new Set((r && r.trashedSessionIds || []).map(String));
1030
+ dsmServerPurgedIds = new Set((r && r.purgedSessionIds || []).map(String));
1031
+ dsmAuthoritativeTitles = new Map(Object.entries(r && r.titles || {}).map(([id, title]) => [String(id), String(title)]));
1032
+ if (dsmRepaintDots) dsmRepaintDots();
1033
+ } catch (e) {
1034
+ }
1035
+ return dsmTrashIds;
1036
+ }
1037
+ var DSM_KEY_PURGED = "dsm-purged-v1";
1038
+ var dsmPurgedIds = null;
1039
+ function dsmLoadPurged() {
1040
+ if (!dsmPurgedIds) {
1041
+ try {
1042
+ dsmPurgedIds = new Set(JSON.parse(localStorage.getItem(DSM_KEY_PURGED) || "[]"));
1043
+ } catch (e) {
1044
+ dsmPurgedIds = /* @__PURE__ */ new Set();
1045
+ }
1046
+ }
1047
+ dsmServerPurgedIds.forEach((id) => dsmPurgedIds.add(id));
1048
+ return dsmPurgedIds;
1049
+ }
1050
+ function dsmSavePurged() {
1051
+ try {
1052
+ localStorage.setItem(DSM_KEY_PURGED, JSON.stringify([...dsmLoadPurged()]));
1053
+ } catch (e) {
1054
+ }
1055
+ }
1056
+ function dsmMarkPurged(ids) {
1057
+ const s = dsmLoadPurged();
1058
+ ids.forEach((id) => s.add(String(id)));
1059
+ dsmSavePurged();
1060
+ if (dsmRepaintDots) dsmRepaintDots();
1061
+ }
1062
+ function installSidebarSessionMenuAug() {
1063
+ if (typeof document === "undefined") return;
1064
+ const AUG = "data-dsm-aug";
1065
+ let styleInjected = false;
1066
+ let activeSubClose = null;
1067
+ let hoverTimer = null;
1068
+ const findFiber = (el) => {
1069
+ const k = Object.keys(el).find((kk) => kk.startsWith("__reactFiber") || kk.startsWith("__reactInternalInstance"));
1070
+ return k ? el[k] : null;
1071
+ };
1072
+ const sessionInfoFromMenu = (menuEl) => {
1073
+ let f = findFiber(menuEl);
1074
+ let guard = 0;
1075
+ while (f && guard++ < 300) {
1076
+ const p = f.memoizedProps;
1077
+ if (p && p.node && typeof p.node.id === "string" && p.node.id) {
1078
+ return { id: p.node.id, cwd: p.node.cwd || p.node.workspacePath || null };
1079
+ }
1080
+ f = f.return;
1081
+ }
1082
+ return null;
1083
+ };
1084
+ const closeMenu = () => {
1085
+ try {
1086
+ document.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
1087
+ } catch (e) {
1088
+ }
1089
+ try {
1090
+ document.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true }));
1091
+ } catch (e) {
1092
+ }
1093
+ };
1094
+ const escapeHtml = (s) => {
1095
+ const d = document.createElement("div");
1096
+ d.textContent = s == null ? "" : String(s);
1097
+ return d.innerHTML;
1098
+ };
1099
+ const toast = (msg) => {
1100
+ const t = document.createElement("div");
1101
+ t.className = "dsm-toast";
1102
+ t.textContent = msg;
1103
+ document.body.appendChild(t);
1104
+ setTimeout(() => t.remove(), 2600);
1105
+ };
1106
+ const ensureStyle = () => {
1107
+ if (styleInjected) return;
1108
+ const s = document.createElement("style");
1109
+ s.dataset.dsm = "aug";
1110
+ s.textContent = SIDEBAR_AUG_CSS;
1111
+ document.head.appendChild(s);
1112
+ styleInjected = true;
1113
+ };
1114
+ const closeMoveSubmenu = () => {
1115
+ if (activeSubClose) {
1116
+ const f = activeSubClose;
1117
+ activeSubClose = null;
1118
+ f();
1119
+ }
1120
+ };
1121
+ const openMoveSubmenu = (moveBtn, info) => {
1122
+ ensureStyle();
1123
+ closeMoveSubmenu();
1124
+ const sub = document.createElement("div");
1125
+ sub.className = "dsm-sub";
1126
+ sub.setAttribute("role", "menu");
1127
+ sub.setAttribute("data-dsm-sub", "");
1128
+ sub.innerHTML = '<div class="dsm-sub-loading">\u52A0\u8F7D\u5DE5\u4F5C\u533A\u2026</div>';
1129
+ const r = moveBtn.getBoundingClientRect();
1130
+ sub.style.top = Math.max(8, Math.round(r.top - 4)) + "px";
1131
+ sub.style.left = Math.round(r.right + 10) + "px";
1132
+ document.body.appendChild(sub);
1133
+ const closeSub = () => {
1134
+ activeSubClose = null;
1135
+ if (sub.parentNode) sub.remove();
1136
+ document.removeEventListener("mousedown", onDocDown, true);
1137
+ window.removeEventListener("blur", closeSub);
1138
+ };
1139
+ const onDocDown = (e) => {
1140
+ if (sub.contains(e.target) || moveBtn.contains(e.target)) return;
1141
+ closeSub();
1142
+ };
1143
+ sub.addEventListener("mousedown", (e) => e.stopPropagation());
1144
+ sub.addEventListener("mouseenter", () => {
1145
+ if (hoverTimer) {
1146
+ clearTimeout(hoverTimer);
1147
+ hoverTimer = null;
1148
+ }
1149
+ });
1150
+ sub.addEventListener("mouseleave", () => {
1151
+ hoverTimer = setTimeout(() => closeSub(), 160);
1152
+ });
1153
+ setTimeout(() => document.addEventListener("mousedown", onDocDown, true), 0);
1154
+ window.addEventListener("blur", closeSub);
1155
+ activeSubClose = closeSub;
1156
+ Promise.all([
1157
+ postJSON("/archived-sessions/workspaces", {}),
1158
+ postJSON("/archived-sessions/sessions", {})
1159
+ ]).then(([ws, sess]) => {
1160
+ const items = ws.items || [];
1161
+ const cur = (sess.items || []).find((x) => x.sessionId === info.id);
1162
+ const curPath = cur ? cur.workspacePath : info.cwd || null;
1163
+ if (!items.length) {
1164
+ sub.innerHTML = '<div class="dsm-sub-empty">\uFF08\u6682\u65E0\u53EF\u7528\u5DE5\u4F5C\u533A\uFF09</div>';
1165
+ return;
1166
+ }
1167
+ sub.innerHTML = "";
1168
+ items.forEach((w) => {
1169
+ const isCur = !!curPath && w.path === curPath;
1170
+ const b = document.createElement("button");
1171
+ b.type = "button";
1172
+ b.className = "dsm-sub-item";
1173
+ b.setAttribute("role", "menuitem");
1174
+ b.disabled = isCur;
1175
+ const name = document.createElement("span");
1176
+ name.className = "dsm-sub-name";
1177
+ name.textContent = w.title || pathName(w.path) || w.workspaceId;
1178
+ b.appendChild(name);
1179
+ if (isCur) {
1180
+ const c = document.createElement("span");
1181
+ c.className = "dsm-sub-cur";
1182
+ c.textContent = "\u5F53\u524D";
1183
+ b.appendChild(c);
1184
+ }
1185
+ b.addEventListener("click", (e) => {
1186
+ e.stopPropagation();
1187
+ e.preventDefault();
1188
+ closeSub();
1189
+ closeMenu();
1190
+ postJSON("/archived-sessions/move", { sessionId: info.id, targetPath: w.path }).then(() => toast("\u79FB\u52A8\u6210\u529F")).catch((ee) => toast("\u79FB\u52A8\u5931\u8D25\uFF1A" + String(ee && ee.message || ee)));
1191
+ });
1192
+ sub.appendChild(b);
1193
+ });
1194
+ }).catch((e) => {
1195
+ sub.innerHTML = '<div class="dsm-sub-err">' + escapeHtml(String(e && e.message || e)) + "</div>";
1196
+ });
1197
+ };
1198
+ const openDeleteConfirm = (id) => {
1199
+ ensureStyle();
1200
+ const backdrop = document.createElement("div");
1201
+ backdrop.className = "dsm-backdrop";
1202
+ const dlg = document.createElement("div");
1203
+ dlg.className = "dsm-dlg";
1204
+ dlg.innerHTML = '<h3 class="dsm-title">\u5220\u9664\u4F1A\u8BDD</h3><p class="dsm-text">\u786E\u8BA4\u5C06\u8BE5\u4F1A\u8BDD\u79FB\u5165\u56DE\u6536\u7AD9\uFF1F\u53EF\u5728\u300C\u8BBE\u7F6E \u2192 \u4F1A\u8BDD\u7BA1\u7406 \u2192 \u56DE\u6536\u7AD9\u300D\u4E2D\u6062\u590D\u6216\u5F7B\u5E95\u5220\u9664\u3002</p><div class="dsm-actions"><button type="button" class="dsm-btn" data-role="cancel">\u53D6\u6D88</button><button type="button" class="dsm-btn dsm-del" data-role="ok">\u79FB\u5165\u56DE\u6536\u7AD9</button></div>';
1205
+ backdrop.appendChild(dlg);
1206
+ document.body.appendChild(backdrop);
1207
+ const close = () => backdrop.remove();
1208
+ backdrop.addEventListener("click", (e) => {
1209
+ if (e.target === backdrop) close();
1210
+ });
1211
+ dlg.querySelector("[data-role=cancel]").addEventListener("click", close);
1212
+ dlg.querySelector("[data-role=ok]").addEventListener("click", () => {
1213
+ close();
1214
+ postJSON("/archived-sessions/delete", { sessionId: id }).then(() => {
1215
+ if (dsmTrashIds) dsmTrashIds.add(String(id));
1216
+ if (dsmRepaintDots) dsmRepaintDots();
1217
+ toast("\u5DF2\u79FB\u5165\u56DE\u6536\u7AD9");
1218
+ }).catch((e) => toast("\u5220\u9664\u5931\u8D25\uFF1A" + String(e && e.message || e)));
1219
+ });
1220
+ };
1221
+ const augmentMenu = (menuEl, info) => {
1222
+ if (menuEl.querySelector("[" + AUG + "]")) return;
1223
+ const viewport = menuEl.querySelector('[role="presentation"]') || menuEl.firstElementChild;
1224
+ if (!viewport) return;
1225
+ const proto = menuEl.querySelector('[role="menuitem"]');
1226
+ if (!proto) return;
1227
+ const protoWrap = proto.parentElement;
1228
+ const protoCls = proto.className;
1229
+ const protoWrapCls = protoWrap ? protoWrap.className : "";
1230
+ const ICON_MOVE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M12 11v4"/><path d="M10 13l2 2 2-2"/></svg>';
1231
+ const ICON_DEL = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M6 7l1 13a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-13"/><path d="M9 7V4h6v3"/></svg>';
1232
+ const ICON_UNREAD = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3" fill="currentColor" stroke="none"/></svg>';
1233
+ const mk = (label, svg, danger) => {
1234
+ const wrap = protoWrap ? protoWrap.cloneNode(false) : document.createElement("div");
1235
+ if (protoWrapCls) wrap.className = protoWrapCls;
1236
+ const btn = document.createElement("button");
1237
+ btn.type = "button";
1238
+ btn.setAttribute("role", "menuitem");
1239
+ btn.className = protoCls;
1240
+ const icon = document.createElement("span");
1241
+ icon.style.cssText = "display:inline-flex;flex:none;width:16px;height:16px;align-items:center;justify-content:center;color:" + (danger ? "var(--dsw-alias-state-error-primary)" : "var(--dsw-alias-label-tertiary)");
1242
+ icon.innerHTML = svg;
1243
+ const lab = document.createElement("span");
1244
+ lab.style.cssText = "flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
1245
+ lab.textContent = label;
1246
+ btn.appendChild(icon);
1247
+ btn.appendChild(lab);
1248
+ if (danger) btn.style.color = "var(--dsw-alias-state-error-primary)";
1249
+ btn.setAttribute(AUG, "");
1250
+ wrap.appendChild(btn);
1251
+ return { wrap, btn };
1252
+ };
1253
+ const move = mk("\u79FB\u52A8\u4F1A\u8BDD", ICON_MOVE, false);
1254
+ const del = mk("\u5220\u9664\u4F1A\u8BDD", ICON_DEL, true);
1255
+ const mark = mk(dsmLoadManual().has(info.id) ? "\u6807\u8BB0\u5DF2\u8BFB" : "\u6807\u8BB0\u672A\u8BFB", ICON_UNREAD, false);
1256
+ if (mark.btn.firstChild) mark.btn.firstChild.style.color = "var(--dsw-alias-state-business-primary)";
1257
+ const chev = document.createElement("span");
1258
+ chev.style.cssText = "margin-left:auto;flex:none;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:1";
1259
+ chev.textContent = "\u203A";
1260
+ move.btn.appendChild(chev);
1261
+ move.btn.addEventListener("mouseenter", () => {
1262
+ if (!document.querySelector("[data-dsm-sub]")) openMoveSubmenu(move.btn, info);
1263
+ });
1264
+ move.btn.addEventListener("mouseleave", () => {
1265
+ hoverTimer = setTimeout(() => closeMoveSubmenu(), 160);
1266
+ });
1267
+ move.btn.addEventListener("click", (e) => {
1268
+ e.stopPropagation();
1269
+ e.preventDefault();
1270
+ });
1271
+ del.btn.addEventListener("click", (e) => {
1272
+ e.stopPropagation();
1273
+ e.preventDefault();
1274
+ closeMoveSubmenu();
1275
+ openDeleteConfirm(info.id);
1276
+ });
1277
+ mark.btn.addEventListener("click", (e) => {
1278
+ e.stopPropagation();
1279
+ e.preventDefault();
1280
+ closeMoveSubmenu();
1281
+ dsmToggleManual(info.id);
1282
+ closeMenu();
1283
+ });
1284
+ viewport.appendChild(move.wrap);
1285
+ viewport.appendChild(del.wrap);
1286
+ viewport.insertBefore(mark.wrap, viewport.firstElementChild);
1287
+ };
1288
+ const seen = /* @__PURE__ */ new WeakSet();
1289
+ const obs = new MutationObserver(() => {
1290
+ const menus = document.querySelectorAll('body > [role="menu"]');
1291
+ menus.forEach((menuEl) => {
1292
+ if (seen.has(menuEl)) return;
1293
+ const info = sessionInfoFromMenu(menuEl);
1294
+ if (!info) return;
1295
+ seen.add(menuEl);
1296
+ try {
1297
+ augmentMenu(menuEl, info);
1298
+ } catch (e) {
1299
+ }
1300
+ });
1301
+ });
1302
+ obs.observe(document.body, { childList: true, subtree: false });
1303
+ }
1304
+ function installSidebarStatusDots() {
1305
+ if (typeof document === "undefined") return;
1306
+ const DOT = "data-dsm-dot";
1307
+ if (!document.querySelector("style[data-dsm=aug]")) {
1308
+ const s = document.createElement("style");
1309
+ s.dataset.dsm = "aug";
1310
+ s.textContent = SIDEBAR_AUG_CSS;
1311
+ document.head.appendChild(s);
1312
+ }
1313
+ const findFiber = (el) => {
1314
+ const k = Object.keys(el).find((kk) => kk.startsWith("__reactFiber") || kk.startsWith("__reactInternalInstance"));
1315
+ return k ? el[k] : null;
1316
+ };
1317
+ const fiberProp = (el, pred) => {
1318
+ let f = findFiber(el);
1319
+ let g = 0;
1320
+ while (f && g++ < 300) {
1321
+ const p = f.memoizedProps;
1322
+ if (p && pred(p)) return pred(p);
1323
+ f = f.return;
1324
+ }
1325
+ return null;
1326
+ };
1327
+ const rowNode = (row) => fiberProp(row, (p) => p.node && typeof p.node.id === "string" && p.node.id ? p.node : null);
1328
+ const rowId = (row) => {
1329
+ const node = rowNode(row);
1330
+ return node ? node.id : null;
1331
+ };
1332
+ let curActive = null;
1333
+ const activeRowId = () => {
1334
+ const sel = document.querySelector('[role="treeitem"][aria-selected="true"]');
1335
+ return sel ? rowId(sel) : null;
1336
+ };
1337
+ const COLOR = {
1338
+ manual: "var(--dsw-alias-state-business-primary)",
1339
+ // 蓝 手动标记未读
1340
+ running: "#EAB308",
1341
+ // 黄 工作中 (DSH running)
1342
+ feedback: "var(--dsw-alias-state-warning-primary)",
1343
+ // 琥珀 需用户反馈 (DSH warning)
1344
+ done: "var(--dsw-alias-state-success-primary)",
1345
+ // 绿 完成后未读 (DSH done)
1346
+ error: "var(--dsw-alias-state-error-primary)"
1347
+ // 红 出错/需关注 (DSH error)
1348
+ };
1349
+ const manualUnread = dsmLoadManual();
1350
+ const paint = () => {
1351
+ const activeId = activeRowId();
1352
+ if (activeId !== curActive && activeId && manualUnread.has(activeId)) {
1353
+ manualUnread.delete(activeId);
1354
+ dsmSaveManual();
1355
+ }
1356
+ curActive = activeId;
1357
+ const rows = document.querySelectorAll('[role="treeitem"]');
1358
+ rows.forEach((row) => {
1359
+ const id = rowId(row);
1360
+ if (!id) return;
1361
+ const purged = dsmLoadPurged();
1362
+ if (dsmTrashIds && dsmTrashIds.has(id) || purged.has(id)) {
1363
+ if (row.style.display !== "none") row.style.display = "none";
1364
+ const d = row.querySelector("[" + DOT + "]");
1365
+ if (d) d.remove();
1366
+ return;
1367
+ }
1368
+ if (row.style.display === "none") row.style.display = "";
1369
+ const authoritativeTitle = dsmAuthoritativeTitles.get(id);
1370
+ if (authoritativeTitle) {
1371
+ const node = rowNode(row) || {};
1372
+ const expected = new Set([node.title, node.displayTitle, node.name].filter((value) => typeof value === "string"));
1373
+ const spans = [...row.children].filter((el) => el.tagName === "SPAN" && !el.querySelector("[data-state]") && (el.textContent || "").trim());
1374
+ const titleEl = spans.find((el) => expected.has((el.textContent || "").trim())) || spans[0];
1375
+ if (titleEl && titleEl.textContent !== authoritativeTitle) titleEl.textContent = authoritativeTitle;
1376
+ }
1377
+ const sd = row.querySelector("[data-state]");
1378
+ if (sd) sd.style.display = "none";
1379
+ let dot = row.querySelector("[" + DOT + "]");
1380
+ let color = null;
1381
+ if (manualUnread.has(id)) color = COLOR.manual;
1382
+ else if (sd) {
1383
+ const st = sd.getAttribute("data-state");
1384
+ if (st === "running") color = COLOR.running;
1385
+ else if (st === "warning") color = COLOR.feedback;
1386
+ else if (st === "error") color = COLOR.error;
1387
+ else if (st === "done") color = activeId === id ? null : COLOR.done;
1388
+ }
1389
+ if (!color) {
1390
+ if (dot) dot.remove();
1391
+ return;
1392
+ }
1393
+ if (!dot) {
1394
+ dot = document.createElement("span");
1395
+ dot.setAttribute(DOT, "");
1396
+ dot.className = "dsm-dot";
1397
+ if (!row.hasAttribute("data-dsm-pos")) {
1398
+ if (getComputedStyle(row).position === "static") row.style.position = "relative";
1399
+ row.setAttribute("data-dsm-pos", "");
1400
+ }
1401
+ dot.addEventListener("click", (e) => {
1402
+ e.stopPropagation();
1403
+ e.preventDefault();
1404
+ dsmToggleManual(id);
1405
+ });
1406
+ row.insertBefore(dot, row.firstChild);
1407
+ }
1408
+ dot.style.background = color;
1409
+ });
1410
+ };
1411
+ dsmRepaintDots = paint;
1412
+ const tick = () => {
1413
+ if (++dsmTrashTick % 8 === 0) dsmLoadTrashIds();
1414
+ paint();
1415
+ };
1416
+ let raf = 0;
1417
+ const schedulePaint = () => {
1418
+ if (raf) return;
1419
+ raf = requestAnimationFrame(() => {
1420
+ raf = 0;
1421
+ paint();
1422
+ });
1423
+ };
1424
+ tick();
1425
+ dsmLoadTrashIds();
1426
+ paint();
1427
+ const obs = new MutationObserver(schedulePaint);
1428
+ obs.observe(document.body, { childList: true, subtree: true });
1429
+ setInterval(tick, 1200);
1430
+ }
1431
+ function installSidebarWorkspaceDrag() {
1432
+ if (typeof document === "undefined") return;
1433
+ let sessions = /* @__PURE__ */ new Map();
1434
+ let dragging = null;
1435
+ let moving = false;
1436
+ const findFiber = (el) => {
1437
+ const key = Object.keys(el).find((k) => k.startsWith("__reactFiber") || k.startsWith("__reactInternalInstance"));
1438
+ return key ? el[key] : null;
1439
+ };
1440
+ const fiberNodes = (el) => {
1441
+ const out = [];
1442
+ let fiber = findFiber(el);
1443
+ let guard = 0;
1444
+ while (fiber && guard++ < 300) {
1445
+ const props = fiber.memoizedProps;
1446
+ if (props && props.node && typeof props.node === "object") out.push(props.node);
1447
+ if (props && props.group && typeof props.group === "object") out.push(props.group);
1448
+ fiber = fiber.return;
1449
+ }
1450
+ return out;
1451
+ };
1452
+ const sessionForRow = (row) => {
1453
+ for (const node of fiberNodes(row)) {
1454
+ const id = node && node.id != null ? String(node.id) : "";
1455
+ if (sessions.has(id)) return sessions.get(id);
1456
+ if (id && node.workspaceId == null && (node.title != null || node.updatedAt != null || node.blank != null)) {
1457
+ return { sessionId: id, title: node.title || "", workspacePath: null };
1458
+ }
1459
+ }
1460
+ return null;
1461
+ };
1462
+ const workspaceForRow = (row) => {
1463
+ if (sessionForRow(row)) return null;
1464
+ for (const group of fiberNodes(row)) {
1465
+ if (group.workspaceId != null && typeof group.cwd === "string" && group.cwd) {
1466
+ return { workspaceId: String(group.workspaceId), path: group.cwd, title: group.label || group.cwd };
1467
+ }
1468
+ }
1469
+ return null;
1470
+ };
1471
+ const eventRow = (event) => {
1472
+ for (const item of event.composedPath ? event.composedPath() : []) {
1473
+ if (item instanceof Element && item.getAttribute("role") === "treeitem") return item;
1474
+ }
1475
+ return event.target instanceof Element ? event.target.closest('[role="treeitem"]') : null;
1476
+ };
1477
+ const toast = (message) => {
1478
+ const el = document.createElement("div");
1479
+ el.className = "dsm-toast";
1480
+ el.setAttribute("role", "status");
1481
+ el.textContent = message;
1482
+ document.body.appendChild(el);
1483
+ setTimeout(() => el.remove(), 2600);
1484
+ };
1485
+ const clearVisuals = () => {
1486
+ document.querySelectorAll(".dsm-drag-source,.dsm-drop-target").forEach((el) => el.classList.remove("dsm-drag-source", "dsm-drop-target"));
1487
+ };
1488
+ const decorateRows = () => {
1489
+ document.querySelectorAll('[role="treeitem"]').forEach((row) => {
1490
+ const session = sessionForRow(row);
1491
+ const ws = workspaceForRow(row);
1492
+ if (session) {
1493
+ row.setAttribute("aria-description", "\u53EF\u62D6\u52A8\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A\uFF1B\u952E\u76D8\u7528\u6237\u53EF\u901A\u8FC7\u66F4\u591A\u83DC\u5355\u4E2D\u7684\u79FB\u52A8\u4F1A\u8BDD\u64CD\u4F5C");
1494
+ }
1495
+ if (ws) row.setAttribute("data-dsm-workspace-drop", "");
1496
+ });
1497
+ };
1498
+ const refresh = async () => {
1499
+ try {
1500
+ const sessionResult = await postJSON("/archived-sessions/sessions", {});
1501
+ sessions = new Map((sessionResult.items || []).map((item) => [String(item.sessionId), item]));
1502
+ decorateRows();
1503
+ } catch (e) {
1504
+ }
1505
+ };
1506
+ document.addEventListener("dragstart", (event) => {
1507
+ const row = eventRow(event);
1508
+ const item = row && sessionForRow(row);
1509
+ if (!item || moving) return;
1510
+ dragging = item;
1511
+ row.classList.add("dsm-drag-source");
1512
+ }, true);
1513
+ document.addEventListener("dragover", (event) => {
1514
+ const row = eventRow(event);
1515
+ const target = row && workspaceForRow(row);
1516
+ if (!dragging || !target || moving) return;
1517
+ if (dragging.workspacePath && target.path === dragging.workspacePath) return;
1518
+ event.preventDefault();
1519
+ event.stopPropagation();
1520
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
1521
+ document.querySelectorAll(".dsm-drop-target").forEach((el) => {
1522
+ if (el !== row) el.classList.remove("dsm-drop-target");
1523
+ });
1524
+ row.classList.add("dsm-drop-target");
1525
+ }, true);
1526
+ document.addEventListener("drop", async (event) => {
1527
+ const row = eventRow(event);
1528
+ const item = dragging;
1529
+ const target = row && workspaceForRow(row);
1530
+ if (!item || !target || moving || item.workspacePath && target.path === item.workspacePath) return;
1531
+ event.preventDefault();
1532
+ event.stopPropagation();
1533
+ moving = true;
1534
+ clearVisuals();
1535
+ row.classList.add("dsm-drag-busy");
1536
+ try {
1537
+ const result = await postJSON("/archived-sessions/move", { sessionId: item.sessionId, targetPath: target.path });
1538
+ sessions.set(item.sessionId, { ...item, workspacePath: result.workspacePath || target.path, workspaceTitle: result.workspaceTitle || target.title });
1539
+ await dsmLoadTrashIds();
1540
+ toast(`\u5DF2\u79FB\u5230\u300C${result.workspaceTitle || target.title}\u300D`);
1541
+ } catch (error) {
1542
+ toast("\u79FB\u52A8\u5931\u8D25\uFF1A" + String(error && error.message || error));
1543
+ } finally {
1544
+ moving = false;
1545
+ dragging = null;
1546
+ row.classList.remove("dsm-drag-busy");
1547
+ decorateRows();
1548
+ }
1549
+ }, true);
1550
+ document.addEventListener("dragend", () => {
1551
+ dragging = null;
1552
+ clearVisuals();
1553
+ }, true);
1554
+ let decorateTimer = null;
1555
+ const scheduleDecorate = () => {
1556
+ if (decorateTimer) return;
1557
+ decorateTimer = requestAnimationFrame(() => {
1558
+ decorateTimer = null;
1559
+ decorateRows();
1560
+ });
1561
+ };
1562
+ refresh();
1563
+ const observer = new MutationObserver(scheduleDecorate);
1564
+ observer.observe(document.body, { childList: true, subtree: true });
1565
+ setInterval(refresh, 5e3);
1566
+ }
1567
+ function apply(ctx) {
1568
+ installSettingsNavIcons(ctx);
1569
+ installSidebarSessionMenuAug();
1570
+ installSidebarStatusDots();
1571
+ installSidebarWorkspaceDrag();
1572
+ const workspacesSvc = ctx.get("workspaces");
1573
+ ctx.slots.inject(
1574
+ "settings.section",
1575
+ () => ctx.slots.register(
1576
+ { name: "settings.section", id: "session-manager", order: 90, label: "\u4F1A\u8BDD\u7BA1\u7406" },
1577
+ (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionPanel, { ...props, workspacesSvc })
1578
+ )
1579
+ );
1580
+ }
1581
+ return module.exports; } });
1582
+ //# sourceMappingURL=client.js.map