@michengai/dsh-archive-manager 0.1.44 → 1.0.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/CHANGELOG.md +63 -0
- package/CHANGELOG.zh-CN.md +63 -0
- package/README.md +65 -17
- package/README.zh-CN.md +69 -17
- package/assets/branding/banner.txt +4 -2
- package/assets/branding/dsh-banner-en.webp +0 -0
- package/assets/branding/dsh-banner.webp +0 -0
- package/assets/screenshots/archived-sessions.webp +0 -0
- package/assets/screenshots/unarchived-sessions.webp +0 -0
- package/lib/archive-discovery.js +252 -0
- package/lib/archive-experience.js +12 -6
- package/lib/archive-organizer.js +108 -0
- package/lib/client.js +1402 -207
- package/lib/contracts.js +15 -0
- package/lib/plugin-updater.js +8 -5
- package/lib/projcache.js +11 -7
- package/lib/session-repair.js +135 -0
- package/lib/workspace.js +250 -20
- package/package.json +16 -9
- package/assets/branding/dsh-banner.png +0 -0
- package/assets/screenshots/archive-session-menu.png +0 -0
- package/assets/screenshots/archived-sessions.png +0 -0
package/lib/client.js
CHANGED
|
@@ -1,6 +1,688 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
(() => {
|
|
2
|
-
// src/
|
|
3
|
+
// src/contracts.ts
|
|
4
|
+
function record(value) {
|
|
5
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("\u53C2\u6570\u5FC5\u987B\u4E3A\u5BF9\u8C61");
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
function errorMessage(error) {
|
|
9
|
+
return String(error && typeof error === "object" && "message" in error ? error.message ?? error : error);
|
|
10
|
+
}
|
|
11
|
+
function errorCode(error) {
|
|
12
|
+
return error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/session-health-locales.ts
|
|
16
|
+
var healthZh = {
|
|
17
|
+
"health.archived": "\u5DF2\u5F52\u6863\u4F1A\u8BDD\u9700\u8981\u68C0\u67E5",
|
|
18
|
+
"health.unarchived": "\u672A\u5F52\u6863\u4F1A\u8BDD\u9700\u8981\u68C0\u67E5",
|
|
19
|
+
"health.heading": "\u8BCA\u65AD\u4E0E\u4FEE\u590D",
|
|
20
|
+
"health.scopeArchived": "\u68C0\u67E5\u8303\u56F4\uFF1A\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF0C\u4E0D\u53D7\u5217\u8868\u7B5B\u9009\u5F71\u54CD\u3002",
|
|
21
|
+
"health.scopeUnarchived": "\u68C0\u67E5\u8303\u56F4\uFF1A\u5168\u90E8\u672A\u5F52\u6863\u4F1A\u8BDD\uFF0C\u4E0D\u53D7\u5217\u8868\u7B5B\u9009\u5F71\u54CD\u3002\u4FEE\u590D\u524D\u9700\u5148\u5F52\u6863\u5E76\u5173\u95ED\u4F1A\u8BDD\u3002",
|
|
22
|
+
"health.retry": "\u91CD\u65B0\u68C0\u6D4B",
|
|
23
|
+
"health.busy": "\u5904\u7406\u4E2D\u2026",
|
|
24
|
+
"health.confirm": "\u786E\u8BA4\u4FEE\u590D",
|
|
25
|
+
"health.diagnose": "\u8BCA\u65AD\u4F1A\u8BDD",
|
|
26
|
+
"health.technical": "\u6280\u672F\u8BE6\u60C5",
|
|
27
|
+
"health.notice": "\u4F1A\u8BDD\u4FEE\u590D\u5B8C\u6210\uFF0C\u5DF2\u91CD\u65B0\u8BFB\u53D6\u8BE6\u60C5\u3002",
|
|
28
|
+
"health.legacy-source.reason": "\u65E7\u7248\u6D88\u606F\u6765\u6E90\u4E0D\u53D7\u65B0\u7248 DSH \u652F\u6301",
|
|
29
|
+
"health.legacy-source.advice": "\u8FD0\u884C\u8BCA\u65AD\uFF0C\u68C0\u67E5\u662F\u5426\u4E3A\u53EF\u8F6C\u6362\u7684\u65E7\u81EA\u52A8\u5316\u6765\u6E90\u3002",
|
|
30
|
+
"health.repair-frame.reason": "\u65E7\u7248\u4FEE\u590D\u751F\u6210\u7684\u538B\u7F29\u683C\u5F0F\u4E0D\u7B26\u5408\u5BBF\u4E3B\u8981\u6C42",
|
|
31
|
+
"health.repair-frame.advice": "\u91CD\u65B0\u8BCA\u65AD\u53EF\u7EA0\u6B63\u538B\u7F29\u5E27\u683C\u5F0F\uFF0C\u539F\u59CB\u65E5\u5FD7\u4FDD\u6301\u4E0D\u53D8\u3002",
|
|
32
|
+
"health.missing.reason": "\u4F1A\u8BDD\u65E5\u5FD7\u6216\u9644\u4EF6\u8DEF\u5F84\u4E0D\u5B58\u5728",
|
|
33
|
+
"health.missing.advice": "\u68C0\u67E5\u539F\u76EE\u5F55\u6216\u78C1\u76D8\u662F\u5426\u53EF\u7528\uFF1B\u7F3A\u5931\u6B63\u6587\u4E0D\u80FD\u901A\u8FC7\u91CD\u5EFA\u7F13\u5B58\u6062\u590D\u3002",
|
|
34
|
+
"health.permission.reason": "\u6CA1\u6709\u6743\u9650\u8BFB\u53D6\u4F1A\u8BDD\u6587\u4EF6",
|
|
35
|
+
"health.permission.advice": "\u68C0\u67E5\u76EE\u5F55\u8BBF\u95EE\u6743\u9650\u3001\u6587\u4EF6\u5360\u7528\u4E0E\u5B89\u5168\u8F6F\u4EF6\u9650\u5236\uFF0C\u518D\u91CD\u8BD5\u3002",
|
|
36
|
+
"health.corrupt.reason": "\u4F1A\u8BDD\u65E5\u5FD7\u53EF\u80FD\u635F\u574F\u6216\u672A\u5B8C\u6574\u5199\u5165",
|
|
37
|
+
"health.corrupt.advice": "\u4FDD\u7559\u73B0\u6709\u65E5\u5FD7\uFF0C\u68C0\u67E5\u78C1\u76D8\u548C\u539F\u59CB\u6587\u4EF6\uFF1B\u4E0D\u81EA\u52A8\u622A\u65AD\u6216\u5220\u9664\u6D88\u606F\u3002",
|
|
38
|
+
"health.unknown.reason": "\u4F1A\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6",
|
|
39
|
+
"health.unknown.advice": "\u5148\u91CD\u8BD5\uFF1B\u4ECD\u5931\u8D25\u65F6\u5C55\u5F00\u6280\u672F\u8BE6\u60C5\uFF0C\u6309\u5177\u4F53\u9519\u8BEF\u68C0\u67E5\u5BBF\u4E3B\u517C\u5BB9\u6027\u3002",
|
|
40
|
+
"health.healthy.reason": "\u4F1A\u8BDD\u5DF2\u53EF\u6B63\u5E38\u8BFB\u53D6",
|
|
41
|
+
"health.healthy.advice": "\u5237\u65B0\u4F1A\u8BDD\u8BE6\u60C5\u5373\u53EF\uFF0C\u65E0\u9700\u4FEE\u590D\u3002",
|
|
42
|
+
"health.ready.reason": "\u53D1\u73B0 {n} \u5904\u65E7\u81EA\u52A8\u5316\u6765\u6E90\uFF0C\u5DF2\u901A\u8FC7\u5BBF\u4E3B\u683C\u5F0F\u8F6C\u6362\u6821\u9A8C",
|
|
43
|
+
"health.ready.advice": "\u5C06\u6765\u6E90\u8F6C\u6362\u4E3A dsh-automation \u63D2\u4EF6\u5F52\u5C5E\uFF0C\u4FDD\u7559\u4EFB\u52A1\u4FE1\u606F\u4E0E\u6B63\u6587\uFF0C\u751F\u6210\u65B0\u7248\u65E5\u5FD7\uFF1B\u65E7\u65E5\u5FD7\u539F\u6837\u4FDD\u7559\u3002\u8BF7\u786E\u4FDD\u5176\u4ED6 DSH \u8FDB\u7A0B\u672A\u6253\u5F00\u8BE5\u4F1A\u8BDD\u3002",
|
|
44
|
+
"health.ready-frame.reason": "\u53D1\u73B0\u65E7\u7248\u4FEE\u590D\u7684\u538B\u7F29\u5E27\u95EE\u9898\uFF0C\u5DF2\u901A\u8FC7\u5BBF\u4E3B\u8BFB\u53D6\u6821\u9A8C",
|
|
45
|
+
"health.ready-frame.advice": "\u7EA0\u6B63\u538B\u7F29\u5E27\u683C\u5F0F\uFF0C\u4FDD\u7559\u6B63\u6587\u53CA\u539F\u59CB\u65E5\u5FD7\u3002\u8BF7\u786E\u4FDD\u5176\u4ED6 DSH \u8FDB\u7A0B\u672A\u6253\u5F00\u8BE5\u4F1A\u8BDD\u3002",
|
|
46
|
+
"health.blocked.reason": "\u6682\u4E0D\u80FD\u81EA\u52A8\u4FEE\u590D",
|
|
47
|
+
"health.blocked.advice": "\u8BF7\u5C55\u5F00\u6280\u672F\u8BE6\u60C5\u67E5\u770B\u5177\u4F53\u9650\u5236\uFF0C\u5904\u7406\u540E\u91CD\u65B0\u8BCA\u65AD\u3002",
|
|
48
|
+
"health.repaired.reason": "\u4FEE\u590D\u5B8C\u6210\uFF0C\u5BBF\u4E3B\u5DF2\u80FD\u6B63\u5E38\u8BFB\u53D6",
|
|
49
|
+
"health.repaired.advice": "\u65E7\u65E5\u5FD7\u4FDD\u7559\uFF0C\u5F52\u6863\u72B6\u6001\u4E0D\u53D8\uFF1B\u53EF\u4EE5\u91CD\u65B0\u9884\u89C8\u6216\u6253\u5F00\u4F1A\u8BDD\u3002",
|
|
50
|
+
"health.published-unreadable.reason": "\u65B0\u7248\u65E5\u5FD7\u5DF2\u751F\u6210\uFF0C\u4F46\u5BBF\u4E3B\u590D\u8BFB\u672A\u901A\u8FC7",
|
|
51
|
+
"health.published-unreadable.advice": "\u65E7\u65E5\u5FD7\u4ECD\u4FDD\u7559\uFF0C\u8BF7\u91CD\u542F DSH \u540E\u91CD\u65B0\u8BCA\u65AD\uFF1B\u4E0D\u8981\u53CD\u590D\u4FEE\u590D\u6216\u5220\u9664\u65E5\u5FD7\u3002",
|
|
52
|
+
"health.failed.reason": "\u64CD\u4F5C\u672A\u5B8C\u6210",
|
|
53
|
+
"health.failed.advice": "\u8BF7\u5C55\u5F00\u6280\u672F\u8BE6\u60C5\u67E5\u770B\u9519\u8BEF\uFF0C\u5904\u7406\u540E\u91CD\u65B0\u8BCA\u65AD\u3002"
|
|
54
|
+
};
|
|
55
|
+
var healthEn = {
|
|
56
|
+
"health.archived": "Archived sessions need attention",
|
|
57
|
+
"health.unarchived": "Unarchived sessions need attention",
|
|
58
|
+
"health.heading": "Diagnosis and repair",
|
|
59
|
+
"health.scopeArchived": "Checks all archived sessions, regardless of list filters.",
|
|
60
|
+
"health.scopeUnarchived": "Checks all unarchived sessions, regardless of list filters. Archive and close a session before repairing it.",
|
|
61
|
+
"health.retry": "Check again",
|
|
62
|
+
"health.busy": "Processing\u2026",
|
|
63
|
+
"health.confirm": "Confirm repair",
|
|
64
|
+
"health.diagnose": "Diagnose session",
|
|
65
|
+
"health.technical": "Technical details",
|
|
66
|
+
"health.notice": "Session repaired. Details have been refreshed.",
|
|
67
|
+
"health.legacy-source.reason": "The new DSH version does not support this legacy message source",
|
|
68
|
+
"health.legacy-source.advice": "Run a diagnosis to check whether the legacy automation source can be converted.",
|
|
69
|
+
"health.repair-frame.reason": "A previous repair used an unsupported compression format",
|
|
70
|
+
"health.repair-frame.advice": "Run a diagnosis to correct the compression frames while preserving the original log.",
|
|
71
|
+
"health.missing.reason": "The session log or attachment path does not exist",
|
|
72
|
+
"health.missing.advice": "Check the original directory and disk. Rebuilding the cache cannot recover missing messages.",
|
|
73
|
+
"health.permission.reason": "Permission to read the session files was denied",
|
|
74
|
+
"health.permission.advice": "Check directory permissions, file locks and security software, then retry.",
|
|
75
|
+
"health.corrupt.reason": "The session log may be corrupt or incomplete",
|
|
76
|
+
"health.corrupt.advice": "Keep the existing log and check the disk and original files. Messages will not be truncated or deleted automatically.",
|
|
77
|
+
"health.unknown.reason": "The session cannot currently be read",
|
|
78
|
+
"health.unknown.advice": "Retry first. If it still fails, expand technical details to check host compatibility.",
|
|
79
|
+
"health.healthy.reason": "The session can be read normally",
|
|
80
|
+
"health.healthy.advice": "Refresh the session details. No repair is needed.",
|
|
81
|
+
"health.ready.reason": "Found {n} legacy automation sources; host format validation passed",
|
|
82
|
+
"health.ready.advice": "Convert the sources to the dsh-automation plugin and generate a new log, preserving task information, messages and the original log. Ensure no other DSH process has the session open.",
|
|
83
|
+
"health.ready-frame.reason": "Found compression frame issues from a previous repair; host validation passed",
|
|
84
|
+
"health.ready-frame.advice": "Correct the compression frames, preserving messages and the original log. Ensure no other DSH process has the session open.",
|
|
85
|
+
"health.blocked.reason": "Automatic repair is currently unavailable",
|
|
86
|
+
"health.blocked.advice": "Expand technical details to see the restriction. Resolve it before diagnosing again.",
|
|
87
|
+
"health.repaired.reason": "Repair complete; the host can read the session",
|
|
88
|
+
"health.repaired.advice": "The original log and archive status are preserved. You can preview or open the session again.",
|
|
89
|
+
"health.published-unreadable.reason": "A new log was generated, but the host could not read it back",
|
|
90
|
+
"health.published-unreadable.advice": "The original log is preserved. Restart DSH and diagnose again. Do not repeatedly repair or delete logs.",
|
|
91
|
+
"health.failed.reason": "The operation did not complete",
|
|
92
|
+
"health.failed.advice": "Expand technical details to inspect the error. Resolve it before diagnosing again."
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/archive-discovery.ts
|
|
96
|
+
var id = (value) => {
|
|
97
|
+
if (typeof value !== "string" || !value.length || value.length > 1024) throw new TypeError("\u4F1A\u8BDD ID \u65E0\u6548");
|
|
98
|
+
return value;
|
|
99
|
+
};
|
|
100
|
+
var queryText = (value, required = false) => {
|
|
101
|
+
if (typeof value !== "string" || value.length > 200 || required && !value.trim()) throw new TypeError("\u5173\u952E\u8BCD\u987B\u4E3A 1\uFF5E200 \u4E2A\u5B57\u7B26");
|
|
102
|
+
return value.trim();
|
|
103
|
+
};
|
|
104
|
+
var searchInputSchema = { parse(input) {
|
|
105
|
+
const value = record(input);
|
|
106
|
+
if (!value || !Array.isArray(value.sessionIds) || !value.sessionIds.length || value.sessionIds.length > 20) throw new TypeError("\u6BCF\u6B21\u68C0\u7D22\u987B\u5305\u542B 1\uFF5E20 \u4E2A\u4F1A\u8BDD");
|
|
107
|
+
return { sessionIds: [...new Set(value.sessionIds.map(id))], query: queryText(value.query, true) };
|
|
108
|
+
} };
|
|
109
|
+
var previewInputSchema = { parse(input) {
|
|
110
|
+
const value = record(input);
|
|
111
|
+
if (!value) throw new TypeError("\u9884\u89C8\u53C2\u6570\u65E0\u6548");
|
|
112
|
+
return { sessionId: id(value.sessionId), query: queryText(value.query ?? "") };
|
|
113
|
+
} };
|
|
114
|
+
var boundedString = (value, max) => {
|
|
115
|
+
if (typeof value !== "string" || value.length > max) throw new TypeError("\u8FD4\u56DE\u6587\u672C\u65E0\u6548");
|
|
116
|
+
return value;
|
|
117
|
+
};
|
|
118
|
+
var sequence = (value) => {
|
|
119
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new TypeError("\u6D88\u606F\u5E8F\u53F7\u65E0\u6548");
|
|
120
|
+
return value;
|
|
121
|
+
};
|
|
122
|
+
var searchResultSchema = { parse(input) {
|
|
123
|
+
const value = record(input);
|
|
124
|
+
if (!value || !Array.isArray(value.items) || !Array.isArray(value.failures) || value.items.length > 20 || value.failures.length > 20) throw new TypeError("\u68C0\u7D22\u7ED3\u679C\u65E0\u6548");
|
|
125
|
+
return {
|
|
126
|
+
items: value.items.map(record).map((row) => ({ sessionId: id(row.sessionId), seq: sequence(row.seq), snippet: boundedString(row.snippet, 400) })),
|
|
127
|
+
failures: value.failures.map(record).map((row) => ({ sessionId: id(row.sessionId), message: boundedString(row.message, 500) }))
|
|
128
|
+
};
|
|
129
|
+
} };
|
|
130
|
+
var previewResultSchema = { parse(input) {
|
|
131
|
+
const value = record(input);
|
|
132
|
+
if (!value || !Array.isArray(value.messages) || value.messages.length > 8 || typeof value.hasEarlier !== "boolean" || typeof value.hasLater !== "boolean") throw new TypeError("\u9884\u89C8\u7ED3\u679C\u65E0\u6548");
|
|
133
|
+
return {
|
|
134
|
+
sessionId: id(value.sessionId),
|
|
135
|
+
hasEarlier: value.hasEarlier,
|
|
136
|
+
hasLater: value.hasLater,
|
|
137
|
+
messages: value.messages.map(record).map((row) => {
|
|
138
|
+
if (typeof row.role !== "string" || !["user", "assistant"].includes(row.role) || typeof row.truncated !== "boolean") throw new TypeError("\u6D88\u606F\u89D2\u8272\u6216\u622A\u65AD\u72B6\u6001\u65E0\u6548");
|
|
139
|
+
return { seq: sequence(row.seq), role: row.role, text: boundedString(row.text, 2e3), truncated: row.truncated };
|
|
140
|
+
})
|
|
141
|
+
};
|
|
142
|
+
} };
|
|
143
|
+
var detailsInputSchema = { parse(input) {
|
|
144
|
+
const value = record(input);
|
|
145
|
+
if (!value || !Array.isArray(value.sessionIds) || !value.sessionIds.length || value.sessionIds.length > 20) throw new TypeError("\u6BCF\u6B21\u987B\u5305\u542B 1\uFF5E20 \u4E2A\u4F1A\u8BDD");
|
|
146
|
+
return { sessionIds: [...new Set(value.sessionIds.map(id))] };
|
|
147
|
+
} };
|
|
148
|
+
var detailsResultSchema = { parse(input) {
|
|
149
|
+
const value = record(input);
|
|
150
|
+
if (!value || !Array.isArray(value.items) || value.items.length > 20) throw new TypeError("\u4F1A\u8BDD\u8BE6\u60C5\u65E0\u6548");
|
|
151
|
+
return { items: value.items.map(record).map((row) => ({ sessionId: id(row.sessionId), ...row.createdAt !== void 0 ? { createdAt: sequence(row.createdAt) } : {}, turnCount: row.turnCount === null ? null : sequence(row.turnCount), path: row.path === null ? null : boundedString(row.path, 32768), error: boundedString(row.error, 500) })) };
|
|
152
|
+
} };
|
|
153
|
+
function compareTurnCounts(left, right, order) {
|
|
154
|
+
const a = typeof left === "number" && Number.isSafeInteger(left) && left >= 0;
|
|
155
|
+
const b = typeof right === "number" && Number.isSafeInteger(right) && right >= 0;
|
|
156
|
+
if (a !== b) return a ? -1 : 1;
|
|
157
|
+
return a && b ? order === "turnsAsc" ? left - right : right - left : 0;
|
|
158
|
+
}
|
|
159
|
+
async function copySessionText(text, clipboard = globalThis.navigator?.clipboard) {
|
|
160
|
+
if (typeof text !== "string" || !text) throw Object.assign(new Error("\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9"), { code: "copy.empty" });
|
|
161
|
+
if (!clipboard?.writeText) throw Object.assign(new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301\u526A\u8D34\u677F\uFF0C\u8BF7\u5728 HTTPS \u6216\u672C\u673A\u5730\u5740\u4E2D\u6253\u5F00\u9875\u9762"), { code: "copy.unavailable" });
|
|
162
|
+
try {
|
|
163
|
+
await clipboard.writeText(text);
|
|
164
|
+
} catch {
|
|
165
|
+
throw Object.assign(new Error("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u5141\u8BB8\u6D4F\u89C8\u5668\u8BBF\u95EE\u526A\u8D34\u677F\u540E\u91CD\u8BD5"), { code: "copy.denied" });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function discoveryInvocations() {
|
|
169
|
+
const codec = (name, schema) => ({ mode: "strict", typeSymbol: `@michengai/dsh-archive-manager/types#${name}`, create: () => schema, schema });
|
|
170
|
+
const methods = [["searchSessionContent", searchInputSchema, searchResultSchema], ["diagnoseSession", repairInputSchema, repairResultSchema], ["repairSession", repairInputSchema, repairResultSchema], ["sessionDetails", detailsInputSchema, detailsResultSchema], ["searchArchivedContent", searchInputSchema, searchResultSchema], ["previewArchivedSession", previewInputSchema, previewResultSchema]];
|
|
171
|
+
return methods.map(([method, input, output]) => ({
|
|
172
|
+
id: `@michengai/dsh-archive-manager#workspaceRegistry/${method}`,
|
|
173
|
+
service: "workspaceRegistry",
|
|
174
|
+
namespace: "workspaceRegistry",
|
|
175
|
+
method,
|
|
176
|
+
invocation: { kind: "direct" },
|
|
177
|
+
parameters: [{ name: "input", wire: "input", source: "json", codec: codec(method + "Input", input) }],
|
|
178
|
+
result: codec(method + "Result", output),
|
|
179
|
+
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
function findTextRange(text, query) {
|
|
183
|
+
const needle = query?.trim().toLowerCase();
|
|
184
|
+
if (!needle) return null;
|
|
185
|
+
const position = text.toLowerCase().indexOf(needle);
|
|
186
|
+
if (position < 0) return null;
|
|
187
|
+
let original = 0, folded = 0, start;
|
|
188
|
+
for (const character of text) {
|
|
189
|
+
const next = folded + character.toLowerCase().length;
|
|
190
|
+
if (start === void 0 && next > position) start = original;
|
|
191
|
+
original += character.length;
|
|
192
|
+
if (next >= position + needle.length) return { start: start ?? original, end: original };
|
|
193
|
+
folded = next;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
function sessionDetailCandidates(ids, byId) {
|
|
198
|
+
return [...new Set(ids)].map((id2) => byId[id2] ?? { id: id2 });
|
|
199
|
+
}
|
|
200
|
+
function dayBoundary(value, nextDay = false) {
|
|
201
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return NaN;
|
|
202
|
+
const [year, month, day] = value.split("-").map(Number);
|
|
203
|
+
const date = new Date(year, month - 1, day);
|
|
204
|
+
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return NaN;
|
|
205
|
+
if (nextDay) date.setDate(date.getDate() + 1);
|
|
206
|
+
return date.getTime();
|
|
207
|
+
}
|
|
208
|
+
function validUpdatedRange(from, to) {
|
|
209
|
+
return (!from || Number.isFinite(dayBoundary(from))) && (!to || Number.isFinite(dayBoundary(to))) && (!from || !to || from <= to);
|
|
210
|
+
}
|
|
211
|
+
function matchesUpdatedRange(value, from, to) {
|
|
212
|
+
if (!validUpdatedRange(from, to)) return false;
|
|
213
|
+
if (!from && !to) return true;
|
|
214
|
+
const time = typeof value === "number" ? value : Date.parse(value ?? "");
|
|
215
|
+
return Number.isFinite(time) && (!from || time >= dayBoundary(from)) && (!to || time < dayBoundary(to, true));
|
|
216
|
+
}
|
|
217
|
+
async function searchArchiveBatches(ids, query, call, { signal, onProgress } = {}) {
|
|
218
|
+
const items = [], failures = [];
|
|
219
|
+
const unique = [...new Set(ids)];
|
|
220
|
+
const check = () => {
|
|
221
|
+
if (signal?.aborted) throw new Error("\u641C\u7D22\u5DF2\u53D6\u6D88");
|
|
222
|
+
};
|
|
223
|
+
for (let start = 0; start < unique.length; start += 20) {
|
|
224
|
+
check();
|
|
225
|
+
const result = searchResultSchema.parse(await call({ sessionIds: unique.slice(start, start + 20), query }));
|
|
226
|
+
check();
|
|
227
|
+
items.push(...result.items);
|
|
228
|
+
failures.push(...result.failures);
|
|
229
|
+
onProgress?.({ done: Math.min(start + 20, unique.length), total: unique.length, items: [...items], failures: [...failures] });
|
|
230
|
+
}
|
|
231
|
+
check();
|
|
232
|
+
return { items, failures };
|
|
233
|
+
}
|
|
234
|
+
function classifySessionError(error) {
|
|
235
|
+
const message = errorMessage(error);
|
|
236
|
+
const descriptions = {
|
|
237
|
+
"repair-frame": ["\u65E7\u7248\u4FEE\u590D\u751F\u6210\u7684\u538B\u7F29\u683C\u5F0F\u4E0D\u7B26\u5408\u5BBF\u4E3B\u8981\u6C42", "\u91CD\u65B0\u8BCA\u65AD\u53EF\u7EA0\u6B63\u538B\u7F29\u5E27\u683C\u5F0F\uFF0C\u539F\u59CB\u65E5\u5FD7\u4FDD\u6301\u4E0D\u53D8\u3002"],
|
|
238
|
+
"legacy-source": ["\u65E7\u7248\u6D88\u606F\u6765\u6E90\u4E0D\u53D7\u65B0\u7248 DSH \u652F\u6301", "\u8FD0\u884C\u8BCA\u65AD\uFF0C\u68C0\u67E5\u662F\u5426\u4E3A\u53EF\u8F6C\u6362\u7684\u65E7\u81EA\u52A8\u5316\u6765\u6E90\u3002"],
|
|
239
|
+
missing: ["\u4F1A\u8BDD\u65E5\u5FD7\u6216\u9644\u4EF6\u8DEF\u5F84\u4E0D\u5B58\u5728", "\u68C0\u67E5\u539F\u76EE\u5F55\u6216\u78C1\u76D8\u662F\u5426\u53EF\u7528\uFF1B\u7F3A\u5931\u6B63\u6587\u4E0D\u80FD\u901A\u8FC7\u91CD\u5EFA\u7F13\u5B58\u6062\u590D\u3002"],
|
|
240
|
+
permission: ["\u6CA1\u6709\u6743\u9650\u8BFB\u53D6\u4F1A\u8BDD\u6587\u4EF6", "\u68C0\u67E5\u76EE\u5F55\u8BBF\u95EE\u6743\u9650\u3001\u6587\u4EF6\u5360\u7528\u4E0E\u5B89\u5168\u8F6F\u4EF6\u9650\u5236\uFF0C\u518D\u91CD\u8BD5\u3002"],
|
|
241
|
+
corrupt: ["\u4F1A\u8BDD\u65E5\u5FD7\u53EF\u80FD\u635F\u574F\u6216\u672A\u5B8C\u6574\u5199\u5165", "\u4FDD\u7559\u73B0\u6709\u65E5\u5FD7\uFF0C\u68C0\u67E5\u78C1\u76D8\u548C\u539F\u59CB\u6587\u4EF6\uFF1B\u4E0D\u81EA\u52A8\u622A\u65AD\u6216\u5220\u9664\u6D88\u606F\u3002"],
|
|
242
|
+
unknown: ["\u4F1A\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6", "\u5148\u91CD\u8BD5\uFF1B\u4ECD\u5931\u8D25\u65F6\u5C55\u5F00\u6280\u672F\u8BE6\u60C5\uFF0C\u6309\u5177\u4F53\u9519\u8BEF\u68C0\u67E5\u5BBF\u4E3B\u517C\u5BB9\u6027\u3002"]
|
|
243
|
+
};
|
|
244
|
+
const codes = { ENOENT: "missing", EACCES: "permission", EPERM: "permission" };
|
|
245
|
+
const patterns = [
|
|
246
|
+
["repair-frame", /first frame is not exactly one header line/],
|
|
247
|
+
["legacy-source", /unclassified message source/],
|
|
248
|
+
["missing", /ENOENT|不存在|not found/i],
|
|
249
|
+
["permission", /EACCES|EPERM|permission/i],
|
|
250
|
+
["corrupt", /corrupt|JSON|incomplete|truncat|损坏/i]
|
|
251
|
+
];
|
|
252
|
+
const rawCode = errorCode(error);
|
|
253
|
+
const explicit = typeof rawCode === "string" ? codes[rawCode] ?? rawCode : "";
|
|
254
|
+
const code = Object.hasOwn(descriptions, explicit) ? explicit : patterns.find(([, pattern]) => pattern.test(message))?.[0] ?? "unknown";
|
|
255
|
+
const [reason, advice] = descriptions[code];
|
|
256
|
+
return { code, reason, advice };
|
|
257
|
+
}
|
|
258
|
+
var repairInputSchema = { parse(input) {
|
|
259
|
+
const value = record(input);
|
|
260
|
+
const sessionId = id(value?.sessionId);
|
|
261
|
+
if (value?.token !== void 0 && (typeof value.token !== "string" || !/^[a-f0-9]{64}$/.test(value.token))) throw new TypeError("\u4FEE\u590D\u51ED\u636E\u65E0\u6548");
|
|
262
|
+
return { sessionId, ...value.token !== void 0 ? { token: value.token } : {} };
|
|
263
|
+
} };
|
|
264
|
+
var repairResultSchema = { parse(input) {
|
|
265
|
+
const value = record(input);
|
|
266
|
+
if (!value || typeof value.repairable !== "boolean" || typeof value.repaired !== "boolean") throw new TypeError("\u8BCA\u65AD\u7ED3\u679C\u65E0\u6548");
|
|
267
|
+
return { ...value.code !== void 0 ? { code: boundedString(value.code, 64) } : {}, sessionId: id(value.sessionId), repairable: value.repairable, repaired: value.repaired, reason: boundedString(value.reason, 1e3), advice: boundedString(value.advice, 1e3), token: boundedString(value.token ?? "", 64), count: sequence(value.count ?? 0) };
|
|
268
|
+
} };
|
|
269
|
+
|
|
270
|
+
// src/session-health-ui.ts
|
|
271
|
+
var defaultT = (key, args = {}) => Object.entries(args).reduce((text, [name, value]) => text.replaceAll("{" + name + "}", String(value)), healthZh[key] ?? key);
|
|
272
|
+
var sessionHealthCss = `
|
|
273
|
+
.dsham_health{margin:0 0 16px;font-size:13px;line-height:1.6;color:var(--dsw-alias-label-primary);--health-accent:var(--dsw-alias-state-business-primary,#507fe5);--health-warning:var(--dsw-alias-state-warn-label)}
|
|
274
|
+
.dsham_health p{margin:0}.dsham_healthPanel{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);overflow:hidden}
|
|
275
|
+
.dsham_healthSummary{display:flex;align-items:center;gap:10px;min-height:52px;padding:12px 16px;list-style:none;cursor:pointer;box-sizing:border-box}
|
|
276
|
+
.dsham_health summary::-webkit-details-marker{display:none}.dsham_health summary::marker{content:''}
|
|
277
|
+
.dsham_healthSummary:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
278
|
+
.dsham_healthIcon{display:grid;place-items:center;flex:none;width:28px;height:28px;border-radius:8px;background:color-mix(in srgb,var(--health-warning) 12%,transparent);color:var(--health-warning)}
|
|
279
|
+
.dsham_healthSummaryText{flex:1;min-width:0;font-weight:600}.dsham_healthCount{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;margin-left:8px;padding:0 6px;box-sizing:border-box;border-radius:6px;background:var(--dsw-alias-bg-layer-3);font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
280
|
+
.dsham_healthSummaryHint{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:400}.dsham_healthChevron{display:flex;transition:transform .15s ease}.dsham_healthPanel[open]>.dsham_healthSummary .dsham_healthChevron{transform:rotate(180deg)}
|
|
281
|
+
.dsham_healthBody{border-top:1px solid var(--dsw-alias-border-l2);padding:14px;display:grid;gap:10px}.dsham_healthIntro{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 2px 4px;color:var(--dsw-alias-label-secondary);font-size:12px}
|
|
282
|
+
.dsham_healthItem{padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-layer-3)}
|
|
283
|
+
.dsham_healthRow{display:flex;align-items:center;justify-content:space-between;gap:16px}.dsham_healthCopy{flex:1;min-width:0}.dsham_healthTitle{display:block;font-size:13px;font-weight:600;overflow-wrap:anywhere}.dsham_healthState{display:flex;align-items:center;gap:6px;margin-top:4px;font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
284
|
+
.dsham_healthState[data-state=ready]{color:var(--dsw-alias-label-primary)}.dsham_healthState[data-state=ready]>span{color:var(--health-accent)}.dsham_healthState[data-state=success]{color:var(--dsw-alias-state-success-primary,#60b58a)}
|
|
285
|
+
.dsham_healthButton{display:inline-flex;align-items:center;justify-content:center;gap:6px;flex:none;min-height:32px;padding:5px 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;white-space:nowrap;cursor:pointer;transition:background .15s,border-color .15s}
|
|
286
|
+
.dsham_healthButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-label-secondary)}.dsham_healthButton[data-primary=true]{background:var(--dsw-alias-button-primary-fill,#3169c6);border-color:transparent;color:var(--dsw-alias-label-primary-foreground,#fff)}.dsham_healthButton[data-primary=true]:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-button-primary-fill,#3169c6));border-color:transparent}.dsham_healthButton:disabled{opacity:.5;cursor:wait}.dsham_healthButton[data-subtle=true]{border-color:transparent;padding:3px 6px;min-height:28px;color:var(--dsw-alias-label-secondary)}
|
|
287
|
+
.dsham_healthAdvice{margin-top:10px!important;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:12px;overflow-wrap:anywhere}.dsham_healthTech{margin-top:10px;font-size:12px;color:var(--dsw-alias-label-secondary)}.dsham_healthTech>summary{display:inline-flex;gap:4px;align-items:center;min-height:24px;cursor:pointer}.dsham_healthTech[open]>summary .dsham_healthChevron{transform:rotate(180deg)}.dsham_healthLog{margin-top:8px;padding:10px;border-radius:6px;background:var(--dsw-alias-bg-layer-2);overflow-wrap:anywhere;font:11px/1.7 ui-monospace,monospace}.dsham_healthLog p+p{margin-top:6px}
|
|
288
|
+
.dsham_healthNotice{display:flex;align-items:center;gap:8px;padding:10px 12px;margin-bottom:10px!important;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-primary)}
|
|
289
|
+
.dsham_health button:focus-visible,.dsham_health summary:focus-visible{outline:2px solid var(--health-accent);outline-offset:3px}.dsham_health svg{flex:none}
|
|
290
|
+
@media(max-width:520px){.dsham_healthSummary{padding:12px}.dsham_healthSummaryHint{display:none}.dsham_healthBody{padding:10px}.dsham_healthItem{padding:12px}.dsham_healthRow{align-items:flex-start;flex-wrap:wrap;gap:12px}.dsham_healthCopy{flex-basis:65%}.dsham_healthButton{min-height:36px}.dsham_healthIntro{align-items:flex-start}.dsham_healthIntro>span{flex:1}}
|
|
291
|
+
@media(prefers-reduced-motion:reduce){.dsham_health *{transition:none!important}}
|
|
292
|
+
`;
|
|
293
|
+
function createSessionHealthPanel(React, icons = {}) {
|
|
294
|
+
const h = React.createElement;
|
|
295
|
+
const icon = (name, className) => icons[name] ? h("span", { className, "aria-hidden": true }, h(icons[name], { width: 16, height: 16 })) : null;
|
|
296
|
+
return function SessionHealthPanel({ items, sessions, t = defaultT, isArchived = true, diagnoseSession, repairSession, retry, pending }) {
|
|
297
|
+
const [results, setResults] = React.useState({});
|
|
298
|
+
const [busyId, setBusyId] = React.useState("");
|
|
299
|
+
const [notice, setNotice] = React.useState("");
|
|
300
|
+
const errors = items.filter((row) => row.error);
|
|
301
|
+
const run = async (row, repair) => {
|
|
302
|
+
if (busyId) return;
|
|
303
|
+
setBusyId(row.sessionId);
|
|
304
|
+
setNotice("");
|
|
305
|
+
try {
|
|
306
|
+
const result = await (repair && repairSession ? repairSession({ sessionId: row.sessionId, token: results[row.sessionId].token }) : diagnoseSession({ sessionId: row.sessionId }));
|
|
307
|
+
setResults((previous) => ({ ...previous, [row.sessionId]: result }));
|
|
308
|
+
if (result.repaired) {
|
|
309
|
+
setNotice(true);
|
|
310
|
+
retry();
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
setResults((previous) => ({ ...previous, [row.sessionId]: { repairable: false, code: "failed", reason: "", advice: errorMessage(error).slice(0, 1e3) } }));
|
|
314
|
+
} finally {
|
|
315
|
+
setBusyId("");
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
return h(
|
|
319
|
+
"div",
|
|
320
|
+
{ className: "dsham_health" },
|
|
321
|
+
h("style", null, sessionHealthCss),
|
|
322
|
+
notice && h("p", { role: "status", className: "dsham_healthNotice" }, icon("check"), t("health.notice")),
|
|
323
|
+
errors.length > 0 && h(
|
|
324
|
+
"details",
|
|
325
|
+
{ className: "dsham_healthPanel" },
|
|
326
|
+
h(
|
|
327
|
+
"summary",
|
|
328
|
+
{ className: "dsham_healthSummary" },
|
|
329
|
+
icon("warning", "dsham_healthIcon"),
|
|
330
|
+
h("span", { className: "dsham_healthSummaryText" }, t(isArchived ? "health.archived" : "health.unarchived"), h("span", { className: "dsham_healthCount" }, errors.length)),
|
|
331
|
+
h("span", { className: "dsham_healthSummaryHint" }, t("health.heading")),
|
|
332
|
+
icon("chevron", "dsham_healthChevron")
|
|
333
|
+
),
|
|
334
|
+
h(
|
|
335
|
+
"div",
|
|
336
|
+
{ className: "dsham_healthBody" },
|
|
337
|
+
h(
|
|
338
|
+
"div",
|
|
339
|
+
{ className: "dsham_healthIntro" },
|
|
340
|
+
h("span", null, t(isArchived ? "health.scopeArchived" : "health.scopeUnarchived")),
|
|
341
|
+
h("button", { type: "button", className: "dsham_healthButton", "data-subtle": true, disabled: pending || Boolean(busyId), onClick: retry }, icon("refresh"), t("health.retry"))
|
|
342
|
+
),
|
|
343
|
+
errors.map((row) => {
|
|
344
|
+
const diagnostic = classifySessionError(row.error);
|
|
345
|
+
const result = results[row.sessionId];
|
|
346
|
+
const code = result ? Object.hasOwn(healthZh, "health." + result.code + ".reason") ? result.code : result.repaired ? "repaired" : result.repairable ? "ready" : "blocked" : diagnostic.code;
|
|
347
|
+
const title = sessions.find((session) => session.id === row.sessionId);
|
|
348
|
+
const repairing = result?.repairable && repairSession;
|
|
349
|
+
return h(
|
|
350
|
+
"section",
|
|
351
|
+
{ key: row.sessionId, className: "dsham_healthItem", "aria-busy": busyId === row.sessionId },
|
|
352
|
+
h(
|
|
353
|
+
"div",
|
|
354
|
+
{ className: "dsham_healthRow" },
|
|
355
|
+
h(
|
|
356
|
+
"div",
|
|
357
|
+
{ className: "dsham_healthCopy" },
|
|
358
|
+
h("strong", { className: "dsham_healthTitle" }, title?.displayTitle || title?.title || row.sessionId),
|
|
359
|
+
h(
|
|
360
|
+
"div",
|
|
361
|
+
{ className: "dsham_healthState", "data-state": result?.repaired ? "success" : repairing ? "ready" : "pending", role: result ? "status" : void 0 },
|
|
362
|
+
icon(result?.repaired ? "check" : "info"),
|
|
363
|
+
t("health." + code + ".reason", { n: result?.count ?? 0 })
|
|
364
|
+
)
|
|
365
|
+
),
|
|
366
|
+
diagnoseSession && h(
|
|
367
|
+
"button",
|
|
368
|
+
{ type: "button", className: "dsham_healthButton", "data-primary": Boolean(repairing), disabled: Boolean(busyId), onClick: () => run(row, Boolean(repairing)) },
|
|
369
|
+
icon(busyId === row.sessionId ? "refresh" : repairing ? "check" : "search"),
|
|
370
|
+
t(busyId === row.sessionId ? "health.busy" : repairing ? "health.confirm" : "health.diagnose")
|
|
371
|
+
)
|
|
372
|
+
),
|
|
373
|
+
result && h("p", { className: "dsham_healthAdvice" }, t("health." + code + ".advice")),
|
|
374
|
+
!result && diagnostic.code !== "legacy-source" && h("p", { className: "dsham_healthAdvice" }, t("health." + code + ".advice")),
|
|
375
|
+
h(
|
|
376
|
+
"details",
|
|
377
|
+
{ className: "dsham_healthTech" },
|
|
378
|
+
h("summary", null, icon("chevron", "dsham_healthChevron"), t("health.technical")),
|
|
379
|
+
h("div", { className: "dsham_healthLog" }, h("p", null, row.sessionId), h("p", null, row.error), result?.reason && h("p", null, result.reason), result?.advice && h("p", null, result.advice))
|
|
380
|
+
)
|
|
381
|
+
);
|
|
382
|
+
})
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
);
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/archive-discovery-ui.ts
|
|
390
|
+
function createDiscoveryTools(React) {
|
|
391
|
+
const h = React.createElement;
|
|
392
|
+
function HighlightedText({ text, query = "" }) {
|
|
393
|
+
const match = findTextRange(text, query);
|
|
394
|
+
return !match ? text : h(React.Fragment, null, text.slice(0, match.start), h("mark", null, text.slice(match.start, match.end)), text.slice(match.end));
|
|
395
|
+
}
|
|
396
|
+
function useArchiveSearch(ids, query, enabled, call) {
|
|
397
|
+
const idsKey = JSON.stringify(ids);
|
|
398
|
+
const key = JSON.stringify([idsKey, query]);
|
|
399
|
+
const [revision, setRevision] = React.useState(0);
|
|
400
|
+
const [state, setState] = React.useState({ key: "", status: "idle", items: [], failures: [] });
|
|
401
|
+
React.useEffect(() => {
|
|
402
|
+
if (!enabled || !query.trim() || !call) return;
|
|
403
|
+
const controller = new AbortController();
|
|
404
|
+
setState({ key, status: "loading", items: [], failures: [], done: 0, total: ids.length });
|
|
405
|
+
const timer = setTimeout(() => {
|
|
406
|
+
searchArchiveBatches(JSON.parse(idsKey), query, call, { signal: controller.signal, onProgress: (progress) => {
|
|
407
|
+
if (!controller.signal.aborted) setState({ key, status: "loading", ...progress });
|
|
408
|
+
} }).then((result) => {
|
|
409
|
+
if (!controller.signal.aborted) setState({ key, status: "ready", done: ids.length, total: ids.length, ...result });
|
|
410
|
+
}).catch((error) => {
|
|
411
|
+
if (!controller.signal.aborted) setState((previous) => ({ ...previous, key, status: "error", error: errorMessage(error) }));
|
|
412
|
+
});
|
|
413
|
+
}, 350);
|
|
414
|
+
return () => {
|
|
415
|
+
controller.abort();
|
|
416
|
+
clearTimeout(timer);
|
|
417
|
+
};
|
|
418
|
+
}, [idsKey, query, enabled, call, revision]);
|
|
419
|
+
const active = enabled && query.trim() && call;
|
|
420
|
+
return { ...active ? state.key === key ? state : { key, status: "loading", items: [], failures: [], done: 0, total: ids.length } : { status: "idle", items: [], failures: [] }, retry: () => setRevision((value) => value + 1) };
|
|
421
|
+
}
|
|
422
|
+
function useSessionDetails(sessions, call, t) {
|
|
423
|
+
const key = JSON.stringify(sessions.map((session) => [session.id, session.updatedAt]));
|
|
424
|
+
const [revision, setRevision] = React.useState(0);
|
|
425
|
+
const [state, setState] = React.useState({ key: "", items: [], pending: false });
|
|
426
|
+
React.useEffect(() => {
|
|
427
|
+
if (!call) return;
|
|
428
|
+
let active = true;
|
|
429
|
+
const ids = [...new Set(JSON.parse(key).map((row) => row[0]))];
|
|
430
|
+
setState({ key, items: [], pending: ids.length > 0 });
|
|
431
|
+
const load = async () => {
|
|
432
|
+
const items2 = [];
|
|
433
|
+
for (let start = 0; start < ids.length && active; start += 20) {
|
|
434
|
+
const batch = ids.slice(start, start + 20);
|
|
435
|
+
try {
|
|
436
|
+
const result = detailsResultSchema.parse(await call({ sessionIds: batch }));
|
|
437
|
+
const found = new Map(result.items.map((row) => [row.sessionId, row]));
|
|
438
|
+
items2.push(...batch.map((sessionId) => found.get(sessionId) ?? { sessionId, turnCount: null, path: null, error: "", errorKey: "details.notReturned" }));
|
|
439
|
+
} catch (error) {
|
|
440
|
+
items2.push(...batch.map((sessionId) => ({ sessionId, turnCount: null, path: null, error: errorMessage(error) })));
|
|
441
|
+
}
|
|
442
|
+
if (active) setState({ key, items: [...items2], pending: start + 20 < ids.length });
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
load();
|
|
446
|
+
return () => {
|
|
447
|
+
active = false;
|
|
448
|
+
};
|
|
449
|
+
}, [key, call, revision]);
|
|
450
|
+
const current = call && state.key === key ? state : { items: [], pending: Boolean(call && sessions.length) };
|
|
451
|
+
const items = current.items.map((row) => row.errorKey ? { ...row, error: t ? t(row.errorKey) : row.errorKey } : row);
|
|
452
|
+
return { ...current, items, byId: Object.fromEntries(items.map((row) => [row.sessionId, row])), retry: () => setRevision((value) => value + 1) };
|
|
453
|
+
}
|
|
454
|
+
function useArchivePreview(call, eligibleIds) {
|
|
455
|
+
const [target, setTarget] = React.useState(null);
|
|
456
|
+
const [state, setState] = React.useState({ status: "idle" });
|
|
457
|
+
const [revision, setRevision] = React.useState(0);
|
|
458
|
+
const key = target;
|
|
459
|
+
const available = target && eligibleIds.includes(target.session.id);
|
|
460
|
+
React.useEffect(() => {
|
|
461
|
+
if (target && !available) setTarget(null);
|
|
462
|
+
}, [target, available]);
|
|
463
|
+
React.useEffect(() => {
|
|
464
|
+
if (!available || typeof window === "undefined") return;
|
|
465
|
+
const onKeyDown = (event) => {
|
|
466
|
+
if (event.key !== "Escape") return;
|
|
467
|
+
event.preventDefault();
|
|
468
|
+
event.stopPropagation();
|
|
469
|
+
event.stopImmediatePropagation();
|
|
470
|
+
setTarget(null);
|
|
471
|
+
};
|
|
472
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
473
|
+
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
474
|
+
}, [available]);
|
|
475
|
+
React.useEffect(() => {
|
|
476
|
+
if (!target || !available || !call) return;
|
|
477
|
+
let active = true;
|
|
478
|
+
setState({ key, status: "loading" });
|
|
479
|
+
Promise.resolve().then(() => call({ sessionId: target.session.id, query: target.query })).then((value) => {
|
|
480
|
+
if (active) setState({ key, status: "ready", value });
|
|
481
|
+
}).catch((error) => {
|
|
482
|
+
if (active) setState({ key, status: "error", error: errorMessage(error) });
|
|
483
|
+
});
|
|
484
|
+
return () => {
|
|
485
|
+
active = false;
|
|
486
|
+
};
|
|
487
|
+
}, [key, available, call, revision]);
|
|
488
|
+
return { target: available ? target : null, ...state.key === key ? state : { status: "loading" }, open: (session, query = "") => setTarget({ session, query }), close: () => setTarget(null), retry: () => setRevision((value) => value + 1) };
|
|
489
|
+
}
|
|
490
|
+
function DiscoveryFilters({ t, from, to, onFrom, onTo, invalid, onClear }) {
|
|
491
|
+
const rootRef = React.useRef(null);
|
|
492
|
+
React.useEffect(() => {
|
|
493
|
+
const root = rootRef.current;
|
|
494
|
+
if (!root) return;
|
|
495
|
+
const onPointerDown = (event) => {
|
|
496
|
+
if (root.open && !root.contains(event.target)) root.open = false;
|
|
497
|
+
};
|
|
498
|
+
root.ownerDocument.addEventListener("pointerdown", onPointerDown, true);
|
|
499
|
+
return () => root.ownerDocument.removeEventListener("pointerdown", onPointerDown, true);
|
|
500
|
+
}, []);
|
|
501
|
+
const active = Boolean(from || to);
|
|
502
|
+
const range = active ? `${from || "\u2026"} \uFF5E ${to || "\u2026"}` : t("discovery.date");
|
|
503
|
+
return h(
|
|
504
|
+
"details",
|
|
505
|
+
{ className: "dsham_dateFilter", ref: rootRef, onKeyDown: (event) => {
|
|
506
|
+
if (event.key === "Escape" && event.currentTarget.open) {
|
|
507
|
+
event.preventDefault();
|
|
508
|
+
event.stopPropagation();
|
|
509
|
+
event.currentTarget.open = false;
|
|
510
|
+
event.currentTarget.querySelector("summary")?.focus();
|
|
511
|
+
}
|
|
512
|
+
} },
|
|
513
|
+
h(
|
|
514
|
+
"summary",
|
|
515
|
+
{ title: range, "aria-label": t("discovery.date") + (active ? t("common.separator") + range : ""), "data-active": active },
|
|
516
|
+
h(
|
|
517
|
+
"svg",
|
|
518
|
+
{ width: 14, height: 14, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "aria-hidden": true },
|
|
519
|
+
h("rect", { x: 2, y: 3.5, width: 12, height: 10.5, rx: 2 }),
|
|
520
|
+
h("path", { d: "M5 1.5v4M11 1.5v4M2 7h12" })
|
|
521
|
+
),
|
|
522
|
+
h("span", null, active ? t("discovery.dateActive") : t("discovery.date"))
|
|
523
|
+
),
|
|
524
|
+
h(
|
|
525
|
+
"div",
|
|
526
|
+
{ className: "dsham_datePanel" },
|
|
527
|
+
h("label", null, t("discovery.from"), h("input", { type: "date", value: from, max: to || void 0, onChange: (event) => onFrom(event.currentTarget.value) })),
|
|
528
|
+
h("label", null, t("discovery.to"), h("input", { type: "date", value: to, min: from || void 0, onChange: (event) => onTo(event.currentTarget.value) })),
|
|
529
|
+
invalid && h("p", { role: "alert" }, t("discovery.invalidDate")),
|
|
530
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: !active, onClick: onClear }, t("discovery.clearDate"))
|
|
531
|
+
)
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
function SearchStatus({ state, t }) {
|
|
535
|
+
if (state.status === "idle") return null;
|
|
536
|
+
return h(
|
|
537
|
+
"div",
|
|
538
|
+
{ className: "dsham_discoveryStatus", role: "status", "aria-live": "polite" },
|
|
539
|
+
h("p", null, t(state.status === "loading" ? "discovery.searching" : state.status === "error" ? "discovery.searchError" : "discovery.searched", { done: state.done ?? 0, total: state.total ?? 0 })),
|
|
540
|
+
state.status === "error" && h("p", null, state.error),
|
|
541
|
+
state.failures.length > 0 && h("details", null, h("summary", null, t("discovery.failed", { n: state.failures.length })), h("ul", null, state.failures.map((row) => h("li", { key: row.sessionId }, row.sessionId, t("common.separator"), row.message)))),
|
|
542
|
+
(state.status === "error" || state.status === "ready" && state.failures.length > 0) && h("button", { type: "button", className: "dsham_settingsAction", onClick: state.retry }, t("discovery.retry"))
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
function PreviewContent({ preview, t, MarkdownText }) {
|
|
546
|
+
const [raw, setRaw] = React.useState(false);
|
|
547
|
+
if (preview.status === "loading") return h("p", { role: "status" }, t("discovery.loading"));
|
|
548
|
+
if (preview.status === "error") return h("div", null, h("p", { role: "alert" }, preview.error), h("button", { type: "button", className: "dsham_settingsAction", onClick: preview.retry }, t("discovery.retry")));
|
|
549
|
+
const value = preview.value;
|
|
550
|
+
if (!value) return null;
|
|
551
|
+
return h(
|
|
552
|
+
"div",
|
|
553
|
+
{ className: "dsham_previewMessages" },
|
|
554
|
+
h(
|
|
555
|
+
"div",
|
|
556
|
+
{ className: "dsham_previewToolbar" },
|
|
557
|
+
h("span", { title: t("discovery.previewHint") }, t("discovery.readOnly"), " \xB7 ", t("discovery.messageCount", { n: value.messages.length })),
|
|
558
|
+
MarkdownText && h(
|
|
559
|
+
"div",
|
|
560
|
+
{ className: "dsham_previewModes", role: "group", "aria-label": t("discovery.displayMode") },
|
|
561
|
+
h("button", { type: "button", "aria-pressed": !raw, onClick: () => setRaw(false) }, t("discovery.formatted")),
|
|
562
|
+
h("button", { type: "button", "aria-pressed": raw, onClick: () => setRaw(true) }, t("discovery.raw"))
|
|
563
|
+
)
|
|
564
|
+
),
|
|
565
|
+
value.hasEarlier && h("p", null, t("discovery.earlier")),
|
|
566
|
+
!value.messages.length && h("p", null, t("discovery.empty")),
|
|
567
|
+
value.messages.map((row) => h("article", { key: row.seq, className: "dsham_previewMessage" }, h("div", { className: "dsham_previewRole", "data-role": row.role }, h("span", { "aria-hidden": true }, t(row.role === "user" ? "discovery.you" : "discovery.ai")), h("strong", null, t("discovery." + row.role))), raw || !MarkdownText ? h("pre", { className: "dsham_previewRaw" }, h(HighlightedText, { text: row.text, query: preview.target?.query })) : h(MarkdownText, { text: row.text, streaming: false, labels: { code: { copyLabel: t("discovery.copyCode"), copiedLabel: t("details.copied") }, footnotes: t("discovery.footnotes") } }), row.truncated && h("small", null, t("discovery.truncated")))),
|
|
568
|
+
value.hasLater && h("p", null, t("discovery.later"))
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
return { HighlightedText, useSessionDetails, useArchiveSearch, useArchivePreview, DiscoveryFilters, SearchStatus, PreviewContent };
|
|
572
|
+
}
|
|
573
|
+
var discoveryCss = ".dsham_settingsToolbar{grid-template-columns:repeat(3,minmax(0,1fr))}.dsham_settingsSearch{grid-column:1/-1;gap:8px;padding:0 8px;height:36px}.dsham_searchScope{flex:none;width:112px;border-right:1px solid var(--dsw-alias-border-l2);padding-right:4px}.dsham_searchScope .dsham_selectTrigger{min-height:26px;padding:0 4px;border:0;border-radius:4px;background:transparent;font-size:12px}.dsham_searchScope .dsham_selectMenu{width:144px;right:auto;top:calc(100% + 8px)}.dsham_dateFilter{position:relative;flex:none;color:var(--dsw-alias-label-secondary);font-size:12px}.dsham_dateFilter summary{display:flex;align-items:center;gap:5px;list-style:none;cursor:pointer;padding:5px 2px 5px 8px;border-left:1px solid var(--dsw-alias-border-l2);white-space:nowrap}.dsham_dateFilter summary::-webkit-details-marker{display:none}.dsham_dateFilter summary[data-active=true]{color:var(--dsw-alias-state-business-primary)}.dsham_datePanel{position:absolute;right:0;top:calc(100% + 8px);z-index:35;display:grid;gap:12px;width:240px;box-sizing:border-box;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3)}.dsham_datePanel label{display:grid;gap:6px}.dsham_settingsSearch .dsham_datePanel input{box-sizing:border-box;max-width:100%;min-width:0;height:32px;padding:4px 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit}.dsham_datePanel p{margin:0}.dsham_searchScope:focus-visible,.dsham_dateFilter summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dsham_discoveryStatus{font-size:12px;margin-bottom:12px;overflow-wrap:anywhere}.dsham_settingsSnippet{display:block;width:100%;padding:0;margin:4px 0 0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}.dsham_previewDialog[role=dialog]{width:min(900px,calc(100vw - 48px));max-height:calc(100dvh - 48px);gap:12px}.dsham_previewDialogContent{min-height:0;overflow:auto}.dsham_previewMessages{max-height:65vh;overflow:auto;overflow-wrap:anywhere;padding-right:8px}.dsham_previewToolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;color:var(--dsw-alias-label-secondary);font-size:12px}.dsham_previewModes{display:flex;gap:4px}.dsham_previewModes button{padding:5px 10px;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;font:inherit;cursor:pointer;white-space:nowrap}.dsham_previewModes button[aria-pressed=true]{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}.dsham_previewRole{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:13px}.dsham_previewRole>span{display:grid;place-items:center;width:28px;height:28px;border-radius:8px;background:var(--dsw-alias-bg-layer-3);font-size:11px}.dsham_previewRole[data-role=user]>span{color:var(--dsw-alias-state-business-primary)}.dsham_previewRaw{white-space:pre-wrap;font:13px/1.8 ui-monospace,monospace;overflow-wrap:anywhere}.dsham_previewMessage pre:not(.dsham_previewRaw){white-space:pre;overflow-x:auto;max-width:100%}.dsham_previewMessage table{display:block;max-width:100%;overflow-x:auto}.dsham_previewMessage img{max-width:100%}@media(max-width:520px){.dsham_previewDialog[role=dialog]{width:calc(100vw - 32px)}.dsham_previewToolbar{align-items:flex-start;flex-wrap:wrap}}.dsham_previewMessage{padding:18px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_previewMessage p{font-size:14px;line-height:1.8}.dsham_previewHint,.dsham_previewMessage small{color:var(--dsw-alias-label-secondary);font-size:12px}.dsham_settings mark,.dsham_previewMessages mark{background:var(--dsw-alias-state-warn-tertiary);color:inherit;border-radius:2px}.dsham_settingsSnippet:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}";
|
|
574
|
+
var discoveryZh = {
|
|
575
|
+
"common.separator": "\uFF1A",
|
|
576
|
+
"details.notReturned": "\u5BBF\u4E3B\u672A\u8FD4\u56DE\u4F1A\u8BDD\u8BE6\u60C5",
|
|
577
|
+
"copy.empty": "\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9",
|
|
578
|
+
"copy.unavailable": "\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301\u526A\u8D34\u677F\uFF0C\u8BF7\u5728 HTTPS \u6216\u672C\u673A\u5730\u5740\u4E2D\u6253\u5F00\u9875\u9762",
|
|
579
|
+
"copy.denied": "\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u5141\u8BB8\u6D4F\u89C8\u5668\u8BBF\u95EE\u526A\u8D34\u677F\u540E\u91CD\u8BD5",
|
|
580
|
+
"discovery.you": "\u4F60",
|
|
581
|
+
"discovery.ai": "AI",
|
|
582
|
+
"discovery.readOnly": "\u53EA\u8BFB\u9884\u89C8",
|
|
583
|
+
"discovery.messageCount": "\u672C\u6B21\u663E\u793A {n} \u6761\u6D88\u606F",
|
|
584
|
+
"discovery.displayMode": "\u663E\u793A\u65B9\u5F0F",
|
|
585
|
+
"discovery.formatted": "\u6392\u7248",
|
|
586
|
+
"discovery.raw": "\u539F\u6587\u4E0E\u9AD8\u4EAE",
|
|
587
|
+
"discovery.copyCode": "\u590D\u5236\u4EE3\u7801",
|
|
588
|
+
"discovery.footnotes": "\u6CE8\u91CA",
|
|
589
|
+
"details.turns": "{n} \u8F6E",
|
|
590
|
+
"details.unknown": "\u8F6E\u6B21\u672A\u77E5",
|
|
591
|
+
"details.pending": "\u8F6E\u6B21\u8BFB\u53D6\u4E2D",
|
|
592
|
+
"details.hint": "\u6309\u7528\u6237\u63D0\u4EA4\u6D88\u606F\u6570\u7EDF\u8BA1\uFF0C\u4E0D\u542B\u5DE5\u5177\u8C03\u7528\u548C\u63D2\u4EF6\u6CE8\u5165",
|
|
593
|
+
"details.more": "\u8F6E\u6B21\u6700\u591A",
|
|
594
|
+
"details.less": "\u8F6E\u6B21\u6700\u5C11",
|
|
595
|
+
"details.failed": "{n} \u6761\u4F1A\u8BDD\u8BE6\u60C5\u8BFB\u53D6\u5931\u8D25",
|
|
596
|
+
"details.copyId": "\u590D\u5236\u4F1A\u8BDD ID",
|
|
597
|
+
"details.copyPath": "\u590D\u5236\u4F1A\u8BDD\u8DEF\u5F84",
|
|
598
|
+
"details.copied": "\u5DF2\u590D\u5236",
|
|
599
|
+
"details.noPath": "\u5BBF\u4E3B\u672A\u63D0\u4F9B\u53EF\u590D\u5236\u7684\u4F1A\u8BDD\u8DEF\u5F84",
|
|
600
|
+
"discovery.date": "\u65E5\u671F",
|
|
601
|
+
"discovery.dateActive": "\u65E5\u671F\xB7\u5DF2\u9009",
|
|
602
|
+
"discovery.clearDate": "\u6E05\u9664\u65E5\u671F",
|
|
603
|
+
"discovery.active": "\u5DF2\u542F\u7528",
|
|
604
|
+
"discovery.scope": "\u67E5\u627E\u8303\u56F4",
|
|
605
|
+
"discovery.titleOnly": "\u4EC5\u6807\u9898",
|
|
606
|
+
"discovery.titleAndContent": "\u6807\u9898\u4E0E\u6B63\u6587",
|
|
607
|
+
"discovery.from": "\u66F4\u65B0\u65F6\u95F4\u4ECE",
|
|
608
|
+
"discovery.to": "\u81F3",
|
|
609
|
+
"discovery.clear": "\u6E05\u9664\u6761\u4EF6",
|
|
610
|
+
"discovery.invalidDate": "\u5F00\u59CB\u65E5\u671F\u4E0D\u80FD\u665A\u4E8E\u7ED3\u675F\u65E5\u671F\uFF0C\u8BF7\u68C0\u67E5\u65E5\u671F\u8303\u56F4\u3002",
|
|
611
|
+
"discovery.searching": "\u6B63\u5728\u68C0\u7D22\u6B63\u6587\uFF1A{done} / {total}",
|
|
612
|
+
"discovery.searched": "\u6B63\u6587\u68C0\u7D22\u5B8C\u6210\uFF1A{done} / {total}",
|
|
613
|
+
"discovery.searchError": "\u6B63\u6587\u68C0\u7D22\u672A\u5B8C\u6210\uFF0C\u5F53\u524D\u7ED3\u679C\u53EF\u80FD\u4E0D\u5B8C\u6574\u3002",
|
|
614
|
+
"discovery.failed": "{n} \u6761\u4F1A\u8BDD\u8BFB\u53D6\u5931\u8D25",
|
|
615
|
+
"discovery.retry": "\u91CD\u8BD5",
|
|
616
|
+
"discovery.preview": "\u5FEB\u901F\u9884\u89C8",
|
|
617
|
+
"discovery.loading": "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u2026",
|
|
618
|
+
"discovery.previewHint": "\u53EA\u8BFB\u9884\u89C8\u539F\u59CB\u5BF9\u8BDD\u6587\u672C\uFF0C\u4E0D\u6062\u590D\u4F1A\u8BDD\uFF1B\u4E0D\u542B\u5DE5\u5177\u8F93\u51FA\u3001\u9644\u4EF6\u3001\u63A8\u7406\u548C\u7CFB\u7EDF\u5185\u5BB9\u3002",
|
|
619
|
+
"discovery.earlier": "\u524D\u9762\u8FD8\u6709\u6D88\u606F\uFF0C\u53EF\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B\u3002",
|
|
620
|
+
"discovery.later": "\u540E\u9762\u8FD8\u6709\u6D88\u606F\uFF0C\u53EF\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B\u3002",
|
|
621
|
+
"discovery.empty": "\u6CA1\u6709\u53EF\u9884\u89C8\u7684\u7528\u6237\u6216\u52A9\u624B\u6587\u672C\u3002",
|
|
622
|
+
"discovery.truncated": "\u672C\u6761\u4EC5\u663E\u793A\u90E8\u5206\u5185\u5BB9\u3002",
|
|
623
|
+
"discovery.user": "\u7528\u6237",
|
|
624
|
+
"discovery.assistant": "\u52A9\u624B",
|
|
625
|
+
"discovery.openFull": "\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD",
|
|
626
|
+
"discovery.searchPlaceholder": "\u641C\u7D22\u6807\u9898\u6216\u6B63\u6587"
|
|
627
|
+
};
|
|
628
|
+
var discoveryEn = {
|
|
629
|
+
"common.separator": ": ",
|
|
630
|
+
"details.notReturned": "The host did not return session details",
|
|
631
|
+
"copy.empty": "Nothing to copy",
|
|
632
|
+
"copy.unavailable": "Clipboard unavailable. Open the page over HTTPS or localhost.",
|
|
633
|
+
"copy.denied": "Copy failed. Allow clipboard access and retry.",
|
|
634
|
+
"discovery.you": "You",
|
|
635
|
+
"discovery.ai": "AI",
|
|
636
|
+
"discovery.readOnly": "Read-only preview",
|
|
637
|
+
"discovery.messageCount": "Showing {n} messages",
|
|
638
|
+
"discovery.displayMode": "Display mode",
|
|
639
|
+
"discovery.formatted": "Formatted",
|
|
640
|
+
"discovery.raw": "Source and highlights",
|
|
641
|
+
"discovery.copyCode": "Copy code",
|
|
642
|
+
"discovery.footnotes": "Footnotes",
|
|
643
|
+
"details.turns": "{n} turns",
|
|
644
|
+
"details.unknown": "Unknown turns",
|
|
645
|
+
"details.pending": "Loading turns",
|
|
646
|
+
"details.hint": "User submissions; excludes tool calls and injected messages",
|
|
647
|
+
"details.more": "Most turns",
|
|
648
|
+
"details.less": "Fewest turns",
|
|
649
|
+
"details.failed": "Could not read turns for {n} sessions",
|
|
650
|
+
"details.copyId": "Copy session ID",
|
|
651
|
+
"details.copyPath": "Copy session path",
|
|
652
|
+
"details.copied": "Copied",
|
|
653
|
+
"details.noPath": "The host did not provide a session path",
|
|
654
|
+
"discovery.date": "Date",
|
|
655
|
+
"discovery.dateActive": "Date \xB7 Set",
|
|
656
|
+
"discovery.clearDate": "Clear dates",
|
|
657
|
+
"discovery.active": "Active",
|
|
658
|
+
"discovery.scope": "Search in",
|
|
659
|
+
"discovery.titleOnly": "Titles",
|
|
660
|
+
"discovery.titleAndContent": "Titles and content",
|
|
661
|
+
"discovery.from": "Updated from",
|
|
662
|
+
"discovery.to": "To",
|
|
663
|
+
"discovery.clear": "Clear filters",
|
|
664
|
+
"discovery.invalidDate": "Check the date range: the start must not be after the end.",
|
|
665
|
+
"discovery.searching": "Searching content: {done} / {total}",
|
|
666
|
+
"discovery.searched": "Content search complete: {done} / {total}",
|
|
667
|
+
"discovery.searchError": "Content search is incomplete; results may be missing.",
|
|
668
|
+
"discovery.failed": "Could not read {n} conversations",
|
|
669
|
+
"discovery.retry": "Retry",
|
|
670
|
+
"discovery.preview": "Quick preview",
|
|
671
|
+
"discovery.loading": "Reading conversation\u2026",
|
|
672
|
+
"discovery.previewHint": "Read-only original conversation text; keeps the conversation archived. Excludes tools, attachments, reasoning and system content.",
|
|
673
|
+
"discovery.earlier": "More messages before this preview. Open the full conversation to read them.",
|
|
674
|
+
"discovery.later": "More messages after this preview. Open the full conversation to read them.",
|
|
675
|
+
"discovery.empty": "No user or assistant text to preview.",
|
|
676
|
+
"discovery.truncated": "Only part of this message is shown.",
|
|
677
|
+
"discovery.user": "User",
|
|
678
|
+
"discovery.assistant": "Assistant",
|
|
679
|
+
"discovery.openFull": "Open full conversation",
|
|
680
|
+
"discovery.searchPlaceholder": "Search titles or content"
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/archive-experience.ts
|
|
3
684
|
var ArchiveNavigationError = class extends Error {
|
|
685
|
+
code;
|
|
4
686
|
constructor(code) {
|
|
5
687
|
super(code);
|
|
6
688
|
this.name = "ArchiveNavigationError";
|
|
@@ -8,28 +690,32 @@
|
|
|
8
690
|
}
|
|
9
691
|
};
|
|
10
692
|
function formatArchiveNavigationError(error, t) {
|
|
11
|
-
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) :
|
|
693
|
+
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) : errorMessage(error);
|
|
12
694
|
}
|
|
13
|
-
function retainInfoSnapshot(sessions,
|
|
695
|
+
function retainInfoSnapshot(sessions, id2) {
|
|
14
696
|
if (typeof sessions?.retainInfo !== "function") return;
|
|
15
|
-
const source = sessions.retainInfo(
|
|
16
|
-
|
|
697
|
+
const source = sessions.retainInfo(id2);
|
|
698
|
+
const value = source && typeof source === "object" && "getSnapshot" in source && typeof source.getSnapshot === "function" ? source.getSnapshot() : source;
|
|
699
|
+
if (!value || typeof value !== "object" || !("retainedBy" in value)) return;
|
|
700
|
+
const retainedBy = value.retainedBy;
|
|
701
|
+
if (!retainedBy || typeof retainedBy !== "object" || !("mainView" in retainedBy) || typeof retainedBy.mainView !== "number") return;
|
|
702
|
+
return { retainedBy: { mainView: retainedBy.mainView } };
|
|
17
703
|
}
|
|
18
704
|
function mainViewSessionId(list) {
|
|
19
705
|
const byId = list?.byId;
|
|
20
706
|
if (byId === void 0) return;
|
|
21
707
|
for (const session of Object.values(byId)) {
|
|
22
|
-
if ((session
|
|
708
|
+
if (session && (session.retainedBy?.mainView ?? 0) > 0) return session.id;
|
|
23
709
|
}
|
|
24
710
|
}
|
|
25
711
|
function currentSessionId(list) {
|
|
26
712
|
return mainViewSessionId(list) ?? list?.current;
|
|
27
713
|
}
|
|
28
|
-
function sessionIsCurrent(list,
|
|
29
|
-
if (
|
|
30
|
-
if ((list?.byId?.[
|
|
31
|
-
if ((retainInfoSnapshot(sessions,
|
|
32
|
-
return list?.current ===
|
|
714
|
+
function sessionIsCurrent(list, id2, sessions) {
|
|
715
|
+
if (id2 === void 0 || id2 === "") return false;
|
|
716
|
+
if ((list?.byId?.[id2]?.retainedBy?.mainView ?? 0) > 0) return true;
|
|
717
|
+
if ((retainInfoSnapshot(sessions, id2)?.retainedBy?.mainView ?? 0) > 0) return true;
|
|
718
|
+
return list?.current === id2;
|
|
33
719
|
}
|
|
34
720
|
async function openArchivedConversation(actions, sessionId, restore, isActive = () => true) {
|
|
35
721
|
if (restore) {
|
|
@@ -44,14 +730,14 @@
|
|
|
44
730
|
let allowed;
|
|
45
731
|
const original = navigation?.clearArchivedCurrent;
|
|
46
732
|
const descriptor = navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent");
|
|
47
|
-
const viewing = (
|
|
733
|
+
const viewing = (id2) => sessionIsCurrent(sessions.list.getSnapshot(), id2, sessions);
|
|
48
734
|
const wrapped = function(...args) {
|
|
49
735
|
if (allowed !== void 0 && viewing(allowed) && workspaces.list.getSnapshot().archivedSessionIds.includes(allowed)) return false;
|
|
50
736
|
allowed = void 0;
|
|
51
|
-
return original
|
|
737
|
+
return original?.apply(this, args);
|
|
52
738
|
};
|
|
53
739
|
const ownsWrapper = () => navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent")?.value === wrapped;
|
|
54
|
-
if (typeof original === "function") {
|
|
740
|
+
if (navigation && typeof original === "function") {
|
|
55
741
|
try {
|
|
56
742
|
navigation.clearArchivedCurrent = wrapped;
|
|
57
743
|
if (!ownsWrapper()) throw new Error("\u5BFC\u822A\u65B9\u6CD5\u672A\u63A5\u7EB3\u5F52\u6863\u9002\u914D");
|
|
@@ -60,22 +746,22 @@
|
|
|
60
746
|
}
|
|
61
747
|
}
|
|
62
748
|
return {
|
|
63
|
-
open(
|
|
64
|
-
allowed =
|
|
749
|
+
open(id2) {
|
|
750
|
+
allowed = id2;
|
|
65
751
|
try {
|
|
66
|
-
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(
|
|
752
|
+
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(id2)) {
|
|
67
753
|
warn("archive-manager: \u5F52\u6863\u5BFC\u822A\u9002\u914D\u4E0D\u53EF\u7528\u6216\u5DF2\u88AB\u66FF\u6362\u3002");
|
|
68
754
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
69
755
|
}
|
|
70
756
|
beginNavigation?.();
|
|
71
|
-
if (typeof sessions.retain === "function" && typeof navigation?.openSession === "function") navigation.openSession(
|
|
72
|
-
else if (typeof sessions.open === "function") sessions.open(
|
|
73
|
-
else if (typeof navigation?.openSession === "function") navigation.openSession(
|
|
757
|
+
if (typeof sessions.retain === "function" && typeof navigation?.openSession === "function") navigation.openSession(id2);
|
|
758
|
+
else if (typeof sessions.open === "function") sessions.open(id2);
|
|
759
|
+
else if (typeof navigation?.openSession === "function") navigation.openSession(id2);
|
|
74
760
|
else {
|
|
75
761
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u63D0\u4F9B\u4F1A\u8BDD\u6253\u5F00\u63A5\u53E3\u3002");
|
|
76
762
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
77
763
|
}
|
|
78
|
-
if (!viewing(
|
|
764
|
+
if (!viewing(id2)) {
|
|
79
765
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\u3002", { cleanupAvailable: typeof original === "function" });
|
|
80
766
|
throw new ArchiveNavigationError("sessionNotRetained");
|
|
81
767
|
}
|
|
@@ -90,12 +776,12 @@
|
|
|
90
776
|
if (!navigation || Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent")?.value !== wrapped) return;
|
|
91
777
|
if (descriptor) Object.defineProperty(navigation, "clearArchivedCurrent", descriptor);
|
|
92
778
|
else delete navigation.clearArchivedCurrent;
|
|
93
|
-
original
|
|
779
|
+
original?.call(navigation);
|
|
94
780
|
}
|
|
95
781
|
};
|
|
96
782
|
}
|
|
97
783
|
|
|
98
|
-
// src/directory-flow-slot.
|
|
784
|
+
// src/directory-flow-slot.ts
|
|
99
785
|
function mirrorDirectoryFlow(ctx, target) {
|
|
100
786
|
const source = "sidebar.workspaces.directoryFlow";
|
|
101
787
|
return ctx.slots.inject(target, () => ctx.effect(() => {
|
|
@@ -160,12 +846,12 @@
|
|
|
160
846
|
}, "dsh-archive-manager: official directory flow"));
|
|
161
847
|
}
|
|
162
848
|
|
|
163
|
-
// src/plugin-update-ui.
|
|
849
|
+
// src/plugin-update-ui.ts
|
|
164
850
|
var UPDATE_HEADER = "x-michengai-plugin-update";
|
|
165
851
|
var STYLE_ID = "michengai-plugin-update-ui";
|
|
166
852
|
var CSS = `
|
|
167
853
|
.mpi-version{margin-left:8px;color:var(--dsw-alias-label-tertiary,#9da1aa);font-family:inherit;font-size:12px;font-weight:500;line-height:18px;letter-spacing:0;white-space:nowrap;vertical-align:baseline}.mpi-check{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);font:inherit;font-size:12px;font-weight:500;line-height:18px;white-space:nowrap;cursor:pointer}.mpi-check:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-check:focus-visible,.mpi-action:focus-visible,.mpi-dialog-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4f8cff);outline-offset:2px}.mpi-icon{display:inline-flex;flex:0 0 auto;width:16px;height:16px;align-items:center;justify-content:center;pointer-events:none}.mpi-icon svg{display:block;width:16px;height:16px}
|
|
168
|
-
.mpi-overlay{position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.62)}.mpi-dialog{position:relative;box-sizing:border-box;width:min(680px,100%);max-height:calc(100vh - 48px);overflow:auto;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:14px;padding:22px;background:var(--dsw-alias-bg-layer-2,var(--dsw-specific-menu,#202124));color:var(--dsw-alias-label-primary,#fff);box-shadow:var(--dsw-shadow-lv3,0 16px 48px rgba(0,0,0,.24));font-family:inherit}.mpi-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.mpi-dialog h2{margin:0;font-size:18px;line-height:26px}.mpi-dialog-close{display:inline-flex;flex:0 0 28px;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);cursor:pointer}.mpi-dialog-close:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-intro{margin:8px 0 18px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:13px;line-height:20px}.mpi-meta{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 18px;margin:0 0 16px;font-size:12px;line-height:18px}.mpi-meta dt{color:var(--dsw-alias-label-secondary,#c2c4ca)}.mpi-meta dd{margin:0;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.mpi-status{margin:0 0 18px;border-radius:7px;padding:12px 14px;background:var(--dsw-alias-bg-layer-3,var(--dsw-
|
|
854
|
+
.mpi-overlay{position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.62)}.mpi-dialog{position:relative;box-sizing:border-box;width:min(680px,100%);max-height:calc(100vh - 48px);overflow:auto;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:14px;padding:22px;background:var(--dsw-alias-bg-layer-2,var(--dsw-specific-menu,#202124));color:var(--dsw-alias-label-primary,#fff);box-shadow:var(--dsw-shadow-lv3,0 16px 48px rgba(0,0,0,.24));font-family:inherit}.mpi-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.mpi-dialog h2{margin:0;font-size:18px;line-height:26px}.mpi-dialog-close{display:inline-flex;flex:0 0 28px;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);cursor:pointer}.mpi-dialog-close:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-intro{margin:8px 0 18px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:13px;line-height:20px}.mpi-meta{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 18px;margin:0 0 16px;font-size:12px;line-height:18px}.mpi-meta dt{color:var(--dsw-alias-label-secondary,#c2c4ca)}.mpi-meta dd{margin:0;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.mpi-status{margin:0 0 18px;border-radius:7px;padding:12px 14px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-interactive-bg-hover,#252527));font-size:13px;font-weight:600;line-height:20px}.mpi-status[data-kind=error]{color:var(--dsw-alias-state-error-primary,#ff6464)}.mpi-status[data-kind=success]{color:var(--dsw-alias-state-success-primary,#36d67a)}.mpi-manual{border-top:1px solid var(--dsw-alias-border-l2,#4b4d52);padding-top:16px}.mpi-manual h3{margin:0 0 6px;font-size:14px;line-height:20px}.mpi-manual p{margin:0 0 10px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:12px;line-height:18px}.mpi-command{display:flex;align-items:center;gap:8px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;padding:10px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-interactive-bg-hover,#252527))}.mpi-command code{min-width:0;flex:1;overflow:auto;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;line-height:18px;white-space:nowrap}.mpi-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:18px}.mpi-actions-group{display:flex;gap:8px}.mpi-action{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:32px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;padding:6px 10px;background:transparent;color:inherit;font:inherit;font-size:12px;cursor:pointer}.mpi-action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#414247)}.mpi-action:disabled{cursor:not-allowed;opacity:.55}.mpi-primary{border-color:transparent;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.mpi-action.mpi-primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.mpi-progress{height:4px;margin-top:10px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2,#4b4d52)}.mpi-progress::after{display:block;width:32%;height:100%;background:var(--dsw-alias-state-business-primary,#4f8cff);content:'';animation:mpi-wave 1.15s ease-in-out infinite}@keyframes mpi-wave{from{transform:translateX(-110%)}to{transform:translateX(330%)}}@media(max-width:560px){.mpi-overlay{padding:10px}.mpi-dialog{max-height:calc(100vh - 20px);padding:16px}.mpi-actions{align-items:stretch}.mpi-actions-group{justify-content:flex-end;flex-wrap:wrap}.mpi-meta{grid-template-columns:1fr;gap:2px}.mpi-meta dd{margin-bottom:6px}}
|
|
169
855
|
`;
|
|
170
856
|
var ZH = {
|
|
171
857
|
check: "\u68C0\u67E5\u66F4\u65B0",
|
|
@@ -217,7 +903,9 @@
|
|
|
217
903
|
restarting: "Update complete. Restarting DSH Desktop\u2026",
|
|
218
904
|
unavailable: "Automatic update is unavailable. Use the manual command."
|
|
219
905
|
};
|
|
220
|
-
function strings() {
|
|
906
|
+
function strings(language) {
|
|
907
|
+
if (language === "en") return EN;
|
|
908
|
+
if (language === "zh") return ZH;
|
|
221
909
|
const lang = document.documentElement.lang.toLowerCase();
|
|
222
910
|
const settings = document.querySelector('[role="dialog"]')?.textContent ?? "";
|
|
223
911
|
return lang.startsWith("en") || settings.includes("Settings") && !settings.includes("\u8BBE\u7F6E") ? EN : ZH;
|
|
@@ -243,7 +931,7 @@
|
|
|
243
931
|
...signalOption
|
|
244
932
|
});
|
|
245
933
|
const value = await response.json();
|
|
246
|
-
if (!response.ok || !validPayload(value)) throw new Error(typeof value.error === "string" ? value.error : strings().failed);
|
|
934
|
+
if (!response.ok || !validPayload(value)) throw new Error(value && typeof value === "object" && "error" in value && typeof value.error === "string" ? value.error : strings().failed);
|
|
247
935
|
return value;
|
|
248
936
|
}
|
|
249
937
|
function manualPluginUpdateCommand(profileName, packageName, version) {
|
|
@@ -262,6 +950,7 @@
|
|
|
262
950
|
if (typeof document === "undefined" || document.body === null) return () => {
|
|
263
951
|
};
|
|
264
952
|
ensureStyle();
|
|
953
|
+
const getStrings = () => strings(options.getLanguage?.());
|
|
265
954
|
const controller = new AbortController();
|
|
266
955
|
let payload;
|
|
267
956
|
let overlay;
|
|
@@ -296,12 +985,18 @@
|
|
|
296
985
|
if (version.textContent !== versionLabel) version.textContent = versionLabel;
|
|
297
986
|
}
|
|
298
987
|
const links = row.querySelector(options.linksSelector);
|
|
299
|
-
if (links === null
|
|
988
|
+
if (links === null) return;
|
|
989
|
+
const existing = links.querySelector(`[data-mpi-check="${options.packageName}"]`);
|
|
990
|
+
if (existing !== null) {
|
|
991
|
+
const label = getStrings().check;
|
|
992
|
+
if (existing.querySelector("[data-mpi-label]")?.textContent !== label) setButtonLabel(existing, label);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
300
995
|
const button = document.createElement("button");
|
|
301
996
|
button.type = "button";
|
|
302
997
|
button.className = "mpi-check";
|
|
303
998
|
button.dataset.mpiCheck = options.packageName;
|
|
304
|
-
setButtonContent(button,
|
|
999
|
+
setButtonContent(button, getStrings().check, "refresh");
|
|
305
1000
|
button.addEventListener("click", openDialog);
|
|
306
1001
|
links.append(button);
|
|
307
1002
|
};
|
|
@@ -316,7 +1011,7 @@
|
|
|
316
1011
|
};
|
|
317
1012
|
function openDialog() {
|
|
318
1013
|
closeDialog();
|
|
319
|
-
const text =
|
|
1014
|
+
const text = getStrings();
|
|
320
1015
|
overlay = document.createElement("div");
|
|
321
1016
|
overlay.className = "mpi-overlay";
|
|
322
1017
|
const dialog = document.createElement("section");
|
|
@@ -324,22 +1019,27 @@
|
|
|
324
1019
|
dialog.setAttribute("role", "dialog");
|
|
325
1020
|
dialog.setAttribute("aria-modal", "true");
|
|
326
1021
|
dialog.innerHTML = `<header class="mpi-head"><h2></h2><button type="button" class="mpi-dialog-close" data-action="close"></button></header><p class="mpi-intro"></p><dl class="mpi-meta"><dt></dt><dd data-role="current"></dd><dt></dt><dd data-role="latest"></dd><dt></dt><dd data-role="profile"></dd></dl><div class="mpi-status" role="status"></div><div class="mpi-progress" hidden></div><section class="mpi-manual"><h3></h3><p></p><div class="mpi-command"><code></code><button type="button" class="mpi-action" data-action="copy"></button></div></section><footer class="mpi-actions"><div class="mpi-actions-group"><button type="button" class="mpi-action" data-action="check"></button><button type="button" class="mpi-action mpi-primary" data-action="update"></button></div></footer>`;
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
1022
|
+
const required = (selector) => {
|
|
1023
|
+
const element = dialog.querySelector(selector);
|
|
1024
|
+
if (!element) throw new Error(`\u66F4\u65B0\u5F39\u7A97\u7F3A\u5C11\u8282\u70B9\uFF1A${selector}`);
|
|
1025
|
+
return element;
|
|
1026
|
+
};
|
|
1027
|
+
const name = text === EN ? options.enName : options.zhName;
|
|
1028
|
+
required("h2").textContent = `${name} ${text.update}`;
|
|
1029
|
+
required(".mpi-intro").textContent = text.intro;
|
|
330
1030
|
const terms = dialog.querySelectorAll("dt");
|
|
331
1031
|
terms[0].textContent = text.current;
|
|
332
1032
|
terms[1].textContent = text.latestLabel;
|
|
333
1033
|
terms[2].textContent = text.profile;
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const status =
|
|
337
|
-
const progress =
|
|
338
|
-
const command =
|
|
339
|
-
const close =
|
|
340
|
-
const check =
|
|
341
|
-
const update =
|
|
342
|
-
const copy =
|
|
1034
|
+
required(".mpi-manual h3").textContent = text.manual;
|
|
1035
|
+
required(".mpi-manual p").textContent = text.manualHint;
|
|
1036
|
+
const status = required(".mpi-status");
|
|
1037
|
+
const progress = required(".mpi-progress");
|
|
1038
|
+
const command = required(".mpi-command code");
|
|
1039
|
+
const close = required("[data-action=close]");
|
|
1040
|
+
const check = required("[data-action=check]");
|
|
1041
|
+
const update = required("[data-action=update]");
|
|
1042
|
+
const copy = required("[data-action=copy]");
|
|
343
1043
|
setButtonContent(close, text.close, "close");
|
|
344
1044
|
close.querySelector("[data-mpi-label]")?.remove();
|
|
345
1045
|
close.setAttribute("aria-label", text.close);
|
|
@@ -360,9 +1060,9 @@
|
|
|
360
1060
|
progress.hidden = !value;
|
|
361
1061
|
};
|
|
362
1062
|
const render = () => {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
1063
|
+
required("[data-role=current]").textContent = payload === void 0 ? text.unknown : `v${payload.currentVersion}`;
|
|
1064
|
+
required("[data-role=latest]").textContent = payload?.latestVersion === void 0 ? text.unknown : `v${payload.latestVersion}`;
|
|
1065
|
+
required("[data-role=profile]").textContent = payload?.profileName ?? text.unknown;
|
|
366
1066
|
command.textContent = manualPluginUpdateCommand(payload?.profileName ?? "", options.packageName, payload?.latestVersion ?? "latest");
|
|
367
1067
|
update.disabled = busy || payload?.canAutoUpdate !== true || payload.updateAvailable !== true;
|
|
368
1068
|
if (payload === void 0) setMessage(text.checking);
|
|
@@ -450,7 +1150,213 @@
|
|
|
450
1150
|
};
|
|
451
1151
|
}
|
|
452
1152
|
|
|
453
|
-
// src/
|
|
1153
|
+
// src/archive-organizer.ts
|
|
1154
|
+
function checkedId(value) {
|
|
1155
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 1024) throw new TypeError("\u4F1A\u8BDD ID \u957F\u5EA6\u987B\u4E3A 1\uFF5E1024 \u4E2A\u5B57\u7B26");
|
|
1156
|
+
return value;
|
|
1157
|
+
}
|
|
1158
|
+
var favoriteInputSchema = {
|
|
1159
|
+
parse(input) {
|
|
1160
|
+
const value = record(input);
|
|
1161
|
+
if (!value || typeof value !== "object" || typeof value.favorite !== "boolean") throw new TypeError("\u6536\u85CF\u72B6\u6001\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C");
|
|
1162
|
+
return { sessionId: checkedId(value.sessionId), favorite: value.favorite };
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1165
|
+
var favoriteStateSchema = {
|
|
1166
|
+
parse(input) {
|
|
1167
|
+
const value = record(input);
|
|
1168
|
+
if (!value || !Array.isArray(value.favoriteSessionIds) || value.favoriteSessionIds.length > 1e5) throw new TypeError("\u6536\u85CF\u96C6\u5408\u65E0\u6548");
|
|
1169
|
+
return { favoriteSessionIds: [...new Set(value.favoriteSessionIds.map(checkedId))] };
|
|
1170
|
+
},
|
|
1171
|
+
safeParse(value) {
|
|
1172
|
+
try {
|
|
1173
|
+
return { success: true, data: this.parse(value) };
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
return { success: false, error };
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
function favoriteInvocations() {
|
|
1180
|
+
const codec = (name, schema) => ({ mode: "strict", typeSymbol: `@michengai/dsh-archive-manager/types#${name}`, create: () => schema, schema });
|
|
1181
|
+
return ["favoriteSessions", "setSessionFavorite"].map((method) => ({
|
|
1182
|
+
id: `@michengai/dsh-archive-manager#workspaceRegistry/${method}`,
|
|
1183
|
+
service: "workspaceRegistry",
|
|
1184
|
+
namespace: "workspaceRegistry",
|
|
1185
|
+
method,
|
|
1186
|
+
invocation: { kind: "direct" },
|
|
1187
|
+
parameters: method === "favoriteSessions" ? [] : [{ name: "input", wire: "input", source: "json", codec: codec("FavoriteInput", favoriteInputSchema) }],
|
|
1188
|
+
result: codec("FavoriteState", favoriteStateSchema),
|
|
1189
|
+
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
1190
|
+
}));
|
|
1191
|
+
}
|
|
1192
|
+
function idleArchiveCandidate(session, { days, now = Date.now(), favorites = /* @__PURE__ */ new Set(), currentId, pending = /* @__PURE__ */ new Map() }) {
|
|
1193
|
+
if (!session || !Number.isInteger(days) || days < 1 || days > 36500) return false;
|
|
1194
|
+
if (favorites.has(session.id) || session.id === currentId || (session.retainedBy?.mainView ?? 0) > 0) return false;
|
|
1195
|
+
if (session.running || (session.runningSubagentCount ?? 0) > 0 || session.pendingInteraction != null || pending.has(session.id)) return false;
|
|
1196
|
+
const updated = typeof session.updatedAt === "number" ? session.updatedAt : Date.parse(session.updatedAt ?? "");
|
|
1197
|
+
return Number.isFinite(updated) && updated <= now - days * 864e5;
|
|
1198
|
+
}
|
|
1199
|
+
async function runSessionBatch(ids, operate, { onProgress, refresh } = {}) {
|
|
1200
|
+
const requested = [...new Set(ids.map(checkedId))];
|
|
1201
|
+
const result = { requested, succeeded: [], skipped: [], failures: [], unprocessed: [], remaining: [], refreshError: null };
|
|
1202
|
+
const report = () => onProgress?.({ total: requested.length, done: result.succeeded.length + result.skipped.length + result.failures.length, succeeded: result.succeeded.length, skipped: result.skipped.length, failed: result.failures.length });
|
|
1203
|
+
report();
|
|
1204
|
+
for (const [index, id2] of requested.entries()) {
|
|
1205
|
+
try {
|
|
1206
|
+
(await operate(id2) ? result.succeeded : result.skipped).push(id2);
|
|
1207
|
+
} catch (error) {
|
|
1208
|
+
result.failures.push({ sessionId: id2, message: error instanceof Error ? error.message : String(error) });
|
|
1209
|
+
result.unprocessed = requested.slice(index + 1);
|
|
1210
|
+
result.remaining = requested.slice(index);
|
|
1211
|
+
report();
|
|
1212
|
+
break;
|
|
1213
|
+
}
|
|
1214
|
+
report();
|
|
1215
|
+
}
|
|
1216
|
+
try {
|
|
1217
|
+
await refresh?.();
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
result.refreshError = error instanceof Error ? error.message : String(error);
|
|
1220
|
+
}
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
function createSessionOrganizer({ workspaces, sessions, archive, restore, deleteOne, getFavorites, refresh, currentSessionId: currentSessionId2 }) {
|
|
1224
|
+
return async (kind, ids, options = {}) => {
|
|
1225
|
+
if (!["archive", "restore", "undo", "delete"].includes(kind)) throw new TypeError("\u672A\u77E5\u6279\u91CF\u64CD\u4F5C");
|
|
1226
|
+
return runSessionBatch(ids, async (id2) => {
|
|
1227
|
+
const before = workspaces.getSnapshot();
|
|
1228
|
+
const archived = before.archivedSessionIds.includes(id2);
|
|
1229
|
+
if (kind === "archive") {
|
|
1230
|
+
if (archived) return false;
|
|
1231
|
+
const snapshot = sessions.getSnapshot();
|
|
1232
|
+
const session = snapshot.byId[id2];
|
|
1233
|
+
if (!session) return false;
|
|
1234
|
+
if (options.idleDays !== void 0) {
|
|
1235
|
+
const favorites = new Set((await getFavorites()).favoriteSessionIds);
|
|
1236
|
+
const latest = sessions.getSnapshot();
|
|
1237
|
+
if (!idleArchiveCandidate(latest.byId[id2], { days: options.idleDays, favorites, currentId: currentSessionId2(latest), pending: options.getPending?.() ?? options.pending })) return false;
|
|
1238
|
+
}
|
|
1239
|
+
await archive(id2);
|
|
1240
|
+
return workspaces.getSnapshot().archivedSessionIds.includes(id2);
|
|
1241
|
+
}
|
|
1242
|
+
if (!archived) return false;
|
|
1243
|
+
if (kind === "delete") {
|
|
1244
|
+
await deleteOne(id2);
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
const value = await restore(id2);
|
|
1248
|
+
const remaining = value?.archivedSessionIds ?? workspaces.getSnapshot().archivedSessionIds;
|
|
1249
|
+
return !remaining.includes(id2);
|
|
1250
|
+
}, { onProgress: options.onProgress, refresh });
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// src/archive-organizer-ui.ts
|
|
1255
|
+
function createOrganizerPanel(React) {
|
|
1256
|
+
const h = React.createElement;
|
|
1257
|
+
return function OrganizerPanel({ t, archived, busy, ready, days, onDays, count, onPreview, progress, result, onRetry, undoCount, onUndo, onReload }) {
|
|
1258
|
+
return h(
|
|
1259
|
+
React.Fragment,
|
|
1260
|
+
null,
|
|
1261
|
+
h("style", null, ".dsham_organizer,.dsham_batchFeedback{display:grid;gap:12px;margin:0 0 16px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dsham_organizerControls{display:flex;align-items:center;flex-wrap:wrap;gap:10px}.dsham_organizer label{display:inline-flex;align-items:center;gap:6px}.dsham_organizer input[type=number]{width:76px;padding:5px;color:inherit;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:5px}.dsham_organizer p,.dsham_batchFeedback p{margin:0;font-size:12px;color:var(--dsw-alias-label-secondary)}.dsham_batchFeedback progress{width:100%}.dsham_batchFeedback details{font-size:12px;overflow-wrap:anywhere}.dsham_archivePreview{max-height:260px;overflow:auto;display:grid;gap:8px;padding:8px 0}.dsham_archivePreview label{display:flex;gap:8px;align-items:center;overflow-wrap:anywhere}"),
|
|
1262
|
+
(!archived || !ready) && h(
|
|
1263
|
+
"div",
|
|
1264
|
+
{ className: "dsham_organizer" },
|
|
1265
|
+
h(
|
|
1266
|
+
"div",
|
|
1267
|
+
{ className: "dsham_organizerControls" },
|
|
1268
|
+
!ready && h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onReload }, t("organizer.reloadFavorites")),
|
|
1269
|
+
!archived && h(
|
|
1270
|
+
React.Fragment,
|
|
1271
|
+
null,
|
|
1272
|
+
h("label", null, t("organizer.idleDays"), h("input", { type: "number", min: 1, max: 36500, step: 1, value: days, disabled: busy, onChange: (event) => onDays(event.currentTarget.value), "aria-label": t("organizer.idleDays") })),
|
|
1273
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: busy || !ready || count === 0, onClick: onPreview }, t("organizer.preview", { n: count }))
|
|
1274
|
+
)
|
|
1275
|
+
),
|
|
1276
|
+
!archived && h("p", null, t("organizer.rules"))
|
|
1277
|
+
),
|
|
1278
|
+
(progress || result || undoCount > 0) && h(
|
|
1279
|
+
"section",
|
|
1280
|
+
{ className: "dsham_batchFeedback", "aria-label": t("organizer.feedback") },
|
|
1281
|
+
progress && h(
|
|
1282
|
+
"div",
|
|
1283
|
+
{ role: "status", "aria-live": "polite" },
|
|
1284
|
+
h("progress", { value: progress.done, max: Math.max(1, progress.total), "aria-label": t("organizer.progress") }),
|
|
1285
|
+
t("organizer.progressCount", { done: progress.done, total: progress.total })
|
|
1286
|
+
),
|
|
1287
|
+
result && h(
|
|
1288
|
+
"div",
|
|
1289
|
+
{ role: "status" },
|
|
1290
|
+
h("strong", null, t(`organizer.${result.kind ?? "archive"}Result`)),
|
|
1291
|
+
h("p", null, t("organizer.result", { succeeded: result.succeeded.length, skipped: result.skipped.length, failed: result.failures.length, remaining: result.unprocessed.length })),
|
|
1292
|
+
result.failures.length > 0 && h("details", null, h("summary", null, t("organizer.failureDetails")), h("ul", null, result.failures.map((failure) => h("li", { key: failure.sessionId }, failure.sessionId, t("common.separator"), failure.message)))),
|
|
1293
|
+
result.refreshError && h("p", { role: "alert" }, t("organizer.refreshError", { detail: result.refreshError })),
|
|
1294
|
+
result.remaining.length > 0 && h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onRetry }, t("organizer.retry", { n: result.remaining.length }))
|
|
1295
|
+
),
|
|
1296
|
+
undoCount > 0 && h(
|
|
1297
|
+
"div",
|
|
1298
|
+
{ className: "dsham_organizerControls" },
|
|
1299
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onUndo }, t("organizer.undo", { n: undoCount })),
|
|
1300
|
+
h("p", null, t("organizer.undoHint"))
|
|
1301
|
+
)
|
|
1302
|
+
)
|
|
1303
|
+
);
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
var organizerZh = {
|
|
1307
|
+
"organizer.feedback": "\u64CD\u4F5C\u53CD\u9988",
|
|
1308
|
+
"organizer.allSessions": "\u5168\u90E8\u4F1A\u8BDD",
|
|
1309
|
+
"organizer.favoriteFilter": "\u6536\u85CF\u7B5B\u9009",
|
|
1310
|
+
"organizer.archiveResult": "\u5F52\u6863\u7ED3\u679C",
|
|
1311
|
+
"organizer.restoreResult": "\u6062\u590D\u7ED3\u679C",
|
|
1312
|
+
"organizer.deleteResult": "\u5220\u9664\u7ED3\u679C",
|
|
1313
|
+
"organizer.undoResult": "\u64A4\u56DE\u7ED3\u679C",
|
|
1314
|
+
"organizer.favorite": "\u6536\u85CF",
|
|
1315
|
+
"organizer.unfavorite": "\u53D6\u6D88\u6536\u85CF",
|
|
1316
|
+
"organizer.favoritesOnly": "\u53EA\u770B\u6536\u85CF",
|
|
1317
|
+
"organizer.reloadFavorites": "\u91CD\u65B0\u52A0\u8F7D\u6536\u85CF",
|
|
1318
|
+
"organizer.idleDays": "\u95F2\u7F6E\u5929\u6570",
|
|
1319
|
+
"organizer.preview": "\u9884\u89C8\u95F2\u7F6E\u5F52\u6863\uFF08{n}\uFF09",
|
|
1320
|
+
"organizer.rules": "\u6309\u6700\u540E\u6D3B\u52A8\u65F6\u95F4\u7B5B\u9009\uFF0C\u9075\u5FAA\u5F53\u524D\u5217\u8868\u7B5B\u9009\u6761\u4EF6\uFF1B\u6392\u9664\u6536\u85CF\u3001\u5F53\u524D\u6253\u5F00\u3001\u6B63\u5728\u6267\u884C\u53CA\u7B49\u5F85\u4EA4\u4E92\u7684\u4F1A\u8BDD\u3002",
|
|
1321
|
+
"organizer.progress": "\u6279\u91CF\u64CD\u4F5C\u8FDB\u5EA6",
|
|
1322
|
+
"organizer.progressCount": "\u5DF2\u5904\u7406 {done} / {total}",
|
|
1323
|
+
"organizer.result": "\u6210\u529F {succeeded} \xB7 \u8DF3\u8FC7 {skipped} \xB7 \u5931\u8D25 {failed} \xB7 \u672A\u5904\u7406 {remaining}",
|
|
1324
|
+
"organizer.failureDetails": "\u67E5\u770B\u5931\u8D25\u8BE6\u60C5",
|
|
1325
|
+
"organizer.refreshError": "\u64CD\u4F5C\u7ED3\u679C\u5DF2\u4FDD\u7559\uFF0C\u4F46\u5217\u8868\u5237\u65B0\u5931\u8D25\uFF1A{detail}",
|
|
1326
|
+
"organizer.retry": "\u91CD\u8BD5\u5269\u4F59 {n} \u6761",
|
|
1327
|
+
"organizer.undo": "\u64A4\u56DE\u672C\u6B21\u5F52\u6863\uFF08{n}\uFF09",
|
|
1328
|
+
"organizer.undoHint": "\u4EC5\u4FDD\u7559\u672C\u6B21\u6253\u5F00\u7BA1\u7406\u9875\u671F\u95F4\u6700\u8FD1\u4E00\u6279\u5F52\u6863\uFF1B\u5173\u95ED\u9875\u9762\u6216\u5237\u65B0\u540E\u6E05\u9664\u3002\u64A4\u56DE\u4E0D\u4F1A\u6062\u590D\u5DF2\u5220\u9664\u7684\u4F1A\u8BDD\u3002",
|
|
1329
|
+
"organizer.idleConfirm": "\u8BF7\u68C0\u67E5\u4EE5\u4E0B\u5019\u9009\uFF0C\u53EF\u53D6\u6D88\u52FE\u9009\uFF1B\u6267\u884C\u524D\u518D\u6B21\u6392\u9664\u6536\u85CF\u53CA\u6D3B\u8DC3\u4F1A\u8BDD\u3002",
|
|
1330
|
+
"organizer.manualConfirm": "\u4EC5\u5F52\u6863\u4EE5\u4E0B\u52FE\u9009\u4F1A\u8BDD\uFF1B\u53EF\u9010\u6761\u53D6\u6D88\u3002\u5F52\u6863\u540E\u53EF\u64A4\u56DE\u672C\u6279\u64CD\u4F5C\u3002"
|
|
1331
|
+
};
|
|
1332
|
+
var organizerEn = {
|
|
1333
|
+
"organizer.feedback": "Operation feedback",
|
|
1334
|
+
"organizer.allSessions": "All sessions",
|
|
1335
|
+
"organizer.favoriteFilter": "Favorites filter",
|
|
1336
|
+
"organizer.archiveResult": "Archive results",
|
|
1337
|
+
"organizer.restoreResult": "Restore results",
|
|
1338
|
+
"organizer.deleteResult": "Delete results",
|
|
1339
|
+
"organizer.undoResult": "Undo results",
|
|
1340
|
+
"organizer.favorite": "Favorite",
|
|
1341
|
+
"organizer.unfavorite": "Unfavorite",
|
|
1342
|
+
"organizer.favoritesOnly": "Favorites only",
|
|
1343
|
+
"organizer.reloadFavorites": "Reload favorites",
|
|
1344
|
+
"organizer.idleDays": "Idle days",
|
|
1345
|
+
"organizer.preview": "Preview idle archives ({n})",
|
|
1346
|
+
"organizer.rules": "Uses last activity, the current list filters. Excludes favorites, open, running and waiting sessions.",
|
|
1347
|
+
"organizer.progress": "Batch progress",
|
|
1348
|
+
"organizer.progressCount": "Processed {done} / {total}",
|
|
1349
|
+
"organizer.result": "Succeeded {succeeded} \xB7 Skipped {skipped} \xB7 Failed {failed} \xB7 Unprocessed {remaining}",
|
|
1350
|
+
"organizer.failureDetails": "Failure details",
|
|
1351
|
+
"organizer.refreshError": "Results retained, but refresh failed: {detail}",
|
|
1352
|
+
"organizer.retry": "Retry remaining {n}",
|
|
1353
|
+
"organizer.undo": "Undo this archive batch ({n})",
|
|
1354
|
+
"organizer.undoHint": "Only the latest archive batch while this page is open is retained. Closing or refreshing clears undo. Deleted sessions cannot be restored.",
|
|
1355
|
+
"organizer.idleConfirm": "Review and deselect candidates. Favorites and active sessions are checked again before archiving.",
|
|
1356
|
+
"organizer.manualConfirm": "Only checked sessions below will be archived. You can undo this batch afterward."
|
|
1357
|
+
};
|
|
1358
|
+
|
|
1359
|
+
// src/client.ts
|
|
454
1360
|
window.__ModuleLoader__.load({
|
|
455
1361
|
id: "@michengai/dsh-archive-manager",
|
|
456
1362
|
factory: (require2) => {
|
|
@@ -467,7 +1373,10 @@
|
|
|
467
1373
|
}
|
|
468
1374
|
let react_jsx_runtime = require2("react/jsx-runtime");
|
|
469
1375
|
let react = require2("react");
|
|
1376
|
+
const OrganizerPanel = createOrganizerPanel(react);
|
|
1377
|
+
const { HighlightedText, useSessionDetails, useArchiveSearch, useArchivePreview, DiscoveryFilters, SearchStatus, PreviewContent } = createDiscoveryTools(react);
|
|
470
1378
|
let _deepseek_ai_dsh_client_ui_primitives = require2("@deepseek-ai/dsh-client-ui-primitives");
|
|
1379
|
+
const SessionHealthPanel = createSessionHealthPanel(react, { warning: _deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, info: _deepseek_ai_dsh_client_ui_primitives.IconInfoOutline14, check: _deepseek_ai_dsh_client_ui_primitives.IconCheckOutline16, refresh: _deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16, search: _deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, chevron: _deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14 });
|
|
471
1380
|
const UPDATE_ICON_PATHS = {
|
|
472
1381
|
refresh: ["M13.5 5.5V2.5m0 0h-3m3 0-2.1 2.1A5.5 5.5 0 1 0 13.2 12"],
|
|
473
1382
|
download: ["M8 2v8m0 0 3-3m-3 3-3-3M3 13v2h10v-2"],
|
|
@@ -501,43 +1410,48 @@
|
|
|
501
1410
|
}
|
|
502
1411
|
};
|
|
503
1412
|
const archivedSetSchema = {
|
|
504
|
-
parse(
|
|
1413
|
+
parse(input) {
|
|
1414
|
+
const value = record(input);
|
|
505
1415
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
506
1416
|
const ids = value.archivedSessionIds;
|
|
507
|
-
if (!Array.isArray(ids) || ids.some((
|
|
1417
|
+
if (!Array.isArray(ids) || ids.some((id2) => typeof id2 !== "string")) throw new TypeError("archivedSessionIds must be a string array");
|
|
508
1418
|
return value;
|
|
509
1419
|
}
|
|
510
1420
|
};
|
|
511
1421
|
const deletedSchema = {
|
|
512
|
-
parse(
|
|
1422
|
+
parse(input) {
|
|
1423
|
+
const value = record(input);
|
|
513
1424
|
if (typeof value !== "object" || value === null || Array.isArray(value) || value.deleted !== true) throw new TypeError("deleted must be true");
|
|
514
1425
|
return value;
|
|
515
1426
|
}
|
|
516
1427
|
};
|
|
517
1428
|
const archivedBatchTargetSchema = {
|
|
518
|
-
parse(
|
|
1429
|
+
parse(input) {
|
|
1430
|
+
const value = record(input);
|
|
519
1431
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("target must be an object");
|
|
520
1432
|
if (value.scope === "all" || value.scope === "ungrouped") return value;
|
|
521
1433
|
if (value.scope === "workspace" && typeof value.workspaceId === "string" && value.workspaceId.length > 0) return value;
|
|
522
|
-
if (value.scope === "sessions" && Array.isArray(value.sessionIds) && value.sessionIds.length > 0 && value.sessionIds.every((
|
|
1434
|
+
if (value.scope === "sessions" && Array.isArray(value.sessionIds) && value.sessionIds.length > 0 && value.sessionIds.every((id2) => typeof id2 === "string" && id2.length > 0)) return value;
|
|
523
1435
|
throw new TypeError("target.scope must be all, ungrouped, workspace with a non-empty workspaceId, or sessions with non-empty sessionIds");
|
|
524
1436
|
}
|
|
525
1437
|
};
|
|
526
1438
|
const deletedBatchSchema = {
|
|
527
|
-
parse(
|
|
1439
|
+
parse(input) {
|
|
1440
|
+
const value = record(input);
|
|
528
1441
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
529
1442
|
for (const key of ["requestedSessionIds", "deletedSessionIds", "skippedSessionIds"]) {
|
|
530
|
-
if (!Array.isArray(value[key]) || value[key].some((
|
|
1443
|
+
if (!Array.isArray(value[key]) || value[key].some((id2) => typeof id2 !== "string")) throw new TypeError(`${key} must be a string array`);
|
|
531
1444
|
}
|
|
532
1445
|
if (!Array.isArray(value.failures) || value.failures.some((failure) => typeof failure !== "object" || failure === null || typeof failure.sessionId !== "string" || typeof failure.message !== "string")) throw new TypeError("failures must contain sessionId/message objects");
|
|
533
1446
|
return value;
|
|
534
1447
|
}
|
|
535
1448
|
};
|
|
536
1449
|
const archivedSessionMetadataSchema = {
|
|
537
|
-
parse(
|
|
1450
|
+
parse(input) {
|
|
1451
|
+
const value = record(input);
|
|
538
1452
|
if (typeof value !== "object" || value === null || Array.isArray(value) || !Array.isArray(value.items)) throw new TypeError("result.items must be an array");
|
|
539
1453
|
if (value.items.some((item) => typeof item !== "object" || item === null || typeof item.sessionId !== "string" || typeof item.createdAt !== "number" || !Number.isFinite(item.createdAt))) throw new TypeError("items must contain sessionId/createdAt objects");
|
|
540
|
-
if (value.repairedSessionIds !== void 0 && (!Array.isArray(value.repairedSessionIds) || value.repairedSessionIds.some((
|
|
1454
|
+
if (value.repairedSessionIds !== void 0 && (!Array.isArray(value.repairedSessionIds) || value.repairedSessionIds.some((id2) => typeof id2 !== "string"))) throw new TypeError("repairedSessionIds must be a string array");
|
|
541
1455
|
return value;
|
|
542
1456
|
}
|
|
543
1457
|
};
|
|
@@ -547,6 +1461,8 @@
|
|
|
547
1461
|
const ARCHIVE_MANAGER_REMOTE = {
|
|
548
1462
|
package: "@michengai/dsh-archive-manager",
|
|
549
1463
|
descriptors: [
|
|
1464
|
+
...favoriteInvocations(),
|
|
1465
|
+
...discoveryInvocations(),
|
|
550
1466
|
{
|
|
551
1467
|
id: "@michengai/dsh-archive-manager#workspaceRegistry/unarchiveSession",
|
|
552
1468
|
service: "workspaceRegistry",
|
|
@@ -704,7 +1620,7 @@
|
|
|
704
1620
|
function GithubMark16() {
|
|
705
1621
|
return (0, react_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", width: 16, height: 16, "aria-hidden": true, focusable: "false", children: (0, react_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z" }) });
|
|
706
1622
|
}
|
|
707
|
-
function ArchivedSessionsSection({ archiveSessions, sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, focusSessionWorkspace, viewState, close, t }) {
|
|
1623
|
+
function ArchivedSessionsSection({ archiveSessions, sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, focusSessionWorkspace, viewState, close, t, diagnoseSession, repairSession, sessionDetails, searchSessionContent, searchArchivedContent, previewArchivedSession, favoriteSessions, setSessionFavorite, organizeBatch, useSessionPendingInteraction, useSessionStatus }) {
|
|
708
1624
|
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
709
1625
|
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
710
1626
|
const [archiveTab, setArchiveTab] = (0, react.useState)("archived");
|
|
@@ -714,6 +1630,7 @@
|
|
|
714
1630
|
const requestArchive = (ids, group = null) => {
|
|
715
1631
|
setError(null);
|
|
716
1632
|
setNotice(null);
|
|
1633
|
+
setIdleRequest(false);
|
|
717
1634
|
setArchiveGroup(group);
|
|
718
1635
|
setArchiveTarget(ids);
|
|
719
1636
|
};
|
|
@@ -736,6 +1653,91 @@
|
|
|
736
1653
|
const [unarchivingSessionIds, setUnarchivingSessionIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
737
1654
|
const unarchivingSessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
738
1655
|
const [selectedSessionIds, setSelectedSessionIds] = (0, react.useState)([]);
|
|
1656
|
+
const [favoriteIds, setFavoriteIds] = (0, react.useState)([]);
|
|
1657
|
+
const [favoritesReady, setFavoritesReady] = (0, react.useState)(false);
|
|
1658
|
+
const [favoriteBusy, setFavoriteBusy] = (0, react.useState)(false);
|
|
1659
|
+
const favoriteLock = (0, react.useRef)(false);
|
|
1660
|
+
const [favoritesOnly, setFavoritesOnly] = (0, react.useState)(false);
|
|
1661
|
+
const [searchScope, setSearchScope] = react.useState("title");
|
|
1662
|
+
const [dateFrom, setDateFrom] = react.useState("");
|
|
1663
|
+
const [dateTo, setDateTo] = react.useState("");
|
|
1664
|
+
const [collapsedGroups, setCollapsedGroups] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
1665
|
+
const [idleDays, setIdleDays] = (0, react.useState)("30");
|
|
1666
|
+
const [idleRequest, setIdleRequest] = (0, react.useState)(false);
|
|
1667
|
+
const [batchProgress, setBatchProgress] = (0, react.useState)(null);
|
|
1668
|
+
const [batchResult, setBatchResult] = (0, react.useState)(null);
|
|
1669
|
+
const [lastArchive, setLastArchive] = (0, react.useState)([]);
|
|
1670
|
+
const batchLock = (0, react.useRef)(false);
|
|
1671
|
+
const retryBatch = (0, react.useRef)(null);
|
|
1672
|
+
const uiFacts = useSessionUiFacts(useSessionPendingInteraction ?? useEmptySessionPendingInteraction, useSessionStatus ?? useEmptySessionStatus, typeof useSessionStatus === "function");
|
|
1673
|
+
const pendingRef = (0, react.useRef)(uiFacts.pending);
|
|
1674
|
+
pendingRef.current = uiFacts.pending;
|
|
1675
|
+
const favoriteSet = new Set(favoriteIds);
|
|
1676
|
+
const loadFavorites = async () => {
|
|
1677
|
+
if (!favoriteSessions) return;
|
|
1678
|
+
try {
|
|
1679
|
+
const result = await favoriteSessions();
|
|
1680
|
+
setFavoriteIds(result.favoriteSessionIds);
|
|
1681
|
+
setFavoritesReady(true);
|
|
1682
|
+
} catch (reason) {
|
|
1683
|
+
setFavoritesReady(false);
|
|
1684
|
+
setError(errorMessage(reason));
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
(0, react.useEffect)(() => {
|
|
1688
|
+
let active = true;
|
|
1689
|
+
if (favoriteSessions) favoriteSessions().then((value) => {
|
|
1690
|
+
if (active) {
|
|
1691
|
+
setFavoriteIds(value.favoriteSessionIds);
|
|
1692
|
+
setFavoritesReady(true);
|
|
1693
|
+
}
|
|
1694
|
+
}).catch((reason) => {
|
|
1695
|
+
if (active) setError(errorMessage(reason));
|
|
1696
|
+
});
|
|
1697
|
+
return () => {
|
|
1698
|
+
active = false;
|
|
1699
|
+
};
|
|
1700
|
+
}, [favoriteSessions]);
|
|
1701
|
+
const toggleFavorite = async (sessionId) => {
|
|
1702
|
+
if (favoriteLock.current || busy || !favoritesReady) return;
|
|
1703
|
+
favoriteLock.current = true;
|
|
1704
|
+
setFavoriteBusy(true);
|
|
1705
|
+
setError(null);
|
|
1706
|
+
try {
|
|
1707
|
+
const value = await setSessionFavorite({ sessionId, favorite: !favoriteSet.has(sessionId) });
|
|
1708
|
+
setFavoriteIds(value.favoriteSessionIds);
|
|
1709
|
+
} catch (reason) {
|
|
1710
|
+
setError(errorMessage(reason));
|
|
1711
|
+
} finally {
|
|
1712
|
+
favoriteLock.current = false;
|
|
1713
|
+
setFavoriteBusy(false);
|
|
1714
|
+
}
|
|
1715
|
+
};
|
|
1716
|
+
const executeBatch = async (kind, ids, { idle = false, retry = false } = {}) => {
|
|
1717
|
+
if (batchLock.current || favoriteLock.current || unarchivingSessionIdsRef.current.size > 0 || !organizeBatch) return;
|
|
1718
|
+
batchLock.current = true;
|
|
1719
|
+
setBusy(true);
|
|
1720
|
+
setError(null);
|
|
1721
|
+
setNotice(null);
|
|
1722
|
+
setBatchResult(null);
|
|
1723
|
+
if (kind === "archive" && !retry) setLastArchive([]);
|
|
1724
|
+
try {
|
|
1725
|
+
const result = await organizeBatch(kind, ids, { idleDays: idle ? Number(idleDays) : void 0, getPending: () => pendingRef.current, onProgress: setBatchProgress });
|
|
1726
|
+
setBatchResult({ ...result, kind, tab: archiveTab });
|
|
1727
|
+
retryBatch.current = result.remaining.length ? { kind, ids: result.remaining, idle } : null;
|
|
1728
|
+
if (kind === "archive") setLastArchive((previous) => [.../* @__PURE__ */ new Set([...previous, ...result.succeeded])]);
|
|
1729
|
+
if (kind === "undo" || kind === "restore" || kind === "delete") setLastArchive((previous) => previous.filter((id2) => !result.succeeded.includes(id2) && !result.skipped.includes(id2)));
|
|
1730
|
+
setSelectedSessionIds((previous) => previous.filter((id2) => !result.succeeded.includes(id2) && !result.skipped.includes(id2)));
|
|
1731
|
+
if (kind === "delete") setFavoriteIds((previous) => previous.filter((id2) => !result.succeeded.includes(id2)));
|
|
1732
|
+
return result;
|
|
1733
|
+
} catch (reason) {
|
|
1734
|
+
setError(errorMessage(reason));
|
|
1735
|
+
} finally {
|
|
1736
|
+
batchLock.current = false;
|
|
1737
|
+
setBusy(false);
|
|
1738
|
+
setBatchProgress(null);
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
739
1741
|
const navigationActive = (0, react.useRef)(true);
|
|
740
1742
|
const navigationPending = (0, react.useRef)(false);
|
|
741
1743
|
(0, react.useEffect)(() => {
|
|
@@ -752,15 +1754,15 @@
|
|
|
752
1754
|
let restored = false;
|
|
753
1755
|
try {
|
|
754
1756
|
await openArchivedConversation({
|
|
755
|
-
prepare: restore ? async (
|
|
756
|
-
await focusSessionWorkspace?.(
|
|
1757
|
+
prepare: restore ? async (id2) => {
|
|
1758
|
+
await focusSessionWorkspace?.(id2);
|
|
757
1759
|
} : void 0,
|
|
758
|
-
restore: async (
|
|
759
|
-
await unarchiveSession(
|
|
1760
|
+
restore: async (id2) => {
|
|
1761
|
+
await unarchiveSession(id2);
|
|
760
1762
|
restored = true;
|
|
761
1763
|
},
|
|
762
|
-
open: async (
|
|
763
|
-
await openConversation(
|
|
1764
|
+
open: async (id2) => {
|
|
1765
|
+
await openConversation(id2);
|
|
764
1766
|
if (navigationActive.current) close?.();
|
|
765
1767
|
}
|
|
766
1768
|
}, session.id, restore, () => navigationActive.current);
|
|
@@ -784,6 +1786,7 @@
|
|
|
784
1786
|
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, eligibleIds, t("group.ungrouped")), [sessions.byId, workspaceState, eligibleIds, t]);
|
|
785
1787
|
const switchTab = (tab) => {
|
|
786
1788
|
if (busy || unarchivingSessionIdsRef.current.size > 0) return;
|
|
1789
|
+
preview.close();
|
|
787
1790
|
setArchiveTab(tab);
|
|
788
1791
|
setSelectedSessionIds([]);
|
|
789
1792
|
setArchiveTarget(null);
|
|
@@ -792,10 +1795,23 @@
|
|
|
792
1795
|
setNotice(null);
|
|
793
1796
|
setProject("all");
|
|
794
1797
|
setQuery("");
|
|
795
|
-
if (tab === "unarchived" && sortBy === "created") setSortBy("updated");
|
|
796
1798
|
};
|
|
797
1799
|
const confirmArchive = async () => {
|
|
798
1800
|
if (archiveBusy.current || busy || !archiveTarget?.length) return;
|
|
1801
|
+
if (organizeBatch) {
|
|
1802
|
+
archiveBusy.current = true;
|
|
1803
|
+
try {
|
|
1804
|
+
const result = await executeBatch("archive", archiveTarget, { idle: idleRequest });
|
|
1805
|
+
if (result) {
|
|
1806
|
+
setArchiveTarget(null);
|
|
1807
|
+
setArchiveGroup(null);
|
|
1808
|
+
setIdleRequest(false);
|
|
1809
|
+
}
|
|
1810
|
+
} finally {
|
|
1811
|
+
archiveBusy.current = false;
|
|
1812
|
+
}
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
799
1815
|
archiveBusy.current = true;
|
|
800
1816
|
setBusy(true);
|
|
801
1817
|
setError(null);
|
|
@@ -816,7 +1832,25 @@
|
|
|
816
1832
|
setBusy(false);
|
|
817
1833
|
}
|
|
818
1834
|
};
|
|
819
|
-
const
|
|
1835
|
+
const details = useSessionDetails(sessionDetailCandidates(eligibleIds, sessions.byId), sessionDetails, t);
|
|
1836
|
+
const copyDetail = async (session, kind) => {
|
|
1837
|
+
setError(null);
|
|
1838
|
+
setNotice(null);
|
|
1839
|
+
try {
|
|
1840
|
+
let text = session.id;
|
|
1841
|
+
if (kind === "path") {
|
|
1842
|
+
let row = details.byId[session.id];
|
|
1843
|
+
if (!row) row = (await sessionDetails({ sessionIds: [session.id] })).items[0];
|
|
1844
|
+
if (!row?.path) throw new Error(t("details.noPath"));
|
|
1845
|
+
text = row.path;
|
|
1846
|
+
}
|
|
1847
|
+
await copySessionText(text);
|
|
1848
|
+
if (navigationActive.current) setNotice(t("details.copied"));
|
|
1849
|
+
} catch (reason) {
|
|
1850
|
+
if (navigationActive.current) setError(typeof errorCode(reason) === "string" && String(errorCode(reason)).startsWith("copy.") ? t(String(errorCode(reason))) : errorMessage(reason));
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1853
|
+
const sortedGroups = (0, react.useMemo)(() => sortArchivedGroups(groups, sortBy, createdAtById, t, details.byId), [groups, sortBy, createdAtById, t, details.byId]);
|
|
820
1854
|
(0, react.useEffect)(() => {
|
|
821
1855
|
let cancelled = false;
|
|
822
1856
|
archivedSessionMetadata().then((result) => {
|
|
@@ -831,19 +1865,19 @@
|
|
|
831
1865
|
(0, react.useEffect)(() => {
|
|
832
1866
|
if (project !== "all" && !groups.some((group) => group.key === project)) setProject("all");
|
|
833
1867
|
}, [groups, project]);
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1868
|
+
const invalidDate = !validUpdatedRange(dateFrom, dateTo);
|
|
1869
|
+
const candidateGroups = sortedGroups.filter((group) => project === "all" || project === group.key).map((group) => ({ ...group, sessions: group.sessions.filter((session) => (!favoritesOnly || favoriteIds.includes(session.id)) && matchesUpdatedRange(session.updatedAt, dateFrom, dateTo)) })).filter((group) => group.sessions.length);
|
|
1870
|
+
const contentEnabled = searchScope === "content" && !invalidDate;
|
|
1871
|
+
const contentSearch = useArchiveSearch(candidateGroups.flatMap((group) => group.sessions.map((session) => session.id)), query, contentEnabled, searchSessionContent ?? searchArchivedContent);
|
|
1872
|
+
const contentMatches = new Map(contentSearch.items.map((item) => [item.sessionId, item]));
|
|
1873
|
+
const preview = useArchivePreview(previewArchivedSession, isArchived ? workspaceState.archivedSessionIds : []);
|
|
1874
|
+
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
1875
|
+
const filteredGroups = candidateGroups.map((group) => ({ ...group, sessions: group.sessions.filter((session) => !normalizedQuery || displayTitle(session, t).toLocaleLowerCase().includes(normalizedQuery) || contentMatches.has(session.id)) })).filter((group) => group.sessions.length);
|
|
1876
|
+
const idleCandidates = favoritesReady ? filteredGroups.flatMap((group) => group.sessions).filter((session) => idleArchiveCandidate(session, { days: Number(idleDays), favorites: favoriteSet, currentId: currentSessionId(sessions), pending: uiFacts.pending })).map((session) => session.id) : [];
|
|
841
1877
|
const visibleSessionIds = (0, react.useMemo)(() => archivedSessionIdsInGroups(filteredGroups), [filteredGroups]);
|
|
842
1878
|
const selectedSessionIdSet = (0, react.useMemo)(() => new Set(selectedSessionIds), [selectedSessionIds]);
|
|
843
1879
|
const selectedVisibleCount = visibleSessionIds.filter((sessionId) => selectedSessionIdSet.has(sessionId)).length;
|
|
844
1880
|
const allVisibleSelected = visibleSessionIds.length > 0 && selectedVisibleCount === visibleSessionIds.length;
|
|
845
|
-
const allBatchTarget = { scope: "all" };
|
|
846
|
-
const allBatchSessionIds = (0, react.useMemo)(() => deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, allBatchTarget), [workspaceState.archivedSessionIds, workspaceState.items]);
|
|
847
1881
|
(0, react.useEffect)(() => {
|
|
848
1882
|
setSelectedSessionIds((current) => pruneArchivedSelection(current, eligibleIds));
|
|
849
1883
|
}, [eligibleIds]);
|
|
@@ -868,6 +1902,11 @@
|
|
|
868
1902
|
};
|
|
869
1903
|
const onBatchUnarchive = async (target) => {
|
|
870
1904
|
if (busy) return;
|
|
1905
|
+
if (organizeBatch) {
|
|
1906
|
+
const ids = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target);
|
|
1907
|
+
const result = await executeBatch("restore", ids);
|
|
1908
|
+
return result && { unarchivedSessionIds: result.succeeded };
|
|
1909
|
+
}
|
|
871
1910
|
setBusy(true);
|
|
872
1911
|
setError(null);
|
|
873
1912
|
setNotice(null);
|
|
@@ -898,7 +1937,7 @@
|
|
|
898
1937
|
if (event.key !== "Escape") return;
|
|
899
1938
|
event.preventDefault();
|
|
900
1939
|
event.stopPropagation();
|
|
901
|
-
if (typeof event.stopImmediatePropagation === "function") event.stopImmediatePropagation();
|
|
1940
|
+
if ("stopImmediatePropagation" in event && typeof event.stopImmediatePropagation === "function") event.stopImmediatePropagation();
|
|
902
1941
|
if (!busy) setDeleteTarget(null);
|
|
903
1942
|
};
|
|
904
1943
|
window.addEventListener("keydown", onKeyDown, true);
|
|
@@ -906,6 +1945,12 @@
|
|
|
906
1945
|
}, [deleteTarget, busy]);
|
|
907
1946
|
const confirmDelete = async () => {
|
|
908
1947
|
if (busy || deleteTarget === null) return;
|
|
1948
|
+
if (organizeBatch && deleteTarget.kind === "batch") {
|
|
1949
|
+
const ids = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, deleteTarget.target);
|
|
1950
|
+
const result = await executeBatch("delete", ids);
|
|
1951
|
+
if (result) setDeleteTarget(null);
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
909
1954
|
setBusy(true);
|
|
910
1955
|
setError(null);
|
|
911
1956
|
setNotice(null);
|
|
@@ -930,9 +1975,9 @@
|
|
|
930
1975
|
}
|
|
931
1976
|
};
|
|
932
1977
|
const batchScope = deleteTarget?.kind === "batch" ? deleteTarget.target.scope : null;
|
|
933
|
-
const deleteDialogTitle = batchScope === "
|
|
934
|
-
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "
|
|
935
|
-
const deleteConfirmLabel = batchScope === "
|
|
1978
|
+
const deleteDialogTitle = batchScope === "ungrouped" ? t("archives.deleteUngroupedTitle") : batchScope === "workspace" ? t("archives.deleteProjectTitle", { name: deleteTarget?.kind === "batch" ? deleteTarget.title : "" }) : batchScope === "sessions" ? t("archives.deleteSelectedTitle") : t("deleteSession.title");
|
|
1979
|
+
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "ungrouped" ? t("archives.deleteUngroupedDesc", { n: deleteTarget.kind === "batch" ? deleteTarget.count : 0 }) : batchScope === "workspace" ? t("archives.deleteProjectDesc", { name: deleteTarget?.kind === "batch" ? deleteTarget.title : "", n: deleteTarget.kind === "batch" ? deleteTarget.count : 0 }) : batchScope === "sessions" ? t("archives.deleteSelectedDesc", { n: deleteTarget.kind === "batch" ? deleteTarget.count : 0 }) : t("deleteSession.desc", { name: displayTitle(deleteTarget.kind === "session" ? deleteTarget.session : {}, t) });
|
|
1980
|
+
const deleteConfirmLabel = batchScope === "ungrouped" ? t("archives.deleteUngroupedConfirm") : batchScope === "workspace" ? t("archives.deleteProjectConfirm") : batchScope === "sessions" ? t("archives.deleteSelectedConfirm") : t("deleteSession.title");
|
|
936
1981
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
937
1982
|
className: "dsham_settings",
|
|
938
1983
|
"aria-label": t("archives.title"),
|
|
@@ -960,21 +2005,45 @@
|
|
|
960
2005
|
event.preventDefault();
|
|
961
2006
|
const next = event.key === "Home" ? "archived" : event.key === "End" ? "unarchived" : isArchived ? "unarchived" : "archived";
|
|
962
2007
|
switchTab(next);
|
|
963
|
-
event.currentTarget.parentElement
|
|
2008
|
+
event.currentTarget.parentElement?.querySelector("#dsham-tab-" + next)?.focus();
|
|
964
2009
|
}
|
|
965
2010
|
},
|
|
966
2011
|
children: t("archives.tab." + tab)
|
|
967
2012
|
}, tab))
|
|
968
|
-
}), isArchived && (0, react_jsx_runtime.jsxs)("div", {
|
|
969
|
-
className: "dsham_settingsHeaderActions",
|
|
970
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsRestoreAll", disabled: busy || allBatchSessionIds.length === 0, onClick: () => onBatchUnarchive(allBatchTarget), children: t("archives.restoreAll") }), (0, react_jsx_runtime.jsxs)("button", { type: "button", className: "dsham_settingsDanger", disabled: busy || allBatchSessionIds.length === 0, onClick: () => setDeleteTarget({ kind: "batch", target: allBatchTarget, title: t("archives.allProjects"), count: allBatchSessionIds.length }), children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}), t("archives.deleteAll")] })]
|
|
971
2013
|
})]
|
|
972
2014
|
}), (0, react_jsx_runtime.jsxs)("div", { id: "dsham-archive-panel", role: "tabpanel", "aria-labelledby": "dsham-tab-" + archiveTab, children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
973
2015
|
className: "dsham_settingsToolbar",
|
|
974
|
-
children: [(0, react_jsx_runtime.jsxs)("
|
|
2016
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
975
2017
|
className: "dsham_settingsSearch",
|
|
976
|
-
children: [(
|
|
977
|
-
|
|
2018
|
+
children: [react.createElement("div", { className: "dsham_searchScope" }, react.createElement(ArchiveProjectSelect, { id: "dsham-search-scope", value: searchScope, "aria-label": t("discovery.scope"), onChange: setSearchScope, options: [{ value: "title", label: t("discovery.titleOnly") }, { value: "content", label: t("discovery.titleAndContent") }] })), (0, react_jsx_runtime.jsx)("input", { type: "search", maxLength: 200, value: query, onChange: (event) => setQuery(event.target.value), placeholder: t(contentEnabled ? "discovery.searchPlaceholder" : isArchived ? "archives.searchPlaceholder" : "archives.searchUnarchived"), "aria-label": t(contentEnabled ? "discovery.searchPlaceholder" : isArchived ? "archives.searchPlaceholder" : "archives.searchUnarchived") }), react.createElement(DiscoveryFilters, { t, from: dateFrom, to: dateTo, onFrom: setDateFrom, onTo: setDateTo, invalid: invalidDate, onClear: () => {
|
|
2019
|
+
setDateFrom("");
|
|
2020
|
+
setDateTo("");
|
|
2021
|
+
} })]
|
|
2022
|
+
}), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-sort-filter", value: sortBy, options: [{ value: "updated", label: t("archives.sortUpdated") }, { value: "created", label: t("archives.sortCreated") }, { value: "alphabetical", label: t("archives.sortAlphabetical") }, ...typeof sessionDetails === "function" ? [{ value: "turnsDesc", label: t("details.more") }, { value: "turnsAsc", label: t("details.less") }] : []], onChange: setSortBy, "aria-label": t("archives.sortBy") }), (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-project-filter", value: project, options: [{ value: "all", label: t("archives.allProjects") }, ...sortedGroups.map((group) => ({ value: group.key, label: group.title }))], onChange: setProject, "aria-label": t("archives.projectFilter") }), typeof setSessionFavorite === "function" && (0, react_jsx_runtime.jsx)(ArchiveProjectSelect, { id: "dsham-favorite-filter", value: favoritesOnly ? "favorites" : "all", disabled: busy || favoriteBusy || !favoritesReady, options: [{ value: "all", label: t("organizer.allSessions") }, { value: "favorites", label: t("organizer.favoritesOnly") }], onChange: (value) => setFavoritesOnly(value === "favorites"), "aria-label": t("organizer.favoriteFilter") })]
|
|
2023
|
+
}), react.createElement("style", null, discoveryCss), react.createElement(SearchStatus, { state: contentSearch, t }), react.createElement(SessionHealthPanel, { key: archiveTab, t, isArchived, items: details.items, sessions: groups.flatMap((group) => group.sessions), diagnoseSession, repairSession, retry: details.retry, pending: details.pending }), organizeBatch && (0, react_jsx_runtime.jsx)(OrganizerPanel, {
|
|
2024
|
+
t,
|
|
2025
|
+
archived: isArchived,
|
|
2026
|
+
busy: busy || favoriteBusy || unarchivingSessionIds.size > 0,
|
|
2027
|
+
ready: favoritesReady,
|
|
2028
|
+
days: idleDays,
|
|
2029
|
+
onDays: setIdleDays,
|
|
2030
|
+
count: idleCandidates.length,
|
|
2031
|
+
onPreview: () => {
|
|
2032
|
+
requestArchive(idleCandidates);
|
|
2033
|
+
setIdleRequest(true);
|
|
2034
|
+
},
|
|
2035
|
+
progress: batchProgress,
|
|
2036
|
+
result: batchResult?.tab === archiveTab ? batchResult : null,
|
|
2037
|
+
onRetry: () => {
|
|
2038
|
+
const retry = retryBatch.current;
|
|
2039
|
+
if (retry) {
|
|
2040
|
+
if (retry.kind === "delete") setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: retry.ids }, count: retry.ids.length });
|
|
2041
|
+
else executeBatch(retry.kind, retry.ids, { idle: retry.idle, retry: true });
|
|
2042
|
+
}
|
|
2043
|
+
},
|
|
2044
|
+
undoCount: lastArchive.filter((id2) => workspaceState.archivedSessionIds.includes(id2)).length,
|
|
2045
|
+
onUndo: () => executeBatch("undo", lastArchive, { retry: true }),
|
|
2046
|
+
onReload: loadFavorites
|
|
978
2047
|
}), groups.length > 0 && (0, react_jsx_runtime.jsx)(ArchiveSelectionToolbar, {
|
|
979
2048
|
selectedCount: selectedSessionIds.length,
|
|
980
2049
|
hiddenCount: selectedSessionIds.length - selectedVisibleCount,
|
|
@@ -988,7 +2057,7 @@
|
|
|
988
2057
|
onArchive: isArchived ? void 0 : () => requestArchive([...selectedSessionIds]),
|
|
989
2058
|
onRestore: onSelectedUnarchive,
|
|
990
2059
|
onDelete: () => setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: selectedSessionIds }, count: selectedSessionIds.length })
|
|
991
|
-
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t(isArchived ? "archives.empty" : "archives.emptyUnarchived") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
2060
|
+
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t(isArchived ? "archives.empty" : "archives.emptyUnarchived") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: contentSearch.status === "loading" || contentSearch.status === "error" || contentSearch.failures.length ? null : t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
992
2061
|
const target = archivedBatchTargetForGroup(group.key);
|
|
993
2062
|
const groupSessionIds = groups.find((item) => item.key === group.key)?.sessions.map((session) => session.id) ?? [];
|
|
994
2063
|
const count = isArchived ? deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length : groupSessionIds.length;
|
|
@@ -996,18 +2065,50 @@
|
|
|
996
2065
|
className: "dsham_settingsGroup",
|
|
997
2066
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
998
2067
|
className: "dsham_settingsGroupHeading",
|
|
999
|
-
children: [(0, react_jsx_runtime.
|
|
2068
|
+
children: [(0, react_jsx_runtime.jsx)("h3", { className: "dsham_settingsGroupTitle", children: (0, react_jsx_runtime.jsxs)("button", { type: "button", className: "dsham_groupToggle", "aria-expanded": !collapsedGroups.has(group.key), "aria-controls": "dsham-group-" + encodeURIComponent(group.key), onClick: () => setCollapsedGroups((previous) => {
|
|
2069
|
+
const next = new Set(previous);
|
|
2070
|
+
if (next.has(group.key)) next.delete(group.key);
|
|
2071
|
+
else next.add(group.key);
|
|
2072
|
+
return next;
|
|
2073
|
+
}), children: [(0, react_jsx_runtime.jsx)(collapsedGroups.has(group.key) ? _deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14 : _deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}), (0, react_jsx_runtime.jsx)("span", { children: group.title })] }) }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsGroupMeta", children: [(0, react_jsx_runtime.jsx)("span", { className: "dsham_settingsCount", children: t("archives.sessionCount", { n: group.sessions.length }) }), (0, react_jsx_runtime.jsx)(ArchivedGroupActions, { group, busy, onArchive: isArchived ? void 0 : () => requestArchive(groupSessionIds, group), onRestore: () => onBatchUnarchive(target), onDelete: () => setDeleteTarget({ kind: "batch", target, title: group.title, count }), t })] })]
|
|
1000
2074
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1001
2075
|
className: "dsham_settingsList",
|
|
1002
|
-
|
|
2076
|
+
id: "dsham-group-" + encodeURIComponent(group.key),
|
|
2077
|
+
hidden: collapsedGroups.has(group.key),
|
|
2078
|
+
children: !collapsedGroups.has(group.key) && group.sessions.map((session) => (0, react_jsx_runtime.jsxs)("article", {
|
|
1003
2079
|
className: "dsham_settingsRow",
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
2080
|
+
"data-selected": selectedSessionIdSet.has(session.id),
|
|
2081
|
+
children: [
|
|
2082
|
+
(0, react_jsx_runtime.jsx)(ArchiveSelectionCheckbox, { checked: selectedSessionIdSet.has(session.id), disabled: busy, label: t("archives.selectSession", { name: displayTitle(session, t) }), onChange: (event) => toggleSessionSelection(session.id, event.target.checked) }),
|
|
2083
|
+
(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsContent", children: [
|
|
2084
|
+
(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsTitleLink", title: displayTitle(session, t), "aria-label": t("archives.openSession") + t("common.separator") + displayTitle(session, t), disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session), children: displayTitle(session, t) }),
|
|
2085
|
+
(0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsMeta", children: [archiveTimeLabel(session.updatedAt, t), typeof sessionDetails === "function" && react.createElement("span", { key: "turns", title: details.byId[session.id]?.error || t("details.hint") }, " \xB7 ", t(typeof details.byId[session.id]?.turnCount === "number" ? "details.turns" : details.byId[session.id] ? "details.unknown" : "details.pending", { n: details.byId[session.id]?.turnCount }))] }),
|
|
2086
|
+
contentMatches.has(session.id) && react.createElement("button", { type: "button", className: "dsham_settingsSnippet", disabled: busy, title: t(isArchived ? "discovery.preview" : "archives.openSession"), onClick: () => isArchived ? preview.open(session, query) : viewConversation(session) }, react.createElement(HighlightedText, { text: contentMatches.get(session.id)?.snippet ?? "", query }))
|
|
2087
|
+
] }),
|
|
2088
|
+
(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsActions", children: [
|
|
2089
|
+
typeof setSessionFavorite === "function" && (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_favorite", title: t(favoriteSet.has(session.id) ? "organizer.unfavorite" : "organizer.favorite"), "aria-pressed": favoriteSet.has(session.id), "aria-label": t(favoriteSet.has(session.id) ? "organizer.unfavorite" : "organizer.favorite") + t("common.separator") + displayTitle(session, t), disabled: busy || favoriteBusy || !favoritesReady, onClick: () => toggleFavorite(session.id), children: (0, react_jsx_runtime.jsx)("span", { "aria-hidden": true, children: favoriteSet.has(session.id) ? "\u2605" : "\u2606" }) }),
|
|
2090
|
+
(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_restoreIcon", title: t(isArchived ? "archives.restore" : "archives.archiveSelected"), "aria-label": t(isArchived ? "archives.restore" : "archives.archiveSelected"), disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => isArchived ? onUnarchive(session.id) : requestArchive([session.id]), children: (0, react_jsx_runtime.jsx)(isArchived ? _deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16 : _deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 }) }),
|
|
2091
|
+
(isArchived || typeof sessionDetails === "function") && (0, react_jsx_runtime.jsx)(ArchivedSessionMenu, { busy: busy || unarchivingSessionIds.has(session.id), t, title: displayTitle(session, t), onCopyId: () => copyDetail(session, "id"), onCopyPath: typeof sessionDetails === "function" ? () => copyDetail(session, "path") : void 0, onPreview: isArchived && typeof previewArchivedSession === "function" ? () => preview.open(session, query) : void 0, onRestoreOpen: isArchived ? () => viewConversation(session, true) : void 0, onDelete: isArchived ? () => setDeleteTarget({ kind: "session", session }) : void 0 })
|
|
2092
|
+
] })
|
|
2093
|
+
]
|
|
1008
2094
|
}, session.id))
|
|
1009
2095
|
})]
|
|
1010
2096
|
}, group.key);
|
|
2097
|
+
}), react.createElement(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2098
|
+
className: "dsham_previewDialog",
|
|
2099
|
+
contentClassName: "dsham_previewDialogContent",
|
|
2100
|
+
open: preview.target !== null,
|
|
2101
|
+
onClose: preview.close,
|
|
2102
|
+
closeLabel: t("close"),
|
|
2103
|
+
title: preview.target ? displayTitle(preview.target.session, t) : t("discovery.preview"),
|
|
2104
|
+
footer: react.createElement(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: () => {
|
|
2105
|
+
if (preview.target) {
|
|
2106
|
+
const session = preview.target.session;
|
|
2107
|
+
preview.close();
|
|
2108
|
+
return viewConversation(session);
|
|
2109
|
+
}
|
|
2110
|
+
} }, t("discovery.openFull")),
|
|
2111
|
+
children: react.createElement(PreviewContent, { preview, t, MarkdownText: _deepseek_ai_dsh_client_ui_primitives.MarkdownText })
|
|
1011
2112
|
}), archiveTarget === null && error !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error }), notice !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsStatus", role: "status", children: notice }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1012
2113
|
open: archiveTarget !== null,
|
|
1013
2114
|
onClose: closeArchive,
|
|
@@ -1016,9 +2117,14 @@
|
|
|
1016
2117
|
description: archiveGroup === null ? t("archives.archiveSelectedDesc") : t(archiveGroup.key === ARCHIVE_UNGROUPED_KEY ? "archives.archiveUngroupedDesc" : "archives.archiveProjectDesc", { name: archiveGroup.title, n: archiveTarget?.length ?? 0 }),
|
|
1017
2118
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1018
2119
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeArchive, children: t("cancel") }),
|
|
1019
|
-
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_archiveWorkspaceConfirm", disabled: busy, onClick: confirmArchive, children: t("archives.archiveSelected") })
|
|
2120
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_archiveWorkspaceConfirm", disabled: busy || !archiveTarget?.length, onClick: confirmArchive, children: t("archives.archiveSelected") })
|
|
1020
2121
|
] }),
|
|
1021
|
-
children:
|
|
2122
|
+
children: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2123
|
+
organizeBatch && (0, react_jsx_runtime.jsx)("p", { children: t(idleRequest ? "organizer.idleConfirm" : "organizer.manualConfirm") }),
|
|
2124
|
+
organizeBatch && (0, react_jsx_runtime.jsx)("div", { className: "dsham_archivePreview", children: (archiveTarget ?? []).map((id2) => (0, react_jsx_runtime.jsxs)("label", { children: [(0, react_jsx_runtime.jsx)("input", { type: "checkbox", checked: true, disabled: busy, onChange: () => setArchiveTarget((current) => (current ?? []).filter((value) => value !== id2)) }), displayTitle(sessions.byId[id2] ?? { id: id2 }, t)] }, id2)) }),
|
|
2125
|
+
batchProgress && (0, react_jsx_runtime.jsxs)("div", { role: "status", children: [(0, react_jsx_runtime.jsx)("progress", { value: batchProgress.done, max: Math.max(1, batchProgress.total) }), t("organizer.progressCount", { done: batchProgress.done, total: batchProgress.total })] }),
|
|
2126
|
+
error !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error })
|
|
2127
|
+
] })
|
|
1022
2128
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1023
2129
|
open: deleteTarget !== null,
|
|
1024
2130
|
onClose: closeDelete,
|
|
@@ -1026,7 +2132,7 @@
|
|
|
1026
2132
|
title: deleteDialogTitle,
|
|
1027
2133
|
...deleteDialogDescription === void 0 ? {} : { description: deleteDialogDescription },
|
|
1028
2134
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeDelete, children: t("cancel") }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_settingsDeleteConfirm", disabled: busy, onClick: confirmDelete, children: deleteConfirmLabel })] }),
|
|
1029
|
-
children: busy && (0, react_jsx_runtime.
|
|
2135
|
+
children: busy && (0, react_jsx_runtime.jsxs)("div", { role: "status", children: [deleteTarget?.kind === "batch" ? t("archives.deleteBatchPending") : t("deleteSession.pending"), batchProgress && (0, react_jsx_runtime.jsx)("progress", { value: batchProgress.done, max: Math.max(1, batchProgress.total), "aria-label": t("organizer.progress") }), batchProgress && t("organizer.progressCount", { done: batchProgress.done, total: batchProgress.total })] })
|
|
1030
2136
|
})] })]
|
|
1031
2137
|
});
|
|
1032
2138
|
}
|
|
@@ -1039,7 +2145,7 @@
|
|
|
1039
2145
|
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
1040
2146
|
return n;
|
|
1041
2147
|
}
|
|
1042
|
-
function clsx() {
|
|
2148
|
+
function clsx(..._values) {
|
|
1043
2149
|
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
1044
2150
|
return n;
|
|
1045
2151
|
}
|
|
@@ -1115,16 +2221,16 @@
|
|
|
1115
2221
|
const accounted = /* @__PURE__ */ new Set();
|
|
1116
2222
|
for (const workspace of workspaces) {
|
|
1117
2223
|
const members = [];
|
|
1118
|
-
for (const
|
|
1119
|
-
const summary = list.byId[
|
|
2224
|
+
for (const id2 of workspace.sessionIds) {
|
|
2225
|
+
const summary = list.byId[id2];
|
|
1120
2226
|
if (summary === void 0) continue;
|
|
1121
|
-
accounted.add(
|
|
2227
|
+
accounted.add(id2);
|
|
1122
2228
|
if (!sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1123
2229
|
members.push(summary);
|
|
1124
2230
|
}
|
|
1125
2231
|
groups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members, "account"));
|
|
1126
2232
|
}
|
|
1127
|
-
const stray = list.ids.map((
|
|
2233
|
+
const stray = list.ids.map((id2) => list.byId[id2]).filter((s) => s !== void 0 && !accounted.has(s.id) && sessionVisible(s, currentSessionId(list), archived, showArchived));
|
|
1128
2234
|
if (stray.length > 0) groups.push(buildGroup("", void 0, void 0, void 0, UNGROUPED_LABEL, ungroupedOrder === void 0 ? stray : orderedUngrouped(stray, ungroupedOrder), ungroupedOrder === void 0 ? "recency" : "account"));
|
|
1129
2235
|
return groups;
|
|
1130
2236
|
}
|
|
@@ -1178,9 +2284,9 @@
|
|
|
1178
2284
|
const pending = /* @__PURE__ */ new Map();
|
|
1179
2285
|
const completed = /* @__PURE__ */ new Set();
|
|
1180
2286
|
if (status instanceof Map) {
|
|
1181
|
-
for (const [
|
|
1182
|
-
if (entry?.pendingInteraction !== void 0) pending.set(
|
|
1183
|
-
if (entry?.completionUnread === true) completed.add(
|
|
2287
|
+
for (const [id2, entry] of status) {
|
|
2288
|
+
if (entry?.pendingInteraction !== void 0) pending.set(id2, entry.pendingInteraction);
|
|
2289
|
+
if (entry?.completionUnread === true) completed.add(id2);
|
|
1184
2290
|
}
|
|
1185
2291
|
}
|
|
1186
2292
|
return { pending, completed };
|
|
@@ -1232,8 +2338,8 @@
|
|
|
1232
2338
|
const archived = new Set(archivedSessionIds);
|
|
1233
2339
|
const descendants = indexSubagentDescendants(list.byId);
|
|
1234
2340
|
const rows = [];
|
|
1235
|
-
for (const
|
|
1236
|
-
const s = list.byId[
|
|
2341
|
+
for (const id2 of list.ids) {
|
|
2342
|
+
const s = list.byId[id2];
|
|
1237
2343
|
if (s === void 0 || !sessionVisible(s, currentSessionId(list), archived, showArchived)) continue;
|
|
1238
2344
|
rows.push(s);
|
|
1239
2345
|
}
|
|
@@ -1254,8 +2360,8 @@
|
|
|
1254
2360
|
const contentBySession = /* @__PURE__ */ new Map();
|
|
1255
2361
|
for (const item of content.items) if (!contentBySession.has(item.sessionId)) contentBySession.set(item.sessionId, item);
|
|
1256
2362
|
const local = [];
|
|
1257
|
-
for (const
|
|
1258
|
-
const summary = list.byId[
|
|
2363
|
+
for (const id2 of list.ids) {
|
|
2364
|
+
const summary = list.byId[id2];
|
|
1259
2365
|
if (summary === void 0 || summary.blank || !sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1260
2366
|
if (sessionTitle(summary).toLowerCase().includes(q) || labelOf(summary).toLowerCase().includes(q)) local.push(summary);
|
|
1261
2367
|
}
|
|
@@ -1384,7 +2490,7 @@
|
|
|
1384
2490
|
return unit === "now" ? t("time.now") : t("time.ago", { t: t(`time.${unit}`, { n }) });
|
|
1385
2491
|
}
|
|
1386
2492
|
function createdLabel(createdAt, t) {
|
|
1387
|
-
const d = new Date(createdAt);
|
|
2493
|
+
const d = new Date(createdAt ?? NaN);
|
|
1388
2494
|
const pad2 = (v) => String(v).padStart(2, "0");
|
|
1389
2495
|
return t("hover.created", { time: `${t("date.ymd", {
|
|
1390
2496
|
y: d.getFullYear(),
|
|
@@ -1470,11 +2576,11 @@
|
|
|
1470
2576
|
setMenuOpen(false);
|
|
1471
2577
|
},
|
|
1472
2578
|
items: workspaceMenuItems,
|
|
1473
|
-
onSelect: (
|
|
2579
|
+
onSelect: (id2) => {
|
|
1474
2580
|
setMenuOpen(false);
|
|
1475
|
-
if (
|
|
1476
|
-
if (
|
|
1477
|
-
else if (
|
|
2581
|
+
if (id2 !== "rename" && id2 !== "archive-workspace" && id2 !== "delete") return;
|
|
2582
|
+
if (id2 === "rename") actions.rename();
|
|
2583
|
+
else if (id2 === "archive-workspace") actions.archive();
|
|
1478
2584
|
else actions.delete();
|
|
1479
2585
|
},
|
|
1480
2586
|
portal: true,
|
|
@@ -1760,13 +2866,13 @@
|
|
|
1760
2866
|
setMenuOpen(false);
|
|
1761
2867
|
},
|
|
1762
2868
|
items: sessionMenuItems,
|
|
1763
|
-
onSelect: (
|
|
2869
|
+
onSelect: (id2) => {
|
|
1764
2870
|
setMenuOpen(false);
|
|
1765
|
-
if (
|
|
1766
|
-
if (
|
|
1767
|
-
if (
|
|
1768
|
-
if (
|
|
1769
|
-
if (
|
|
2871
|
+
if (id2 === "rename") onRename(node.id, row.title);
|
|
2872
|
+
if (id2 === "fork") onFork(node.id);
|
|
2873
|
+
if (id2 === "archive") onArchive(node.id);
|
|
2874
|
+
if (id2 === "unarchive") onUnarchive(node.id);
|
|
2875
|
+
if (id2 === "delete-session") onDeleteSession(node.id, row.title);
|
|
1770
2876
|
},
|
|
1771
2877
|
portal: true,
|
|
1772
2878
|
closeOnPointerLeave: true,
|
|
@@ -1883,12 +2989,12 @@
|
|
|
1883
2989
|
setErrorOpen(true);
|
|
1884
2990
|
}
|
|
1885
2991
|
};
|
|
1886
|
-
const handleSelect = (
|
|
1887
|
-
if (
|
|
2992
|
+
const handleSelect = (id2) => {
|
|
2993
|
+
if (id2 === ADD_WORKSPACE) {
|
|
1888
2994
|
openDirectoryFlow();
|
|
1889
2995
|
return;
|
|
1890
2996
|
}
|
|
1891
|
-
onPick(
|
|
2997
|
+
onPick(id2);
|
|
1892
2998
|
};
|
|
1893
2999
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1894
3000
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
@@ -2017,18 +3123,18 @@
|
|
|
2017
3123
|
}
|
|
2018
3124
|
function reconciledSessionOrder(sessionIds, stored) {
|
|
2019
3125
|
if (stored === void 0) return [...sessionIds];
|
|
2020
|
-
const byId = new Map(sessionIds.map((
|
|
3126
|
+
const byId = new Map(sessionIds.map((id2) => [id2, id2]));
|
|
2021
3127
|
const ordered = [];
|
|
2022
3128
|
const included = /* @__PURE__ */ new Set();
|
|
2023
3129
|
for (const key of stored) {
|
|
2024
|
-
const
|
|
2025
|
-
if (
|
|
2026
|
-
ordered.push(
|
|
3130
|
+
const id2 = byId.get(key);
|
|
3131
|
+
if (id2 === void 0 || included.has(key)) continue;
|
|
3132
|
+
ordered.push(id2);
|
|
2027
3133
|
included.add(key);
|
|
2028
3134
|
}
|
|
2029
|
-
for (const
|
|
2030
|
-
if (included.has(
|
|
2031
|
-
ordered.push(
|
|
3135
|
+
for (const id2 of sessionIds) {
|
|
3136
|
+
if (included.has(id2)) continue;
|
|
3137
|
+
ordered.push(id2);
|
|
2032
3138
|
}
|
|
2033
3139
|
return ordered;
|
|
2034
3140
|
}
|
|
@@ -2042,22 +3148,22 @@
|
|
|
2042
3148
|
let order = reconciledSessionOrder(sessionIds, previousOrder);
|
|
2043
3149
|
if (sortByRecency) order.sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
2044
3150
|
else if (orderBy === "updated") {
|
|
2045
|
-
const promoted = sessionIds.filter((
|
|
2046
|
-
const session = list.byId[
|
|
2047
|
-
return session !== void 0 && (previousUpdatedAt[
|
|
3151
|
+
const promoted = sessionIds.filter((id2) => {
|
|
3152
|
+
const session = list.byId[id2];
|
|
3153
|
+
return session !== void 0 && (previousUpdatedAt[id2] === void 0 || session.updatedAt > previousUpdatedAt[id2]);
|
|
2048
3154
|
}).sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
2049
3155
|
if (promoted.length > 0) {
|
|
2050
3156
|
const promotedIds = new Set(promoted);
|
|
2051
|
-
order = [...promoted, ...order.filter((
|
|
3157
|
+
order = [...promoted, ...order.filter((id2) => !promotedIds.has(id2))];
|
|
2052
3158
|
}
|
|
2053
3159
|
}
|
|
2054
3160
|
const updatedAt = {};
|
|
2055
|
-
for (const
|
|
2056
|
-
const session = list.byId[
|
|
2057
|
-
if (session !== void 0) updatedAt[
|
|
3161
|
+
for (const id2 of sessionIds) {
|
|
3162
|
+
const session = list.byId[id2];
|
|
3163
|
+
if (session !== void 0) updatedAt[id2] = session.updatedAt;
|
|
2058
3164
|
}
|
|
2059
|
-
const orderChanged = previousOrder === void 0 || order.length !== previousOrder.length || order.some((
|
|
2060
|
-
const timestampsChanged = Object.keys(updatedAt).length !== Object.keys(previousUpdatedAt).length || Object.entries(updatedAt).some(([
|
|
3165
|
+
const orderChanged = previousOrder === void 0 || order.length !== previousOrder.length || order.some((id2, index) => id2 !== previousOrder[index]);
|
|
3166
|
+
const timestampsChanged = Object.keys(updatedAt).length !== Object.keys(previousUpdatedAt).length || Object.entries(updatedAt).some(([id2, timestamp]) => previousUpdatedAt[id2] !== timestamp);
|
|
2061
3167
|
return {
|
|
2062
3168
|
order,
|
|
2063
3169
|
updatedAt,
|
|
@@ -2104,9 +3210,9 @@
|
|
|
2104
3210
|
}
|
|
2105
3211
|
],
|
|
2106
3212
|
selectedIds: [groupBy, orderBy],
|
|
2107
|
-
onSelect: (
|
|
2108
|
-
if (
|
|
2109
|
-
else if (
|
|
3213
|
+
onSelect: (id2) => {
|
|
3214
|
+
if (id2 === "workspace" || id2 === "flat") onGroupPick(id2);
|
|
3215
|
+
else if (id2 === "manual" || id2 === "updated") onOrderPick(id2);
|
|
2110
3216
|
setOpen(false);
|
|
2111
3217
|
},
|
|
2112
3218
|
align: "end",
|
|
@@ -2132,7 +3238,7 @@
|
|
|
2132
3238
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
2133
3239
|
return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
2134
3240
|
}
|
|
2135
|
-
function SessionTree({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onArchiveRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
3241
|
+
function SessionTree({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, startSession, open, forkSession, workspaces, archivedSessionIds, showArchived, onRenameRequest, onArchiveRequest, onDeleteRequest, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, insertWorkspaceBefore, insertSessionBefore, orderBy, groupExpansion, setGroupExpanded, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed, showArchivedToast }) {
|
|
2136
3242
|
const list = useSessions((s) => s);
|
|
2137
3243
|
const pendingInteractions = useSessionUiFacts(useSessionPendingInteraction, useSessionStatus, preferSessionStatus);
|
|
2138
3244
|
const current = currentSessionId(list);
|
|
@@ -2165,7 +3271,7 @@
|
|
|
2165
3271
|
const expandedGroups = (0, react.useMemo)(() => Object.entries(groupExpansion).filter(([, expanded]) => expanded).map(([key]) => key), [groupExpansion]);
|
|
2166
3272
|
const ungroupedSessionIds = (0, react.useMemo)(() => {
|
|
2167
3273
|
const accounted = new Set(workspaces.flatMap((workspace) => workspace.sessionIds));
|
|
2168
|
-
return list.ids.filter((
|
|
3274
|
+
return list.ids.filter((id2) => list.byId[id2] !== void 0 && !accounted.has(id2));
|
|
2169
3275
|
}, [list, workspaces]);
|
|
2170
3276
|
(0, react.useEffect)(() => {
|
|
2171
3277
|
if (list.phase !== "ready") return;
|
|
@@ -2173,7 +3279,7 @@
|
|
|
2173
3279
|
previousOrderBy.current = orderBy;
|
|
2174
3280
|
const accounts = [...workspaces.map((workspace) => ({
|
|
2175
3281
|
key: workspace.workspaceId,
|
|
2176
|
-
sessionIds: workspace.sessionIds.filter((
|
|
3282
|
+
sessionIds: workspace.sessionIds.filter((id2) => list.byId[id2] !== void 0)
|
|
2177
3283
|
})), {
|
|
2178
3284
|
key: "",
|
|
2179
3285
|
sessionIds: ungroupedSessionIds
|
|
@@ -2188,7 +3294,7 @@
|
|
|
2188
3294
|
orderBy,
|
|
2189
3295
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2190
3296
|
});
|
|
2191
|
-
if (next.changed && typeof syncSessionOrderAccount === "function") syncSessionOrderAccount(key, next.order.map((
|
|
3297
|
+
if (next.changed && typeof syncSessionOrderAccount === "function") syncSessionOrderAccount(key, next.order.map((id2) => id2), next.updatedAt);
|
|
2192
3298
|
}
|
|
2193
3299
|
}, [
|
|
2194
3300
|
list,
|
|
@@ -2250,10 +3356,10 @@
|
|
|
2250
3356
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2251
3357
|
const accountSessionIds = activeDrag.accountKey === "" ? orderedUngroupedSessionIds : orderedWorkspaces.find((workspace) => workspace.workspaceId === activeDrag.accountKey)?.sessionIds;
|
|
2252
3358
|
if (accountSessionIds === void 0) return;
|
|
2253
|
-
const nextOrder = accountSessionIds.filter((
|
|
3359
|
+
const nextOrder = accountSessionIds.filter((id2) => id2 !== activeDrag.sessionId);
|
|
2254
3360
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2255
3361
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2256
|
-
setSessionOrder(activeDrag.accountKey, nextOrder.map((
|
|
3362
|
+
setSessionOrder(activeDrag.accountKey, nextOrder.map((id2) => id2));
|
|
2257
3363
|
if (orderBy === "updated" || activeDrag.accountKey === "") return;
|
|
2258
3364
|
insertSessionBefore(activeDrag.accountKey, activeDrag.sessionId, anchor).catch((reason) => {
|
|
2259
3365
|
console.warn("session reorder rejected:", reason);
|
|
@@ -2373,9 +3479,7 @@
|
|
|
2373
3479
|
onOpen: open,
|
|
2374
3480
|
onRename: onSessionRename,
|
|
2375
3481
|
onFork: (sessionId) => {
|
|
2376
|
-
|
|
2377
|
-
showArchivedToast(formatForkError(reason, t));
|
|
2378
|
-
});
|
|
3482
|
+
void forkWithFeedback(sessionId, forkSession, showArchivedToast, t);
|
|
2379
3483
|
},
|
|
2380
3484
|
onArchive: onSessionArchive,
|
|
2381
3485
|
onUnarchive: onSessionUnarchive,
|
|
@@ -2436,7 +3540,7 @@
|
|
|
2436
3540
|
]
|
|
2437
3541
|
});
|
|
2438
3542
|
}
|
|
2439
|
-
function FlatList({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
3543
|
+
function FlatList({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed, showArchivedToast }) {
|
|
2440
3544
|
const list = useSessions((s) => s);
|
|
2441
3545
|
const pendingInteractions = useSessionUiFacts(useSessionPendingInteraction, useSessionStatus, preferSessionStatus);
|
|
2442
3546
|
const current = currentSessionId(list);
|
|
@@ -2462,7 +3566,7 @@
|
|
|
2462
3566
|
orderBy,
|
|
2463
3567
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2464
3568
|
});
|
|
2465
|
-
if (next.changed) syncSessionOrderAccount(FLAT_SESSION_ORDER_KEY, next.order.map((
|
|
3569
|
+
if (next.changed) syncSessionOrderAccount(FLAT_SESSION_ORDER_KEY, next.order.map((id2) => id2), next.updatedAt);
|
|
2466
3570
|
}, [
|
|
2467
3571
|
list,
|
|
2468
3572
|
orderBy,
|
|
@@ -2473,8 +3577,8 @@
|
|
|
2473
3577
|
]);
|
|
2474
3578
|
const rows = (0, react.useMemo)(() => {
|
|
2475
3579
|
const byId = new Map(baseRows.map((row) => [row.id, row]));
|
|
2476
|
-
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((
|
|
2477
|
-
const row = byId.get(
|
|
3580
|
+
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((id2) => {
|
|
3581
|
+
const row = byId.get(id2);
|
|
2478
3582
|
return row === void 0 ? [] : [row];
|
|
2479
3583
|
});
|
|
2480
3584
|
}, [
|
|
@@ -2496,10 +3600,10 @@
|
|
|
2496
3600
|
const sourceIndex = rows.findIndex((row) => row.id === activeDrag.sessionId);
|
|
2497
3601
|
const anchorIndex = anchor === void 0 ? rows.length : rows.findIndex((row) => row.id === anchor);
|
|
2498
3602
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2499
|
-
const nextOrder = rows.map((row) => row.id).filter((
|
|
3603
|
+
const nextOrder = rows.map((row) => row.id).filter((id2) => id2 !== activeDrag.sessionId);
|
|
2500
3604
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2501
3605
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2502
|
-
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((
|
|
3606
|
+
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((id2) => id2));
|
|
2503
3607
|
};
|
|
2504
3608
|
const now = Date.now();
|
|
2505
3609
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -2520,9 +3624,7 @@
|
|
|
2520
3624
|
onOpen: open,
|
|
2521
3625
|
onRename: onSessionRename,
|
|
2522
3626
|
onFork: (sessionId) => {
|
|
2523
|
-
|
|
2524
|
-
showArchivedToast(formatForkError(reason, t));
|
|
2525
|
-
});
|
|
3627
|
+
void forkWithFeedback(sessionId, forkSession, showArchivedToast, t);
|
|
2526
3628
|
},
|
|
2527
3629
|
onArchive: onSessionArchive,
|
|
2528
3630
|
onUnarchive: onSessionUnarchive,
|
|
@@ -2665,7 +3767,7 @@
|
|
|
2665
3767
|
};
|
|
2666
3768
|
const [archivedToast, setArchivedToast] = (0, react.useState)(null);
|
|
2667
3769
|
const archivedToastSeq = (0, react.useRef)(0);
|
|
2668
|
-
const
|
|
3770
|
+
const showArchivedToast = (text) => {
|
|
2669
3771
|
archivedToastSeq.current += 1;
|
|
2670
3772
|
setArchivedToast({
|
|
2671
3773
|
text,
|
|
@@ -2674,7 +3776,7 @@
|
|
|
2674
3776
|
};
|
|
2675
3777
|
const guardedOpen = (sessionId) => {
|
|
2676
3778
|
if (archivedSet.has(sessionId)) {
|
|
2677
|
-
|
|
3779
|
+
showArchivedToast(t("archived.notOpenable"));
|
|
2678
3780
|
return;
|
|
2679
3781
|
}
|
|
2680
3782
|
open(sessionId);
|
|
@@ -2840,7 +3942,7 @@
|
|
|
2840
3942
|
};
|
|
2841
3943
|
const onSessionArchive = (sessionId) => {
|
|
2842
3944
|
archiveSession(sessionId).catch((reason) => {
|
|
2843
|
-
|
|
3945
|
+
showArchivedToast(formatArchiveError(reason, t));
|
|
2844
3946
|
});
|
|
2845
3947
|
};
|
|
2846
3948
|
const [archiveWorkspaceTarget, setArchiveWorkspaceTarget] = (0, react.useState)(null);
|
|
@@ -2899,7 +4001,7 @@
|
|
|
2899
4001
|
};
|
|
2900
4002
|
const onSessionUnarchive = (sessionId) => {
|
|
2901
4003
|
unarchiveSession(sessionId).catch((reason) => {
|
|
2902
|
-
|
|
4004
|
+
showArchivedToast(formatUnarchiveError(reason, t));
|
|
2903
4005
|
});
|
|
2904
4006
|
};
|
|
2905
4007
|
const [deleteSessionTarget, setDeleteSessionTarget] = (0, react.useState)(null);
|
|
@@ -3093,6 +4195,7 @@
|
|
|
3093
4195
|
open: guardedOpen,
|
|
3094
4196
|
revealSessionId,
|
|
3095
4197
|
onSessionRevealed: acknowledgeSessionReveal,
|
|
4198
|
+
showArchivedToast,
|
|
3096
4199
|
forkSession,
|
|
3097
4200
|
onSessionRename,
|
|
3098
4201
|
onSessionArchive,
|
|
@@ -3116,6 +4219,7 @@
|
|
|
3116
4219
|
preferSessionStatus,
|
|
3117
4220
|
revealSessionId,
|
|
3118
4221
|
onSessionRevealed: acknowledgeSessionReveal,
|
|
4222
|
+
showArchivedToast,
|
|
3119
4223
|
onSessionRename,
|
|
3120
4224
|
onSessionArchive,
|
|
3121
4225
|
onSessionUnarchive,
|
|
@@ -3353,13 +4457,13 @@
|
|
|
3353
4457
|
]
|
|
3354
4458
|
});
|
|
3355
4459
|
}
|
|
3356
|
-
const ARCHIVE_TABS_CSS = ".dsham_archiveTabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_archiveTab{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;padding:12px 2px;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-weight:600;cursor:pointer}.dsham_archiveTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary)}.dsham_archiveTab:focus-visible{outline:2px solid var(--dsw-alias-state-
|
|
3357
|
-
const ARCHIVE_SETTINGS_CSS = ".dsham_settings{container-type:inline-size;min-width:0;box-sizing:border-box;width:min(100%,760px);margin:0 auto;padding:0 0 32px;color:var(--dsw-alias-label-primary)}.dsham_settingsHeader{display:flex;flex-direction:column;align-items:stretch;gap:16px;margin-bottom:16px}.dsham_settings h2{margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px;white-space:nowrap}.dsham_settingsIntro{margin:12px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}.dsham_settingsDanger{display:inline-flex;align-items:center;gap:6px;min-height:32px;padding:0 12px;color:var(--dsw-alias-state-error-primary);background:transparent;border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsDanger:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)}.dsham_settingsToolbar{display:
|
|
3358
|
-
const ARCHIVE_SETTINGS_BATCH_CSS = ".dsham_settingsHeaderActions,.dsham_settingsGroupMeta{display:flex;align-items:center;gap:8px;flex:none;flex-wrap:wrap}.dsham_settingsRestoreAll{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsRestoreAll:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsRestoreAll:disabled,.dsham_settingsDanger:disabled,.dsham_settingsGroupMenu:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsGroupMenu{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsGroupMenu:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsStatus{margin-top:10px;color:var(--dsw-alias-label-secondary);font-size:12px}@media(max-width:720px){.dsham_settingsHeader{flex-direction:column}.dsham_settingsHeaderActions{align-self:flex-start}}";
|
|
3359
|
-
const ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS = ".dsham_settingsTitleRow{display:flex;align-items:center;gap:8px 12px;min-width:0;flex-wrap:wrap}.dsham_settingsLinks{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.dsham_settingsExternalLink{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dsham_settingsExternalLink:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsExternalLink:focus-visible{outline:2px solid var(--dsw-alias-state-
|
|
4460
|
+
const ARCHIVE_TABS_CSS = ".dsham_archiveTabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_archiveTab{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;padding:12px 2px;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-weight:600;cursor:pointer}.dsham_archiveTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary)}.dsham_archiveTab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dsham_archiveTab:disabled{opacity:.5;cursor:not-allowed}@container(max-width:520px){.dsham_archiveTabs{gap:16px}}";
|
|
4461
|
+
const ARCHIVE_SETTINGS_CSS = ".dsham_settings{container-type:inline-size;min-width:0;box-sizing:border-box;width:min(100%,760px);margin:0 auto;padding:0 0 32px;color:var(--dsw-alias-label-primary)}.dsham_settingsHeader{display:flex;flex-direction:column;align-items:stretch;gap:16px;margin-bottom:16px}.dsham_settings h2{margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px;white-space:nowrap}.dsham_settingsIntro{margin:12px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}.dsham_settingsDanger{display:inline-flex;align-items:center;gap:6px;min-height:32px;padding:0 12px;color:var(--dsw-alias-state-error-primary);background:transparent;border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsDanger:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)}.dsham_settingsToolbar{display:grid;grid-template-columns:minmax(150px,1fr) repeat(3,minmax(0,126px));align-items:center;gap:8px;margin-bottom:16px}.dsham_settingsSearch{display:flex;align-items:center;gap:8px;min-width:0;flex:1;height:32px;padding:0 12px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-button-elevated-fill));border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.dsham_settingsSearch:focus-within{border-color:var(--dsw-alias-label-tertiary)}.dsham_settingsSearch input{width:100%;min-width:0;padding:0;color:var(--dsw-alias-label-primary);background:transparent;border:0;outline:0;font:inherit;font-size:12px}.dsham_settingsSearch input::placeholder{color:var(--dsw-alias-label-tertiary)}.dsham_settingsFilter{position:relative;min-width:0;flex:none}.dsham_selectTrigger{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:32px;padding:0 10px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-button-elevated-fill));border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;line-height:20px;text-align:left}.dsham_selectTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_selectTrigger:focus-visible{outline:2px solid var(--dsw-alias-label-secondary);outline-offset:2px}.dsham_selectTrigger[aria-expanded='true']{border-color:var(--dsw-alias-label-tertiary)}.dsham_selectValue{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsham_selectCaret{flex:none;width:12px;height:12px;color:var(--dsw-alias-label-tertiary)}.dsham_selectMenu{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:30;box-sizing:border-box;min-width:100%;max-height:280px;overflow:auto;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3)}.dsham_selectOption{box-sizing:border-box;display:flex;align-items:center;width:100%;min-height:32px;padding:0 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer}.dsham_selectOption:hover,.dsham_selectOption[data-active='true']{background:var(--dsw-alias-interactive-bg-hover)}.dsham_selectOption[aria-selected='true']{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsGroup{margin:0 0 20px}.dsham_settingsGroupHeading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 14px}.dsham_settingsGroupTitle{display:flex;align-items:center;gap:8px;min-width:0;margin:0;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.dsham_settingsGroupTitle svg{flex:none;color:var(--dsw-alias-label-secondary)}.dsham_settingsCount{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px}.dsham_settingsList{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-button-elevated-fill))}.dsham_settingsRow{display:grid;grid-template-columns:16px minmax(0,1fr) auto;align-items:center;gap:12px;min-height:64px;padding:10px 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsRow:last-child{border-bottom:0}.dsham_settingsContent{min-width:0;flex:1}.dsham_settingsTitle{overflow:hidden;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.dsham_settingsMeta{margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.dsham_settingsActions{display:flex;align-items:center;gap:4px;flex:none}.dsham_settingsAction{min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsAction:hover{filter:brightness(1.12)}.dsham_settingsDelete{display:flex;align-items:center;justify-content:center;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsDelete:hover{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsEmpty{padding:28px 8px;color:var(--dsw-alias-label-secondary);text-align:center}.dsham_settingsError{margin-top:10px;color:var(--dsw-alias-state-error-primary);font-size:12px}@container(max-width:520px){.dsham_settingsHeader{margin-bottom:16px}.dsham_settingsToolbar{grid-template-columns:repeat(3,minmax(0,1fr));margin-bottom:16px}.dsham_settingsSearch{grid-column:1/-1}.dsham_settingsFilter{flex:1;min-width:0}.dsham_settingsGroup{margin-bottom:32px}.dsham_settingsRow{padding:10px 12px}.dsham_settingsActions{gap:4px}}";
|
|
4462
|
+
const ARCHIVE_SETTINGS_BATCH_CSS = ".dsham_favorite,.dsham_restoreIcon{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;background:transparent;border-radius:6px;color:var(--dsw-alias-label-secondary);cursor:pointer}.dsham_favorite{font-size:22px}.dsham_favorite[aria-pressed=true]{color:var(--dsw-alias-state-warn-primary)}.dsham_favorite:hover,.dsham_restoreIcon:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_favorite:disabled,.dsham_restoreIcon:disabled{opacity:.5;cursor:not-allowed}.dsham_settingsTitleLink{display:block;max-width:100%;padding:0;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;font-weight:600;line-height:20px;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.dsham_settingsTitleLink:hover:not(:disabled){text-decoration:underline;text-underline-offset:3px}.dsham_settingsTitleLink:disabled{cursor:default;opacity:.6}.dsham_groupToggle{display:flex;align-items:center;gap:8px;min-width:0;max-width:100%;padding:4px 0;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.dsham_groupToggle span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsham_settingsRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsRow[data-selected=true]{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsTitleLink:focus-visible,.dsham_groupToggle:focus-visible,.dsham_favorite:focus-visible,.dsham_restoreIcon:focus-visible,.dsham_settingsGroupMenu:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#3b82f6);outline-offset:2px}.dsham_selectTrigger:disabled{opacity:.5;cursor:not-allowed}@container(max-width:620px){.dsham_settingsToolbar{grid-template-columns:repeat(3,minmax(0,1fr))}.dsham_settingsSearch{grid-column:1/-1}}@container(max-width:400px){.dsham_settingsRow{gap:8px;padding:10px 8px}.dsham_settingsActions{gap:0}.dsham_settingsMeta{font-size:11px}.dsham_selectTrigger{font-size:12px;padding:0 8px}}.dsham_settingsHeaderActions,.dsham_settingsGroupMeta{display:flex;align-items:center;gap:8px;flex:none;flex-wrap:wrap}.dsham_settingsRestoreAll{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsRestoreAll:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsRestoreAll:disabled,.dsham_settingsDanger:disabled,.dsham_settingsGroupMenu:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsGroupMenu{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsGroupMenu:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsStatus{margin-top:10px;color:var(--dsw-alias-label-secondary);font-size:12px}@media(max-width:720px){.dsham_settingsHeader{flex-direction:column}.dsham_settingsHeaderActions{align-self:flex-start}}";
|
|
4463
|
+
const ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS = ".dsham_settingsTitleRow{display:flex;align-items:center;gap:8px 12px;min-width:0;flex-wrap:wrap}.dsham_settingsLinks{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.dsham_settingsExternalLink{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dsham_settingsExternalLink:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsExternalLink:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dsham_settingsExternalLink svg{flex:none}@media(max-width:720px){.dsham_settingsTitleRow{flex-wrap:wrap}}";
|
|
3360
4464
|
const ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS = ".dsham_settingsDeleteConfirm{color:var(--dsw-alias-state-error-primary)!important;background:transparent!important;border-color:var(--dsw-alias-state-error-primary)!important}.dsham_settingsDeleteConfirm:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)!important}.dsham_settingsDeleteConfirm:focus-visible{outline:2px solid var(--dsw-alias-state-error-secondary);outline-offset:2px}.dsham_settingsDeleteConfirm:disabled{cursor:not-allowed;opacity:.5}";
|
|
3361
4465
|
const ARCHIVE_WORKSPACE_CONFIRM_CSS = ".dsham_archiveWorkspaceConfirm{color:var(--dsw-alias-state-error-primary)!important;background:transparent!important;border-color:var(--dsw-alias-state-error-primary)!important}.dsham_archiveWorkspaceConfirm:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)!important}.dsham_archiveWorkspaceConfirm:focus-visible{outline:2px solid var(--dsw-alias-state-error-secondary);outline-offset:2px}.dsham_archiveWorkspaceConfirm:disabled{cursor:not-allowed;opacity:.5}";
|
|
3362
|
-
const ARCHIVE_SETTINGS_SELECTION_CSS = ".dsham_settingsSelection{margin:-8px 0 16px;padding:4px 0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsSelectionMain{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;min-height:36px}.dsham_settingsSelectionSummary{display:flex;flex-wrap:wrap;align-items:center;gap:12px;min-width:0;max-width:100%}.dsham_settingsSelectionToggle{display:inline-flex;flex:none;white-space:nowrap;align-items:center;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;cursor:pointer}.dsham_settingsCheckbox{flex:none;width:16px;height:16px;margin:0;accent-color:var(--dsw-alias-
|
|
4466
|
+
const ARCHIVE_SETTINGS_SELECTION_CSS = ".dsham_settingsSelection{margin:-8px 0 16px;padding:4px 0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsSelectionMain{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;min-height:36px}.dsham_settingsSelectionSummary{display:flex;flex-wrap:wrap;align-items:center;gap:12px;min-width:0;max-width:100%}.dsham_settingsSelectionToggle{display:inline-flex;flex:none;white-space:nowrap;align-items:center;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;cursor:pointer}.dsham_settingsCheckbox{flex:none;width:16px;height:16px;margin:0;accent-color:var(--dsw-alias-brand-primary)}.dsham_settingsSelectionClear{flex:none;min-height:28px;padding:0 0 0 12px;border:0;border-left:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-state-business-primary,#3b82f6);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer}.dsham_settingsSelectionClear:hover:not(:disabled){text-decoration:underline}.dsham_settingsSelectionActions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;max-width:100%;margin-left:auto}.dsham_settingsSelectionAction{flex:none;white-space:nowrap;min-height:32px;padding:0 14px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsSelectionAction:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsSelectionArchive,.dsham_settingsSelectionDelete{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}.dsham_settingsSelectionScope{margin:8px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow-wrap:anywhere}.dsham_settingsSelectionAction:disabled,.dsham_settingsSelectionClear:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsSelectionAction:focus-visible,.dsham_settingsSelectionClear:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#3b82f6);outline-offset:3px}";
|
|
3363
4467
|
const ARCHIVE_SETTINGS_LAYOUT_OVERRIDE = ".dsham_settings{margin:0 auto!important}@media(max-width:720px){.dsham_settings{margin:0 auto!important}}";
|
|
3364
4468
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-archive-manager/ArchiveSettings.layout.css") + "]") === null) {
|
|
3365
4469
|
const tag = document.createElement("style");
|
|
@@ -3368,7 +4472,7 @@
|
|
|
3368
4472
|
tag.textContent = ARCHIVE_SETTINGS_LAYOUT_OVERRIDE + ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS + ARCHIVE_WORKSPACE_CONFIRM_CSS;
|
|
3369
4473
|
document.head.appendChild(tag);
|
|
3370
4474
|
}
|
|
3371
|
-
function ArchiveProjectSelect({ id, value, options, onChange, "aria-label": ariaLabel }) {
|
|
4475
|
+
function ArchiveProjectSelect({ id: id2, value, options, onChange, disabled = false, "aria-label": ariaLabel }) {
|
|
3372
4476
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3373
4477
|
const selectedIndex = Math.max(0, options.findIndex((option) => option.value === value));
|
|
3374
4478
|
const [active, setActive] = (0, react.useState)(selectedIndex);
|
|
@@ -3401,9 +4505,10 @@
|
|
|
3401
4505
|
}, [open]);
|
|
3402
4506
|
(0, react.useEffect)(() => {
|
|
3403
4507
|
if (!open) return;
|
|
3404
|
-
document.getElementById(
|
|
3405
|
-
}, [active, open,
|
|
4508
|
+
document.getElementById(id2 + "-opt-" + String(active))?.scrollIntoView({ block: "nearest" });
|
|
4509
|
+
}, [active, open, id2]);
|
|
3406
4510
|
const choose = (next) => {
|
|
4511
|
+
if (disabled) return;
|
|
3407
4512
|
onChange(next);
|
|
3408
4513
|
setOpen(false);
|
|
3409
4514
|
};
|
|
@@ -3415,14 +4520,15 @@
|
|
|
3415
4520
|
className: "dsham_settingsFilter",
|
|
3416
4521
|
ref: rootRef,
|
|
3417
4522
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
3418
|
-
id,
|
|
4523
|
+
id: id2,
|
|
3419
4524
|
ref: triggerRef,
|
|
3420
4525
|
type: "button",
|
|
3421
4526
|
className: "dsham_selectTrigger",
|
|
4527
|
+
disabled,
|
|
3422
4528
|
"aria-label": ariaLabel,
|
|
3423
4529
|
"aria-haspopup": "listbox",
|
|
3424
4530
|
"aria-expanded": open,
|
|
3425
|
-
"aria-controls":
|
|
4531
|
+
"aria-controls": id2 + "-list",
|
|
3426
4532
|
onClick: () => setOpen((current) => !current),
|
|
3427
4533
|
onKeyDown: (event) => {
|
|
3428
4534
|
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
|
|
@@ -3445,12 +4551,12 @@
|
|
|
3445
4551
|
})
|
|
3446
4552
|
})]
|
|
3447
4553
|
}), open ? (0, react_jsx_runtime.jsx)("div", {
|
|
3448
|
-
id:
|
|
4554
|
+
id: id2 + "-list",
|
|
3449
4555
|
ref: listRef,
|
|
3450
4556
|
className: "dsham_selectMenu",
|
|
3451
4557
|
role: "listbox",
|
|
3452
4558
|
tabIndex: 0,
|
|
3453
|
-
"aria-activedescendant":
|
|
4559
|
+
"aria-activedescendant": id2 + "-opt-" + String(active),
|
|
3454
4560
|
onKeyDown: (event) => {
|
|
3455
4561
|
if (event.key === "ArrowDown") {
|
|
3456
4562
|
event.preventDefault();
|
|
@@ -3481,12 +4587,12 @@
|
|
|
3481
4587
|
if (event.key === "Escape" || event.key === "Tab") {
|
|
3482
4588
|
event.preventDefault();
|
|
3483
4589
|
event.stopPropagation();
|
|
3484
|
-
if (typeof event.stopImmediatePropagation === "function") event.stopImmediatePropagation();
|
|
4590
|
+
if ("stopImmediatePropagation" in event && typeof event.stopImmediatePropagation === "function") event.stopImmediatePropagation();
|
|
3485
4591
|
setOpen(false);
|
|
3486
4592
|
}
|
|
3487
4593
|
},
|
|
3488
4594
|
children: options.map((option, index) => (0, react_jsx_runtime.jsx)("button", {
|
|
3489
|
-
id:
|
|
4595
|
+
id: id2 + "-opt-" + String(index),
|
|
3490
4596
|
type: "button",
|
|
3491
4597
|
role: "option",
|
|
3492
4598
|
className: "dsham_selectOption",
|
|
@@ -3540,6 +4646,33 @@
|
|
|
3540
4646
|
onChange
|
|
3541
4647
|
});
|
|
3542
4648
|
}
|
|
4649
|
+
function ArchivedSessionMenu({ busy, title, t, onPreview, onRestoreOpen, onDelete, onCopyId, onCopyPath }) {
|
|
4650
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
4651
|
+
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
4652
|
+
open,
|
|
4653
|
+
onClose: () => setOpen(false),
|
|
4654
|
+
portal: true,
|
|
4655
|
+
align: "end",
|
|
4656
|
+
autoFocus: true,
|
|
4657
|
+
items: [
|
|
4658
|
+
...onPreview ? [{ id: "preview", label: t("discovery.preview"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, {}) }] : [],
|
|
4659
|
+
...onRestoreOpen ? [{ id: "restoreOpen", label: t("archives.restoreOpen"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16, {}) }] : [],
|
|
4660
|
+
...onCopyId ? [{ id: "copyId", label: t("details.copyId"), icon: react.createElement(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}) }] : [],
|
|
4661
|
+
...onCopyPath ? [{ id: "copyPath", label: t("details.copyPath"), icon: react.createElement(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}) }] : [],
|
|
4662
|
+
...onDelete ? [{ id: "delete", label: t("menu.deleteSession"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}), danger: true }] : []
|
|
4663
|
+
],
|
|
4664
|
+
onSelect: (id2) => {
|
|
4665
|
+
setOpen(false);
|
|
4666
|
+
if (busy) return;
|
|
4667
|
+
if (id2 === "copyId") return onCopyId?.();
|
|
4668
|
+
if (id2 === "copyPath") return onCopyPath?.();
|
|
4669
|
+
if (id2 === "preview") return onPreview?.();
|
|
4670
|
+
if (id2 === "restoreOpen") return onRestoreOpen?.();
|
|
4671
|
+
if (id2 === "delete") onDelete?.();
|
|
4672
|
+
},
|
|
4673
|
+
anchor: (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsGroupMenu", disabled: busy, title: t("archives.moreActions"), "aria-label": t("archives.moreActions") + t("common.separator") + title, "aria-haspopup": "menu", "aria-expanded": open, onClick: () => setOpen((value) => !value), children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, {}) })
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
3543
4676
|
function ArchivedGroupActions({ group, busy, onArchive, onRestore, onDelete, t }) {
|
|
3544
4677
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3545
4678
|
const ungrouped = group.key === ARCHIVE_UNGROUPED_KEY;
|
|
@@ -3562,12 +4695,12 @@
|
|
|
3562
4695
|
open,
|
|
3563
4696
|
onClose: () => setOpen(false),
|
|
3564
4697
|
items,
|
|
3565
|
-
onSelect: (
|
|
4698
|
+
onSelect: (id2) => {
|
|
3566
4699
|
setOpen(false);
|
|
3567
4700
|
if (busy) return;
|
|
3568
|
-
if (
|
|
3569
|
-
else if (
|
|
3570
|
-
else if (
|
|
4701
|
+
if (id2 === "archive") onArchive?.();
|
|
4702
|
+
else if (id2 === "restore") onRestore?.();
|
|
4703
|
+
else if (id2 === "delete") onDelete?.();
|
|
3571
4704
|
},
|
|
3572
4705
|
portal: true,
|
|
3573
4706
|
anchor: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -3589,21 +4722,21 @@
|
|
|
3589
4722
|
if (target.scope === "all") return ids;
|
|
3590
4723
|
if (target.scope === "sessions") {
|
|
3591
4724
|
const selected = new Set(target.sessionIds ?? []);
|
|
3592
|
-
return ids.filter((
|
|
4725
|
+
return ids.filter((id2) => selected.has(id2));
|
|
3593
4726
|
}
|
|
3594
4727
|
if (target.scope === "workspace") {
|
|
3595
4728
|
const accounted2 = new Set(items.find((workspace) => workspace.workspaceId === target.workspaceId)?.sessionIds ?? []);
|
|
3596
|
-
return ids.filter((
|
|
4729
|
+
return ids.filter((id2) => accounted2.has(id2));
|
|
3597
4730
|
}
|
|
3598
4731
|
const accounted = new Set(items.flatMap((workspace) => workspace.sessionIds));
|
|
3599
|
-
return ids.filter((
|
|
4732
|
+
return ids.filter((id2) => !accounted.has(id2));
|
|
3600
4733
|
}
|
|
3601
4734
|
function archivedSessionIdsInGroups(groups) {
|
|
3602
4735
|
return [...new Set(groups.flatMap((group) => group.sessions.map((session) => session.id)))];
|
|
3603
4736
|
}
|
|
3604
4737
|
function pruneArchivedSelection(selectedSessionIds, archivedSessionIds) {
|
|
3605
4738
|
const archived = new Set(archivedSessionIds);
|
|
3606
|
-
return [...new Set(selectedSessionIds)].filter((
|
|
4739
|
+
return [...new Set(selectedSessionIds)].filter((id2) => archived.has(id2));
|
|
3607
4740
|
}
|
|
3608
4741
|
function toggleArchivedSelection(selectedSessionIds, sessionIds, checked) {
|
|
3609
4742
|
const selected = new Set(selectedSessionIds);
|
|
@@ -3642,23 +4775,27 @@
|
|
|
3642
4775
|
sessions: []
|
|
3643
4776
|
}));
|
|
3644
4777
|
const ungrouped = [];
|
|
3645
|
-
for (const
|
|
3646
|
-
const session = byId[
|
|
4778
|
+
for (const id2 of archivedSessionIds) {
|
|
4779
|
+
const session = byId[id2];
|
|
3647
4780
|
if (session === void 0 || session.origin === "subagent") continue;
|
|
3648
|
-
const group = byWorkspace.find((workspace) => workspace.ids
|
|
4781
|
+
const group = byWorkspace.find((workspace) => workspace.ids?.has(id2));
|
|
3649
4782
|
(group === void 0 ? ungrouped : group.sessions).push(session);
|
|
3650
4783
|
}
|
|
3651
4784
|
const result = byWorkspace.filter((group) => group.sessions.length > 0);
|
|
3652
4785
|
if (ungrouped.length > 0) result.push({ key: ARCHIVE_UNGROUPED_KEY, title: ungroupedLabel, sessions: ungrouped });
|
|
3653
4786
|
return result;
|
|
3654
4787
|
}
|
|
3655
|
-
function sortArchivedGroups(groups, sortBy, createdAtById, t) {
|
|
4788
|
+
function sortArchivedGroups(groups, sortBy, createdAtById, t, details = {}) {
|
|
3656
4789
|
const compareText = (left, right) => String(left).localeCompare(String(right), void 0, { numeric: true, sensitivity: "base" });
|
|
3657
4790
|
const timestampOf = (session) => {
|
|
3658
|
-
const value = sortBy === "created" ? createdAtById[session.id] : session.updatedAt;
|
|
4791
|
+
const value = sortBy === "created" ? details[session.id]?.createdAt ?? createdAtById[session.id] : session.updatedAt;
|
|
3659
4792
|
return typeof value === "number" && Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
|
|
3660
4793
|
};
|
|
3661
4794
|
const compareSessions = (left, right) => {
|
|
4795
|
+
if (sortBy === "turnsAsc" || sortBy === "turnsDesc") {
|
|
4796
|
+
const difference = compareTurnCounts(details[left.id]?.turnCount, details[right.id]?.turnCount, sortBy);
|
|
4797
|
+
if (difference) return difference;
|
|
4798
|
+
}
|
|
3662
4799
|
if (sortBy !== "alphabetical") {
|
|
3663
4800
|
const byTime = timestampOf(right) - timestampOf(left);
|
|
3664
4801
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3667,6 +4804,10 @@
|
|
|
3667
4804
|
};
|
|
3668
4805
|
const result = groups.map((group) => ({ ...group, sessions: [...group.sessions].sort(compareSessions) }));
|
|
3669
4806
|
return result.sort((left, right) => {
|
|
4807
|
+
if (sortBy === "turnsAsc" || sortBy === "turnsDesc") {
|
|
4808
|
+
const difference = compareTurnCounts(details[left.sessions[0]?.id]?.turnCount, details[right.sessions[0]?.id]?.turnCount, sortBy);
|
|
4809
|
+
if (difference) return difference;
|
|
4810
|
+
}
|
|
3670
4811
|
if (sortBy !== "alphabetical") {
|
|
3671
4812
|
const byTime = timestampOf(right.sessions[0]) - timestampOf(left.sessions[0]);
|
|
3672
4813
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3675,6 +4816,11 @@
|
|
|
3675
4816
|
});
|
|
3676
4817
|
}
|
|
3677
4818
|
const zh = {
|
|
4819
|
+
...organizerZh,
|
|
4820
|
+
...discoveryZh,
|
|
4821
|
+
...healthZh,
|
|
4822
|
+
"locale.language": "zh",
|
|
4823
|
+
"service.unavailable": "\u670D\u52A1\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5",
|
|
3678
4824
|
"archives.archiveProject": "\u5F52\u6863\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
3679
4825
|
"archives.archiveUngrouped": "\u5F52\u6863\u5168\u90E8\u672A\u5206\u7EC4\u804A\u5929",
|
|
3680
4826
|
"archives.archiveProjectDesc": "\u5C06\u201C{name}\u201D\u4E2D\u5168\u90E8 {n} \u6761\u672A\u5F52\u6863\u4F1A\u8BDD\u5F52\u6863\uFF0C\u4E0D\u53D7\u5F53\u524D\u641C\u7D22\u7B5B\u9009\u5F71\u54CD\u3002\u4E4B\u540E\u53EF\u5728\u201C\u5DF2\u5F52\u6863\u201D\u4E2D\u6062\u590D\u3002",
|
|
@@ -3684,13 +4830,14 @@
|
|
|
3684
4830
|
"archives.searchUnarchived": "\u641C\u7D22\u672A\u5F52\u6863\u804A\u5929",
|
|
3685
4831
|
"archives.emptyUnarchived": "\u6682\u65E0\u672A\u5F52\u6863\u4F1A\u8BDD\u3002",
|
|
3686
4832
|
"archives.archiveSelected": "\u5F52\u6863",
|
|
3687
|
-
"archives.openSession": "\u6253\u5F00
|
|
4833
|
+
"archives.openSession": "\u6253\u5F00",
|
|
4834
|
+
"archives.moreActions": "\u66F4\u591A\u64CD\u4F5C",
|
|
3688
4835
|
"archives.archiveSelectedDesc": "\u5C06\u9009\u4E2D\u7684\u4F1A\u8BDD\u5F52\u6863\uFF0C\u5305\u542B\u5F53\u524D\u7B5B\u9009\u9690\u85CF\u7684\u5DF2\u9009\u9879\u3002\u4E4B\u540E\u53EF\u5728\u201C\u5DF2\u5F52\u6863\u201D\u4E2D\u67E5\u770B\u548C\u6062\u590D\u3002",
|
|
3689
4836
|
"archives.archiveSuccess": "\u5DF2\u5F52\u6863 {n} \u6761\u4F1A\u8BDD\u3002",
|
|
3690
4837
|
"archives.archiveBatchFailed": "\u6279\u91CF\u5F52\u6863\u5931\u8D25\uFF1A{detail}",
|
|
3691
4838
|
"archives.navigationUnavailable": "\u5F53\u524D\u5BBF\u4E3B\u65E0\u6CD5\u4FDD\u6301\u5F52\u6863\u5BF9\u8BDD\uFF0C\u8BF7\u4F7F\u7528\u201C\u6062\u590D\u5E76\u6253\u5F00\u201D\u3002",
|
|
3692
4839
|
"archives.sessionNotRetained": "\u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6216\u6062\u590D\u540E\u518D\u8BD5\u3002",
|
|
3693
|
-
"archives.restoreOpen": "\u6062\u590D\
|
|
4840
|
+
"archives.restoreOpen": "\u6062\u590D\u6253\u5F00",
|
|
3694
4841
|
"archives.selectedCount": "\u5DF2\u9009 {n} \u6761",
|
|
3695
4842
|
"archives.selectionHiddenHint": "\u542B\u5F53\u524D\u672A\u663E\u793A\u7684 {hidden} \u6761\uFF0C\u4E5F\u5C06\u53C2\u4E0E\u64CD\u4F5C",
|
|
3696
4843
|
"archives.clearSelectionShort": "\u6E05\u7A7A",
|
|
@@ -3731,7 +4878,7 @@
|
|
|
3731
4878
|
"archives.viewProject": "GitHub",
|
|
3732
4879
|
"archives.feedback": "\u95EE\u9898\u53CD\u9988",
|
|
3733
4880
|
"archives.empty": "\u6682\u65E0\u5DF2\u5F52\u6863\u4F1A\u8BDD",
|
|
3734
|
-
"archives.emptyFiltered": "\u6CA1\u6709\
|
|
4881
|
+
"archives.emptyFiltered": "\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u804A\u5929",
|
|
3735
4882
|
"archives.searchPlaceholder": "\u641C\u7D22\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3736
4883
|
"archives.sortBy": "\u6392\u5E8F\u65B9\u5F0F",
|
|
3737
4884
|
"archives.sortUpdated": "\u66F4\u65B0\u65F6\u95F4",
|
|
@@ -3745,24 +4892,20 @@
|
|
|
3745
4892
|
"archives.restoreSelected": "\u6062\u590D\u6240\u9009",
|
|
3746
4893
|
"archives.deleteSelected": "\u5220\u9664\u6240\u9009",
|
|
3747
4894
|
"archives.timestamp": "{date}\uFF0C{time}",
|
|
3748
|
-
"archives.
|
|
3749
|
-
"archives.restoreProject": "\u6062\u590D\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
4895
|
+
"archives.restoreProject": "\u6062\u590D\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3750
4896
|
"archives.restoreUngrouped": "\u5168\u90E8\u6062\u590D",
|
|
3751
|
-
"archives.deleteProject": "\u5220\u9664\
|
|
4897
|
+
"archives.deleteProject": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3752
4898
|
"archives.deleteUngrouped": "\u5168\u90E8\u5220\u9664",
|
|
3753
4899
|
"archives.projectActions": "\u9879\u76EE\u201C{name}\u201D\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3754
4900
|
"archives.ungroupedActions": "\u672A\u5206\u7EC4\u804A\u5929\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3755
4901
|
"archives.restoreSuccess": "\u5DF2\u6062\u590D {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u3002",
|
|
3756
4902
|
"archives.restoreBatchFailed": "\u6279\u91CF\u6062\u590D\u5931\u8D25\uFF1A{detail}",
|
|
3757
|
-
"archives.deleteAll": "\u5168\u90E8\u5220\u9664",
|
|
3758
|
-
"archives.deleteAllTitle": "\u5220\u9664\u5168\u90E8\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3759
|
-
"archives.deleteAllDesc": "\u5C06\u6C38\u4E45\u5220\u9664\u5168\u90E8 {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u53CA\u5176\u5B50\u4EE3\u7406\uFF08\u542B\u6B63\u5728\u8FD0\u884C\u7684\uFF09\u548C\u8BB0\u5F55\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
3760
4903
|
"archives.deleteSelectedTitle": "\u5220\u9664\u6240\u9009\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3761
4904
|
"archives.deleteSelectedDesc": "\u5C06\u6C38\u4E45\u5220\u9664\u6240\u9009\u7684 {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u53CA\u5176\u5B50\u4EE3\u7406\uFF08\u542B\u6B63\u5728\u8FD0\u884C\u7684\uFF09\u548C\u8BB0\u5F55\u3002\u5176\u4ED6\u804A\u5929\u4E0D\u4F1A\u53D7\u5F71\u54CD\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
3762
4905
|
"archives.deleteSelectedConfirm": "\u5220\u9664\u6240\u9009\u804A\u5929",
|
|
3763
4906
|
"archives.deleteProjectTitle": "\u5220\u9664\u201C{name}\u201D\u4E2D\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3764
4907
|
"archives.deleteProjectDesc": "\u5C06\u6C38\u4E45\u5220\u9664\u201C{name}\u201D\u4E2D\u7684 {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u53CA\u5176\u5B50\u4EE3\u7406\u548C\u8BB0\u5F55\u3002\u9879\u76EE\u76EE\u5F55\u548C\u672A\u5F52\u6863\u804A\u5929\u4E0D\u4F1A\u53D7\u5F71\u54CD\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
3765
|
-
"archives.deleteProjectConfirm": "\u5220\u9664\
|
|
4908
|
+
"archives.deleteProjectConfirm": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3766
4909
|
"archives.deleteUngroupedTitle": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3767
4910
|
"archives.deleteUngroupedDesc": "\u5C06\u6C38\u4E45\u5220\u9664\u672A\u5206\u7EC4\u4E2D\u7684 {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u53CA\u5176\u5B50\u4EE3\u7406\u548C\u8BB0\u5F55\u3002\u5176\u4ED6\u9879\u76EE\u548C\u672A\u5F52\u6863\u804A\u5929\u4E0D\u4F1A\u53D7\u5F71\u54CD\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
3768
4911
|
"archives.deleteUngroupedConfirm": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5168\u90E8\u804A\u5929",
|
|
@@ -3823,6 +4966,12 @@
|
|
|
3823
4966
|
"time.ago": "{t}\u524D"
|
|
3824
4967
|
};
|
|
3825
4968
|
const en = {
|
|
4969
|
+
...organizerEn,
|
|
4970
|
+
...discoveryEn,
|
|
4971
|
+
...healthEn,
|
|
4972
|
+
"locale.language": "en",
|
|
4973
|
+
"service.unavailable": "The service is not ready. Please retry.",
|
|
4974
|
+
"archives.moreActions": "More actions",
|
|
3826
4975
|
"archives.archiveProject": "Archive all chats in this project",
|
|
3827
4976
|
"archives.archiveUngrouped": "Archive all ungrouped chats",
|
|
3828
4977
|
"archives.archiveProjectDesc": "Archive all {n} unarchived sessions in \u201C{name}\u201D, regardless of the current search filter. You can restore them in Archived.",
|
|
@@ -3879,7 +5028,7 @@
|
|
|
3879
5028
|
"archives.viewProject": "GitHub",
|
|
3880
5029
|
"archives.feedback": "Issues",
|
|
3881
5030
|
"archives.empty": "No archived sessions.",
|
|
3882
|
-
"archives.emptyFiltered": "No
|
|
5031
|
+
"archives.emptyFiltered": "No chats match your filters.",
|
|
3883
5032
|
"archives.searchPlaceholder": "Search archived chats",
|
|
3884
5033
|
"archives.sortBy": "Sort archived chats",
|
|
3885
5034
|
"archives.sortUpdated": "Last updated",
|
|
@@ -3893,7 +5042,6 @@
|
|
|
3893
5042
|
"archives.restoreSelected": "Restore selected",
|
|
3894
5043
|
"archives.deleteSelected": "Delete selected",
|
|
3895
5044
|
"archives.timestamp": "{date}, {time}",
|
|
3896
|
-
"archives.restoreAll": "Restore all",
|
|
3897
5045
|
"archives.restoreProject": "Restore all chats in this project",
|
|
3898
5046
|
"archives.restoreUngrouped": "Restore all",
|
|
3899
5047
|
"archives.deleteProject": "Delete all chats in this project",
|
|
@@ -3902,9 +5050,6 @@
|
|
|
3902
5050
|
"archives.ungroupedActions": "Archive actions for ungrouped chats",
|
|
3903
5051
|
"archives.restoreSuccess": "Restored {n} archived chats.",
|
|
3904
5052
|
"archives.restoreBatchFailed": "Could not restore the archived chats: {detail}",
|
|
3905
|
-
"archives.deleteAll": "Delete all",
|
|
3906
|
-
"archives.deleteAllTitle": "Delete all archived chats",
|
|
3907
|
-
"archives.deleteAllDesc": "This permanently deletes all {n} archived chats, their child agents (including any that are still running), and their records. This cannot be undone.",
|
|
3908
5053
|
"archives.deleteSelectedTitle": "Delete selected archived chats",
|
|
3909
5054
|
"archives.deleteSelectedDesc": "This permanently deletes the selected {n} archived chats, their child agents (including any that are still running), and their records. Other chats are not affected. This cannot be undone.",
|
|
3910
5055
|
"archives.deleteSelectedConfirm": "Delete selected chats",
|
|
@@ -4011,13 +5156,13 @@
|
|
|
4011
5156
|
const archivedSessionIds = [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
4012
5157
|
return {
|
|
4013
5158
|
archivedSessionIds,
|
|
4014
|
-
archivedSessionIdsAdded: archivedSessionIds.filter((
|
|
5159
|
+
archivedSessionIdsAdded: archivedSessionIds.filter((id2) => !before.has(id2))
|
|
4015
5160
|
};
|
|
4016
5161
|
}
|
|
4017
5162
|
async function unarchiveSessionsViaOfficial(workspaces, sessionIds, refresh, unarchive) {
|
|
4018
5163
|
const before = new Set(workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []);
|
|
4019
5164
|
const seen = /* @__PURE__ */ new Set();
|
|
4020
|
-
const run = typeof unarchive === "function" ? unarchive : (
|
|
5165
|
+
const run = typeof unarchive === "function" ? unarchive : (id2) => workspaces.unarchiveSession?.(id2);
|
|
4021
5166
|
let archivedSessionIds;
|
|
4022
5167
|
for (const sessionId of sessionIds) {
|
|
4023
5168
|
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
@@ -4029,7 +5174,7 @@
|
|
|
4029
5174
|
archivedSessionIds ??= [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
4030
5175
|
return {
|
|
4031
5176
|
archivedSessionIds,
|
|
4032
|
-
unarchivedSessionIds: [...before].filter((
|
|
5177
|
+
unarchivedSessionIds: [...before].filter((id2) => !archivedSessionIds.includes(id2))
|
|
4033
5178
|
};
|
|
4034
5179
|
}
|
|
4035
5180
|
async function apply(ctx) {
|
|
@@ -4054,6 +5199,7 @@
|
|
|
4054
5199
|
linksSelector: ".dsham_settingsLinks",
|
|
4055
5200
|
zhName: "\u5F52\u6863\u4F1A\u8BDD",
|
|
4056
5201
|
enName: "Archived sessions",
|
|
5202
|
+
getLanguage: () => ctx.locale.bind(NS)("locale.language"),
|
|
4057
5203
|
createIcon: createPluginUpdateIcon
|
|
4058
5204
|
}), "dsh-archive-manager: plugin update ui");
|
|
4059
5205
|
const uiWorkspaceAt = () => ctx.get("uiWorkspace");
|
|
@@ -4064,7 +5210,7 @@
|
|
|
4064
5210
|
onOpened: () => ctx.get("layout")?.selectPanel(null),
|
|
4065
5211
|
beginNavigation: () => ctx.get("layout")?.beginNavigation?.()
|
|
4066
5212
|
});
|
|
4067
|
-
return () => archiveNavigation
|
|
5213
|
+
return () => archiveNavigation?.dispose();
|
|
4068
5214
|
};
|
|
4069
5215
|
if (typeof ctx.inject === "function") ctx.inject(["uiWorkspace"], (ready) => attachArchiveNavigation(ready.uiWorkspace ?? uiWorkspaceAt()));
|
|
4070
5216
|
else ctx.effect(() => attachArchiveNavigation(uiWorkspaceAt()), "archive-manager: explicit archived navigation");
|
|
@@ -4096,6 +5242,37 @@
|
|
|
4096
5242
|
}
|
|
4097
5243
|
};
|
|
4098
5244
|
const unarchiveOne = createUnarchiveSession(ctx.workspaces, () => ctx.get("remote.workspaceRegistry"));
|
|
5245
|
+
const registryCall = async (method, ...args) => {
|
|
5246
|
+
const registry = ctx.get("remote.workspaceRegistry");
|
|
5247
|
+
if (!registry || typeof registry[method] !== "function") throw new Error(ctx.locale.bind(NS)("service.unavailable"));
|
|
5248
|
+
const call = registry[method];
|
|
5249
|
+
const result = await call.apply(registry, args);
|
|
5250
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5251
|
+
return result.value;
|
|
5252
|
+
};
|
|
5253
|
+
const sessionDetails = (input) => registryCall("sessionDetails", input);
|
|
5254
|
+
const diagnoseSession = (input) => registryCall("diagnoseSession", input);
|
|
5255
|
+
const repairSession = (input) => registryCall("repairSession", input);
|
|
5256
|
+
const searchArchivedContent = (input) => registryCall("searchArchivedContent", input);
|
|
5257
|
+
const searchSessionContent = (input) => registryCall("searchSessionContent", input);
|
|
5258
|
+
const previewArchivedSession = (input) => registryCall("previewArchivedSession", input);
|
|
5259
|
+
const favoriteSessions = () => registryCall("favoriteSessions");
|
|
5260
|
+
const setSessionFavorite = (input) => registryCall("setSessionFavorite", input);
|
|
5261
|
+
const organizeBatch = createSessionOrganizer({
|
|
5262
|
+
workspaces: ctx.workspaces.list,
|
|
5263
|
+
sessions: ctx.sessions.list,
|
|
5264
|
+
archive: (id2) => ctx.workspaces.archiveSession(id2),
|
|
5265
|
+
restore: unarchiveOne,
|
|
5266
|
+
deleteOne: async (id2) => {
|
|
5267
|
+
const registry = ctx.get("remote.workspaceRegistry");
|
|
5268
|
+
if (!registry) throw new Error(ctx.locale.bind(NS)("service.unavailable"));
|
|
5269
|
+
const result = await registry.deleteSession(id2);
|
|
5270
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5271
|
+
},
|
|
5272
|
+
getFavorites: favoriteSessions,
|
|
5273
|
+
refresh: () => ctx.sessions.refresh?.(),
|
|
5274
|
+
currentSessionId
|
|
5275
|
+
});
|
|
4099
5276
|
const unarchiveSession = async (sessionId) => {
|
|
4100
5277
|
await unarchiveOne(sessionId);
|
|
4101
5278
|
await refreshSessionList();
|
|
@@ -4238,15 +5415,33 @@
|
|
|
4238
5415
|
openConversation,
|
|
4239
5416
|
focusSessionWorkspace,
|
|
4240
5417
|
viewState: archiveViewState,
|
|
5418
|
+
favoriteSessions,
|
|
5419
|
+
setSessionFavorite,
|
|
5420
|
+
organizeBatch,
|
|
5421
|
+
diagnoseSession,
|
|
5422
|
+
repairSession,
|
|
5423
|
+
sessionDetails,
|
|
5424
|
+
searchSessionContent,
|
|
5425
|
+
searchArchivedContent,
|
|
5426
|
+
previewArchivedSession,
|
|
4241
5427
|
t: ctx.locale.bind(NS)
|
|
4242
5428
|
})
|
|
4243
5429
|
}, ArchivedSessionsSection));
|
|
4244
5430
|
}
|
|
5431
|
+
async function forkWithFeedback(sessionId, fork, notify, t) {
|
|
5432
|
+
try {
|
|
5433
|
+
await fork(sessionId);
|
|
5434
|
+
} catch (reason) {
|
|
5435
|
+
notify(formatForkError(reason, t));
|
|
5436
|
+
}
|
|
5437
|
+
}
|
|
4245
5438
|
exports.__test = {
|
|
5439
|
+
forkWithFeedback,
|
|
4246
5440
|
unarchivedSessionIds,
|
|
4247
5441
|
ArchiveSelectionToolbar,
|
|
4248
5442
|
ArchivedSessionsSection,
|
|
4249
5443
|
zh,
|
|
5444
|
+
en,
|
|
4250
5445
|
displayTitle,
|
|
4251
5446
|
sessionVisible,
|
|
4252
5447
|
indexSubagentDescendants,
|