@michengai/dsh-archive-manager 0.1.43 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -13
- package/CHANGELOG.zh-CN.md +64 -13
- package/README.md +65 -18
- package/README.zh-CN.md +68 -17
- package/RELEASE_NOTES.md +113 -0
- package/assets/branding/banner.txt +3 -2
- package/assets/branding/dsh-banner-en.png +0 -0
- package/assets/branding/dsh-banner.png +0 -0
- package/assets/screenshots/archived-sessions.png +0 -0
- package/assets/screenshots/unarchived-sessions.png +0 -0
- package/lib/archive-discovery.js +235 -0
- package/lib/archive-experience.js +34 -5
- package/lib/archive-organizer.js +105 -0
- package/lib/client.js +1416 -196
- package/lib/session-repair.js +123 -0
- package/lib/workspace.js +237 -35
- package/package.json +43 -42
package/lib/client.js
CHANGED
|
@@ -1,4 +1,662 @@
|
|
|
1
1
|
(() => {
|
|
2
|
+
// src/session-health-locales.js
|
|
3
|
+
var healthZh = {
|
|
4
|
+
"health.archived": "\u5DF2\u5F52\u6863\u4F1A\u8BDD\u9700\u8981\u68C0\u67E5",
|
|
5
|
+
"health.unarchived": "\u672A\u5F52\u6863\u4F1A\u8BDD\u9700\u8981\u68C0\u67E5",
|
|
6
|
+
"health.heading": "\u8BCA\u65AD\u4E0E\u4FEE\u590D",
|
|
7
|
+
"health.scopeArchived": "\u68C0\u67E5\u8303\u56F4\uFF1A\u5168\u90E8\u5DF2\u5F52\u6863\u4F1A\u8BDD\uFF0C\u4E0D\u53D7\u5217\u8868\u7B5B\u9009\u5F71\u54CD\u3002",
|
|
8
|
+
"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",
|
|
9
|
+
"health.retry": "\u91CD\u65B0\u68C0\u6D4B",
|
|
10
|
+
"health.busy": "\u5904\u7406\u4E2D\u2026",
|
|
11
|
+
"health.confirm": "\u786E\u8BA4\u4FEE\u590D",
|
|
12
|
+
"health.diagnose": "\u8BCA\u65AD\u4F1A\u8BDD",
|
|
13
|
+
"health.technical": "\u6280\u672F\u8BE6\u60C5",
|
|
14
|
+
"health.notice": "\u4F1A\u8BDD\u4FEE\u590D\u5B8C\u6210\uFF0C\u5DF2\u91CD\u65B0\u8BFB\u53D6\u8BE6\u60C5\u3002",
|
|
15
|
+
"health.legacy-source.reason": "\u65E7\u7248\u6D88\u606F\u6765\u6E90\u4E0D\u53D7\u65B0\u7248 DSH \u652F\u6301",
|
|
16
|
+
"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",
|
|
17
|
+
"health.repair-frame.reason": "\u65E7\u7248\u4FEE\u590D\u751F\u6210\u7684\u538B\u7F29\u683C\u5F0F\u4E0D\u7B26\u5408\u5BBF\u4E3B\u8981\u6C42",
|
|
18
|
+
"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",
|
|
19
|
+
"health.missing.reason": "\u4F1A\u8BDD\u65E5\u5FD7\u6216\u9644\u4EF6\u8DEF\u5F84\u4E0D\u5B58\u5728",
|
|
20
|
+
"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",
|
|
21
|
+
"health.permission.reason": "\u6CA1\u6709\u6743\u9650\u8BFB\u53D6\u4F1A\u8BDD\u6587\u4EF6",
|
|
22
|
+
"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",
|
|
23
|
+
"health.corrupt.reason": "\u4F1A\u8BDD\u65E5\u5FD7\u53EF\u80FD\u635F\u574F\u6216\u672A\u5B8C\u6574\u5199\u5165",
|
|
24
|
+
"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",
|
|
25
|
+
"health.unknown.reason": "\u4F1A\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6",
|
|
26
|
+
"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",
|
|
27
|
+
"health.healthy.reason": "\u4F1A\u8BDD\u5DF2\u53EF\u6B63\u5E38\u8BFB\u53D6",
|
|
28
|
+
"health.healthy.advice": "\u5237\u65B0\u4F1A\u8BDD\u8BE6\u60C5\u5373\u53EF\uFF0C\u65E0\u9700\u4FEE\u590D\u3002",
|
|
29
|
+
"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",
|
|
30
|
+
"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",
|
|
31
|
+
"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",
|
|
32
|
+
"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",
|
|
33
|
+
"health.blocked.reason": "\u6682\u4E0D\u80FD\u81EA\u52A8\u4FEE\u590D",
|
|
34
|
+
"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",
|
|
35
|
+
"health.repaired.reason": "\u4FEE\u590D\u5B8C\u6210\uFF0C\u5BBF\u4E3B\u5DF2\u80FD\u6B63\u5E38\u8BFB\u53D6",
|
|
36
|
+
"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",
|
|
37
|
+
"health.published-unreadable.reason": "\u65B0\u7248\u65E5\u5FD7\u5DF2\u751F\u6210\uFF0C\u4F46\u5BBF\u4E3B\u590D\u8BFB\u672A\u901A\u8FC7",
|
|
38
|
+
"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",
|
|
39
|
+
"health.failed.reason": "\u64CD\u4F5C\u672A\u5B8C\u6210",
|
|
40
|
+
"health.failed.advice": "\u8BF7\u5C55\u5F00\u6280\u672F\u8BE6\u60C5\u67E5\u770B\u9519\u8BEF\uFF0C\u5904\u7406\u540E\u91CD\u65B0\u8BCA\u65AD\u3002"
|
|
41
|
+
};
|
|
42
|
+
var healthEn = {
|
|
43
|
+
"health.archived": "Archived sessions need attention",
|
|
44
|
+
"health.unarchived": "Unarchived sessions need attention",
|
|
45
|
+
"health.heading": "Diagnosis and repair",
|
|
46
|
+
"health.scopeArchived": "Checks all archived sessions, regardless of list filters.",
|
|
47
|
+
"health.scopeUnarchived": "Checks all unarchived sessions, regardless of list filters. Archive and close a session before repairing it.",
|
|
48
|
+
"health.retry": "Check again",
|
|
49
|
+
"health.busy": "Processing\u2026",
|
|
50
|
+
"health.confirm": "Confirm repair",
|
|
51
|
+
"health.diagnose": "Diagnose session",
|
|
52
|
+
"health.technical": "Technical details",
|
|
53
|
+
"health.notice": "Session repaired. Details have been refreshed.",
|
|
54
|
+
"health.legacy-source.reason": "The new DSH version does not support this legacy message source",
|
|
55
|
+
"health.legacy-source.advice": "Run a diagnosis to check whether the legacy automation source can be converted.",
|
|
56
|
+
"health.repair-frame.reason": "A previous repair used an unsupported compression format",
|
|
57
|
+
"health.repair-frame.advice": "Run a diagnosis to correct the compression frames while preserving the original log.",
|
|
58
|
+
"health.missing.reason": "The session log or attachment path does not exist",
|
|
59
|
+
"health.missing.advice": "Check the original directory and disk. Rebuilding the cache cannot recover missing messages.",
|
|
60
|
+
"health.permission.reason": "Permission to read the session files was denied",
|
|
61
|
+
"health.permission.advice": "Check directory permissions, file locks and security software, then retry.",
|
|
62
|
+
"health.corrupt.reason": "The session log may be corrupt or incomplete",
|
|
63
|
+
"health.corrupt.advice": "Keep the existing log and check the disk and original files. Messages will not be truncated or deleted automatically.",
|
|
64
|
+
"health.unknown.reason": "The session cannot currently be read",
|
|
65
|
+
"health.unknown.advice": "Retry first. If it still fails, expand technical details to check host compatibility.",
|
|
66
|
+
"health.healthy.reason": "The session can be read normally",
|
|
67
|
+
"health.healthy.advice": "Refresh the session details. No repair is needed.",
|
|
68
|
+
"health.ready.reason": "Found {n} legacy automation sources; host format validation passed",
|
|
69
|
+
"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.",
|
|
70
|
+
"health.ready-frame.reason": "Found compression frame issues from a previous repair; host validation passed",
|
|
71
|
+
"health.ready-frame.advice": "Correct the compression frames, preserving messages and the original log. Ensure no other DSH process has the session open.",
|
|
72
|
+
"health.blocked.reason": "Automatic repair is currently unavailable",
|
|
73
|
+
"health.blocked.advice": "Expand technical details to see the restriction. Resolve it before diagnosing again.",
|
|
74
|
+
"health.repaired.reason": "Repair complete; the host can read the session",
|
|
75
|
+
"health.repaired.advice": "The original log and archive status are preserved. You can preview or open the session again.",
|
|
76
|
+
"health.published-unreadable.reason": "A new log was generated, but the host could not read it back",
|
|
77
|
+
"health.published-unreadable.advice": "The original log is preserved. Restart DSH and diagnose again. Do not repeatedly repair or delete logs.",
|
|
78
|
+
"health.failed.reason": "The operation did not complete",
|
|
79
|
+
"health.failed.advice": "Expand technical details to inspect the error. Resolve it before diagnosing again."
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// src/archive-discovery.js
|
|
83
|
+
var id = (value) => {
|
|
84
|
+
if (typeof value !== "string" || !value.length || value.length > 1024) throw new TypeError("\u4F1A\u8BDD ID \u65E0\u6548");
|
|
85
|
+
return value;
|
|
86
|
+
};
|
|
87
|
+
var queryText = (value, required = false) => {
|
|
88
|
+
if (typeof value !== "string" || value.length > 200 || required && !value.trim()) throw new TypeError("\u5173\u952E\u8BCD\u987B\u4E3A 1\uFF5E200 \u4E2A\u5B57\u7B26");
|
|
89
|
+
return value.trim();
|
|
90
|
+
};
|
|
91
|
+
var searchInputSchema = { parse(value) {
|
|
92
|
+
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");
|
|
93
|
+
return { sessionIds: [...new Set(value.sessionIds.map(id))], query: queryText(value.query, true) };
|
|
94
|
+
} };
|
|
95
|
+
var previewInputSchema = { parse(value) {
|
|
96
|
+
if (!value) throw new TypeError("\u9884\u89C8\u53C2\u6570\u65E0\u6548");
|
|
97
|
+
return { sessionId: id(value.sessionId), query: queryText(value.query ?? "") };
|
|
98
|
+
} };
|
|
99
|
+
var boundedString = (value, max) => {
|
|
100
|
+
if (typeof value !== "string" || value.length > max) throw new TypeError("\u8FD4\u56DE\u6587\u672C\u65E0\u6548");
|
|
101
|
+
return value;
|
|
102
|
+
};
|
|
103
|
+
var sequence = (value) => {
|
|
104
|
+
if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("\u6D88\u606F\u5E8F\u53F7\u65E0\u6548");
|
|
105
|
+
return value;
|
|
106
|
+
};
|
|
107
|
+
var searchResultSchema = { parse(value) {
|
|
108
|
+
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");
|
|
109
|
+
return {
|
|
110
|
+
items: value.items.map((row) => ({ sessionId: id(row.sessionId), seq: sequence(row.seq), snippet: boundedString(row.snippet, 400) })),
|
|
111
|
+
failures: value.failures.map((row) => ({ sessionId: id(row.sessionId), message: boundedString(row.message, 500) }))
|
|
112
|
+
};
|
|
113
|
+
} };
|
|
114
|
+
var previewResultSchema = { parse(value) {
|
|
115
|
+
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");
|
|
116
|
+
return {
|
|
117
|
+
sessionId: id(value.sessionId),
|
|
118
|
+
hasEarlier: value.hasEarlier,
|
|
119
|
+
hasLater: value.hasLater,
|
|
120
|
+
messages: value.messages.map((row) => {
|
|
121
|
+
if (!["user", "assistant"].includes(row.role) || typeof row.truncated !== "boolean") throw new TypeError("\u6D88\u606F\u89D2\u8272\u6216\u622A\u65AD\u72B6\u6001\u65E0\u6548");
|
|
122
|
+
return { seq: sequence(row.seq), role: row.role, text: boundedString(row.text, 2e3), truncated: row.truncated };
|
|
123
|
+
})
|
|
124
|
+
};
|
|
125
|
+
} };
|
|
126
|
+
var detailsInputSchema = { parse(value) {
|
|
127
|
+
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");
|
|
128
|
+
return { sessionIds: [...new Set(value.sessionIds.map(id))] };
|
|
129
|
+
} };
|
|
130
|
+
var detailsResultSchema = { parse(value) {
|
|
131
|
+
if (!value || !Array.isArray(value.items) || value.items.length > 20) throw new TypeError("\u4F1A\u8BDD\u8BE6\u60C5\u65E0\u6548");
|
|
132
|
+
return { items: value.items.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) })) };
|
|
133
|
+
} };
|
|
134
|
+
function compareTurnCounts(left, right, order) {
|
|
135
|
+
const a = Number.isSafeInteger(left) && left >= 0;
|
|
136
|
+
const b = Number.isSafeInteger(right) && right >= 0;
|
|
137
|
+
if (a !== b) return a ? -1 : 1;
|
|
138
|
+
return a ? order === "turnsAsc" ? left - right : right - left : 0;
|
|
139
|
+
}
|
|
140
|
+
async function copySessionText(text, clipboard = globalThis.navigator?.clipboard) {
|
|
141
|
+
if (typeof text !== "string" || !text) throw Object.assign(new Error("\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9"), { code: "copy.empty" });
|
|
142
|
+
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" });
|
|
143
|
+
try {
|
|
144
|
+
await clipboard.writeText(text);
|
|
145
|
+
} catch {
|
|
146
|
+
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" });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function discoveryInvocations() {
|
|
150
|
+
const codec = (name, schema) => ({ mode: "strict", typeSymbol: `@michengai/dsh-archive-manager/types#${name}`, create: () => schema, schema });
|
|
151
|
+
return [["searchSessionContent", searchInputSchema, searchResultSchema], ["diagnoseSession", repairInputSchema, repairResultSchema], ["repairSession", repairInputSchema, repairResultSchema], ["sessionDetails", detailsInputSchema, detailsResultSchema], ["searchArchivedContent", searchInputSchema, searchResultSchema], ["previewArchivedSession", previewInputSchema, previewResultSchema]].map(([method, input, output]) => ({
|
|
152
|
+
id: `@michengai/dsh-archive-manager#workspaceRegistry/${method}`,
|
|
153
|
+
service: "workspaceRegistry",
|
|
154
|
+
namespace: "workspaceRegistry",
|
|
155
|
+
method,
|
|
156
|
+
invocation: { kind: "direct" },
|
|
157
|
+
parameters: [{ name: "input", wire: "input", source: "json", codec: codec(method + "Input", input) }],
|
|
158
|
+
result: codec(method + "Result", output),
|
|
159
|
+
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
function findTextRange(text, query) {
|
|
163
|
+
const needle = query?.trim().toLowerCase();
|
|
164
|
+
if (!needle) return null;
|
|
165
|
+
const position = text.toLowerCase().indexOf(needle);
|
|
166
|
+
if (position < 0) return null;
|
|
167
|
+
let original = 0, folded = 0, start;
|
|
168
|
+
for (const character of text) {
|
|
169
|
+
const next = folded + character.toLowerCase().length;
|
|
170
|
+
if (start === void 0 && next > position) start = original;
|
|
171
|
+
original += character.length;
|
|
172
|
+
if (next >= position + needle.length) return { start, end: original };
|
|
173
|
+
folded = next;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
function sessionDetailCandidates(ids, byId) {
|
|
178
|
+
return [...new Set(ids)].map((id2) => byId[id2] ?? { id: id2 });
|
|
179
|
+
}
|
|
180
|
+
function dayBoundary(value, nextDay = false) {
|
|
181
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return NaN;
|
|
182
|
+
const [year, month, day] = value.split("-").map(Number);
|
|
183
|
+
const date = new Date(year, month - 1, day);
|
|
184
|
+
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) return NaN;
|
|
185
|
+
if (nextDay) date.setDate(date.getDate() + 1);
|
|
186
|
+
return date.getTime();
|
|
187
|
+
}
|
|
188
|
+
function validUpdatedRange(from, to) {
|
|
189
|
+
return (!from || Number.isFinite(dayBoundary(from))) && (!to || Number.isFinite(dayBoundary(to))) && (!from || !to || from <= to);
|
|
190
|
+
}
|
|
191
|
+
function matchesUpdatedRange(value, from, to) {
|
|
192
|
+
if (!validUpdatedRange(from, to)) return false;
|
|
193
|
+
if (!from && !to) return true;
|
|
194
|
+
const time = typeof value === "number" ? value : Date.parse(value);
|
|
195
|
+
return Number.isFinite(time) && (!from || time >= dayBoundary(from)) && (!to || time < dayBoundary(to, true));
|
|
196
|
+
}
|
|
197
|
+
async function searchArchiveBatches(ids, query, call, { signal, onProgress } = {}) {
|
|
198
|
+
const items = [], failures = [];
|
|
199
|
+
const unique = [...new Set(ids)];
|
|
200
|
+
const check = () => {
|
|
201
|
+
if (signal?.aborted) throw new Error("\u641C\u7D22\u5DF2\u53D6\u6D88");
|
|
202
|
+
};
|
|
203
|
+
for (let start = 0; start < unique.length; start += 20) {
|
|
204
|
+
check();
|
|
205
|
+
const result = searchResultSchema.parse(await call({ sessionIds: unique.slice(start, start + 20), query }));
|
|
206
|
+
check();
|
|
207
|
+
items.push(...result.items);
|
|
208
|
+
failures.push(...result.failures);
|
|
209
|
+
onProgress?.({ done: Math.min(start + 20, unique.length), total: unique.length, items: [...items], failures: [...failures] });
|
|
210
|
+
}
|
|
211
|
+
check();
|
|
212
|
+
return { items, failures };
|
|
213
|
+
}
|
|
214
|
+
function classifySessionError(error) {
|
|
215
|
+
const message = String(error?.message ?? error);
|
|
216
|
+
const descriptions = {
|
|
217
|
+
"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"],
|
|
218
|
+
"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"],
|
|
219
|
+
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"],
|
|
220
|
+
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"],
|
|
221
|
+
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"],
|
|
222
|
+
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"]
|
|
223
|
+
};
|
|
224
|
+
const codes = { ENOENT: "missing", EACCES: "permission", EPERM: "permission" };
|
|
225
|
+
const patterns = [
|
|
226
|
+
["repair-frame", /first frame is not exactly one header line/],
|
|
227
|
+
["legacy-source", /unclassified message source/],
|
|
228
|
+
["missing", /ENOENT|不存在|not found/i],
|
|
229
|
+
["permission", /EACCES|EPERM|permission/i],
|
|
230
|
+
["corrupt", /corrupt|JSON|incomplete|truncat|损坏/i]
|
|
231
|
+
];
|
|
232
|
+
const explicit = Object.hasOwn(codes, error?.code) ? codes[error.code] : error?.code;
|
|
233
|
+
const code = Object.hasOwn(descriptions, explicit) ? explicit : patterns.find(([, pattern]) => pattern.test(message))?.[0] ?? "unknown";
|
|
234
|
+
const [reason, advice] = descriptions[code];
|
|
235
|
+
return { code, reason, advice };
|
|
236
|
+
}
|
|
237
|
+
var repairInputSchema = { parse(value) {
|
|
238
|
+
const sessionId = id(value?.sessionId);
|
|
239
|
+
if (value?.token !== void 0 && !/^[a-f0-9]{64}$/.test(value.token)) throw new TypeError("\u4FEE\u590D\u51ED\u636E\u65E0\u6548");
|
|
240
|
+
return { sessionId, ...value.token !== void 0 ? { token: value.token } : {} };
|
|
241
|
+
} };
|
|
242
|
+
var repairResultSchema = { parse(value) {
|
|
243
|
+
if (!value || typeof value.repairable !== "boolean" || typeof value.repaired !== "boolean") throw new TypeError("\u8BCA\u65AD\u7ED3\u679C\u65E0\u6548");
|
|
244
|
+
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) };
|
|
245
|
+
} };
|
|
246
|
+
|
|
247
|
+
// src/session-health-ui.js
|
|
248
|
+
var defaultT = (key, args = {}) => Object.entries(args).reduce((text, [name, value]) => text.replaceAll("{" + name + "}", String(value)), healthZh[key] ?? key);
|
|
249
|
+
var sessionHealthCss = `
|
|
250
|
+
.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)}
|
|
251
|
+
.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}
|
|
252
|
+
.dsham_healthSummary{display:flex;align-items:center;gap:10px;min-height:52px;padding:12px 16px;list-style:none;cursor:pointer;box-sizing:border-box}
|
|
253
|
+
.dsham_health summary::-webkit-details-marker{display:none}.dsham_health summary::marker{content:''}
|
|
254
|
+
.dsham_healthSummary:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
255
|
+
.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)}
|
|
256
|
+
.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)}
|
|
257
|
+
.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)}
|
|
258
|
+
.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}
|
|
259
|
+
.dsham_healthItem{padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-layer-3)}
|
|
260
|
+
.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)}
|
|
261
|
+
.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)}
|
|
262
|
+
.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}
|
|
263
|
+
.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)}
|
|
264
|
+
.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}
|
|
265
|
+
.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)}
|
|
266
|
+
.dsham_health button:focus-visible,.dsham_health summary:focus-visible{outline:2px solid var(--health-accent);outline-offset:3px}.dsham_health svg{flex:none}
|
|
267
|
+
@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}}
|
|
268
|
+
@media(prefers-reduced-motion:reduce){.dsham_health *{transition:none!important}}
|
|
269
|
+
`;
|
|
270
|
+
function createSessionHealthPanel(React, icons = {}) {
|
|
271
|
+
const h = React.createElement;
|
|
272
|
+
const icon = (name, className) => icons[name] ? h("span", { className, "aria-hidden": true }, h(icons[name], { width: 16, height: 16 })) : null;
|
|
273
|
+
return function SessionHealthPanel({ items, sessions, t = defaultT, isArchived = true, diagnoseSession, repairSession, retry, pending }) {
|
|
274
|
+
const [results, setResults] = React.useState({});
|
|
275
|
+
const [busyId, setBusyId] = React.useState("");
|
|
276
|
+
const [notice, setNotice] = React.useState("");
|
|
277
|
+
const errors = items.filter((row) => row.error);
|
|
278
|
+
const run = async (row, repair) => {
|
|
279
|
+
if (busyId) return;
|
|
280
|
+
setBusyId(row.sessionId);
|
|
281
|
+
setNotice("");
|
|
282
|
+
try {
|
|
283
|
+
const result = await (repair ? repairSession({ sessionId: row.sessionId, token: results[row.sessionId].token }) : diagnoseSession({ sessionId: row.sessionId }));
|
|
284
|
+
setResults((previous) => ({ ...previous, [row.sessionId]: result }));
|
|
285
|
+
if (result.repaired) {
|
|
286
|
+
setNotice(true);
|
|
287
|
+
retry();
|
|
288
|
+
}
|
|
289
|
+
} catch (error) {
|
|
290
|
+
setResults((previous) => ({ ...previous, [row.sessionId]: { repairable: false, code: "failed", reason: "", advice: String(error?.message ?? error).slice(0, 1e3) } }));
|
|
291
|
+
} finally {
|
|
292
|
+
setBusyId("");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
return h(
|
|
296
|
+
"div",
|
|
297
|
+
{ className: "dsham_health" },
|
|
298
|
+
h("style", null, sessionHealthCss),
|
|
299
|
+
notice && h("p", { role: "status", className: "dsham_healthNotice" }, icon("check"), t("health.notice")),
|
|
300
|
+
errors.length > 0 && h(
|
|
301
|
+
"details",
|
|
302
|
+
{ className: "dsham_healthPanel" },
|
|
303
|
+
h(
|
|
304
|
+
"summary",
|
|
305
|
+
{ className: "dsham_healthSummary" },
|
|
306
|
+
icon("warning", "dsham_healthIcon"),
|
|
307
|
+
h("span", { className: "dsham_healthSummaryText" }, t(isArchived ? "health.archived" : "health.unarchived"), h("span", { className: "dsham_healthCount" }, errors.length)),
|
|
308
|
+
h("span", { className: "dsham_healthSummaryHint" }, t("health.heading")),
|
|
309
|
+
icon("chevron", "dsham_healthChevron")
|
|
310
|
+
),
|
|
311
|
+
h(
|
|
312
|
+
"div",
|
|
313
|
+
{ className: "dsham_healthBody" },
|
|
314
|
+
h(
|
|
315
|
+
"div",
|
|
316
|
+
{ className: "dsham_healthIntro" },
|
|
317
|
+
h("span", null, t(isArchived ? "health.scopeArchived" : "health.scopeUnarchived")),
|
|
318
|
+
h("button", { type: "button", className: "dsham_healthButton", "data-subtle": true, disabled: pending || Boolean(busyId), onClick: retry }, icon("refresh"), t("health.retry"))
|
|
319
|
+
),
|
|
320
|
+
errors.map((row) => {
|
|
321
|
+
const diagnostic = classifySessionError(row.error);
|
|
322
|
+
const result = results[row.sessionId];
|
|
323
|
+
const code = result ? Object.hasOwn(healthZh, "health." + result.code + ".reason") ? result.code : result.repaired ? "repaired" : result.repairable ? "ready" : "blocked" : diagnostic.code;
|
|
324
|
+
const title = sessions.find((session) => session.id === row.sessionId);
|
|
325
|
+
const repairing = result?.repairable && repairSession;
|
|
326
|
+
return h(
|
|
327
|
+
"section",
|
|
328
|
+
{ key: row.sessionId, className: "dsham_healthItem", "aria-busy": busyId === row.sessionId },
|
|
329
|
+
h(
|
|
330
|
+
"div",
|
|
331
|
+
{ className: "dsham_healthRow" },
|
|
332
|
+
h(
|
|
333
|
+
"div",
|
|
334
|
+
{ className: "dsham_healthCopy" },
|
|
335
|
+
h("strong", { className: "dsham_healthTitle" }, title?.displayTitle || title?.title || row.sessionId),
|
|
336
|
+
h(
|
|
337
|
+
"div",
|
|
338
|
+
{ className: "dsham_healthState", "data-state": result?.repaired ? "success" : repairing ? "ready" : "pending", role: result ? "status" : void 0 },
|
|
339
|
+
icon(result?.repaired ? "check" : "info"),
|
|
340
|
+
t("health." + code + ".reason", { n: result?.count ?? 0 })
|
|
341
|
+
)
|
|
342
|
+
),
|
|
343
|
+
diagnoseSession && h(
|
|
344
|
+
"button",
|
|
345
|
+
{ type: "button", className: "dsham_healthButton", "data-primary": Boolean(repairing), disabled: Boolean(busyId), onClick: () => run(row, Boolean(repairing)) },
|
|
346
|
+
icon(busyId === row.sessionId ? "refresh" : repairing ? "check" : "search"),
|
|
347
|
+
t(busyId === row.sessionId ? "health.busy" : repairing ? "health.confirm" : "health.diagnose")
|
|
348
|
+
)
|
|
349
|
+
),
|
|
350
|
+
result && h("p", { className: "dsham_healthAdvice" }, t("health." + code + ".advice")),
|
|
351
|
+
!result && diagnostic.code !== "legacy-source" && h("p", { className: "dsham_healthAdvice" }, t("health." + code + ".advice")),
|
|
352
|
+
h(
|
|
353
|
+
"details",
|
|
354
|
+
{ className: "dsham_healthTech" },
|
|
355
|
+
h("summary", null, icon("chevron", "dsham_healthChevron"), t("health.technical")),
|
|
356
|
+
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))
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
})
|
|
360
|
+
)
|
|
361
|
+
)
|
|
362
|
+
);
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/archive-discovery-ui.js
|
|
367
|
+
function createDiscoveryTools(React) {
|
|
368
|
+
const h = React.createElement;
|
|
369
|
+
function HighlightedText({ text, query }) {
|
|
370
|
+
const match = findTextRange(text, query);
|
|
371
|
+
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));
|
|
372
|
+
}
|
|
373
|
+
function useArchiveSearch(ids, query, enabled, call) {
|
|
374
|
+
const idsKey = JSON.stringify(ids);
|
|
375
|
+
const key = JSON.stringify([idsKey, query]);
|
|
376
|
+
const [revision, setRevision] = React.useState(0);
|
|
377
|
+
const [state, setState] = React.useState({ key: "", status: "idle", items: [], failures: [] });
|
|
378
|
+
React.useEffect(() => {
|
|
379
|
+
if (!enabled || !query.trim() || !call) return;
|
|
380
|
+
const controller = new AbortController();
|
|
381
|
+
setState({ key, status: "loading", items: [], failures: [], done: 0, total: ids.length });
|
|
382
|
+
const timer = setTimeout(() => {
|
|
383
|
+
searchArchiveBatches(JSON.parse(idsKey), query, call, { signal: controller.signal, onProgress: (progress) => {
|
|
384
|
+
if (!controller.signal.aborted) setState({ key, status: "loading", ...progress });
|
|
385
|
+
} }).then((result) => {
|
|
386
|
+
if (!controller.signal.aborted) setState({ key, status: "ready", done: ids.length, total: ids.length, ...result });
|
|
387
|
+
}).catch((error) => {
|
|
388
|
+
if (!controller.signal.aborted) setState((previous) => ({ ...previous, key, status: "error", error: String(error?.message ?? error) }));
|
|
389
|
+
});
|
|
390
|
+
}, 350);
|
|
391
|
+
return () => {
|
|
392
|
+
controller.abort();
|
|
393
|
+
clearTimeout(timer);
|
|
394
|
+
};
|
|
395
|
+
}, [idsKey, query, enabled, call, revision]);
|
|
396
|
+
const active = enabled && query.trim() && call;
|
|
397
|
+
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) };
|
|
398
|
+
}
|
|
399
|
+
function useSessionDetails(sessions, call, t) {
|
|
400
|
+
const key = JSON.stringify(sessions.map((session) => [session.id, session.updatedAt]));
|
|
401
|
+
const [revision, setRevision] = React.useState(0);
|
|
402
|
+
const [state, setState] = React.useState({ key: "", items: [], pending: false });
|
|
403
|
+
React.useEffect(() => {
|
|
404
|
+
if (!call) return;
|
|
405
|
+
let active = true;
|
|
406
|
+
const ids = [...new Set(JSON.parse(key).map((row) => row[0]))];
|
|
407
|
+
setState({ key, items: [], pending: ids.length > 0 });
|
|
408
|
+
const load = async () => {
|
|
409
|
+
const items2 = [];
|
|
410
|
+
for (let start = 0; start < ids.length && active; start += 20) {
|
|
411
|
+
const batch = ids.slice(start, start + 20);
|
|
412
|
+
try {
|
|
413
|
+
const result = detailsResultSchema.parse(await call({ sessionIds: batch }));
|
|
414
|
+
const found = new Map(result.items.map((row) => [row.sessionId, row]));
|
|
415
|
+
items2.push(...batch.map((sessionId) => found.get(sessionId) ?? { sessionId, turnCount: null, path: null, error: "", errorKey: "details.notReturned" }));
|
|
416
|
+
} catch (error) {
|
|
417
|
+
items2.push(...batch.map((sessionId) => ({ sessionId, turnCount: null, path: null, error: String(error?.message ?? error) })));
|
|
418
|
+
}
|
|
419
|
+
if (active) setState({ key, items: [...items2], pending: start + 20 < ids.length });
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
load();
|
|
423
|
+
return () => {
|
|
424
|
+
active = false;
|
|
425
|
+
};
|
|
426
|
+
}, [key, call, revision]);
|
|
427
|
+
const current = call && state.key === key ? state : { items: [], pending: Boolean(call && sessions.length) };
|
|
428
|
+
const items = current.items.map((row) => row.errorKey ? { ...row, error: t ? t(row.errorKey) : row.errorKey } : row);
|
|
429
|
+
return { ...current, items, byId: Object.fromEntries(items.map((row) => [row.sessionId, row])), retry: () => setRevision((value) => value + 1) };
|
|
430
|
+
}
|
|
431
|
+
function useArchivePreview(call, eligibleIds) {
|
|
432
|
+
const [target, setTarget] = React.useState(null);
|
|
433
|
+
const [state, setState] = React.useState({ status: "idle" });
|
|
434
|
+
const [revision, setRevision] = React.useState(0);
|
|
435
|
+
const key = target;
|
|
436
|
+
const available = target && eligibleIds.includes(target.session.id);
|
|
437
|
+
React.useEffect(() => {
|
|
438
|
+
if (target && !available) setTarget(null);
|
|
439
|
+
}, [target, available]);
|
|
440
|
+
React.useEffect(() => {
|
|
441
|
+
if (!available || typeof window === "undefined") return;
|
|
442
|
+
const onKeyDown = (event) => {
|
|
443
|
+
if (event.key !== "Escape") return;
|
|
444
|
+
event.preventDefault();
|
|
445
|
+
event.stopPropagation();
|
|
446
|
+
event.stopImmediatePropagation();
|
|
447
|
+
setTarget(null);
|
|
448
|
+
};
|
|
449
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
450
|
+
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
451
|
+
}, [available]);
|
|
452
|
+
React.useEffect(() => {
|
|
453
|
+
if (!target || !available || !call) return;
|
|
454
|
+
let active = true;
|
|
455
|
+
setState({ key, status: "loading" });
|
|
456
|
+
Promise.resolve().then(() => call({ sessionId: target.session.id, query: target.query })).then((value) => {
|
|
457
|
+
if (active) setState({ key, status: "ready", value });
|
|
458
|
+
}).catch((error) => {
|
|
459
|
+
if (active) setState({ key, status: "error", error: String(error?.message ?? error) });
|
|
460
|
+
});
|
|
461
|
+
return () => {
|
|
462
|
+
active = false;
|
|
463
|
+
};
|
|
464
|
+
}, [key, available, call, revision]);
|
|
465
|
+
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) };
|
|
466
|
+
}
|
|
467
|
+
function DiscoveryFilters({ t, from, to, onFrom, onTo, invalid, onClear }) {
|
|
468
|
+
const rootRef = React.useRef(null);
|
|
469
|
+
React.useEffect(() => {
|
|
470
|
+
const root = rootRef.current;
|
|
471
|
+
if (!root) return;
|
|
472
|
+
const onPointerDown = (event) => {
|
|
473
|
+
if (root.open && !root.contains(event.target)) root.open = false;
|
|
474
|
+
};
|
|
475
|
+
root.ownerDocument.addEventListener("pointerdown", onPointerDown, true);
|
|
476
|
+
return () => root.ownerDocument.removeEventListener("pointerdown", onPointerDown, true);
|
|
477
|
+
}, []);
|
|
478
|
+
const active = Boolean(from || to);
|
|
479
|
+
const range = active ? `${from || "\u2026"} \uFF5E ${to || "\u2026"}` : t("discovery.date");
|
|
480
|
+
return h(
|
|
481
|
+
"details",
|
|
482
|
+
{ className: "dsham_dateFilter", ref: rootRef, onKeyDown: (event) => {
|
|
483
|
+
if (event.key === "Escape" && event.currentTarget.open) {
|
|
484
|
+
event.preventDefault();
|
|
485
|
+
event.stopPropagation();
|
|
486
|
+
event.currentTarget.open = false;
|
|
487
|
+
event.currentTarget.querySelector("summary")?.focus();
|
|
488
|
+
}
|
|
489
|
+
} },
|
|
490
|
+
h(
|
|
491
|
+
"summary",
|
|
492
|
+
{ title: range, "aria-label": t("discovery.date") + (active ? t("common.separator") + range : ""), "data-active": active },
|
|
493
|
+
h(
|
|
494
|
+
"svg",
|
|
495
|
+
{ width: 14, height: 14, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "aria-hidden": true },
|
|
496
|
+
h("rect", { x: 2, y: 3.5, width: 12, height: 10.5, rx: 2 }),
|
|
497
|
+
h("path", { d: "M5 1.5v4M11 1.5v4M2 7h12" })
|
|
498
|
+
),
|
|
499
|
+
h("span", null, active ? t("discovery.dateActive") : t("discovery.date"))
|
|
500
|
+
),
|
|
501
|
+
h(
|
|
502
|
+
"div",
|
|
503
|
+
{ className: "dsham_datePanel" },
|
|
504
|
+
h("label", null, t("discovery.from"), h("input", { type: "date", value: from, max: to || void 0, onChange: (event) => onFrom(event.target.value) })),
|
|
505
|
+
h("label", null, t("discovery.to"), h("input", { type: "date", value: to, min: from || void 0, onChange: (event) => onTo(event.target.value) })),
|
|
506
|
+
invalid && h("p", { role: "alert" }, t("discovery.invalidDate")),
|
|
507
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: !active, onClick: onClear }, t("discovery.clearDate"))
|
|
508
|
+
)
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
function SearchStatus({ state, t }) {
|
|
512
|
+
if (state.status === "idle") return null;
|
|
513
|
+
return h(
|
|
514
|
+
"div",
|
|
515
|
+
{ className: "dsham_discoveryStatus", role: "status", "aria-live": "polite" },
|
|
516
|
+
h("p", null, t(state.status === "loading" ? "discovery.searching" : state.status === "error" ? "discovery.searchError" : "discovery.searched", { done: state.done ?? 0, total: state.total ?? 0 })),
|
|
517
|
+
state.status === "error" && h("p", null, state.error),
|
|
518
|
+
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)))),
|
|
519
|
+
(state.status === "error" || state.status === "ready" && state.failures.length > 0) && h("button", { type: "button", className: "dsham_settingsAction", onClick: state.retry }, t("discovery.retry"))
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
function PreviewContent({ preview, t, MarkdownText }) {
|
|
523
|
+
const [raw, setRaw] = React.useState(false);
|
|
524
|
+
if (preview.status === "loading") return h("p", { role: "status" }, t("discovery.loading"));
|
|
525
|
+
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")));
|
|
526
|
+
const value = preview.value;
|
|
527
|
+
if (!value) return null;
|
|
528
|
+
return h(
|
|
529
|
+
"div",
|
|
530
|
+
{ className: "dsham_previewMessages" },
|
|
531
|
+
h(
|
|
532
|
+
"div",
|
|
533
|
+
{ className: "dsham_previewToolbar" },
|
|
534
|
+
h("span", { title: t("discovery.previewHint") }, t("discovery.readOnly"), " \xB7 ", t("discovery.messageCount", { n: value.messages.length })),
|
|
535
|
+
MarkdownText && h(
|
|
536
|
+
"div",
|
|
537
|
+
{ className: "dsham_previewModes", role: "group", "aria-label": t("discovery.displayMode") },
|
|
538
|
+
h("button", { type: "button", "aria-pressed": !raw, onClick: () => setRaw(false) }, t("discovery.formatted")),
|
|
539
|
+
h("button", { type: "button", "aria-pressed": raw, onClick: () => setRaw(true) }, t("discovery.raw"))
|
|
540
|
+
)
|
|
541
|
+
),
|
|
542
|
+
value.hasEarlier && h("p", null, t("discovery.earlier")),
|
|
543
|
+
!value.messages.length && h("p", null, t("discovery.empty")),
|
|
544
|
+
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")))),
|
|
545
|
+
value.hasLater && h("p", null, t("discovery.later"))
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
return { HighlightedText, useSessionDetails, useArchiveSearch, useArchivePreview, DiscoveryFilters, SearchStatus, PreviewContent };
|
|
549
|
+
}
|
|
550
|
+
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}";
|
|
551
|
+
var discoveryZh = {
|
|
552
|
+
"common.separator": "\uFF1A",
|
|
553
|
+
"details.notReturned": "\u5BBF\u4E3B\u672A\u8FD4\u56DE\u4F1A\u8BDD\u8BE6\u60C5",
|
|
554
|
+
"copy.empty": "\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9",
|
|
555
|
+
"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",
|
|
556
|
+
"copy.denied": "\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u5141\u8BB8\u6D4F\u89C8\u5668\u8BBF\u95EE\u526A\u8D34\u677F\u540E\u91CD\u8BD5",
|
|
557
|
+
"discovery.you": "\u4F60",
|
|
558
|
+
"discovery.ai": "AI",
|
|
559
|
+
"discovery.readOnly": "\u53EA\u8BFB\u9884\u89C8",
|
|
560
|
+
"discovery.messageCount": "\u672C\u6B21\u663E\u793A {n} \u6761\u6D88\u606F",
|
|
561
|
+
"discovery.displayMode": "\u663E\u793A\u65B9\u5F0F",
|
|
562
|
+
"discovery.formatted": "\u6392\u7248",
|
|
563
|
+
"discovery.raw": "\u539F\u6587\u4E0E\u9AD8\u4EAE",
|
|
564
|
+
"discovery.copyCode": "\u590D\u5236\u4EE3\u7801",
|
|
565
|
+
"discovery.footnotes": "\u6CE8\u91CA",
|
|
566
|
+
"details.turns": "{n} \u8F6E",
|
|
567
|
+
"details.unknown": "\u8F6E\u6B21\u672A\u77E5",
|
|
568
|
+
"details.pending": "\u8F6E\u6B21\u8BFB\u53D6\u4E2D",
|
|
569
|
+
"details.hint": "\u6309\u7528\u6237\u63D0\u4EA4\u6D88\u606F\u6570\u7EDF\u8BA1\uFF0C\u4E0D\u542B\u5DE5\u5177\u8C03\u7528\u548C\u63D2\u4EF6\u6CE8\u5165",
|
|
570
|
+
"details.more": "\u8F6E\u6B21\u6700\u591A",
|
|
571
|
+
"details.less": "\u8F6E\u6B21\u6700\u5C11",
|
|
572
|
+
"details.failed": "{n} \u6761\u4F1A\u8BDD\u8BE6\u60C5\u8BFB\u53D6\u5931\u8D25",
|
|
573
|
+
"details.copyId": "\u590D\u5236\u4F1A\u8BDD ID",
|
|
574
|
+
"details.copyPath": "\u590D\u5236\u4F1A\u8BDD\u8DEF\u5F84",
|
|
575
|
+
"details.copied": "\u5DF2\u590D\u5236",
|
|
576
|
+
"details.noPath": "\u5BBF\u4E3B\u672A\u63D0\u4F9B\u53EF\u590D\u5236\u7684\u4F1A\u8BDD\u8DEF\u5F84",
|
|
577
|
+
"discovery.date": "\u65E5\u671F",
|
|
578
|
+
"discovery.dateActive": "\u65E5\u671F\xB7\u5DF2\u9009",
|
|
579
|
+
"discovery.clearDate": "\u6E05\u9664\u65E5\u671F",
|
|
580
|
+
"discovery.active": "\u5DF2\u542F\u7528",
|
|
581
|
+
"discovery.scope": "\u67E5\u627E\u8303\u56F4",
|
|
582
|
+
"discovery.titleOnly": "\u4EC5\u6807\u9898",
|
|
583
|
+
"discovery.titleAndContent": "\u6807\u9898\u4E0E\u6B63\u6587",
|
|
584
|
+
"discovery.from": "\u66F4\u65B0\u65F6\u95F4\u4ECE",
|
|
585
|
+
"discovery.to": "\u81F3",
|
|
586
|
+
"discovery.clear": "\u6E05\u9664\u6761\u4EF6",
|
|
587
|
+
"discovery.invalidDate": "\u5F00\u59CB\u65E5\u671F\u4E0D\u80FD\u665A\u4E8E\u7ED3\u675F\u65E5\u671F\uFF0C\u8BF7\u68C0\u67E5\u65E5\u671F\u8303\u56F4\u3002",
|
|
588
|
+
"discovery.searching": "\u6B63\u5728\u68C0\u7D22\u6B63\u6587\uFF1A{done} / {total}",
|
|
589
|
+
"discovery.searched": "\u6B63\u6587\u68C0\u7D22\u5B8C\u6210\uFF1A{done} / {total}",
|
|
590
|
+
"discovery.searchError": "\u6B63\u6587\u68C0\u7D22\u672A\u5B8C\u6210\uFF0C\u5F53\u524D\u7ED3\u679C\u53EF\u80FD\u4E0D\u5B8C\u6574\u3002",
|
|
591
|
+
"discovery.failed": "{n} \u6761\u4F1A\u8BDD\u8BFB\u53D6\u5931\u8D25",
|
|
592
|
+
"discovery.retry": "\u91CD\u8BD5",
|
|
593
|
+
"discovery.preview": "\u5FEB\u901F\u9884\u89C8",
|
|
594
|
+
"discovery.loading": "\u6B63\u5728\u8BFB\u53D6\u4F1A\u8BDD\u2026",
|
|
595
|
+
"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",
|
|
596
|
+
"discovery.earlier": "\u524D\u9762\u8FD8\u6709\u6D88\u606F\uFF0C\u53EF\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B\u3002",
|
|
597
|
+
"discovery.later": "\u540E\u9762\u8FD8\u6709\u6D88\u606F\uFF0C\u53EF\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B\u3002",
|
|
598
|
+
"discovery.empty": "\u6CA1\u6709\u53EF\u9884\u89C8\u7684\u7528\u6237\u6216\u52A9\u624B\u6587\u672C\u3002",
|
|
599
|
+
"discovery.truncated": "\u672C\u6761\u4EC5\u663E\u793A\u90E8\u5206\u5185\u5BB9\u3002",
|
|
600
|
+
"discovery.user": "\u7528\u6237",
|
|
601
|
+
"discovery.assistant": "\u52A9\u624B",
|
|
602
|
+
"discovery.openFull": "\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD",
|
|
603
|
+
"discovery.searchPlaceholder": "\u641C\u7D22\u6807\u9898\u6216\u6B63\u6587"
|
|
604
|
+
};
|
|
605
|
+
var discoveryEn = {
|
|
606
|
+
"common.separator": ": ",
|
|
607
|
+
"details.notReturned": "The host did not return session details",
|
|
608
|
+
"copy.empty": "Nothing to copy",
|
|
609
|
+
"copy.unavailable": "Clipboard unavailable. Open the page over HTTPS or localhost.",
|
|
610
|
+
"copy.denied": "Copy failed. Allow clipboard access and retry.",
|
|
611
|
+
"discovery.you": "You",
|
|
612
|
+
"discovery.ai": "AI",
|
|
613
|
+
"discovery.readOnly": "Read-only preview",
|
|
614
|
+
"discovery.messageCount": "Showing {n} messages",
|
|
615
|
+
"discovery.displayMode": "Display mode",
|
|
616
|
+
"discovery.formatted": "Formatted",
|
|
617
|
+
"discovery.raw": "Source and highlights",
|
|
618
|
+
"discovery.copyCode": "Copy code",
|
|
619
|
+
"discovery.footnotes": "Footnotes",
|
|
620
|
+
"details.turns": "{n} turns",
|
|
621
|
+
"details.unknown": "Unknown turns",
|
|
622
|
+
"details.pending": "Loading turns",
|
|
623
|
+
"details.hint": "User submissions; excludes tool calls and injected messages",
|
|
624
|
+
"details.more": "Most turns",
|
|
625
|
+
"details.less": "Fewest turns",
|
|
626
|
+
"details.failed": "Could not read turns for {n} sessions",
|
|
627
|
+
"details.copyId": "Copy session ID",
|
|
628
|
+
"details.copyPath": "Copy session path",
|
|
629
|
+
"details.copied": "Copied",
|
|
630
|
+
"details.noPath": "The host did not provide a session path",
|
|
631
|
+
"discovery.date": "Date",
|
|
632
|
+
"discovery.dateActive": "Date \xB7 Set",
|
|
633
|
+
"discovery.clearDate": "Clear dates",
|
|
634
|
+
"discovery.active": "Active",
|
|
635
|
+
"discovery.scope": "Search in",
|
|
636
|
+
"discovery.titleOnly": "Titles",
|
|
637
|
+
"discovery.titleAndContent": "Titles and content",
|
|
638
|
+
"discovery.from": "Updated from",
|
|
639
|
+
"discovery.to": "To",
|
|
640
|
+
"discovery.clear": "Clear filters",
|
|
641
|
+
"discovery.invalidDate": "Check the date range: the start must not be after the end.",
|
|
642
|
+
"discovery.searching": "Searching content: {done} / {total}",
|
|
643
|
+
"discovery.searched": "Content search complete: {done} / {total}",
|
|
644
|
+
"discovery.searchError": "Content search is incomplete; results may be missing.",
|
|
645
|
+
"discovery.failed": "Could not read {n} conversations",
|
|
646
|
+
"discovery.retry": "Retry",
|
|
647
|
+
"discovery.preview": "Quick preview",
|
|
648
|
+
"discovery.loading": "Reading conversation\u2026",
|
|
649
|
+
"discovery.previewHint": "Read-only original conversation text; keeps the conversation archived. Excludes tools, attachments, reasoning and system content.",
|
|
650
|
+
"discovery.earlier": "More messages before this preview. Open the full conversation to read them.",
|
|
651
|
+
"discovery.later": "More messages after this preview. Open the full conversation to read them.",
|
|
652
|
+
"discovery.empty": "No user or assistant text to preview.",
|
|
653
|
+
"discovery.truncated": "Only part of this message is shown.",
|
|
654
|
+
"discovery.user": "User",
|
|
655
|
+
"discovery.assistant": "Assistant",
|
|
656
|
+
"discovery.openFull": "Open full conversation",
|
|
657
|
+
"discovery.searchPlaceholder": "Search titles or content"
|
|
658
|
+
};
|
|
659
|
+
|
|
2
660
|
// src/archive-experience.js
|
|
3
661
|
var ArchiveNavigationError = class extends Error {
|
|
4
662
|
constructor(code) {
|
|
@@ -10,6 +668,27 @@
|
|
|
10
668
|
function formatArchiveNavigationError(error, t) {
|
|
11
669
|
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) : String(error?.message ?? error);
|
|
12
670
|
}
|
|
671
|
+
function retainInfoSnapshot(sessions, id2) {
|
|
672
|
+
if (typeof sessions?.retainInfo !== "function") return;
|
|
673
|
+
const source = sessions.retainInfo(id2);
|
|
674
|
+
return typeof source?.getSnapshot === "function" ? source.getSnapshot() : source;
|
|
675
|
+
}
|
|
676
|
+
function mainViewSessionId(list) {
|
|
677
|
+
const byId = list?.byId;
|
|
678
|
+
if (byId === void 0) return;
|
|
679
|
+
for (const session of Object.values(byId)) {
|
|
680
|
+
if ((session?.retainedBy?.mainView ?? 0) > 0) return session.id;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
function currentSessionId(list) {
|
|
684
|
+
return mainViewSessionId(list) ?? list?.current;
|
|
685
|
+
}
|
|
686
|
+
function sessionIsCurrent(list, id2, sessions) {
|
|
687
|
+
if (id2 === void 0 || id2 === "") return false;
|
|
688
|
+
if ((list?.byId?.[id2]?.retainedBy?.mainView ?? 0) > 0) return true;
|
|
689
|
+
if ((retainInfoSnapshot(sessions, id2)?.retainedBy?.mainView ?? 0) > 0) return true;
|
|
690
|
+
return list?.current === id2;
|
|
691
|
+
}
|
|
13
692
|
async function openArchivedConversation(actions, sessionId, restore, isActive = () => true) {
|
|
14
693
|
if (restore) {
|
|
15
694
|
if (typeof actions.prepare === "function") await actions.prepare(sessionId);
|
|
@@ -23,9 +702,9 @@
|
|
|
23
702
|
let allowed;
|
|
24
703
|
const original = navigation?.clearArchivedCurrent;
|
|
25
704
|
const descriptor = navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent");
|
|
705
|
+
const viewing = (id2) => sessionIsCurrent(sessions.list.getSnapshot(), id2, sessions);
|
|
26
706
|
const wrapped = function(...args) {
|
|
27
|
-
|
|
28
|
-
if (current === allowed && current !== void 0 && workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false;
|
|
707
|
+
if (allowed !== void 0 && viewing(allowed) && workspaces.list.getSnapshot().archivedSessionIds.includes(allowed)) return false;
|
|
29
708
|
allowed = void 0;
|
|
30
709
|
return original.apply(this, args);
|
|
31
710
|
};
|
|
@@ -39,16 +718,22 @@
|
|
|
39
718
|
}
|
|
40
719
|
}
|
|
41
720
|
return {
|
|
42
|
-
open(
|
|
43
|
-
allowed =
|
|
721
|
+
open(id2) {
|
|
722
|
+
allowed = id2;
|
|
44
723
|
try {
|
|
45
|
-
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(
|
|
724
|
+
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(id2)) {
|
|
46
725
|
warn("archive-manager: \u5F52\u6863\u5BFC\u822A\u9002\u914D\u4E0D\u53EF\u7528\u6216\u5DF2\u88AB\u66FF\u6362\u3002");
|
|
47
726
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
48
727
|
}
|
|
49
728
|
beginNavigation?.();
|
|
50
|
-
sessions.
|
|
51
|
-
if (sessions.
|
|
729
|
+
if (typeof sessions.retain === "function" && typeof navigation?.openSession === "function") navigation.openSession(id2);
|
|
730
|
+
else if (typeof sessions.open === "function") sessions.open(id2);
|
|
731
|
+
else if (typeof navigation?.openSession === "function") navigation.openSession(id2);
|
|
732
|
+
else {
|
|
733
|
+
warn("archive-manager: \u5BBF\u4E3B\u672A\u63D0\u4F9B\u4F1A\u8BDD\u6253\u5F00\u63A5\u53E3\u3002");
|
|
734
|
+
throw new ArchiveNavigationError("navigationUnavailable");
|
|
735
|
+
}
|
|
736
|
+
if (!viewing(id2)) {
|
|
52
737
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\u3002", { cleanupAvailable: typeof original === "function" });
|
|
53
738
|
throw new ArchiveNavigationError("sessionNotRetained");
|
|
54
739
|
}
|
|
@@ -138,7 +823,7 @@
|
|
|
138
823
|
var STYLE_ID = "michengai-plugin-update-ui";
|
|
139
824
|
var CSS = `
|
|
140
825
|
.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}
|
|
141
|
-
.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-
|
|
826
|
+
.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}}
|
|
142
827
|
`;
|
|
143
828
|
var ZH = {
|
|
144
829
|
check: "\u68C0\u67E5\u66F4\u65B0",
|
|
@@ -190,7 +875,9 @@
|
|
|
190
875
|
restarting: "Update complete. Restarting DSH Desktop\u2026",
|
|
191
876
|
unavailable: "Automatic update is unavailable. Use the manual command."
|
|
192
877
|
};
|
|
193
|
-
function strings() {
|
|
878
|
+
function strings(language) {
|
|
879
|
+
if (language === "en") return EN;
|
|
880
|
+
if (language === "zh") return ZH;
|
|
194
881
|
const lang = document.documentElement.lang.toLowerCase();
|
|
195
882
|
const settings = document.querySelector('[role="dialog"]')?.textContent ?? "";
|
|
196
883
|
return lang.startsWith("en") || settings.includes("Settings") && !settings.includes("\u8BBE\u7F6E") ? EN : ZH;
|
|
@@ -235,6 +922,7 @@
|
|
|
235
922
|
if (typeof document === "undefined" || document.body === null) return () => {
|
|
236
923
|
};
|
|
237
924
|
ensureStyle();
|
|
925
|
+
const getStrings = () => strings(options.getLanguage?.());
|
|
238
926
|
const controller = new AbortController();
|
|
239
927
|
let payload;
|
|
240
928
|
let overlay;
|
|
@@ -269,12 +957,18 @@
|
|
|
269
957
|
if (version.textContent !== versionLabel) version.textContent = versionLabel;
|
|
270
958
|
}
|
|
271
959
|
const links = row.querySelector(options.linksSelector);
|
|
272
|
-
if (links === null
|
|
960
|
+
if (links === null) return;
|
|
961
|
+
const existing = links.querySelector(`[data-mpi-check="${options.packageName}"]`);
|
|
962
|
+
if (existing !== null) {
|
|
963
|
+
const label = getStrings().check;
|
|
964
|
+
if (existing.querySelector("[data-mpi-label]")?.textContent !== label) setButtonLabel(existing, label);
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
273
967
|
const button = document.createElement("button");
|
|
274
968
|
button.type = "button";
|
|
275
969
|
button.className = "mpi-check";
|
|
276
970
|
button.dataset.mpiCheck = options.packageName;
|
|
277
|
-
setButtonContent(button,
|
|
971
|
+
setButtonContent(button, getStrings().check, "refresh");
|
|
278
972
|
button.addEventListener("click", openDialog);
|
|
279
973
|
links.append(button);
|
|
280
974
|
};
|
|
@@ -289,7 +983,7 @@
|
|
|
289
983
|
};
|
|
290
984
|
function openDialog() {
|
|
291
985
|
closeDialog();
|
|
292
|
-
const text =
|
|
986
|
+
const text = getStrings();
|
|
293
987
|
overlay = document.createElement("div");
|
|
294
988
|
overlay.className = "mpi-overlay";
|
|
295
989
|
const dialog = document.createElement("section");
|
|
@@ -297,7 +991,7 @@
|
|
|
297
991
|
dialog.setAttribute("role", "dialog");
|
|
298
992
|
dialog.setAttribute("aria-modal", "true");
|
|
299
993
|
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>`;
|
|
300
|
-
const name =
|
|
994
|
+
const name = text === EN ? options.enName : options.zhName;
|
|
301
995
|
dialog.querySelector("h2").textContent = `${name} ${text.update}`;
|
|
302
996
|
dialog.querySelector(".mpi-intro").textContent = text.intro;
|
|
303
997
|
const terms = dialog.querySelectorAll("dt");
|
|
@@ -423,6 +1117,210 @@
|
|
|
423
1117
|
};
|
|
424
1118
|
}
|
|
425
1119
|
|
|
1120
|
+
// src/archive-organizer.js
|
|
1121
|
+
function checkedId(value) {
|
|
1122
|
+
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");
|
|
1123
|
+
return value;
|
|
1124
|
+
}
|
|
1125
|
+
var favoriteInputSchema = {
|
|
1126
|
+
parse(value) {
|
|
1127
|
+
if (!value || typeof value !== "object" || typeof value.favorite !== "boolean") throw new TypeError("\u6536\u85CF\u72B6\u6001\u5FC5\u987B\u4E3A\u5E03\u5C14\u503C");
|
|
1128
|
+
return { sessionId: checkedId(value.sessionId), favorite: value.favorite };
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
var favoriteStateSchema = {
|
|
1132
|
+
parse(value) {
|
|
1133
|
+
if (!value || !Array.isArray(value.favoriteSessionIds) || value.favoriteSessionIds.length > 1e5) throw new TypeError("\u6536\u85CF\u96C6\u5408\u65E0\u6548");
|
|
1134
|
+
return { favoriteSessionIds: [...new Set(value.favoriteSessionIds.map(checkedId))] };
|
|
1135
|
+
},
|
|
1136
|
+
safeParse(value) {
|
|
1137
|
+
try {
|
|
1138
|
+
return { success: true, data: this.parse(value) };
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
return { success: false, error };
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
function favoriteInvocations() {
|
|
1145
|
+
const codec = (name, schema) => ({ mode: "strict", typeSymbol: `@michengai/dsh-archive-manager/types#${name}`, create: () => schema, schema });
|
|
1146
|
+
return ["favoriteSessions", "setSessionFavorite"].map((method) => ({
|
|
1147
|
+
id: `@michengai/dsh-archive-manager#workspaceRegistry/${method}`,
|
|
1148
|
+
service: "workspaceRegistry",
|
|
1149
|
+
namespace: "workspaceRegistry",
|
|
1150
|
+
method,
|
|
1151
|
+
invocation: { kind: "direct" },
|
|
1152
|
+
parameters: method === "favoriteSessions" ? [] : [{ name: "input", wire: "input", source: "json", codec: codec("FavoriteInput", favoriteInputSchema) }],
|
|
1153
|
+
result: codec("FavoriteState", favoriteStateSchema),
|
|
1154
|
+
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
1155
|
+
}));
|
|
1156
|
+
}
|
|
1157
|
+
function idleArchiveCandidate(session, { days, now = Date.now(), favorites = /* @__PURE__ */ new Set(), currentId, pending = /* @__PURE__ */ new Map() }) {
|
|
1158
|
+
if (!session || !Number.isInteger(days) || days < 1 || days > 36500) return false;
|
|
1159
|
+
if (favorites.has(session.id) || session.id === currentId || session.retainedBy?.mainView > 0) return false;
|
|
1160
|
+
if (session.running || session.runningSubagentCount > 0 || session.pendingInteraction != null || pending.has(session.id)) return false;
|
|
1161
|
+
const updated = typeof session.updatedAt === "number" ? session.updatedAt : Date.parse(session.updatedAt);
|
|
1162
|
+
return Number.isFinite(updated) && updated <= now - days * 864e5;
|
|
1163
|
+
}
|
|
1164
|
+
async function runSessionBatch(ids, operate, { onProgress, refresh } = {}) {
|
|
1165
|
+
const requested = [...new Set(ids.map(checkedId))];
|
|
1166
|
+
const result = { requested, succeeded: [], skipped: [], failures: [], unprocessed: [], remaining: [], refreshError: null };
|
|
1167
|
+
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 });
|
|
1168
|
+
report();
|
|
1169
|
+
for (const [index, id2] of requested.entries()) {
|
|
1170
|
+
try {
|
|
1171
|
+
(await operate(id2) ? result.succeeded : result.skipped).push(id2);
|
|
1172
|
+
} catch (error) {
|
|
1173
|
+
result.failures.push({ sessionId: id2, message: error instanceof Error ? error.message : String(error) });
|
|
1174
|
+
result.unprocessed = requested.slice(index + 1);
|
|
1175
|
+
result.remaining = requested.slice(index);
|
|
1176
|
+
report();
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
report();
|
|
1180
|
+
}
|
|
1181
|
+
try {
|
|
1182
|
+
await refresh?.();
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
result.refreshError = error instanceof Error ? error.message : String(error);
|
|
1185
|
+
}
|
|
1186
|
+
return result;
|
|
1187
|
+
}
|
|
1188
|
+
function createSessionOrganizer({ workspaces, sessions, archive, restore, deleteOne, getFavorites, refresh, currentSessionId: currentSessionId2 }) {
|
|
1189
|
+
return async (kind, ids, options = {}) => {
|
|
1190
|
+
if (!["archive", "restore", "undo", "delete"].includes(kind)) throw new TypeError("\u672A\u77E5\u6279\u91CF\u64CD\u4F5C");
|
|
1191
|
+
return runSessionBatch(ids, async (id2) => {
|
|
1192
|
+
const before = workspaces.getSnapshot();
|
|
1193
|
+
const archived = before.archivedSessionIds.includes(id2);
|
|
1194
|
+
if (kind === "archive") {
|
|
1195
|
+
if (archived) return false;
|
|
1196
|
+
const snapshot = sessions.getSnapshot();
|
|
1197
|
+
const session = snapshot.byId[id2];
|
|
1198
|
+
if (!session) return false;
|
|
1199
|
+
if (options.idleDays !== void 0) {
|
|
1200
|
+
const favorites = new Set((await getFavorites()).favoriteSessionIds);
|
|
1201
|
+
const latest = sessions.getSnapshot();
|
|
1202
|
+
if (!idleArchiveCandidate(latest.byId[id2], { days: options.idleDays, favorites, currentId: currentSessionId2(latest), pending: options.getPending?.() ?? options.pending })) return false;
|
|
1203
|
+
}
|
|
1204
|
+
await archive(id2);
|
|
1205
|
+
return workspaces.getSnapshot().archivedSessionIds.includes(id2);
|
|
1206
|
+
}
|
|
1207
|
+
if (!archived) return false;
|
|
1208
|
+
if (kind === "delete") {
|
|
1209
|
+
await deleteOne(id2);
|
|
1210
|
+
return true;
|
|
1211
|
+
}
|
|
1212
|
+
const value = await restore(id2);
|
|
1213
|
+
const remaining = value?.archivedSessionIds ?? workspaces.getSnapshot().archivedSessionIds;
|
|
1214
|
+
return !remaining.includes(id2);
|
|
1215
|
+
}, { onProgress: options.onProgress, refresh });
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
// src/archive-organizer-ui.js
|
|
1220
|
+
function createOrganizerPanel(React) {
|
|
1221
|
+
const h = React.createElement;
|
|
1222
|
+
return function OrganizerPanel({ t, archived, busy, ready, days, onDays, count, onPreview, progress, result, onRetry, undoCount, onUndo, onReload }) {
|
|
1223
|
+
return h(
|
|
1224
|
+
React.Fragment,
|
|
1225
|
+
null,
|
|
1226
|
+
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}"),
|
|
1227
|
+
(!archived || !ready) && h(
|
|
1228
|
+
"div",
|
|
1229
|
+
{ className: "dsham_organizer" },
|
|
1230
|
+
h(
|
|
1231
|
+
"div",
|
|
1232
|
+
{ className: "dsham_organizerControls" },
|
|
1233
|
+
!ready && h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onReload }, t("organizer.reloadFavorites")),
|
|
1234
|
+
!archived && h(
|
|
1235
|
+
React.Fragment,
|
|
1236
|
+
null,
|
|
1237
|
+
h("label", null, t("organizer.idleDays"), h("input", { type: "number", min: 1, max: 36500, step: 1, value: days, disabled: busy, onChange: (event) => onDays(event.target.value), "aria-label": t("organizer.idleDays") })),
|
|
1238
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: busy || !ready || count === 0, onClick: onPreview }, t("organizer.preview", { n: count }))
|
|
1239
|
+
)
|
|
1240
|
+
),
|
|
1241
|
+
!archived && h("p", null, t("organizer.rules"))
|
|
1242
|
+
),
|
|
1243
|
+
(progress || result || undoCount > 0) && h(
|
|
1244
|
+
"section",
|
|
1245
|
+
{ className: "dsham_batchFeedback", "aria-label": t("organizer.feedback") },
|
|
1246
|
+
progress && h(
|
|
1247
|
+
"div",
|
|
1248
|
+
{ role: "status", "aria-live": "polite" },
|
|
1249
|
+
h("progress", { value: progress.done, max: Math.max(1, progress.total), "aria-label": t("organizer.progress") }),
|
|
1250
|
+
t("organizer.progressCount", { done: progress.done, total: progress.total })
|
|
1251
|
+
),
|
|
1252
|
+
result && h(
|
|
1253
|
+
"div",
|
|
1254
|
+
{ role: "status" },
|
|
1255
|
+
h("strong", null, t(`organizer.${result.kind ?? "archive"}Result`)),
|
|
1256
|
+
h("p", null, t("organizer.result", { succeeded: result.succeeded.length, skipped: result.skipped.length, failed: result.failures.length, remaining: result.unprocessed.length })),
|
|
1257
|
+
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)))),
|
|
1258
|
+
result.refreshError && h("p", { role: "alert" }, t("organizer.refreshError", { detail: result.refreshError })),
|
|
1259
|
+
result.remaining.length > 0 && h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onRetry }, t("organizer.retry", { n: result.remaining.length }))
|
|
1260
|
+
),
|
|
1261
|
+
undoCount > 0 && h(
|
|
1262
|
+
"div",
|
|
1263
|
+
{ className: "dsham_organizerControls" },
|
|
1264
|
+
h("button", { type: "button", className: "dsham_settingsAction", disabled: busy, onClick: onUndo }, t("organizer.undo", { n: undoCount })),
|
|
1265
|
+
h("p", null, t("organizer.undoHint"))
|
|
1266
|
+
)
|
|
1267
|
+
)
|
|
1268
|
+
);
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
var organizerZh = {
|
|
1272
|
+
"organizer.feedback": "\u64CD\u4F5C\u53CD\u9988",
|
|
1273
|
+
"organizer.allSessions": "\u5168\u90E8\u4F1A\u8BDD",
|
|
1274
|
+
"organizer.favoriteFilter": "\u6536\u85CF\u7B5B\u9009",
|
|
1275
|
+
"organizer.archiveResult": "\u5F52\u6863\u7ED3\u679C",
|
|
1276
|
+
"organizer.restoreResult": "\u6062\u590D\u7ED3\u679C",
|
|
1277
|
+
"organizer.deleteResult": "\u5220\u9664\u7ED3\u679C",
|
|
1278
|
+
"organizer.undoResult": "\u64A4\u56DE\u7ED3\u679C",
|
|
1279
|
+
"organizer.favorite": "\u6536\u85CF",
|
|
1280
|
+
"organizer.unfavorite": "\u53D6\u6D88\u6536\u85CF",
|
|
1281
|
+
"organizer.favoritesOnly": "\u53EA\u770B\u6536\u85CF",
|
|
1282
|
+
"organizer.reloadFavorites": "\u91CD\u65B0\u52A0\u8F7D\u6536\u85CF",
|
|
1283
|
+
"organizer.idleDays": "\u95F2\u7F6E\u5929\u6570",
|
|
1284
|
+
"organizer.preview": "\u9884\u89C8\u95F2\u7F6E\u5F52\u6863\uFF08{n}\uFF09",
|
|
1285
|
+
"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",
|
|
1286
|
+
"organizer.progress": "\u6279\u91CF\u64CD\u4F5C\u8FDB\u5EA6",
|
|
1287
|
+
"organizer.progressCount": "\u5DF2\u5904\u7406 {done} / {total}",
|
|
1288
|
+
"organizer.result": "\u6210\u529F {succeeded} \xB7 \u8DF3\u8FC7 {skipped} \xB7 \u5931\u8D25 {failed} \xB7 \u672A\u5904\u7406 {remaining}",
|
|
1289
|
+
"organizer.failureDetails": "\u67E5\u770B\u5931\u8D25\u8BE6\u60C5",
|
|
1290
|
+
"organizer.refreshError": "\u64CD\u4F5C\u7ED3\u679C\u5DF2\u4FDD\u7559\uFF0C\u4F46\u5217\u8868\u5237\u65B0\u5931\u8D25\uFF1A{detail}",
|
|
1291
|
+
"organizer.retry": "\u91CD\u8BD5\u5269\u4F59 {n} \u6761",
|
|
1292
|
+
"organizer.undo": "\u64A4\u56DE\u672C\u6B21\u5F52\u6863\uFF08{n}\uFF09",
|
|
1293
|
+
"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",
|
|
1294
|
+
"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",
|
|
1295
|
+
"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"
|
|
1296
|
+
};
|
|
1297
|
+
var organizerEn = {
|
|
1298
|
+
"organizer.feedback": "Operation feedback",
|
|
1299
|
+
"organizer.allSessions": "All sessions",
|
|
1300
|
+
"organizer.favoriteFilter": "Favorites filter",
|
|
1301
|
+
"organizer.archiveResult": "Archive results",
|
|
1302
|
+
"organizer.restoreResult": "Restore results",
|
|
1303
|
+
"organizer.deleteResult": "Delete results",
|
|
1304
|
+
"organizer.undoResult": "Undo results",
|
|
1305
|
+
"organizer.favorite": "Favorite",
|
|
1306
|
+
"organizer.unfavorite": "Unfavorite",
|
|
1307
|
+
"organizer.favoritesOnly": "Favorites only",
|
|
1308
|
+
"organizer.reloadFavorites": "Reload favorites",
|
|
1309
|
+
"organizer.idleDays": "Idle days",
|
|
1310
|
+
"organizer.preview": "Preview idle archives ({n})",
|
|
1311
|
+
"organizer.rules": "Uses last activity, the current list filters. Excludes favorites, open, running and waiting sessions.",
|
|
1312
|
+
"organizer.progress": "Batch progress",
|
|
1313
|
+
"organizer.progressCount": "Processed {done} / {total}",
|
|
1314
|
+
"organizer.result": "Succeeded {succeeded} \xB7 Skipped {skipped} \xB7 Failed {failed} \xB7 Unprocessed {remaining}",
|
|
1315
|
+
"organizer.failureDetails": "Failure details",
|
|
1316
|
+
"organizer.refreshError": "Results retained, but refresh failed: {detail}",
|
|
1317
|
+
"organizer.retry": "Retry remaining {n}",
|
|
1318
|
+
"organizer.undo": "Undo this archive batch ({n})",
|
|
1319
|
+
"organizer.undoHint": "Only the latest archive batch while this page is open is retained. Closing or refreshing clears undo. Deleted sessions cannot be restored.",
|
|
1320
|
+
"organizer.idleConfirm": "Review and deselect candidates. Favorites and active sessions are checked again before archiving.",
|
|
1321
|
+
"organizer.manualConfirm": "Only checked sessions below will be archived. You can undo this batch afterward."
|
|
1322
|
+
};
|
|
1323
|
+
|
|
426
1324
|
// src/client.js
|
|
427
1325
|
window.__ModuleLoader__.load({
|
|
428
1326
|
id: "@michengai/dsh-archive-manager",
|
|
@@ -440,7 +1338,10 @@
|
|
|
440
1338
|
}
|
|
441
1339
|
let react_jsx_runtime = require2("react/jsx-runtime");
|
|
442
1340
|
let react = require2("react");
|
|
1341
|
+
const OrganizerPanel = createOrganizerPanel(react);
|
|
1342
|
+
const { HighlightedText, useSessionDetails, useArchiveSearch, useArchivePreview, DiscoveryFilters, SearchStatus, PreviewContent } = createDiscoveryTools(react);
|
|
443
1343
|
let _deepseek_ai_dsh_client_ui_primitives = require2("@deepseek-ai/dsh-client-ui-primitives");
|
|
1344
|
+
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 });
|
|
444
1345
|
const UPDATE_ICON_PATHS = {
|
|
445
1346
|
refresh: ["M13.5 5.5V2.5m0 0h-3m3 0-2.1 2.1A5.5 5.5 0 1 0 13.2 12"],
|
|
446
1347
|
download: ["M8 2v8m0 0 3-3m-3 3-3-3M3 13v2h10v-2"],
|
|
@@ -477,7 +1378,7 @@
|
|
|
477
1378
|
parse(value) {
|
|
478
1379
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
479
1380
|
const ids = value.archivedSessionIds;
|
|
480
|
-
if (!Array.isArray(ids) || ids.some((
|
|
1381
|
+
if (!Array.isArray(ids) || ids.some((id2) => typeof id2 !== "string")) throw new TypeError("archivedSessionIds must be a string array");
|
|
481
1382
|
return value;
|
|
482
1383
|
}
|
|
483
1384
|
};
|
|
@@ -492,7 +1393,7 @@
|
|
|
492
1393
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("target must be an object");
|
|
493
1394
|
if (value.scope === "all" || value.scope === "ungrouped") return value;
|
|
494
1395
|
if (value.scope === "workspace" && typeof value.workspaceId === "string" && value.workspaceId.length > 0) return value;
|
|
495
|
-
if (value.scope === "sessions" && Array.isArray(value.sessionIds) && value.sessionIds.length > 0 && value.sessionIds.every((
|
|
1396
|
+
if (value.scope === "sessions" && Array.isArray(value.sessionIds) && value.sessionIds.length > 0 && value.sessionIds.every((id2) => typeof id2 === "string" && id2.length > 0)) return value;
|
|
496
1397
|
throw new TypeError("target.scope must be all, ungrouped, workspace with a non-empty workspaceId, or sessions with non-empty sessionIds");
|
|
497
1398
|
}
|
|
498
1399
|
};
|
|
@@ -500,7 +1401,7 @@
|
|
|
500
1401
|
parse(value) {
|
|
501
1402
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
502
1403
|
for (const key of ["requestedSessionIds", "deletedSessionIds", "skippedSessionIds"]) {
|
|
503
|
-
if (!Array.isArray(value[key]) || value[key].some((
|
|
1404
|
+
if (!Array.isArray(value[key]) || value[key].some((id2) => typeof id2 !== "string")) throw new TypeError(`${key} must be a string array`);
|
|
504
1405
|
}
|
|
505
1406
|
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");
|
|
506
1407
|
return value;
|
|
@@ -510,13 +1411,18 @@
|
|
|
510
1411
|
parse(value) {
|
|
511
1412
|
if (typeof value !== "object" || value === null || Array.isArray(value) || !Array.isArray(value.items)) throw new TypeError("result.items must be an array");
|
|
512
1413
|
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");
|
|
513
|
-
if (value.repairedSessionIds !== void 0 && (!Array.isArray(value.repairedSessionIds) || value.repairedSessionIds.some((
|
|
1414
|
+
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");
|
|
514
1415
|
return value;
|
|
515
1416
|
}
|
|
516
1417
|
};
|
|
1418
|
+
function strictCodec(typeSymbol, schema) {
|
|
1419
|
+
return { mode: "strict", typeSymbol, create: () => schema, schema };
|
|
1420
|
+
}
|
|
517
1421
|
const ARCHIVE_MANAGER_REMOTE = {
|
|
518
1422
|
package: "@michengai/dsh-archive-manager",
|
|
519
1423
|
descriptors: [
|
|
1424
|
+
...favoriteInvocations(),
|
|
1425
|
+
...discoveryInvocations(),
|
|
520
1426
|
{
|
|
521
1427
|
id: "@michengai/dsh-archive-manager#workspaceRegistry/unarchiveSession",
|
|
522
1428
|
service: "workspaceRegistry",
|
|
@@ -527,13 +1433,9 @@
|
|
|
527
1433
|
name: "sessionId",
|
|
528
1434
|
wire: "sessionId",
|
|
529
1435
|
source: "json",
|
|
530
|
-
codec:
|
|
1436
|
+
codec: strictCodec("@deepseek-ai/dsh-session/types#SessionId", sessionIdSchema)
|
|
531
1437
|
}],
|
|
532
|
-
result:
|
|
533
|
-
mode: "strict",
|
|
534
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedSessionIds",
|
|
535
|
-
schema: archivedSetSchema
|
|
536
|
-
},
|
|
1438
|
+
result: strictCodec("@michengai/dsh-archive-manager/types#ArchivedSessionIds", archivedSetSchema),
|
|
537
1439
|
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
538
1440
|
},
|
|
539
1441
|
{
|
|
@@ -546,13 +1448,9 @@
|
|
|
546
1448
|
name: "sessionId",
|
|
547
1449
|
wire: "sessionId",
|
|
548
1450
|
source: "json",
|
|
549
|
-
codec:
|
|
1451
|
+
codec: strictCodec("@deepseek-ai/dsh-session/types#SessionId", sessionIdSchema)
|
|
550
1452
|
}],
|
|
551
|
-
result:
|
|
552
|
-
mode: "strict",
|
|
553
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#Deleted",
|
|
554
|
-
schema: deletedSchema
|
|
555
|
-
},
|
|
1453
|
+
result: strictCodec("@michengai/dsh-archive-manager/types#Deleted", deletedSchema),
|
|
556
1454
|
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
557
1455
|
},
|
|
558
1456
|
{
|
|
@@ -565,13 +1463,9 @@
|
|
|
565
1463
|
name: "target",
|
|
566
1464
|
wire: "target",
|
|
567
1465
|
source: "json",
|
|
568
|
-
codec:
|
|
1466
|
+
codec: strictCodec("@michengai/dsh-archive-manager/types#ArchivedBatchTarget", archivedBatchTargetSchema)
|
|
569
1467
|
}],
|
|
570
|
-
result:
|
|
571
|
-
mode: "strict",
|
|
572
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#DeletedBatch",
|
|
573
|
-
schema: deletedBatchSchema
|
|
574
|
-
},
|
|
1468
|
+
result: strictCodec("@michengai/dsh-archive-manager/types#DeletedBatch", deletedBatchSchema),
|
|
575
1469
|
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
576
1470
|
},
|
|
577
1471
|
{
|
|
@@ -581,11 +1475,7 @@
|
|
|
581
1475
|
method: "archivedSessionMetadata",
|
|
582
1476
|
invocation: { kind: "direct" },
|
|
583
1477
|
parameters: [],
|
|
584
|
-
result:
|
|
585
|
-
mode: "strict",
|
|
586
|
-
typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedSessionMetadata",
|
|
587
|
-
schema: archivedSessionMetadataSchema
|
|
588
|
-
},
|
|
1478
|
+
result: strictCodec("@michengai/dsh-archive-manager/types#ArchivedSessionMetadata", archivedSessionMetadataSchema),
|
|
589
1479
|
sourceLocation: { file: "@michengai/dsh-archive-manager/lib/workspace.js", line: 1, column: 1 }
|
|
590
1480
|
}
|
|
591
1481
|
]
|
|
@@ -690,7 +1580,7 @@
|
|
|
690
1580
|
function GithubMark16() {
|
|
691
1581
|
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" }) });
|
|
692
1582
|
}
|
|
693
|
-
function ArchivedSessionsSection({ archiveSessions, sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, focusSessionWorkspace, viewState, close, t }) {
|
|
1583
|
+
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 }) {
|
|
694
1584
|
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
695
1585
|
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
696
1586
|
const [archiveTab, setArchiveTab] = (0, react.useState)("archived");
|
|
@@ -700,6 +1590,7 @@
|
|
|
700
1590
|
const requestArchive = (ids, group = null) => {
|
|
701
1591
|
setError(null);
|
|
702
1592
|
setNotice(null);
|
|
1593
|
+
setIdleRequest(false);
|
|
703
1594
|
setArchiveGroup(group);
|
|
704
1595
|
setArchiveTarget(ids);
|
|
705
1596
|
};
|
|
@@ -722,6 +1613,91 @@
|
|
|
722
1613
|
const [unarchivingSessionIds, setUnarchivingSessionIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
723
1614
|
const unarchivingSessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
724
1615
|
const [selectedSessionIds, setSelectedSessionIds] = (0, react.useState)([]);
|
|
1616
|
+
const [favoriteIds, setFavoriteIds] = (0, react.useState)([]);
|
|
1617
|
+
const [favoritesReady, setFavoritesReady] = (0, react.useState)(false);
|
|
1618
|
+
const [favoriteBusy, setFavoriteBusy] = (0, react.useState)(false);
|
|
1619
|
+
const favoriteLock = (0, react.useRef)(false);
|
|
1620
|
+
const [favoritesOnly, setFavoritesOnly] = (0, react.useState)(false);
|
|
1621
|
+
const [searchScope, setSearchScope] = react.useState("title");
|
|
1622
|
+
const [dateFrom, setDateFrom] = react.useState("");
|
|
1623
|
+
const [dateTo, setDateTo] = react.useState("");
|
|
1624
|
+
const [collapsedGroups, setCollapsedGroups] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
1625
|
+
const [idleDays, setIdleDays] = (0, react.useState)("30");
|
|
1626
|
+
const [idleRequest, setIdleRequest] = (0, react.useState)(false);
|
|
1627
|
+
const [batchProgress, setBatchProgress] = (0, react.useState)(null);
|
|
1628
|
+
const [batchResult, setBatchResult] = (0, react.useState)(null);
|
|
1629
|
+
const [lastArchive, setLastArchive] = (0, react.useState)([]);
|
|
1630
|
+
const batchLock = (0, react.useRef)(false);
|
|
1631
|
+
const retryBatch = (0, react.useRef)(null);
|
|
1632
|
+
const uiFacts = useSessionUiFacts(useSessionPendingInteraction ?? useEmptySessionPendingInteraction, useSessionStatus ?? useEmptySessionStatus, typeof useSessionStatus === "function");
|
|
1633
|
+
const pendingRef = (0, react.useRef)(uiFacts.pending);
|
|
1634
|
+
pendingRef.current = uiFacts.pending;
|
|
1635
|
+
const favoriteSet = new Set(favoriteIds);
|
|
1636
|
+
const loadFavorites = async () => {
|
|
1637
|
+
if (!favoriteSessions) return;
|
|
1638
|
+
try {
|
|
1639
|
+
const result = await favoriteSessions();
|
|
1640
|
+
setFavoriteIds(result.favoriteSessionIds);
|
|
1641
|
+
setFavoritesReady(true);
|
|
1642
|
+
} catch (reason) {
|
|
1643
|
+
setFavoritesReady(false);
|
|
1644
|
+
setError(String(reason?.message ?? reason));
|
|
1645
|
+
}
|
|
1646
|
+
};
|
|
1647
|
+
(0, react.useEffect)(() => {
|
|
1648
|
+
let active = true;
|
|
1649
|
+
if (favoriteSessions) favoriteSessions().then((value) => {
|
|
1650
|
+
if (active) {
|
|
1651
|
+
setFavoriteIds(value.favoriteSessionIds);
|
|
1652
|
+
setFavoritesReady(true);
|
|
1653
|
+
}
|
|
1654
|
+
}).catch((reason) => {
|
|
1655
|
+
if (active) setError(String(reason?.message ?? reason));
|
|
1656
|
+
});
|
|
1657
|
+
return () => {
|
|
1658
|
+
active = false;
|
|
1659
|
+
};
|
|
1660
|
+
}, [favoriteSessions]);
|
|
1661
|
+
const toggleFavorite = async (sessionId) => {
|
|
1662
|
+
if (favoriteLock.current || busy || !favoritesReady) return;
|
|
1663
|
+
favoriteLock.current = true;
|
|
1664
|
+
setFavoriteBusy(true);
|
|
1665
|
+
setError(null);
|
|
1666
|
+
try {
|
|
1667
|
+
const value = await setSessionFavorite({ sessionId, favorite: !favoriteSet.has(sessionId) });
|
|
1668
|
+
setFavoriteIds(value.favoriteSessionIds);
|
|
1669
|
+
} catch (reason) {
|
|
1670
|
+
setError(String(reason?.message ?? reason));
|
|
1671
|
+
} finally {
|
|
1672
|
+
favoriteLock.current = false;
|
|
1673
|
+
setFavoriteBusy(false);
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
1676
|
+
const executeBatch = async (kind, ids, { idle = false, retry = false } = {}) => {
|
|
1677
|
+
if (batchLock.current || favoriteLock.current || unarchivingSessionIdsRef.current.size > 0 || !organizeBatch) return;
|
|
1678
|
+
batchLock.current = true;
|
|
1679
|
+
setBusy(true);
|
|
1680
|
+
setError(null);
|
|
1681
|
+
setNotice(null);
|
|
1682
|
+
setBatchResult(null);
|
|
1683
|
+
if (kind === "archive" && !retry) setLastArchive([]);
|
|
1684
|
+
try {
|
|
1685
|
+
const result = await organizeBatch(kind, ids, { idleDays: idle ? Number(idleDays) : void 0, getPending: () => pendingRef.current, onProgress: setBatchProgress });
|
|
1686
|
+
setBatchResult({ ...result, kind, tab: archiveTab });
|
|
1687
|
+
retryBatch.current = result.remaining.length ? { kind, ids: result.remaining, idle } : null;
|
|
1688
|
+
if (kind === "archive") setLastArchive((previous) => [.../* @__PURE__ */ new Set([...previous, ...result.succeeded])]);
|
|
1689
|
+
if (kind === "undo" || kind === "restore" || kind === "delete") setLastArchive((previous) => previous.filter((id2) => !result.succeeded.includes(id2) && !result.skipped.includes(id2)));
|
|
1690
|
+
setSelectedSessionIds((previous) => previous.filter((id2) => !result.succeeded.includes(id2) && !result.skipped.includes(id2)));
|
|
1691
|
+
if (kind === "delete") setFavoriteIds((previous) => previous.filter((id2) => !result.succeeded.includes(id2)));
|
|
1692
|
+
return result;
|
|
1693
|
+
} catch (reason) {
|
|
1694
|
+
setError(String(reason?.message ?? reason));
|
|
1695
|
+
} finally {
|
|
1696
|
+
batchLock.current = false;
|
|
1697
|
+
setBusy(false);
|
|
1698
|
+
setBatchProgress(null);
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
725
1701
|
const navigationActive = (0, react.useRef)(true);
|
|
726
1702
|
const navigationPending = (0, react.useRef)(false);
|
|
727
1703
|
(0, react.useEffect)(() => {
|
|
@@ -738,15 +1714,15 @@
|
|
|
738
1714
|
let restored = false;
|
|
739
1715
|
try {
|
|
740
1716
|
await openArchivedConversation({
|
|
741
|
-
prepare: restore ? async (
|
|
742
|
-
await focusSessionWorkspace?.(
|
|
1717
|
+
prepare: restore ? async (id2) => {
|
|
1718
|
+
await focusSessionWorkspace?.(id2);
|
|
743
1719
|
} : void 0,
|
|
744
|
-
restore: async (
|
|
745
|
-
await unarchiveSession(
|
|
1720
|
+
restore: async (id2) => {
|
|
1721
|
+
await unarchiveSession(id2);
|
|
746
1722
|
restored = true;
|
|
747
1723
|
},
|
|
748
|
-
open: async (
|
|
749
|
-
await openConversation(
|
|
1724
|
+
open: async (id2) => {
|
|
1725
|
+
await openConversation(id2);
|
|
750
1726
|
if (navigationActive.current) close?.();
|
|
751
1727
|
}
|
|
752
1728
|
}, session.id, restore, () => navigationActive.current);
|
|
@@ -770,6 +1746,7 @@
|
|
|
770
1746
|
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, eligibleIds, t("group.ungrouped")), [sessions.byId, workspaceState, eligibleIds, t]);
|
|
771
1747
|
const switchTab = (tab) => {
|
|
772
1748
|
if (busy || unarchivingSessionIdsRef.current.size > 0) return;
|
|
1749
|
+
preview.close();
|
|
773
1750
|
setArchiveTab(tab);
|
|
774
1751
|
setSelectedSessionIds([]);
|
|
775
1752
|
setArchiveTarget(null);
|
|
@@ -778,10 +1755,23 @@
|
|
|
778
1755
|
setNotice(null);
|
|
779
1756
|
setProject("all");
|
|
780
1757
|
setQuery("");
|
|
781
|
-
if (tab === "unarchived" && sortBy === "created") setSortBy("updated");
|
|
782
1758
|
};
|
|
783
1759
|
const confirmArchive = async () => {
|
|
784
1760
|
if (archiveBusy.current || busy || !archiveTarget?.length) return;
|
|
1761
|
+
if (organizeBatch) {
|
|
1762
|
+
archiveBusy.current = true;
|
|
1763
|
+
try {
|
|
1764
|
+
const result = await executeBatch("archive", archiveTarget, { idle: idleRequest });
|
|
1765
|
+
if (result) {
|
|
1766
|
+
setArchiveTarget(null);
|
|
1767
|
+
setArchiveGroup(null);
|
|
1768
|
+
setIdleRequest(false);
|
|
1769
|
+
}
|
|
1770
|
+
} finally {
|
|
1771
|
+
archiveBusy.current = false;
|
|
1772
|
+
}
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
785
1775
|
archiveBusy.current = true;
|
|
786
1776
|
setBusy(true);
|
|
787
1777
|
setError(null);
|
|
@@ -802,7 +1792,25 @@
|
|
|
802
1792
|
setBusy(false);
|
|
803
1793
|
}
|
|
804
1794
|
};
|
|
805
|
-
const
|
|
1795
|
+
const details = useSessionDetails(sessionDetailCandidates(eligibleIds, sessions.byId), sessionDetails, t);
|
|
1796
|
+
const copyDetail = async (session, kind) => {
|
|
1797
|
+
setError(null);
|
|
1798
|
+
setNotice(null);
|
|
1799
|
+
try {
|
|
1800
|
+
let text = session.id;
|
|
1801
|
+
if (kind === "path") {
|
|
1802
|
+
let row = details.byId[session.id];
|
|
1803
|
+
if (!row) row = (await sessionDetails({ sessionIds: [session.id] })).items[0];
|
|
1804
|
+
if (!row?.path) throw new Error(t("details.noPath"));
|
|
1805
|
+
text = row.path;
|
|
1806
|
+
}
|
|
1807
|
+
await copySessionText(text);
|
|
1808
|
+
if (navigationActive.current) setNotice(t("details.copied"));
|
|
1809
|
+
} catch (reason) {
|
|
1810
|
+
if (navigationActive.current) setError(reason?.code?.startsWith("copy.") ? t(reason.code) : String(reason?.message ?? reason));
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
const sortedGroups = (0, react.useMemo)(() => sortArchivedGroups(groups, sortBy, createdAtById, t, details.byId), [groups, sortBy, createdAtById, t, details.byId]);
|
|
806
1814
|
(0, react.useEffect)(() => {
|
|
807
1815
|
let cancelled = false;
|
|
808
1816
|
archivedSessionMetadata().then((result) => {
|
|
@@ -817,19 +1825,19 @@
|
|
|
817
1825
|
(0, react.useEffect)(() => {
|
|
818
1826
|
if (project !== "all" && !groups.some((group) => group.key === project)) setProject("all");
|
|
819
1827
|
}, [groups, project]);
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1828
|
+
const invalidDate = !validUpdatedRange(dateFrom, dateTo);
|
|
1829
|
+
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);
|
|
1830
|
+
const contentEnabled = searchScope === "content" && !invalidDate;
|
|
1831
|
+
const contentSearch = useArchiveSearch(candidateGroups.flatMap((group) => group.sessions.map((session) => session.id)), query, contentEnabled, searchSessionContent ?? searchArchivedContent);
|
|
1832
|
+
const contentMatches = new Map(contentSearch.items.map((item) => [item.sessionId, item]));
|
|
1833
|
+
const preview = useArchivePreview(previewArchivedSession, isArchived ? workspaceState.archivedSessionIds : []);
|
|
1834
|
+
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
1835
|
+
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);
|
|
1836
|
+
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) : [];
|
|
827
1837
|
const visibleSessionIds = (0, react.useMemo)(() => archivedSessionIdsInGroups(filteredGroups), [filteredGroups]);
|
|
828
1838
|
const selectedSessionIdSet = (0, react.useMemo)(() => new Set(selectedSessionIds), [selectedSessionIds]);
|
|
829
1839
|
const selectedVisibleCount = visibleSessionIds.filter((sessionId) => selectedSessionIdSet.has(sessionId)).length;
|
|
830
1840
|
const allVisibleSelected = visibleSessionIds.length > 0 && selectedVisibleCount === visibleSessionIds.length;
|
|
831
|
-
const allBatchTarget = { scope: "all" };
|
|
832
|
-
const allBatchSessionIds = (0, react.useMemo)(() => deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, allBatchTarget), [workspaceState.archivedSessionIds, workspaceState.items]);
|
|
833
1841
|
(0, react.useEffect)(() => {
|
|
834
1842
|
setSelectedSessionIds((current) => pruneArchivedSelection(current, eligibleIds));
|
|
835
1843
|
}, [eligibleIds]);
|
|
@@ -854,6 +1862,11 @@
|
|
|
854
1862
|
};
|
|
855
1863
|
const onBatchUnarchive = async (target) => {
|
|
856
1864
|
if (busy) return;
|
|
1865
|
+
if (organizeBatch) {
|
|
1866
|
+
const ids = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target);
|
|
1867
|
+
const result = await executeBatch("restore", ids);
|
|
1868
|
+
return result && { unarchivedSessionIds: result.succeeded };
|
|
1869
|
+
}
|
|
857
1870
|
setBusy(true);
|
|
858
1871
|
setError(null);
|
|
859
1872
|
setNotice(null);
|
|
@@ -892,6 +1905,12 @@
|
|
|
892
1905
|
}, [deleteTarget, busy]);
|
|
893
1906
|
const confirmDelete = async () => {
|
|
894
1907
|
if (busy || deleteTarget === null) return;
|
|
1908
|
+
if (organizeBatch && deleteTarget.kind === "batch") {
|
|
1909
|
+
const ids = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, deleteTarget.target);
|
|
1910
|
+
const result = await executeBatch("delete", ids);
|
|
1911
|
+
if (result) setDeleteTarget(null);
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
895
1914
|
setBusy(true);
|
|
896
1915
|
setError(null);
|
|
897
1916
|
setNotice(null);
|
|
@@ -916,9 +1935,9 @@
|
|
|
916
1935
|
}
|
|
917
1936
|
};
|
|
918
1937
|
const batchScope = deleteTarget?.kind === "batch" ? deleteTarget.target.scope : null;
|
|
919
|
-
const deleteDialogTitle = batchScope === "
|
|
920
|
-
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "
|
|
921
|
-
const deleteConfirmLabel = batchScope === "
|
|
1938
|
+
const deleteDialogTitle = batchScope === "ungrouped" ? t("archives.deleteUngroupedTitle") : batchScope === "workspace" ? t("archives.deleteProjectTitle", { name: deleteTarget.title }) : batchScope === "sessions" ? t("archives.deleteSelectedTitle") : t("deleteSession.title");
|
|
1939
|
+
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "ungrouped" ? t("archives.deleteUngroupedDesc", { n: deleteTarget.count }) : batchScope === "workspace" ? t("archives.deleteProjectDesc", { name: deleteTarget.title, n: deleteTarget.count }) : batchScope === "sessions" ? t("archives.deleteSelectedDesc", { n: deleteTarget.count }) : t("deleteSession.desc", { name: displayTitle(deleteTarget.session, t) });
|
|
1940
|
+
const deleteConfirmLabel = batchScope === "ungrouped" ? t("archives.deleteUngroupedConfirm") : batchScope === "workspace" ? t("archives.deleteProjectConfirm") : batchScope === "sessions" ? t("archives.deleteSelectedConfirm") : t("deleteSession.title");
|
|
922
1941
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
923
1942
|
className: "dsham_settings",
|
|
924
1943
|
"aria-label": t("archives.title"),
|
|
@@ -951,16 +1970,40 @@
|
|
|
951
1970
|
},
|
|
952
1971
|
children: t("archives.tab." + tab)
|
|
953
1972
|
}, tab))
|
|
954
|
-
}), isArchived && (0, react_jsx_runtime.jsxs)("div", {
|
|
955
|
-
className: "dsham_settingsHeaderActions",
|
|
956
|
-
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")] })]
|
|
957
1973
|
})]
|
|
958
1974
|
}), (0, react_jsx_runtime.jsxs)("div", { id: "dsham-archive-panel", role: "tabpanel", "aria-labelledby": "dsham-tab-" + archiveTab, children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
959
1975
|
className: "dsham_settingsToolbar",
|
|
960
|
-
children: [(0, react_jsx_runtime.jsxs)("
|
|
1976
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
961
1977
|
className: "dsham_settingsSearch",
|
|
962
|
-
children: [(
|
|
963
|
-
|
|
1978
|
+
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: () => {
|
|
1979
|
+
setDateFrom("");
|
|
1980
|
+
setDateTo("");
|
|
1981
|
+
} })]
|
|
1982
|
+
}), (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") }, ...sessionDetails ? [{ 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") }), setSessionFavorite && (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") })]
|
|
1983
|
+
}), 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, {
|
|
1984
|
+
t,
|
|
1985
|
+
archived: isArchived,
|
|
1986
|
+
busy: busy || favoriteBusy || unarchivingSessionIds.size > 0,
|
|
1987
|
+
ready: favoritesReady,
|
|
1988
|
+
days: idleDays,
|
|
1989
|
+
onDays: setIdleDays,
|
|
1990
|
+
count: idleCandidates.length,
|
|
1991
|
+
onPreview: () => {
|
|
1992
|
+
requestArchive(idleCandidates);
|
|
1993
|
+
setIdleRequest(true);
|
|
1994
|
+
},
|
|
1995
|
+
progress: batchProgress,
|
|
1996
|
+
result: batchResult?.tab === archiveTab ? batchResult : null,
|
|
1997
|
+
onRetry: () => {
|
|
1998
|
+
const retry = retryBatch.current;
|
|
1999
|
+
if (retry) {
|
|
2000
|
+
if (retry.kind === "delete") setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: retry.ids }, count: retry.ids.length });
|
|
2001
|
+
else executeBatch(retry.kind, retry.ids, { idle: retry.idle, retry: true });
|
|
2002
|
+
}
|
|
2003
|
+
},
|
|
2004
|
+
undoCount: lastArchive.filter((id2) => workspaceState.archivedSessionIds.includes(id2)).length,
|
|
2005
|
+
onUndo: () => executeBatch("undo", lastArchive, { retry: true }),
|
|
2006
|
+
onReload: loadFavorites
|
|
964
2007
|
}), groups.length > 0 && (0, react_jsx_runtime.jsx)(ArchiveSelectionToolbar, {
|
|
965
2008
|
selectedCount: selectedSessionIds.length,
|
|
966
2009
|
hiddenCount: selectedSessionIds.length - selectedVisibleCount,
|
|
@@ -974,7 +2017,7 @@
|
|
|
974
2017
|
onArchive: isArchived ? void 0 : () => requestArchive([...selectedSessionIds]),
|
|
975
2018
|
onRestore: onSelectedUnarchive,
|
|
976
2019
|
onDelete: () => setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: selectedSessionIds }, count: selectedSessionIds.length })
|
|
977
|
-
}), 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) => {
|
|
2020
|
+
}), 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) => {
|
|
978
2021
|
const target = archivedBatchTargetForGroup(group.key);
|
|
979
2022
|
const groupSessionIds = groups.find((item) => item.key === group.key)?.sessions.map((session) => session.id) ?? [];
|
|
980
2023
|
const count = isArchived ? deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length : groupSessionIds.length;
|
|
@@ -982,18 +2025,50 @@
|
|
|
982
2025
|
className: "dsham_settingsGroup",
|
|
983
2026
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
984
2027
|
className: "dsham_settingsGroupHeading",
|
|
985
|
-
children: [(0, react_jsx_runtime.
|
|
2028
|
+
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) => {
|
|
2029
|
+
const next = new Set(previous);
|
|
2030
|
+
if (next.has(group.key)) next.delete(group.key);
|
|
2031
|
+
else next.add(group.key);
|
|
2032
|
+
return next;
|
|
2033
|
+
}), 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 })] })]
|
|
986
2034
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
987
2035
|
className: "dsham_settingsList",
|
|
988
|
-
|
|
2036
|
+
id: "dsham-group-" + encodeURIComponent(group.key),
|
|
2037
|
+
hidden: collapsedGroups.has(group.key),
|
|
2038
|
+
children: !collapsedGroups.has(group.key) && group.sessions.map((session) => (0, react_jsx_runtime.jsxs)("article", {
|
|
989
2039
|
className: "dsham_settingsRow",
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
2040
|
+
"data-selected": selectedSessionIdSet.has(session.id),
|
|
2041
|
+
children: [
|
|
2042
|
+
(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) }),
|
|
2043
|
+
(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsContent", children: [
|
|
2044
|
+
(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) }),
|
|
2045
|
+
(0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsMeta", children: [archiveTimeLabel(session.updatedAt, t), sessionDetails && 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 }))] }),
|
|
2046
|
+
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 }))
|
|
2047
|
+
] }),
|
|
2048
|
+
(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsActions", children: [
|
|
2049
|
+
setSessionFavorite && (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" }) }),
|
|
2050
|
+
(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 }) }),
|
|
2051
|
+
(isArchived || sessionDetails) && (0, react_jsx_runtime.jsx)(ArchivedSessionMenu, { busy: busy || unarchivingSessionIds.has(session.id), t, title: displayTitle(session, t), onCopyId: () => copyDetail(session, "id"), onCopyPath: sessionDetails ? () => copyDetail(session, "path") : void 0, onPreview: isArchived && previewArchivedSession ? () => preview.open(session, query) : void 0, onRestoreOpen: isArchived ? () => viewConversation(session, true) : void 0, onDelete: isArchived ? () => setDeleteTarget({ kind: "session", session }) : void 0 })
|
|
2052
|
+
] })
|
|
2053
|
+
]
|
|
994
2054
|
}, session.id))
|
|
995
2055
|
})]
|
|
996
2056
|
}, group.key);
|
|
2057
|
+
}), react.createElement(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2058
|
+
className: "dsham_previewDialog",
|
|
2059
|
+
contentClassName: "dsham_previewDialogContent",
|
|
2060
|
+
open: preview.target !== null,
|
|
2061
|
+
onClose: preview.close,
|
|
2062
|
+
closeLabel: t("close"),
|
|
2063
|
+
title: preview.target ? displayTitle(preview.target.session, t) : t("discovery.preview"),
|
|
2064
|
+
footer: react.createElement(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: () => {
|
|
2065
|
+
if (preview.target) {
|
|
2066
|
+
const session = preview.target.session;
|
|
2067
|
+
preview.close();
|
|
2068
|
+
return viewConversation(session);
|
|
2069
|
+
}
|
|
2070
|
+
} }, t("discovery.openFull")),
|
|
2071
|
+
children: react.createElement(PreviewContent, { preview, t, MarkdownText: _deepseek_ai_dsh_client_ui_primitives.MarkdownText })
|
|
997
2072
|
}), 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, {
|
|
998
2073
|
open: archiveTarget !== null,
|
|
999
2074
|
onClose: closeArchive,
|
|
@@ -1002,9 +2077,14 @@
|
|
|
1002
2077
|
description: archiveGroup === null ? t("archives.archiveSelectedDesc") : t(archiveGroup.key === ARCHIVE_UNGROUPED_KEY ? "archives.archiveUngroupedDesc" : "archives.archiveProjectDesc", { name: archiveGroup.title, n: archiveTarget?.length ?? 0 }),
|
|
1003
2078
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1004
2079
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeArchive, children: t("cancel") }),
|
|
1005
|
-
(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") })
|
|
2080
|
+
(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") })
|
|
1006
2081
|
] }),
|
|
1007
|
-
children:
|
|
2082
|
+
children: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2083
|
+
organizeBatch && (0, react_jsx_runtime.jsx)("p", { children: t(idleRequest ? "organizer.idleConfirm" : "organizer.manualConfirm") }),
|
|
2084
|
+
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)) }),
|
|
2085
|
+
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 })] }),
|
|
2086
|
+
error !== null && (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsError", role: "alert", children: error })
|
|
2087
|
+
] })
|
|
1008
2088
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1009
2089
|
open: deleteTarget !== null,
|
|
1010
2090
|
onClose: closeDelete,
|
|
@@ -1012,7 +2092,7 @@
|
|
|
1012
2092
|
title: deleteDialogTitle,
|
|
1013
2093
|
...deleteDialogDescription === void 0 ? {} : { description: deleteDialogDescription },
|
|
1014
2094
|
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 })] }),
|
|
1015
|
-
children: busy && (0, react_jsx_runtime.
|
|
2095
|
+
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 })] })
|
|
1016
2096
|
})] })]
|
|
1017
2097
|
});
|
|
1018
2098
|
}
|
|
@@ -1101,16 +2181,16 @@
|
|
|
1101
2181
|
const accounted = /* @__PURE__ */ new Set();
|
|
1102
2182
|
for (const workspace of workspaces) {
|
|
1103
2183
|
const members = [];
|
|
1104
|
-
for (const
|
|
1105
|
-
const summary = list.byId[
|
|
2184
|
+
for (const id2 of workspace.sessionIds) {
|
|
2185
|
+
const summary = list.byId[id2];
|
|
1106
2186
|
if (summary === void 0) continue;
|
|
1107
|
-
accounted.add(
|
|
1108
|
-
if (!sessionVisible(summary, list
|
|
2187
|
+
accounted.add(id2);
|
|
2188
|
+
if (!sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1109
2189
|
members.push(summary);
|
|
1110
2190
|
}
|
|
1111
2191
|
groups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members, "account"));
|
|
1112
2192
|
}
|
|
1113
|
-
const stray = list.ids.map((
|
|
2193
|
+
const stray = list.ids.map((id2) => list.byId[id2]).filter((s) => s !== void 0 && !accounted.has(s.id) && sessionVisible(s, currentSessionId(list), archived, showArchived));
|
|
1114
2194
|
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"));
|
|
1115
2195
|
return groups;
|
|
1116
2196
|
}
|
|
@@ -1143,18 +2223,49 @@
|
|
|
1143
2223
|
return visiblePendingKind(kind);
|
|
1144
2224
|
}
|
|
1145
2225
|
const EMPTY_PENDING_INTERACTIONS = /* @__PURE__ */ new Map();
|
|
2226
|
+
const EMPTY_COMPLETED_SESSIONS = /* @__PURE__ */ new Set();
|
|
2227
|
+
const EMPTY_SESSION_STATUS = /* @__PURE__ */ new Map();
|
|
1146
2228
|
function useEmptySessionPendingInteraction(selector) {
|
|
1147
2229
|
return selector(EMPTY_PENDING_INTERACTIONS);
|
|
1148
2230
|
}
|
|
2231
|
+
function useEmptySessionStatus(selector) {
|
|
2232
|
+
return selector(EMPTY_SESSION_STATUS);
|
|
2233
|
+
}
|
|
2234
|
+
function pendingFacts(pendingInteractions) {
|
|
2235
|
+
if (pendingInteractions instanceof Map || pendingInteractions == null) {
|
|
2236
|
+
return { pending: pendingInteractions ?? EMPTY_PENDING_INTERACTIONS, completed: EMPTY_COMPLETED_SESSIONS };
|
|
2237
|
+
}
|
|
2238
|
+
return {
|
|
2239
|
+
pending: pendingInteractions.pending ?? EMPTY_PENDING_INTERACTIONS,
|
|
2240
|
+
completed: pendingInteractions.completed ?? EMPTY_COMPLETED_SESSIONS
|
|
2241
|
+
};
|
|
2242
|
+
}
|
|
2243
|
+
function factsFromSessionStatus(status) {
|
|
2244
|
+
const pending = /* @__PURE__ */ new Map();
|
|
2245
|
+
const completed = /* @__PURE__ */ new Set();
|
|
2246
|
+
if (status instanceof Map) {
|
|
2247
|
+
for (const [id2, entry] of status) {
|
|
2248
|
+
if (entry?.pendingInteraction !== void 0) pending.set(id2, entry.pendingInteraction);
|
|
2249
|
+
if (entry?.completionUnread === true) completed.add(id2);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
return { pending, completed };
|
|
2253
|
+
}
|
|
2254
|
+
function useSessionUiFacts(usePending, useStatus, preferStatus) {
|
|
2255
|
+
const pending = usePending((s) => s);
|
|
2256
|
+
const status = useStatus((s) => s);
|
|
2257
|
+
return preferStatus ? factsFromSessionStatus(status) : { pending, completed: EMPTY_COMPLETED_SESSIONS };
|
|
2258
|
+
}
|
|
1149
2259
|
function sessionNode(s, descendants, archived, pendingInteractions) {
|
|
1150
|
-
const
|
|
2260
|
+
const facts = pendingFacts(pendingInteractions);
|
|
2261
|
+
const pendingInteraction = pendingInteractionForSession(s, facts.pending);
|
|
1151
2262
|
return {
|
|
1152
2263
|
id: s.id,
|
|
1153
2264
|
title: sessionTitle(s),
|
|
1154
2265
|
blank: s.blank,
|
|
1155
2266
|
running: s.running,
|
|
1156
2267
|
runningSubagentCount: descendants.get(s.id)?.runningCount ?? 0,
|
|
1157
|
-
completed: s.completed === true,
|
|
2268
|
+
completed: s.completed === true || facts.completed.has(s.id),
|
|
1158
2269
|
updatedAt: s.updatedAt,
|
|
1159
2270
|
archived: archived.has(s.id),
|
|
1160
2271
|
...pendingInteraction === void 0 ? {} : { pendingInteraction }
|
|
@@ -1164,7 +2275,8 @@
|
|
|
1164
2275
|
const archived = new Set(archivedSessionIds);
|
|
1165
2276
|
const expandedGroups = new Set(view.expandedGroups);
|
|
1166
2277
|
const descendants = indexSubagentDescendants(list.byId);
|
|
1167
|
-
const
|
|
2278
|
+
const current = currentSessionId(list);
|
|
2279
|
+
const currentGroup = current === void 0 ? void 0 : workspaces.find((w) => w.sessionIds.includes(current))?.workspaceId ?? "";
|
|
1168
2280
|
const groups = [];
|
|
1169
2281
|
for (const g of groupByWorkspace(list, workspaces, archived, view.ungroupedOrder, view.showArchived)) {
|
|
1170
2282
|
const expanded = expandedGroups.has(g.key);
|
|
@@ -1186,9 +2298,9 @@
|
|
|
1186
2298
|
const archived = new Set(archivedSessionIds);
|
|
1187
2299
|
const descendants = indexSubagentDescendants(list.byId);
|
|
1188
2300
|
const rows = [];
|
|
1189
|
-
for (const
|
|
1190
|
-
const s = list.byId[
|
|
1191
|
-
if (s === void 0 || !sessionVisible(s, list
|
|
2301
|
+
for (const id2 of list.ids) {
|
|
2302
|
+
const s = list.byId[id2];
|
|
2303
|
+
if (s === void 0 || !sessionVisible(s, currentSessionId(list), archived, showArchived)) continue;
|
|
1192
2304
|
rows.push(s);
|
|
1193
2305
|
}
|
|
1194
2306
|
rows.sort(byRecency);
|
|
@@ -1208,9 +2320,9 @@
|
|
|
1208
2320
|
const contentBySession = /* @__PURE__ */ new Map();
|
|
1209
2321
|
for (const item of content.items) if (!contentBySession.has(item.sessionId)) contentBySession.set(item.sessionId, item);
|
|
1210
2322
|
const local = [];
|
|
1211
|
-
for (const
|
|
1212
|
-
const summary = list.byId[
|
|
1213
|
-
if (summary === void 0 || summary.blank || !sessionVisible(summary, list
|
|
2323
|
+
for (const id2 of list.ids) {
|
|
2324
|
+
const summary = list.byId[id2];
|
|
2325
|
+
if (summary === void 0 || summary.blank || !sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1214
2326
|
if (sessionTitle(summary).toLowerCase().includes(q) || labelOf(summary).toLowerCase().includes(q)) local.push(summary);
|
|
1215
2327
|
}
|
|
1216
2328
|
local.sort(byRecency);
|
|
@@ -1224,12 +2336,13 @@
|
|
|
1224
2336
|
for (const summary of local) include(summary);
|
|
1225
2337
|
for (const item of content.items) {
|
|
1226
2338
|
const summary = list.byId[item.sessionId];
|
|
1227
|
-
if (summary !== void 0 && !summary.blank && sessionVisible(summary, list
|
|
2339
|
+
if (summary !== void 0 && !summary.blank && sessionVisible(summary, currentSessionId(list), archived, showArchived)) include(summary);
|
|
1228
2340
|
}
|
|
2341
|
+
const facts = pendingFacts(pendingInteractions);
|
|
1229
2342
|
return {
|
|
1230
2343
|
items: ordered.slice(0, limit).map((summary) => {
|
|
1231
2344
|
const match = contentBySession.get(summary.id);
|
|
1232
|
-
const pendingInteraction = pendingInteractionForSession(summary,
|
|
2345
|
+
const pendingInteraction = pendingInteractionForSession(summary, facts.pending);
|
|
1233
2346
|
return {
|
|
1234
2347
|
id: summary.id,
|
|
1235
2348
|
title: sessionTitle(summary),
|
|
@@ -1238,7 +2351,7 @@
|
|
|
1238
2351
|
runningSubagentCount: descendants.get(summary.id)?.runningCount ?? 0,
|
|
1239
2352
|
archived: archived.has(summary.id),
|
|
1240
2353
|
...pendingInteraction === void 0 ? {} : { pendingInteraction },
|
|
1241
|
-
completed: summary.completed === true,
|
|
2354
|
+
completed: summary.completed === true || facts.completed.has(summary.id),
|
|
1242
2355
|
...match === void 0 ? {} : { snippet: match.snippet }
|
|
1243
2356
|
};
|
|
1244
2357
|
}),
|
|
@@ -1423,11 +2536,11 @@
|
|
|
1423
2536
|
setMenuOpen(false);
|
|
1424
2537
|
},
|
|
1425
2538
|
items: workspaceMenuItems,
|
|
1426
|
-
onSelect: (
|
|
2539
|
+
onSelect: (id2) => {
|
|
1427
2540
|
setMenuOpen(false);
|
|
1428
|
-
if (
|
|
1429
|
-
if (
|
|
1430
|
-
else if (
|
|
2541
|
+
if (id2 !== "rename" && id2 !== "archive-workspace" && id2 !== "delete") return;
|
|
2542
|
+
if (id2 === "rename") actions.rename();
|
|
2543
|
+
else if (id2 === "archive-workspace") actions.archive();
|
|
1431
2544
|
else actions.delete();
|
|
1432
2545
|
},
|
|
1433
2546
|
portal: true,
|
|
@@ -1713,13 +2826,13 @@
|
|
|
1713
2826
|
setMenuOpen(false);
|
|
1714
2827
|
},
|
|
1715
2828
|
items: sessionMenuItems,
|
|
1716
|
-
onSelect: (
|
|
2829
|
+
onSelect: (id2) => {
|
|
1717
2830
|
setMenuOpen(false);
|
|
1718
|
-
if (
|
|
1719
|
-
if (
|
|
1720
|
-
if (
|
|
1721
|
-
if (
|
|
1722
|
-
if (
|
|
2831
|
+
if (id2 === "rename") onRename(node.id, row.title);
|
|
2832
|
+
if (id2 === "fork") onFork(node.id);
|
|
2833
|
+
if (id2 === "archive") onArchive(node.id);
|
|
2834
|
+
if (id2 === "unarchive") onUnarchive(node.id);
|
|
2835
|
+
if (id2 === "delete-session") onDeleteSession(node.id, row.title);
|
|
1723
2836
|
},
|
|
1724
2837
|
portal: true,
|
|
1725
2838
|
closeOnPointerLeave: true,
|
|
@@ -1836,12 +2949,12 @@
|
|
|
1836
2949
|
setErrorOpen(true);
|
|
1837
2950
|
}
|
|
1838
2951
|
};
|
|
1839
|
-
const handleSelect = (
|
|
1840
|
-
if (
|
|
2952
|
+
const handleSelect = (id2) => {
|
|
2953
|
+
if (id2 === ADD_WORKSPACE) {
|
|
1841
2954
|
openDirectoryFlow();
|
|
1842
2955
|
return;
|
|
1843
2956
|
}
|
|
1844
|
-
onPick(
|
|
2957
|
+
onPick(id2);
|
|
1845
2958
|
};
|
|
1846
2959
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1847
2960
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
@@ -1970,18 +3083,18 @@
|
|
|
1970
3083
|
}
|
|
1971
3084
|
function reconciledSessionOrder(sessionIds, stored) {
|
|
1972
3085
|
if (stored === void 0) return [...sessionIds];
|
|
1973
|
-
const byId = new Map(sessionIds.map((
|
|
3086
|
+
const byId = new Map(sessionIds.map((id2) => [id2, id2]));
|
|
1974
3087
|
const ordered = [];
|
|
1975
3088
|
const included = /* @__PURE__ */ new Set();
|
|
1976
3089
|
for (const key of stored) {
|
|
1977
|
-
const
|
|
1978
|
-
if (
|
|
1979
|
-
ordered.push(
|
|
3090
|
+
const id2 = byId.get(key);
|
|
3091
|
+
if (id2 === void 0 || included.has(key)) continue;
|
|
3092
|
+
ordered.push(id2);
|
|
1980
3093
|
included.add(key);
|
|
1981
3094
|
}
|
|
1982
|
-
for (const
|
|
1983
|
-
if (included.has(
|
|
1984
|
-
ordered.push(
|
|
3095
|
+
for (const id2 of sessionIds) {
|
|
3096
|
+
if (included.has(id2)) continue;
|
|
3097
|
+
ordered.push(id2);
|
|
1985
3098
|
}
|
|
1986
3099
|
return ordered;
|
|
1987
3100
|
}
|
|
@@ -1995,22 +3108,22 @@
|
|
|
1995
3108
|
let order = reconciledSessionOrder(sessionIds, previousOrder);
|
|
1996
3109
|
if (sortByRecency) order.sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
1997
3110
|
else if (orderBy === "updated") {
|
|
1998
|
-
const promoted = sessionIds.filter((
|
|
1999
|
-
const session = list.byId[
|
|
2000
|
-
return session !== void 0 && (previousUpdatedAt[
|
|
3111
|
+
const promoted = sessionIds.filter((id2) => {
|
|
3112
|
+
const session = list.byId[id2];
|
|
3113
|
+
return session !== void 0 && (previousUpdatedAt[id2] === void 0 || session.updatedAt > previousUpdatedAt[id2]);
|
|
2001
3114
|
}).sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
2002
3115
|
if (promoted.length > 0) {
|
|
2003
3116
|
const promotedIds = new Set(promoted);
|
|
2004
|
-
order = [...promoted, ...order.filter((
|
|
3117
|
+
order = [...promoted, ...order.filter((id2) => !promotedIds.has(id2))];
|
|
2005
3118
|
}
|
|
2006
3119
|
}
|
|
2007
3120
|
const updatedAt = {};
|
|
2008
|
-
for (const
|
|
2009
|
-
const session = list.byId[
|
|
2010
|
-
if (session !== void 0) updatedAt[
|
|
3121
|
+
for (const id2 of sessionIds) {
|
|
3122
|
+
const session = list.byId[id2];
|
|
3123
|
+
if (session !== void 0) updatedAt[id2] = session.updatedAt;
|
|
2011
3124
|
}
|
|
2012
|
-
const orderChanged = previousOrder === void 0 || order.length !== previousOrder.length || order.some((
|
|
2013
|
-
const timestampsChanged = Object.keys(updatedAt).length !== Object.keys(previousUpdatedAt).length || Object.entries(updatedAt).some(([
|
|
3125
|
+
const orderChanged = previousOrder === void 0 || order.length !== previousOrder.length || order.some((id2, index) => id2 !== previousOrder[index]);
|
|
3126
|
+
const timestampsChanged = Object.keys(updatedAt).length !== Object.keys(previousUpdatedAt).length || Object.entries(updatedAt).some(([id2, timestamp]) => previousUpdatedAt[id2] !== timestamp);
|
|
2014
3127
|
return {
|
|
2015
3128
|
order,
|
|
2016
3129
|
updatedAt,
|
|
@@ -2057,9 +3170,9 @@
|
|
|
2057
3170
|
}
|
|
2058
3171
|
],
|
|
2059
3172
|
selectedIds: [groupBy, orderBy],
|
|
2060
|
-
onSelect: (
|
|
2061
|
-
if (
|
|
2062
|
-
else if (
|
|
3173
|
+
onSelect: (id2) => {
|
|
3174
|
+
if (id2 === "workspace" || id2 === "flat") onGroupPick(id2);
|
|
3175
|
+
else if (id2 === "manual" || id2 === "updated") onOrderPick(id2);
|
|
2063
3176
|
setOpen(false);
|
|
2064
3177
|
},
|
|
2065
3178
|
align: "end",
|
|
@@ -2085,10 +3198,10 @@
|
|
|
2085
3198
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
2086
3199
|
return e.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
2087
3200
|
}
|
|
2088
|
-
function SessionTree({ useSessions, useSessionPendingInteraction, 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 }) {
|
|
3201
|
+
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 }) {
|
|
2089
3202
|
const list = useSessions((s) => s);
|
|
2090
|
-
const pendingInteractions = useSessionPendingInteraction
|
|
2091
|
-
const current = list
|
|
3203
|
+
const pendingInteractions = useSessionUiFacts(useSessionPendingInteraction, useSessionStatus, preferSessionStatus);
|
|
3204
|
+
const current = currentSessionId(list);
|
|
2092
3205
|
const [expandedSessionGroups, setExpandedSessionGroups] = (0, react.useState)([]);
|
|
2093
3206
|
const [drag, setDrag] = (0, react.useState)(null);
|
|
2094
3207
|
const sessionDropCommitted = (0, react.useRef)(false);
|
|
@@ -2118,7 +3231,7 @@
|
|
|
2118
3231
|
const expandedGroups = (0, react.useMemo)(() => Object.entries(groupExpansion).filter(([, expanded]) => expanded).map(([key]) => key), [groupExpansion]);
|
|
2119
3232
|
const ungroupedSessionIds = (0, react.useMemo)(() => {
|
|
2120
3233
|
const accounted = new Set(workspaces.flatMap((workspace) => workspace.sessionIds));
|
|
2121
|
-
return list.ids.filter((
|
|
3234
|
+
return list.ids.filter((id2) => list.byId[id2] !== void 0 && !accounted.has(id2));
|
|
2122
3235
|
}, [list, workspaces]);
|
|
2123
3236
|
(0, react.useEffect)(() => {
|
|
2124
3237
|
if (list.phase !== "ready") return;
|
|
@@ -2126,7 +3239,7 @@
|
|
|
2126
3239
|
previousOrderBy.current = orderBy;
|
|
2127
3240
|
const accounts = [...workspaces.map((workspace) => ({
|
|
2128
3241
|
key: workspace.workspaceId,
|
|
2129
|
-
sessionIds: workspace.sessionIds.filter((
|
|
3242
|
+
sessionIds: workspace.sessionIds.filter((id2) => list.byId[id2] !== void 0)
|
|
2130
3243
|
})), {
|
|
2131
3244
|
key: "",
|
|
2132
3245
|
sessionIds: ungroupedSessionIds
|
|
@@ -2141,7 +3254,7 @@
|
|
|
2141
3254
|
orderBy,
|
|
2142
3255
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2143
3256
|
});
|
|
2144
|
-
if (next.changed && typeof syncSessionOrderAccount === "function") syncSessionOrderAccount(key, next.order.map((
|
|
3257
|
+
if (next.changed && typeof syncSessionOrderAccount === "function") syncSessionOrderAccount(key, next.order.map((id2) => id2), next.updatedAt);
|
|
2145
3258
|
}
|
|
2146
3259
|
}, [
|
|
2147
3260
|
list,
|
|
@@ -2203,10 +3316,10 @@
|
|
|
2203
3316
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2204
3317
|
const accountSessionIds = activeDrag.accountKey === "" ? orderedUngroupedSessionIds : orderedWorkspaces.find((workspace) => workspace.workspaceId === activeDrag.accountKey)?.sessionIds;
|
|
2205
3318
|
if (accountSessionIds === void 0) return;
|
|
2206
|
-
const nextOrder = accountSessionIds.filter((
|
|
3319
|
+
const nextOrder = accountSessionIds.filter((id2) => id2 !== activeDrag.sessionId);
|
|
2207
3320
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2208
3321
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2209
|
-
setSessionOrder(activeDrag.accountKey, nextOrder.map((
|
|
3322
|
+
setSessionOrder(activeDrag.accountKey, nextOrder.map((id2) => id2));
|
|
2210
3323
|
if (orderBy === "updated" || activeDrag.accountKey === "") return;
|
|
2211
3324
|
insertSessionBefore(activeDrag.accountKey, activeDrag.sessionId, anchor).catch((reason) => {
|
|
2212
3325
|
console.warn("session reorder rejected:", reason);
|
|
@@ -2389,9 +3502,10 @@
|
|
|
2389
3502
|
]
|
|
2390
3503
|
});
|
|
2391
3504
|
}
|
|
2392
|
-
function FlatList({ useSessions, useSessionPendingInteraction, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
3505
|
+
function FlatList({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, open, forkSession, onSessionRename, onSessionArchive, onSessionUnarchive, onSessionDelete, archivedSessionIds, showArchived, orderBy, sessionOrderByAccount, sessionUpdatedAtByAccount, syncSessionOrderAccount, setSessionOrder, t, revealSessionId, onSessionRevealed }) {
|
|
2393
3506
|
const list = useSessions((s) => s);
|
|
2394
|
-
const pendingInteractions = useSessionPendingInteraction
|
|
3507
|
+
const pendingInteractions = useSessionUiFacts(useSessionPendingInteraction, useSessionStatus, preferSessionStatus);
|
|
3508
|
+
const current = currentSessionId(list);
|
|
2395
3509
|
const baseRows = (0, react.useMemo)(() => deriveFlat(list, archivedSessionIds, pendingInteractions, showArchived), [
|
|
2396
3510
|
list,
|
|
2397
3511
|
archivedSessionIds,
|
|
@@ -2414,7 +3528,7 @@
|
|
|
2414
3528
|
orderBy,
|
|
2415
3529
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2416
3530
|
});
|
|
2417
|
-
if (next.changed) syncSessionOrderAccount(FLAT_SESSION_ORDER_KEY, next.order.map((
|
|
3531
|
+
if (next.changed) syncSessionOrderAccount(FLAT_SESSION_ORDER_KEY, next.order.map((id2) => id2), next.updatedAt);
|
|
2418
3532
|
}, [
|
|
2419
3533
|
list,
|
|
2420
3534
|
orderBy,
|
|
@@ -2425,8 +3539,8 @@
|
|
|
2425
3539
|
]);
|
|
2426
3540
|
const rows = (0, react.useMemo)(() => {
|
|
2427
3541
|
const byId = new Map(baseRows.map((row) => [row.id, row]));
|
|
2428
|
-
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((
|
|
2429
|
-
const row = byId.get(
|
|
3542
|
+
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((id2) => {
|
|
3543
|
+
const row = byId.get(id2);
|
|
2430
3544
|
return row === void 0 ? [] : [row];
|
|
2431
3545
|
});
|
|
2432
3546
|
}, [
|
|
@@ -2448,10 +3562,10 @@
|
|
|
2448
3562
|
const sourceIndex = rows.findIndex((row) => row.id === activeDrag.sessionId);
|
|
2449
3563
|
const anchorIndex = anchor === void 0 ? rows.length : rows.findIndex((row) => row.id === anchor);
|
|
2450
3564
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2451
|
-
const nextOrder = rows.map((row) => row.id).filter((
|
|
3565
|
+
const nextOrder = rows.map((row) => row.id).filter((id2) => id2 !== activeDrag.sessionId);
|
|
2452
3566
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2453
3567
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2454
|
-
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((
|
|
3568
|
+
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((id2) => id2));
|
|
2455
3569
|
};
|
|
2456
3570
|
const now = Date.now();
|
|
2457
3571
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -2467,7 +3581,7 @@
|
|
|
2467
3581
|
const active = drag !== null;
|
|
2468
3582
|
return (0, react_jsx_runtime.jsx)(SessionNodeItem, {
|
|
2469
3583
|
node,
|
|
2470
|
-
currentId:
|
|
3584
|
+
currentId: current,
|
|
2471
3585
|
now,
|
|
2472
3586
|
onOpen: open,
|
|
2473
3587
|
onRename: onSessionRename,
|
|
@@ -2495,8 +3609,8 @@
|
|
|
2495
3609
|
active,
|
|
2496
3610
|
marker: active && drag.over?.id === node.id ? drag.over.half : null,
|
|
2497
3611
|
hover: (half) => {
|
|
2498
|
-
setDrag((
|
|
2499
|
-
...
|
|
3612
|
+
setDrag((current2) => current2 === null ? current2 : {
|
|
3613
|
+
...current2,
|
|
2500
3614
|
over: {
|
|
2501
3615
|
id: node.id,
|
|
2502
3616
|
half
|
|
@@ -2521,9 +3635,9 @@
|
|
|
2521
3635
|
}), (0, react_jsx_runtime.jsx)("span", { className: WorkspaceBrowser_module_css_default.fade })]
|
|
2522
3636
|
});
|
|
2523
3637
|
}
|
|
2524
|
-
function SearchResults({ useSessions, useSessionPendingInteraction, open, workspaces, archivedSessionIds, showArchived, query, remote, resultLimit, t }) {
|
|
3638
|
+
function SearchResults({ useSessions, useSessionPendingInteraction, useSessionStatus, preferSessionStatus, open, workspaces, archivedSessionIds, showArchived, query, remote, resultLimit, t }) {
|
|
2525
3639
|
const list = useSessions((s) => s);
|
|
2526
|
-
const pendingInteractions = useSessionPendingInteraction
|
|
3640
|
+
const pendingInteractions = useSessionUiFacts(useSessionPendingInteraction, useSessionStatus, preferSessionStatus);
|
|
2527
3641
|
const ungroupedLabel = t("group.ungrouped");
|
|
2528
3642
|
const currentRemote = remote.query === query ? remote : {
|
|
2529
3643
|
query,
|
|
@@ -2555,7 +3669,7 @@
|
|
|
2555
3669
|
"aria-label": t("search.results.aria"),
|
|
2556
3670
|
children: results.items.map((result) => (0, react_jsx_runtime.jsx)(SearchResultItem, {
|
|
2557
3671
|
result,
|
|
2558
|
-
currentId: list
|
|
3672
|
+
currentId: currentSessionId(list),
|
|
2559
3673
|
onOpen: open,
|
|
2560
3674
|
t
|
|
2561
3675
|
}, result.id))
|
|
@@ -2594,8 +3708,10 @@
|
|
|
2594
3708
|
};
|
|
2595
3709
|
}
|
|
2596
3710
|
};
|
|
2597
|
-
function WorkspaceBrowser({ wide, expandSidebar, useSessions, useSessionPendingInteraction, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, archiveWorkspaceSessions, unarchiveSession, deleteSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, renderSlot, t }) {
|
|
3711
|
+
function WorkspaceBrowser({ wide, expandSidebar, useSessions, useSessionPendingInteraction, useSessionStatus, useWorkspaces, useStore, actions, startSession, open, renameSession, forkSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, archiveSession, archiveWorkspaceSessions, unarchiveSession, deleteSession, insertSessionBefore, createWorkspace, searchSessions, searchResultLimit, useDirectoryFlow, renderSlot, t }) {
|
|
3712
|
+
const preferSessionStatus = typeof useSessionStatus === "function";
|
|
2598
3713
|
const useEffectiveSessionPendingInteraction = useSessionPendingInteraction ?? useEmptySessionPendingInteraction;
|
|
3714
|
+
const useEffectiveSessionStatus = useSessionStatus ?? useEmptySessionStatus;
|
|
2599
3715
|
const workspaces = useWorkspaces((state) => state.items);
|
|
2600
3716
|
const workspacePhase = useWorkspaces((state) => state.phase);
|
|
2601
3717
|
const archivedSessionIds = useWorkspaces((state) => state.archivedSessionIds);
|
|
@@ -3020,6 +4136,8 @@
|
|
|
3020
4136
|
children: wide && (normalizedQuery !== "" ? (0, react_jsx_runtime.jsx)(SearchResults, {
|
|
3021
4137
|
useSessions,
|
|
3022
4138
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
4139
|
+
useSessionStatus: useEffectiveSessionStatus,
|
|
4140
|
+
preferSessionStatus,
|
|
3023
4141
|
open: (sessionId) => {
|
|
3024
4142
|
setRevealSessionId(sessionId);
|
|
3025
4143
|
setQuery("");
|
|
@@ -3036,6 +4154,8 @@
|
|
|
3036
4154
|
}) : groupBy === "flat" ? (0, react_jsx_runtime.jsx)(FlatList, {
|
|
3037
4155
|
useSessions,
|
|
3038
4156
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
4157
|
+
useSessionStatus: useEffectiveSessionStatus,
|
|
4158
|
+
preferSessionStatus,
|
|
3039
4159
|
open: guardedOpen,
|
|
3040
4160
|
revealSessionId,
|
|
3041
4161
|
onSessionRevealed: acknowledgeSessionReveal,
|
|
@@ -3058,6 +4178,8 @@
|
|
|
3058
4178
|
}) : (0, react_jsx_runtime.jsx)(SessionTree, {
|
|
3059
4179
|
useSessions,
|
|
3060
4180
|
useSessionPendingInteraction: useEffectiveSessionPendingInteraction,
|
|
4181
|
+
useSessionStatus: useEffectiveSessionStatus,
|
|
4182
|
+
preferSessionStatus,
|
|
3061
4183
|
revealSessionId,
|
|
3062
4184
|
onSessionRevealed: acknowledgeSessionReveal,
|
|
3063
4185
|
onSessionRename,
|
|
@@ -3297,13 +4419,13 @@
|
|
|
3297
4419
|
]
|
|
3298
4420
|
});
|
|
3299
4421
|
}
|
|
3300
|
-
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-
|
|
3301
|
-
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:
|
|
3302
|
-
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}}";
|
|
3303
|
-
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-
|
|
4422
|
+
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}}";
|
|
4423
|
+
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}}";
|
|
4424
|
+
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}}";
|
|
4425
|
+
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}}";
|
|
3304
4426
|
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}";
|
|
3305
4427
|
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}";
|
|
3306
|
-
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-
|
|
4428
|
+
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}";
|
|
3307
4429
|
const ARCHIVE_SETTINGS_LAYOUT_OVERRIDE = ".dsham_settings{margin:0 auto!important}@media(max-width:720px){.dsham_settings{margin:0 auto!important}}";
|
|
3308
4430
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-archive-manager/ArchiveSettings.layout.css") + "]") === null) {
|
|
3309
4431
|
const tag = document.createElement("style");
|
|
@@ -3312,7 +4434,7 @@
|
|
|
3312
4434
|
tag.textContent = ARCHIVE_SETTINGS_LAYOUT_OVERRIDE + ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS + ARCHIVE_WORKSPACE_CONFIRM_CSS;
|
|
3313
4435
|
document.head.appendChild(tag);
|
|
3314
4436
|
}
|
|
3315
|
-
function ArchiveProjectSelect({ id, value, options, onChange, "aria-label": ariaLabel }) {
|
|
4437
|
+
function ArchiveProjectSelect({ id: id2, value, options, onChange, disabled = false, "aria-label": ariaLabel }) {
|
|
3316
4438
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3317
4439
|
const selectedIndex = Math.max(0, options.findIndex((option) => option.value === value));
|
|
3318
4440
|
const [active, setActive] = (0, react.useState)(selectedIndex);
|
|
@@ -3345,9 +4467,10 @@
|
|
|
3345
4467
|
}, [open]);
|
|
3346
4468
|
(0, react.useEffect)(() => {
|
|
3347
4469
|
if (!open) return;
|
|
3348
|
-
document.getElementById(
|
|
3349
|
-
}, [active, open,
|
|
4470
|
+
document.getElementById(id2 + "-opt-" + String(active))?.scrollIntoView({ block: "nearest" });
|
|
4471
|
+
}, [active, open, id2]);
|
|
3350
4472
|
const choose = (next) => {
|
|
4473
|
+
if (disabled) return;
|
|
3351
4474
|
onChange(next);
|
|
3352
4475
|
setOpen(false);
|
|
3353
4476
|
};
|
|
@@ -3359,14 +4482,15 @@
|
|
|
3359
4482
|
className: "dsham_settingsFilter",
|
|
3360
4483
|
ref: rootRef,
|
|
3361
4484
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
3362
|
-
id,
|
|
4485
|
+
id: id2,
|
|
3363
4486
|
ref: triggerRef,
|
|
3364
4487
|
type: "button",
|
|
3365
4488
|
className: "dsham_selectTrigger",
|
|
4489
|
+
disabled,
|
|
3366
4490
|
"aria-label": ariaLabel,
|
|
3367
4491
|
"aria-haspopup": "listbox",
|
|
3368
4492
|
"aria-expanded": open,
|
|
3369
|
-
"aria-controls":
|
|
4493
|
+
"aria-controls": id2 + "-list",
|
|
3370
4494
|
onClick: () => setOpen((current) => !current),
|
|
3371
4495
|
onKeyDown: (event) => {
|
|
3372
4496
|
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
|
|
@@ -3389,12 +4513,12 @@
|
|
|
3389
4513
|
})
|
|
3390
4514
|
})]
|
|
3391
4515
|
}), open ? (0, react_jsx_runtime.jsx)("div", {
|
|
3392
|
-
id:
|
|
4516
|
+
id: id2 + "-list",
|
|
3393
4517
|
ref: listRef,
|
|
3394
4518
|
className: "dsham_selectMenu",
|
|
3395
4519
|
role: "listbox",
|
|
3396
4520
|
tabIndex: 0,
|
|
3397
|
-
"aria-activedescendant":
|
|
4521
|
+
"aria-activedescendant": id2 + "-opt-" + String(active),
|
|
3398
4522
|
onKeyDown: (event) => {
|
|
3399
4523
|
if (event.key === "ArrowDown") {
|
|
3400
4524
|
event.preventDefault();
|
|
@@ -3430,7 +4554,7 @@
|
|
|
3430
4554
|
}
|
|
3431
4555
|
},
|
|
3432
4556
|
children: options.map((option, index) => (0, react_jsx_runtime.jsx)("button", {
|
|
3433
|
-
id:
|
|
4557
|
+
id: id2 + "-opt-" + String(index),
|
|
3434
4558
|
type: "button",
|
|
3435
4559
|
role: "option",
|
|
3436
4560
|
className: "dsham_selectOption",
|
|
@@ -3484,6 +4608,33 @@
|
|
|
3484
4608
|
onChange
|
|
3485
4609
|
});
|
|
3486
4610
|
}
|
|
4611
|
+
function ArchivedSessionMenu({ busy, title, t, onPreview, onRestoreOpen, onDelete, onCopyId, onCopyPath }) {
|
|
4612
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
4613
|
+
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
4614
|
+
open,
|
|
4615
|
+
onClose: () => setOpen(false),
|
|
4616
|
+
portal: true,
|
|
4617
|
+
align: "end",
|
|
4618
|
+
autoFocus: true,
|
|
4619
|
+
items: [
|
|
4620
|
+
...onPreview ? [{ id: "preview", label: t("discovery.preview"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, {}) }] : [],
|
|
4621
|
+
...onRestoreOpen ? [{ id: "restoreOpen", label: t("archives.restoreOpen"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16, {}) }] : [],
|
|
4622
|
+
...onCopyId ? [{ id: "copyId", label: t("details.copyId"), icon: react.createElement(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {}) }] : [],
|
|
4623
|
+
...onCopyPath ? [{ id: "copyPath", label: t("details.copyPath"), icon: react.createElement(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}) }] : [],
|
|
4624
|
+
...onDelete ? [{ id: "delete", label: t("menu.deleteSession"), icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}), danger: true }] : []
|
|
4625
|
+
],
|
|
4626
|
+
onSelect: (id2) => {
|
|
4627
|
+
setOpen(false);
|
|
4628
|
+
if (busy) return;
|
|
4629
|
+
if (id2 === "copyId") return onCopyId?.();
|
|
4630
|
+
if (id2 === "copyPath") return onCopyPath?.();
|
|
4631
|
+
if (id2 === "preview") return onPreview?.();
|
|
4632
|
+
if (id2 === "restoreOpen") return onRestoreOpen();
|
|
4633
|
+
if (id2 === "delete") onDelete();
|
|
4634
|
+
},
|
|
4635
|
+
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, {}) })
|
|
4636
|
+
});
|
|
4637
|
+
}
|
|
3487
4638
|
function ArchivedGroupActions({ group, busy, onArchive, onRestore, onDelete, t }) {
|
|
3488
4639
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3489
4640
|
const ungrouped = group.key === ARCHIVE_UNGROUPED_KEY;
|
|
@@ -3506,12 +4657,12 @@
|
|
|
3506
4657
|
open,
|
|
3507
4658
|
onClose: () => setOpen(false),
|
|
3508
4659
|
items,
|
|
3509
|
-
onSelect: (
|
|
4660
|
+
onSelect: (id2) => {
|
|
3510
4661
|
setOpen(false);
|
|
3511
4662
|
if (busy) return;
|
|
3512
|
-
if (
|
|
3513
|
-
else if (
|
|
3514
|
-
else if (
|
|
4663
|
+
if (id2 === "archive") onArchive?.();
|
|
4664
|
+
else if (id2 === "restore") onRestore();
|
|
4665
|
+
else if (id2 === "delete") onDelete();
|
|
3515
4666
|
},
|
|
3516
4667
|
portal: true,
|
|
3517
4668
|
anchor: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -3533,21 +4684,21 @@
|
|
|
3533
4684
|
if (target.scope === "all") return ids;
|
|
3534
4685
|
if (target.scope === "sessions") {
|
|
3535
4686
|
const selected = new Set(target.sessionIds ?? []);
|
|
3536
|
-
return ids.filter((
|
|
4687
|
+
return ids.filter((id2) => selected.has(id2));
|
|
3537
4688
|
}
|
|
3538
4689
|
if (target.scope === "workspace") {
|
|
3539
4690
|
const accounted2 = new Set(items.find((workspace) => workspace.workspaceId === target.workspaceId)?.sessionIds ?? []);
|
|
3540
|
-
return ids.filter((
|
|
4691
|
+
return ids.filter((id2) => accounted2.has(id2));
|
|
3541
4692
|
}
|
|
3542
4693
|
const accounted = new Set(items.flatMap((workspace) => workspace.sessionIds));
|
|
3543
|
-
return ids.filter((
|
|
4694
|
+
return ids.filter((id2) => !accounted.has(id2));
|
|
3544
4695
|
}
|
|
3545
4696
|
function archivedSessionIdsInGroups(groups) {
|
|
3546
4697
|
return [...new Set(groups.flatMap((group) => group.sessions.map((session) => session.id)))];
|
|
3547
4698
|
}
|
|
3548
4699
|
function pruneArchivedSelection(selectedSessionIds, archivedSessionIds) {
|
|
3549
4700
|
const archived = new Set(archivedSessionIds);
|
|
3550
|
-
return [...new Set(selectedSessionIds)].filter((
|
|
4701
|
+
return [...new Set(selectedSessionIds)].filter((id2) => archived.has(id2));
|
|
3551
4702
|
}
|
|
3552
4703
|
function toggleArchivedSelection(selectedSessionIds, sessionIds, checked) {
|
|
3553
4704
|
const selected = new Set(selectedSessionIds);
|
|
@@ -3586,23 +4737,27 @@
|
|
|
3586
4737
|
sessions: []
|
|
3587
4738
|
}));
|
|
3588
4739
|
const ungrouped = [];
|
|
3589
|
-
for (const
|
|
3590
|
-
const session = byId[
|
|
4740
|
+
for (const id2 of archivedSessionIds) {
|
|
4741
|
+
const session = byId[id2];
|
|
3591
4742
|
if (session === void 0 || session.origin === "subagent") continue;
|
|
3592
|
-
const group = byWorkspace.find((workspace) => workspace.ids.has(
|
|
4743
|
+
const group = byWorkspace.find((workspace) => workspace.ids.has(id2));
|
|
3593
4744
|
(group === void 0 ? ungrouped : group.sessions).push(session);
|
|
3594
4745
|
}
|
|
3595
4746
|
const result = byWorkspace.filter((group) => group.sessions.length > 0);
|
|
3596
4747
|
if (ungrouped.length > 0) result.push({ key: ARCHIVE_UNGROUPED_KEY, title: ungroupedLabel, sessions: ungrouped });
|
|
3597
4748
|
return result;
|
|
3598
4749
|
}
|
|
3599
|
-
function sortArchivedGroups(groups, sortBy, createdAtById, t) {
|
|
4750
|
+
function sortArchivedGroups(groups, sortBy, createdAtById, t, details = {}) {
|
|
3600
4751
|
const compareText = (left, right) => String(left).localeCompare(String(right), void 0, { numeric: true, sensitivity: "base" });
|
|
3601
4752
|
const timestampOf = (session) => {
|
|
3602
|
-
const value = sortBy === "created" ? createdAtById[session.id] : session.updatedAt;
|
|
4753
|
+
const value = sortBy === "created" ? details[session.id]?.createdAt ?? createdAtById[session.id] : session.updatedAt;
|
|
3603
4754
|
return typeof value === "number" && Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
|
|
3604
4755
|
};
|
|
3605
4756
|
const compareSessions = (left, right) => {
|
|
4757
|
+
if (sortBy === "turnsAsc" || sortBy === "turnsDesc") {
|
|
4758
|
+
const difference = compareTurnCounts(details[left.id]?.turnCount, details[right.id]?.turnCount, sortBy);
|
|
4759
|
+
if (difference) return difference;
|
|
4760
|
+
}
|
|
3606
4761
|
if (sortBy !== "alphabetical") {
|
|
3607
4762
|
const byTime = timestampOf(right) - timestampOf(left);
|
|
3608
4763
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3611,6 +4766,10 @@
|
|
|
3611
4766
|
};
|
|
3612
4767
|
const result = groups.map((group) => ({ ...group, sessions: [...group.sessions].sort(compareSessions) }));
|
|
3613
4768
|
return result.sort((left, right) => {
|
|
4769
|
+
if (sortBy === "turnsAsc" || sortBy === "turnsDesc") {
|
|
4770
|
+
const difference = compareTurnCounts(details[left.sessions[0]?.id]?.turnCount, details[right.sessions[0]?.id]?.turnCount, sortBy);
|
|
4771
|
+
if (difference) return difference;
|
|
4772
|
+
}
|
|
3614
4773
|
if (sortBy !== "alphabetical") {
|
|
3615
4774
|
const byTime = timestampOf(right.sessions[0]) - timestampOf(left.sessions[0]);
|
|
3616
4775
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3619,6 +4778,11 @@
|
|
|
3619
4778
|
});
|
|
3620
4779
|
}
|
|
3621
4780
|
const zh = {
|
|
4781
|
+
...organizerZh,
|
|
4782
|
+
...discoveryZh,
|
|
4783
|
+
...healthZh,
|
|
4784
|
+
"locale.language": "zh",
|
|
4785
|
+
"service.unavailable": "\u670D\u52A1\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5",
|
|
3622
4786
|
"archives.archiveProject": "\u5F52\u6863\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
3623
4787
|
"archives.archiveUngrouped": "\u5F52\u6863\u5168\u90E8\u672A\u5206\u7EC4\u804A\u5929",
|
|
3624
4788
|
"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",
|
|
@@ -3628,13 +4792,14 @@
|
|
|
3628
4792
|
"archives.searchUnarchived": "\u641C\u7D22\u672A\u5F52\u6863\u804A\u5929",
|
|
3629
4793
|
"archives.emptyUnarchived": "\u6682\u65E0\u672A\u5F52\u6863\u4F1A\u8BDD\u3002",
|
|
3630
4794
|
"archives.archiveSelected": "\u5F52\u6863",
|
|
3631
|
-
"archives.openSession": "\u6253\u5F00
|
|
4795
|
+
"archives.openSession": "\u6253\u5F00",
|
|
4796
|
+
"archives.moreActions": "\u66F4\u591A\u64CD\u4F5C",
|
|
3632
4797
|
"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",
|
|
3633
4798
|
"archives.archiveSuccess": "\u5DF2\u5F52\u6863 {n} \u6761\u4F1A\u8BDD\u3002",
|
|
3634
4799
|
"archives.archiveBatchFailed": "\u6279\u91CF\u5F52\u6863\u5931\u8D25\uFF1A{detail}",
|
|
3635
4800
|
"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",
|
|
3636
4801
|
"archives.sessionNotRetained": "\u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6216\u6062\u590D\u540E\u518D\u8BD5\u3002",
|
|
3637
|
-
"archives.restoreOpen": "\u6062\u590D\
|
|
4802
|
+
"archives.restoreOpen": "\u6062\u590D\u6253\u5F00",
|
|
3638
4803
|
"archives.selectedCount": "\u5DF2\u9009 {n} \u6761",
|
|
3639
4804
|
"archives.selectionHiddenHint": "\u542B\u5F53\u524D\u672A\u663E\u793A\u7684 {hidden} \u6761\uFF0C\u4E5F\u5C06\u53C2\u4E0E\u64CD\u4F5C",
|
|
3640
4805
|
"archives.clearSelectionShort": "\u6E05\u7A7A",
|
|
@@ -3675,7 +4840,7 @@
|
|
|
3675
4840
|
"archives.viewProject": "GitHub",
|
|
3676
4841
|
"archives.feedback": "\u95EE\u9898\u53CD\u9988",
|
|
3677
4842
|
"archives.empty": "\u6682\u65E0\u5DF2\u5F52\u6863\u4F1A\u8BDD",
|
|
3678
|
-
"archives.emptyFiltered": "\u6CA1\u6709\
|
|
4843
|
+
"archives.emptyFiltered": "\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u804A\u5929",
|
|
3679
4844
|
"archives.searchPlaceholder": "\u641C\u7D22\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3680
4845
|
"archives.sortBy": "\u6392\u5E8F\u65B9\u5F0F",
|
|
3681
4846
|
"archives.sortUpdated": "\u66F4\u65B0\u65F6\u95F4",
|
|
@@ -3689,24 +4854,20 @@
|
|
|
3689
4854
|
"archives.restoreSelected": "\u6062\u590D\u6240\u9009",
|
|
3690
4855
|
"archives.deleteSelected": "\u5220\u9664\u6240\u9009",
|
|
3691
4856
|
"archives.timestamp": "{date}\uFF0C{time}",
|
|
3692
|
-
"archives.
|
|
3693
|
-
"archives.restoreProject": "\u6062\u590D\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
4857
|
+
"archives.restoreProject": "\u6062\u590D\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3694
4858
|
"archives.restoreUngrouped": "\u5168\u90E8\u6062\u590D",
|
|
3695
|
-
"archives.deleteProject": "\u5220\u9664\
|
|
4859
|
+
"archives.deleteProject": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3696
4860
|
"archives.deleteUngrouped": "\u5168\u90E8\u5220\u9664",
|
|
3697
4861
|
"archives.projectActions": "\u9879\u76EE\u201C{name}\u201D\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3698
4862
|
"archives.ungroupedActions": "\u672A\u5206\u7EC4\u804A\u5929\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3699
4863
|
"archives.restoreSuccess": "\u5DF2\u6062\u590D {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u3002",
|
|
3700
4864
|
"archives.restoreBatchFailed": "\u6279\u91CF\u6062\u590D\u5931\u8D25\uFF1A{detail}",
|
|
3701
|
-
"archives.deleteAll": "\u5168\u90E8\u5220\u9664",
|
|
3702
|
-
"archives.deleteAllTitle": "\u5220\u9664\u5168\u90E8\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3703
|
-
"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",
|
|
3704
4865
|
"archives.deleteSelectedTitle": "\u5220\u9664\u6240\u9009\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3705
4866
|
"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",
|
|
3706
4867
|
"archives.deleteSelectedConfirm": "\u5220\u9664\u6240\u9009\u804A\u5929",
|
|
3707
4868
|
"archives.deleteProjectTitle": "\u5220\u9664\u201C{name}\u201D\u4E2D\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3708
4869
|
"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",
|
|
3709
|
-
"archives.deleteProjectConfirm": "\u5220\u9664\
|
|
4870
|
+
"archives.deleteProjectConfirm": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3710
4871
|
"archives.deleteUngroupedTitle": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3711
4872
|
"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",
|
|
3712
4873
|
"archives.deleteUngroupedConfirm": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5168\u90E8\u804A\u5929",
|
|
@@ -3767,6 +4928,12 @@
|
|
|
3767
4928
|
"time.ago": "{t}\u524D"
|
|
3768
4929
|
};
|
|
3769
4930
|
const en = {
|
|
4931
|
+
...organizerEn,
|
|
4932
|
+
...discoveryEn,
|
|
4933
|
+
...healthEn,
|
|
4934
|
+
"locale.language": "en",
|
|
4935
|
+
"service.unavailable": "The service is not ready. Please retry.",
|
|
4936
|
+
"archives.moreActions": "More actions",
|
|
3770
4937
|
"archives.archiveProject": "Archive all chats in this project",
|
|
3771
4938
|
"archives.archiveUngrouped": "Archive all ungrouped chats",
|
|
3772
4939
|
"archives.archiveProjectDesc": "Archive all {n} unarchived sessions in \u201C{name}\u201D, regardless of the current search filter. You can restore them in Archived.",
|
|
@@ -3823,7 +4990,7 @@
|
|
|
3823
4990
|
"archives.viewProject": "GitHub",
|
|
3824
4991
|
"archives.feedback": "Issues",
|
|
3825
4992
|
"archives.empty": "No archived sessions.",
|
|
3826
|
-
"archives.emptyFiltered": "No
|
|
4993
|
+
"archives.emptyFiltered": "No chats match your filters.",
|
|
3827
4994
|
"archives.searchPlaceholder": "Search archived chats",
|
|
3828
4995
|
"archives.sortBy": "Sort archived chats",
|
|
3829
4996
|
"archives.sortUpdated": "Last updated",
|
|
@@ -3837,7 +5004,6 @@
|
|
|
3837
5004
|
"archives.restoreSelected": "Restore selected",
|
|
3838
5005
|
"archives.deleteSelected": "Delete selected",
|
|
3839
5006
|
"archives.timestamp": "{date}, {time}",
|
|
3840
|
-
"archives.restoreAll": "Restore all",
|
|
3841
5007
|
"archives.restoreProject": "Restore all chats in this project",
|
|
3842
5008
|
"archives.restoreUngrouped": "Restore all",
|
|
3843
5009
|
"archives.deleteProject": "Delete all chats in this project",
|
|
@@ -3846,9 +5012,6 @@
|
|
|
3846
5012
|
"archives.ungroupedActions": "Archive actions for ungrouped chats",
|
|
3847
5013
|
"archives.restoreSuccess": "Restored {n} archived chats.",
|
|
3848
5014
|
"archives.restoreBatchFailed": "Could not restore the archived chats: {detail}",
|
|
3849
|
-
"archives.deleteAll": "Delete all",
|
|
3850
|
-
"archives.deleteAllTitle": "Delete all archived chats",
|
|
3851
|
-
"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.",
|
|
3852
5015
|
"archives.deleteSelectedTitle": "Delete selected archived chats",
|
|
3853
5016
|
"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.",
|
|
3854
5017
|
"archives.deleteSelectedConfirm": "Delete selected chats",
|
|
@@ -3955,13 +5118,13 @@
|
|
|
3955
5118
|
const archivedSessionIds = [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
3956
5119
|
return {
|
|
3957
5120
|
archivedSessionIds,
|
|
3958
|
-
archivedSessionIdsAdded: archivedSessionIds.filter((
|
|
5121
|
+
archivedSessionIdsAdded: archivedSessionIds.filter((id2) => !before.has(id2))
|
|
3959
5122
|
};
|
|
3960
5123
|
}
|
|
3961
5124
|
async function unarchiveSessionsViaOfficial(workspaces, sessionIds, refresh, unarchive) {
|
|
3962
5125
|
const before = new Set(workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []);
|
|
3963
5126
|
const seen = /* @__PURE__ */ new Set();
|
|
3964
|
-
const run = typeof unarchive === "function" ? unarchive : (
|
|
5127
|
+
const run = typeof unarchive === "function" ? unarchive : (id2) => workspaces.unarchiveSession(id2);
|
|
3965
5128
|
let archivedSessionIds;
|
|
3966
5129
|
for (const sessionId of sessionIds) {
|
|
3967
5130
|
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
@@ -3973,7 +5136,7 @@
|
|
|
3973
5136
|
archivedSessionIds ??= [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
3974
5137
|
return {
|
|
3975
5138
|
archivedSessionIds,
|
|
3976
|
-
unarchivedSessionIds: [...before].filter((
|
|
5139
|
+
unarchivedSessionIds: [...before].filter((id2) => !archivedSessionIds.includes(id2))
|
|
3977
5140
|
};
|
|
3978
5141
|
}
|
|
3979
5142
|
async function apply(ctx) {
|
|
@@ -3998,6 +5161,7 @@
|
|
|
3998
5161
|
linksSelector: ".dsham_settingsLinks",
|
|
3999
5162
|
zhName: "\u5F52\u6863\u4F1A\u8BDD",
|
|
4000
5163
|
enName: "Archived sessions",
|
|
5164
|
+
getLanguage: () => ctx.locale.bind(NS)("locale.language"),
|
|
4001
5165
|
createIcon: createPluginUpdateIcon
|
|
4002
5166
|
}), "dsh-archive-manager: plugin update ui");
|
|
4003
5167
|
const uiWorkspaceAt = () => ctx.get("uiWorkspace");
|
|
@@ -4040,6 +5204,43 @@
|
|
|
4040
5204
|
}
|
|
4041
5205
|
};
|
|
4042
5206
|
const unarchiveOne = createUnarchiveSession(ctx.workspaces, () => ctx.get("remote.workspaceRegistry"));
|
|
5207
|
+
const favoriteCall = async (method, input) => {
|
|
5208
|
+
const registry = ctx.get("remote.workspaceRegistry");
|
|
5209
|
+
if (!registry || typeof registry[method] !== "function") throw new Error(ctx.locale.bind(NS)("service.unavailable"));
|
|
5210
|
+
const result = input === void 0 ? await registry[method]() : await registry[method](input);
|
|
5211
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5212
|
+
return result.value;
|
|
5213
|
+
};
|
|
5214
|
+
const discoveryCall = async (method, input) => {
|
|
5215
|
+
const registry = ctx.get("remote.workspaceRegistry");
|
|
5216
|
+
if (!registry || typeof registry[method] !== "function") throw new Error(ctx.locale.bind(NS)("service.unavailable"));
|
|
5217
|
+
const result = await registry[method](input);
|
|
5218
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5219
|
+
return result.value;
|
|
5220
|
+
};
|
|
5221
|
+
const sessionDetails = (input) => discoveryCall("sessionDetails", input);
|
|
5222
|
+
const diagnoseSession = (input) => discoveryCall("diagnoseSession", input);
|
|
5223
|
+
const repairSession = (input) => discoveryCall("repairSession", input);
|
|
5224
|
+
const searchArchivedContent = (input) => discoveryCall("searchArchivedContent", input);
|
|
5225
|
+
const searchSessionContent = (input) => discoveryCall("searchSessionContent", input);
|
|
5226
|
+
const previewArchivedSession = (input) => discoveryCall("previewArchivedSession", input);
|
|
5227
|
+
const favoriteSessions = () => favoriteCall("favoriteSessions");
|
|
5228
|
+
const setSessionFavorite = (input) => favoriteCall("setSessionFavorite", input);
|
|
5229
|
+
const organizeBatch = createSessionOrganizer({
|
|
5230
|
+
workspaces: ctx.workspaces.list,
|
|
5231
|
+
sessions: ctx.sessions.list,
|
|
5232
|
+
archive: (id2) => ctx.workspaces.archiveSession(id2),
|
|
5233
|
+
restore: unarchiveOne,
|
|
5234
|
+
deleteOne: async (id2) => {
|
|
5235
|
+
const registry = ctx.get("remote.workspaceRegistry");
|
|
5236
|
+
if (!registry) throw new Error(ctx.locale.bind(NS)("service.unavailable"));
|
|
5237
|
+
const result = await registry.deleteSession(id2);
|
|
5238
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5239
|
+
},
|
|
5240
|
+
getFavorites: favoriteSessions,
|
|
5241
|
+
refresh: () => ctx.sessions.refresh?.(),
|
|
5242
|
+
currentSessionId
|
|
5243
|
+
});
|
|
4043
5244
|
const unarchiveSession = async (sessionId) => {
|
|
4044
5245
|
await unarchiveOne(sessionId);
|
|
4045
5246
|
await refreshSessionList();
|
|
@@ -4099,16 +5300,24 @@
|
|
|
4099
5300
|
searchSessions,
|
|
4100
5301
|
searchResultLimit: ctx.sessions.searchResultLimit,
|
|
4101
5302
|
renameSession: async (sessionId, title) => {
|
|
5303
|
+
const rename = async (session2) => {
|
|
5304
|
+
const result = await session2.rename(title);
|
|
5305
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
5306
|
+
};
|
|
5307
|
+
if (typeof ctx.sessions.using === "function") {
|
|
5308
|
+
await ctx.sessions.using(sessionId, { source: "workspaceOperation" }, (reference) => rename(reference.binding.session));
|
|
5309
|
+
return;
|
|
5310
|
+
}
|
|
4102
5311
|
const session = ctx.sessions.binding(sessionId)?.session;
|
|
4103
5312
|
if (session === void 0) throw new Error(`unknown session "${sessionId}"`);
|
|
4104
|
-
|
|
4105
|
-
if (!result.ok) throw new Error(result.error.message);
|
|
5313
|
+
await rename(session);
|
|
4106
5314
|
},
|
|
4107
5315
|
forkSession: (sessionId) => {
|
|
4108
5316
|
const uiWorkspace = uiWorkspaceAt();
|
|
4109
5317
|
if (typeof uiWorkspace?.forkSession === "function") return uiWorkspace.forkSession(sessionId);
|
|
4110
5318
|
return ctx.sessions.fork({ sessionId, increaseTitle: true }).then((childId) => {
|
|
4111
|
-
|
|
5319
|
+
if (typeof uiWorkspace?.openSession === "function") uiWorkspace.openSession(childId);
|
|
5320
|
+
else ctx.sessions.open(childId);
|
|
4112
5321
|
});
|
|
4113
5322
|
},
|
|
4114
5323
|
renameWorkspace: async (workspaceId, title) => {
|
|
@@ -4174,6 +5383,15 @@
|
|
|
4174
5383
|
openConversation,
|
|
4175
5384
|
focusSessionWorkspace,
|
|
4176
5385
|
viewState: archiveViewState,
|
|
5386
|
+
favoriteSessions,
|
|
5387
|
+
setSessionFavorite,
|
|
5388
|
+
organizeBatch,
|
|
5389
|
+
diagnoseSession,
|
|
5390
|
+
repairSession,
|
|
5391
|
+
sessionDetails,
|
|
5392
|
+
searchSessionContent,
|
|
5393
|
+
searchArchivedContent,
|
|
5394
|
+
previewArchivedSession,
|
|
4177
5395
|
t: ctx.locale.bind(NS)
|
|
4178
5396
|
})
|
|
4179
5397
|
}, ArchivedSessionsSection));
|
|
@@ -4183,6 +5401,7 @@
|
|
|
4183
5401
|
ArchiveSelectionToolbar,
|
|
4184
5402
|
ArchivedSessionsSection,
|
|
4185
5403
|
zh,
|
|
5404
|
+
en,
|
|
4186
5405
|
displayTitle,
|
|
4187
5406
|
sessionVisible,
|
|
4188
5407
|
indexSubagentDescendants,
|
|
@@ -4211,7 +5430,8 @@
|
|
|
4211
5430
|
hasSplitClientStore,
|
|
4212
5431
|
groupByWorkspace,
|
|
4213
5432
|
byRecency,
|
|
4214
|
-
ARCHIVE_MANAGER_REMOTE
|
|
5433
|
+
ARCHIVE_MANAGER_REMOTE,
|
|
5434
|
+
currentSessionId
|
|
4215
5435
|
};
|
|
4216
5436
|
exports.apply = apply;
|
|
4217
5437
|
exports.inject = inject;
|