@bit-ark/dsh-archive 0.1.0 → 0.1.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/README.md CHANGED
@@ -9,7 +9,9 @@
9
9
  - **入口**:侧边栏 footer 的「归档 N」按钮(宽栏显示文字 + 计数,rail 窄栏为圆形
10
10
  图标按钮)。当前项目没有归档时按钮隐藏;归档第一个会话后自动出现。
11
11
  - **面板**:点击按钮在 footer 上方打开浮动面板,支持 Escape / 点击外部关闭。
12
- 面板结构:头部(标题 + 关闭)→ 滚动列表 → footer(归档计数提示 + 一键删除)。
12
+ 面板结构:头部(标题 + 关闭)→ 滚动列表 → footer(一键删除按钮)。面板上
13
+ 不常驻任何说明/结果提示:删除动作只保留点击时的 `window.confirm` 二次确认,
14
+ 确认后直接执行;删除失败的错误明细以错误横幅显示,关闭面板后即清除。
13
15
  - **列表**:只显示当前项目的已归档会话——归档会话属于当前项目当且仅当它在该项目的
14
16
  workspace 记账中,或其存储 cwd 等于项目路径。当前项目解析不依赖打开的会话:
15
17
  最近活跃 workspace → 当前会话所属 workspace → 当前会话 cwd 对应的 workspace。
@@ -18,7 +20,8 @@
18
20
  workspace 记账、移出归档集合,并尽力清理投影缓存行。正在运行(live)的会话会被拒绝。
19
21
  - **一键删除**:面板底部 footer 区域的按钮,确认后把当前项目全部已归档会话一次性
20
22
  批量硬删除——复用单删的同一套步骤(逐会话),运行中的会话跳过、单个硬错误不中断
21
- 整批,完成后显示汇总(删除 / 跳过 / 失败计数与失败明细)。
23
+ 整批。成功后不再显示汇总(「删除即删除」),仅当有会话删除失败时在面板内以错误
24
+ 横幅显示失败明细。
22
25
 
23
26
  ## 结构
24
27
 
package/lib/client.js CHANGED
@@ -290,49 +290,23 @@ function apply(ctx) {
290
290
  lineHeight: "1",
291
291
  cursor: "pointer"
292
292
  },
293
- footerHint: {
294
- flex: 1,
295
- minWidth: 0,
296
- overflow: "hidden",
297
- textOverflow: "ellipsis",
298
- whiteSpace: "nowrap",
299
- color: "var(--dsw-alias-label-tertiary)",
300
- fontSize: "12px",
301
- lineHeight: "16px"
302
- },
303
293
  panelFooter: {
304
294
  flex: "none",
305
295
  display: "flex",
306
296
  alignItems: "center",
297
+ justifyContent: "flex-end",
307
298
  gap: "8px",
308
299
  minHeight: "44px",
309
300
  padding: "0 12px",
310
301
  boxSizing: "border-box",
311
302
  borderTop: "1px solid var(--dsw-alias-border-l2)"
312
303
  },
313
- notice: {
314
- padding: "8px 12px",
315
- marginBottom: "8px",
316
- borderRadius: "8px",
317
- border: "1px solid var(--dsw-alias-border-l2)",
318
- background: "var(--dsw-alias-bg-base)",
319
- color: "var(--dsw-alias-label-primary)",
320
- fontSize: "12px",
321
- whiteSpace: "pre-wrap",
322
- wordBreak: "break-all"
323
- },
324
304
  panelBody: {
325
305
  flex: 1,
326
306
  minHeight: 0,
327
307
  overflowY: "auto",
328
308
  padding: "8px 12px 12px"
329
309
  },
330
- hint: {
331
- color: "var(--dsw-alias-label-tertiary)",
332
- fontSize: "12px",
333
- lineHeight: "18px",
334
- margin: "4px 0 8px"
335
- },
336
310
  error: {
337
311
  padding: "8px 12px",
338
312
  marginBottom: "8px",
@@ -399,11 +373,14 @@ function apply(ctx) {
399
373
  const [busy, setBusy] = (0, import_react.useState)(null);
400
374
  const [batchBusy, setBatchBusy] = (0, import_react.useState)(false);
401
375
  const [error, setError] = (0, import_react.useState)(null);
402
- const [notice, setNotice] = (0, import_react.useState)(null);
403
376
  const panelRef = (0, import_react.useRef)(null);
404
377
  const triggerRef = (0, import_react.useRef)(null);
405
378
  const busyRef = (0, import_react.useRef)(false);
406
379
  const batchBusyRef = (0, import_react.useRef)(false);
380
+ const closePanel = () => {
381
+ setError(null);
382
+ setOpen(false);
383
+ };
407
384
  const workspace = (0, import_react.useMemo)(() => {
408
385
  const items = workspaces?.items;
409
386
  if (items === void 0 || items.length === 0) return void 0;
@@ -448,13 +425,17 @@ function apply(ctx) {
448
425
  (0, import_react.useEffect)(() => {
449
426
  if (!open) return;
450
427
  const onKey = (event) => {
451
- if (event.key === "Escape") setOpen(false);
428
+ if (event.key === "Escape") {
429
+ setError(null);
430
+ setOpen(false);
431
+ }
452
432
  };
453
433
  const onPointerDown = (event) => {
454
434
  const target = event.target;
455
435
  if (target === null) return;
456
436
  if (panelRef.current?.contains(target) === true) return;
457
437
  if (triggerRef.current?.contains(target) === true) return;
438
+ setError(null);
458
439
  setOpen(false);
459
440
  };
460
441
  document.addEventListener("keydown", onKey);
@@ -472,7 +453,6 @@ function apply(ctx) {
472
453
  if (busyRef.current) return;
473
454
  busyRef.current = true;
474
455
  setError(null);
475
- setNotice(null);
476
456
  setBusy({ id, action });
477
457
  try {
478
458
  await callHost(action, { sessionId: id });
@@ -510,7 +490,6 @@ function apply(ctx) {
510
490
  if (batchBusyRef.current) return;
511
491
  batchBusyRef.current = true;
512
492
  setError(null);
513
- setNotice(null);
514
493
  setBatchBusy(true);
515
494
  void (async () => {
516
495
  try {
@@ -528,14 +507,15 @@ function apply(ctx) {
528
507
  const chunkFailures = payload.failures;
529
508
  if (chunkFailures !== void 0 && chunkFailures.length > 0) failures.push(...chunkFailures);
530
509
  }
531
- const parts = [`\u5DF2\u5220\u9664 ${deleted} \u4E2A`];
532
- if (skipped > 0) parts.push(`\u8DF3\u8FC7\u8FD0\u884C\u4E2D ${skipped} \u4E2A`);
533
- if (failed > 0) parts.push(`\u5931\u8D25 ${failed} \u4E2A`);
534
- let message = parts.join("\uFF0C");
535
- if (failures.length > 0) {
536
- message += `\uFF1A${failures.map((item) => `${item.sessionId}\uFF08${item.error}\uFF09`).join("\uFF1B")}`;
510
+ if (failed > 0) {
511
+ const parts = [`\u5DF2\u5220\u9664 ${deleted} \u4E2A`, `\u5931\u8D25 ${failed} \u4E2A`];
512
+ if (skipped > 0) parts.push(`\u8DF3\u8FC7\u8FD0\u884C\u4E2D ${skipped} \u4E2A`);
513
+ let message = parts.join("\uFF0C");
514
+ if (failures.length > 0) {
515
+ message += `\uFF1A${failures.map((item) => `${item.sessionId}\uFF08${item.error}\uFF09`).join("\uFF1B")}`;
516
+ }
517
+ setError(message);
537
518
  }
538
- setNotice(message);
539
519
  ctx.sessions.refresh?.().catch?.(() => {
540
520
  });
541
521
  ctx.workspaces.refresh?.().catch?.(() => {
@@ -551,7 +531,7 @@ function apply(ctx) {
551
531
  const openSession = (id) => {
552
532
  try {
553
533
  ctx.sessions.open(id);
554
- setOpen(false);
534
+ closePanel();
555
535
  } catch {
556
536
  }
557
537
  };
@@ -577,16 +557,14 @@ function apply(ctx) {
577
557
  style: styles.close,
578
558
  "aria-label": "\u5173\u95ED",
579
559
  onClick: () => {
580
- setOpen(false);
560
+ closePanel();
581
561
  },
582
562
  children: "\u2715"
583
563
  }
584
564
  )
585
565
  ] }),
586
566
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.panelBody, children: [
587
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.hint, children: "\u4EC5\u663E\u793A\u5F53\u524D\u9879\u76EE\u7684\u5F52\u6863\u3002\u4E0B\u8F7D\u4F1A\u5BFC\u51FA\u8BE5\u4F1A\u8BDD\u7684\u65E5\u5FD7 ZIP\uFF1B\u6062\u590D\u4F1A\u628A\u4F1A\u8BDD\u653E\u56DE\u4FA7\u8FB9\u680F\uFF1B\u5220\u9664\u4F1A\u6C38\u4E45\u79FB\u9664\u4F1A\u8BDD\u7684\u5168\u90E8\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6062\u590D\u3002" }),
588
567
  error !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.error, children: error }) : null,
589
- notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.notice, children: notice }) : null,
590
568
  rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.empty, children: "\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD" }) : null,
591
569
  rows.map((row) => {
592
570
  const rowBusy = busy !== null && busy.id === row.id;
@@ -665,26 +643,22 @@ function apply(ctx) {
665
643
  ] }, row.id);
666
644
  })
667
645
  ] }),
668
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", { style: styles.panelFooter, children: [
669
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.footerHint, children: rows.length === 0 ? "\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD" : `\u5171 ${rows.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u8FD0\u884C\u4E2D\u7684\u4F1A\u8DF3\u8FC7\uFF09` }),
670
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
671
- "button",
672
- {
673
- type: "button",
674
- className: "dsh-archive-batch",
675
- style: {
676
- ...styles.batchDelete,
677
- opacity: batchBusy || busy !== null || rows.length === 0 ? 0.5 : 1
678
- },
679
- disabled: batchBusy || busy !== null || rows.length === 0,
680
- title: rows.length === 0 ? "\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD" : `\u4E00\u952E\u5220\u9664\u5F53\u524D\u9879\u76EE\u5168\u90E8 ${rows.length} \u4E2A\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08\u8FD0\u884C\u4E2D\u7684\u4F1A\u8DF3\u8FC7\uFF09`,
681
- onClick: () => {
682
- deleteAll();
683
- },
684
- children: batchBusy ? "\u5220\u9664\u4E2D\u2026" : "\u4E00\u952E\u5220\u9664"
685
- }
686
- )
687
- ] })
646
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { style: styles.panelFooter, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
647
+ "button",
648
+ {
649
+ type: "button",
650
+ className: "dsh-archive-batch",
651
+ style: {
652
+ ...styles.batchDelete,
653
+ opacity: batchBusy || busy !== null || rows.length === 0 ? 0.5 : 1
654
+ },
655
+ disabled: batchBusy || busy !== null || rows.length === 0,
656
+ onClick: () => {
657
+ deleteAll();
658
+ },
659
+ children: batchBusy ? "\u5220\u9664\u4E2D\u2026" : "\u4E00\u952E\u5220\u9664"
660
+ }
661
+ ) })
688
662
  ]
689
663
  }
690
664
  ),
@@ -700,7 +674,8 @@ function apply(ctx) {
700
674
  "aria-expanded": open,
701
675
  title: wide ? void 0 : `\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08${String(rows.length)}\uFF09`,
702
676
  onClick: () => {
703
- setOpen((value) => !value);
677
+ if (open) closePanel();
678
+ else setOpen(true);
704
679
  },
705
680
  children: [
706
681
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchiveIcon, { size: wide ? 16 : 18 }),
package/lib/client.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/client/index.tsx"],
4
- "sourcesContent": ["/**\n * dsh-archive \u2014 \u5BA2\u6237\u7AEF\u534A\uFF08Browser\uFF09\u3002\n *\n * \u5728\u4FA7\u8FB9\u680F footer \u52A8\u4F5C\u5217\u8868\u6CE8\u518C\u4E00\u4E2A\u6761\u76EE\uFF1A\u5F52\u6863\u52A8\u4F5C\u3002footer \u52A8\u4F5C\u5E38\u9A7B\u663E\u793A\n * \uFF08\u5BBD\u680F = \u6587\u5B57 + \u8BA1\u6570\uFF0Crail \u7A84\u680F = \u7EAF\u56FE\u6807\uFF1B\u9879\u76EE\u65E0\u5F52\u6863\u65F6\u8BA1\u6570\u4E3A 0\uFF09\u3002\u70B9\u51FB\n * \u540E\u5728 footer \u4E0A\u65B9\u6253\u5F00\u6D6E\u52A8\u9762\u677F\uFF0C\u53EA\u5217\u51FA\u300C\u5F53\u524D\u9879\u76EE\u300D\u7684\u5DF2\u5F52\u6863\u4F1A\u8BDD\u2014\u2014\u5F52\u6863\u4F1A\u8BDD\n * \u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\u5F53\u4E14\u4EC5\u5F53\uFF1A\u5B83\u5728\u5F53\u524D workspace \u7684\u8D26\u76EE\u4E2D\uFF0C\u6216\u5176\u5B58\u50A8\u7684 cwd \u7B49\u4E8E\n * \u9879\u76EE\u8DEF\u5F84\u3002\u6BCF\u884C\u63D0\u4F9B\u4E09\u4E2A\u52A8\u8BCD\uFF1A\n *\n * - \u4E0B\u8F7D\uFF1A\u5BF9\u63A5 harness \u6838\u5FC3\u7AEF\u70B9\u7684\u81EA\u5305\u542B\u5BFC\u51FA\uFF08/api/session.export\uFF0C\u4E0E\n * session-log-download \u63D2\u4EF6\u65E0\u5173\uFF1B\u540E\u8005\u4E0D\u5728\u672C\u90E8\u7F72\u7684 bundle \u5217\u8868\u91CC\uFF0C\u5176\u5934\u90E8\n * \u6309\u94AE\u4F4D\u88AB notifier \u94C3\u94DB\u5360\u636E\uFF09\u3002\u6BCF\u4E2A\u4F1A\u8BDD\u7684\u5BFC\u51FA\u72B6\u6001\u5B58\u5728\u672C\u63D2\u4EF6\u81EA\u5DF1\u7684 store\n * \u91CC\uFF08\u6A21\u5757\u7EA7 downloadStates\uFF09\uFF0C\u884C UI \u7A7A\u95F2\u6E32\u67D3\u4E5F\u4E0D\u4E22\u72B6\u6001\u3002\n * - \u6062\u590D\uFF1APOST /dsh-archive/restore\u2014\u2014\u5BBF\u4E3B\u628A\u4F1A\u8BDD\u79FB\u51FA\u5F52\u6863\u96C6\u5408\uFF1B\u968F\u540E\u5E7F\u64AD\n * \u7684 host/archived-sessions-changed \u5E27\u4F1A\u8BA9\u4FA7\u8FB9\u680F\u4E0E\u9762\u677F\u81EA\u52A8\u5237\u65B0\u3002\n * - \u5220\u9664\uFF1A\u786E\u8BA4\u540E POST /dsh-archive/delete\u2014\u2014\u5BBF\u4E3B\u786C\u5220\u9664\uFF08\u6301\u4E45\u5316\u5DE5\u4EF6 +\n * workspace \u8D26\u76EE + \u5F52\u6863\u96C6\u5408\uFF09\uFF1B\u6210\u529F\u540E\u672C\u9875\u4E3B\u52A8\u5237\u65B0 sessions \u4E0E workspaces\n * \u5217\u8868\uFF0C\u8BA9\u4FA7\u8FB9\u680F\u7ACB\u5373\u6D88\u5931\u3001\u4E0D\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\u3002\n * - \u4E00\u952E\u5220\u9664\uFF1A\u9762\u677F\u5E95\u90E8 footer \u533A\u57DF\u7684\u6309\u94AE\uFF0C\u786E\u8BA4\u540E POST\n * /dsh-archive/delete-all\u2014\u2014\u628A\u5F53\u524D\u9879\u76EE\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\u4E00\u6B21\u6027\u6279\u91CF\u786C\u5220\u9664\n * \uFF08\u5BBF\u4E3B\u4FA7\u8DF3\u8FC7\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\uFF09\uFF0C\u6210\u529F\u540E\u540C\u6837\u5237\u65B0\u4E24\u4E2A\u5217\u8868\u5E76\u663E\u793A\u6C47\u603B\n * \uFF08\u5220\u9664 / \u8DF3\u8FC7 / \u5931\u8D25\u8BA1\u6570\u4E0E\u5931\u8D25\u660E\u7EC6\uFF09\u3002\n *\n * \u300C\u5F53\u524D\u9879\u76EE\u300D\u4E0D\u4F9D\u8D56\u4EFB\u4F55\u6253\u5F00\u7684\u4F1A\u8BDD\u5373\u53EF\u89E3\u6790\uFF1A\u6700\u8FD1\u6D3B\u8DC3\u7684 workspace \u2192 \u6301\u6709\n * \u5F53\u524D\u4F1A\u8BDD\u7684 workspace \u8D26\u76EE \u2192 \u5F53\u524D\u4F1A\u8BDD cwd \u5BF9\u5E94\u7684 workspace\u3002\u884C\u6570\u636E\u5168\u90E8\u6765\u81EA\n * \u8FD0\u884C\u65F6\u65E2\u6709 store\uFF08ctx.workspaces.list \u63D0\u4F9B\u5F52\u6863\u96C6\u5408\uFF0Cctx.sessions.list \u63D0\u4F9B\n * \u6807\u9898\uFF09\uFF1B\u53EA\u6709\u4E24\u4E2A\u53D8\u66F4\u64CD\u4F5C\u9700\u8981\u672C\u63D2\u4EF6\u81EA\u5DF1\u7684\u5BBF\u4E3B\u8DEF\u7531\u3002\n *\n * \u653E\u7F6E\u7406\u7531\uFF1A\u5F52\u6863\u662F\u4FA7\u8FB9\u680F\u52A8\u4F5C\uFF08workspace \u6D4F\u89C8\u5668\u53F3\u952E\u300C\u5F52\u6863\u4F1A\u8BDD\u300D\uFF09\uFF0C\u6062\u590D\u540E\n * \u4E5F\u56DE\u5230\u540C\u4E00\u5217\u8868\u2014\u2014\u7BA1\u7406\u754C\u9762\u653E\u5728\u751F\u547D\u5468\u671F\u8D77\u70B9\u4E0E\u7EC8\u70B9\u6240\u5728\u7684\u4FA7\u8FB9\u680F\uFF0C\u800C\u4E0D\u662F\u653E\u5728\n * session \u4F5C\u7528\u57DF\u7684\u4F1A\u8BDD tab \u884C\u91CC\u3002\n */\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\n\nexport const inject = ['slots', 'sessions', 'workspaces']\n\n/** \u6279\u91CF\u5220\u9664\u5355\u6B21\u8BF7\u6C42\u7684 id \u4E0A\u9650\uFF08\u5BBF\u4E3B\u786C\u4E0A\u9650 500\uFF1B\u53D6 200 \u7559\u4F59\u91CF\u4E14\u8FDB\u5EA6\u53EF\u611F\u77E5\uFF09\u3002 */\nconst DELETE_BATCH_SIZE = 200\n\n/** \u7EBF\u4E0A\u6570\u636E\u5F62\u72B6\uFF08\u5BBF\u4E3B\u57DF\u5BF9\u8C61\u7684\u7EAF JSON \u6295\u5F71\uFF09\u3002 */\ninterface WorkspaceRow {\n workspaceId: string\n path: string\n title: string\n sessionIds: readonly string[]\n}\ninterface WorkspaceListSnapshot {\n items: readonly WorkspaceRow[]\n archivedSessionIds: readonly string[]\n recentWorkspaceId?: string\n}\ninterface SessionSummaryRow {\n id: string\n displayTitle: string\n cwd?: string\n updatedAt: number\n}\ninterface SessionListSnapshot {\n byId: Record<string, SessionSummaryRow | undefined>\n current?: string\n}\n\n/** \u9762\u677F\u91CC\u7684\u4E00\u884C\u5F52\u6863\u4F1A\u8BDD\u3002 */\ninterface ArchiveRow {\n id: string\n title: string\n updatedAt?: number\n}\n\n/**\n * \u8C03\u7528\u5BBF\u4E3B\u7AEF\u70B9\uFF08restore | delete | delete-all\uFF09\u3002\n * \u6210\u529F\u8981\u6C42 HTTP 200 \u4E14 payload.ok === true\uFF0C\u5426\u5219\u629B\u51FA\u53EF\u8BFB\u9519\u8BEF\u3002\n */\nasync function callHost(endpoint: 'restore' | 'delete' | 'delete-all', body: Record<string, unknown>): Promise<Record<string, unknown>> {\n const response = await fetch(`/dsh-archive/${endpoint}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n let payload: { ok?: boolean; error?: string } | undefined\n try {\n payload = await response.json() as { ok?: boolean; error?: string }\n } catch {\n payload = undefined\n }\n if (!response.ok || payload === undefined || payload.ok !== true) {\n throw new Error(payload?.error ?? `\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${String(response.status)}\uFF09`)\n }\n return payload as Record<string, unknown>\n}\n\n/** \u65F6\u95F4\u6233 \u2192 \u672C\u5730\u53EF\u8BFB\u65F6\u95F4\u5B57\u7B26\u4E32\uFF08\u975E\u6CD5\u8F93\u5165\u8FD4\u56DE\u7A7A\u4E32\uFF09\u3002 */\nfunction formatTime(value: number | undefined): string {\n if (value === undefined || Number.isNaN(value)) return ''\n try {\n return new Date(value).toLocaleString()\n } catch {\n return ''\n }\n}\n\n/** \u5185\u8054\u5F52\u6863\u7BB1\u56FE\u6807\uFF08\u4E0D\u5F15\u5165\u56FE\u6807\u5305\u4F9D\u8D56\uFF0C\u4FDD\u6301\u63D2\u4EF6\u81EA\u5305\u542B\uFF09\u3002 */\nfunction ArchiveIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <rect x=\"1.5\" y=\"2\" width=\"13\" height=\"3.5\" rx=\"1\" />\n <path d=\"M2.5 5.5v7a1.5 1.5 0 0 0 1.5 1.5h8a1.5 1.5 0 0 0 1.5-1.5v-7\" />\n <path d=\"M6 8.5h4\" />\n </svg>\n )\n}\n\n/**\n * \u6BCF\u4E2A\u4F1A\u8BDD\u7684\u65E5\u5FD7\u5BFC\u51FA\u72B6\u6001\uFF08\u672C\u63D2\u4EF6\u79C1\u6709 store\uFF0C\u884C UI \u7A7A\u95F2\u6E32\u67D3\u4E5F\u4FDD\u7559\uFF09\u3002\n * \u6A21\u5757\u7EA7\u800C\u975E\u7EC4\u4EF6\u7EA7\uFF1A\u9762\u677F\u5173\u95ED\u518D\u6253\u5F00\u3001\u884C\u91CD\u6E32\u67D3\u65F6\u4E0B\u8F7D\u72B6\u6001\u4E0D\u4E22\u3002\n */\ntype DownloadStatus = 'downloading' | 'success' | 'error'\ninterface DownloadEntry { status: DownloadStatus; error?: string }\nconst downloadStates: Record<string, DownloadEntry> = {}\nconst downloadListeners = new Set<() => void>()\n/** \u5728\u9014\u4E0B\u8F7D\u7684 sessionId \u96C6\u5408\uFF1A\u540C\u6B65\u62E6\u622A\u540C\u4E00\u4F1A\u8BDD\u7684\u91CD\u590D\u70B9\u51FB\uFF08\u6309\u94AE\u7981\u7528\u8981\u7B49\u6E32\u67D3\uFF09\u3002 */\nconst downloadInflight = new Set<string>()\n\n/**\n * \u4F9B useSyncExternalStore \u4F7F\u7528\u7684\u7F13\u5B58\u5FEB\u7167\u3002\u5305\u88C5\u5C42\u5FC5\u987B\u4FDD\u6301\u5F15\u7528\u7A33\u5B9A\uFF1A\n * useSyncExternalStore \u7528 Object.is \u6BD4\u8F83 getSnapshot() \u7684\u7ED3\u679C\uFF0C\u82E5\u6BCF\u6B21\u8BFB\u53D6\n * \u90FD\u8FD4\u56DE\u65B0\u5BF9\u8C61\u4F1A\u9020\u6210\u65E0\u9650\u91CD\u6E32\u67D3\uFF08React #185\uFF09\u3002\u53EA\u6709 emitDownloads \u5728\u72B6\u6001\n * \u771F\u6B63\u53D8\u5316\u65F6\u624D\u66FF\u6362\u5FEB\u7167\u3002\n */\nlet downloadsSnapshot: { bySession: Record<string, DownloadEntry> } = { bySession: {} }\n/** \u8BA2\u9605\u4E0B\u8F7D\u72B6\u6001\u53D8\u5316\uFF1B\u8FD4\u56DE\u53D6\u6D88\u8BA2\u9605\u51FD\u6570\uFF08useSyncExternalStore \u5951\u7EA6\uFF09\u3002 */\nfunction subscribeDownloads(listener: () => void): () => void {\n downloadListeners.add(listener)\n return () => { downloadListeners.delete(listener) }\n}\n/** \u5E7F\u64AD\u5FEB\u7167\u53D8\u66F4\uFF1A\u91CD\u5EFA\u5FEB\u7167\u5BF9\u8C61\u5E76\u9010\u4E2A\u901A\u77E5\u8BA2\u9605\u8005\u3002 */\nfunction emitDownloads(): void {\n downloadsSnapshot = { bySession: { ...downloadStates } }\n for (const listener of downloadListeners) listener()\n}\n/** \u5F53\u524D\u5FEB\u7167\uFF08\u5F15\u7528\u7A33\u5B9A\uFF0C\u4EC5\u5728 emitDownloads \u65F6\u66FF\u6362\uFF09\u3002 */\nfunction getDownloadsSnapshot(): { bySession: Record<string, DownloadEntry> } {\n return downloadsSnapshot\n}\n\n/** \u540C\u6E90 Host \u57FA\u5740\uFF08\u8FDE\u63A5\u8F7D\u4F53\u7684 null-origin \u515C\u5E95\uFF09\u3002 */\nfunction hostBase(): string {\n const origin = (globalThis as { location?: { origin?: string } }).location?.origin\n return origin !== undefined && origin !== 'null' ? origin : 'http://dsh.internal'\n}\n\n/** \u4E3A\u67D0\u4E2A\u4F1A\u8BDD id \u751F\u6210\u5B89\u5168\u7684\u6D4F\u89C8\u5668\u4E0B\u8F7D\u6587\u4EF6\u540D\u3002 */\nfunction sessionLogZipFilename(sessionId: string): string {\n return `dsh-session-${String(sessionId).replace(/[^A-Za-z0-9_-]/g, '_')}.zip`\n}\n\n/** /api/session.export \u7684 URL \u2014\u2014 \u6838\u5FC3 API\uFF0C\u4E0E session-log-download \u65E0\u5173\u3002 */\nfunction exportUrl(sessionId: string): string {\n const url = new URL('/api/session.export', hostBase())\n url.searchParams.set('sessionId', sessionId)\n url.searchParams.set('includeDescendants', 'true')\n return url.toString()\n}\n\n/**\n * \u628A\u4E00\u4E2A\u5F52\u6863\u4F1A\u8BDD\u7684\u65E5\u5FD7\u4F5C\u4E3A ZIP \u901A\u8FC7\u6D4F\u89C8\u5668\u4E0B\u8F7D\u7BA1\u7406\u5668\u5BFC\u51FA\u3002\n * \u5148 HEAD \u63A2\u6D4B\u53EF\u7528\u6027\uFF0C\u518D\u7528 <a download> \u89E6\u53D1 GET \u4E0B\u8F7D\uFF1B\u72B6\u6001\u5199\u5165\u79C1\u6709 store\u3002\n * downloadInflight \u505A\u540C\u6B65\u53BB\u91CD\uFF1A\u540C\u4E00\u4F1A\u8BDD\u7684\u7B2C\u4E8C\u6B21\u70B9\u51FB\uFF08\u6E32\u67D3\u7981\u7528\u751F\u6548\u524D\uFF09\n * \u76F4\u63A5\u5FFD\u7565\uFF0C\u907F\u514D\u53CC\u53D1 HEAD+GET\u3002\n *\n * \u5DF2\u77E5\u9650\u5236\uFF1A<a download> \u89E6\u53D1\u7684\u662F\u6D4F\u89C8\u5668\u539F\u751F\u4E0B\u8F7D\uFF0C\u65E0\u6CD5\u56DE\u8BFB GET \u7ED3\u679C\u2014\u2014HEAD\n * \u901A\u8FC7\u4F46 GET \u671F\u95F4\u5931\u8D25\uFF08\u5982\u4F1A\u8BDD\u6070\u5728\u4E24\u6B65\u4E4B\u95F4\u88AB\u5220\uFF09\u65F6\uFF0C\u6D4F\u89C8\u5668\u4F1A\u628A\u9519\u8BEF\u4F53\u5B58\u6210\n * .zip \u4E14 UI \u5DF2\u6807\u8BB0\u6210\u529F\u3002\u4E0E harness \u81EA\u5E26 session-log-download \u63A7\u5236\u5668\u540C\u6B3E\n * \u884C\u4E3A\uFF08\u5E73\u53F0\u7EA7\u9650\u5236\uFF09\uFF0C\u6545\u4E0D\u505A\u4E8C\u6B21\u6821\u9A8C\u3002\n */\nasync function downloadSessionLog(sessionId: string): Promise<void> {\n if (downloadInflight.has(sessionId)) return\n downloadInflight.add(sessionId)\n downloadStates[sessionId] = { status: 'downloading' }\n emitDownloads()\n try {\n const response = await fetch(exportUrl(sessionId), { method: 'HEAD' })\n if (!response.ok) throw new Error(`\u5BFC\u51FA\u5931\u8D25\uFF1AHTTP ${response.status}`)\n const anchor = document.createElement('a')\n anchor.href = exportUrl(sessionId)\n anchor.download = sessionLogZipFilename(sessionId)\n anchor.click()\n downloadStates[sessionId] = { status: 'success' }\n } catch (error: unknown) {\n downloadStates[sessionId] = {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n }\n } finally {\n downloadInflight.delete(sessionId)\n }\n emitDownloads()\n}\n\n/**\n * \u6E05\u7406\u5DF2\u4E0D\u5B58\u5728\u4F1A\u8BDD\u7684\u4E0B\u8F7D\u72B6\u6001\uFF1A\u884C\u6D88\u5931\uFF08\u4F1A\u8BDD\u88AB\u5220 / \u79FB\u51FA\u9879\u76EE\uFF09\u540E\uFF0C\u6B8B\u7559\u7684\n * success/error \u6761\u76EE\u4F1A\u5728\u4F1A\u8BDD id \u5C06\u6765\u590D\u7528\u65F6\u9519\u8BEF\u5730\u91CD\u65B0\u51FA\u73B0\uFF1B\u9762\u677F\u5173\u95ED\u65F6\u7EDF\u4E00\n * \u4FEE\u526A\u4E00\u6B21\uFF08\u6A21\u5757\u7EA7 store \u957F\u9A7B\uFF0C\u53EA\u9760\u65B0\u589E\u8986\u76D6\u4F1A\u65E0\u9650\u81A8\u80C0\uFF09\u3002\n */\nfunction pruneDownloads(activeIds: ReadonlySet<string>): void {\n let changed = false\n for (const id of Object.keys(downloadStates)) {\n if (!activeIds.has(id)) {\n delete downloadStates[id]\n changed = true\n }\n }\n if (changed) emitDownloads()\n}\n\nexport function apply(ctx: any): void {\n // \u4E00\u5F20\u5E26\u6807\u8BB0\u7684\u6837\u5F0F\u8868\uFF0C\u8865\u4E0A\u5185\u8054\u6837\u5F0F\u8868\u8FBE\u4E0D\u4E86\u7684 hover / active \u6001\u3002\n // \u4E0E dsh-update \u540C\u6837\u7684\u7EA6\u5B9A\uFF08id + data-plugin\uFF09\uFF1B\u5B88\u536B\u9632\u6B62\u91CD\u590D\u6302\u8F7D\u91CD\u590D\u63D2\u6807\u7B7E\u3002\n const STYLE_ID = 'dsh-archive-style'\n if (typeof document !== 'undefined' && document.getElementById(STYLE_ID) === null) {\n const styleEl = document.createElement('style')\n styleEl.id = STYLE_ID\n styleEl.setAttribute('data-plugin', 'dsh-archive')\n styleEl.textContent = `\n .dsh-archive-badge {\n background: transparent;\n }\n .dsh-archive-badge:hover,\n .dsh-archive-badge[data-active] {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n .dsh-archive-close:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n .dsh-archive-batch:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);\n }\n `\n document.head.appendChild(styleEl)\n }\n\n const styles = {\n // \u4FA7\u8FB9\u680F footer \u628A\u52A8\u4F5C\u6392\u6210\u4E00\u884C\u6C34\u5E73 flex\uFF08flex-direction: row, nowrap\uFF09\u3002\n // \u6761\u76EE\u662F\u5360\u6EE1\u6574\u884C\u7684 flex \u9879\uFF08\u53EF\u6536\u7F29\uFF0C\u672A\u6765\u6709\u5144\u5F1F\u52A8\u4F5C\u65F6\u5171\u4EAB\u7A7A\u95F4\u800C\u975E\u88AB\u6324\u51FA\uFF09\uFF0C\n // \u5FBD\u6807\u51E0\u4F55\u4E0E\u8BBE\u7F6E\u89E6\u53D1\u6309\u94AE\u4E00\u81F4\u2014\u2014\u540C\u4E3A 34px \u9AD8\u300112px \u5706\u89D2\u300114px/22px \u5B57\u4F53\uFF0C\n // hover \u9AD8\u4EAE\u5411\u5916\u6EA2\u51FA 4px\u3002rail \u7A84\u680F\u4FDD\u6301 36px \u5706\u5F62\u3002\n layer: {\n position: 'relative',\n flex: '1 1 auto',\n minWidth: 0,\n display: 'flex',\n alignItems: 'center',\n },\n layerRail: {\n flex: 'none',\n },\n badge: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n width: 'calc(100% + 8px)',\n height: '34px',\n margin: '4px -4px 4px',\n padding: '6px 10px',\n boxSizing: 'border-box',\n border: 'none',\n borderRadius: '12px',\n color: 'var(--dsw-alias-label-primary)',\n fontFamily: 'inherit',\n fontSize: '14px',\n lineHeight: '22px',\n cursor: 'pointer',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n badgeRail: {\n justifyContent: 'center',\n gap: '0',\n width: '36px',\n height: '36px',\n margin: '8px 0 10px',\n padding: '0',\n borderRadius: '50%',\n },\n badgeLabel: {\n flex: 'none',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n badgeCount: {\n flex: 'none',\n marginLeft: 'auto',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n lineHeight: '16px',\n fontVariantNumeric: 'tabular-nums',\n },\n panel: {\n position: 'fixed',\n left: '12px',\n bottom: '128px',\n zIndex: 30,\n display: 'flex',\n flexDirection: 'column',\n width: '420px',\n maxWidth: 'calc(100vw - 24px)',\n maxHeight: '60vh',\n overflow: 'hidden',\n border: '1px solid var(--dsw-alias-border-l1)',\n borderRadius: '12px',\n background: 'var(--dsw-alias-bg-base)',\n boxShadow: 'var(--dsw-shadow-lv2)',\n },\n panelHeader: {\n flex: 'none',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n minHeight: '44px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderBottom: '1px solid var(--dsw-alias-border-l2)',\n },\n panelTitle: {\n fontSize: '13px',\n fontWeight: 500,\n lineHeight: '20px',\n color: 'var(--dsw-alias-label-primary)',\n },\n panelProject: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: '12px',\n color: 'var(--dsw-alias-label-tertiary)',\n },\n close: {\n flex: 'none',\n marginLeft: 'auto',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n padding: 0,\n border: 'none',\n borderRadius: '6px',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '14px',\n cursor: 'pointer',\n },\n batchDelete: {\n flex: 'none',\n display: 'inline-flex',\n alignItems: 'center',\n height: '24px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderRadius: '6px',\n border: '1px solid var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: '12px',\n lineHeight: '1',\n cursor: 'pointer',\n },\n footerHint: {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n lineHeight: '16px',\n },\n panelFooter: {\n flex: 'none',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n minHeight: '44px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderTop: '1px solid var(--dsw-alias-border-l2)',\n },\n notice: {\n padding: '8px 12px',\n marginBottom: '8px',\n borderRadius: '8px',\n border: '1px solid var(--dsw-alias-border-l2)',\n background: 'var(--dsw-alias-bg-base)',\n color: 'var(--dsw-alias-label-primary)',\n fontSize: '12px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n },\n panelBody: {\n flex: 1,\n minHeight: 0,\n overflowY: 'auto',\n padding: '8px 12px 12px',\n },\n hint: {\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n lineHeight: '18px',\n margin: '4px 0 8px',\n },\n error: {\n padding: '8px 12px',\n marginBottom: '8px',\n borderRadius: '8px',\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: '12px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n },\n row: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n marginBottom: '8px',\n borderRadius: '8px',\n border: '1px solid var(--dsw-alias-border-l2)',\n background: 'var(--dsw-alias-bg-base)',\n },\n rowMain: {\n flex: 1,\n minWidth: 0,\n },\n rowTitle: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n fontSize: '13px',\n color: 'var(--dsw-alias-label-primary)',\n },\n rowMeta: {\n marginTop: '2px',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n },\n buttonBase: {\n flex: 'none',\n padding: '4px 12px',\n borderRadius: '6px',\n fontSize: '12px',\n cursor: 'pointer',\n background: 'transparent',\n },\n empty: {\n padding: '24px 0',\n textAlign: 'center',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n },\n } as const\n\n /** \u4FA7\u8FB9\u680F footer \u7684\u5F52\u6863\u52A8\u4F5C\uFF1A\u5FBD\u6807 + \u6D6E\u52A8\u9762\u677F\u3002 */\n function ArchiveFooterAction(props: { wide?: boolean }): any {\n const wide = props.wide !== false\n // \u8BA2\u9605\u8FD0\u884C\u65F6 store\uFF1Aworkspaces\uFF08\u5F52\u6863\u96C6\u5408 / \u9879\u76EE\u89E3\u6790\uFF09\u3001sessions\uFF08\u6807\u9898\uFF09\u3002\n const workspaces = useSyncExternalStore(\n ctx.workspaces.list.subscribe as (listener: () => void) => () => void,\n () => ctx.workspaces.list.getSnapshot() as WorkspaceListSnapshot,\n )\n const sessions = useSyncExternalStore(\n ctx.sessions.list.subscribe as (listener: () => void) => () => void,\n () => ctx.sessions.list.getSnapshot() as SessionListSnapshot,\n )\n const [open, setOpen] = useState(false)\n const [busy, setBusy] = useState<{ id: string; action: 'restore' | 'delete' } | null>(null)\n const [batchBusy, setBatchBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const panelRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n // \u540C\u6B65\u5728\u9014\u5B88\u536B\uFF1AsetBusy \u8981\u7B49\u4E0B\u4E00\u6B21\u6E32\u67D3\u624D\u7981\u7528\u6309\u94AE\uFF0C\u540C\u4E00 tick \u91CC\u7684\u7B2C\u4E8C\u6B21\n // \u70B9\u51FB\u4F1A\u91CD\u65B0\u8FDB\u5165 run/deleteAll\uFF08React 18 \u6279\u5904\u7406\uFF09\u2014\u2014\u7528 ref \u5728\u8FDB\u5165\u65F6\n // \u7ACB\u5373\u62E6\u622A\uFF0C\u675C\u7EDD\u53CC\u51FB\u53CC\u53D1\uFF08\u6279\u91CF\u5220\u9664\u4F1A\u53CC\u8BA1\u6570\u3001\u4E0B\u8F7D\u4F1A\u53CC\u53D1 HEAD+GET\uFF09\u3002\n const busyRef = useRef(false)\n const batchBusyRef = useRef(false)\n\n // \u4E0D\u4F9D\u8D56\u6253\u5F00\u4F1A\u8BDD\u89E3\u6790\u5F53\u524D\u9879\u76EE\uFF1A\u6700\u8FD1\u6D3B\u8DC3 workspace \u2192 \u6301\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\n // workspace \u2192 \u5F53\u524D\u4F1A\u8BDD cwd \u5BF9\u5E94\u7684 workspace\u3002\n const workspace = useMemo((): WorkspaceRow | undefined => {\n const items = workspaces?.items\n if (items === undefined || items.length === 0) return undefined\n const recent = workspaces?.recentWorkspaceId\n if (recent !== undefined) {\n const byRecent = items.find(item => item.workspaceId === recent)\n if (byRecent !== undefined) return byRecent\n }\n const current = sessions?.current\n if (current !== undefined) {\n const byMembership = items.find(item => item.sessionIds.includes(current))\n if (byMembership !== undefined) return byMembership\n const currentCwd = sessions?.byId[current]?.cwd\n if (currentCwd !== undefined) {\n const byPath = items.find(item => item.path === currentCwd)\n if (byPath !== undefined) return byPath\n }\n }\n return undefined\n }, [workspaces, sessions])\n\n const projectLabel = workspace?.title\n\n // \u53EA\u53D6\u5F53\u524D\u9879\u76EE\u7684\u5F52\u6863\uFF1Aworkspace \u8D26\u76EE\u6210\u5458\uFF0C\u6216\u5B58\u50A8 cwd \u7B49\u4E8E\u9879\u76EE\u8DEF\u5F84\u3002\n const rows = useMemo((): ArchiveRow[] => {\n const archived = workspaces?.archivedSessionIds\n if (archived === undefined || archived.length === 0 || workspace === undefined) return []\n const result: ArchiveRow[] = []\n for (const id of archived) {\n const summary = sessions?.byId[id]\n const inAccount = workspace.sessionIds.includes(id)\n const sameProject = summary?.cwd !== undefined && summary.cwd === workspace.path\n if (!inAccount && !sameProject) continue\n result.push({\n id,\n title: summary?.displayTitle ?? id,\n updatedAt: summary?.updatedAt,\n })\n }\n return result\n }, [workspaces, sessions, workspace])\n\n // \u4F1A\u8BDD\u5217\u8868\u53D8\u5316\u65F6\u4FEE\u526A\u4E0B\u8F7D\u72B6\u6001\uFF1A\u5DF2\u4E0D\u5728\u5F53\u524D\u9879\u76EE\u91CC\u7684\u4F1A\u8BDD\uFF08\u88AB\u5220/\u79FB\u51FA\uFF09\u7684\n // \u6B8B\u7559 success/error \u6761\u76EE\u6E05\u6389\uFF0C\u907F\u514D\u72B6\u6001\u65E0\u9650\u5806\u79EF\u6216 id \u590D\u7528\u65F6\u8BEF\u663E\u793A\u3002\n useEffect(() => {\n pruneDownloads(new Set(rows.map(row => row.id)))\n }, [rows])\n\n // Escape \u5173\u95ED\uFF1B\u70B9\u51FB\u9762\u677F\u4E0E\u89E6\u53D1\u6309\u94AE\u4E4B\u5916\u7684\u533A\u57DF\u5173\u95ED\u3002\n // \uFF08\u89E6\u53D1\u6309\u94AE\u88AB\u6392\u9664\u5728\u5916\uFF0C\u8BA9\u70B9\u51FB\u4E8B\u4EF6\u81EA\u5DF1\u8D1F\u8D23\u5F00\u5173\u2014\u2014\u5426\u5219 mousedown \u5173\u95ED\u540E\n // \u7D27\u63A5\u7684 click \u5207\u6362\u4F1A\u7ACB\u523B\u91CD\u65B0\u6253\u5F00\u3002\uFF09\n useEffect(() => {\n if (!open) return\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') setOpen(false)\n }\n const onPointerDown = (event: MouseEvent): void => {\n const target = event.target as Node | null\n if (target === null) return\n if (panelRef.current?.contains(target) === true) return\n if (triggerRef.current?.contains(target) === true) return\n setOpen(false)\n }\n document.addEventListener('keydown', onKey)\n document.addEventListener('mousedown', onPointerDown)\n return () => {\n document.removeEventListener('keydown', onKey)\n document.removeEventListener('mousedown', onPointerDown)\n }\n }, [open])\n\n // \u6BCF\u4E2A\u4F1A\u8BDD\u7684\u5B9E\u65F6\u5BFC\u51FA\u72B6\u6001\uFF08\u79C1\u6709 store\uFF09\uFF0C\u884C\u6309\u94AE\u636E\u6B64\u663E\u793A\u300C\u4E0B\u8F7D\u4E2D\u2026\u300D\u5E76\u7981\u7528\uFF0C\n // \u51FA\u9519\u65F6\u53D8\u6210\u300C\u91CD\u8BD5\u300D\u3002\n const downloads = useSyncExternalStore(\n (listener: () => void) => subscribeDownloads(listener),\n () => getDownloadsSnapshot(),\n )\n\n /** \u6267\u884C\u6062\u590D / \u5220\u9664\uFF1B\u5931\u8D25\u628A\u53EF\u8BFB\u9519\u8BEF\u5199\u5165\u9762\u677F\u3002 */\n const run = async (action: 'restore' | 'delete', id: string): Promise<void> => {\n if (busyRef.current) return\n busyRef.current = true\n setError(null)\n setNotice(null)\n setBusy({ id, action })\n try {\n await callHost(action, { sessionId: id })\n // \u5220\u9664\u540E\u4E3B\u52A8\u5237\u65B0\uFF1Asessions \u5217\u8868\uFF08\u4F1A\u8BDD\u6D88\u5931\uFF09+ workspaces \u5217\u8868\n // \uFF08workspace \u8D26\u76EE\u5DF2\u89E3\u9664\uFF0C\u907F\u514D\u4FA7\u8FB9\u680F\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\uFF09\u3002\n // \u6062\u590D\u4E5F\u5237\u65B0 workspaces\uFF1A\u867D\u7136\u5BBF\u4E3B\u5199\u94FE\u4F1A\u5E7F\u64AD archived-sessions-changed\n // \u9A71\u52A8\u5B9E\u65F6\u5237\u65B0\uFF0C\u4F46\u90A3\u4F9D\u8D56 harness \u5185\u90E8\u4E8B\u4EF6\uFF0C\u8FD9\u91CC\u4E3B\u52A8\u5237\u65B0\u515C\u5E95\u3002\n ctx.sessions.refresh?.().catch?.(() => {})\n ctx.workspaces.refresh?.().catch?.(() => {})\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n busyRef.current = false\n setBusy(null)\n }\n }\n\n /** \u6062\u590D\u5355\u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u56DE\u5230\u4FA7\u8FB9\u680F\u539F\u4F4D\u7F6E\uFF09\u3002 */\n const restore = (id: string): void => { void run('restore', id) }\n /** \u786C\u5220\u9664\u5355\u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u542B\u4E8C\u6B21\u786E\u8BA4\uFF0C\u786E\u8BA4\u6587\u6848\u8BF4\u660E\u4E0D\u53EF\u6062\u590D\uFF09\u3002 */\n const remove = (id: string, title: string): void => {\n const confirmed = window.confirm(\n `\u786E\u5B9A\u8981\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD\u300C${title}\u300D\u5417\uFF1F\\n\\n\u8FD9\u662F\u786C\u5220\u9664\uFF1A\u4F1A\u8BDD\u7684\u6240\u6709\u6587\u4EF6\u90FD\u4F1A\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u6062\u590D\u3002`,\n )\n if (confirmed) void run('delete', id)\n }\n /**\n * \u4E00\u952E\u5220\u9664\uFF1A\u628A\u5F53\u524D\u9879\u76EE\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\u4E00\u6B21\u6027\u786C\u5220\u9664\u3002\n * \u5BBF\u4E3B\u5355\u6B21\u4E0A\u9650 500 \u4E2A id\uFF08\u8D85\u9650\u6574\u6279 400\uFF09\uFF0C\u8FD9\u91CC\u6309 200/\u6279\u5206\u7247\u4E32\u884C\uFF0C\n * \u4FDD\u8BC1\u5F52\u6863\u6570 >500 \u7684\u9879\u76EE\u4E5F\u80FD\u6574\u6279\u5220\u5B8C\u800C\u975E\u6574\u6279\u5931\u8D25\u3002\n */\n const deleteAll = (): void => {\n if (rows.length === 0) return\n const confirmed = window.confirm(\n `\u786E\u5B9A\u8981\u4E00\u952E\u5220\u9664\u5168\u90E8 ${rows.length} \u4E2A\u5DF2\u5F52\u6863\u4F1A\u8BDD\u5417\uFF1F\\n\\n\u8FD9\u662F\u786C\u5220\u9664\uFF1A\u6BCF\u4E2A\u4F1A\u8BDD\u7684\u6240\u6709\u6587\u4EF6\u90FD\u4F1A\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u6062\u590D\u3002\\n\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u4F1A\u88AB\u8DF3\u8FC7\u3002`,\n )\n if (!confirmed) return\n if (batchBusyRef.current) return\n batchBusyRef.current = true\n setError(null)\n setNotice(null)\n setBatchBusy(true)\n void (async () => {\n try {\n const ids = rows.map(row => row.id)\n const total = ids.length\n let deleted = 0\n let skipped = 0\n let failed = 0\n const failures: Array<{ sessionId: string; error: string }> = []\n for (let offset = 0; offset < ids.length; offset += DELETE_BATCH_SIZE) {\n const payload = await callHost('delete-all', { sessionIds: ids.slice(offset, offset + DELETE_BATCH_SIZE) }) as {\n total?: number\n deleted?: number\n skipped?: number\n failed?: number\n failures?: Array<{ sessionId: string; error: string }>\n }\n deleted += payload.deleted ?? 0\n skipped += payload.skipped ?? 0\n failed += payload.failed ?? 0\n const chunkFailures = payload.failures\n if (chunkFailures !== undefined && chunkFailures.length > 0) failures.push(...chunkFailures)\n }\n const parts: string[] = [`\u5DF2\u5220\u9664 ${deleted} \u4E2A`]\n if (skipped > 0) parts.push(`\u8DF3\u8FC7\u8FD0\u884C\u4E2D ${skipped} \u4E2A`)\n if (failed > 0) parts.push(`\u5931\u8D25 ${failed} \u4E2A`)\n let message = parts.join('\uFF0C')\n if (failures.length > 0) {\n message += `\uFF1A${failures.map(item => `${item.sessionId}\uFF08${item.error}\uFF09`).join('\uFF1B')}`\n }\n setNotice(message)\n // \u5220\u9664\u540E\u4E3B\u52A8\u5237\u65B0\uFF1Asessions \u5217\u8868\uFF08\u4F1A\u8BDD\u6D88\u5931\uFF09+ workspaces \u5217\u8868\n // \uFF08workspace \u8D26\u76EE\u5DF2\u89E3\u9664\uFF0C\u907F\u514D\u4FA7\u8FB9\u680F\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\uFF09\u3002\n ctx.sessions.refresh?.().catch?.(() => {})\n ctx.workspaces.refresh?.().catch?.(() => {})\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n batchBusyRef.current = false\n setBatchBusy(false)\n }\n })()\n }\n /** \u6253\u5F00\u4F1A\u8BDD\uFF08\u4ECE\u9762\u677F\u5207\u5230\u4F1A\u8BDD\u533A\uFF09\uFF1B\u5931\u8D25\u901A\u5E38\u662F\u56E0\u4E3A\u5217\u8868\u5237\u65B0\u4E2D\u884C\u5DF2\u6D88\u5931\u3002 */\n const openSession = (id: string): void => {\n try {\n ctx.sessions.open(id)\n setOpen(false)\n } catch {\n // \u884C\u5728\u5217\u8868\u5237\u65B0\u65F6\u6D88\u5931\u7684\u7ADE\u6001\uFF1A\u4E0B\u4E00\u6B21\u6E32\u67D3\u81EA\u7136\u6E05\u6389\u3002\n }\n }\n\n return (\n <div style={wide ? styles.layer : { ...styles.layer, ...styles.layerRail }}>\n {open && (\n <section\n ref={panelRef}\n style={styles.panel}\n aria-label=\"\u5DF2\u5F52\u6863\u4F1A\u8BDD\"\n >\n <header style={styles.panelHeader}>\n <span style={styles.panelTitle}>\u5DF2\u5F52\u6863\u4F1A\u8BDD</span>\n {projectLabel !== undefined\n ? <span style={styles.panelProject}>\u00B7 {projectLabel}</span>\n : null}\n <button\n type=\"button\"\n className=\"dsh-archive-close\"\n style={styles.close}\n aria-label=\"\u5173\u95ED\"\n onClick={() => { setOpen(false) }}\n >\n \u2715\n </button>\n </header>\n <div style={styles.panelBody}>\n <div style={styles.hint}>\n \u4EC5\u663E\u793A\u5F53\u524D\u9879\u76EE\u7684\u5F52\u6863\u3002\u4E0B\u8F7D\u4F1A\u5BFC\u51FA\u8BE5\u4F1A\u8BDD\u7684\u65E5\u5FD7 ZIP\uFF1B\u6062\u590D\u4F1A\u628A\u4F1A\u8BDD\u653E\u56DE\u4FA7\u8FB9\u680F\uFF1B\u5220\u9664\u4F1A\u6C38\u4E45\u79FB\u9664\u4F1A\u8BDD\u7684\u5168\u90E8\u6587\u4EF6\uFF0C\u65E0\u6CD5\u6062\u590D\u3002\n </div>\n {error !== null ? <div style={styles.error}>{error}</div> : null}\n {notice !== null ? <div style={styles.notice}>{notice}</div> : null}\n {rows.length === 0\n ? <div style={styles.empty}>\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD</div>\n : null}\n {rows.map(row => {\n const rowBusy = busy !== null && busy.id === row.id\n const anyBusy = busy !== null || batchBusy\n const time = formatTime(row.updatedAt)\n const dlEntry = downloads?.bySession?.[row.id]\n const downloading = dlEntry?.status === 'downloading'\n const dlError = dlEntry?.status === 'error' ? (dlEntry.error ?? '\u5BFC\u51FA\u5931\u8D25') : null\n return (\n <div key={row.id} style={styles.row}>\n <div style={styles.rowMain}>\n <div\n style={styles.rowTitle}\n title={`\u6253\u5F00\u4F1A\u8BDD ${row.title}`}\n onClick={() => { openSession(row.id) }}\n >\n {row.title}\n </div>\n {time !== '' ? <div style={styles.rowMeta}>{time}</div> : null}\n </div>\n <button\n type=\"button\"\n title={dlError ?? '\u4E0B\u8F7D\u4F1A\u8BDD\u65E5\u5FD7 (ZIP)'}\n disabled={anyBusy || downloading}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n opacity: anyBusy || downloading ? 0.5 : 1,\n }}\n onClick={() => { void downloadSessionLog(row.id) }}\n >\n {downloading ? '\u4E0B\u8F7D\u4E2D\u2026' : dlError !== null ? '\u91CD\u8BD5' : '\u4E0B\u8F7D'}\n </button>\n <button\n type=\"button\"\n disabled={anyBusy}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n opacity: anyBusy && !rowBusy ? 0.5 : 1,\n }}\n onClick={() => { restore(row.id) }}\n >\n {rowBusy && busy?.action === 'restore' ? '\u6062\u590D\u4E2D\u2026' : '\u6062\u590D'}\n </button>\n <button\n type=\"button\"\n disabled={anyBusy}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n opacity: anyBusy && !rowBusy ? 0.5 : 1,\n }}\n onClick={() => { remove(row.id, row.title) }}\n >\n {rowBusy && busy?.action === 'delete' ? '\u5220\u9664\u4E2D\u2026' : '\u5220\u9664'}\n </button>\n </div>\n )\n })}\n </div>\n <footer style={styles.panelFooter}>\n <span style={styles.footerHint}>\n {rows.length === 0\n ? '\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD'\n : `\u5171 ${rows.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u8FD0\u884C\u4E2D\u7684\u4F1A\u8DF3\u8FC7\uFF09`}\n </span>\n <button\n type=\"button\"\n className=\"dsh-archive-batch\"\n style={{\n ...styles.batchDelete,\n opacity: batchBusy || busy !== null || rows.length === 0 ? 0.5 : 1,\n }}\n disabled={batchBusy || busy !== null || rows.length === 0}\n title={rows.length === 0\n ? '\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD'\n : `\u4E00\u952E\u5220\u9664\u5F53\u524D\u9879\u76EE\u5168\u90E8 ${rows.length} \u4E2A\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08\u8FD0\u884C\u4E2D\u7684\u4F1A\u8DF3\u8FC7\uFF09`}\n onClick={() => { deleteAll() }}\n >\n {batchBusy ? '\u5220\u9664\u4E2D\u2026' : '\u4E00\u952E\u5220\u9664'}\n </button>\n </footer>\n </section>\n )}\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"dsh-archive-badge\"\n style={wide ? styles.badge : { ...styles.badge, ...styles.badgeRail }}\n data-active={open || undefined}\n aria-label={`\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08${String(rows.length)}\uFF09`}\n aria-expanded={open}\n title={wide ? undefined : `\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08${String(rows.length)}\uFF09`}\n onClick={() => { setOpen(value => !value) }}\n >\n <ArchiveIcon size={wide ? 16 : 18} />\n {wide && (\n <>\n <span style={styles.badgeLabel}>\u5F52\u6863</span>\n <span style={styles.badgeCount}>{rows.length}</span>\n </>\n )}\n </button>\n </div>\n )\n }\n\n // \u6CE8\u518C\u5230\u4FA7\u8FB9\u680F footer \u52A8\u4F5C\u5217\u8868\uFF08id: archive-panel\uFF09\u3002\n ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register(\n {\n name: 'sidebar.footer.action',\n id: 'archive-panel',\n },\n ArchiveFooterAction,\n ))\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * dsh-archive \u2014 \u5BA2\u6237\u7AEF\u534A\uFF08Browser\uFF09\u3002\n *\n * \u5728\u4FA7\u8FB9\u680F footer \u52A8\u4F5C\u5217\u8868\u6CE8\u518C\u4E00\u4E2A\u6761\u76EE\uFF1A\u5F52\u6863\u52A8\u4F5C\u3002footer \u52A8\u4F5C\u5E38\u9A7B\u663E\u793A\n * \uFF08\u5BBD\u680F = \u6587\u5B57 + \u8BA1\u6570\uFF0Crail \u7A84\u680F = \u7EAF\u56FE\u6807\uFF1B\u9879\u76EE\u65E0\u5F52\u6863\u65F6\u8BA1\u6570\u4E3A 0\uFF09\u3002\u70B9\u51FB\n * \u540E\u5728 footer \u4E0A\u65B9\u6253\u5F00\u6D6E\u52A8\u9762\u677F\uFF0C\u53EA\u5217\u51FA\u300C\u5F53\u524D\u9879\u76EE\u300D\u7684\u5DF2\u5F52\u6863\u4F1A\u8BDD\u2014\u2014\u5F52\u6863\u4F1A\u8BDD\n * \u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\u5F53\u4E14\u4EC5\u5F53\uFF1A\u5B83\u5728\u5F53\u524D workspace \u7684\u8D26\u76EE\u4E2D\uFF0C\u6216\u5176\u5B58\u50A8\u7684 cwd \u7B49\u4E8E\n * \u9879\u76EE\u8DEF\u5F84\u3002\u6BCF\u884C\u63D0\u4F9B\u4E09\u4E2A\u52A8\u8BCD\uFF1A\n *\n * - \u4E0B\u8F7D\uFF1A\u5BF9\u63A5 harness \u6838\u5FC3\u7AEF\u70B9\u7684\u81EA\u5305\u542B\u5BFC\u51FA\uFF08/api/session.export\uFF0C\u4E0E\n * session-log-download \u63D2\u4EF6\u65E0\u5173\uFF1B\u540E\u8005\u4E0D\u5728\u672C\u90E8\u7F72\u7684 bundle \u5217\u8868\u91CC\uFF0C\u5176\u5934\u90E8\n * \u6309\u94AE\u4F4D\u88AB notifier \u94C3\u94DB\u5360\u636E\uFF09\u3002\u6BCF\u4E2A\u4F1A\u8BDD\u7684\u5BFC\u51FA\u72B6\u6001\u5B58\u5728\u672C\u63D2\u4EF6\u81EA\u5DF1\u7684 store\n * \u91CC\uFF08\u6A21\u5757\u7EA7 downloadStates\uFF09\uFF0C\u884C UI \u7A7A\u95F2\u6E32\u67D3\u4E5F\u4E0D\u4E22\u72B6\u6001\u3002\n * - \u6062\u590D\uFF1APOST /dsh-archive/restore\u2014\u2014\u5BBF\u4E3B\u628A\u4F1A\u8BDD\u79FB\u51FA\u5F52\u6863\u96C6\u5408\uFF1B\u968F\u540E\u5E7F\u64AD\n * \u7684 host/archived-sessions-changed \u5E27\u4F1A\u8BA9\u4FA7\u8FB9\u680F\u4E0E\u9762\u677F\u81EA\u52A8\u5237\u65B0\u3002\n * - \u5220\u9664\uFF1A\u786E\u8BA4\u540E POST /dsh-archive/delete\u2014\u2014\u5BBF\u4E3B\u786C\u5220\u9664\uFF08\u6301\u4E45\u5316\u5DE5\u4EF6 +\n * workspace \u8D26\u76EE + \u5F52\u6863\u96C6\u5408\uFF09\uFF1B\u6210\u529F\u540E\u672C\u9875\u4E3B\u52A8\u5237\u65B0 sessions \u4E0E workspaces\n * \u5217\u8868\uFF0C\u8BA9\u4FA7\u8FB9\u680F\u7ACB\u5373\u6D88\u5931\u3001\u4E0D\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\u3002\n * - \u4E00\u952E\u5220\u9664\uFF1A\u9762\u677F\u5E95\u90E8 footer \u533A\u57DF\u7684\u6309\u94AE\uFF0C\u786E\u8BA4\u540E POST\n * /dsh-archive/delete-all\u2014\u2014\u628A\u5F53\u524D\u9879\u76EE\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\u4E00\u6B21\u6027\u6279\u91CF\u786C\u5220\u9664\n * \uFF08\u5BBF\u4E3B\u4FA7\u8DF3\u8FC7\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\uFF09\uFF0C\u6210\u529F\u540E\u540C\u6837\u5237\u65B0\u4E24\u4E2A\u5217\u8868\uFF1B\u4E0D\u518D\u663E\u793A\u6210\u529F\u6C47\u603B\n * \uFF08\"\u5220\u9664\u5373\u5220\u9664\"\uFF09\uFF0C\u4EC5\u5F53\u6709\u4F1A\u8BDD\u5220\u9664\u5931\u8D25\u65F6\u5728\u9519\u8BEF\u6A2A\u5E45\u91CC\u7ED9\u51FA\u5931\u8D25\u660E\u7EC6\u3002\n *\n * \u300C\u5F53\u524D\u9879\u76EE\u300D\u4E0D\u4F9D\u8D56\u4EFB\u4F55\u6253\u5F00\u7684\u4F1A\u8BDD\u5373\u53EF\u89E3\u6790\uFF1A\u6700\u8FD1\u6D3B\u8DC3\u7684 workspace \u2192 \u6301\u6709\n * \u5F53\u524D\u4F1A\u8BDD\u7684 workspace \u8D26\u76EE \u2192 \u5F53\u524D\u4F1A\u8BDD cwd \u5BF9\u5E94\u7684 workspace\u3002\u884C\u6570\u636E\u5168\u90E8\u6765\u81EA\n * \u8FD0\u884C\u65F6\u65E2\u6709 store\uFF08ctx.workspaces.list \u63D0\u4F9B\u5F52\u6863\u96C6\u5408\uFF0Cctx.sessions.list \u63D0\u4F9B\n * \u6807\u9898\uFF09\uFF1B\u53EA\u6709\u4E24\u4E2A\u53D8\u66F4\u64CD\u4F5C\u9700\u8981\u672C\u63D2\u4EF6\u81EA\u5DF1\u7684\u5BBF\u4E3B\u8DEF\u7531\u3002\n *\n * \u653E\u7F6E\u7406\u7531\uFF1A\u5F52\u6863\u662F\u4FA7\u8FB9\u680F\u52A8\u4F5C\uFF08workspace \u6D4F\u89C8\u5668\u53F3\u952E\u300C\u5F52\u6863\u4F1A\u8BDD\u300D\uFF09\uFF0C\u6062\u590D\u540E\n * \u4E5F\u56DE\u5230\u540C\u4E00\u5217\u8868\u2014\u2014\u7BA1\u7406\u754C\u9762\u653E\u5728\u751F\u547D\u5468\u671F\u8D77\u70B9\u4E0E\u7EC8\u70B9\u6240\u5728\u7684\u4FA7\u8FB9\u680F\uFF0C\u800C\u4E0D\u662F\u653E\u5728\n * session \u4F5C\u7528\u57DF\u7684\u4F1A\u8BDD tab \u884C\u91CC\u3002\n */\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\n\nexport const inject = ['slots', 'sessions', 'workspaces']\n\n/** \u6279\u91CF\u5220\u9664\u5355\u6B21\u8BF7\u6C42\u7684 id \u4E0A\u9650\uFF08\u5BBF\u4E3B\u786C\u4E0A\u9650 500\uFF1B\u53D6 200 \u7559\u4F59\u91CF\u4E14\u8FDB\u5EA6\u53EF\u611F\u77E5\uFF09\u3002 */\nconst DELETE_BATCH_SIZE = 200\n\n/** \u7EBF\u4E0A\u6570\u636E\u5F62\u72B6\uFF08\u5BBF\u4E3B\u57DF\u5BF9\u8C61\u7684\u7EAF JSON \u6295\u5F71\uFF09\u3002 */\ninterface WorkspaceRow {\n workspaceId: string\n path: string\n title: string\n sessionIds: readonly string[]\n}\ninterface WorkspaceListSnapshot {\n items: readonly WorkspaceRow[]\n archivedSessionIds: readonly string[]\n recentWorkspaceId?: string\n}\ninterface SessionSummaryRow {\n id: string\n displayTitle: string\n cwd?: string\n updatedAt: number\n}\ninterface SessionListSnapshot {\n byId: Record<string, SessionSummaryRow | undefined>\n current?: string\n}\n\n/** \u9762\u677F\u91CC\u7684\u4E00\u884C\u5F52\u6863\u4F1A\u8BDD\u3002 */\ninterface ArchiveRow {\n id: string\n title: string\n updatedAt?: number\n}\n\n/**\n * \u8C03\u7528\u5BBF\u4E3B\u7AEF\u70B9\uFF08restore | delete | delete-all\uFF09\u3002\n * \u6210\u529F\u8981\u6C42 HTTP 200 \u4E14 payload.ok === true\uFF0C\u5426\u5219\u629B\u51FA\u53EF\u8BFB\u9519\u8BEF\u3002\n */\nasync function callHost(endpoint: 'restore' | 'delete' | 'delete-all', body: Record<string, unknown>): Promise<Record<string, unknown>> {\n const response = await fetch(`/dsh-archive/${endpoint}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n let payload: { ok?: boolean; error?: string } | undefined\n try {\n payload = await response.json() as { ok?: boolean; error?: string }\n } catch {\n payload = undefined\n }\n if (!response.ok || payload === undefined || payload.ok !== true) {\n throw new Error(payload?.error ?? `\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${String(response.status)}\uFF09`)\n }\n return payload as Record<string, unknown>\n}\n\n/** \u65F6\u95F4\u6233 \u2192 \u672C\u5730\u53EF\u8BFB\u65F6\u95F4\u5B57\u7B26\u4E32\uFF08\u975E\u6CD5\u8F93\u5165\u8FD4\u56DE\u7A7A\u4E32\uFF09\u3002 */\nfunction formatTime(value: number | undefined): string {\n if (value === undefined || Number.isNaN(value)) return ''\n try {\n return new Date(value).toLocaleString()\n } catch {\n return ''\n }\n}\n\n/** \u5185\u8054\u5F52\u6863\u7BB1\u56FE\u6807\uFF08\u4E0D\u5F15\u5165\u56FE\u6807\u5305\u4F9D\u8D56\uFF0C\u4FDD\u6301\u63D2\u4EF6\u81EA\u5305\u542B\uFF09\u3002 */\nfunction ArchiveIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <rect x=\"1.5\" y=\"2\" width=\"13\" height=\"3.5\" rx=\"1\" />\n <path d=\"M2.5 5.5v7a1.5 1.5 0 0 0 1.5 1.5h8a1.5 1.5 0 0 0 1.5-1.5v-7\" />\n <path d=\"M6 8.5h4\" />\n </svg>\n )\n}\n\n/**\n * \u6BCF\u4E2A\u4F1A\u8BDD\u7684\u65E5\u5FD7\u5BFC\u51FA\u72B6\u6001\uFF08\u672C\u63D2\u4EF6\u79C1\u6709 store\uFF0C\u884C UI \u7A7A\u95F2\u6E32\u67D3\u4E5F\u4FDD\u7559\uFF09\u3002\n * \u6A21\u5757\u7EA7\u800C\u975E\u7EC4\u4EF6\u7EA7\uFF1A\u9762\u677F\u5173\u95ED\u518D\u6253\u5F00\u3001\u884C\u91CD\u6E32\u67D3\u65F6\u4E0B\u8F7D\u72B6\u6001\u4E0D\u4E22\u3002\n */\ntype DownloadStatus = 'downloading' | 'success' | 'error'\ninterface DownloadEntry { status: DownloadStatus; error?: string }\nconst downloadStates: Record<string, DownloadEntry> = {}\nconst downloadListeners = new Set<() => void>()\n/** \u5728\u9014\u4E0B\u8F7D\u7684 sessionId \u96C6\u5408\uFF1A\u540C\u6B65\u62E6\u622A\u540C\u4E00\u4F1A\u8BDD\u7684\u91CD\u590D\u70B9\u51FB\uFF08\u6309\u94AE\u7981\u7528\u8981\u7B49\u6E32\u67D3\uFF09\u3002 */\nconst downloadInflight = new Set<string>()\n\n/**\n * \u4F9B useSyncExternalStore \u4F7F\u7528\u7684\u7F13\u5B58\u5FEB\u7167\u3002\u5305\u88C5\u5C42\u5FC5\u987B\u4FDD\u6301\u5F15\u7528\u7A33\u5B9A\uFF1A\n * useSyncExternalStore \u7528 Object.is \u6BD4\u8F83 getSnapshot() \u7684\u7ED3\u679C\uFF0C\u82E5\u6BCF\u6B21\u8BFB\u53D6\n * \u90FD\u8FD4\u56DE\u65B0\u5BF9\u8C61\u4F1A\u9020\u6210\u65E0\u9650\u91CD\u6E32\u67D3\uFF08React #185\uFF09\u3002\u53EA\u6709 emitDownloads \u5728\u72B6\u6001\n * \u771F\u6B63\u53D8\u5316\u65F6\u624D\u66FF\u6362\u5FEB\u7167\u3002\n */\nlet downloadsSnapshot: { bySession: Record<string, DownloadEntry> } = { bySession: {} }\n/** \u8BA2\u9605\u4E0B\u8F7D\u72B6\u6001\u53D8\u5316\uFF1B\u8FD4\u56DE\u53D6\u6D88\u8BA2\u9605\u51FD\u6570\uFF08useSyncExternalStore \u5951\u7EA6\uFF09\u3002 */\nfunction subscribeDownloads(listener: () => void): () => void {\n downloadListeners.add(listener)\n return () => { downloadListeners.delete(listener) }\n}\n/** \u5E7F\u64AD\u5FEB\u7167\u53D8\u66F4\uFF1A\u91CD\u5EFA\u5FEB\u7167\u5BF9\u8C61\u5E76\u9010\u4E2A\u901A\u77E5\u8BA2\u9605\u8005\u3002 */\nfunction emitDownloads(): void {\n downloadsSnapshot = { bySession: { ...downloadStates } }\n for (const listener of downloadListeners) listener()\n}\n/** \u5F53\u524D\u5FEB\u7167\uFF08\u5F15\u7528\u7A33\u5B9A\uFF0C\u4EC5\u5728 emitDownloads \u65F6\u66FF\u6362\uFF09\u3002 */\nfunction getDownloadsSnapshot(): { bySession: Record<string, DownloadEntry> } {\n return downloadsSnapshot\n}\n\n/** \u540C\u6E90 Host \u57FA\u5740\uFF08\u8FDE\u63A5\u8F7D\u4F53\u7684 null-origin \u515C\u5E95\uFF09\u3002 */\nfunction hostBase(): string {\n const origin = (globalThis as { location?: { origin?: string } }).location?.origin\n return origin !== undefined && origin !== 'null' ? origin : 'http://dsh.internal'\n}\n\n/** \u4E3A\u67D0\u4E2A\u4F1A\u8BDD id \u751F\u6210\u5B89\u5168\u7684\u6D4F\u89C8\u5668\u4E0B\u8F7D\u6587\u4EF6\u540D\u3002 */\nfunction sessionLogZipFilename(sessionId: string): string {\n return `dsh-session-${String(sessionId).replace(/[^A-Za-z0-9_-]/g, '_')}.zip`\n}\n\n/** /api/session.export \u7684 URL \u2014\u2014 \u6838\u5FC3 API\uFF0C\u4E0E session-log-download \u65E0\u5173\u3002 */\nfunction exportUrl(sessionId: string): string {\n const url = new URL('/api/session.export', hostBase())\n url.searchParams.set('sessionId', sessionId)\n url.searchParams.set('includeDescendants', 'true')\n return url.toString()\n}\n\n/**\n * \u628A\u4E00\u4E2A\u5F52\u6863\u4F1A\u8BDD\u7684\u65E5\u5FD7\u4F5C\u4E3A ZIP \u901A\u8FC7\u6D4F\u89C8\u5668\u4E0B\u8F7D\u7BA1\u7406\u5668\u5BFC\u51FA\u3002\n * \u5148 HEAD \u63A2\u6D4B\u53EF\u7528\u6027\uFF0C\u518D\u7528 <a download> \u89E6\u53D1 GET \u4E0B\u8F7D\uFF1B\u72B6\u6001\u5199\u5165\u79C1\u6709 store\u3002\n * downloadInflight \u505A\u540C\u6B65\u53BB\u91CD\uFF1A\u540C\u4E00\u4F1A\u8BDD\u7684\u7B2C\u4E8C\u6B21\u70B9\u51FB\uFF08\u6E32\u67D3\u7981\u7528\u751F\u6548\u524D\uFF09\n * \u76F4\u63A5\u5FFD\u7565\uFF0C\u907F\u514D\u53CC\u53D1 HEAD+GET\u3002\n *\n * \u5DF2\u77E5\u9650\u5236\uFF1A<a download> \u89E6\u53D1\u7684\u662F\u6D4F\u89C8\u5668\u539F\u751F\u4E0B\u8F7D\uFF0C\u65E0\u6CD5\u56DE\u8BFB GET \u7ED3\u679C\u2014\u2014HEAD\n * \u901A\u8FC7\u4F46 GET \u671F\u95F4\u5931\u8D25\uFF08\u5982\u4F1A\u8BDD\u6070\u5728\u4E24\u6B65\u4E4B\u95F4\u88AB\u5220\uFF09\u65F6\uFF0C\u6D4F\u89C8\u5668\u4F1A\u628A\u9519\u8BEF\u4F53\u5B58\u6210\n * .zip \u4E14 UI \u5DF2\u6807\u8BB0\u6210\u529F\u3002\u4E0E harness \u81EA\u5E26 session-log-download \u63A7\u5236\u5668\u540C\u6B3E\n * \u884C\u4E3A\uFF08\u5E73\u53F0\u7EA7\u9650\u5236\uFF09\uFF0C\u6545\u4E0D\u505A\u4E8C\u6B21\u6821\u9A8C\u3002\n */\nasync function downloadSessionLog(sessionId: string): Promise<void> {\n if (downloadInflight.has(sessionId)) return\n downloadInflight.add(sessionId)\n downloadStates[sessionId] = { status: 'downloading' }\n emitDownloads()\n try {\n const response = await fetch(exportUrl(sessionId), { method: 'HEAD' })\n if (!response.ok) throw new Error(`\u5BFC\u51FA\u5931\u8D25\uFF1AHTTP ${response.status}`)\n const anchor = document.createElement('a')\n anchor.href = exportUrl(sessionId)\n anchor.download = sessionLogZipFilename(sessionId)\n anchor.click()\n downloadStates[sessionId] = { status: 'success' }\n } catch (error: unknown) {\n downloadStates[sessionId] = {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n }\n } finally {\n downloadInflight.delete(sessionId)\n }\n emitDownloads()\n}\n\n/**\n * \u6E05\u7406\u5DF2\u4E0D\u5B58\u5728\u4F1A\u8BDD\u7684\u4E0B\u8F7D\u72B6\u6001\uFF1A\u884C\u6D88\u5931\uFF08\u4F1A\u8BDD\u88AB\u5220 / \u79FB\u51FA\u9879\u76EE\uFF09\u540E\uFF0C\u6B8B\u7559\u7684\n * success/error \u6761\u76EE\u4F1A\u5728\u4F1A\u8BDD id \u5C06\u6765\u590D\u7528\u65F6\u9519\u8BEF\u5730\u91CD\u65B0\u51FA\u73B0\uFF1B\u9762\u677F\u5173\u95ED\u65F6\u7EDF\u4E00\n * \u4FEE\u526A\u4E00\u6B21\uFF08\u6A21\u5757\u7EA7 store \u957F\u9A7B\uFF0C\u53EA\u9760\u65B0\u589E\u8986\u76D6\u4F1A\u65E0\u9650\u81A8\u80C0\uFF09\u3002\n */\nfunction pruneDownloads(activeIds: ReadonlySet<string>): void {\n let changed = false\n for (const id of Object.keys(downloadStates)) {\n if (!activeIds.has(id)) {\n delete downloadStates[id]\n changed = true\n }\n }\n if (changed) emitDownloads()\n}\n\nexport function apply(ctx: any): void {\n // \u4E00\u5F20\u5E26\u6807\u8BB0\u7684\u6837\u5F0F\u8868\uFF0C\u8865\u4E0A\u5185\u8054\u6837\u5F0F\u8868\u8FBE\u4E0D\u4E86\u7684 hover / active \u6001\u3002\n // \u4E0E dsh-update \u540C\u6837\u7684\u7EA6\u5B9A\uFF08id + data-plugin\uFF09\uFF1B\u5B88\u536B\u9632\u6B62\u91CD\u590D\u6302\u8F7D\u91CD\u590D\u63D2\u6807\u7B7E\u3002\n const STYLE_ID = 'dsh-archive-style'\n if (typeof document !== 'undefined' && document.getElementById(STYLE_ID) === null) {\n const styleEl = document.createElement('style')\n styleEl.id = STYLE_ID\n styleEl.setAttribute('data-plugin', 'dsh-archive')\n styleEl.textContent = `\n .dsh-archive-badge {\n background: transparent;\n }\n .dsh-archive-badge:hover,\n .dsh-archive-badge[data-active] {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n .dsh-archive-close:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n .dsh-archive-batch:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);\n }\n `\n document.head.appendChild(styleEl)\n }\n\n const styles = {\n // \u4FA7\u8FB9\u680F footer \u628A\u52A8\u4F5C\u6392\u6210\u4E00\u884C\u6C34\u5E73 flex\uFF08flex-direction: row, nowrap\uFF09\u3002\n // \u6761\u76EE\u662F\u5360\u6EE1\u6574\u884C\u7684 flex \u9879\uFF08\u53EF\u6536\u7F29\uFF0C\u672A\u6765\u6709\u5144\u5F1F\u52A8\u4F5C\u65F6\u5171\u4EAB\u7A7A\u95F4\u800C\u975E\u88AB\u6324\u51FA\uFF09\uFF0C\n // \u5FBD\u6807\u51E0\u4F55\u4E0E\u8BBE\u7F6E\u89E6\u53D1\u6309\u94AE\u4E00\u81F4\u2014\u2014\u540C\u4E3A 34px \u9AD8\u300112px \u5706\u89D2\u300114px/22px \u5B57\u4F53\uFF0C\n // hover \u9AD8\u4EAE\u5411\u5916\u6EA2\u51FA 4px\u3002rail \u7A84\u680F\u4FDD\u6301 36px \u5706\u5F62\u3002\n layer: {\n position: 'relative',\n flex: '1 1 auto',\n minWidth: 0,\n display: 'flex',\n alignItems: 'center',\n },\n layerRail: {\n flex: 'none',\n },\n badge: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n width: 'calc(100% + 8px)',\n height: '34px',\n margin: '4px -4px 4px',\n padding: '6px 10px',\n boxSizing: 'border-box',\n border: 'none',\n borderRadius: '12px',\n color: 'var(--dsw-alias-label-primary)',\n fontFamily: 'inherit',\n fontSize: '14px',\n lineHeight: '22px',\n cursor: 'pointer',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n badgeRail: {\n justifyContent: 'center',\n gap: '0',\n width: '36px',\n height: '36px',\n margin: '8px 0 10px',\n padding: '0',\n borderRadius: '50%',\n },\n badgeLabel: {\n flex: 'none',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n badgeCount: {\n flex: 'none',\n marginLeft: 'auto',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n lineHeight: '16px',\n fontVariantNumeric: 'tabular-nums',\n },\n panel: {\n position: 'fixed',\n left: '12px',\n bottom: '128px',\n zIndex: 30,\n display: 'flex',\n flexDirection: 'column',\n width: '420px',\n maxWidth: 'calc(100vw - 24px)',\n maxHeight: '60vh',\n overflow: 'hidden',\n border: '1px solid var(--dsw-alias-border-l1)',\n borderRadius: '12px',\n background: 'var(--dsw-alias-bg-base)',\n boxShadow: 'var(--dsw-shadow-lv2)',\n },\n panelHeader: {\n flex: 'none',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n minHeight: '44px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderBottom: '1px solid var(--dsw-alias-border-l2)',\n },\n panelTitle: {\n fontSize: '13px',\n fontWeight: 500,\n lineHeight: '20px',\n color: 'var(--dsw-alias-label-primary)',\n },\n panelProject: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: '12px',\n color: 'var(--dsw-alias-label-tertiary)',\n },\n close: {\n flex: 'none',\n marginLeft: 'auto',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n padding: 0,\n border: 'none',\n borderRadius: '6px',\n background: 'transparent',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '14px',\n cursor: 'pointer',\n },\n batchDelete: {\n flex: 'none',\n display: 'inline-flex',\n alignItems: 'center',\n height: '24px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderRadius: '6px',\n border: '1px solid var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: '12px',\n lineHeight: '1',\n cursor: 'pointer',\n },\n panelFooter: {\n flex: 'none',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: '8px',\n minHeight: '44px',\n padding: '0 12px',\n boxSizing: 'border-box',\n borderTop: '1px solid var(--dsw-alias-border-l2)',\n },\n panelBody: {\n flex: 1,\n minHeight: 0,\n overflowY: 'auto',\n padding: '8px 12px 12px',\n },\n error: {\n padding: '8px 12px',\n marginBottom: '8px',\n borderRadius: '8px',\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n fontSize: '12px',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n },\n row: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n marginBottom: '8px',\n borderRadius: '8px',\n border: '1px solid var(--dsw-alias-border-l2)',\n background: 'var(--dsw-alias-bg-base)',\n },\n rowMain: {\n flex: 1,\n minWidth: 0,\n },\n rowTitle: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n fontSize: '13px',\n color: 'var(--dsw-alias-label-primary)',\n },\n rowMeta: {\n marginTop: '2px',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n },\n buttonBase: {\n flex: 'none',\n padding: '4px 12px',\n borderRadius: '6px',\n fontSize: '12px',\n cursor: 'pointer',\n background: 'transparent',\n },\n empty: {\n padding: '24px 0',\n textAlign: 'center',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: '12px',\n },\n } as const\n\n /** \u4FA7\u8FB9\u680F footer \u7684\u5F52\u6863\u52A8\u4F5C\uFF1A\u5FBD\u6807 + \u6D6E\u52A8\u9762\u677F\u3002 */\n function ArchiveFooterAction(props: { wide?: boolean }): any {\n const wide = props.wide !== false\n // \u8BA2\u9605\u8FD0\u884C\u65F6 store\uFF1Aworkspaces\uFF08\u5F52\u6863\u96C6\u5408 / \u9879\u76EE\u89E3\u6790\uFF09\u3001sessions\uFF08\u6807\u9898\uFF09\u3002\n const workspaces = useSyncExternalStore(\n ctx.workspaces.list.subscribe as (listener: () => void) => () => void,\n () => ctx.workspaces.list.getSnapshot() as WorkspaceListSnapshot,\n )\n const sessions = useSyncExternalStore(\n ctx.sessions.list.subscribe as (listener: () => void) => () => void,\n () => ctx.sessions.list.getSnapshot() as SessionListSnapshot,\n )\n const [open, setOpen] = useState(false)\n const [busy, setBusy] = useState<{ id: string; action: 'restore' | 'delete' } | null>(null)\n const [batchBusy, setBatchBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const panelRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n // \u540C\u6B65\u5728\u9014\u5B88\u536B\uFF1AsetBusy \u8981\u7B49\u4E0B\u4E00\u6B21\u6E32\u67D3\u624D\u7981\u7528\u6309\u94AE\uFF0C\u540C\u4E00 tick \u91CC\u7684\u7B2C\u4E8C\u6B21\n // \u70B9\u51FB\u4F1A\u91CD\u65B0\u8FDB\u5165 run/deleteAll\uFF08React 18 \u6279\u5904\u7406\uFF09\u2014\u2014\u7528 ref \u5728\u8FDB\u5165\u65F6\n // \u7ACB\u5373\u62E6\u622A\uFF0C\u675C\u7EDD\u53CC\u51FB\u53CC\u53D1\uFF08\u6279\u91CF\u5220\u9664\u4F1A\u53CC\u8BA1\u6570\u3001\u4E0B\u8F7D\u4F1A\u53CC\u53D1 HEAD+GET\uFF09\u3002\n const busyRef = useRef(false)\n const batchBusyRef = useRef(false)\n /** \u5173\u95ED\u9762\u677F\u5E76\u6E05\u7A7A\u9519\u8BEF\u6A2A\u5E45\uFF1A\u9519\u8BEF\u63D0\u793A\u53EA\u5728\u5F53\u6B21\u6253\u5F00\u7684\u9762\u677F\u91CC\u505C\u7559\uFF0C\u91CD\u5F00\u5373\u5E72\u51C0\u3002 */\n const closePanel = (): void => {\n setError(null)\n setOpen(false)\n }\n\n // \u4E0D\u4F9D\u8D56\u6253\u5F00\u4F1A\u8BDD\u89E3\u6790\u5F53\u524D\u9879\u76EE\uFF1A\u6700\u8FD1\u6D3B\u8DC3 workspace \u2192 \u6301\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\n // workspace \u2192 \u5F53\u524D\u4F1A\u8BDD cwd \u5BF9\u5E94\u7684 workspace\u3002\n const workspace = useMemo((): WorkspaceRow | undefined => {\n const items = workspaces?.items\n if (items === undefined || items.length === 0) return undefined\n const recent = workspaces?.recentWorkspaceId\n if (recent !== undefined) {\n const byRecent = items.find(item => item.workspaceId === recent)\n if (byRecent !== undefined) return byRecent\n }\n const current = sessions?.current\n if (current !== undefined) {\n const byMembership = items.find(item => item.sessionIds.includes(current))\n if (byMembership !== undefined) return byMembership\n const currentCwd = sessions?.byId[current]?.cwd\n if (currentCwd !== undefined) {\n const byPath = items.find(item => item.path === currentCwd)\n if (byPath !== undefined) return byPath\n }\n }\n return undefined\n }, [workspaces, sessions])\n\n const projectLabel = workspace?.title\n\n // \u53EA\u53D6\u5F53\u524D\u9879\u76EE\u7684\u5F52\u6863\uFF1Aworkspace \u8D26\u76EE\u6210\u5458\uFF0C\u6216\u5B58\u50A8 cwd \u7B49\u4E8E\u9879\u76EE\u8DEF\u5F84\u3002\n const rows = useMemo((): ArchiveRow[] => {\n const archived = workspaces?.archivedSessionIds\n if (archived === undefined || archived.length === 0 || workspace === undefined) return []\n const result: ArchiveRow[] = []\n for (const id of archived) {\n const summary = sessions?.byId[id]\n const inAccount = workspace.sessionIds.includes(id)\n const sameProject = summary?.cwd !== undefined && summary.cwd === workspace.path\n if (!inAccount && !sameProject) continue\n result.push({\n id,\n title: summary?.displayTitle ?? id,\n updatedAt: summary?.updatedAt,\n })\n }\n return result\n }, [workspaces, sessions, workspace])\n\n // \u4F1A\u8BDD\u5217\u8868\u53D8\u5316\u65F6\u4FEE\u526A\u4E0B\u8F7D\u72B6\u6001\uFF1A\u5DF2\u4E0D\u5728\u5F53\u524D\u9879\u76EE\u91CC\u7684\u4F1A\u8BDD\uFF08\u88AB\u5220/\u79FB\u51FA\uFF09\u7684\n // \u6B8B\u7559 success/error \u6761\u76EE\u6E05\u6389\uFF0C\u907F\u514D\u72B6\u6001\u65E0\u9650\u5806\u79EF\u6216 id \u590D\u7528\u65F6\u8BEF\u663E\u793A\u3002\n useEffect(() => {\n pruneDownloads(new Set(rows.map(row => row.id)))\n }, [rows])\n\n // Escape \u5173\u95ED\uFF1B\u70B9\u51FB\u9762\u677F\u4E0E\u89E6\u53D1\u6309\u94AE\u4E4B\u5916\u7684\u533A\u57DF\u5173\u95ED\u3002\n // \uFF08\u89E6\u53D1\u6309\u94AE\u88AB\u6392\u9664\u5728\u5916\uFF0C\u8BA9\u70B9\u51FB\u4E8B\u4EF6\u81EA\u5DF1\u8D1F\u8D23\u5F00\u5173\u2014\u2014\u5426\u5219 mousedown \u5173\u95ED\u540E\n // \u7D27\u63A5\u7684 click \u5207\u6362\u4F1A\u7ACB\u523B\u91CD\u65B0\u6253\u5F00\u3002\uFF09\n useEffect(() => {\n if (!open) return\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n setError(null)\n setOpen(false)\n }\n }\n const onPointerDown = (event: MouseEvent): void => {\n const target = event.target as Node | null\n if (target === null) return\n if (panelRef.current?.contains(target) === true) return\n if (triggerRef.current?.contains(target) === true) return\n setError(null)\n setOpen(false)\n }\n document.addEventListener('keydown', onKey)\n document.addEventListener('mousedown', onPointerDown)\n return () => {\n document.removeEventListener('keydown', onKey)\n document.removeEventListener('mousedown', onPointerDown)\n }\n }, [open])\n\n // \u6BCF\u4E2A\u4F1A\u8BDD\u7684\u5B9E\u65F6\u5BFC\u51FA\u72B6\u6001\uFF08\u79C1\u6709 store\uFF09\uFF0C\u884C\u6309\u94AE\u636E\u6B64\u663E\u793A\u300C\u4E0B\u8F7D\u4E2D\u2026\u300D\u5E76\u7981\u7528\uFF0C\n // \u51FA\u9519\u65F6\u53D8\u6210\u300C\u91CD\u8BD5\u300D\u3002\n const downloads = useSyncExternalStore(\n (listener: () => void) => subscribeDownloads(listener),\n () => getDownloadsSnapshot(),\n )\n\n /** \u6267\u884C\u6062\u590D / \u5220\u9664\uFF1B\u5931\u8D25\u628A\u53EF\u8BFB\u9519\u8BEF\u5199\u5165\u9762\u677F\u3002 */\n const run = async (action: 'restore' | 'delete', id: string): Promise<void> => {\n if (busyRef.current) return\n busyRef.current = true\n setError(null)\n setBusy({ id, action })\n try {\n await callHost(action, { sessionId: id })\n // \u5220\u9664\u540E\u4E3B\u52A8\u5237\u65B0\uFF1Asessions \u5217\u8868\uFF08\u4F1A\u8BDD\u6D88\u5931\uFF09+ workspaces \u5217\u8868\n // \uFF08workspace \u8D26\u76EE\u5DF2\u89E3\u9664\uFF0C\u907F\u514D\u4FA7\u8FB9\u680F\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\uFF09\u3002\n // \u6062\u590D\u4E5F\u5237\u65B0 workspaces\uFF1A\u867D\u7136\u5BBF\u4E3B\u5199\u94FE\u4F1A\u5E7F\u64AD archived-sessions-changed\n // \u9A71\u52A8\u5B9E\u65F6\u5237\u65B0\uFF0C\u4F46\u90A3\u4F9D\u8D56 harness \u5185\u90E8\u4E8B\u4EF6\uFF0C\u8FD9\u91CC\u4E3B\u52A8\u5237\u65B0\u515C\u5E95\u3002\n ctx.sessions.refresh?.().catch?.(() => {})\n ctx.workspaces.refresh?.().catch?.(() => {})\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n busyRef.current = false\n setBusy(null)\n }\n }\n\n /** \u6062\u590D\u5355\u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u56DE\u5230\u4FA7\u8FB9\u680F\u539F\u4F4D\u7F6E\uFF09\u3002 */\n const restore = (id: string): void => { void run('restore', id) }\n /** \u786C\u5220\u9664\u5355\u4E2A\u5F52\u6863\u4F1A\u8BDD\uFF08\u542B\u4E8C\u6B21\u786E\u8BA4\uFF0C\u786E\u8BA4\u6587\u6848\u8BF4\u660E\u4E0D\u53EF\u6062\u590D\uFF09\u3002 */\n const remove = (id: string, title: string): void => {\n const confirmed = window.confirm(\n `\u786E\u5B9A\u8981\u6C38\u4E45\u5220\u9664\u4F1A\u8BDD\u300C${title}\u300D\u5417\uFF1F\\n\\n\u8FD9\u662F\u786C\u5220\u9664\uFF1A\u4F1A\u8BDD\u7684\u6240\u6709\u6587\u4EF6\u90FD\u4F1A\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u6062\u590D\u3002`,\n )\n if (confirmed) void run('delete', id)\n }\n /**\n * \u4E00\u952E\u5220\u9664\uFF1A\u628A\u5F53\u524D\u9879\u76EE\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\u4E00\u6B21\u6027\u786C\u5220\u9664\u3002\n * \u5BBF\u4E3B\u5355\u6B21\u4E0A\u9650 500 \u4E2A id\uFF08\u8D85\u9650\u6574\u6279 400\uFF09\uFF0C\u8FD9\u91CC\u6309 200/\u6279\u5206\u7247\u4E32\u884C\uFF0C\n * \u4FDD\u8BC1\u5F52\u6863\u6570 >500 \u7684\u9879\u76EE\u4E5F\u80FD\u6574\u6279\u5220\u5B8C\u800C\u975E\u6574\u6279\u5931\u8D25\u3002\n */\n const deleteAll = (): void => {\n if (rows.length === 0) return\n const confirmed = window.confirm(\n `\u786E\u5B9A\u8981\u4E00\u952E\u5220\u9664\u5168\u90E8 ${rows.length} \u4E2A\u5DF2\u5F52\u6863\u4F1A\u8BDD\u5417\uFF1F\\n\\n\u8FD9\u662F\u786C\u5220\u9664\uFF1A\u6BCF\u4E2A\u4F1A\u8BDD\u7684\u6240\u6709\u6587\u4EF6\u90FD\u4F1A\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u6062\u590D\u3002\\n\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u4F1A\u88AB\u8DF3\u8FC7\u3002`,\n )\n if (!confirmed) return\n if (batchBusyRef.current) return\n batchBusyRef.current = true\n setError(null)\n setBatchBusy(true)\n void (async () => {\n try {\n const ids = rows.map(row => row.id)\n const total = ids.length\n let deleted = 0\n let skipped = 0\n let failed = 0\n const failures: Array<{ sessionId: string; error: string }> = []\n for (let offset = 0; offset < ids.length; offset += DELETE_BATCH_SIZE) {\n const payload = await callHost('delete-all', { sessionIds: ids.slice(offset, offset + DELETE_BATCH_SIZE) }) as {\n total?: number\n deleted?: number\n skipped?: number\n failed?: number\n failures?: Array<{ sessionId: string; error: string }>\n }\n deleted += payload.deleted ?? 0\n skipped += payload.skipped ?? 0\n failed += payload.failed ?? 0\n const chunkFailures = payload.failures\n if (chunkFailures !== undefined && chunkFailures.length > 0) failures.push(...chunkFailures)\n }\n // \u6210\u529F\u540E\u4E0D\u518D\u663E\u793A\u6C47\u603B\u63D0\u793A\uFF08\"\u5220\u9664\u5373\u5220\u9664\"\uFF0C\u9762\u677F\u4FDD\u6301\u5E72\u51C0\uFF09\uFF1B\u4EC5\u5F53\u6709\u4F1A\u8BDD\n // \u5220\u9664\u5931\u8D25\u65F6\u628A\u5931\u8D25\u660E\u7EC6\u653E\u8FDB\u9519\u8BEF\u6A2A\u5E45\uFF0C\u907F\u514D\u9759\u9ED8\u5931\u8D25\u3002\u8DF3\u8FC7\u8FD0\u884C\u4E2D\u5C5E\u4E8E\n // \u786E\u8BA4\u6846\u91CC\u5DF2\u9884\u544A\u7684\u6B63\u5E38\u7ED3\u679C\uFF0C\u4E0D\u63D0\u793A\u3002\n if (failed > 0) {\n const parts: string[] = [`\u5DF2\u5220\u9664 ${deleted} \u4E2A`, `\u5931\u8D25 ${failed} \u4E2A`]\n if (skipped > 0) parts.push(`\u8DF3\u8FC7\u8FD0\u884C\u4E2D ${skipped} \u4E2A`)\n let message = parts.join('\uFF0C')\n if (failures.length > 0) {\n message += `\uFF1A${failures.map(item => `${item.sessionId}\uFF08${item.error}\uFF09`).join('\uFF1B')}`\n }\n setError(message)\n }\n // \u5220\u9664\u540E\u4E3B\u52A8\u5237\u65B0\uFF1Asessions \u5217\u8868\uFF08\u4F1A\u8BDD\u6D88\u5931\uFF09+ workspaces \u5217\u8868\n // \uFF08workspace \u8D26\u76EE\u5DF2\u89E3\u9664\uFF0C\u907F\u514D\u4FA7\u8FB9\u680F\u6B8B\u7559\u5E7D\u7075\u6761\u76EE\uFF09\u3002\n ctx.sessions.refresh?.().catch?.(() => {})\n ctx.workspaces.refresh?.().catch?.(() => {})\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n batchBusyRef.current = false\n setBatchBusy(false)\n }\n })()\n }\n /** \u6253\u5F00\u4F1A\u8BDD\uFF08\u4ECE\u9762\u677F\u5207\u5230\u4F1A\u8BDD\u533A\uFF09\uFF1B\u5931\u8D25\u901A\u5E38\u662F\u56E0\u4E3A\u5217\u8868\u5237\u65B0\u4E2D\u884C\u5DF2\u6D88\u5931\u3002 */\n const openSession = (id: string): void => {\n try {\n ctx.sessions.open(id)\n closePanel()\n } catch {\n // \u884C\u5728\u5217\u8868\u5237\u65B0\u65F6\u6D88\u5931\u7684\u7ADE\u6001\uFF1A\u4E0B\u4E00\u6B21\u6E32\u67D3\u81EA\u7136\u6E05\u6389\u3002\n }\n }\n\n return (\n <div style={wide ? styles.layer : { ...styles.layer, ...styles.layerRail }}>\n {open && (\n <section\n ref={panelRef}\n style={styles.panel}\n aria-label=\"\u5DF2\u5F52\u6863\u4F1A\u8BDD\"\n >\n <header style={styles.panelHeader}>\n <span style={styles.panelTitle}>\u5DF2\u5F52\u6863\u4F1A\u8BDD</span>\n {projectLabel !== undefined\n ? <span style={styles.panelProject}>\u00B7 {projectLabel}</span>\n : null}\n <button\n type=\"button\"\n className=\"dsh-archive-close\"\n style={styles.close}\n aria-label=\"\u5173\u95ED\"\n onClick={() => { closePanel() }}\n >\n \u2715\n </button>\n </header>\n <div style={styles.panelBody}>\n {error !== null ? <div style={styles.error}>{error}</div> : null}\n {rows.length === 0\n ? <div style={styles.empty}>\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u5F52\u6863\u7684\u4F1A\u8BDD</div>\n : null}\n {rows.map(row => {\n const rowBusy = busy !== null && busy.id === row.id\n const anyBusy = busy !== null || batchBusy\n const time = formatTime(row.updatedAt)\n const dlEntry = downloads?.bySession?.[row.id]\n const downloading = dlEntry?.status === 'downloading'\n const dlError = dlEntry?.status === 'error' ? (dlEntry.error ?? '\u5BFC\u51FA\u5931\u8D25') : null\n return (\n <div key={row.id} style={styles.row}>\n <div style={styles.rowMain}>\n <div\n style={styles.rowTitle}\n title={`\u6253\u5F00\u4F1A\u8BDD ${row.title}`}\n onClick={() => { openSession(row.id) }}\n >\n {row.title}\n </div>\n {time !== '' ? <div style={styles.rowMeta}>{time}</div> : null}\n </div>\n <button\n type=\"button\"\n title={dlError ?? '\u4E0B\u8F7D\u4F1A\u8BDD\u65E5\u5FD7 (ZIP)'}\n disabled={anyBusy || downloading}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n opacity: anyBusy || downloading ? 0.5 : 1,\n }}\n onClick={() => { void downloadSessionLog(row.id) }}\n >\n {downloading ? '\u4E0B\u8F7D\u4E2D\u2026' : dlError !== null ? '\u91CD\u8BD5' : '\u4E0B\u8F7D'}\n </button>\n <button\n type=\"button\"\n disabled={anyBusy}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n opacity: anyBusy && !rowBusy ? 0.5 : 1,\n }}\n onClick={() => { restore(row.id) }}\n >\n {rowBusy && busy?.action === 'restore' ? '\u6062\u590D\u4E2D\u2026' : '\u6062\u590D'}\n </button>\n <button\n type=\"button\"\n disabled={anyBusy}\n style={{\n ...styles.buttonBase,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n opacity: anyBusy && !rowBusy ? 0.5 : 1,\n }}\n onClick={() => { remove(row.id, row.title) }}\n >\n {rowBusy && busy?.action === 'delete' ? '\u5220\u9664\u4E2D\u2026' : '\u5220\u9664'}\n </button>\n </div>\n )\n })}\n </div>\n <footer style={styles.panelFooter}>\n <button\n type=\"button\"\n className=\"dsh-archive-batch\"\n style={{\n ...styles.batchDelete,\n opacity: batchBusy || busy !== null || rows.length === 0 ? 0.5 : 1,\n }}\n disabled={batchBusy || busy !== null || rows.length === 0}\n onClick={() => { deleteAll() }}\n >\n {batchBusy ? '\u5220\u9664\u4E2D\u2026' : '\u4E00\u952E\u5220\u9664'}\n </button>\n </footer>\n </section>\n )}\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"dsh-archive-badge\"\n style={wide ? styles.badge : { ...styles.badge, ...styles.badgeRail }}\n data-active={open || undefined}\n aria-label={`\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08${String(rows.length)}\uFF09`}\n aria-expanded={open}\n title={wide ? undefined : `\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF08${String(rows.length)}\uFF09`}\n onClick={() => { if (open) closePanel(); else setOpen(true) }}\n >\n <ArchiveIcon size={wide ? 16 : 18} />\n {wide && (\n <>\n <span style={styles.badgeLabel}>\u5F52\u6863</span>\n <span style={styles.badgeCount}>{rows.length}</span>\n </>\n )}\n </button>\n </div>\n )\n }\n\n // \u6CE8\u518C\u5230\u4FA7\u8FB9\u680F footer \u52A8\u4F5C\u5217\u8868\uFF08id: archive-panel\uFF09\u3002\n ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register(\n {\n name: 'sidebar.footer.action',\n id: 'archive-panel',\n },\n ArchiveFooterAction,\n ))\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCA,mBAA2E;AAwEvE;AAtEG,IAAM,SAAS,CAAC,SAAS,YAAY,YAAY;AAGxD,IAAM,oBAAoB;AAoC1B,eAAe,SAAS,UAA+C,MAAiE;AACtI,QAAM,WAAW,MAAM,MAAM,gBAAgB,QAAQ,IAAI;AAAA,IACvD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,SAAS,KAAK;AAAA,EAChC,QAAQ;AACN,cAAU;AAAA,EACZ;AACA,MAAI,CAAC,SAAS,MAAM,YAAY,UAAa,QAAQ,OAAO,MAAM;AAChE,UAAM,IAAI,MAAM,SAAS,SAAS,sCAAa,OAAO,SAAS,MAAM,CAAC,QAAG;AAAA,EAC3E;AACA,SAAO;AACT;AAGA,SAAS,WAAW,OAAmC;AACrD,MAAI,UAAU,UAAa,OAAO,MAAM,KAAK,EAAG,QAAO;AACvD,MAAI;AACF,WAAO,IAAI,KAAK,KAAK,EAAE,eAAe;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,YAAY,EAAE,KAAK,GAAqB;AAC/C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAW;AAAA,MAEX;AAAA,oDAAC,UAAK,GAAE,OAAM,GAAE,KAAI,OAAM,MAAK,QAAO,OAAM,IAAG,KAAI;AAAA,QACnD,4CAAC,UAAK,GAAE,+DAA8D;AAAA,QACtE,4CAAC,UAAK,GAAE,YAAW;AAAA;AAAA;AAAA,EACrB;AAEJ;AAQA,IAAM,iBAAgD,CAAC;AACvD,IAAM,oBAAoB,oBAAI,IAAgB;AAE9C,IAAM,mBAAmB,oBAAI,IAAY;AAQzC,IAAI,oBAAkE,EAAE,WAAW,CAAC,EAAE;AAEtF,SAAS,mBAAmB,UAAkC;AAC5D,oBAAkB,IAAI,QAAQ;AAC9B,SAAO,MAAM;AAAE,sBAAkB,OAAO,QAAQ;AAAA,EAAE;AACpD;AAEA,SAAS,gBAAsB;AAC7B,sBAAoB,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE;AACvD,aAAW,YAAY,kBAAmB,UAAS;AACrD;AAEA,SAAS,uBAAqE;AAC5E,SAAO;AACT;AAGA,SAAS,WAAmB;AAC1B,QAAM,SAAU,WAAkD,UAAU;AAC5E,SAAO,WAAW,UAAa,WAAW,SAAS,SAAS;AAC9D;AAGA,SAAS,sBAAsB,WAA2B;AACxD,SAAO,eAAe,OAAO,SAAS,EAAE,QAAQ,mBAAmB,GAAG,CAAC;AACzE;AAGA,SAAS,UAAU,WAA2B;AAC5C,QAAM,MAAM,IAAI,IAAI,uBAAuB,SAAS,CAAC;AACrD,MAAI,aAAa,IAAI,aAAa,SAAS;AAC3C,MAAI,aAAa,IAAI,sBAAsB,MAAM;AACjD,SAAO,IAAI,SAAS;AACtB;AAaA,eAAe,mBAAmB,WAAkC;AAClE,MAAI,iBAAiB,IAAI,SAAS,EAAG;AACrC,mBAAiB,IAAI,SAAS;AAC9B,iBAAe,SAAS,IAAI,EAAE,QAAQ,cAAc;AACpD,gBAAc;AACd,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,UAAU,SAAS,GAAG,EAAE,QAAQ,OAAO,CAAC;AACrE,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,sCAAa,SAAS,MAAM,EAAE;AAChE,UAAM,SAAS,SAAS,cAAc,GAAG;AACzC,WAAO,OAAO,UAAU,SAAS;AACjC,WAAO,WAAW,sBAAsB,SAAS;AACjD,WAAO,MAAM;AACb,mBAAe,SAAS,IAAI,EAAE,QAAQ,UAAU;AAAA,EAClD,SAAS,OAAgB;AACvB,mBAAe,SAAS,IAAI;AAAA,MAC1B,QAAQ;AAAA,MACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA,EACF,UAAE;AACA,qBAAiB,OAAO,SAAS;AAAA,EACnC;AACA,gBAAc;AAChB;AAOA,SAAS,eAAe,WAAsC;AAC5D,MAAI,UAAU;AACd,aAAW,MAAM,OAAO,KAAK,cAAc,GAAG;AAC5C,QAAI,CAAC,UAAU,IAAI,EAAE,GAAG;AACtB,aAAO,eAAe,EAAE;AACxB,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI,QAAS,eAAc;AAC7B;AAEO,SAAS,MAAM,KAAgB;AAGpC,QAAM,WAAW;AACjB,MAAI,OAAO,aAAa,eAAe,SAAS,eAAe,QAAQ,MAAM,MAAM;AACjF,UAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,YAAQ,KAAK;AACb,YAAQ,aAAa,eAAe,aAAa;AACjD,YAAQ,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAetB,aAAS,KAAK,YAAY,OAAO;AAAA,EACnC;AAEA,QAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAKb,OAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,MACL,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,IACd;AAAA,IACA,WAAW;AAAA,MACT,gBAAgB;AAAA,MAChB,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,cAAc;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,IACd;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,oBAAoB;AAAA,IACtB;AAAA,IACA,OAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,eAAe;AAAA,MACf,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,WAAW;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA,MACX,cAAc;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IACA,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,KAAK;AAAA,MACL,WAAW;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,IACA,OAAO;AAAA,MACL,SAAS;AAAA,MACT,cAAc;AAAA,MACd,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,IACA,KAAK;AAAA,MACH,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,SAAS;AAAA,MACT,cAAc;AAAA,MACd,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,IACA,OAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,EACF;AAGA,WAAS,oBAAoB,OAAgC;AAC3D,UAAM,OAAO,MAAM,SAAS;AAE5B,UAAM,iBAAa;AAAA,MACjB,IAAI,WAAW,KAAK;AAAA,MACpB,MAAM,IAAI,WAAW,KAAK,YAAY;AAAA,IACxC;AACA,UAAM,eAAW;AAAA,MACf,IAAI,SAAS,KAAK;AAAA,MAClB,MAAM,IAAI,SAAS,KAAK,YAAY;AAAA,IACtC;AACA,UAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,KAAK;AACtC,UAAM,CAAC,MAAM,OAAO,QAAI,uBAA8D,IAAI;AAC1F,UAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,KAAK;AAChD,UAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB,IAAI;AACtD,UAAM,eAAW,qBAA8B,IAAI;AACnD,UAAM,iBAAa,qBAAiC,IAAI;AAIxD,UAAM,cAAU,qBAAO,KAAK;AAC5B,UAAM,mBAAe,qBAAO,KAAK;AAEjC,UAAM,aAAa,MAAY;AAC7B,eAAS,IAAI;AACb,cAAQ,KAAK;AAAA,IACf;AAIA,UAAM,gBAAY,sBAAQ,MAAgC;AACxD,YAAM,QAAQ,YAAY;AAC1B,UAAI,UAAU,UAAa,MAAM,WAAW,EAAG,QAAO;AACtD,YAAM,SAAS,YAAY;AAC3B,UAAI,WAAW,QAAW;AACxB,cAAM,WAAW,MAAM,KAAK,UAAQ,KAAK,gBAAgB,MAAM;AAC/D,YAAI,aAAa,OAAW,QAAO;AAAA,MACrC;AACA,YAAM,UAAU,UAAU;AAC1B,UAAI,YAAY,QAAW;AACzB,cAAM,eAAe,MAAM,KAAK,UAAQ,KAAK,WAAW,SAAS,OAAO,CAAC;AACzE,YAAI,iBAAiB,OAAW,QAAO;AACvC,cAAM,aAAa,UAAU,KAAK,OAAO,GAAG;AAC5C,YAAI,eAAe,QAAW;AAC5B,gBAAM,SAAS,MAAM,KAAK,UAAQ,KAAK,SAAS,UAAU;AAC1D,cAAI,WAAW,OAAW,QAAO;AAAA,QACnC;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAG,CAAC,YAAY,QAAQ,CAAC;AAEzB,UAAM,eAAe,WAAW;AAGhC,UAAM,WAAO,sBAAQ,MAAoB;AACvC,YAAM,WAAW,YAAY;AAC7B,UAAI,aAAa,UAAa,SAAS,WAAW,KAAK,cAAc,OAAW,QAAO,CAAC;AACxF,YAAM,SAAuB,CAAC;AAC9B,iBAAW,MAAM,UAAU;AACzB,cAAM,UAAU,UAAU,KAAK,EAAE;AACjC,cAAM,YAAY,UAAU,WAAW,SAAS,EAAE;AAClD,cAAM,cAAc,SAAS,QAAQ,UAAa,QAAQ,QAAQ,UAAU;AAC5E,YAAI,CAAC,aAAa,CAAC,YAAa;AAChC,eAAO,KAAK;AAAA,UACV;AAAA,UACA,OAAO,SAAS,gBAAgB;AAAA,UAChC,WAAW,SAAS;AAAA,QACtB,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,GAAG,CAAC,YAAY,UAAU,SAAS,CAAC;AAIpC,gCAAU,MAAM;AACd,qBAAe,IAAI,IAAI,KAAK,IAAI,SAAO,IAAI,EAAE,CAAC,CAAC;AAAA,IACjD,GAAG,CAAC,IAAI,CAAC;AAKT,gCAAU,MAAM;AACd,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,CAAC,UAA+B;AAC5C,YAAI,MAAM,QAAQ,UAAU;AAC1B,mBAAS,IAAI;AACb,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF;AACA,YAAM,gBAAgB,CAAC,UAA4B;AACjD,cAAM,SAAS,MAAM;AACrB,YAAI,WAAW,KAAM;AACrB,YAAI,SAAS,SAAS,SAAS,MAAM,MAAM,KAAM;AACjD,YAAI,WAAW,SAAS,SAAS,MAAM,MAAM,KAAM;AACnD,iBAAS,IAAI;AACb,gBAAQ,KAAK;AAAA,MACf;AACA,eAAS,iBAAiB,WAAW,KAAK;AAC1C,eAAS,iBAAiB,aAAa,aAAa;AACpD,aAAO,MAAM;AACX,iBAAS,oBAAoB,WAAW,KAAK;AAC7C,iBAAS,oBAAoB,aAAa,aAAa;AAAA,MACzD;AAAA,IACF,GAAG,CAAC,IAAI,CAAC;AAIT,UAAM,gBAAY;AAAA,MAChB,CAAC,aAAyB,mBAAmB,QAAQ;AAAA,MACrD,MAAM,qBAAqB;AAAA,IAC7B;AAGA,UAAM,MAAM,OAAO,QAA8B,OAA8B;AAC7E,UAAI,QAAQ,QAAS;AACrB,cAAQ,UAAU;AAClB,eAAS,IAAI;AACb,cAAQ,EAAE,IAAI,OAAO,CAAC;AACtB,UAAI;AACF,cAAM,SAAS,QAAQ,EAAE,WAAW,GAAG,CAAC;AAKxC,YAAI,SAAS,UAAU,EAAE,QAAQ,MAAM;AAAA,QAAC,CAAC;AACzC,YAAI,WAAW,UAAU,EAAE,QAAQ,MAAM;AAAA,QAAC,CAAC;AAAA,MAC7C,SAAS,KAAK;AACZ,iBAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3D,UAAE;AACA,gBAAQ,UAAU;AAClB,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF;AAGA,UAAM,UAAU,CAAC,OAAqB;AAAE,WAAK,IAAI,WAAW,EAAE;AAAA,IAAE;AAEhE,UAAM,SAAS,CAAC,IAAY,UAAwB;AAClD,YAAM,YAAY,OAAO;AAAA,QACvB,+DAAa,KAAK;AAAA;AAAA;AAAA,MACpB;AACA,UAAI,UAAW,MAAK,IAAI,UAAU,EAAE;AAAA,IACtC;AAMA,UAAM,YAAY,MAAY;AAC5B,UAAI,KAAK,WAAW,EAAG;AACvB,YAAM,YAAY,OAAO;AAAA,QACvB,0DAAa,KAAK,MAAM;AAAA;AAAA;AAAA;AAAA,MAC1B;AACA,UAAI,CAAC,UAAW;AAChB,UAAI,aAAa,QAAS;AAC1B,mBAAa,UAAU;AACvB,eAAS,IAAI;AACb,mBAAa,IAAI;AACjB,YAAM,YAAY;AAChB,YAAI;AACF,gBAAM,MAAM,KAAK,IAAI,SAAO,IAAI,EAAE;AAClC,gBAAM,QAAQ,IAAI;AAClB,cAAI,UAAU;AACd,cAAI,UAAU;AACd,cAAI,SAAS;AACb,gBAAM,WAAwD,CAAC;AAC/D,mBAAS,SAAS,GAAG,SAAS,IAAI,QAAQ,UAAU,mBAAmB;AACrE,kBAAM,UAAU,MAAM,SAAS,cAAc,EAAE,YAAY,IAAI,MAAM,QAAQ,SAAS,iBAAiB,EAAE,CAAC;AAO1G,uBAAW,QAAQ,WAAW;AAC9B,uBAAW,QAAQ,WAAW;AAC9B,sBAAU,QAAQ,UAAU;AAC5B,kBAAM,gBAAgB,QAAQ;AAC9B,gBAAI,kBAAkB,UAAa,cAAc,SAAS,EAAG,UAAS,KAAK,GAAG,aAAa;AAAA,UAC7F;AAIA,cAAI,SAAS,GAAG;AACd,kBAAM,QAAkB,CAAC,sBAAO,OAAO,WAAM,gBAAM,MAAM,SAAI;AAC7D,gBAAI,UAAU,EAAG,OAAM,KAAK,kCAAS,OAAO,SAAI;AAChD,gBAAI,UAAU,MAAM,KAAK,QAAG;AAC5B,gBAAI,SAAS,SAAS,GAAG;AACvB,yBAAW,SAAI,SAAS,IAAI,UAAQ,GAAG,KAAK,SAAS,SAAI,KAAK,KAAK,QAAG,EAAE,KAAK,QAAG,CAAC;AAAA,YACnF;AACA,qBAAS,OAAO;AAAA,UAClB;AAGA,cAAI,SAAS,UAAU,EAAE,QAAQ,MAAM;AAAA,UAAC,CAAC;AACzC,cAAI,WAAW,UAAU,EAAE,QAAQ,MAAM;AAAA,UAAC,CAAC;AAAA,QAC7C,SAAS,KAAK;AACZ,mBAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAC3D,UAAE;AACA,uBAAa,UAAU;AACvB,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF,GAAG;AAAA,IACL;AAEA,UAAM,cAAc,CAAC,OAAqB;AACxC,UAAI;AACF,YAAI,SAAS,KAAK,EAAE;AACpB,mBAAW;AAAA,MACb,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WACE,6CAAC,SAAI,OAAO,OAAO,OAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,GAAG,OAAO,UAAU,GACtE;AAAA,cACC;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,OAAO,OAAO;AAAA,UACd,cAAW;AAAA,UAEX;AAAA,yDAAC,YAAO,OAAO,OAAO,aACpB;AAAA,0DAAC,UAAK,OAAO,OAAO,YAAY,4CAAK;AAAA,cACpC,iBAAiB,SACd,6CAAC,UAAK,OAAO,OAAO,cAAc;AAAA;AAAA,gBAAG;AAAA,iBAAa,IAClD;AAAA,cACJ;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,OAAO,OAAO;AAAA,kBACd,cAAW;AAAA,kBACX,SAAS,MAAM;AAAE,+BAAW;AAAA,kBAAE;AAAA,kBAC/B;AAAA;AAAA,cAED;AAAA,eACF;AAAA,YACA,6CAAC,SAAI,OAAO,OAAO,WAChB;AAAA,wBAAU,OAAO,4CAAC,SAAI,OAAO,OAAO,OAAQ,iBAAM,IAAS;AAAA,cAC3D,KAAK,WAAW,IACb,4CAAC,SAAI,OAAO,OAAO,OAAO,sFAAY,IACtC;AAAA,cACH,KAAK,IAAI,SAAO;AACf,sBAAM,UAAU,SAAS,QAAQ,KAAK,OAAO,IAAI;AACjD,sBAAM,UAAU,SAAS,QAAQ;AACjC,sBAAM,OAAO,WAAW,IAAI,SAAS;AACrC,sBAAM,UAAU,WAAW,YAAY,IAAI,EAAE;AAC7C,sBAAM,cAAc,SAAS,WAAW;AACxC,sBAAM,UAAU,SAAS,WAAW,UAAW,QAAQ,SAAS,6BAAU;AAC1E,uBACE,6CAAC,SAAiB,OAAO,OAAO,KAC9B;AAAA,+DAAC,SAAI,OAAO,OAAO,SACjB;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO,OAAO;AAAA,wBACd,OAAO,4BAAQ,IAAI,KAAK;AAAA,wBACxB,SAAS,MAAM;AAAE,sCAAY,IAAI,EAAE;AAAA,wBAAE;AAAA,wBAEpC,cAAI;AAAA;AAAA,oBACP;AAAA,oBACC,SAAS,KAAK,4CAAC,SAAI,OAAO,OAAO,SAAU,gBAAK,IAAS;AAAA,qBAC5D;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,OAAO,WAAW;AAAA,sBAClB,UAAU,WAAW;AAAA,sBACrB,OAAO;AAAA,wBACL,GAAG,OAAO;AAAA,wBACV,QAAQ;AAAA,wBACR,OAAO;AAAA,wBACP,SAAS,WAAW,cAAc,MAAM;AAAA,sBAC1C;AAAA,sBACA,SAAS,MAAM;AAAE,6BAAK,mBAAmB,IAAI,EAAE;AAAA,sBAAE;AAAA,sBAEhD,wBAAc,6BAAS,YAAY,OAAO,iBAAO;AAAA;AAAA,kBACpD;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,UAAU;AAAA,sBACV,OAAO;AAAA,wBACL,GAAG,OAAO;AAAA,wBACV,QAAQ;AAAA,wBACR,OAAO;AAAA,wBACP,SAAS,WAAW,CAAC,UAAU,MAAM;AAAA,sBACvC;AAAA,sBACA,SAAS,MAAM;AAAE,gCAAQ,IAAI,EAAE;AAAA,sBAAE;AAAA,sBAEhC,qBAAW,MAAM,WAAW,YAAY,6BAAS;AAAA;AAAA,kBACpD;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,UAAU;AAAA,sBACV,OAAO;AAAA,wBACL,GAAG,OAAO;AAAA,wBACV,QAAQ;AAAA,wBACR,OAAO;AAAA,wBACP,SAAS,WAAW,CAAC,UAAU,MAAM;AAAA,sBACvC;AAAA,sBACA,SAAS,MAAM;AAAE,+BAAO,IAAI,IAAI,IAAI,KAAK;AAAA,sBAAE;AAAA,sBAE1C,qBAAW,MAAM,WAAW,WAAW,6BAAS;AAAA;AAAA,kBACnD;AAAA,qBAlDQ,IAAI,EAmDd;AAAA,cAEJ,CAAC;AAAA,eACH;AAAA,YACA,4CAAC,YAAO,OAAO,OAAO,aACpB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,GAAG,OAAO;AAAA,kBACV,SAAS,aAAa,SAAS,QAAQ,KAAK,WAAW,IAAI,MAAM;AAAA,gBACnE;AAAA,gBACA,UAAU,aAAa,SAAS,QAAQ,KAAK,WAAW;AAAA,gBACxD,SAAS,MAAM;AAAE,4BAAU;AAAA,gBAAE;AAAA,gBAE5B,sBAAY,6BAAS;AAAA;AAAA,YACxB,GACF;AAAA;AAAA;AAAA,MACF;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO,OAAO,OAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,GAAG,OAAO,UAAU;AAAA,UACpE,eAAa,QAAQ;AAAA,UACrB,cAAY,uCAAS,OAAO,KAAK,MAAM,CAAC;AAAA,UACxC,iBAAe;AAAA,UACf,OAAO,OAAO,SAAY,uCAAS,OAAO,KAAK,MAAM,CAAC;AAAA,UACtD,SAAS,MAAM;AAAE,gBAAI,KAAM,YAAW;AAAA,gBAAQ,SAAQ,IAAI;AAAA,UAAE;AAAA,UAE5D;AAAA,wDAAC,eAAY,MAAM,OAAO,KAAK,IAAI;AAAA,YAClC,QACC,4EACE;AAAA,0DAAC,UAAK,OAAO,OAAO,YAAY,0BAAE;AAAA,cAClC,4CAAC,UAAK,OAAO,OAAO,YAAa,eAAK,QAAO;AAAA,eAC/C;AAAA;AAAA;AAAA,MAEJ;AAAA,OACF;AAAA,EAEJ;AAGA,MAAI,MAAM,OAAO,yBAAyB,MAAM,IAAI,MAAM;AAAA,IACxD;AAAA,MACE,MAAM;AAAA,MACN,IAAI;AAAA,IACN;AAAA,IACA;AAAA,EACF,CAAC;AACH;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bit-ark/dsh-archive",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Adds a 归档 (Archive) tab after the Trajectory tab: lists the current project's archived sessions with restore (unarchive) and hard delete.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",