dsh-sessions-manager 3.2.2 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +6 -1
- package/README.md +6 -1
- package/lib/client.js +99 -5
- package/lib/client.js.map +2 -2
- package/lib/index.js +299 -24
- package/lib/index.js.map +4 -4
- package/package.json +1 -1
- package/src/client/index.jsx +90 -6
- package/src/client/logic.js +6 -0
- package/src/index.js +77 -0
- package/src/markdown.js +175 -0
- package/src/star-index.js +109 -0
package/README.en.md
CHANGED
|
@@ -16,6 +16,7 @@ A persistent DSH plugin (host + browser halves). Starting with v3.0.0, it covers
|
|
|
16
16
|
|
|
17
17
|
## Changelog
|
|
18
18
|
|
|
19
|
+
- **v3.3.0**: new **starred sessions** — an always-visible star button on each row and a dedicated "Starred" view, backed by a plugin-owned schema v3 index (reusing the recycle bin's version-migration / serialized-mutation / atomic-write pattern); new **single-session Markdown export** (human-readable transcript, sectioned by turn, with user / assistant / tool-call summaries); the detail panel gains an **export section** whose "Download raw log (ZIP)" action reuses DSH's official `session.export` endpoint (subsessions + attachments included, auto-hidden when the backend lacks raw-artifact support) instead of duplicating it.
|
|
19
20
|
- **v3.2.2**: engineering hardening, no behavior change. Sidebar decision logic extracted to `src/client/logic.js` (dot semantics / drop validation / fiber row detection) with 13 new regression tests; CI now smoke-tests each runtime version against real cordis and tracks runtime drift.
|
|
20
21
|
- **v3.2.1**: zstd session-log safety fix (frame-boundary scan mismatching zstd magic inside compressed data).
|
|
21
22
|
- **v3.2.0**: sidebar cross-workspace drag & drop + full session management workbench.
|
|
@@ -35,12 +36,14 @@ A persistent DSH plugin (host + browser halves). Starting with v3.0.0, it covers
|
|
|
35
36
|
|
|
36
37
|
### Settings panel: Session Manager
|
|
37
38
|
|
|
38
|
-
- **Unified panel**:
|
|
39
|
+
- **Unified panel**: five top-level views — **All / Active / Archived / Starred / Recycle bin** — with search across title, session ID, and workspace, plus workspace filters and creation-time/title sorting.
|
|
40
|
+
- **Starred sessions**: an always-visible star button on each session row toggles starring optimistically with rollback on failure; the Starred view is orthogonal to DSH's active/archived states and they stack. The star index is plugin-owned (schema v3) and never touches DSH logs; stars are cleaned up automatically when a session is permanently purged.
|
|
39
41
|
- **Cold-title synchronization**: the sidebar is corrected from the latest log-backed `session/title`, so renamed cold sessions no longer need to be opened before showing their current name.
|
|
40
42
|
- **Sidebar workspace drag-and-drop**: drag a session onto a workspace heading to move it, with a highlighted drop target, same-workspace protection, failure feedback, and the More → Move session menu retained for keyboard access.
|
|
41
43
|
- **Archive / Restore**: archive hides a session from the sidebar; restore unarchives it and puts it back into its original workspace group.
|
|
42
44
|
- **Move to a workspace**: pick an **existing workspace**, or enter a **new directory path** (auto-created); the new-path mode also lets you open the **native OS directory picker** with a **「浏览…」** button. The session's working directory and log are migrated together, and even an open session can be moved safely.
|
|
43
45
|
- **Session details**: expand any session to see **disk usage**, **turns / steps / user·assistant messages / tool calls / image attachments** stats, **tool-usage breakdown**, **search·fetch records**, the **write/edit file list** (already filtered for paths that no longer exist on disk), and **lineage** (parent session / child sessions / subagents).
|
|
46
|
+
- **Export**: the detail panel offers two actions — "**Download raw log (ZIP)**" goes straight to DSH's official `session.export` endpoint (subsessions + attachments included, hidden automatically when the persistence backend lacks raw-artifact support); "**Export Markdown**" renders the session into a human-readable transcript (front matter + per-turn sections + user / assistant / tool-call summaries, with no streaming-delta duplication).
|
|
44
47
|
- **Batch multi-select**: select-all / archive selected / restore selected / delete selected (single confirmation for batch delete).
|
|
45
48
|
|
|
46
49
|
### Main sidebar: session ⋯ menu augmentation
|
|
@@ -144,6 +147,8 @@ lib/client.js pre-built client (ModuleLoader CJS handshake)
|
|
|
144
147
|
| POST | `/archived-sessions/move` | Move a session to a target workspace `{ sessionId, targetPath }` |
|
|
145
148
|
| POST | `/archived-sessions/details` | Session details (disk / stats / tools / fetch / files / lineage) `{ sessionId }` |
|
|
146
149
|
| POST | `/archived-sessions/sidebar-state` | Authoritative sidebar titles, recycle-bin IDs, and permanent-deletion tombstones |
|
|
150
|
+
| POST | `/archived-sessions/star/set` | Star / unstar sessions `{ sessionId | sessionIds, starred }` |
|
|
151
|
+
| GET | `/archived-sessions/export-md?sessionId=` | Single-session Markdown export (human-readable transcript) |
|
|
147
152
|
|
|
148
153
|
> Deleting a session moves it to the recycle bin by default; only "permanently delete" inside the recycle bin physically removes the log. Permanently deleted sessions are hidden forever on the client side so they don't reappear in the sidebar or "ungrouped" due to DSH runtime caching.
|
|
149
154
|
|
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
## 更新日志
|
|
18
18
|
|
|
19
|
+
- **v3.3.0**:新增**收藏(星标)**——会话行内常驻星标按钮与独立「已收藏」视图,索引采用 schema v3(沿用回收站的版本迁移 / 串行变更 / 原子写入模式);新增**单会话 Markdown 导出**(人类可读对话记录,按轮分节,含用户 / 助手 / 工具调用摘要);详情面板新增**导出区**,「下载原始日志 (ZIP)」直接复用 DSH 官方 `session.export` 端点(含子会话与附件,后端不支持时自动降级隐藏),不重复造轮子。
|
|
19
20
|
- **v3.2.2**:工程加固版,无功能变化。侧栏判定纯逻辑抽取到 `src/client/logic.js`(状态点语义 / 拖拽校验 / fiber 行识别),新增 13 个回归测试;CI 新增 runtime 版本冒烟(真实 cordis DI 契约校验 + 版本漂移追踪)。
|
|
20
21
|
- **v3.2.1**:zstd 会话日志安全修复(帧边界定位误匹配压缩数据内的 magic)。
|
|
21
22
|
- **v3.2.0**:侧栏跨工作区拖拽 + 完整会话管理工作台。
|
|
@@ -35,12 +36,14 @@
|
|
|
35
36
|
|
|
36
37
|
### 设置面板:会话管理
|
|
37
38
|
|
|
38
|
-
- **统一面板**:顶部提供「全部 / 活动 / 已归档 /
|
|
39
|
+
- **统一面板**:顶部提供「全部 / 活动 / 已归档 / 已收藏 / 回收站」五个视图,支持按标题、会话 ID、工作区搜索,按工作区筛选,并按创建时间或标题排序。
|
|
40
|
+
- **收藏(星标)**:会话行左侧常驻星标按钮,单击即收藏 / 取消(乐观更新、失败回滚);「已收藏」视图与 DSH 的活动 / 归档状态正交、可叠加;收藏索引为插件自有 schema v3,不触碰 DSH 日志,会话被彻底删除时自动清理。
|
|
39
41
|
- **冷态标题同步**:侧栏使用日志中最新的 `session/title` 修正冷启动缓存,改名后的会话无需先打开即可显示新名称。
|
|
40
42
|
- **侧栏跨工作区拖拽**:直接把会话拖到目标工作区标题即可切换工作区;目标高亮、同工作区拦截、失败反馈,并保留“更多 → 移动会话”作为键盘操作入口。
|
|
41
43
|
- **归档 / 恢复**:归档把会话从侧栏隐藏;恢复取消归档并放回原工作区分组。
|
|
42
44
|
- **移动到工作区**:任选**已有工作区**或**新建目录路径**(自动创建),新建目录支持点击 **「浏览…」** 调用系统目录选择窗口。会话的工作目录与日志一起迁移;即使会话处于打开状态也可安全移动。
|
|
43
45
|
- **会话详情**:展开单条会话查看**磁盘占用**、**轮次 / 步骤 / 用户·助手消息 / 工具调用 / 图片附件**统计、**工具使用分布**、**搜索·抓取记录**、**write/edit 写过的文件列表**(已过滤磁盘上已不存在的路径),以及**血统**(父会话 / 子会话 / 子代理)。
|
|
46
|
+
- **导出**:详情面板底部提供两个入口——「**下载原始日志 (ZIP)**」直接走 DSH 官方 `session.export` 端点(含子会话与附件,持久化后端不支持时自动隐藏);「**导出 Markdown**」由本插件把会话渲染为人类可读对话记录(front matter + 按轮分节 + 用户 / 助手 / 工具调用摘要,流式增量不重复)。
|
|
44
47
|
- **批量多选**:全选 / 批量归档 / 恢复所选 / 删除所选(批量删除一次二次确认)。
|
|
45
48
|
|
|
46
49
|
### 主页侧边栏:会话 ⋯ 菜单增强
|
|
@@ -144,6 +147,8 @@ lib/client.js 预构建 client(ModuleLoader CJS handshake)
|
|
|
144
147
|
| POST | `/archived-sessions/move` | 把会话移动到目标工作区 `{ sessionId, targetPath }` |
|
|
145
148
|
| POST | `/archived-sessions/details` | 会话详情(磁盘/统计/工具/fetch/文件/血统)`{ sessionId }` |
|
|
146
149
|
| POST | `/archived-sessions/sidebar-state` | 返回侧栏权威标题、回收站 ID 与永久删除墓碑 |
|
|
150
|
+
| POST | `/archived-sessions/star/set` | 收藏 / 取消收藏 `{ sessionId | sessionIds, starred }` |
|
|
151
|
+
| GET | `/archived-sessions/export-md?sessionId=` | 单会话 Markdown 导出(人类可读对话记录) |
|
|
147
152
|
|
|
148
153
|
> 删除会话默认进入回收站,只有回收站内的「彻底删除」才会物理移除日志。被彻底删除的会话由前端永久隐藏,避免 DSH 运行时缓存使其重新出现在侧栏或「未分组」中。
|
|
149
154
|
|
package/lib/client.js
CHANGED
|
@@ -75,6 +75,9 @@ function workspaceForNodes(nodes) {
|
|
|
75
75
|
}
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
78
|
+
function starredOf(items) {
|
|
79
|
+
return (items || []).filter((item) => item && item.starred);
|
|
80
|
+
}
|
|
78
81
|
|
|
79
82
|
// src/client/index.jsx
|
|
80
83
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -122,6 +125,11 @@ var CSS = `
|
|
|
122
125
|
.archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}
|
|
123
126
|
.archv-dot{color:var(--dsw-alias-border-l3);flex:none}
|
|
124
127
|
.archv-check{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);flex:none;cursor:pointer}
|
|
128
|
+
.archv-star{appearance:none;width:24px;height:24px;flex:none;display:inline-flex;align-items:center;justify-content:center;border:none;background:0 0;border-radius:7px;cursor:pointer;color:var(--dsw-alias-label-tertiary);transition:color .15s ease,background-color .15s ease}
|
|
129
|
+
.archv-star:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}
|
|
130
|
+
.archv-star svg{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linejoin:round}
|
|
131
|
+
.archv-star-on,.archv-star-on:hover{color:var(--dsw-alias-state-business-primary)}
|
|
132
|
+
.archv-star-on svg{fill:currentColor}
|
|
125
133
|
.archv-body{flex:1;min-width:0;display:flex;align-items:center;gap:12px}
|
|
126
134
|
.archv-actions{display:flex;gap:8px;flex:none;flex-wrap:nowrap;justify-content:flex-end}
|
|
127
135
|
.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}
|
|
@@ -167,6 +175,9 @@ var CSS = `
|
|
|
167
175
|
.dtl-k{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
168
176
|
.dtl-v{font-size:12px;color:var(--dsw-alias-label-primary);word-break:break-all}
|
|
169
177
|
.dtl-sec{margin-top:12px}
|
|
178
|
+
.dtl-export{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
179
|
+
.dtl-export .archv-btn{text-decoration:none}
|
|
180
|
+
.dtl-note{margin-top:8px;font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5}
|
|
170
181
|
.dtl-sec-t{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);text-transform:uppercase;letter-spacing:.03em;margin-bottom:6px}
|
|
171
182
|
.dtl-tags{display:flex;flex-wrap:wrap;gap:6px}
|
|
172
183
|
.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}
|
|
@@ -268,7 +279,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
268
279
|
const [sessions, setSessions] = (0, import_react.useState)(null);
|
|
269
280
|
const [workspaces, setWorkspaces] = (0, import_react.useState)([]);
|
|
270
281
|
const initialPrefs = (0, import_react.useRef)(loadPanelPrefs()).current;
|
|
271
|
-
const [filter, setFilter] = (0, import_react.useState)(() => ["all", "active", "archived", "trash"].includes(initialPrefs.filter) ? initialPrefs.filter : "all");
|
|
282
|
+
const [filter, setFilter] = (0, import_react.useState)(() => ["all", "active", "archived", "starred", "trash"].includes(initialPrefs.filter) ? initialPrefs.filter : "all");
|
|
272
283
|
const [query, setQuery] = (0, import_react.useState)("");
|
|
273
284
|
const [workspaceFilter, setWorkspaceFilter] = (0, import_react.useState)(() => initialPrefs.workspaceFilter || "all");
|
|
274
285
|
const [sortBy, setSortBy] = (0, import_react.useState)(() => ["newest", "oldest", "title"].includes(initialPrefs.sortBy) ? initialPrefs.sortBy : "newest");
|
|
@@ -291,6 +302,9 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
291
302
|
const [details, setDetails] = (0, import_react.useState)({});
|
|
292
303
|
const [openDetails, setOpenDetails] = (0, import_react.useState)(null);
|
|
293
304
|
const [detailsLoading, setDetailsLoading] = (0, import_react.useState)(null);
|
|
305
|
+
const [mdBusy, setMdBusy] = (0, import_react.useState)(null);
|
|
306
|
+
const [zipOk, setZipOk] = (0, import_react.useState)(true);
|
|
307
|
+
const zipChecked = (0, import_react.useRef)(false);
|
|
294
308
|
const [openMenu, setOpenMenu] = (0, import_react.useState)(null);
|
|
295
309
|
const timer = (0, import_react.useRef)(null);
|
|
296
310
|
const menuRef = (0, import_react.useRef)(null);
|
|
@@ -329,6 +343,43 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
329
343
|
} catch (e) {
|
|
330
344
|
}
|
|
331
345
|
}, [filter, workspaceFilter, sortBy]);
|
|
346
|
+
const toggleStar = async (it) => {
|
|
347
|
+
const next = !it.starred;
|
|
348
|
+
setSessions((s) => s && s.map((x) => x.sessionId === it.sessionId ? { ...x, starred: next } : x));
|
|
349
|
+
try {
|
|
350
|
+
await postJSON("/archived-sessions/star/set", { sessionId: it.sessionId, starred: next });
|
|
351
|
+
} catch (e) {
|
|
352
|
+
setSessions((s) => s && s.map((x) => x.sessionId === it.sessionId ? { ...x, starred: !next } : x));
|
|
353
|
+
showToast("\u6536\u85CF\u5931\u8D25\uFF1A" + String(e && e.message || e));
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const exportMarkdown = async (it) => {
|
|
357
|
+
if (mdBusy) return;
|
|
358
|
+
setMdBusy(it.sessionId);
|
|
359
|
+
try {
|
|
360
|
+
const res = await fetch("/archived-sessions/export-md?sessionId=" + encodeURIComponent(it.sessionId));
|
|
361
|
+
if (!res.ok) throw new Error("HTTP " + res.status);
|
|
362
|
+
const blob = await res.blob();
|
|
363
|
+
const url = URL.createObjectURL(blob);
|
|
364
|
+
const a = document.createElement("a");
|
|
365
|
+
a.href = url;
|
|
366
|
+
a.download = "dsh-session-" + it.sessionId + ".md";
|
|
367
|
+
document.body.appendChild(a);
|
|
368
|
+
a.click();
|
|
369
|
+
a.remove();
|
|
370
|
+
URL.revokeObjectURL(url);
|
|
371
|
+
showToast("\u5DF2\u5BFC\u51FA Markdown");
|
|
372
|
+
} catch (e) {
|
|
373
|
+
showToast("\u5BFC\u51FA\u5931\u8D25\uFF1A" + String(e && e.message || e));
|
|
374
|
+
} finally {
|
|
375
|
+
setMdBusy(null);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
(0, import_react.useEffect)(() => {
|
|
379
|
+
if (openDetails === null || zipChecked.current) return;
|
|
380
|
+
zipChecked.current = true;
|
|
381
|
+
fetch("/api/session.export?sessionId=probe&includeDescendants=false", { method: "HEAD" }).then((res) => setZipOk(res.status !== 501)).catch(() => setZipOk(true));
|
|
382
|
+
}, [openDetails]);
|
|
332
383
|
(0, import_react.useEffect)(() => {
|
|
333
384
|
if (openMenu === null) return;
|
|
334
385
|
const onDown = (e) => {
|
|
@@ -366,9 +417,10 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
366
417
|
};
|
|
367
418
|
const archivedList = sessions ? sessions.filter((x) => x.archived) : [];
|
|
368
419
|
const activeList = sessions ? sessions.filter((x) => !x.archived) : [];
|
|
420
|
+
const starredList = starredOf(sessions);
|
|
369
421
|
const list = (0, import_react.useMemo)(() => {
|
|
370
422
|
if (filter === "trash") return [];
|
|
371
|
-
const base = filter === "archived" ? archivedList : filter === "active" ? activeList : sessions || [];
|
|
423
|
+
const base = filter === "archived" ? archivedList : filter === "active" ? activeList : filter === "starred" ? starredList : sessions || [];
|
|
372
424
|
const needle = query.trim().toLocaleLowerCase();
|
|
373
425
|
const filtered = base.filter((item) => {
|
|
374
426
|
if (workspaceFilter !== "all" && (item.workspacePath || "") !== workspaceFilter) return false;
|
|
@@ -676,6 +728,15 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
676
728
|
archivedList.length,
|
|
677
729
|
")"
|
|
678
730
|
] }),
|
|
731
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "starred", className: "sess-fbtn" + (filter === "starred" ? " sess-fbtn-on" : ""), onClick: () => {
|
|
732
|
+
setFilter("starred");
|
|
733
|
+
clearSel();
|
|
734
|
+
setConfirmBatch(false);
|
|
735
|
+
}, children: [
|
|
736
|
+
"\u5DF2\u6536\u85CF (",
|
|
737
|
+
starredList.length,
|
|
738
|
+
")"
|
|
739
|
+
] }),
|
|
679
740
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", role: "tab", "aria-selected": filter === "trash", className: "sess-fbtn" + (filter === "trash" ? " sess-fbtn-on" : ""), onClick: () => {
|
|
680
741
|
setFilter("trash");
|
|
681
742
|
clearSel();
|
|
@@ -712,11 +773,11 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
712
773
|
"\u663E\u793A ",
|
|
713
774
|
list.length,
|
|
714
775
|
" \u4E2A\u4F1A\u8BDD",
|
|
715
|
-
query || workspaceFilter !== "all" ? `\uFF0C\u5171 ${filter === "archived" ? archivedList.length : filter === "active" ? activeList.length : sessions.length} \u4E2A` : ""
|
|
776
|
+
query || workspaceFilter !== "all" ? `\uFF0C\u5171 ${filter === "archived" ? archivedList.length : filter === "active" ? activeList.length : filter === "starred" ? starredList.length : sessions.length} \u4E2A` : ""
|
|
716
777
|
] })
|
|
717
778
|
] }),
|
|
718
779
|
filter !== "trash" && list.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-batch", children: [
|
|
719
|
-
/* @__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` }),
|
|
780
|
+
/* @__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` : filter === "starred" ? `\u5171 ${starredList.length} \u4E2A\u6536\u85CF\u4F1A\u8BDD` : `\u5171 ${sessions.length} \u4E2A\u4F1A\u8BDD\uFF08\u6D3B\u52A8 ${activeList.length} / \u5DF2\u5F52\u6863 ${archivedList.length}\uFF09` }),
|
|
720
781
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: list.length === 0, onClick: selectAll, children: "\u5168\u9009" }),
|
|
721
782
|
selIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
722
783
|
filter === "archived" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
@@ -727,7 +788,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
727
788
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: clearSel, children: "\u53D6\u6D88\u9009\u62E9" })
|
|
728
789
|
] })
|
|
729
790
|
] }),
|
|
730
|
-
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) => {
|
|
791
|
+
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" : filter === "starred" ? "\u8FD8\u6CA1\u6709\u6536\u85CF\u7684\u4F1A\u8BDD\u3002\u70B9\u51FB\u4F1A\u8BDD\u5DE6\u4FA7\u7684\u661F\u6807\u5373\u53EF\u6536\u85CF\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) => {
|
|
731
792
|
const date = fmtDate(it.createdAt);
|
|
732
793
|
const expanded = openMove === it.sessionId;
|
|
733
794
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-card" + (expanded ? " archv-card-exp" : ""), role: "listitem", children: [
|
|
@@ -742,6 +803,21 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
742
803
|
"aria-label": "\u9009\u62E9 " + (it.title || it.sessionId)
|
|
743
804
|
}
|
|
744
805
|
),
|
|
806
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
807
|
+
"button",
|
|
808
|
+
{
|
|
809
|
+
type: "button",
|
|
810
|
+
className: "archv-star" + (it.starred ? " archv-star-on" : ""),
|
|
811
|
+
"aria-pressed": !!it.starred,
|
|
812
|
+
"aria-label": (it.starred ? "\u53D6\u6D88\u6536\u85CF " : "\u6536\u85CF ") + (it.title || it.sessionId),
|
|
813
|
+
title: it.starred ? "\u53D6\u6D88\u6536\u85CF" : "\u6536\u85CF",
|
|
814
|
+
onClick: (e) => {
|
|
815
|
+
e.stopPropagation();
|
|
816
|
+
toggleStar(it);
|
|
817
|
+
},
|
|
818
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2.5l2.9 5.9 6.6.9-4.8 4.6 1.2 6.5-5.9-3.1-5.9 3.1 1.2-6.5L2.5 9.3l6.6-.9z" }) })
|
|
819
|
+
}
|
|
820
|
+
),
|
|
745
821
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-body", children: [
|
|
746
822
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-main", children: [
|
|
747
823
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
|
|
@@ -911,6 +987,24 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
911
987
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: d.lineage.subagents.join(", ") })
|
|
912
988
|
] })
|
|
913
989
|
] })
|
|
990
|
+
] }),
|
|
991
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u5BFC\u51FA" }),
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-export", children: [
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
995
|
+
"a",
|
|
996
|
+
{
|
|
997
|
+
className: "archv-btn",
|
|
998
|
+
href: `/api/session.export?sessionId=${encodeURIComponent(it.sessionId)}&includeDescendants=true`,
|
|
999
|
+
onClick: (e) => e.stopPropagation(),
|
|
1000
|
+
style: zipOk ? void 0 : { pointerEvents: "none", opacity: 0.45 },
|
|
1001
|
+
title: zipOk ? "\u542B\u5B50\u4F1A\u8BDD\u4E0E\u9644\u4EF6\uFF0C\u7531 DSH \u63D0\u4F9B" : "\u5F53\u524D\u6301\u4E45\u5316\u540E\u7AEF\u4E0D\u652F\u6301\u539F\u59CB\u65E5\u5FD7\u5BFC\u51FA",
|
|
1002
|
+
children: "\u4E0B\u8F7D\u539F\u59CB\u65E5\u5FD7 (ZIP)"
|
|
1003
|
+
}
|
|
1004
|
+
),
|
|
1005
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mdBusy === it.sessionId, onClick: () => exportMarkdown(it), children: mdBusy === it.sessionId ? "\u751F\u6210\u4E2D\u2026" : "\u5BFC\u51FA Markdown" })
|
|
1006
|
+
] }),
|
|
1007
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "ZIP \u542B\u5B50\u4F1A\u8BDD\u4E0E\u9644\u4EF6\uFF0C\u7531 DSH \u63D0\u4F9B \xB7 Markdown \u4E3A\u672C\u63D2\u4EF6\u751F\u6210\u7684\u53EF\u8BFB\u5BF9\u8BDD\u8BB0\u5F55" })
|
|
914
1008
|
] })
|
|
915
1009
|
] });
|
|
916
1010
|
})()
|