@michengai/dsh-archive-manager 0.1.44 → 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 +56 -0
- package/CHANGELOG.zh-CN.md +56 -0
- package/README.md +64 -17
- package/README.zh-CN.md +67 -16
- 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-organizer.js +105 -0
- package/lib/client.js +1314 -159
- package/lib/session-repair.js +123 -0
- package/lib/workspace.js +222 -0
- package/package.json +3 -2
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,9 +668,9 @@
|
|
|
10
668
|
function formatArchiveNavigationError(error, t) {
|
|
11
669
|
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) : String(error?.message ?? error);
|
|
12
670
|
}
|
|
13
|
-
function retainInfoSnapshot(sessions,
|
|
671
|
+
function retainInfoSnapshot(sessions, id2) {
|
|
14
672
|
if (typeof sessions?.retainInfo !== "function") return;
|
|
15
|
-
const source = sessions.retainInfo(
|
|
673
|
+
const source = sessions.retainInfo(id2);
|
|
16
674
|
return typeof source?.getSnapshot === "function" ? source.getSnapshot() : source;
|
|
17
675
|
}
|
|
18
676
|
function mainViewSessionId(list) {
|
|
@@ -25,11 +683,11 @@
|
|
|
25
683
|
function currentSessionId(list) {
|
|
26
684
|
return mainViewSessionId(list) ?? list?.current;
|
|
27
685
|
}
|
|
28
|
-
function sessionIsCurrent(list,
|
|
29
|
-
if (
|
|
30
|
-
if ((list?.byId?.[
|
|
31
|
-
if ((retainInfoSnapshot(sessions,
|
|
32
|
-
return list?.current ===
|
|
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;
|
|
33
691
|
}
|
|
34
692
|
async function openArchivedConversation(actions, sessionId, restore, isActive = () => true) {
|
|
35
693
|
if (restore) {
|
|
@@ -44,7 +702,7 @@
|
|
|
44
702
|
let allowed;
|
|
45
703
|
const original = navigation?.clearArchivedCurrent;
|
|
46
704
|
const descriptor = navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent");
|
|
47
|
-
const viewing = (
|
|
705
|
+
const viewing = (id2) => sessionIsCurrent(sessions.list.getSnapshot(), id2, sessions);
|
|
48
706
|
const wrapped = function(...args) {
|
|
49
707
|
if (allowed !== void 0 && viewing(allowed) && workspaces.list.getSnapshot().archivedSessionIds.includes(allowed)) return false;
|
|
50
708
|
allowed = void 0;
|
|
@@ -60,22 +718,22 @@
|
|
|
60
718
|
}
|
|
61
719
|
}
|
|
62
720
|
return {
|
|
63
|
-
open(
|
|
64
|
-
allowed =
|
|
721
|
+
open(id2) {
|
|
722
|
+
allowed = id2;
|
|
65
723
|
try {
|
|
66
|
-
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(
|
|
724
|
+
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(id2)) {
|
|
67
725
|
warn("archive-manager: \u5F52\u6863\u5BFC\u822A\u9002\u914D\u4E0D\u53EF\u7528\u6216\u5DF2\u88AB\u66FF\u6362\u3002");
|
|
68
726
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
69
727
|
}
|
|
70
728
|
beginNavigation?.();
|
|
71
|
-
if (typeof sessions.retain === "function" && typeof navigation?.openSession === "function") navigation.openSession(
|
|
72
|
-
else if (typeof sessions.open === "function") sessions.open(
|
|
73
|
-
else if (typeof navigation?.openSession === "function") navigation.openSession(
|
|
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);
|
|
74
732
|
else {
|
|
75
733
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u63D0\u4F9B\u4F1A\u8BDD\u6253\u5F00\u63A5\u53E3\u3002");
|
|
76
734
|
throw new ArchiveNavigationError("navigationUnavailable");
|
|
77
735
|
}
|
|
78
|
-
if (!viewing(
|
|
736
|
+
if (!viewing(id2)) {
|
|
79
737
|
warn("archive-manager: \u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\u3002", { cleanupAvailable: typeof original === "function" });
|
|
80
738
|
throw new ArchiveNavigationError("sessionNotRetained");
|
|
81
739
|
}
|
|
@@ -165,7 +823,7 @@
|
|
|
165
823
|
var STYLE_ID = "michengai-plugin-update-ui";
|
|
166
824
|
var CSS = `
|
|
167
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}
|
|
168
|
-
.mpi-overlay{position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.62)}.mpi-dialog{position:relative;box-sizing:border-box;width:min(680px,100%);max-height:calc(100vh - 48px);overflow:auto;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:14px;padding:22px;background:var(--dsw-alias-bg-layer-2,var(--dsw-specific-menu,#202124));color:var(--dsw-alias-label-primary,#fff);box-shadow:var(--dsw-shadow-lv3,0 16px 48px rgba(0,0,0,.24));font-family:inherit}.mpi-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.mpi-dialog h2{margin:0;font-size:18px;line-height:26px}.mpi-dialog-close{display:inline-flex;flex:0 0 28px;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);cursor:pointer}.mpi-dialog-close:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-intro{margin:8px 0 18px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:13px;line-height:20px}.mpi-meta{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 18px;margin:0 0 16px;font-size:12px;line-height:18px}.mpi-meta dt{color:var(--dsw-alias-label-secondary,#c2c4ca)}.mpi-meta dd{margin:0;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.mpi-status{margin:0 0 18px;border-radius:7px;padding:12px 14px;background:var(--dsw-alias-bg-layer-3,var(--dsw-
|
|
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}}
|
|
169
827
|
`;
|
|
170
828
|
var ZH = {
|
|
171
829
|
check: "\u68C0\u67E5\u66F4\u65B0",
|
|
@@ -217,7 +875,9 @@
|
|
|
217
875
|
restarting: "Update complete. Restarting DSH Desktop\u2026",
|
|
218
876
|
unavailable: "Automatic update is unavailable. Use the manual command."
|
|
219
877
|
};
|
|
220
|
-
function strings() {
|
|
878
|
+
function strings(language) {
|
|
879
|
+
if (language === "en") return EN;
|
|
880
|
+
if (language === "zh") return ZH;
|
|
221
881
|
const lang = document.documentElement.lang.toLowerCase();
|
|
222
882
|
const settings = document.querySelector('[role="dialog"]')?.textContent ?? "";
|
|
223
883
|
return lang.startsWith("en") || settings.includes("Settings") && !settings.includes("\u8BBE\u7F6E") ? EN : ZH;
|
|
@@ -262,6 +922,7 @@
|
|
|
262
922
|
if (typeof document === "undefined" || document.body === null) return () => {
|
|
263
923
|
};
|
|
264
924
|
ensureStyle();
|
|
925
|
+
const getStrings = () => strings(options.getLanguage?.());
|
|
265
926
|
const controller = new AbortController();
|
|
266
927
|
let payload;
|
|
267
928
|
let overlay;
|
|
@@ -296,12 +957,18 @@
|
|
|
296
957
|
if (version.textContent !== versionLabel) version.textContent = versionLabel;
|
|
297
958
|
}
|
|
298
959
|
const links = row.querySelector(options.linksSelector);
|
|
299
|
-
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
|
+
}
|
|
300
967
|
const button = document.createElement("button");
|
|
301
968
|
button.type = "button";
|
|
302
969
|
button.className = "mpi-check";
|
|
303
970
|
button.dataset.mpiCheck = options.packageName;
|
|
304
|
-
setButtonContent(button,
|
|
971
|
+
setButtonContent(button, getStrings().check, "refresh");
|
|
305
972
|
button.addEventListener("click", openDialog);
|
|
306
973
|
links.append(button);
|
|
307
974
|
};
|
|
@@ -316,7 +983,7 @@
|
|
|
316
983
|
};
|
|
317
984
|
function openDialog() {
|
|
318
985
|
closeDialog();
|
|
319
|
-
const text =
|
|
986
|
+
const text = getStrings();
|
|
320
987
|
overlay = document.createElement("div");
|
|
321
988
|
overlay.className = "mpi-overlay";
|
|
322
989
|
const dialog = document.createElement("section");
|
|
@@ -324,7 +991,7 @@
|
|
|
324
991
|
dialog.setAttribute("role", "dialog");
|
|
325
992
|
dialog.setAttribute("aria-modal", "true");
|
|
326
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>`;
|
|
327
|
-
const name =
|
|
994
|
+
const name = text === EN ? options.enName : options.zhName;
|
|
328
995
|
dialog.querySelector("h2").textContent = `${name} ${text.update}`;
|
|
329
996
|
dialog.querySelector(".mpi-intro").textContent = text.intro;
|
|
330
997
|
const terms = dialog.querySelectorAll("dt");
|
|
@@ -450,6 +1117,210 @@
|
|
|
450
1117
|
};
|
|
451
1118
|
}
|
|
452
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
|
+
|
|
453
1324
|
// src/client.js
|
|
454
1325
|
window.__ModuleLoader__.load({
|
|
455
1326
|
id: "@michengai/dsh-archive-manager",
|
|
@@ -467,7 +1338,10 @@
|
|
|
467
1338
|
}
|
|
468
1339
|
let react_jsx_runtime = require2("react/jsx-runtime");
|
|
469
1340
|
let react = require2("react");
|
|
1341
|
+
const OrganizerPanel = createOrganizerPanel(react);
|
|
1342
|
+
const { HighlightedText, useSessionDetails, useArchiveSearch, useArchivePreview, DiscoveryFilters, SearchStatus, PreviewContent } = createDiscoveryTools(react);
|
|
470
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 });
|
|
471
1345
|
const UPDATE_ICON_PATHS = {
|
|
472
1346
|
refresh: ["M13.5 5.5V2.5m0 0h-3m3 0-2.1 2.1A5.5 5.5 0 1 0 13.2 12"],
|
|
473
1347
|
download: ["M8 2v8m0 0 3-3m-3 3-3-3M3 13v2h10v-2"],
|
|
@@ -504,7 +1378,7 @@
|
|
|
504
1378
|
parse(value) {
|
|
505
1379
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
506
1380
|
const ids = value.archivedSessionIds;
|
|
507
|
-
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");
|
|
508
1382
|
return value;
|
|
509
1383
|
}
|
|
510
1384
|
};
|
|
@@ -519,7 +1393,7 @@
|
|
|
519
1393
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("target must be an object");
|
|
520
1394
|
if (value.scope === "all" || value.scope === "ungrouped") return value;
|
|
521
1395
|
if (value.scope === "workspace" && typeof value.workspaceId === "string" && value.workspaceId.length > 0) return value;
|
|
522
|
-
if (value.scope === "sessions" && Array.isArray(value.sessionIds) && value.sessionIds.length > 0 && value.sessionIds.every((
|
|
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;
|
|
523
1397
|
throw new TypeError("target.scope must be all, ungrouped, workspace with a non-empty workspaceId, or sessions with non-empty sessionIds");
|
|
524
1398
|
}
|
|
525
1399
|
};
|
|
@@ -527,7 +1401,7 @@
|
|
|
527
1401
|
parse(value) {
|
|
528
1402
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("result must be an object");
|
|
529
1403
|
for (const key of ["requestedSessionIds", "deletedSessionIds", "skippedSessionIds"]) {
|
|
530
|
-
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`);
|
|
531
1405
|
}
|
|
532
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");
|
|
533
1407
|
return value;
|
|
@@ -537,7 +1411,7 @@
|
|
|
537
1411
|
parse(value) {
|
|
538
1412
|
if (typeof value !== "object" || value === null || Array.isArray(value) || !Array.isArray(value.items)) throw new TypeError("result.items must be an array");
|
|
539
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");
|
|
540
|
-
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");
|
|
541
1415
|
return value;
|
|
542
1416
|
}
|
|
543
1417
|
};
|
|
@@ -547,6 +1421,8 @@
|
|
|
547
1421
|
const ARCHIVE_MANAGER_REMOTE = {
|
|
548
1422
|
package: "@michengai/dsh-archive-manager",
|
|
549
1423
|
descriptors: [
|
|
1424
|
+
...favoriteInvocations(),
|
|
1425
|
+
...discoveryInvocations(),
|
|
550
1426
|
{
|
|
551
1427
|
id: "@michengai/dsh-archive-manager#workspaceRegistry/unarchiveSession",
|
|
552
1428
|
service: "workspaceRegistry",
|
|
@@ -704,7 +1580,7 @@
|
|
|
704
1580
|
function GithubMark16() {
|
|
705
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" }) });
|
|
706
1582
|
}
|
|
707
|
-
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 }) {
|
|
708
1584
|
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
709
1585
|
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
710
1586
|
const [archiveTab, setArchiveTab] = (0, react.useState)("archived");
|
|
@@ -714,6 +1590,7 @@
|
|
|
714
1590
|
const requestArchive = (ids, group = null) => {
|
|
715
1591
|
setError(null);
|
|
716
1592
|
setNotice(null);
|
|
1593
|
+
setIdleRequest(false);
|
|
717
1594
|
setArchiveGroup(group);
|
|
718
1595
|
setArchiveTarget(ids);
|
|
719
1596
|
};
|
|
@@ -736,6 +1613,91 @@
|
|
|
736
1613
|
const [unarchivingSessionIds, setUnarchivingSessionIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
737
1614
|
const unarchivingSessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
738
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
|
+
};
|
|
739
1701
|
const navigationActive = (0, react.useRef)(true);
|
|
740
1702
|
const navigationPending = (0, react.useRef)(false);
|
|
741
1703
|
(0, react.useEffect)(() => {
|
|
@@ -752,15 +1714,15 @@
|
|
|
752
1714
|
let restored = false;
|
|
753
1715
|
try {
|
|
754
1716
|
await openArchivedConversation({
|
|
755
|
-
prepare: restore ? async (
|
|
756
|
-
await focusSessionWorkspace?.(
|
|
1717
|
+
prepare: restore ? async (id2) => {
|
|
1718
|
+
await focusSessionWorkspace?.(id2);
|
|
757
1719
|
} : void 0,
|
|
758
|
-
restore: async (
|
|
759
|
-
await unarchiveSession(
|
|
1720
|
+
restore: async (id2) => {
|
|
1721
|
+
await unarchiveSession(id2);
|
|
760
1722
|
restored = true;
|
|
761
1723
|
},
|
|
762
|
-
open: async (
|
|
763
|
-
await openConversation(
|
|
1724
|
+
open: async (id2) => {
|
|
1725
|
+
await openConversation(id2);
|
|
764
1726
|
if (navigationActive.current) close?.();
|
|
765
1727
|
}
|
|
766
1728
|
}, session.id, restore, () => navigationActive.current);
|
|
@@ -784,6 +1746,7 @@
|
|
|
784
1746
|
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, eligibleIds, t("group.ungrouped")), [sessions.byId, workspaceState, eligibleIds, t]);
|
|
785
1747
|
const switchTab = (tab) => {
|
|
786
1748
|
if (busy || unarchivingSessionIdsRef.current.size > 0) return;
|
|
1749
|
+
preview.close();
|
|
787
1750
|
setArchiveTab(tab);
|
|
788
1751
|
setSelectedSessionIds([]);
|
|
789
1752
|
setArchiveTarget(null);
|
|
@@ -792,10 +1755,23 @@
|
|
|
792
1755
|
setNotice(null);
|
|
793
1756
|
setProject("all");
|
|
794
1757
|
setQuery("");
|
|
795
|
-
if (tab === "unarchived" && sortBy === "created") setSortBy("updated");
|
|
796
1758
|
};
|
|
797
1759
|
const confirmArchive = async () => {
|
|
798
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
|
+
}
|
|
799
1775
|
archiveBusy.current = true;
|
|
800
1776
|
setBusy(true);
|
|
801
1777
|
setError(null);
|
|
@@ -816,7 +1792,25 @@
|
|
|
816
1792
|
setBusy(false);
|
|
817
1793
|
}
|
|
818
1794
|
};
|
|
819
|
-
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]);
|
|
820
1814
|
(0, react.useEffect)(() => {
|
|
821
1815
|
let cancelled = false;
|
|
822
1816
|
archivedSessionMetadata().then((result) => {
|
|
@@ -831,19 +1825,19 @@
|
|
|
831
1825
|
(0, react.useEffect)(() => {
|
|
832
1826
|
if (project !== "all" && !groups.some((group) => group.key === project)) setProject("all");
|
|
833
1827
|
}, [groups, project]);
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
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) : [];
|
|
841
1837
|
const visibleSessionIds = (0, react.useMemo)(() => archivedSessionIdsInGroups(filteredGroups), [filteredGroups]);
|
|
842
1838
|
const selectedSessionIdSet = (0, react.useMemo)(() => new Set(selectedSessionIds), [selectedSessionIds]);
|
|
843
1839
|
const selectedVisibleCount = visibleSessionIds.filter((sessionId) => selectedSessionIdSet.has(sessionId)).length;
|
|
844
1840
|
const allVisibleSelected = visibleSessionIds.length > 0 && selectedVisibleCount === visibleSessionIds.length;
|
|
845
|
-
const allBatchTarget = { scope: "all" };
|
|
846
|
-
const allBatchSessionIds = (0, react.useMemo)(() => deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, allBatchTarget), [workspaceState.archivedSessionIds, workspaceState.items]);
|
|
847
1841
|
(0, react.useEffect)(() => {
|
|
848
1842
|
setSelectedSessionIds((current) => pruneArchivedSelection(current, eligibleIds));
|
|
849
1843
|
}, [eligibleIds]);
|
|
@@ -868,6 +1862,11 @@
|
|
|
868
1862
|
};
|
|
869
1863
|
const onBatchUnarchive = async (target) => {
|
|
870
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
|
+
}
|
|
871
1870
|
setBusy(true);
|
|
872
1871
|
setError(null);
|
|
873
1872
|
setNotice(null);
|
|
@@ -906,6 +1905,12 @@
|
|
|
906
1905
|
}, [deleteTarget, busy]);
|
|
907
1906
|
const confirmDelete = async () => {
|
|
908
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
|
+
}
|
|
909
1914
|
setBusy(true);
|
|
910
1915
|
setError(null);
|
|
911
1916
|
setNotice(null);
|
|
@@ -930,9 +1935,9 @@
|
|
|
930
1935
|
}
|
|
931
1936
|
};
|
|
932
1937
|
const batchScope = deleteTarget?.kind === "batch" ? deleteTarget.target.scope : null;
|
|
933
|
-
const deleteDialogTitle = batchScope === "
|
|
934
|
-
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "
|
|
935
|
-
const deleteConfirmLabel = batchScope === "
|
|
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");
|
|
936
1941
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
937
1942
|
className: "dsham_settings",
|
|
938
1943
|
"aria-label": t("archives.title"),
|
|
@@ -965,16 +1970,40 @@
|
|
|
965
1970
|
},
|
|
966
1971
|
children: t("archives.tab." + tab)
|
|
967
1972
|
}, tab))
|
|
968
|
-
}), isArchived && (0, react_jsx_runtime.jsxs)("div", {
|
|
969
|
-
className: "dsham_settingsHeaderActions",
|
|
970
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsRestoreAll", disabled: busy || allBatchSessionIds.length === 0, onClick: () => onBatchUnarchive(allBatchTarget), children: t("archives.restoreAll") }), (0, react_jsx_runtime.jsxs)("button", { type: "button", className: "dsham_settingsDanger", disabled: busy || allBatchSessionIds.length === 0, onClick: () => setDeleteTarget({ kind: "batch", target: allBatchTarget, title: t("archives.allProjects"), count: allBatchSessionIds.length }), children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}), t("archives.deleteAll")] })]
|
|
971
1973
|
})]
|
|
972
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", {
|
|
973
1975
|
className: "dsham_settingsToolbar",
|
|
974
|
-
children: [(0, react_jsx_runtime.jsxs)("
|
|
1976
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
975
1977
|
className: "dsham_settingsSearch",
|
|
976
|
-
children: [(
|
|
977
|
-
|
|
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
|
|
978
2007
|
}), groups.length > 0 && (0, react_jsx_runtime.jsx)(ArchiveSelectionToolbar, {
|
|
979
2008
|
selectedCount: selectedSessionIds.length,
|
|
980
2009
|
hiddenCount: selectedSessionIds.length - selectedVisibleCount,
|
|
@@ -988,7 +2017,7 @@
|
|
|
988
2017
|
onArchive: isArchived ? void 0 : () => requestArchive([...selectedSessionIds]),
|
|
989
2018
|
onRestore: onSelectedUnarchive,
|
|
990
2019
|
onDelete: () => setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: selectedSessionIds }, count: selectedSessionIds.length })
|
|
991
|
-
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t(isArchived ? "archives.empty" : "archives.emptyUnarchived") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
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) => {
|
|
992
2021
|
const target = archivedBatchTargetForGroup(group.key);
|
|
993
2022
|
const groupSessionIds = groups.find((item) => item.key === group.key)?.sessions.map((session) => session.id) ?? [];
|
|
994
2023
|
const count = isArchived ? deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length : groupSessionIds.length;
|
|
@@ -996,18 +2025,50 @@
|
|
|
996
2025
|
className: "dsham_settingsGroup",
|
|
997
2026
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
998
2027
|
className: "dsham_settingsGroupHeading",
|
|
999
|
-
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 })] })]
|
|
1000
2034
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1001
2035
|
className: "dsham_settingsList",
|
|
1002
|
-
|
|
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", {
|
|
1003
2039
|
className: "dsham_settingsRow",
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
+
]
|
|
1008
2054
|
}, session.id))
|
|
1009
2055
|
})]
|
|
1010
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 })
|
|
1011
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, {
|
|
1012
2073
|
open: archiveTarget !== null,
|
|
1013
2074
|
onClose: closeArchive,
|
|
@@ -1016,9 +2077,14 @@
|
|
|
1016
2077
|
description: archiveGroup === null ? t("archives.archiveSelectedDesc") : t(archiveGroup.key === ARCHIVE_UNGROUPED_KEY ? "archives.archiveUngroupedDesc" : "archives.archiveProjectDesc", { name: archiveGroup.title, n: archiveTarget?.length ?? 0 }),
|
|
1017
2078
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1018
2079
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", disabled: busy, onClick: closeArchive, children: t("cancel") }),
|
|
1019
|
-
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, { variant: "outline", className: "dsham_archiveWorkspaceConfirm", disabled: busy, onClick: confirmArchive, children: t("archives.archiveSelected") })
|
|
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") })
|
|
1020
2081
|
] }),
|
|
1021
|
-
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
|
+
] })
|
|
1022
2088
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1023
2089
|
open: deleteTarget !== null,
|
|
1024
2090
|
onClose: closeDelete,
|
|
@@ -1026,7 +2092,7 @@
|
|
|
1026
2092
|
title: deleteDialogTitle,
|
|
1027
2093
|
...deleteDialogDescription === void 0 ? {} : { description: deleteDialogDescription },
|
|
1028
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 })] }),
|
|
1029
|
-
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 })] })
|
|
1030
2096
|
})] })]
|
|
1031
2097
|
});
|
|
1032
2098
|
}
|
|
@@ -1115,16 +2181,16 @@
|
|
|
1115
2181
|
const accounted = /* @__PURE__ */ new Set();
|
|
1116
2182
|
for (const workspace of workspaces) {
|
|
1117
2183
|
const members = [];
|
|
1118
|
-
for (const
|
|
1119
|
-
const summary = list.byId[
|
|
2184
|
+
for (const id2 of workspace.sessionIds) {
|
|
2185
|
+
const summary = list.byId[id2];
|
|
1120
2186
|
if (summary === void 0) continue;
|
|
1121
|
-
accounted.add(
|
|
2187
|
+
accounted.add(id2);
|
|
1122
2188
|
if (!sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1123
2189
|
members.push(summary);
|
|
1124
2190
|
}
|
|
1125
2191
|
groups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members, "account"));
|
|
1126
2192
|
}
|
|
1127
|
-
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));
|
|
1128
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"));
|
|
1129
2195
|
return groups;
|
|
1130
2196
|
}
|
|
@@ -1178,9 +2244,9 @@
|
|
|
1178
2244
|
const pending = /* @__PURE__ */ new Map();
|
|
1179
2245
|
const completed = /* @__PURE__ */ new Set();
|
|
1180
2246
|
if (status instanceof Map) {
|
|
1181
|
-
for (const [
|
|
1182
|
-
if (entry?.pendingInteraction !== void 0) pending.set(
|
|
1183
|
-
if (entry?.completionUnread === true) completed.add(
|
|
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);
|
|
1184
2250
|
}
|
|
1185
2251
|
}
|
|
1186
2252
|
return { pending, completed };
|
|
@@ -1232,8 +2298,8 @@
|
|
|
1232
2298
|
const archived = new Set(archivedSessionIds);
|
|
1233
2299
|
const descendants = indexSubagentDescendants(list.byId);
|
|
1234
2300
|
const rows = [];
|
|
1235
|
-
for (const
|
|
1236
|
-
const s = list.byId[
|
|
2301
|
+
for (const id2 of list.ids) {
|
|
2302
|
+
const s = list.byId[id2];
|
|
1237
2303
|
if (s === void 0 || !sessionVisible(s, currentSessionId(list), archived, showArchived)) continue;
|
|
1238
2304
|
rows.push(s);
|
|
1239
2305
|
}
|
|
@@ -1254,8 +2320,8 @@
|
|
|
1254
2320
|
const contentBySession = /* @__PURE__ */ new Map();
|
|
1255
2321
|
for (const item of content.items) if (!contentBySession.has(item.sessionId)) contentBySession.set(item.sessionId, item);
|
|
1256
2322
|
const local = [];
|
|
1257
|
-
for (const
|
|
1258
|
-
const summary = list.byId[
|
|
2323
|
+
for (const id2 of list.ids) {
|
|
2324
|
+
const summary = list.byId[id2];
|
|
1259
2325
|
if (summary === void 0 || summary.blank || !sessionVisible(summary, currentSessionId(list), archived, showArchived)) continue;
|
|
1260
2326
|
if (sessionTitle(summary).toLowerCase().includes(q) || labelOf(summary).toLowerCase().includes(q)) local.push(summary);
|
|
1261
2327
|
}
|
|
@@ -1470,11 +2536,11 @@
|
|
|
1470
2536
|
setMenuOpen(false);
|
|
1471
2537
|
},
|
|
1472
2538
|
items: workspaceMenuItems,
|
|
1473
|
-
onSelect: (
|
|
2539
|
+
onSelect: (id2) => {
|
|
1474
2540
|
setMenuOpen(false);
|
|
1475
|
-
if (
|
|
1476
|
-
if (
|
|
1477
|
-
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();
|
|
1478
2544
|
else actions.delete();
|
|
1479
2545
|
},
|
|
1480
2546
|
portal: true,
|
|
@@ -1760,13 +2826,13 @@
|
|
|
1760
2826
|
setMenuOpen(false);
|
|
1761
2827
|
},
|
|
1762
2828
|
items: sessionMenuItems,
|
|
1763
|
-
onSelect: (
|
|
2829
|
+
onSelect: (id2) => {
|
|
1764
2830
|
setMenuOpen(false);
|
|
1765
|
-
if (
|
|
1766
|
-
if (
|
|
1767
|
-
if (
|
|
1768
|
-
if (
|
|
1769
|
-
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);
|
|
1770
2836
|
},
|
|
1771
2837
|
portal: true,
|
|
1772
2838
|
closeOnPointerLeave: true,
|
|
@@ -1883,12 +2949,12 @@
|
|
|
1883
2949
|
setErrorOpen(true);
|
|
1884
2950
|
}
|
|
1885
2951
|
};
|
|
1886
|
-
const handleSelect = (
|
|
1887
|
-
if (
|
|
2952
|
+
const handleSelect = (id2) => {
|
|
2953
|
+
if (id2 === ADD_WORKSPACE) {
|
|
1888
2954
|
openDirectoryFlow();
|
|
1889
2955
|
return;
|
|
1890
2956
|
}
|
|
1891
|
-
onPick(
|
|
2957
|
+
onPick(id2);
|
|
1892
2958
|
};
|
|
1893
2959
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1894
2960
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
@@ -2017,18 +3083,18 @@
|
|
|
2017
3083
|
}
|
|
2018
3084
|
function reconciledSessionOrder(sessionIds, stored) {
|
|
2019
3085
|
if (stored === void 0) return [...sessionIds];
|
|
2020
|
-
const byId = new Map(sessionIds.map((
|
|
3086
|
+
const byId = new Map(sessionIds.map((id2) => [id2, id2]));
|
|
2021
3087
|
const ordered = [];
|
|
2022
3088
|
const included = /* @__PURE__ */ new Set();
|
|
2023
3089
|
for (const key of stored) {
|
|
2024
|
-
const
|
|
2025
|
-
if (
|
|
2026
|
-
ordered.push(
|
|
3090
|
+
const id2 = byId.get(key);
|
|
3091
|
+
if (id2 === void 0 || included.has(key)) continue;
|
|
3092
|
+
ordered.push(id2);
|
|
2027
3093
|
included.add(key);
|
|
2028
3094
|
}
|
|
2029
|
-
for (const
|
|
2030
|
-
if (included.has(
|
|
2031
|
-
ordered.push(
|
|
3095
|
+
for (const id2 of sessionIds) {
|
|
3096
|
+
if (included.has(id2)) continue;
|
|
3097
|
+
ordered.push(id2);
|
|
2032
3098
|
}
|
|
2033
3099
|
return ordered;
|
|
2034
3100
|
}
|
|
@@ -2042,22 +3108,22 @@
|
|
|
2042
3108
|
let order = reconciledSessionOrder(sessionIds, previousOrder);
|
|
2043
3109
|
if (sortByRecency) order.sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
2044
3110
|
else if (orderBy === "updated") {
|
|
2045
|
-
const promoted = sessionIds.filter((
|
|
2046
|
-
const session = list.byId[
|
|
2047
|
-
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]);
|
|
2048
3114
|
}).sort((a, b) => compareSessionRecency(a, b, list.byId));
|
|
2049
3115
|
if (promoted.length > 0) {
|
|
2050
3116
|
const promotedIds = new Set(promoted);
|
|
2051
|
-
order = [...promoted, ...order.filter((
|
|
3117
|
+
order = [...promoted, ...order.filter((id2) => !promotedIds.has(id2))];
|
|
2052
3118
|
}
|
|
2053
3119
|
}
|
|
2054
3120
|
const updatedAt = {};
|
|
2055
|
-
for (const
|
|
2056
|
-
const session = list.byId[
|
|
2057
|
-
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;
|
|
2058
3124
|
}
|
|
2059
|
-
const orderChanged = previousOrder === void 0 || order.length !== previousOrder.length || order.some((
|
|
2060
|
-
const timestampsChanged = Object.keys(updatedAt).length !== Object.keys(previousUpdatedAt).length || Object.entries(updatedAt).some(([
|
|
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);
|
|
2061
3127
|
return {
|
|
2062
3128
|
order,
|
|
2063
3129
|
updatedAt,
|
|
@@ -2104,9 +3170,9 @@
|
|
|
2104
3170
|
}
|
|
2105
3171
|
],
|
|
2106
3172
|
selectedIds: [groupBy, orderBy],
|
|
2107
|
-
onSelect: (
|
|
2108
|
-
if (
|
|
2109
|
-
else if (
|
|
3173
|
+
onSelect: (id2) => {
|
|
3174
|
+
if (id2 === "workspace" || id2 === "flat") onGroupPick(id2);
|
|
3175
|
+
else if (id2 === "manual" || id2 === "updated") onOrderPick(id2);
|
|
2110
3176
|
setOpen(false);
|
|
2111
3177
|
},
|
|
2112
3178
|
align: "end",
|
|
@@ -2165,7 +3231,7 @@
|
|
|
2165
3231
|
const expandedGroups = (0, react.useMemo)(() => Object.entries(groupExpansion).filter(([, expanded]) => expanded).map(([key]) => key), [groupExpansion]);
|
|
2166
3232
|
const ungroupedSessionIds = (0, react.useMemo)(() => {
|
|
2167
3233
|
const accounted = new Set(workspaces.flatMap((workspace) => workspace.sessionIds));
|
|
2168
|
-
return list.ids.filter((
|
|
3234
|
+
return list.ids.filter((id2) => list.byId[id2] !== void 0 && !accounted.has(id2));
|
|
2169
3235
|
}, [list, workspaces]);
|
|
2170
3236
|
(0, react.useEffect)(() => {
|
|
2171
3237
|
if (list.phase !== "ready") return;
|
|
@@ -2173,7 +3239,7 @@
|
|
|
2173
3239
|
previousOrderBy.current = orderBy;
|
|
2174
3240
|
const accounts = [...workspaces.map((workspace) => ({
|
|
2175
3241
|
key: workspace.workspaceId,
|
|
2176
|
-
sessionIds: workspace.sessionIds.filter((
|
|
3242
|
+
sessionIds: workspace.sessionIds.filter((id2) => list.byId[id2] !== void 0)
|
|
2177
3243
|
})), {
|
|
2178
3244
|
key: "",
|
|
2179
3245
|
sessionIds: ungroupedSessionIds
|
|
@@ -2188,7 +3254,7 @@
|
|
|
2188
3254
|
orderBy,
|
|
2189
3255
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2190
3256
|
});
|
|
2191
|
-
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);
|
|
2192
3258
|
}
|
|
2193
3259
|
}, [
|
|
2194
3260
|
list,
|
|
@@ -2250,10 +3316,10 @@
|
|
|
2250
3316
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2251
3317
|
const accountSessionIds = activeDrag.accountKey === "" ? orderedUngroupedSessionIds : orderedWorkspaces.find((workspace) => workspace.workspaceId === activeDrag.accountKey)?.sessionIds;
|
|
2252
3318
|
if (accountSessionIds === void 0) return;
|
|
2253
|
-
const nextOrder = accountSessionIds.filter((
|
|
3319
|
+
const nextOrder = accountSessionIds.filter((id2) => id2 !== activeDrag.sessionId);
|
|
2254
3320
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2255
3321
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2256
|
-
setSessionOrder(activeDrag.accountKey, nextOrder.map((
|
|
3322
|
+
setSessionOrder(activeDrag.accountKey, nextOrder.map((id2) => id2));
|
|
2257
3323
|
if (orderBy === "updated" || activeDrag.accountKey === "") return;
|
|
2258
3324
|
insertSessionBefore(activeDrag.accountKey, activeDrag.sessionId, anchor).catch((reason) => {
|
|
2259
3325
|
console.warn("session reorder rejected:", reason);
|
|
@@ -2462,7 +3528,7 @@
|
|
|
2462
3528
|
orderBy,
|
|
2463
3529
|
sortByRecency: orderBy === "updated" && (previousOrder === void 0 || switchedToUpdated)
|
|
2464
3530
|
});
|
|
2465
|
-
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);
|
|
2466
3532
|
}, [
|
|
2467
3533
|
list,
|
|
2468
3534
|
orderBy,
|
|
@@ -2473,8 +3539,8 @@
|
|
|
2473
3539
|
]);
|
|
2474
3540
|
const rows = (0, react.useMemo)(() => {
|
|
2475
3541
|
const byId = new Map(baseRows.map((row) => [row.id, row]));
|
|
2476
|
-
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((
|
|
2477
|
-
const row = byId.get(
|
|
3542
|
+
return reconciledSessionOrder(sessionIds, sessionOrderByAccount[FLAT_SESSION_ORDER_KEY]).flatMap((id2) => {
|
|
3543
|
+
const row = byId.get(id2);
|
|
2478
3544
|
return row === void 0 ? [] : [row];
|
|
2479
3545
|
});
|
|
2480
3546
|
}, [
|
|
@@ -2496,10 +3562,10 @@
|
|
|
2496
3562
|
const sourceIndex = rows.findIndex((row) => row.id === activeDrag.sessionId);
|
|
2497
3563
|
const anchorIndex = anchor === void 0 ? rows.length : rows.findIndex((row) => row.id === anchor);
|
|
2498
3564
|
if (sourceIndex !== -1 && (anchorIndex === sourceIndex || anchorIndex === sourceIndex + 1)) return;
|
|
2499
|
-
const nextOrder = rows.map((row) => row.id).filter((
|
|
3565
|
+
const nextOrder = rows.map((row) => row.id).filter((id2) => id2 !== activeDrag.sessionId);
|
|
2500
3566
|
const insertAt = anchor === void 0 ? nextOrder.length : nextOrder.indexOf(anchor);
|
|
2501
3567
|
nextOrder.splice(insertAt === -1 ? nextOrder.length : insertAt, 0, activeDrag.sessionId);
|
|
2502
|
-
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((
|
|
3568
|
+
setSessionOrder(FLAT_SESSION_ORDER_KEY, nextOrder.map((id2) => id2));
|
|
2503
3569
|
};
|
|
2504
3570
|
const now = Date.now();
|
|
2505
3571
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -3353,13 +4419,13 @@
|
|
|
3353
4419
|
]
|
|
3354
4420
|
});
|
|
3355
4421
|
}
|
|
3356
|
-
const ARCHIVE_TABS_CSS = ".dsham_archiveTabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_archiveTab{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;padding:12px 2px;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-weight:600;cursor:pointer}.dsham_archiveTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary)}.dsham_archiveTab:focus-visible{outline:2px solid var(--dsw-alias-state-
|
|
3357
|
-
const ARCHIVE_SETTINGS_CSS = ".dsham_settings{container-type:inline-size;min-width:0;box-sizing:border-box;width:min(100%,760px);margin:0 auto;padding:0 0 32px;color:var(--dsw-alias-label-primary)}.dsham_settingsHeader{display:flex;flex-direction:column;align-items:stretch;gap:16px;margin-bottom:16px}.dsham_settings h2{margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px;white-space:nowrap}.dsham_settingsIntro{margin:12px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px}.dsham_settingsDanger{display:inline-flex;align-items:center;gap:6px;min-height:32px;padding:0 12px;color:var(--dsw-alias-state-error-primary);background:transparent;border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsDanger:hover{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 20%,transparent)}.dsham_settingsToolbar{display:
|
|
3358
|
-
const ARCHIVE_SETTINGS_BATCH_CSS = ".dsham_settingsHeaderActions,.dsham_settingsGroupMeta{display:flex;align-items:center;gap:8px;flex:none;flex-wrap:wrap}.dsham_settingsRestoreAll{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;cursor:pointer;font:inherit;font-size:13px;font-weight:500}.dsham_settingsRestoreAll:hover{background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsRestoreAll:disabled,.dsham_settingsDanger:disabled,.dsham_settingsGroupMenu:disabled{cursor:not-allowed;opacity:.5}.dsham_settingsGroupMenu{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;color:var(--dsw-alias-label-tertiary);background:transparent;border:0;border-radius:8px;cursor:pointer}.dsham_settingsGroupMenu:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsStatus{margin-top:10px;color:var(--dsw-alias-label-secondary);font-size:12px}@media(max-width:720px){.dsham_settingsHeader{flex-direction:column}.dsham_settingsHeaderActions{align-self:flex-start}}";
|
|
3359
|
-
const ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS = ".dsham_settingsTitleRow{display:flex;align-items:center;gap:8px 12px;min-width:0;flex-wrap:wrap}.dsham_settingsLinks{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.dsham_settingsExternalLink{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dsham_settingsExternalLink:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dsham_settingsExternalLink:focus-visible{outline:2px solid var(--dsw-alias-state-
|
|
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}}";
|
|
3360
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}";
|
|
3361
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}";
|
|
3362
|
-
const ARCHIVE_SETTINGS_SELECTION_CSS = ".dsham_settingsSelection{margin:-8px 0 16px;padding:4px 0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsham_settingsSelectionMain{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;min-height:36px}.dsham_settingsSelectionSummary{display:flex;flex-wrap:wrap;align-items:center;gap:12px;min-width:0;max-width:100%}.dsham_settingsSelectionToggle{display:inline-flex;flex:none;white-space:nowrap;align-items:center;gap:12px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;cursor:pointer}.dsham_settingsCheckbox{flex:none;width:16px;height:16px;margin:0;accent-color:var(--dsw-alias-
|
|
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}";
|
|
3363
4429
|
const ARCHIVE_SETTINGS_LAYOUT_OVERRIDE = ".dsham_settings{margin:0 auto!important}@media(max-width:720px){.dsham_settings{margin:0 auto!important}}";
|
|
3364
4430
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify("dsh-archive-manager/ArchiveSettings.layout.css") + "]") === null) {
|
|
3365
4431
|
const tag = document.createElement("style");
|
|
@@ -3368,7 +4434,7 @@
|
|
|
3368
4434
|
tag.textContent = ARCHIVE_SETTINGS_LAYOUT_OVERRIDE + ARCHIVE_SETTINGS_DELETE_CONFIRM_CSS + ARCHIVE_WORKSPACE_CONFIRM_CSS;
|
|
3369
4435
|
document.head.appendChild(tag);
|
|
3370
4436
|
}
|
|
3371
|
-
function ArchiveProjectSelect({ id, value, options, onChange, "aria-label": ariaLabel }) {
|
|
4437
|
+
function ArchiveProjectSelect({ id: id2, value, options, onChange, disabled = false, "aria-label": ariaLabel }) {
|
|
3372
4438
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3373
4439
|
const selectedIndex = Math.max(0, options.findIndex((option) => option.value === value));
|
|
3374
4440
|
const [active, setActive] = (0, react.useState)(selectedIndex);
|
|
@@ -3401,9 +4467,10 @@
|
|
|
3401
4467
|
}, [open]);
|
|
3402
4468
|
(0, react.useEffect)(() => {
|
|
3403
4469
|
if (!open) return;
|
|
3404
|
-
document.getElementById(
|
|
3405
|
-
}, [active, open,
|
|
4470
|
+
document.getElementById(id2 + "-opt-" + String(active))?.scrollIntoView({ block: "nearest" });
|
|
4471
|
+
}, [active, open, id2]);
|
|
3406
4472
|
const choose = (next) => {
|
|
4473
|
+
if (disabled) return;
|
|
3407
4474
|
onChange(next);
|
|
3408
4475
|
setOpen(false);
|
|
3409
4476
|
};
|
|
@@ -3415,14 +4482,15 @@
|
|
|
3415
4482
|
className: "dsham_settingsFilter",
|
|
3416
4483
|
ref: rootRef,
|
|
3417
4484
|
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
3418
|
-
id,
|
|
4485
|
+
id: id2,
|
|
3419
4486
|
ref: triggerRef,
|
|
3420
4487
|
type: "button",
|
|
3421
4488
|
className: "dsham_selectTrigger",
|
|
4489
|
+
disabled,
|
|
3422
4490
|
"aria-label": ariaLabel,
|
|
3423
4491
|
"aria-haspopup": "listbox",
|
|
3424
4492
|
"aria-expanded": open,
|
|
3425
|
-
"aria-controls":
|
|
4493
|
+
"aria-controls": id2 + "-list",
|
|
3426
4494
|
onClick: () => setOpen((current) => !current),
|
|
3427
4495
|
onKeyDown: (event) => {
|
|
3428
4496
|
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
|
|
@@ -3445,12 +4513,12 @@
|
|
|
3445
4513
|
})
|
|
3446
4514
|
})]
|
|
3447
4515
|
}), open ? (0, react_jsx_runtime.jsx)("div", {
|
|
3448
|
-
id:
|
|
4516
|
+
id: id2 + "-list",
|
|
3449
4517
|
ref: listRef,
|
|
3450
4518
|
className: "dsham_selectMenu",
|
|
3451
4519
|
role: "listbox",
|
|
3452
4520
|
tabIndex: 0,
|
|
3453
|
-
"aria-activedescendant":
|
|
4521
|
+
"aria-activedescendant": id2 + "-opt-" + String(active),
|
|
3454
4522
|
onKeyDown: (event) => {
|
|
3455
4523
|
if (event.key === "ArrowDown") {
|
|
3456
4524
|
event.preventDefault();
|
|
@@ -3486,7 +4554,7 @@
|
|
|
3486
4554
|
}
|
|
3487
4555
|
},
|
|
3488
4556
|
children: options.map((option, index) => (0, react_jsx_runtime.jsx)("button", {
|
|
3489
|
-
id:
|
|
4557
|
+
id: id2 + "-opt-" + String(index),
|
|
3490
4558
|
type: "button",
|
|
3491
4559
|
role: "option",
|
|
3492
4560
|
className: "dsham_selectOption",
|
|
@@ -3540,6 +4608,33 @@
|
|
|
3540
4608
|
onChange
|
|
3541
4609
|
});
|
|
3542
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
|
+
}
|
|
3543
4638
|
function ArchivedGroupActions({ group, busy, onArchive, onRestore, onDelete, t }) {
|
|
3544
4639
|
const [open, setOpen] = (0, react.useState)(false);
|
|
3545
4640
|
const ungrouped = group.key === ARCHIVE_UNGROUPED_KEY;
|
|
@@ -3562,12 +4657,12 @@
|
|
|
3562
4657
|
open,
|
|
3563
4658
|
onClose: () => setOpen(false),
|
|
3564
4659
|
items,
|
|
3565
|
-
onSelect: (
|
|
4660
|
+
onSelect: (id2) => {
|
|
3566
4661
|
setOpen(false);
|
|
3567
4662
|
if (busy) return;
|
|
3568
|
-
if (
|
|
3569
|
-
else if (
|
|
3570
|
-
else if (
|
|
4663
|
+
if (id2 === "archive") onArchive?.();
|
|
4664
|
+
else if (id2 === "restore") onRestore();
|
|
4665
|
+
else if (id2 === "delete") onDelete();
|
|
3571
4666
|
},
|
|
3572
4667
|
portal: true,
|
|
3573
4668
|
anchor: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -3589,21 +4684,21 @@
|
|
|
3589
4684
|
if (target.scope === "all") return ids;
|
|
3590
4685
|
if (target.scope === "sessions") {
|
|
3591
4686
|
const selected = new Set(target.sessionIds ?? []);
|
|
3592
|
-
return ids.filter((
|
|
4687
|
+
return ids.filter((id2) => selected.has(id2));
|
|
3593
4688
|
}
|
|
3594
4689
|
if (target.scope === "workspace") {
|
|
3595
4690
|
const accounted2 = new Set(items.find((workspace) => workspace.workspaceId === target.workspaceId)?.sessionIds ?? []);
|
|
3596
|
-
return ids.filter((
|
|
4691
|
+
return ids.filter((id2) => accounted2.has(id2));
|
|
3597
4692
|
}
|
|
3598
4693
|
const accounted = new Set(items.flatMap((workspace) => workspace.sessionIds));
|
|
3599
|
-
return ids.filter((
|
|
4694
|
+
return ids.filter((id2) => !accounted.has(id2));
|
|
3600
4695
|
}
|
|
3601
4696
|
function archivedSessionIdsInGroups(groups) {
|
|
3602
4697
|
return [...new Set(groups.flatMap((group) => group.sessions.map((session) => session.id)))];
|
|
3603
4698
|
}
|
|
3604
4699
|
function pruneArchivedSelection(selectedSessionIds, archivedSessionIds) {
|
|
3605
4700
|
const archived = new Set(archivedSessionIds);
|
|
3606
|
-
return [...new Set(selectedSessionIds)].filter((
|
|
4701
|
+
return [...new Set(selectedSessionIds)].filter((id2) => archived.has(id2));
|
|
3607
4702
|
}
|
|
3608
4703
|
function toggleArchivedSelection(selectedSessionIds, sessionIds, checked) {
|
|
3609
4704
|
const selected = new Set(selectedSessionIds);
|
|
@@ -3642,23 +4737,27 @@
|
|
|
3642
4737
|
sessions: []
|
|
3643
4738
|
}));
|
|
3644
4739
|
const ungrouped = [];
|
|
3645
|
-
for (const
|
|
3646
|
-
const session = byId[
|
|
4740
|
+
for (const id2 of archivedSessionIds) {
|
|
4741
|
+
const session = byId[id2];
|
|
3647
4742
|
if (session === void 0 || session.origin === "subagent") continue;
|
|
3648
|
-
const group = byWorkspace.find((workspace) => workspace.ids.has(
|
|
4743
|
+
const group = byWorkspace.find((workspace) => workspace.ids.has(id2));
|
|
3649
4744
|
(group === void 0 ? ungrouped : group.sessions).push(session);
|
|
3650
4745
|
}
|
|
3651
4746
|
const result = byWorkspace.filter((group) => group.sessions.length > 0);
|
|
3652
4747
|
if (ungrouped.length > 0) result.push({ key: ARCHIVE_UNGROUPED_KEY, title: ungroupedLabel, sessions: ungrouped });
|
|
3653
4748
|
return result;
|
|
3654
4749
|
}
|
|
3655
|
-
function sortArchivedGroups(groups, sortBy, createdAtById, t) {
|
|
4750
|
+
function sortArchivedGroups(groups, sortBy, createdAtById, t, details = {}) {
|
|
3656
4751
|
const compareText = (left, right) => String(left).localeCompare(String(right), void 0, { numeric: true, sensitivity: "base" });
|
|
3657
4752
|
const timestampOf = (session) => {
|
|
3658
|
-
const value = sortBy === "created" ? createdAtById[session.id] : session.updatedAt;
|
|
4753
|
+
const value = sortBy === "created" ? details[session.id]?.createdAt ?? createdAtById[session.id] : session.updatedAt;
|
|
3659
4754
|
return typeof value === "number" && Number.isFinite(value) ? value : Number.NEGATIVE_INFINITY;
|
|
3660
4755
|
};
|
|
3661
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
|
+
}
|
|
3662
4761
|
if (sortBy !== "alphabetical") {
|
|
3663
4762
|
const byTime = timestampOf(right) - timestampOf(left);
|
|
3664
4763
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3667,6 +4766,10 @@
|
|
|
3667
4766
|
};
|
|
3668
4767
|
const result = groups.map((group) => ({ ...group, sessions: [...group.sessions].sort(compareSessions) }));
|
|
3669
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
|
+
}
|
|
3670
4773
|
if (sortBy !== "alphabetical") {
|
|
3671
4774
|
const byTime = timestampOf(right.sessions[0]) - timestampOf(left.sessions[0]);
|
|
3672
4775
|
if (Number.isFinite(byTime) && byTime !== 0) return byTime;
|
|
@@ -3675,6 +4778,11 @@
|
|
|
3675
4778
|
});
|
|
3676
4779
|
}
|
|
3677
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",
|
|
3678
4786
|
"archives.archiveProject": "\u5F52\u6863\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
3679
4787
|
"archives.archiveUngrouped": "\u5F52\u6863\u5168\u90E8\u672A\u5206\u7EC4\u804A\u5929",
|
|
3680
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",
|
|
@@ -3684,13 +4792,14 @@
|
|
|
3684
4792
|
"archives.searchUnarchived": "\u641C\u7D22\u672A\u5F52\u6863\u804A\u5929",
|
|
3685
4793
|
"archives.emptyUnarchived": "\u6682\u65E0\u672A\u5F52\u6863\u4F1A\u8BDD\u3002",
|
|
3686
4794
|
"archives.archiveSelected": "\u5F52\u6863",
|
|
3687
|
-
"archives.openSession": "\u6253\u5F00
|
|
4795
|
+
"archives.openSession": "\u6253\u5F00",
|
|
4796
|
+
"archives.moreActions": "\u66F4\u591A\u64CD\u4F5C",
|
|
3688
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",
|
|
3689
4798
|
"archives.archiveSuccess": "\u5DF2\u5F52\u6863 {n} \u6761\u4F1A\u8BDD\u3002",
|
|
3690
4799
|
"archives.archiveBatchFailed": "\u6279\u91CF\u5F52\u6863\u5931\u8D25\uFF1A{detail}",
|
|
3691
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",
|
|
3692
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",
|
|
3693
|
-
"archives.restoreOpen": "\u6062\u590D\
|
|
4802
|
+
"archives.restoreOpen": "\u6062\u590D\u6253\u5F00",
|
|
3694
4803
|
"archives.selectedCount": "\u5DF2\u9009 {n} \u6761",
|
|
3695
4804
|
"archives.selectionHiddenHint": "\u542B\u5F53\u524D\u672A\u663E\u793A\u7684 {hidden} \u6761\uFF0C\u4E5F\u5C06\u53C2\u4E0E\u64CD\u4F5C",
|
|
3696
4805
|
"archives.clearSelectionShort": "\u6E05\u7A7A",
|
|
@@ -3731,7 +4840,7 @@
|
|
|
3731
4840
|
"archives.viewProject": "GitHub",
|
|
3732
4841
|
"archives.feedback": "\u95EE\u9898\u53CD\u9988",
|
|
3733
4842
|
"archives.empty": "\u6682\u65E0\u5DF2\u5F52\u6863\u4F1A\u8BDD",
|
|
3734
|
-
"archives.emptyFiltered": "\u6CA1\u6709\
|
|
4843
|
+
"archives.emptyFiltered": "\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u804A\u5929",
|
|
3735
4844
|
"archives.searchPlaceholder": "\u641C\u7D22\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3736
4845
|
"archives.sortBy": "\u6392\u5E8F\u65B9\u5F0F",
|
|
3737
4846
|
"archives.sortUpdated": "\u66F4\u65B0\u65F6\u95F4",
|
|
@@ -3745,24 +4854,20 @@
|
|
|
3745
4854
|
"archives.restoreSelected": "\u6062\u590D\u6240\u9009",
|
|
3746
4855
|
"archives.deleteSelected": "\u5220\u9664\u6240\u9009",
|
|
3747
4856
|
"archives.timestamp": "{date}\uFF0C{time}",
|
|
3748
|
-
"archives.
|
|
3749
|
-
"archives.restoreProject": "\u6062\u590D\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
4857
|
+
"archives.restoreProject": "\u6062\u590D\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3750
4858
|
"archives.restoreUngrouped": "\u5168\u90E8\u6062\u590D",
|
|
3751
|
-
"archives.deleteProject": "\u5220\u9664\
|
|
4859
|
+
"archives.deleteProject": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3752
4860
|
"archives.deleteUngrouped": "\u5168\u90E8\u5220\u9664",
|
|
3753
4861
|
"archives.projectActions": "\u9879\u76EE\u201C{name}\u201D\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3754
4862
|
"archives.ungroupedActions": "\u672A\u5206\u7EC4\u804A\u5929\u7684\u5F52\u6863\u64CD\u4F5C",
|
|
3755
4863
|
"archives.restoreSuccess": "\u5DF2\u6062\u590D {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u3002",
|
|
3756
4864
|
"archives.restoreBatchFailed": "\u6279\u91CF\u6062\u590D\u5931\u8D25\uFF1A{detail}",
|
|
3757
|
-
"archives.deleteAll": "\u5168\u90E8\u5220\u9664",
|
|
3758
|
-
"archives.deleteAllTitle": "\u5220\u9664\u5168\u90E8\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3759
|
-
"archives.deleteAllDesc": "\u5C06\u6C38\u4E45\u5220\u9664\u5168\u90E8 {n} \u4E2A\u5DF2\u5F52\u6863\u804A\u5929\u53CA\u5176\u5B50\u4EE3\u7406\uFF08\u542B\u6B63\u5728\u8FD0\u884C\u7684\uFF09\u548C\u8BB0\u5F55\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002",
|
|
3760
4865
|
"archives.deleteSelectedTitle": "\u5220\u9664\u6240\u9009\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3761
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",
|
|
3762
4867
|
"archives.deleteSelectedConfirm": "\u5220\u9664\u6240\u9009\u804A\u5929",
|
|
3763
4868
|
"archives.deleteProjectTitle": "\u5220\u9664\u201C{name}\u201D\u4E2D\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3764
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",
|
|
3765
|
-
"archives.deleteProjectConfirm": "\u5220\u9664\
|
|
4870
|
+
"archives.deleteProjectConfirm": "\u5220\u9664\u9879\u76EE\u5168\u90E8\u804A\u5929",
|
|
3766
4871
|
"archives.deleteUngroupedTitle": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3767
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",
|
|
3768
4873
|
"archives.deleteUngroupedConfirm": "\u5220\u9664\u672A\u5206\u7EC4\u7684\u5168\u90E8\u804A\u5929",
|
|
@@ -3823,6 +4928,12 @@
|
|
|
3823
4928
|
"time.ago": "{t}\u524D"
|
|
3824
4929
|
};
|
|
3825
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",
|
|
3826
4937
|
"archives.archiveProject": "Archive all chats in this project",
|
|
3827
4938
|
"archives.archiveUngrouped": "Archive all ungrouped chats",
|
|
3828
4939
|
"archives.archiveProjectDesc": "Archive all {n} unarchived sessions in \u201C{name}\u201D, regardless of the current search filter. You can restore them in Archived.",
|
|
@@ -3879,7 +4990,7 @@
|
|
|
3879
4990
|
"archives.viewProject": "GitHub",
|
|
3880
4991
|
"archives.feedback": "Issues",
|
|
3881
4992
|
"archives.empty": "No archived sessions.",
|
|
3882
|
-
"archives.emptyFiltered": "No
|
|
4993
|
+
"archives.emptyFiltered": "No chats match your filters.",
|
|
3883
4994
|
"archives.searchPlaceholder": "Search archived chats",
|
|
3884
4995
|
"archives.sortBy": "Sort archived chats",
|
|
3885
4996
|
"archives.sortUpdated": "Last updated",
|
|
@@ -3893,7 +5004,6 @@
|
|
|
3893
5004
|
"archives.restoreSelected": "Restore selected",
|
|
3894
5005
|
"archives.deleteSelected": "Delete selected",
|
|
3895
5006
|
"archives.timestamp": "{date}, {time}",
|
|
3896
|
-
"archives.restoreAll": "Restore all",
|
|
3897
5007
|
"archives.restoreProject": "Restore all chats in this project",
|
|
3898
5008
|
"archives.restoreUngrouped": "Restore all",
|
|
3899
5009
|
"archives.deleteProject": "Delete all chats in this project",
|
|
@@ -3902,9 +5012,6 @@
|
|
|
3902
5012
|
"archives.ungroupedActions": "Archive actions for ungrouped chats",
|
|
3903
5013
|
"archives.restoreSuccess": "Restored {n} archived chats.",
|
|
3904
5014
|
"archives.restoreBatchFailed": "Could not restore the archived chats: {detail}",
|
|
3905
|
-
"archives.deleteAll": "Delete all",
|
|
3906
|
-
"archives.deleteAllTitle": "Delete all archived chats",
|
|
3907
|
-
"archives.deleteAllDesc": "This permanently deletes all {n} archived chats, their child agents (including any that are still running), and their records. This cannot be undone.",
|
|
3908
5015
|
"archives.deleteSelectedTitle": "Delete selected archived chats",
|
|
3909
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.",
|
|
3910
5017
|
"archives.deleteSelectedConfirm": "Delete selected chats",
|
|
@@ -4011,13 +5118,13 @@
|
|
|
4011
5118
|
const archivedSessionIds = [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
4012
5119
|
return {
|
|
4013
5120
|
archivedSessionIds,
|
|
4014
|
-
archivedSessionIdsAdded: archivedSessionIds.filter((
|
|
5121
|
+
archivedSessionIdsAdded: archivedSessionIds.filter((id2) => !before.has(id2))
|
|
4015
5122
|
};
|
|
4016
5123
|
}
|
|
4017
5124
|
async function unarchiveSessionsViaOfficial(workspaces, sessionIds, refresh, unarchive) {
|
|
4018
5125
|
const before = new Set(workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []);
|
|
4019
5126
|
const seen = /* @__PURE__ */ new Set();
|
|
4020
|
-
const run = typeof unarchive === "function" ? unarchive : (
|
|
5127
|
+
const run = typeof unarchive === "function" ? unarchive : (id2) => workspaces.unarchiveSession(id2);
|
|
4021
5128
|
let archivedSessionIds;
|
|
4022
5129
|
for (const sessionId of sessionIds) {
|
|
4023
5130
|
if (typeof sessionId !== "string" || sessionId.length === 0 || seen.has(sessionId)) continue;
|
|
@@ -4029,7 +5136,7 @@
|
|
|
4029
5136
|
archivedSessionIds ??= [...workspaces.list?.getSnapshot?.()?.archivedSessionIds ?? []];
|
|
4030
5137
|
return {
|
|
4031
5138
|
archivedSessionIds,
|
|
4032
|
-
unarchivedSessionIds: [...before].filter((
|
|
5139
|
+
unarchivedSessionIds: [...before].filter((id2) => !archivedSessionIds.includes(id2))
|
|
4033
5140
|
};
|
|
4034
5141
|
}
|
|
4035
5142
|
async function apply(ctx) {
|
|
@@ -4054,6 +5161,7 @@
|
|
|
4054
5161
|
linksSelector: ".dsham_settingsLinks",
|
|
4055
5162
|
zhName: "\u5F52\u6863\u4F1A\u8BDD",
|
|
4056
5163
|
enName: "Archived sessions",
|
|
5164
|
+
getLanguage: () => ctx.locale.bind(NS)("locale.language"),
|
|
4057
5165
|
createIcon: createPluginUpdateIcon
|
|
4058
5166
|
}), "dsh-archive-manager: plugin update ui");
|
|
4059
5167
|
const uiWorkspaceAt = () => ctx.get("uiWorkspace");
|
|
@@ -4096,6 +5204,43 @@
|
|
|
4096
5204
|
}
|
|
4097
5205
|
};
|
|
4098
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
|
+
});
|
|
4099
5244
|
const unarchiveSession = async (sessionId) => {
|
|
4100
5245
|
await unarchiveOne(sessionId);
|
|
4101
5246
|
await refreshSessionList();
|
|
@@ -4238,6 +5383,15 @@
|
|
|
4238
5383
|
openConversation,
|
|
4239
5384
|
focusSessionWorkspace,
|
|
4240
5385
|
viewState: archiveViewState,
|
|
5386
|
+
favoriteSessions,
|
|
5387
|
+
setSessionFavorite,
|
|
5388
|
+
organizeBatch,
|
|
5389
|
+
diagnoseSession,
|
|
5390
|
+
repairSession,
|
|
5391
|
+
sessionDetails,
|
|
5392
|
+
searchSessionContent,
|
|
5393
|
+
searchArchivedContent,
|
|
5394
|
+
previewArchivedSession,
|
|
4241
5395
|
t: ctx.locale.bind(NS)
|
|
4242
5396
|
})
|
|
4243
5397
|
}, ArchivedSessionsSection));
|
|
@@ -4247,6 +5401,7 @@
|
|
|
4247
5401
|
ArchiveSelectionToolbar,
|
|
4248
5402
|
ArchivedSessionsSection,
|
|
4249
5403
|
zh,
|
|
5404
|
+
en,
|
|
4250
5405
|
displayTitle,
|
|
4251
5406
|
sessionVisible,
|
|
4252
5407
|
indexSubagentDescendants,
|