@chaoset/session-archive 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +1 -1
- package/client/client.cjs +215 -135
- package/client/index.tsx +501 -0
- package/lib/config-store.d.ts +32 -0
- package/lib/config-store.d.ts.map +1 -0
- package/lib/config-store.js +107 -0
- package/lib/config-store.js.map +1 -0
- package/lib/index.d.ts +130 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +334 -0
- package/lib/index.js.map +1 -0
- package/lib/remote.d.ts +36 -0
- package/lib/remote.d.ts.map +1 -0
- package/lib/remote.js +108 -0
- package/lib/remote.js.map +1 -0
- package/lib/typert.host.d.ts +62 -0
- package/lib/typert.host.d.ts.map +1 -0
- package/lib/typert.host.js +68 -68
- package/lib/typert.host.js.map +1 -0
- package/package.json +10 -9
- package/lib/config-store.mjs +0 -97
- package/lib/index.mjs +0 -314
- package/lib/remote.mjs +0 -110
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.3](https://github.com/winliyou/dsh-plugins) (2026-08-18)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* confirm-delete button hover: red text on red background was unreadable; changed to red background with white text
|
|
8
|
+
|
|
9
|
+
## [0.1.2](https://github.com/winliyou/dsh-plugins) (2026-08-18)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* keep ghost archived id after deleting archived sessions so in-memory sessions don't reappear in the sidebar
|
|
14
|
+
|
|
15
|
+
## [0.1.1](https://github.com/winliyou/dsh-plugins) (2026-08-17)
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* archived sessions no longer mislabeled as running; restored selectable deletion
|
|
20
|
+
|
|
21
|
+
## [0.1.0](https://github.com/winliyou/dsh-plugins) (2026-08-17)
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* initial session archive plugin: archived session list, read-only detail, batch restore and permanent delete
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-plugins contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -53,11 +53,11 @@ dsh plugin --profile web add @chaoset/session-archive
|
|
|
53
53
|
| `list()` | — | `{ items: ArchiveRow[] }` |
|
|
54
54
|
| `detail(sessionId)` | 会话 id | `{ sessionId, header, title, messageCount, messages, live }` |
|
|
55
55
|
| `delete(sessionIds[])` | id 数组 | `{ deleted, failed, removedFromArchive }` |
|
|
56
|
+
| `unarchive(sessionIds[])` | id 数组 | `{ restored, removedFromArchive }` |
|
|
56
57
|
|
|
57
58
|
> `delete` 的 `removedFromArchive` 恒为 0:删除保留归档 ghost id(见上),
|
|
58
59
|
> 侧边栏不会重新显示已删除的会话;`unarchive` 的 `removedFromArchive` 为
|
|
59
60
|
> 实际从归档集合移除的 id 数。
|
|
60
|
-
| `unarchive(sessionIds[])` | id 数组 | `{ restored, removedFromArchive }` |
|
|
61
61
|
|
|
62
62
|
`ArchiveRow`:`{ sessionId, title, cwd, createdAt, updatedAt, size, live }`。
|
|
63
63
|
|
package/client/client.cjs
CHANGED
|
@@ -3,15 +3,52 @@ window.__ModuleLoader__.load({
|
|
|
3
3
|
factory: (require) => {
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
|
-
|
|
6
|
+
"use strict";
|
|
7
|
+
var __create = Object.create;
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
12
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
33
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
7
34
|
|
|
8
|
-
//
|
|
35
|
+
// client/index.tsx
|
|
36
|
+
var index_exports = {};
|
|
37
|
+
__export(index_exports, {
|
|
38
|
+
apply: () => apply,
|
|
39
|
+
inject: () => inject
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
|
+
var React = __toESM(require("react"), 1);
|
|
9
43
|
var css = [
|
|
10
44
|
".sa_badge{width:100%;height:49px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:0 8px 0 6px;font-family:inherit;font-size:14px;display:inline-flex;overflow:hidden}",
|
|
11
45
|
".sa_badge:hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
12
|
-
".sa_badgeIcon{flex:none;
|
|
46
|
+
".sa_badgeIcon{flex:none;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--dsw-alias-label-primary)}",
|
|
47
|
+
".sa_badgeIcon svg{width:18px;height:18px;display:block}",
|
|
13
48
|
".sa_badgeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}",
|
|
14
49
|
".sa_badgeCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;font-size:12px;line-height:16px}",
|
|
50
|
+
".sa_badge--collapsed{width:auto;justify-content:center;padding:0}",
|
|
51
|
+
".sa_badge--collapsed .sa_badgeLabel,.sa_badge--collapsed .sa_badgeCount{display:none}",
|
|
15
52
|
".sa_panel{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:440px;max-width:calc(100vw - 24px);max-height:62vh;box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;flex-direction:column;display:flex;position:fixed;bottom:128px;left:12px;overflow:hidden}",
|
|
16
53
|
".sa_header{box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:8px 12px;display:flex}",
|
|
17
54
|
".sa_title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}",
|
|
@@ -33,6 +70,7 @@ window.__ModuleLoader__.load({
|
|
|
33
70
|
".sa_actionDanger:hover:not(:disabled){background:var(--dsw-alias-state-error-primary)}",
|
|
34
71
|
".sa_actionDanger:disabled{opacity:.4}",
|
|
35
72
|
".sa_confirm{color:var(--dsw-alias-state-error-primary);border:1px solid var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}",
|
|
73
|
+
".sa_confirm:hover:not(:disabled){background:var(--dsw-alias-state-error-primary);color:#fff}",
|
|
36
74
|
".sa_body{flex:1;min-height:0;padding:4px 12px 12px;overflow-y:auto}",
|
|
37
75
|
".sa_empty{color:var(--dsw-alias-label-tertiary);margin:24px 0;text-align:center;font-size:12px;line-height:18px}",
|
|
38
76
|
".sa_error{color:var(--dsw-alias-state-error-primary);margin:8px 0;font-size:12px;line-height:18px}",
|
|
@@ -54,49 +92,48 @@ window.__ModuleLoader__.load({
|
|
|
54
92
|
".sa_busy{opacity:.55;pointer-events:none}"
|
|
55
93
|
].join("");
|
|
56
94
|
var tagId = "@chaoset/session-archive/client.css";
|
|
57
|
-
if (typeof document !== "undefined" && document.querySelector(
|
|
58
|
-
|
|
95
|
+
if (typeof document !== "undefined" && document.querySelector('style[data-plugin-css="' + tagId + '"]') === null) {
|
|
96
|
+
tag = document.createElement("style");
|
|
59
97
|
tag.dataset.plugin = "@chaoset/session-archive";
|
|
60
98
|
tag.dataset.pluginCss = tagId;
|
|
61
99
|
tag.textContent = css;
|
|
62
100
|
document.head.appendChild(tag);
|
|
63
101
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
noMessages: "(无文本消息)",
|
|
102
|
+
var tag;
|
|
103
|
+
var NS = "sidebar.sessionArchive";
|
|
104
|
+
var zh = {
|
|
105
|
+
badge: "\u5F52\u6863",
|
|
106
|
+
panelTitle: "\u5F52\u6863\u4F1A\u8BDD",
|
|
107
|
+
refresh: "\u5237\u65B0",
|
|
108
|
+
close: "\u5173\u95ED",
|
|
109
|
+
empty: "\u6682\u65E0\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u4F1A\u8BDD\u5217\u8868\u7684\u66F4\u591A\u83DC\u5355\u4E2D\u5F52\u6863\u4F1A\u8BDD\u540E\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002",
|
|
110
|
+
loadFailed: "\u52A0\u8F7D\u5F52\u6863\u5217\u8868\u5931\u8D25",
|
|
111
|
+
selectAll: "\u5168\u9009",
|
|
112
|
+
selected: "\u5DF2\u9009 {n} \u9879",
|
|
113
|
+
restore: "\u6062\u590D\u6240\u9009",
|
|
114
|
+
restoreDone: "\u5DF2\u6062\u590D {n} \u4E2A\u5F52\u6863\u4F1A\u8BDD",
|
|
115
|
+
restoreFailed: "\u6062\u590D\u5931\u8D25",
|
|
116
|
+
delete: "\u5220\u9664\u6240\u9009",
|
|
117
|
+
deleteConfirm: "\u518D\u6B21\u70B9\u51FB\u786E\u8BA4\u5220\u9664",
|
|
118
|
+
deleteDone: "\u5DF2\u5220\u9664 {n} \u4E2A\u5F52\u6863\u4F1A\u8BDD",
|
|
119
|
+
deleteFailed: "\u90E8\u5206\u5220\u9664\u5931\u8D25\uFF1A{n} \u4E2A",
|
|
120
|
+
confirmAll: "\u786E\u8BA4\u5220\u9664\u5168\u90E8 {n} \u4E2A\uFF1F",
|
|
121
|
+
noSelection: "\u8BF7\u5148\u52FE\u9009\u4F1A\u8BDD",
|
|
122
|
+
view: "\u67E5\u770B",
|
|
123
|
+
collapse: "\u6536\u8D77",
|
|
124
|
+
live: "\u8FD0\u884C\u4E2D",
|
|
125
|
+
detailLoadFailed: "\u8BFB\u53D6\u4F1A\u8BDD\u5185\u5BB9\u5931\u8D25",
|
|
126
|
+
noneTitle: "\uFF08\u65E0\u6807\u9898\uFF09",
|
|
127
|
+
user: "\u7528\u6237",
|
|
128
|
+
assistant: "\u52A9\u624B",
|
|
129
|
+
messages: "\u5171 {n} \u6761\u6D88\u606F",
|
|
130
|
+
noMessages: "\uFF08\u65E0\u6587\u672C\u6D88\u606F\uFF09",
|
|
94
131
|
sizeBytes: "{n} B",
|
|
95
132
|
sizeKB: "{n} KB",
|
|
96
133
|
sizeMB: "{n} MB",
|
|
97
|
-
runningHint: "
|
|
134
|
+
runningHint: "\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u4E0D\u80FD\u5220\u9664\uFF0C\u8BF7\u5148\u505C\u6B62"
|
|
98
135
|
};
|
|
99
|
-
|
|
136
|
+
var en = {
|
|
100
137
|
badge: "Archive",
|
|
101
138
|
panelTitle: "Archived sessions",
|
|
102
139
|
refresh: "Refresh",
|
|
@@ -106,11 +143,11 @@ window.__ModuleLoader__.load({
|
|
|
106
143
|
selectAll: "Select all",
|
|
107
144
|
selected: "{n} selected",
|
|
108
145
|
restore: "Restore",
|
|
109
|
-
restoreDone: "Restored {n} sessions",
|
|
146
|
+
restoreDone: "Restored {n} archived sessions",
|
|
110
147
|
restoreFailed: "Restore failed",
|
|
111
148
|
delete: "Delete",
|
|
112
149
|
deleteConfirm: "Click again to confirm delete",
|
|
113
|
-
deleteDone: "Deleted {n} sessions",
|
|
150
|
+
deleteDone: "Deleted {n} archived sessions",
|
|
114
151
|
deleteFailed: "Some deletions failed: {n}",
|
|
115
152
|
confirmAll: "Delete all {n}?",
|
|
116
153
|
noSelection: "Select sessions first",
|
|
@@ -128,38 +165,54 @@ window.__ModuleLoader__.load({
|
|
|
128
165
|
sizeMB: "{n} MB",
|
|
129
166
|
runningHint: "Running sessions cannot be deleted; stop them first"
|
|
130
167
|
};
|
|
131
|
-
|
|
132
|
-
// ── 工具函数 ─────────────────────────────────────────────────────────
|
|
133
168
|
function formatBytes(bytes, t) {
|
|
134
169
|
if (bytes < 1024) return t("sizeBytes").replace("{n}", String(bytes));
|
|
135
170
|
if (bytes < 1024 * 1024) return t("sizeKB").replace("{n}", (bytes / 1024).toFixed(1));
|
|
136
171
|
return t("sizeMB").replace("{n}", (bytes / (1024 * 1024)).toFixed(1));
|
|
137
172
|
}
|
|
138
173
|
function formatTime(ms) {
|
|
139
|
-
try {
|
|
174
|
+
try {
|
|
175
|
+
return new Date(ms).toLocaleString();
|
|
176
|
+
} catch {
|
|
177
|
+
return String(ms);
|
|
178
|
+
}
|
|
140
179
|
}
|
|
141
180
|
function shortId(id) {
|
|
142
|
-
return id.length > 12 ? id.slice(0, 12) + "
|
|
181
|
+
return id.length > 12 ? id.slice(0, 12) + "\u2026" : id;
|
|
143
182
|
}
|
|
144
|
-
|
|
145
|
-
// ── 归档面板 ─────────────────────────────────────────────────────────
|
|
146
183
|
function ArchivePanel(props) {
|
|
147
184
|
const t = props.t;
|
|
148
185
|
const call = props.call;
|
|
149
|
-
const
|
|
150
|
-
const [
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
186
|
+
const wideExplicit = typeof props.wide === "boolean" ? props.wide : void 0;
|
|
187
|
+
const [narrow, setNarrow] = React.useState(false);
|
|
188
|
+
const collapsed = wideExplicit === void 0 ? narrow : !wideExplicit;
|
|
189
|
+
const badgeRef = React.useRef(null);
|
|
190
|
+
React.useEffect(() => {
|
|
191
|
+
const el = badgeRef.current?.parentElement;
|
|
192
|
+
if (el === void 0 || el === null || typeof globalThis.ResizeObserver === "undefined") return;
|
|
193
|
+
const ro = new globalThis.ResizeObserver((entries) => {
|
|
194
|
+
for (const entry of entries) {
|
|
195
|
+
const w = entry.contentRect?.width ?? el.clientWidth;
|
|
196
|
+
setNarrow(w > 0 && w < 80);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
ro.observe(el);
|
|
200
|
+
return () => ro.disconnect();
|
|
201
|
+
}, []);
|
|
202
|
+
const iconOnly = collapsed;
|
|
203
|
+
const rootRef = React.useRef(null);
|
|
204
|
+
const [open, setOpen] = React.useState(false);
|
|
205
|
+
const [items, setItems] = React.useState([]);
|
|
206
|
+
const [loading, setLoading] = React.useState(false);
|
|
207
|
+
const [error, setError] = React.useState(null);
|
|
208
|
+
const [selected, setSelected] = React.useState(/* @__PURE__ */ new Set());
|
|
209
|
+
const [expanded, setExpanded] = React.useState(null);
|
|
210
|
+
const [details, setDetails] = React.useState(/* @__PURE__ */ new Map());
|
|
211
|
+
const [detailLoading, setDetailLoading] = React.useState(/* @__PURE__ */ new Set());
|
|
212
|
+
const [busy, setBusy] = React.useState(false);
|
|
213
|
+
const [confirmingDelete, setConfirmingDelete] = React.useState(false);
|
|
214
|
+
const [notice, setNotice] = React.useState(null);
|
|
215
|
+
const load = React.useCallback(async () => {
|
|
163
216
|
setLoading(true);
|
|
164
217
|
setError(null);
|
|
165
218
|
try {
|
|
@@ -171,12 +224,38 @@ window.__ModuleLoader__.load({
|
|
|
171
224
|
setLoading(false);
|
|
172
225
|
}
|
|
173
226
|
}, [call, t]);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
227
|
+
React.useEffect(() => {
|
|
228
|
+
if (open) {
|
|
229
|
+
setNotice(null);
|
|
230
|
+
load();
|
|
231
|
+
}
|
|
177
232
|
}, [open, load]);
|
|
178
|
-
|
|
179
|
-
|
|
233
|
+
const refreshSilently = React.useCallback(async () => {
|
|
234
|
+
try {
|
|
235
|
+
const result = await call("list");
|
|
236
|
+
setItems(Array.isArray(result.items) ? result.items : []);
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
}, [call]);
|
|
240
|
+
React.useEffect(() => {
|
|
241
|
+
if (open) return;
|
|
242
|
+
refreshSilently();
|
|
243
|
+
const id = globalThis.setInterval(refreshSilently, 5e3);
|
|
244
|
+
const onVis = () => {
|
|
245
|
+
if (document.visibilityState === "visible") refreshSilently();
|
|
246
|
+
};
|
|
247
|
+
document.addEventListener("visibilitychange", onVis);
|
|
248
|
+
return () => {
|
|
249
|
+
clearInterval(id);
|
|
250
|
+
document.removeEventListener("visibilitychange", onVis);
|
|
251
|
+
};
|
|
252
|
+
}, [open, refreshSilently]);
|
|
253
|
+
React.useEffect(() => {
|
|
254
|
+
if (notice === null) return;
|
|
255
|
+
const id = globalThis.setTimeout(() => setNotice(null), 4e3);
|
|
256
|
+
return () => clearTimeout(id);
|
|
257
|
+
}, [notice]);
|
|
258
|
+
React.useEffect(() => {
|
|
180
259
|
if (!open) return;
|
|
181
260
|
const onPointerDown = (event) => {
|
|
182
261
|
if (rootRef.current !== null && !rootRef.current.contains(event.target)) {
|
|
@@ -186,25 +265,23 @@ window.__ModuleLoader__.load({
|
|
|
186
265
|
document.addEventListener("pointerdown", onPointerDown);
|
|
187
266
|
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
188
267
|
}, [open]);
|
|
189
|
-
|
|
190
268
|
const selectable = items.filter((item) => !item.live);
|
|
191
269
|
const allSelected = selectable.length > 0 && selectable.every((item) => selected.has(item.sessionId));
|
|
192
|
-
|
|
193
270
|
const toggleAll = (checked) => {
|
|
194
271
|
if (checked) {
|
|
195
272
|
setSelected(new Set(selectable.map((item) => item.sessionId)));
|
|
196
273
|
} else {
|
|
197
|
-
setSelected(new Set());
|
|
274
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
198
275
|
}
|
|
199
276
|
};
|
|
200
277
|
const toggleOne = (sessionId, checked) => {
|
|
201
278
|
setSelected((current) => {
|
|
202
279
|
const next = new Set(current);
|
|
203
|
-
if (checked) next.add(sessionId);
|
|
280
|
+
if (checked) next.add(sessionId);
|
|
281
|
+
else next.delete(sessionId);
|
|
204
282
|
return next;
|
|
205
283
|
});
|
|
206
284
|
};
|
|
207
|
-
|
|
208
285
|
const toggleDetail = (item) => {
|
|
209
286
|
if (expanded === item.sessionId) {
|
|
210
287
|
setExpanded(null);
|
|
@@ -228,7 +305,6 @@ window.__ModuleLoader__.load({
|
|
|
228
305
|
});
|
|
229
306
|
}
|
|
230
307
|
};
|
|
231
|
-
|
|
232
308
|
const runBatch = async (action, doneKey, failKey) => {
|
|
233
309
|
const ids = [...selected];
|
|
234
310
|
if (ids.length === 0) {
|
|
@@ -250,7 +326,7 @@ window.__ModuleLoader__.load({
|
|
|
250
326
|
const done = new Set(doneIds);
|
|
251
327
|
setItems((current) => current.filter((item) => !done.has(item.sessionId)));
|
|
252
328
|
}
|
|
253
|
-
setSelected(new Set());
|
|
329
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
254
330
|
setConfirmingDelete(false);
|
|
255
331
|
await load();
|
|
256
332
|
} catch (actionError) {
|
|
@@ -263,49 +339,60 @@ window.__ModuleLoader__.load({
|
|
|
263
339
|
const deleteSelected = () => {
|
|
264
340
|
if (!confirmingDelete) {
|
|
265
341
|
setConfirmingDelete(true);
|
|
266
|
-
window.setTimeout(() => setConfirmingDelete(false),
|
|
342
|
+
window.setTimeout(() => setConfirmingDelete(false), 4e3);
|
|
267
343
|
return;
|
|
268
344
|
}
|
|
269
345
|
runBatch("delete", "deleteDone", "deleteFailed");
|
|
270
346
|
};
|
|
271
|
-
|
|
272
347
|
const hasSelection = selected.size > 0;
|
|
273
|
-
|
|
274
|
-
return react.createElement(
|
|
348
|
+
return React.createElement(
|
|
275
349
|
"div",
|
|
276
350
|
{ className: "sa_root", ref: rootRef },
|
|
277
|
-
|
|
351
|
+
React.createElement(
|
|
278
352
|
"button",
|
|
279
353
|
{
|
|
280
|
-
|
|
354
|
+
ref: badgeRef,
|
|
355
|
+
className: "sa_badge" + (iconOnly ? " sa_badge--collapsed" : ""),
|
|
281
356
|
type: "button",
|
|
282
357
|
onClick: () => setOpen(!open),
|
|
283
358
|
"aria-expanded": open,
|
|
284
359
|
title: t("badge")
|
|
285
360
|
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
361
|
+
React.createElement(
|
|
362
|
+
"span",
|
|
363
|
+
{ className: "sa_badgeIcon", "aria-hidden": true },
|
|
364
|
+
React.createElement(
|
|
365
|
+
"svg",
|
|
366
|
+
{ viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" },
|
|
367
|
+
React.createElement("rect", { x: 3, y: 4, width: 18, height: 4, rx: 1 }),
|
|
368
|
+
React.createElement("path", { d: "M5 8v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8" }),
|
|
369
|
+
React.createElement("path", { d: "M10 12h4" })
|
|
370
|
+
)
|
|
371
|
+
),
|
|
372
|
+
iconOnly ? null : React.createElement("span", { className: "sa_badgeLabel" }, t("badge")),
|
|
373
|
+
iconOnly ? null : React.createElement("span", { className: "sa_badgeCount" }, String(items.length))
|
|
289
374
|
),
|
|
290
|
-
open ?
|
|
375
|
+
open ? React.createElement(
|
|
291
376
|
"div",
|
|
292
377
|
{ className: "sa_panel" },
|
|
293
|
-
|
|
378
|
+
React.createElement(
|
|
294
379
|
"div",
|
|
295
380
|
{ className: "sa_header" },
|
|
296
|
-
|
|
297
|
-
|
|
381
|
+
React.createElement("span", { className: "sa_title" }, t("panelTitle")),
|
|
382
|
+
React.createElement(
|
|
298
383
|
"span",
|
|
299
384
|
{ style: { display: "inline-flex", gap: "6px", alignItems: "center" } },
|
|
300
|
-
|
|
301
|
-
|
|
385
|
+
React.createElement("button", { className: "sa_refresh", type: "button", title: t("refresh"), disabled: busy || loading, onClick: load }, t("refresh")),
|
|
386
|
+
React.createElement("button", { className: "sa_iconBtn", type: "button", title: t("close"), disabled: busy, onClick: () => setOpen(false) }, "\u2715")
|
|
302
387
|
)
|
|
303
388
|
),
|
|
304
|
-
|
|
389
|
+
React.createElement(
|
|
305
390
|
"div",
|
|
306
391
|
{ className: "sa_toolbar" },
|
|
307
|
-
|
|
308
|
-
|
|
392
|
+
React.createElement(
|
|
393
|
+
"label",
|
|
394
|
+
{ className: "sa_toolLabel" },
|
|
395
|
+
React.createElement("input", {
|
|
309
396
|
className: "sa_check",
|
|
310
397
|
type: "checkbox",
|
|
311
398
|
checked: allSelected,
|
|
@@ -314,41 +401,41 @@ window.__ModuleLoader__.load({
|
|
|
314
401
|
}),
|
|
315
402
|
t("selectAll")
|
|
316
403
|
),
|
|
317
|
-
|
|
318
|
-
|
|
404
|
+
React.createElement("span", { className: "sa_count" }, t("selected").replace("{n}", String(selected.size))),
|
|
405
|
+
React.createElement("button", {
|
|
319
406
|
className: "sa_action",
|
|
320
407
|
type: "button",
|
|
321
408
|
disabled: busy || !hasSelection,
|
|
322
409
|
onClick: restoreSelected
|
|
323
410
|
}, t("restore")),
|
|
324
|
-
|
|
411
|
+
React.createElement("button", {
|
|
325
412
|
className: "sa_action " + (confirmingDelete ? "sa_actionDanger sa_confirm" : "sa_actionDanger"),
|
|
326
413
|
type: "button",
|
|
327
414
|
disabled: busy || !hasSelection,
|
|
328
415
|
onClick: deleteSelected
|
|
329
416
|
}, confirmingDelete ? t("deleteConfirm") : t("delete"))
|
|
330
417
|
),
|
|
331
|
-
|
|
418
|
+
React.createElement(
|
|
332
419
|
"div",
|
|
333
420
|
{ className: "sa_body" },
|
|
334
|
-
notice !== null ?
|
|
335
|
-
error !== null ?
|
|
336
|
-
loading && items.length === 0 ?
|
|
337
|
-
!loading && items.length === 0 && error === null ?
|
|
338
|
-
items.length > 0 ?
|
|
421
|
+
notice !== null ? React.createElement("p", { className: "sa_error" + (notice.kind === "ok" ? "" : ""), role: "status" }, notice.text) : null,
|
|
422
|
+
error !== null ? React.createElement("p", { className: "sa_error", role: "alert" }, error) : null,
|
|
423
|
+
loading && items.length === 0 ? React.createElement("p", { className: "sa_empty" }, "\u2026") : null,
|
|
424
|
+
!loading && items.length === 0 && error === null ? React.createElement("p", { className: "sa_empty" }, t("empty")) : null,
|
|
425
|
+
items.length > 0 ? React.createElement(
|
|
339
426
|
"ul",
|
|
340
427
|
{ className: "sa_rows" },
|
|
341
428
|
items.map((item) => {
|
|
342
429
|
const isExpanded = expanded === item.sessionId;
|
|
343
430
|
const detail = details.get(item.sessionId);
|
|
344
431
|
const detailPending = detailLoading.has(item.sessionId);
|
|
345
|
-
return
|
|
432
|
+
return React.createElement(
|
|
346
433
|
"li",
|
|
347
434
|
{ className: "sa_row" + (busy ? " sa_busy" : ""), key: item.sessionId },
|
|
348
|
-
|
|
435
|
+
React.createElement(
|
|
349
436
|
"div",
|
|
350
437
|
{ className: "sa_rowHead" },
|
|
351
|
-
|
|
438
|
+
React.createElement("input", {
|
|
352
439
|
className: "sa_check",
|
|
353
440
|
type: "checkbox",
|
|
354
441
|
checked: selected.has(item.sessionId),
|
|
@@ -356,31 +443,33 @@ window.__ModuleLoader__.load({
|
|
|
356
443
|
title: item.live ? t("runningHint") : void 0,
|
|
357
444
|
onChange: (e) => toggleOne(item.sessionId, e.target.checked)
|
|
358
445
|
}),
|
|
359
|
-
|
|
446
|
+
React.createElement(
|
|
360
447
|
"span",
|
|
361
448
|
{ className: "sa_rowTitle", onClick: () => toggleDetail(item), title: t("view") },
|
|
362
449
|
item.title !== null && item.title !== void 0 && item.title !== "" ? item.title : t("noneTitle")
|
|
363
450
|
),
|
|
364
|
-
item.live ?
|
|
451
|
+
item.live ? React.createElement("span", { className: "sa_live" }, t("live")) : null
|
|
365
452
|
),
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
453
|
+
React.createElement(
|
|
454
|
+
"div",
|
|
455
|
+
{ className: "sa_rowMeta" },
|
|
456
|
+
React.createElement("span", null, formatTime(item.updatedAt)),
|
|
457
|
+
item.cwd !== null && item.cwd !== void 0 ? React.createElement("span", null, " \xB7 ", React.createElement("code", null, item.cwd)) : null,
|
|
458
|
+
React.createElement("span", null, " \xB7 ", formatBytes(item.size, t))
|
|
370
459
|
),
|
|
371
|
-
|
|
460
|
+
React.createElement(
|
|
372
461
|
"div",
|
|
373
462
|
{ className: "sa_rowFoot" },
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
463
|
+
React.createElement(
|
|
464
|
+
"span",
|
|
465
|
+
{ className: "sa_rowMeta" },
|
|
466
|
+
React.createElement("code", null, shortId(item.sessionId)),
|
|
467
|
+
detail !== void 0 && !detail.error && detail.messageCount !== void 0 ? " \xB7 " + t("messages").replace("{n}", String(detail.messageCount)) : null
|
|
379
468
|
),
|
|
380
|
-
|
|
469
|
+
React.createElement(
|
|
381
470
|
"div",
|
|
382
471
|
{ className: "sa_rowActions" },
|
|
383
|
-
|
|
472
|
+
React.createElement("button", {
|
|
384
473
|
className: "sa_action",
|
|
385
474
|
type: "button",
|
|
386
475
|
disabled: busy || detailPending,
|
|
@@ -388,19 +477,16 @@ window.__ModuleLoader__.load({
|
|
|
388
477
|
}, isExpanded ? t("collapse") : t("view"))
|
|
389
478
|
)
|
|
390
479
|
),
|
|
391
|
-
isExpanded ?
|
|
480
|
+
isExpanded ? React.createElement(
|
|
392
481
|
"div",
|
|
393
482
|
{ className: "sa_detail" },
|
|
394
|
-
detailPending ?
|
|
395
|
-
detail === void 0 ? null :
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
react.createElement("span", { className: "sa_msgRole" }, message.role === "user" ? t("user") : t("assistant") + " · " + formatTime(message.time)),
|
|
402
|
-
react.createElement("span", { className: "sa_msgText" + (message.role === "user" ? " sa_msgTextUser" : "") }, message.text)
|
|
403
|
-
))
|
|
483
|
+
detailPending ? React.createElement("p", { className: "sa_empty" }, "\u2026") : null,
|
|
484
|
+
detail === void 0 ? null : detail.error !== void 0 ? React.createElement("p", { className: "sa_error" }, detail.error) : detail.messages.length === 0 ? React.createElement("p", { className: "sa_empty" }, t("noMessages")) : detail.messages.map((message, index) => React.createElement(
|
|
485
|
+
"div",
|
|
486
|
+
{ className: "sa_msg", key: index },
|
|
487
|
+
React.createElement("span", { className: "sa_msgRole" }, message.role === "user" ? t("user") : t("assistant") + " \xB7 " + formatTime(message.time)),
|
|
488
|
+
React.createElement("span", { className: "sa_msgText" + (message.role === "user" ? " sa_msgTextUser" : "") }, message.text)
|
|
489
|
+
))
|
|
404
490
|
) : null
|
|
405
491
|
);
|
|
406
492
|
})
|
|
@@ -409,13 +495,9 @@ window.__ModuleLoader__.load({
|
|
|
409
495
|
) : null
|
|
410
496
|
);
|
|
411
497
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
// ctx.remote.$mount(contribution) 显式挂载(官方 dsh-api-remotes 即如此)。
|
|
416
|
-
const inject = ["slots", "locale", "remote"];
|
|
417
|
-
const passthroughSchema = { parse: (value) => value };
|
|
418
|
-
const REMOTE_CONTRIBUTION = {
|
|
498
|
+
var inject = ["slots", "locale", "remote"];
|
|
499
|
+
var passthroughSchema = { parse: (value) => value };
|
|
500
|
+
var REMOTE_CONTRIBUTION = {
|
|
419
501
|
package: "@chaoset/session-archive",
|
|
420
502
|
descriptors: [
|
|
421
503
|
{ id: "@chaoset/session-archive#sessionArchive/list", service: "sessionArchive", namespace: "sessionArchive", method: "list", invocation: { kind: "direct" }, parameters: [], result: { mode: "strict", typeSymbol: "sessionArchive/list:result", schema: passthroughSchema } },
|
|
@@ -443,8 +525,6 @@ window.__ModuleLoader__.load({
|
|
|
443
525
|
}, ArchivePanel));
|
|
444
526
|
}
|
|
445
527
|
|
|
446
|
-
exports.apply = apply;
|
|
447
|
-
exports.inject = inject;
|
|
448
528
|
return module.exports;
|
|
449
529
|
}
|
|
450
530
|
});
|