@michengai/dsh-archive-manager 0.1.38 → 0.1.40
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 +12 -0
- package/CHANGELOG.zh-CN.md +12 -0
- package/README.md +63 -112
- package/README.zh-CN.md +64 -113
- package/cordis.patch.yml +3 -3
- package/lib/archive-experience.js +68 -0
- package/lib/client.js +202 -389
- package/lib/workspace.js +374 -178
- package/package.json +3 -1
package/lib/client.js
CHANGED
|
@@ -1,4 +1,133 @@
|
|
|
1
1
|
(() => {
|
|
2
|
+
// src/archive-experience.js
|
|
3
|
+
var ArchiveNavigationError = class extends Error {
|
|
4
|
+
constructor(code) {
|
|
5
|
+
super(code);
|
|
6
|
+
this.name = "ArchiveNavigationError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
function formatArchiveNavigationError(error, t) {
|
|
11
|
+
return error instanceof ArchiveNavigationError ? t(`archives.${error.code}`) : String(error?.message ?? error);
|
|
12
|
+
}
|
|
13
|
+
async function openArchivedConversation(actions, sessionId, restore, isActive = () => true) {
|
|
14
|
+
if (restore) await actions.restore(sessionId);
|
|
15
|
+
if (isActive()) await actions.open(sessionId);
|
|
16
|
+
}
|
|
17
|
+
function allowArchivedNavigation(navigation, sessions, workspaces, { onOpened = () => {
|
|
18
|
+
}, warn = (...args) => console.warn(...args) } = {}) {
|
|
19
|
+
let allowed;
|
|
20
|
+
const original = navigation?.clearArchivedCurrent;
|
|
21
|
+
const descriptor = navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent");
|
|
22
|
+
const wrapped = function(...args) {
|
|
23
|
+
const current = sessions.list.getSnapshot().current;
|
|
24
|
+
if (current === allowed && current !== void 0 && workspaces.list.getSnapshot().archivedSessionIds.includes(current)) return false;
|
|
25
|
+
allowed = void 0;
|
|
26
|
+
return original.apply(this, args);
|
|
27
|
+
};
|
|
28
|
+
const ownsWrapper = () => navigation && Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent")?.value === wrapped;
|
|
29
|
+
if (typeof original === "function") {
|
|
30
|
+
try {
|
|
31
|
+
navigation.clearArchivedCurrent = wrapped;
|
|
32
|
+
if (!ownsWrapper()) throw new Error("\u5BFC\u822A\u65B9\u6CD5\u672A\u63A5\u7EB3\u5F52\u6863\u9002\u914D");
|
|
33
|
+
} catch (error) {
|
|
34
|
+
warn("archive-manager: \u65E0\u6CD5\u9002\u914D\u5F52\u6863\u5BFC\u822A\uFF0C\u8BF7\u6062\u590D\u4F1A\u8BDD\u540E\u6253\u5F00\u3002", error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
open(id) {
|
|
39
|
+
allowed = id;
|
|
40
|
+
try {
|
|
41
|
+
if (typeof original === "function" && !ownsWrapper() && workspaces.list.getSnapshot().archivedSessionIds.includes(id)) {
|
|
42
|
+
warn("archive-manager: \u5F52\u6863\u5BFC\u822A\u9002\u914D\u4E0D\u53EF\u7528\u6216\u5DF2\u88AB\u66FF\u6362\u3002");
|
|
43
|
+
throw new ArchiveNavigationError("navigationUnavailable");
|
|
44
|
+
}
|
|
45
|
+
sessions.open(id);
|
|
46
|
+
if (sessions.list.getSnapshot().current !== id) {
|
|
47
|
+
warn("archive-manager: \u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\u3002", { cleanupAvailable: typeof original === "function" });
|
|
48
|
+
throw new ArchiveNavigationError("sessionNotRetained");
|
|
49
|
+
}
|
|
50
|
+
onOpened();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
allowed = void 0;
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
dispose() {
|
|
57
|
+
allowed = void 0;
|
|
58
|
+
if (!navigation || Object.getOwnPropertyDescriptor(navigation, "clearArchivedCurrent")?.value !== wrapped) return;
|
|
59
|
+
if (descriptor) Object.defineProperty(navigation, "clearArchivedCurrent", descriptor);
|
|
60
|
+
else delete navigation.clearArchivedCurrent;
|
|
61
|
+
original.call(navigation);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/directory-flow-slot.js
|
|
67
|
+
function mirrorDirectoryFlow(ctx, target) {
|
|
68
|
+
const source = "sidebar.workspaces.directoryFlow";
|
|
69
|
+
return ctx.slots.inject(target, () => ctx.effect(() => {
|
|
70
|
+
const mounted = /* @__PURE__ */ new Map();
|
|
71
|
+
let registrant;
|
|
72
|
+
const release = (entry, dispose) => {
|
|
73
|
+
mounted.delete(entry);
|
|
74
|
+
try {
|
|
75
|
+
dispose();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error(`archive-manager: \u6E05\u7406\u76EE\u5F55\u955C\u50CF\u5931\u8D25 ${source} -> ${target}\uFF08${entry.registrant ?? "\u672A\u77E5\u6765\u6E90"}\uFF09`, error);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const clearMounted = () => {
|
|
81
|
+
for (const [entry, dispose] of mounted) release(entry, dispose);
|
|
82
|
+
};
|
|
83
|
+
const reconcile = () => {
|
|
84
|
+
registrant = void 0;
|
|
85
|
+
const entries = ctx.slots.entries(source);
|
|
86
|
+
for (const [entry, dispose] of mounted) {
|
|
87
|
+
if (!entries.includes(entry)) {
|
|
88
|
+
release(entry, dispose);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
if (mounted.has(entry)) continue;
|
|
93
|
+
if (Object.keys(entry.children ?? {}).length > 0) {
|
|
94
|
+
console.warn("archive-manager: \u4E0D\u652F\u6301\u5E26\u5B50\u63D2\u69FD\u7684\u76EE\u5F55\u7EC4\u4EF6\uFF0C\u8BF7\u4F7F\u7528\u5B98\u65B9\u9996\u9875\u5165\u53E3");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
registrant = entry.registrant;
|
|
98
|
+
mounted.set(entry, ctx.slots.register({
|
|
99
|
+
...entry.options,
|
|
100
|
+
name: target,
|
|
101
|
+
registrant: entry.registrant,
|
|
102
|
+
inject: entry.inject,
|
|
103
|
+
store: entry.store,
|
|
104
|
+
locale: entry.locale
|
|
105
|
+
}, entry.component));
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const unsubscribe = ctx.on("slots/changed", (key) => {
|
|
109
|
+
if (key !== source) return;
|
|
110
|
+
try {
|
|
111
|
+
reconcile();
|
|
112
|
+
} catch (error) {
|
|
113
|
+
clearMounted();
|
|
114
|
+
console.error(`archive-manager: \u540C\u6B65\u76EE\u5F55\u955C\u50CF\u5931\u8D25 ${source} -> ${target}\uFF08${registrant ?? "\u672A\u77E5\u6765\u6E90"}\uFF09\uFF1B\u8BF7\u4F7F\u7528\u5B98\u65B9\u9996\u9875\u5165\u53E3\uFF0C\u540E\u7EED\u6E90\u63D2\u69FD\u53D8\u5316\u65F6\u91CD\u8BD5`, error);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
reconcile();
|
|
119
|
+
} catch (error) {
|
|
120
|
+
unsubscribe();
|
|
121
|
+
clearMounted();
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
return () => {
|
|
125
|
+
unsubscribe();
|
|
126
|
+
clearMounted();
|
|
127
|
+
};
|
|
128
|
+
}, "dsh-archive-manager: official directory flow"));
|
|
129
|
+
}
|
|
130
|
+
|
|
2
131
|
// src/plugin-update-ui.js
|
|
3
132
|
var UPDATE_HEADER = "x-michengai-plugin-update";
|
|
4
133
|
var STYLE_ID = "michengai-plugin-update-ui";
|
|
@@ -600,20 +729,48 @@
|
|
|
600
729
|
function GithubMark16() {
|
|
601
730
|
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" }) });
|
|
602
731
|
}
|
|
603
|
-
function
|
|
732
|
+
function ArchivedSessionsSection({ sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, openConversation, viewState, close, t }) {
|
|
604
733
|
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
605
734
|
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
606
735
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
|
|
607
736
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
608
737
|
const [error, setError] = (0, react.useState)(null);
|
|
609
738
|
const [notice, setNotice] = (0, react.useState)(null);
|
|
610
|
-
const [query, setQuery] = (0, react.useState)("");
|
|
611
|
-
const [project, setProject] = (0, react.useState)("all");
|
|
612
|
-
const [sortBy, setSortBy] = (0, react.useState)("updated");
|
|
739
|
+
const [query, setQuery] = (0, react.useState)(viewState?.query ?? "");
|
|
740
|
+
const [project, setProject] = (0, react.useState)(viewState?.project ?? "all");
|
|
741
|
+
const [sortBy, setSortBy] = (0, react.useState)(viewState?.sortBy ?? "updated");
|
|
613
742
|
const [createdAtById, setCreatedAtById] = (0, react.useState)({});
|
|
614
743
|
const [unarchivingSessionIds, setUnarchivingSessionIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
615
744
|
const unarchivingSessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
616
745
|
const [selectedSessionIds, setSelectedSessionIds] = (0, react.useState)([]);
|
|
746
|
+
const navigationActive = (0, react.useRef)(true);
|
|
747
|
+
const navigationPending = (0, react.useRef)(false);
|
|
748
|
+
(0, react.useEffect)(() => {
|
|
749
|
+
navigationActive.current = true;
|
|
750
|
+
return () => {
|
|
751
|
+
navigationActive.current = false;
|
|
752
|
+
};
|
|
753
|
+
}, []);
|
|
754
|
+
const viewConversation = async (session, restore = false) => {
|
|
755
|
+
if (busy || navigationPending.current) return;
|
|
756
|
+
navigationPending.current = true;
|
|
757
|
+
setBusy(true);
|
|
758
|
+
setError(null);
|
|
759
|
+
try {
|
|
760
|
+
await openArchivedConversation({ restore: unarchiveSession, open: async (id) => {
|
|
761
|
+
await openConversation(id);
|
|
762
|
+
if (navigationActive.current) close?.();
|
|
763
|
+
} }, session.id, restore, () => navigationActive.current);
|
|
764
|
+
} catch (reason) {
|
|
765
|
+
if (navigationActive.current) setError(formatArchiveNavigationError(reason, t));
|
|
766
|
+
} finally {
|
|
767
|
+
navigationPending.current = false;
|
|
768
|
+
if (navigationActive.current) setBusy(false);
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
(0, react.useEffect)(() => {
|
|
772
|
+
if (viewState) Object.assign(viewState, { query, project, sortBy });
|
|
773
|
+
}, [query, project, sortBy, viewState]);
|
|
617
774
|
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, workspaceState.archivedSessionIds, t("group.ungrouped")), [sessions.byId, workspaceState, t]);
|
|
618
775
|
const sortedGroups = (0, react.useMemo)(() => sortArchivedGroups(groups, sortBy, createdAtById, t), [groups, sortBy, createdAtById, t]);
|
|
619
776
|
(0, react.useEffect)(() => {
|
|
@@ -754,7 +911,7 @@
|
|
|
754
911
|
children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
755
912
|
className: "dsham_settingsSelectionToggle",
|
|
756
913
|
children: [(0, react_jsx_runtime.jsx)(ArchiveSelectionCheckbox, { checked: allVisibleSelected, indeterminate: selectedVisibleCount > 0 && !allVisibleSelected, disabled: busy || visibleSessionIds.length === 0, label: t("archives.selectAllFiltered"), onChange: (event) => toggleVisibleSelection(event.target.checked) }), t("archives.selectAllFiltered")]
|
|
757
|
-
}), (0, react_jsx_runtime.jsx)("span", { className: "dsham_settingsSelectionCount", children: t("archives.
|
|
914
|
+
}), (0, react_jsx_runtime.jsx)("span", { className: "dsham_settingsSelectionCount", children: t("archives.selectedScope", { n: selectedSessionIds.length, hidden: selectedSessionIds.length - selectedVisibleCount }) }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction", disabled: busy || selectedSessionIds.length === 0, onClick: () => setSelectedSessionIds([]), children: t("archives.clearSelection") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction", disabled: busy || selectedSessionIds.length === 0, onClick: onSelectedUnarchive, children: t("archives.restoreSelected") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsSelectionAction dsham_settingsSelectionDelete", disabled: busy || selectedSessionIds.length === 0, onClick: () => setDeleteTarget({ kind: "batch", target: { scope: "sessions", sessionIds: selectedSessionIds }, count: selectedSessionIds.length }), children: t("archives.deleteSelected") })]
|
|
758
915
|
}), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.empty") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
759
916
|
const target = archivedBatchTargetForGroup(group.key);
|
|
760
917
|
const count = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length;
|
|
@@ -769,7 +926,7 @@
|
|
|
769
926
|
className: "dsham_settingsRow",
|
|
770
927
|
children: [(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) }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsContent", children: [(0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsTitle", children: displayTitle(session, t) }), (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsMeta", children: archiveTimeLabel(session.updatedAt, t) })] }), (0, react_jsx_runtime.jsxs)("div", {
|
|
771
928
|
className: "dsham_settingsActions",
|
|
772
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => onUnarchive(session.id), children: t("menu.unarchive") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsDelete", disabled: busy || unarchivingSessionIds.has(session.id), "aria-label": t("menu.deleteSession"), onClick: () => setDeleteTarget({ kind: "session", session }), children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) })]
|
|
929
|
+
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session), children: t("archives.viewConversation") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => viewConversation(session, true), children: t("archives.restoreOpen") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => onUnarchive(session.id), children: t("menu.unarchive") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsDelete", disabled: busy || unarchivingSessionIds.has(session.id), "aria-label": t("menu.deleteSession"), onClick: () => setDeleteTarget({ kind: "session", session }), children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) })]
|
|
773
930
|
})]
|
|
774
931
|
}, session.id))
|
|
775
932
|
})]
|
|
@@ -1045,7 +1202,7 @@
|
|
|
1045
1202
|
};
|
|
1046
1203
|
}
|
|
1047
1204
|
const css$2 = '.YDXeBa_projectRow,.YDXeBa_sessionRow{cursor:pointer;user-select:none;color:var(--dsw-alias-label-primary);border-radius:8px;align-items:center;gap:6px;padding:0 8px;display:flex}.YDXeBa_projectRow:hover,.YDXeBa_sessionRow:hover,.YDXeBa_sessionRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultRow{box-sizing:border-box;cursor:pointer;text-align:left;width:100%;min-height:48px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;flex-direction:column;align-items:stretch;padding:4px 8px;display:flex}.YDXeBa_searchResultRow:hover,.YDXeBa_searchResultRow.YDXeBa_selected{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_searchResultHeading{align-items:center;min-width:0;display:flex}.YDXeBa_searchResultTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;margin-left:4px;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_searchResultMeta{align-items:center;gap:6px;min-width:0;margin-left:20px;display:flex}.YDXeBa_searchResultWorkspace,.YDXeBa_searchResultSnippet{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px;overflow:hidden}.YDXeBa_searchResultWorkspace{max-width:40%;color:var(--dsw-alias-label-tertiary);flex:none}.YDXeBa_searchResultSnippet{min-width:0;color:var(--dsw-alias-label-secondary);flex:1}.YDXeBa_projectRow{box-sizing:border-box;align-items:center;height:34px}.YDXeBa_projectRow .YDXeBa_rowActions{height:20px}.YDXeBa_sessionRow{height:32px;animation:YDXeBa_row-in .15s var(--ds-ease-in-out);gap:0}.YDXeBa_sessionRow .YDXeBa_title{margin:0 6px 0 4px}.YDXeBa_flatSessionRowWithoutStatus .YDXeBa_title{margin-left:0}@keyframes YDXeBa_row-in{0%{opacity:0}}.YDXeBa_slot{width:16px;height:20px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.YDXeBa_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.YDXeBa_folderActive{color:var(--dsw-alias-state-business-primary)}.YDXeBa_projectRow .YDXeBa_chevron{display:none}.YDXeBa_projectRow:hover .YDXeBa_chevron{display:inline-flex}.YDXeBa_projectRow:hover .YDXeBa_folder{display:none}.YDXeBa_arrow{transition:transform .15s var(--ds-ease-in-out)}.YDXeBa_arrowOpen{transform:rotate(90deg)}.YDXeBa_projectText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.YDXeBa_title{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;line-height:20px;overflow:hidden}.YDXeBa_renameInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);min-width:0;color:inherit;border-radius:4px;outline:none;padding:0 2px;font-size:14px;line-height:20px}.YDXeBa_sessionRow .YDXeBa_title{flex:1}.YDXeBa_meta{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;overflow:hidden}.YDXeBa_time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:20px}.YDXeBa_dot{flex:none}.YDXeBa_rowActions{flex:none;align-items:center;gap:12px;display:none}.YDXeBa_projectRow:hover .YDXeBa_rowActions,.YDXeBa_sessionRow:hover .YDXeBa_rowActions,.YDXeBa_projectRow.YDXeBa_menuOpen .YDXeBa_rowActions,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_rowActions{display:inline-flex}.YDXeBa_sessionRow:hover .YDXeBa_time,.YDXeBa_sessionRow.YDXeBa_menuOpen .YDXeBa_time{display:none}.YDXeBa_projectRow.YDXeBa_menuOpen,.YDXeBa_sessionRow.YDXeBa_menuOpen{background:var(--dsw-alias-interactive-bg-hover)}.YDXeBa_sessionRow.YDXeBa_dropBefore,.YDXeBa_sessionRow.YDXeBa_dropAfter{position:relative}.YDXeBa_sessionRow.YDXeBa_dropBefore:before,.YDXeBa_sessionRow.YDXeBa_dropAfter:after{content:"";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:4px}.YDXeBa_sessionRow.YDXeBa_dropBefore:before{top:-7px}.YDXeBa_sessionRow.YDXeBa_dropAfter:after{bottom:-7px}.YDXeBa_hoverContent{flex-direction:column;gap:8px;display:flex}.YDXeBa_hoverTitle{color:#fff;overflow-wrap:break-word;font-size:14px;line-height:20px}.YDXeBa_hoverPath{color:#cfd3d6;word-break:break-all;font-size:12px;line-height:16px}.YDXeBa_hoverTime{color:#cfd3d6;font-size:12px;line-height:16px}.YDXeBa_hoverStatus{color:#adb2b8;align-items:center;gap:8px;font-size:12px;line-height:20px;display:flex}.YDXeBa_iconButton{cursor:pointer;width:16px;height:16px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.YDXeBa_iconButton:hover{color:var(--dsw-alias-label-primary)}.YDXeBa_chevron{color:var(--dsw-alias-label-caption)}@media (prefers-reduced-motion:reduce){.YDXeBa_sessionRow,.YDXeBa_arrow{transition:none;animation:none}}';
|
|
1048
|
-
const tagId$2 = "@
|
|
1205
|
+
const tagId$2 = "@michengai/dsh-archive-manager/Rows.module.css";
|
|
1049
1206
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
1050
1207
|
const tag = document.createElement("style");
|
|
1051
1208
|
tag.dataset.plugin = "@michengai/dsh-archive-manager";
|
|
@@ -1511,7 +1668,7 @@
|
|
|
1511
1668
|
});
|
|
1512
1669
|
}
|
|
1513
1670
|
const css$1 = "._G5b-a_modalAction{min-width:72px}._G5b-a_modalError,._G5b-a_menuStatus{margin-top:8px;font-size:12px;line-height:18px}._G5b-a_modalError{color:var(--dsw-alias-state-error-primary)}._G5b-a_menuStatus{color:var(--dsw-alias-label-secondary)}";
|
|
1514
|
-
const tagId$1 = "@
|
|
1671
|
+
const tagId$1 = "@michengai/dsh-archive-manager/WorkspacePicker.module.css";
|
|
1515
1672
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1516
1673
|
const tag = document.createElement("style");
|
|
1517
1674
|
tag.dataset.plugin = "@michengai/dsh-archive-manager";
|
|
@@ -1649,22 +1806,8 @@
|
|
|
1649
1806
|
})
|
|
1650
1807
|
] });
|
|
1651
1808
|
}
|
|
1652
|
-
function WorkspacePicker({ open, anchorRef, useWorkspaces, selectedId, onPick, onClose, createWorkspace, useDirectoryFlow, renderSlot, t }) {
|
|
1653
|
-
return (0, react_jsx_runtime.jsx)(WorkspacePickFlow, {
|
|
1654
|
-
t,
|
|
1655
|
-
open,
|
|
1656
|
-
anchorRef,
|
|
1657
|
-
useWorkspaces,
|
|
1658
|
-
createWorkspace,
|
|
1659
|
-
useDirectoryFlow,
|
|
1660
|
-
renderDirectoryFlow: (owner) => renderSlot("conversation.hero.workspace.directoryFlow", owner),
|
|
1661
|
-
selectedId,
|
|
1662
|
-
onPick,
|
|
1663
|
-
onClose
|
|
1664
|
-
});
|
|
1665
|
-
}
|
|
1666
1809
|
const css = '.qDHVXG_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding);--dsh-session-list-scrollbar-width:8px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;min-height:0;padding-right:var(--dsh-session-list-edge-inset);flex-direction:column;flex:1;display:flex}.qDHVXG_root.qDHVXG_rail{padding-right:0}.qDHVXG_iconButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_sectionHeader{box-sizing:border-box;height:36px;color:var(--dsw-alias-label-tertiary);border-radius:12px;flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;display:flex;overflow:hidden}.qDHVXG_root:not(.qDHVXG_rail) .qDHVXG_sectionHeader{margin-top:2px;margin-right:-4px}.qDHVXG_sectionLabel{white-space:nowrap;opacity:1;visibility:visible;min-width:0;max-width:45%;transition:max-width .18s var(--ds-ease-in-out), margin-right .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;line-height:20px;overflow:hidden}.qDHVXG_sectionLabelHidden{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transition-delay:0s,0s,0s,0s,.18s;transform:translate(-4px)}.qDHVXG_searchSlot{box-sizing:border-box;min-width:0;max-width:28px;transition:max-width .18s var(--ds-ease-in-out), padding-left .18s var(--ds-ease-in-out);flex:1;align-items:center;margin-left:auto;padding-left:0;display:flex}.qDHVXG_searchSlotExpanded{max-width:100%;padding-left:0}.qDHVXG_headerActions{opacity:1;visibility:visible;max-width:60px;transition:max-width .18s var(--ds-ease-in-out), opacity .12s var(--ds-ease-in-out), transform .18s var(--ds-ease-in-out), visibility 0s linear;flex:none;align-items:center;gap:4px;display:flex;overflow:hidden}.qDHVXG_headerActionsHidden{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transition-delay:0s,0s,0s,.18s;transform:translate(4px)}.qDHVXG_search{box-sizing:border-box;cursor:text;width:100%;height:28px;color:var(--dsw-alias-label-secondary);transition:width .18s var(--ds-ease-in-out), padding .18s var(--ds-ease-in-out), border-color .18s var(--ds-ease-in-out), background-color .18s var(--ds-ease-in-out);background:0 0;border:none;border-radius:50%;flex:none;align-items:center;gap:0;margin:0;padding:0;display:flex;overflow:hidden}.qDHVXG_searchExpanded{border:1px solid var(--dsw-alias-border-l2);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);background:0 0;border-radius:10px;margin-inline:-2px;padding:0 4px 0 0}.qDHVXG_searchButton{cursor:pointer;width:28px;height:28px;color:inherit;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_searchExpanded .qDHVXG_searchButton{width:28px;height:30px}.qDHVXG_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_searchExpanded .qDHVXG_searchButton:hover{background:0 0}.qDHVXG_searchInput{opacity:0;pointer-events:none;width:0;min-width:0;color:var(--dsw-alias-label-primary);transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;font-size:13px;line-height:18px}.qDHVXG_searchExpanded .qDHVXG_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.qDHVXG_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.qDHVXG_clearButton{cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.qDHVXG_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_rail .qDHVXG_sectionHeader{justify-content:flex-start;gap:0;margin-bottom:12px;padding-left:0}.qDHVXG_rail .qDHVXG_headerActions{max-width:none}.qDHVXG_rail .qDHVXG_iconButton{width:36px;height:36px;color:var(--dsw-alias-label-primary)}.qDHVXG_rail .qDHVXG_search{background:0 0;border-color:#0000;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.qDHVXG_rail .qDHVXG_searchButton{width:36px;height:36px;color:var(--dsw-alias-label-primary)}.qDHVXG_rail .qDHVXG_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.qDHVXG_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:visible}.qDHVXG_rail .qDHVXG_listArea{margin-left:0;margin-right:0;padding-left:0}.qDHVXG_treeBody{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.qDHVXG_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}.qDHVXG_wide{animation:qDHVXG_wide-in .2s var(--ds-ease-in-out)}@keyframes qDHVXG_wide-in{0%{opacity:0}}.qDHVXG_list{min-height:0;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;flex:1;padding-bottom:16px;overflow-y:auto}.qDHVXG_flatList>*+*,.qDHVXG_searchTree>[role=treeitem]+[role=treeitem],.qDHVXG_groupSection>*+*{margin-top:2px}.qDHVXG_searchStatus,.qDHVXG_searchWarning{color:var(--dsw-alias-label-tertiary);padding:10px 12px;font-size:12px;line-height:18px}.qDHVXG_searchWarning{color:var(--dsw-alias-label-secondary)}.qDHVXG_groupSection{position:relative}.qDHVXG_groupSection+.qDHVXG_groupSection{margin-top:4px}.qDHVXG_listTopDropIndicator,.qDHVXG_workspaceDropBefore:before,.qDHVXG_workspaceDropAfter:after{content:"";z-index:1;background:linear-gradient(55deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 0 / 5px 7px no-repeat, linear-gradient(125deg, transparent calc(50% - 1px), var(--dsw-alias-state-business-primary) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)) 0 5px / 5px 7px no-repeat, linear-gradient(var(--dsw-alias-state-business-primary) 0 0) 4px 5px / calc(100% - 4px) 2px no-repeat;pointer-events:none;height:12px;position:absolute;left:0;right:0}.qDHVXG_listTopDropIndicator{top:-8px;left:0;right:var(--dsh-session-list-edge-inset)}.qDHVXG_listTopDropActive>.qDHVXG_workspaceDropBefore:first-child:before{display:none}.qDHVXG_workspaceDropBefore:before{top:-8px}.qDHVXG_workspaceDropAfter:after{bottom:-8px}.qDHVXG_sessionOverflowButton{cursor:pointer;text-align:left;width:100%;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:8px;padding:0 12px 0 28px;font-size:12px}.qDHVXG_groupSection>.qDHVXG_sessionOverflowButton{margin-top:0}.qDHVXG_sessionOverflowButton:hover{color:var(--dsw-alias-label-secondary);background:0 0}.qDHVXG_empty{color:var(--dsw-alias-label-tertiary);padding:16px 12px;font-size:13px}.qDHVXG_renameInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);width:100%;height:44px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:22px;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.qDHVXG_renameInput:disabled{color:var(--dsw-alias-label-dimmed)}.qDHVXG_renameError{color:var(--dsw-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}.qDHVXG_deleteAction:not(:disabled){color:var(--dsw-alias-state-error-primary)}.qDHVXG_deleteStatus{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}@media (prefers-reduced-motion:reduce){.qDHVXG_wide{animation:none}.qDHVXG_search,.qDHVXG_sectionLabel,.qDHVXG_searchSlot,.qDHVXG_searchInput,.qDHVXG_headerActions{transition:none}}';
|
|
1667
|
-
const tagId = "@
|
|
1810
|
+
const tagId = "@michengai/dsh-archive-manager/WorkspaceBrowser.module.css";
|
|
1668
1811
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1669
1812
|
const tag = document.createElement("style");
|
|
1670
1813
|
tag.dataset.plugin = "@michengai/dsh-archive-manager";
|
|
@@ -2718,7 +2861,7 @@
|
|
|
2718
2861
|
useWorkspaces,
|
|
2719
2862
|
createWorkspace,
|
|
2720
2863
|
useDirectoryFlow,
|
|
2721
|
-
renderDirectoryFlow: (owner) => renderSlot(
|
|
2864
|
+
renderDirectoryFlow: (owner) => renderSlot(DIRECTORY_FLOW_SLOT, owner),
|
|
2722
2865
|
addOnly: true,
|
|
2723
2866
|
side: "right",
|
|
2724
2867
|
onPick: (workspaceId) => {
|
|
@@ -3304,172 +3447,13 @@
|
|
|
3304
3447
|
return compareText(left.title, right.title) || compareText(left.key, right.key);
|
|
3305
3448
|
});
|
|
3306
3449
|
}
|
|
3307
|
-
function ArchivedSessionsSection({ sessionStore, workspaceStore, unarchiveSession, deleteSession, unarchiveSessions, deleteArchivedSessions, archivedSessionMetadata, t }) {
|
|
3308
|
-
const sessions = (0, react.useSyncExternalStore)(sessionStore.subscribe, sessionStore.getSnapshot);
|
|
3309
|
-
const workspaceState = (0, react.useSyncExternalStore)(workspaceStore.subscribe, workspaceStore.getSnapshot);
|
|
3310
|
-
const [deleteTarget, setDeleteTarget] = (0, react.useState)(null);
|
|
3311
|
-
const [busy, setBusy] = (0, react.useState)(false);
|
|
3312
|
-
const [error, setError] = (0, react.useState)(null);
|
|
3313
|
-
const [notice, setNotice] = (0, react.useState)(null);
|
|
3314
|
-
const [query, setQuery] = (0, react.useState)("");
|
|
3315
|
-
const [project, setProject] = (0, react.useState)("all");
|
|
3316
|
-
const [sortBy, setSortBy] = (0, react.useState)("updated");
|
|
3317
|
-
const [createdAtById, setCreatedAtById] = (0, react.useState)({});
|
|
3318
|
-
const [unarchivingSessionIds, setUnarchivingSessionIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
3319
|
-
const unarchivingSessionIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
3320
|
-
const [selectedSessionIds, setSelectedSessionIds] = (0, react.useState)([]);
|
|
3321
|
-
const groups = (0, react.useMemo)(() => deriveArchivedGroups(sessions.byId, workspaceState.items, workspaceState.archivedSessionIds, t("group.ungrouped")), [sessions.byId, workspaceState, t]);
|
|
3322
|
-
const sortedGroups = (0, react.useMemo)(() => sortArchivedGroups(groups, sortBy, createdAtById, t), [groups, sortBy, createdAtById, t]);
|
|
3323
|
-
(0, react.useEffect)(() => {
|
|
3324
|
-
let cancelled = false;
|
|
3325
|
-
archivedSessionMetadata().then((result) => {
|
|
3326
|
-
if (cancelled) return;
|
|
3327
|
-
setCreatedAtById(Object.fromEntries(result.items.map((item) => [item.sessionId, item.createdAt])));
|
|
3328
|
-
}).catch(() => {
|
|
3329
|
-
if (!cancelled) setCreatedAtById({});
|
|
3330
|
-
});
|
|
3331
|
-
return () => {
|
|
3332
|
-
cancelled = true;
|
|
3333
|
-
};
|
|
3334
|
-
}, [archivedSessionMetadata, workspaceState.archivedSessionIds]);
|
|
3335
|
-
(0, react.useEffect)(() => {
|
|
3336
|
-
if (project === "all") return;
|
|
3337
|
-
if (groups.some((group) => group.key === project)) return;
|
|
3338
|
-
setProject("all");
|
|
3339
|
-
}, [groups, project]);
|
|
3340
|
-
const filteredGroups = (0, react.useMemo)(() => {
|
|
3341
|
-
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
3342
|
-
return sortedGroups.filter((group) => project === "all" || project === group.key).map((group) => ({
|
|
3343
|
-
...group,
|
|
3344
|
-
sessions: group.sessions.filter((session) => normalizedQuery === "" || displayTitle(session, t).toLocaleLowerCase().includes(normalizedQuery))
|
|
3345
|
-
})).filter((group) => group.sessions.length > 0);
|
|
3346
|
-
}, [sortedGroups, project, query, t]);
|
|
3347
|
-
const visibleSessionIds = (0, react.useMemo)(() => archivedSessionIdsInGroups(filteredGroups), [filteredGroups]);
|
|
3348
|
-
const selectedSessionIdSet = (0, react.useMemo)(() => new Set(selectedSessionIds), [selectedSessionIds]);
|
|
3349
|
-
const selectedVisibleCount = visibleSessionIds.filter((sessionId) => selectedSessionIdSet.has(sessionId)).length;
|
|
3350
|
-
const allVisibleSelected = visibleSessionIds.length > 0 && selectedVisibleCount === visibleSessionIds.length;
|
|
3351
|
-
const allBatchTarget = { scope: "all" };
|
|
3352
|
-
const allBatchSessionIds = (0, react.useMemo)(() => deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, allBatchTarget), [workspaceState.archivedSessionIds, workspaceState.items]);
|
|
3353
|
-
(0, react.useEffect)(() => {
|
|
3354
|
-
setSelectedSessionIds((current) => pruneArchivedSelection(current, workspaceState.archivedSessionIds));
|
|
3355
|
-
}, [workspaceState.archivedSessionIds]);
|
|
3356
|
-
const toggleSessionSelection = (sessionId, checked) => {
|
|
3357
|
-
setSelectedSessionIds((current) => toggleArchivedSelection(current, [sessionId], checked));
|
|
3358
|
-
};
|
|
3359
|
-
const toggleVisibleSelection = (checked) => {
|
|
3360
|
-
setSelectedSessionIds((current) => toggleArchivedSelection(current, visibleSessionIds, checked));
|
|
3361
|
-
};
|
|
3362
|
-
const onUnarchive = (sessionId) => {
|
|
3363
|
-
if (busy || unarchivingSessionIdsRef.current.has(sessionId)) return;
|
|
3364
|
-
unarchivingSessionIdsRef.current.add(sessionId);
|
|
3365
|
-
setUnarchivingSessionIds(new Set(unarchivingSessionIdsRef.current));
|
|
3366
|
-
setError(null);
|
|
3367
|
-
setNotice(null);
|
|
3368
|
-
unarchiveSession(sessionId).catch((reason) => {
|
|
3369
|
-
setError(formatUnarchiveError(reason, t));
|
|
3370
|
-
}).finally(() => {
|
|
3371
|
-
unarchivingSessionIdsRef.current.delete(sessionId);
|
|
3372
|
-
setUnarchivingSessionIds(new Set(unarchivingSessionIdsRef.current));
|
|
3373
|
-
});
|
|
3374
|
-
};
|
|
3375
|
-
const onBatchUnarchive = async (target) => {
|
|
3376
|
-
if (busy) return;
|
|
3377
|
-
setBusy(true);
|
|
3378
|
-
setError(null);
|
|
3379
|
-
setNotice(null);
|
|
3380
|
-
try {
|
|
3381
|
-
const result = await unarchiveSessions(target);
|
|
3382
|
-
setNotice(t("archives.restoreSuccess", { n: result.unarchivedSessionIds.length }));
|
|
3383
|
-
return result;
|
|
3384
|
-
} catch (reason) {
|
|
3385
|
-
setError(t("archives.restoreBatchFailed", { detail: reason instanceof Error ? reason.message : String(reason) }));
|
|
3386
|
-
} finally {
|
|
3387
|
-
setBusy(false);
|
|
3388
|
-
}
|
|
3389
|
-
};
|
|
3390
|
-
const onSelectedUnarchive = async () => {
|
|
3391
|
-
if (selectedSessionIds.length === 0) return;
|
|
3392
|
-
const result = await onBatchUnarchive({ scope: "sessions", sessionIds: selectedSessionIds });
|
|
3393
|
-
if (result !== void 0) {
|
|
3394
|
-
const restored = new Set(result.unarchivedSessionIds);
|
|
3395
|
-
setSelectedSessionIds((current) => current.filter((sessionId) => !restored.has(sessionId)));
|
|
3396
|
-
}
|
|
3397
|
-
};
|
|
3398
|
-
const closeDelete = () => {
|
|
3399
|
-
if (!busy) setDeleteTarget(null);
|
|
3400
|
-
};
|
|
3401
|
-
(0, react.useEffect)(() => {
|
|
3402
|
-
if (deleteTarget === null) return;
|
|
3403
|
-
const onKeyDown = (event) => {
|
|
3404
|
-
if (event.key !== "Escape") return;
|
|
3405
|
-
event.preventDefault();
|
|
3406
|
-
event.stopPropagation();
|
|
3407
|
-
if (typeof event.stopImmediatePropagation === "function") event.stopImmediatePropagation();
|
|
3408
|
-
if (!busy) setDeleteTarget(null);
|
|
3409
|
-
};
|
|
3410
|
-
window.addEventListener("keydown", onKeyDown, true);
|
|
3411
|
-
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
3412
|
-
}, [deleteTarget, busy]);
|
|
3413
|
-
const confirmDelete = async () => {
|
|
3414
|
-
if (busy || deleteTarget === null) return;
|
|
3415
|
-
setBusy(true);
|
|
3416
|
-
setError(null);
|
|
3417
|
-
setNotice(null);
|
|
3418
|
-
try {
|
|
3419
|
-
if (deleteTarget.kind === "batch") {
|
|
3420
|
-
const result = await deleteArchivedSessions(deleteTarget.target);
|
|
3421
|
-
const feedback = archivedDeleteFeedback(result, t);
|
|
3422
|
-
if (feedback.kind === "error") setError(feedback.message);
|
|
3423
|
-
else setNotice(feedback.message);
|
|
3424
|
-
if (deleteTarget.target.scope === "sessions") {
|
|
3425
|
-
const completed = /* @__PURE__ */ new Set([...result.deletedSessionIds, ...result.skippedSessionIds]);
|
|
3426
|
-
setSelectedSessionIds((current) => current.filter((sessionId) => !completed.has(sessionId)));
|
|
3427
|
-
}
|
|
3428
|
-
} else {
|
|
3429
|
-
await deleteSession(deleteTarget.session.id);
|
|
3430
|
-
}
|
|
3431
|
-
setDeleteTarget(null);
|
|
3432
|
-
} catch (reason) {
|
|
3433
|
-
setError(formatDeleteError(reason, t));
|
|
3434
|
-
} finally {
|
|
3435
|
-
setBusy(false);
|
|
3436
|
-
}
|
|
3437
|
-
};
|
|
3438
|
-
const batchScope = deleteTarget?.kind === "batch" ? deleteTarget.target.scope : null;
|
|
3439
|
-
const deleteDialogTitle = batchScope === "all" ? t("archives.deleteAllTitle") : batchScope === "ungrouped" ? t("archives.deleteUngroupedTitle") : batchScope === "workspace" ? t("archives.deleteProjectTitle", { name: deleteTarget.title }) : batchScope === "sessions" ? t("archives.deleteSelectedTitle") : t("deleteSession.title");
|
|
3440
|
-
const deleteDialogDescription = deleteTarget === null ? void 0 : batchScope === "all" ? t("archives.deleteAllDesc", { n: deleteTarget.count }) : 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) });
|
|
3441
|
-
const deleteConfirmLabel = batchScope === "all" ? t("archives.deleteAll") : batchScope === "ungrouped" ? t("archives.deleteUngroupedConfirm") : batchScope === "workspace" ? t("archives.deleteProjectConfirm") : batchScope === "sessions" ? t("archives.deleteSelectedConfirm") : t("deleteSession.title");
|
|
3442
|
-
return (0, react_jsx_runtime.jsxs)("section", {
|
|
3443
|
-
className: "dsham_settings",
|
|
3444
|
-
"aria-label": t("archives.title"),
|
|
3445
|
-
children: [(0, react_jsx_runtime.jsx)("style", { children: ARCHIVE_SETTINGS_CSS + ARCHIVE_SETTINGS_BATCH_CSS + ARCHIVE_SETTINGS_EXTERNAL_LINK_CSS }), (0, react_jsx_runtime.jsxs)("header", { className: "dsham_settingsHeader", children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsTitleRow", children: [(0, react_jsx_runtime.jsx)("h2", { children: t("archives.title") }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsLinks", children: [(0, react_jsx_runtime.jsxs)("a", { className: "dsham_settingsExternalLink", href: "https://github.com/MichengAI/dsh-archive-manager", target: "_blank", rel: "noreferrer", "aria-label": t("archives.viewProject"), children: [(0, react_jsx_runtime.jsx)(GithubMark16, {}), t("archives.viewProject")] }), (0, react_jsx_runtime.jsxs)("a", { className: "dsham_settingsExternalLink", href: "https://github.com/MichengAI/dsh-archive-manager/issues", target: "_blank", rel: "noreferrer", "aria-label": t("archives.feedback"), children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, {}), t("archives.feedback")] })] })] }), (0, react_jsx_runtime.jsx)("p", { className: "dsham_settingsIntro", children: t("archives.description") })] }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsHeaderActions", 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")] })] })] }), (0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsToolbar", children: [(0, react_jsx_runtime.jsxs)("label", { className: "dsham_settingsSearch", children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, {}), (0, react_jsx_runtime.jsx)("input", { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: t("archives.searchPlaceholder"), "aria-label": t("archives.searchPlaceholder") })] }), (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") }], 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") })] }), groups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.empty") }) : filteredGroups.length === 0 ? (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsEmpty", children: t("archives.emptyFiltered") }) : filteredGroups.map((group) => {
|
|
3446
|
-
const target = archivedBatchTargetForGroup(group.key);
|
|
3447
|
-
const count = deriveArchivedBatchIds(workspaceState.archivedSessionIds, workspaceState.items, target).length;
|
|
3448
|
-
return (0, react_jsx_runtime.jsxs)("section", {
|
|
3449
|
-
className: "dsham_settingsGroup",
|
|
3450
|
-
children: [(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsGroupHeading", children: [(0, react_jsx_runtime.jsxs)("h3", { className: "dsham_settingsGroupTitle", children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, {}), 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: count }) }), (0, react_jsx_runtime.jsx)(ArchivedGroupActions, { group, busy, onRestore: () => onBatchUnarchive(target), onDelete: () => setDeleteTarget({ kind: "batch", target, title: group.title, count }), t })] })] }), (0, react_jsx_runtime.jsx)("div", {
|
|
3451
|
-
className: "dsham_settingsList",
|
|
3452
|
-
children: group.sessions.map((session) => (0, react_jsx_runtime.jsxs)("article", {
|
|
3453
|
-
className: "dsham_settingsRow",
|
|
3454
|
-
children: [(0, react_jsx_runtime.jsxs)("div", { className: "dsham_settingsContent", children: [(0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsTitle", children: displayTitle(session, t) }), (0, react_jsx_runtime.jsx)("div", { className: "dsham_settingsMeta", children: archiveTimeLabel(session.updatedAt, t) })] }), (0, react_jsx_runtime.jsxs)("div", {
|
|
3455
|
-
className: "dsham_settingsActions",
|
|
3456
|
-
children: [(0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsAction", disabled: busy || unarchivingSessionIds.has(session.id), onClick: () => onUnarchive(session.id), children: t("menu.unarchive") }), (0, react_jsx_runtime.jsx)("button", { type: "button", className: "dsham_settingsDelete", disabled: busy || unarchivingSessionIds.has(session.id), "aria-label": t("menu.deleteSession"), onClick: () => setDeleteTarget({ kind: "session", session }), children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {}) })]
|
|
3457
|
-
})]
|
|
3458
|
-
}, session.id))
|
|
3459
|
-
})]
|
|
3460
|
-
}, group.key);
|
|
3461
|
-
}), 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.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3462
|
-
open: deleteTarget !== null,
|
|
3463
|
-
onClose: closeDelete,
|
|
3464
|
-
closeLabel: t("close"),
|
|
3465
|
-
title: deleteDialogTitle,
|
|
3466
|
-
...deleteDialogDescription === void 0 ? {} : { description: deleteDialogDescription },
|
|
3467
|
-
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 })] }),
|
|
3468
|
-
children: busy && (0, react_jsx_runtime.jsx)("div", { role: "status", children: deleteTarget?.kind === "batch" ? t("archives.deleteBatchPending") : t("deleteSession.pending") })
|
|
3469
|
-
})]
|
|
3470
|
-
});
|
|
3471
|
-
}
|
|
3472
3450
|
const zh = {
|
|
3451
|
+
"archives.viewConversation": "\u67E5\u770B\u5BF9\u8BDD",
|
|
3452
|
+
"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",
|
|
3453
|
+
"archives.sessionNotRetained": "\u5BBF\u4E3B\u672A\u4FDD\u7559\u76EE\u6807\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6216\u6062\u590D\u540E\u518D\u8BD5\u3002",
|
|
3454
|
+
"archives.restoreOpen": "\u6062\u590D\u5E76\u6253\u5F00",
|
|
3455
|
+
"archives.selectedScope": "\u5DF2\u9009 {n} \u6761\uFF0C\u5176\u4E2D {hidden} \u6761\u4E0D\u5728\u5F53\u524D\u7ED3\u679C",
|
|
3456
|
+
"archives.clearSelection": "\u6E05\u7A7A\u9009\u62E9",
|
|
3473
3457
|
"group.ungrouped": "\u672A\u5206\u7EC4",
|
|
3474
3458
|
"session.new": "\u65B0\u4F1A\u8BDD",
|
|
3475
3459
|
"section.workspaces": "\u5DE5\u4F5C\u533A",
|
|
@@ -3484,7 +3468,6 @@
|
|
|
3484
3468
|
"sessions.expand": "\u5C55\u5F00\u5176\u4F59 {n} \u4E2A\u4F1A\u8BDD",
|
|
3485
3469
|
"sessions.collapse": "\u6536\u8D77",
|
|
3486
3470
|
"empty.none": "\u6682\u65E0\u4F1A\u8BDD",
|
|
3487
|
-
"empty.noMatches": "\u65E0\u5339\u914D\u7ED3\u679C",
|
|
3488
3471
|
"workspace.add": "\u6DFB\u52A0\u5DE5\u4F5C\u533A",
|
|
3489
3472
|
"search.sessions.aria": "\u641C\u7D22\u4F1A\u8BDD",
|
|
3490
3473
|
"search.placeholder": "\u641C\u7D22\u4F1A\u8BDD\u2026",
|
|
@@ -3515,7 +3498,6 @@
|
|
|
3515
3498
|
"archives.sessionCount": "{n} \u4E2A\u804A\u5929",
|
|
3516
3499
|
"archives.selectAllFiltered": "\u5168\u9009\u5F53\u524D\u7B5B\u9009\u7ED3\u679C",
|
|
3517
3500
|
"archives.selectSession": "\u9009\u62E9\u4F1A\u8BDD\u201C{name}\u201D",
|
|
3518
|
-
"archives.selectedCount": "\u5DF2\u9009 {n} \u4E2A",
|
|
3519
3501
|
"archives.restoreSelected": "\u6062\u590D\u6240\u9009",
|
|
3520
3502
|
"archives.deleteSelected": "\u5220\u9664\u6240\u9009",
|
|
3521
3503
|
"archives.timestamp": "{date}\uFF0C{time}",
|
|
@@ -3534,7 +3516,6 @@
|
|
|
3534
3516
|
"archives.deleteSelectedTitle": "\u5220\u9664\u6240\u9009\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3535
3517
|
"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",
|
|
3536
3518
|
"archives.deleteSelectedConfirm": "\u5220\u9664\u6240\u9009\u804A\u5929",
|
|
3537
|
-
"archives.deleteAllPending": "\u6B63\u5728\u5220\u9664\u5DF2\u5F52\u6863\u804A\u5929\u2026",
|
|
3538
3519
|
"archives.deleteProjectTitle": "\u5220\u9664\u201C{name}\u201D\u4E2D\u7684\u5DF2\u5F52\u6863\u804A\u5929",
|
|
3539
3520
|
"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",
|
|
3540
3521
|
"archives.deleteProjectConfirm": "\u5220\u9664\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u804A\u5929",
|
|
@@ -3575,8 +3556,6 @@
|
|
|
3575
3556
|
"archiveWorkspace.desc": "\u8FD9\u4F1A\u5C06\u201C{name}\u201D\u4E2D\u7684\u804A\u5929\u5F52\u6863\u3002\u4E4B\u540E\u4F60\u53EF\u4EE5\u5728\u5DF2\u5F52\u6863\u7684\u804A\u5929\u4E2D\u627E\u5230\u5B83\u4EEC\u3002",
|
|
3576
3557
|
"archiveWorkspace.confirm": "\u5168\u90E8\u5F52\u6863",
|
|
3577
3558
|
"archiveWorkspace.pending": "\u6B63\u5728\u5F52\u6863\u804A\u5929\u2026",
|
|
3578
|
-
"sessions.count.one": "{n} \u4E2A\u4F1A\u8BDD",
|
|
3579
|
-
"sessions.count.other": "{n} \u4E2A\u4F1A\u8BDD",
|
|
3580
3559
|
"actions.workspace.aria": "\u5DE5\u4F5C\u533A\u201C{name}\u201D\u7684\u64CD\u4F5C",
|
|
3581
3560
|
"actions.session.aria": "\u4F1A\u8BDD\u201C{name}\u201D\u7684\u64CD\u4F5C",
|
|
3582
3561
|
"actions.newSession.aria": "\u5728\u201C{name}\u201D\u4E2D\u65B0\u5EFA\u4F1A\u8BDD",
|
|
@@ -3600,6 +3579,12 @@
|
|
|
3600
3579
|
"time.ago": "{t}\u524D"
|
|
3601
3580
|
};
|
|
3602
3581
|
const en = {
|
|
3582
|
+
"archives.viewConversation": "View conversation",
|
|
3583
|
+
"archives.navigationUnavailable": "This host cannot keep the conversation archived while opening it. Use \u201CRestore and open\u201D instead.",
|
|
3584
|
+
"archives.sessionNotRetained": "The host did not keep the requested conversation open. Try again, or restore it before opening.",
|
|
3585
|
+
"archives.restoreOpen": "Restore and open",
|
|
3586
|
+
"archives.selectedScope": "{n} selected, {hidden} outside current results",
|
|
3587
|
+
"archives.clearSelection": "Clear selection",
|
|
3603
3588
|
"group.ungrouped": "Ungrouped",
|
|
3604
3589
|
"session.new": "New Session",
|
|
3605
3590
|
"section.workspaces": "Workspaces",
|
|
@@ -3614,7 +3599,6 @@
|
|
|
3614
3599
|
"sessions.expand": "Show {n} more sessions",
|
|
3615
3600
|
"sessions.collapse": "Show less",
|
|
3616
3601
|
"empty.none": "No sessions yet",
|
|
3617
|
-
"empty.noMatches": "No matches",
|
|
3618
3602
|
"workspace.add": "Add workspace",
|
|
3619
3603
|
"search.sessions.aria": "Search sessions",
|
|
3620
3604
|
"search.placeholder": "Search sessions...",
|
|
@@ -3645,7 +3629,6 @@
|
|
|
3645
3629
|
"archives.sessionCount": "{n} chats",
|
|
3646
3630
|
"archives.selectAllFiltered": "Select all results",
|
|
3647
3631
|
"archives.selectSession": "Select chat {name}",
|
|
3648
|
-
"archives.selectedCount": "{n} selected",
|
|
3649
3632
|
"archives.restoreSelected": "Restore selected",
|
|
3650
3633
|
"archives.deleteSelected": "Delete selected",
|
|
3651
3634
|
"archives.timestamp": "{date}, {time}",
|
|
@@ -3664,7 +3647,6 @@
|
|
|
3664
3647
|
"archives.deleteSelectedTitle": "Delete selected archived chats",
|
|
3665
3648
|
"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.",
|
|
3666
3649
|
"archives.deleteSelectedConfirm": "Delete selected chats",
|
|
3667
|
-
"archives.deleteAllPending": "Deleting archived chats\u2026",
|
|
3668
3650
|
"archives.deleteProjectTitle": "Delete archived chats in {name}",
|
|
3669
3651
|
"archives.deleteProjectDesc": "This permanently deletes the {n} archived chats in {name}, their child agents, and their records. The project directory and unarchived chats are not affected. This cannot be undone.",
|
|
3670
3652
|
"archives.deleteProjectConfirm": "Delete all project chats",
|
|
@@ -3705,8 +3687,6 @@
|
|
|
3705
3687
|
"archiveWorkspace.desc": "This archives the chats in \u201C{name}\u201D. You can find them later in Archived chats.",
|
|
3706
3688
|
"archiveWorkspace.confirm": "Archive all",
|
|
3707
3689
|
"archiveWorkspace.pending": "Archiving chats\u2026",
|
|
3708
|
-
"sessions.count.one": "{n} session",
|
|
3709
|
-
"sessions.count.other": "{n} sessions",
|
|
3710
3690
|
"actions.workspace.aria": "Workspace actions for {name}",
|
|
3711
3691
|
"actions.session.aria": "Session actions for {name}",
|
|
3712
3692
|
"actions.newSession.aria": "New session in {name}",
|
|
@@ -3729,14 +3709,16 @@
|
|
|
3729
3709
|
"time.years": "{n}y",
|
|
3730
3710
|
"time.ago": "{t} ago"
|
|
3731
3711
|
};
|
|
3732
|
-
const NS = "workspace";
|
|
3712
|
+
const NS = "archive-manager-workspace";
|
|
3713
|
+
const DIRECTORY_FLOW_SLOT = "archiveManager.sidebar.directoryFlow";
|
|
3733
3714
|
const inject = [
|
|
3734
3715
|
"slots",
|
|
3735
3716
|
"sessions",
|
|
3736
3717
|
"workspaces",
|
|
3737
3718
|
"locale",
|
|
3738
3719
|
"remote",
|
|
3739
|
-
"typert"
|
|
3720
|
+
"typert",
|
|
3721
|
+
...hasSplitClientStore ? ["uiWorkspace"] : []
|
|
3740
3722
|
];
|
|
3741
3723
|
function bindObservable(source) {
|
|
3742
3724
|
return {
|
|
@@ -3744,173 +3726,6 @@
|
|
|
3744
3726
|
subscribe: source.subscribe.bind(source)
|
|
3745
3727
|
};
|
|
3746
3728
|
}
|
|
3747
|
-
class DirectoryBrowseError extends Error {
|
|
3748
|
-
constructor(rpcError) {
|
|
3749
|
-
super(`directory browse failed: ${rpcError.code}: ${rpcError.message}`);
|
|
3750
|
-
this.name = "DirectoryBrowseError";
|
|
3751
|
-
this.rpcError = rpcError;
|
|
3752
|
-
}
|
|
3753
|
-
}
|
|
3754
|
-
function provideUiWorkspace(ctx) {
|
|
3755
|
-
if (ctx.get("uiWorkspace") !== void 0) return () => {
|
|
3756
|
-
};
|
|
3757
|
-
const sessions = ctx.sessions;
|
|
3758
|
-
const workspaces = ctx.workspaces;
|
|
3759
|
-
const connecting = /* @__PURE__ */ new Map();
|
|
3760
|
-
const lifetime = new AbortController();
|
|
3761
|
-
const layoutAt = () => ctx.get("layout");
|
|
3762
|
-
const beginNavigation = () => {
|
|
3763
|
-
const signal = layoutAt()?.beginNavigation?.();
|
|
3764
|
-
return signal === void 0 ? lifetime.signal : AbortSignal.any([signal, lifetime.signal]);
|
|
3765
|
-
};
|
|
3766
|
-
const recentWorkspace = () => {
|
|
3767
|
-
const workspaceState = workspaces.list.getSnapshot();
|
|
3768
|
-
const sessionState = sessions.list.getSnapshot();
|
|
3769
|
-
let selected;
|
|
3770
|
-
let selectedTime = Number.NEGATIVE_INFINITY;
|
|
3771
|
-
for (const workspace of workspaceState.items ?? []) {
|
|
3772
|
-
let latest = Number.NEGATIVE_INFINITY;
|
|
3773
|
-
for (const sessionId of workspace.sessionIds) {
|
|
3774
|
-
const session = sessionState.byId[sessionId];
|
|
3775
|
-
if (session !== void 0) latest = Math.max(latest, session.updatedAt);
|
|
3776
|
-
}
|
|
3777
|
-
if (latest === Number.NEGATIVE_INFINITY) latest = Date.parse(workspace.createdAt);
|
|
3778
|
-
if (selected === void 0 || latest > selectedTime) {
|
|
3779
|
-
selected = workspace.workspaceId;
|
|
3780
|
-
selectedTime = latest;
|
|
3781
|
-
}
|
|
3782
|
-
}
|
|
3783
|
-
return selected;
|
|
3784
|
-
};
|
|
3785
|
-
const directoryPicker = () => ctx.get("remote.directoryPicker") ?? ctx.get("remote")?.directoryPicker;
|
|
3786
|
-
const service = {
|
|
3787
|
-
connectWorkspace(workspaceId) {
|
|
3788
|
-
const workspaceState = workspaces.list.getSnapshot();
|
|
3789
|
-
const workspace = (workspaceState.items ?? []).find((item) => item.workspaceId === workspaceId);
|
|
3790
|
-
if (workspace === void 0) return Promise.reject(new Error(`uiWorkspace.connectWorkspace: unknown workspace ${workspaceId}`));
|
|
3791
|
-
const inflight = connecting.get(workspaceId);
|
|
3792
|
-
if (inflight !== void 0) return inflight;
|
|
3793
|
-
const sessionState = sessions.list.getSnapshot();
|
|
3794
|
-
const archived = new Set(workspaceState.archivedSessionIds ?? []);
|
|
3795
|
-
for (const id of sessionState.ids) {
|
|
3796
|
-
const summary = sessionState.byId[id];
|
|
3797
|
-
if (summary !== void 0 && summary.blank && summary.cwd === workspace.path && workspace.sessionIds.includes(summary.id) && !archived.has(summary.id)) return Promise.resolve(summary.id);
|
|
3798
|
-
}
|
|
3799
|
-
const attempt = sessions.create({ workspaceId }).finally(() => {
|
|
3800
|
-
connecting.delete(workspaceId);
|
|
3801
|
-
});
|
|
3802
|
-
connecting.set(workspaceId, attempt);
|
|
3803
|
-
return attempt;
|
|
3804
|
-
},
|
|
3805
|
-
/** 打开指定会话,并从新版全局面板回到对话。 */
|
|
3806
|
-
openSession(sessionId) {
|
|
3807
|
-
if (lifetime.signal.aborted) return;
|
|
3808
|
-
sessions.open(sessionId);
|
|
3809
|
-
layoutAt()?.selectPanel?.(null);
|
|
3810
|
-
},
|
|
3811
|
-
/** 创建或复用工作区会话;导航仍有效时先交接草稿,失败向调用方传播。 */
|
|
3812
|
-
async openWorkspace(workspaceId, beforeOpen) {
|
|
3813
|
-
const navigation = beginNavigation();
|
|
3814
|
-
const sessionId = await service.connectWorkspace(workspaceId);
|
|
3815
|
-
if (navigation.aborted) return;
|
|
3816
|
-
beforeOpen?.(sessionId);
|
|
3817
|
-
if (!navigation.aborted) service.openSession(sessionId);
|
|
3818
|
-
},
|
|
3819
|
-
/** 分叉落盘后仅在导航未取消时打开结果,保留失败语义。 */
|
|
3820
|
-
async forkSession(sessionId) {
|
|
3821
|
-
const navigation = beginNavigation();
|
|
3822
|
-
const childId = await sessions.fork({ sessionId, increaseTitle: true });
|
|
3823
|
-
if (!navigation.aborted) service.openSession(childId);
|
|
3824
|
-
},
|
|
3825
|
-
startSession(workspaceId) {
|
|
3826
|
-
const workspaceState = workspaces.list.getSnapshot();
|
|
3827
|
-
const sessionState = sessions.list.getSnapshot();
|
|
3828
|
-
const currentWorkspaceId = sessionState.current === void 0 ? void 0 : (workspaceState.items ?? []).find((item) => item.sessionIds.includes(sessionState.current))?.workspaceId;
|
|
3829
|
-
const recent = workspaceState.phase === "ready" && sessionState.phase === "ready" ? recentWorkspace() : void 0;
|
|
3830
|
-
const target = workspaceId ?? currentWorkspaceId ?? recent;
|
|
3831
|
-
if (target === void 0) {
|
|
3832
|
-
sessions.clear();
|
|
3833
|
-
layoutAt()?.selectPanel?.(null);
|
|
3834
|
-
return;
|
|
3835
|
-
}
|
|
3836
|
-
void service.openWorkspace(target).catch((reason) => {
|
|
3837
|
-
console.warn("new session failed:", reason);
|
|
3838
|
-
});
|
|
3839
|
-
},
|
|
3840
|
-
archiveSession(sessionId) {
|
|
3841
|
-
return workspaces.archiveSession(sessionId);
|
|
3842
|
-
},
|
|
3843
|
-
async pickDirectory() {
|
|
3844
|
-
const picker = directoryPicker();
|
|
3845
|
-
if (picker === void 0) throw new Error("directory picker is unavailable");
|
|
3846
|
-
const result = await picker.pick();
|
|
3847
|
-
if (!result.ok) throw new Error(`directory picker failed: ${result.error.message}`);
|
|
3848
|
-
return result.value;
|
|
3849
|
-
},
|
|
3850
|
-
async listDirectory(path, signal) {
|
|
3851
|
-
const picker = directoryPicker();
|
|
3852
|
-
if (picker === void 0) throw new Error("directory picker is unavailable");
|
|
3853
|
-
const result = await picker.list(path, signal);
|
|
3854
|
-
if (!result.ok) throw new DirectoryBrowseError(result.error);
|
|
3855
|
-
return result.value;
|
|
3856
|
-
},
|
|
3857
|
-
async createDirectory(path, name) {
|
|
3858
|
-
const picker = directoryPicker();
|
|
3859
|
-
if (picker === void 0) throw new Error("directory picker is unavailable");
|
|
3860
|
-
const result = await picker.createDirectory(path, name);
|
|
3861
|
-
if (!result.ok) throw new DirectoryBrowseError(result.error);
|
|
3862
|
-
return result.value;
|
|
3863
|
-
}
|
|
3864
|
-
};
|
|
3865
|
-
const dispose = ctx.provide("uiWorkspace", service);
|
|
3866
|
-
ctx.slots.provideRoot?.({ hooks: { workspaces: workspaces.list } });
|
|
3867
|
-
ctx.effect(() => {
|
|
3868
|
-
let initial = "waiting";
|
|
3869
|
-
let disposed = false;
|
|
3870
|
-
const reconcile = () => {
|
|
3871
|
-
if (disposed) return;
|
|
3872
|
-
const workspaceState = workspaces.list.getSnapshot();
|
|
3873
|
-
const sessionState = sessions.list.getSnapshot();
|
|
3874
|
-
if (sessionState.current !== void 0 && (workspaceState.archivedSessionIds ?? []).includes(sessionState.current)) {
|
|
3875
|
-
sessions.clear();
|
|
3876
|
-
return;
|
|
3877
|
-
}
|
|
3878
|
-
if (initial !== "waiting" || workspaceState.phase !== "ready" || sessionState.phase !== "ready") return;
|
|
3879
|
-
if (sessionState.current !== void 0) {
|
|
3880
|
-
initial = "done";
|
|
3881
|
-
return;
|
|
3882
|
-
}
|
|
3883
|
-
const target = recentWorkspace();
|
|
3884
|
-
if (target === void 0) {
|
|
3885
|
-
initial = "done";
|
|
3886
|
-
return;
|
|
3887
|
-
}
|
|
3888
|
-
initial = "connecting";
|
|
3889
|
-
void service.connectWorkspace(target).then((sessionId) => {
|
|
3890
|
-
if (disposed) return;
|
|
3891
|
-
if (sessions.list.getSnapshot().current === void 0) sessions.open(sessionId);
|
|
3892
|
-
initial = "done";
|
|
3893
|
-
}, (reason) => {
|
|
3894
|
-
if (disposed) return;
|
|
3895
|
-
initial = "waiting";
|
|
3896
|
-
console.warn("initial workspace selection failed:", reason);
|
|
3897
|
-
});
|
|
3898
|
-
};
|
|
3899
|
-
const disposeWorkspaces = workspaces.list.subscribe(reconcile);
|
|
3900
|
-
const disposeSessions = sessions.list.subscribe(reconcile);
|
|
3901
|
-
reconcile();
|
|
3902
|
-
return () => {
|
|
3903
|
-
disposed = true;
|
|
3904
|
-
lifetime.abort();
|
|
3905
|
-
disposeSessions();
|
|
3906
|
-
disposeWorkspaces();
|
|
3907
|
-
};
|
|
3908
|
-
}, "dsh-archive-manager: uiWorkspace navigation policy");
|
|
3909
|
-
return () => {
|
|
3910
|
-
lifetime.abort();
|
|
3911
|
-
dispose();
|
|
3912
|
-
};
|
|
3913
|
-
}
|
|
3914
3729
|
async function archiveWorkspaceSessionsAndRefresh(registry, workspaceId, refresh) {
|
|
3915
3730
|
const result = await registry.archiveWorkspaceSessions(workspaceId);
|
|
3916
3731
|
if (!result.ok) throw new Error(result.error.message);
|
|
@@ -3922,11 +3737,8 @@
|
|
|
3922
3737
|
let disposeRemote = () => {
|
|
3923
3738
|
};
|
|
3924
3739
|
if (remote !== void 0) disposeRemote = await remote.$mount(ARCHIVE_MANAGER_REMOTE);
|
|
3925
|
-
const disposeUiWorkspace = hasSplitClientStore ? provideUiWorkspace(ctx) : () => {
|
|
3926
|
-
};
|
|
3927
3740
|
applyWorkspaceBrowser(ctx);
|
|
3928
3741
|
return async () => {
|
|
3929
|
-
disposeUiWorkspace();
|
|
3930
3742
|
await disposeRemote();
|
|
3931
3743
|
};
|
|
3932
3744
|
}
|
|
@@ -3945,6 +3757,15 @@
|
|
|
3945
3757
|
createIcon: createPluginUpdateIcon
|
|
3946
3758
|
}), "dsh-archive-manager: plugin update ui");
|
|
3947
3759
|
const uiWorkspaceAt = () => ctx.get("uiWorkspace");
|
|
3760
|
+
const archiveViewState = {};
|
|
3761
|
+
let archiveNavigation;
|
|
3762
|
+
ctx.effect(() => {
|
|
3763
|
+
archiveNavigation = allowArchivedNavigation(uiWorkspaceAt(), ctx.sessions, ctx.workspaces, {
|
|
3764
|
+
onOpened: () => ctx.get("layout")?.selectPanel(null)
|
|
3765
|
+
});
|
|
3766
|
+
return () => archiveNavigation.dispose();
|
|
3767
|
+
}, "archive-manager: explicit archived navigation");
|
|
3768
|
+
const openConversation = (sessionId) => archiveNavigation.open(sessionId);
|
|
3948
3769
|
const searchSessions = async (query, signal) => {
|
|
3949
3770
|
const result = await ctx.sessions.search(query, signal);
|
|
3950
3771
|
if (!result.ok) throw new Error(result.error.message);
|
|
@@ -3954,8 +3775,7 @@
|
|
|
3954
3775
|
getSnapshot: () => ctx.slots.entries(hole).length > 0,
|
|
3955
3776
|
subscribe: (listener) => ctx.slots.subscribe(hole, listener)
|
|
3956
3777
|
});
|
|
3957
|
-
const browserFlowSource = flowSource(
|
|
3958
|
-
const pickerFlowSource = flowSource("conversation.hero.workspace.directoryFlow");
|
|
3778
|
+
const browserFlowSource = flowSource(DIRECTORY_FLOW_SLOT);
|
|
3959
3779
|
const refreshSessionList = async () => {
|
|
3960
3780
|
if (typeof ctx.sessions.refresh !== "function") return;
|
|
3961
3781
|
try {
|
|
@@ -4060,13 +3880,11 @@
|
|
|
4060
3880
|
createWorkspace: (input) => ctx.workspaces.create(input),
|
|
4061
3881
|
hooks: { directoryFlow: browserFlowSource }
|
|
4062
3882
|
});
|
|
4063
|
-
const pickerInjected = () => ({
|
|
4064
|
-
createWorkspace: (input) => ctx.workspaces.create(input),
|
|
4065
|
-
hooks: { directoryFlow: pickerFlowSource }
|
|
4066
|
-
});
|
|
4067
3883
|
ctx.slots.inject("sidebar.workspaces", () => ctx.slots.register({
|
|
4068
3884
|
name: "sidebar.workspaces",
|
|
4069
|
-
|
|
3885
|
+
// 显示顺序:Codex UI(-1)→ 归档(-0.5)→ 官方默认(0)。
|
|
3886
|
+
priority: -0.5,
|
|
3887
|
+
children: { [DIRECTORY_FLOW_SLOT]: {
|
|
4070
3888
|
kind: "single",
|
|
4071
3889
|
scope: "root"
|
|
4072
3890
|
} },
|
|
@@ -4074,15 +3892,7 @@
|
|
|
4074
3892
|
inject: browserInjected,
|
|
4075
3893
|
locale: NS
|
|
4076
3894
|
}, WorkspaceBrowser));
|
|
4077
|
-
ctx
|
|
4078
|
-
name: "conversation.hero.workspace",
|
|
4079
|
-
children: { "conversation.hero.workspace.directoryFlow": {
|
|
4080
|
-
kind: "single",
|
|
4081
|
-
scope: "root"
|
|
4082
|
-
} },
|
|
4083
|
-
inject: pickerInjected,
|
|
4084
|
-
locale: NS
|
|
4085
|
-
}, WorkspacePicker));
|
|
3895
|
+
mirrorDirectoryFlow(ctx, DIRECTORY_FLOW_SLOT);
|
|
4086
3896
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
4087
3897
|
name: "settings.section",
|
|
4088
3898
|
id: "archived-sessions",
|
|
@@ -4098,11 +3908,15 @@
|
|
|
4098
3908
|
unarchiveSessions,
|
|
4099
3909
|
deleteArchivedSessions,
|
|
4100
3910
|
archivedSessionMetadata,
|
|
3911
|
+
openConversation,
|
|
3912
|
+
viewState: archiveViewState,
|
|
4101
3913
|
t: ctx.locale.bind(NS)
|
|
4102
3914
|
})
|
|
4103
|
-
},
|
|
3915
|
+
}, ArchivedSessionsSection));
|
|
4104
3916
|
}
|
|
4105
3917
|
exports.__test = {
|
|
3918
|
+
ArchivedSessionsSection,
|
|
3919
|
+
zh,
|
|
4106
3920
|
displayTitle,
|
|
4107
3921
|
sessionVisible,
|
|
4108
3922
|
indexSubagentDescendants,
|
|
@@ -4124,7 +3938,6 @@
|
|
|
4124
3938
|
createWorkspaceViewStore,
|
|
4125
3939
|
bindObservable,
|
|
4126
3940
|
hasSplitClientStore,
|
|
4127
|
-
provideUiWorkspace,
|
|
4128
3941
|
groupByWorkspace,
|
|
4129
3942
|
byRecency,
|
|
4130
3943
|
ARCHIVE_MANAGER_REMOTE
|