@michengai/dsh-codex-ui 1.1.12 → 1.1.14
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 +49 -0
- package/CHANGELOG.zh-CN.md +49 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/lib/client.js +594 -193
- package/lib/session-title-plugin.mjs +4 -0
- package/lib/usage-frame.css +1 -1
- package/lib/usage-frame.js +98 -98
- package/package.json +37 -37
package/lib/client.js
CHANGED
|
@@ -8,11 +8,167 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
10
|
let react_dom = require("react-dom");
|
|
11
|
+
//#region src/client/session-host.ts
|
|
12
|
+
var UnknownSessionError = class extends Error {
|
|
13
|
+
constructor() {
|
|
14
|
+
super("unknown session");
|
|
15
|
+
this.name = "UnknownSessionError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/** 旧宿主读 list.current;alpha.2 主视图改由 retainedBy.mainView 标记。 */
|
|
19
|
+
function currentSessionId(state) {
|
|
20
|
+
if (state === void 0) return void 0;
|
|
21
|
+
if (typeof state.current === "string" && state.current !== "") return state.current;
|
|
22
|
+
const byId = state.byId ?? {};
|
|
23
|
+
const ids = Array.isArray(state.ids) && state.ids.length > 0 ? state.ids : Object.keys(byId);
|
|
24
|
+
const pick = (id, row) => {
|
|
25
|
+
if (row === void 0 || (row.retainedBy?.mainView ?? 0) <= 0) return void 0;
|
|
26
|
+
const explicit = row.id?.trim();
|
|
27
|
+
return explicit !== void 0 && explicit !== "" ? explicit : id;
|
|
28
|
+
};
|
|
29
|
+
for (const id of ids) {
|
|
30
|
+
const found = pick(id, byId[id]);
|
|
31
|
+
if (found !== void 0) return found;
|
|
32
|
+
}
|
|
33
|
+
for (const id of Object.keys(byId)) {
|
|
34
|
+
if (ids.includes(id)) continue;
|
|
35
|
+
const found = pick(id, byId[id]);
|
|
36
|
+
if (found !== void 0) return found;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** 官方树在全局面板打开时取消会话选中。 */
|
|
40
|
+
function visibleSelectedSessionId(state, panelActive = false) {
|
|
41
|
+
return panelActive ? void 0 : currentSessionId(state);
|
|
42
|
+
}
|
|
43
|
+
function sessionRowUnread(localUnread, status, selected = false) {
|
|
44
|
+
return localUnread || status?.completionUnread === true && !selected;
|
|
45
|
+
}
|
|
46
|
+
function sessionRunningFlags(byId, status) {
|
|
47
|
+
const ids = new Set(Object.keys(byId));
|
|
48
|
+
if (status !== void 0) for (const id of status.keys()) ids.add(id);
|
|
49
|
+
const next = {};
|
|
50
|
+
for (const id of ids) next[id] = sessionIsRunning(byId[id], status?.get(id));
|
|
51
|
+
return next;
|
|
52
|
+
}
|
|
53
|
+
/** 旧宿主看 current 是否空会话;alpha.2 看主视图 retain 的 blank。 */
|
|
54
|
+
function isBlankOnboardingSession(state) {
|
|
55
|
+
if (state?.phase !== "ready") return false;
|
|
56
|
+
const id = currentSessionId(state);
|
|
57
|
+
return id === void 0 || state.byId?.[id]?.blank === true;
|
|
58
|
+
}
|
|
59
|
+
function hostAccess(ctx) {
|
|
60
|
+
return ctx;
|
|
61
|
+
}
|
|
62
|
+
/** 有 reflect 时只 probe,不能硬读未注入服务,否则 Cordis 会挡住插件激活。 */
|
|
63
|
+
function probeService(ctx, name) {
|
|
64
|
+
if (ctx === void 0) return void 0;
|
|
65
|
+
const access = hostAccess(ctx);
|
|
66
|
+
const reflectGet = access.reflect?.get;
|
|
67
|
+
const hasReflect = typeof reflectGet === "function";
|
|
68
|
+
if (hasReflect) try {
|
|
69
|
+
const found = reflectGet.call(access.reflect, name);
|
|
70
|
+
if (found !== void 0) return found;
|
|
71
|
+
} catch {}
|
|
72
|
+
if (typeof access.get === "function") try {
|
|
73
|
+
const found = access.get(name);
|
|
74
|
+
if (found !== void 0) return found;
|
|
75
|
+
} catch {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (hasReflect) return void 0;
|
|
79
|
+
try {
|
|
80
|
+
return access[name];
|
|
81
|
+
} catch {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function openHostSession(ctx, id) {
|
|
86
|
+
if (id === "") return false;
|
|
87
|
+
const access = hostAccess(ctx);
|
|
88
|
+
const uiWorkspace = probeService(access, "uiWorkspace");
|
|
89
|
+
if (typeof uiWorkspace?.openSession === "function") {
|
|
90
|
+
uiWorkspace.openSession(id);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (typeof access.sessions?.retain === "function") return false;
|
|
94
|
+
if (typeof access.sessions?.open === "function") {
|
|
95
|
+
access.sessions.open(id);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
async function withSessionBinding(sessions, sessionId, operation) {
|
|
101
|
+
const host = sessions === void 0 ? void 0 : hostAccess({ sessions }).sessions;
|
|
102
|
+
if (host === void 0) throw new UnknownSessionError();
|
|
103
|
+
if (typeof host.using === "function") return host.using(sessionId, { source: "controllerOperation" }, async (reference) => {
|
|
104
|
+
if (reference.ready !== void 0) await reference.ready;
|
|
105
|
+
if (reference.binding === void 0) throw new UnknownSessionError();
|
|
106
|
+
return operation(reference.binding);
|
|
107
|
+
});
|
|
108
|
+
const existing = host.binding?.(sessionId);
|
|
109
|
+
if (existing !== void 0) return operation(existing);
|
|
110
|
+
if (typeof host.retain !== "function") throw new UnknownSessionError();
|
|
111
|
+
const reference = host.retain(sessionId, { source: "controllerOperation" });
|
|
112
|
+
try {
|
|
113
|
+
if (reference.ready !== void 0) await reference.ready;
|
|
114
|
+
if (reference.binding === void 0) throw new UnknownSessionError();
|
|
115
|
+
return await operation(reference.binding);
|
|
116
|
+
} finally {
|
|
117
|
+
reference.release?.();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function renameHostSession(ctx, sessionId, title) {
|
|
121
|
+
await withSessionBinding(hostAccess(ctx).sessions, sessionId, async (binding) => {
|
|
122
|
+
if (typeof binding.session?.rename !== "function") throw new UnknownSessionError();
|
|
123
|
+
const result = await binding.session.rename(title);
|
|
124
|
+
if (result.ok === false) throw result.error ?? /* @__PURE__ */ new Error("rename failed");
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async function forkHostSession(ctx, sessionId) {
|
|
128
|
+
const access = hostAccess(ctx);
|
|
129
|
+
const uiWorkspace = probeService(access, "uiWorkspace");
|
|
130
|
+
if (typeof uiWorkspace?.forkSession === "function") {
|
|
131
|
+
await uiWorkspace.forkSession(sessionId);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const childId = await access.sessions?.fork?.({
|
|
135
|
+
sessionId,
|
|
136
|
+
increaseTitle: true
|
|
137
|
+
});
|
|
138
|
+
if (typeof childId === "string" && childId !== "") openHostSession(access, childId);
|
|
139
|
+
}
|
|
140
|
+
async function archiveHostSession(ctx, sessionId) {
|
|
141
|
+
const access = hostAccess(ctx);
|
|
142
|
+
const uiWorkspace = probeService(access, "uiWorkspace");
|
|
143
|
+
if (typeof uiWorkspace?.archiveSession === "function") {
|
|
144
|
+
await uiWorkspace.archiveSession(sessionId);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
await access.workspaces?.archiveSession?.(sessionId);
|
|
148
|
+
}
|
|
149
|
+
function mergePendingInteractions(legacy, status) {
|
|
150
|
+
const next = new Map(legacy);
|
|
151
|
+
for (const [id, row] of status) if (row?.pendingInteraction !== void 0) next.set(id, row.pendingInteraction);
|
|
152
|
+
return next;
|
|
153
|
+
}
|
|
154
|
+
function sessionIsRunning(session, status) {
|
|
155
|
+
if (status?.running !== void 0) return status.running === true;
|
|
156
|
+
return session?.running === true;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
11
159
|
//#region src/client/session-navigation.ts
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
160
|
+
function openConversation(host, layout, id) {
|
|
161
|
+
const opened = openHostSession(host, id);
|
|
162
|
+
if (opened) selectGlobalPanel(layout, null);
|
|
163
|
+
return opened;
|
|
164
|
+
}
|
|
165
|
+
/** 先打开再写草稿,避免 using 释放后 composer 换新 binding。 */
|
|
166
|
+
async function openConversationWithDraft(host, layout, sessions, sessionId, writeDraft) {
|
|
167
|
+
return withSessionBinding(sessions, sessionId, (binding) => {
|
|
168
|
+
const opened = openConversation(host, layout, sessionId);
|
|
169
|
+
writeDraft(binding);
|
|
170
|
+
return opened;
|
|
171
|
+
});
|
|
16
172
|
}
|
|
17
173
|
/** 统一检测旧宿主是否提供面板切换能力,保留宿主方法的 this。 */
|
|
18
174
|
function selectGlobalPanel(layout, id) {
|
|
@@ -720,17 +876,112 @@ window.__ModuleLoader__.load({
|
|
|
720
876
|
key: "17ys0d"
|
|
721
877
|
}]]);
|
|
722
878
|
//#endregion
|
|
879
|
+
//#region src/client/settings-navigation.ts
|
|
880
|
+
/**
|
|
881
|
+
* DSH 设置壳暂未提供按 section id 打开的公开 API。该兼容层只从本插件渲染
|
|
882
|
+
* 的设置入口触发,再按壳的可访问名称选择页面;宿主升级时可集中替换。
|
|
883
|
+
*/
|
|
884
|
+
function pickSettingsSectionButton(buttons, labels) {
|
|
885
|
+
for (const label of labels) {
|
|
886
|
+
const match = buttons.find((button) => button.textContent?.trim() === label);
|
|
887
|
+
if (match !== void 0) return match;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* 可选插件未注册设置入口时,直接打开兜底页,避免先展示通用设置并等待导航超时。
|
|
892
|
+
*/
|
|
893
|
+
function routeOptionalSettingsSection(available, openRequested, openFallback) {
|
|
894
|
+
if (available) {
|
|
895
|
+
openRequested();
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
openFallback();
|
|
899
|
+
}
|
|
900
|
+
/** 官方 alpha.2 插件管理页占用 sidebar.panellist / main 的同一 id。 */
|
|
901
|
+
const OFFICIAL_PLUGINS_PANEL_ID = "plugins";
|
|
902
|
+
let cancelPendingNavigation;
|
|
903
|
+
const SETTINGS_NAVIGATION_TIMEOUT_MS = 4e3;
|
|
904
|
+
const SETTINGS_TRIGGER_SELECTOR = "[data-dcu-settings-trigger],[aria-haspopup=\"dialog\"]";
|
|
905
|
+
const SETTINGS_OPEN_SECTION_EVENT = "dcu-settings-open-section";
|
|
906
|
+
/** 根入口与分区跳转使用同一触发器合约,兼容保留的宿主设置壳。 */
|
|
907
|
+
function openSettingsRoot(root) {
|
|
908
|
+
root?.querySelector(SETTINGS_TRIGGER_SELECTOR)?.click();
|
|
909
|
+
}
|
|
910
|
+
function openSettingsSection(root, label, onMissing, onSelected) {
|
|
911
|
+
const labels = typeof label === "string" ? [label] : label;
|
|
912
|
+
const trigger = root?.querySelector(SETTINGS_TRIGGER_SELECTOR);
|
|
913
|
+
if (trigger === null || trigger === void 0) {
|
|
914
|
+
onMissing?.();
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const opening = cancelPendingNavigation !== void 0;
|
|
918
|
+
cancelPendingNavigation?.();
|
|
919
|
+
const request = new CustomEvent(SETTINGS_OPEN_SECTION_EVENT, {
|
|
920
|
+
detail: { labels },
|
|
921
|
+
cancelable: true
|
|
922
|
+
});
|
|
923
|
+
if (!trigger.dispatchEvent(request)) {
|
|
924
|
+
onSelected?.();
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
const pageSelector = trigger.hasAttribute("data-dcu-settings-trigger") ? "[data-dcu-settings-page]" : "[role=\"dialog\"]";
|
|
928
|
+
if (!opening && document.querySelector(pageSelector) === null) trigger.click();
|
|
929
|
+
let frame;
|
|
930
|
+
let finished = false;
|
|
931
|
+
const observer = new MutationObserver(() => {
|
|
932
|
+
schedule();
|
|
933
|
+
});
|
|
934
|
+
const cleanup = () => {
|
|
935
|
+
if (finished) return;
|
|
936
|
+
finished = true;
|
|
937
|
+
observer.disconnect();
|
|
938
|
+
window.clearTimeout(timeout);
|
|
939
|
+
if (frame !== void 0) window.cancelAnimationFrame(frame);
|
|
940
|
+
if (cancelPendingNavigation === cleanup) cancelPendingNavigation = void 0;
|
|
941
|
+
};
|
|
942
|
+
const select = () => {
|
|
943
|
+
const target = pickSettingsSectionButton([...document.querySelectorAll(`${pageSelector} nav button`)], labels);
|
|
944
|
+
if (target === void 0) return false;
|
|
945
|
+
cleanup();
|
|
946
|
+
target.click();
|
|
947
|
+
onSelected?.();
|
|
948
|
+
return true;
|
|
949
|
+
};
|
|
950
|
+
const schedule = () => {
|
|
951
|
+
if (finished || frame !== void 0) return;
|
|
952
|
+
frame = window.requestAnimationFrame(() => {
|
|
953
|
+
frame = void 0;
|
|
954
|
+
select();
|
|
955
|
+
});
|
|
956
|
+
};
|
|
957
|
+
const timeout = window.setTimeout(() => {
|
|
958
|
+
if (select()) return;
|
|
959
|
+
cleanup();
|
|
960
|
+
console.warn(`[michengai-codex-ui] 未找到设置分区:${labels.join(" / ")}`);
|
|
961
|
+
onMissing?.();
|
|
962
|
+
}, SETTINGS_NAVIGATION_TIMEOUT_MS);
|
|
963
|
+
observer.observe(document.body, {
|
|
964
|
+
childList: true,
|
|
965
|
+
subtree: true
|
|
966
|
+
});
|
|
967
|
+
cancelPendingNavigation = cleanup;
|
|
968
|
+
schedule();
|
|
969
|
+
}
|
|
970
|
+
//#endregion
|
|
723
971
|
//#region src/client/global-panels.tsx
|
|
724
972
|
/** 从宿主注册表读取面板元数据;缓存快照以满足 React 外部状态订阅契约。 */
|
|
725
973
|
function createGlobalPanelSource(slots, locale) {
|
|
726
974
|
let cached = [];
|
|
727
975
|
return {
|
|
728
976
|
getSnapshot() {
|
|
729
|
-
const next = slots.entriesOfSlot("sidebar.panellist").flatMap(({ options }) =>
|
|
730
|
-
id
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
977
|
+
const next = slots.entriesOfSlot("sidebar.panellist").flatMap(({ options }) => {
|
|
978
|
+
if (options.id === void 0 || options.id === "plugins") return [];
|
|
979
|
+
return [{
|
|
980
|
+
id: options.id,
|
|
981
|
+
order: options.order ?? 0,
|
|
982
|
+
label: (typeof options.label === "function" ? options.label() : options.label) ?? options.id
|
|
983
|
+
}];
|
|
984
|
+
}).sort((a, b) => a.order - b.order);
|
|
734
985
|
if (next.length !== cached.length || next.some((panel, index) => {
|
|
735
986
|
const previous = cached[index];
|
|
736
987
|
return previous === void 0 || panel.id !== previous.id || panel.label !== previous.label || panel.order !== previous.order;
|
|
@@ -907,96 +1158,6 @@ window.__ModuleLoader__.load({
|
|
|
907
1158
|
} catch {}
|
|
908
1159
|
}
|
|
909
1160
|
//#endregion
|
|
910
|
-
//#region src/client/settings-navigation.ts
|
|
911
|
-
/**
|
|
912
|
-
* DSH 设置壳暂未提供按 section id 打开的公开 API。该兼容层只从本插件渲染
|
|
913
|
-
* 的设置入口触发,再按壳的可访问名称选择页面;宿主升级时可集中替换。
|
|
914
|
-
*/
|
|
915
|
-
function pickSettingsSectionButton(buttons, labels) {
|
|
916
|
-
for (const label of labels) {
|
|
917
|
-
const match = buttons.find((button) => button.textContent?.trim() === label);
|
|
918
|
-
if (match !== void 0) return match;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* 可选插件未注册设置入口时,直接打开兜底页,避免先展示通用设置并等待导航超时。
|
|
923
|
-
*/
|
|
924
|
-
function routeOptionalSettingsSection(available, openRequested, openFallback) {
|
|
925
|
-
if (available) {
|
|
926
|
-
openRequested();
|
|
927
|
-
return;
|
|
928
|
-
}
|
|
929
|
-
openFallback();
|
|
930
|
-
}
|
|
931
|
-
let cancelPendingNavigation;
|
|
932
|
-
const SETTINGS_NAVIGATION_TIMEOUT_MS = 4e3;
|
|
933
|
-
const SETTINGS_TRIGGER_SELECTOR = "[data-dcu-settings-trigger],[aria-haspopup=\"dialog\"]";
|
|
934
|
-
const SETTINGS_OPEN_SECTION_EVENT = "dcu-settings-open-section";
|
|
935
|
-
/** 根入口与分区跳转使用同一触发器合约,兼容保留的宿主设置壳。 */
|
|
936
|
-
function openSettingsRoot(root) {
|
|
937
|
-
root?.querySelector(SETTINGS_TRIGGER_SELECTOR)?.click();
|
|
938
|
-
}
|
|
939
|
-
function openSettingsSection(root, label, onMissing, onSelected) {
|
|
940
|
-
const labels = typeof label === "string" ? [label] : label;
|
|
941
|
-
const trigger = root?.querySelector(SETTINGS_TRIGGER_SELECTOR);
|
|
942
|
-
if (trigger === null || trigger === void 0) {
|
|
943
|
-
onMissing?.();
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
const opening = cancelPendingNavigation !== void 0;
|
|
947
|
-
cancelPendingNavigation?.();
|
|
948
|
-
const request = new CustomEvent(SETTINGS_OPEN_SECTION_EVENT, {
|
|
949
|
-
detail: { labels },
|
|
950
|
-
cancelable: true
|
|
951
|
-
});
|
|
952
|
-
if (!trigger.dispatchEvent(request)) {
|
|
953
|
-
onSelected?.();
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
956
|
-
const pageSelector = trigger.hasAttribute("data-dcu-settings-trigger") ? "[data-dcu-settings-page]" : "[role=\"dialog\"]";
|
|
957
|
-
if (!opening && document.querySelector(pageSelector) === null) trigger.click();
|
|
958
|
-
let frame;
|
|
959
|
-
let finished = false;
|
|
960
|
-
const observer = new MutationObserver(() => {
|
|
961
|
-
schedule();
|
|
962
|
-
});
|
|
963
|
-
const cleanup = () => {
|
|
964
|
-
if (finished) return;
|
|
965
|
-
finished = true;
|
|
966
|
-
observer.disconnect();
|
|
967
|
-
window.clearTimeout(timeout);
|
|
968
|
-
if (frame !== void 0) window.cancelAnimationFrame(frame);
|
|
969
|
-
if (cancelPendingNavigation === cleanup) cancelPendingNavigation = void 0;
|
|
970
|
-
};
|
|
971
|
-
const select = () => {
|
|
972
|
-
const target = pickSettingsSectionButton([...document.querySelectorAll(`${pageSelector} nav button`)], labels);
|
|
973
|
-
if (target === void 0) return false;
|
|
974
|
-
cleanup();
|
|
975
|
-
target.click();
|
|
976
|
-
onSelected?.();
|
|
977
|
-
return true;
|
|
978
|
-
};
|
|
979
|
-
const schedule = () => {
|
|
980
|
-
if (finished || frame !== void 0) return;
|
|
981
|
-
frame = window.requestAnimationFrame(() => {
|
|
982
|
-
frame = void 0;
|
|
983
|
-
select();
|
|
984
|
-
});
|
|
985
|
-
};
|
|
986
|
-
const timeout = window.setTimeout(() => {
|
|
987
|
-
if (select()) return;
|
|
988
|
-
cleanup();
|
|
989
|
-
console.warn(`[michengai-codex-ui] 未找到设置分区:${labels.join(" / ")}`);
|
|
990
|
-
onMissing?.();
|
|
991
|
-
}, SETTINGS_NAVIGATION_TIMEOUT_MS);
|
|
992
|
-
observer.observe(document.body, {
|
|
993
|
-
childList: true,
|
|
994
|
-
subtree: true
|
|
995
|
-
});
|
|
996
|
-
cancelPendingNavigation = cleanup;
|
|
997
|
-
schedule();
|
|
998
|
-
}
|
|
999
|
-
//#endregion
|
|
1000
1161
|
//#region src/client/sidebar-search.ts
|
|
1001
1162
|
/** 按用户可见名称和辅助关键词筛选侧栏搜索结果。 */
|
|
1002
1163
|
function filterSidebarSearchItems(items, query) {
|
|
@@ -1587,9 +1748,20 @@ window.__ModuleLoader__.load({
|
|
|
1587
1748
|
//#endregion
|
|
1588
1749
|
//#region src/client/session-pending.ts
|
|
1589
1750
|
const EMPTY_PENDING_INTERACTIONS = /* @__PURE__ */ new Map();
|
|
1751
|
+
const EMPTY_SESSION_STATUS = /* @__PURE__ */ new Map();
|
|
1590
1752
|
function useEmptySessionPendingInteraction(selector) {
|
|
1591
1753
|
return selector(EMPTY_PENDING_INTERACTIONS);
|
|
1592
1754
|
}
|
|
1755
|
+
function useEmptySessionStatus(selector) {
|
|
1756
|
+
return selector(EMPTY_SESSION_STATUS);
|
|
1757
|
+
}
|
|
1758
|
+
function useHostSessionStatus(useSessionStatus) {
|
|
1759
|
+
return (useSessionStatus ?? useEmptySessionStatus)((state) => state);
|
|
1760
|
+
}
|
|
1761
|
+
/** 旧宿主订阅 pending Store;alpha.2 改走 useSessionStatus。两路都要订阅,避免条件 Hook。 */
|
|
1762
|
+
function useHostPendingInteractions(useSessionPendingInteraction, useSessionStatus) {
|
|
1763
|
+
return mergePendingInteractions((useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state), (useSessionStatus ?? useEmptySessionStatus)((state) => state));
|
|
1764
|
+
}
|
|
1593
1765
|
function visiblePendingKind(kind) {
|
|
1594
1766
|
switch (kind) {
|
|
1595
1767
|
case "approval":
|
|
@@ -2081,12 +2253,12 @@ window.__ModuleLoader__.load({
|
|
|
2081
2253
|
const HEADER_PROJECT_TIP_EVENT = "dcu-header-project-tip";
|
|
2082
2254
|
const HEADER_SESSION_MENU_EVENT = "dcu-header-session-menu";
|
|
2083
2255
|
const CONVERSATION_HEADER_STYLE = `
|
|
2084
|
-
header:has([data-dcu-inline-tabs]){box-sizing:border-box;display:flex;flex-wrap:
|
|
2256
|
+
header:has([data-dcu-inline-tabs]){box-sizing:border-box;display:flex;flex-wrap:nowrap;align-items:center;gap:10px;min-height:34px;padding-top:3px;padding-bottom:3px;border-bottom:0}
|
|
2085
2257
|
header:has([data-dcu-inline-tabs]):after{display:none;content:none}
|
|
2086
2258
|
header:has([data-dcu-inline-tabs]) [class*="titleRow"],header:has([data-dcu-inline-tabs]) [class*="titleCluster"]{display:contents}
|
|
2087
|
-
header:has([data-dcu-inline-tabs]) [class*="crumbs"]{order:1;flex:1;min-width:0}
|
|
2259
|
+
header:has([data-dcu-inline-tabs]) [class*="crumbs"]{order:1;flex:0 1 auto;min-width:0}
|
|
2088
2260
|
header:has([data-dcu-inline-tabs]) [class*="headerActions"]{order:2;flex:none}
|
|
2089
|
-
header [data-dcu-inline-tabs]{box-sizing:border-box;order:3;flex:none;display:flex;align-items:center;gap:0;margin:0;padding:0;height:28px;position:relative;z-index:1;overflow:hidden;border:1px solid var(--dsw-alias-border-subtle,rgba(255,255,255,.12));border-radius:8px;background:var(--dsw-alias-background-secondary,rgba(255,255,255,.025))}
|
|
2261
|
+
header [data-dcu-inline-tabs]{box-sizing:border-box;order:3;flex:none;display:flex;align-items:center;gap:0;margin:0 0 0 auto;padding:0;height:28px;position:relative;z-index:1;overflow:hidden;border:1px solid var(--dsw-alias-border-subtle,rgba(255,255,255,.12));border-radius:8px;background:var(--dsw-alias-background-secondary,rgba(255,255,255,.025))}
|
|
2090
2262
|
header:has([data-dcu-inline-tabs]) [class*="headerUtilities"]{order:4;flex:none}
|
|
2091
2263
|
/* 新版角落插槽被 display:contents 摊平后,需要独立排序并撤销嵌套布局的边距补偿。 */
|
|
2092
2264
|
header:has([data-dcu-inline-tabs]) [data-conversation-header-corner]{order:5;flex:none;margin-left:0;margin-right:0}
|
|
@@ -2729,6 +2901,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2729
2901
|
function hasConnectWorkspace(value) {
|
|
2730
2902
|
return value !== null && typeof value === "object" && "connectWorkspace" in value && typeof value.connectWorkspace === "function";
|
|
2731
2903
|
}
|
|
2904
|
+
function hasOpenWorkspace(value) {
|
|
2905
|
+
return value !== null && typeof value === "object" && "openWorkspace" in value && typeof value.openWorkspace === "function";
|
|
2906
|
+
}
|
|
2732
2907
|
/** 与 DSH 官方最近工作区策略一致;时间相同时保留 Host 工作区顺序。 */
|
|
2733
2908
|
function recentWorkspaceId(workspaces, sessions) {
|
|
2734
2909
|
let selected;
|
|
@@ -2963,10 +3138,23 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2963
3138
|
lower = after ? rows[index + 1]?.rect.top : edge.rect.top;
|
|
2964
3139
|
} else if (target.matches(".dcu-wb-pin-start,.dcu-wb-pin-end")) {
|
|
2965
3140
|
if (anchor.width <= 0 || anchor.height <= 0) return void 0;
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
3141
|
+
const itemRows = rows.filter((row) => !row.node.matches(".dcu-wb-section-head,.dcu-wb-empty,.dcu-wb-nochat"));
|
|
3142
|
+
if (target.matches(".dcu-wb-pin-end") && itemRows.length > 0) {
|
|
3143
|
+
const last = itemRows[itemRows.length - 1];
|
|
3144
|
+
anchor = last.rect;
|
|
3145
|
+
upper = last.rect.bottom;
|
|
3146
|
+
lower = rows.find((row) => row.rect.top >= last.rect.bottom - .5)?.rect.top;
|
|
3147
|
+
} else if (target.matches(".dcu-wb-pin-start") && itemRows.length > 0) {
|
|
3148
|
+
const first = itemRows[0];
|
|
3149
|
+
anchor = first.rect;
|
|
3150
|
+
lower = first.rect.top;
|
|
3151
|
+
upper = rows.filter((row) => row.rect.bottom <= first.rect.top + .5).at(-1)?.rect.bottom;
|
|
3152
|
+
} else {
|
|
3153
|
+
upper = rows.filter((row) => row.rect.bottom <= anchor.top).at(-1)?.rect.bottom;
|
|
3154
|
+
lower = rows.find((row) => row.rect.top >= anchor.bottom)?.rect.top;
|
|
3155
|
+
if (lower === void 0) lower = anchor.bottom;
|
|
3156
|
+
if (upper === void 0) upper = anchor.top;
|
|
3157
|
+
}
|
|
2970
3158
|
} else return void 0;
|
|
2971
3159
|
const center = upper === void 0 ? lower - 4 : lower === void 0 ? upper + 4 : (upper + lower) / 2;
|
|
2972
3160
|
const box = root.getBoundingClientRect();
|
|
@@ -3145,7 +3333,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3145
3333
|
.dcu-wb-project-head:hover,.dcu-wb-project-head.dcu-wb-menu-open,.dcu-wb-session:hover,.dcu-wb-session.dcu-wb-selected,.dcu-wb-session.dcu-wb-menu-open{background:var(--dcu-sidebar-hover)}.dcu-wb-project.dcu-wb-session-drop>.dcu-wb-project-head{border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.dcu-wb-project.dcu-wb-session-move-drop{border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.dcu-wb-project.dcu-wb-session-move-drop>.dcu-wb-project-head{background:transparent;outline:0}.dcu-wb-project-body>.dcu-wb-session:first-child,.dcu-wb-project-body>.dcu-wb-nochat:first-child{margin-top:4px}.dcu-wb-session+.dcu-wb-session{margin-top:2px}
|
|
3146
3334
|
.dcu-wb-project-head[draggable=true],.dcu-wb-session[draggable=true]{cursor:grab}
|
|
3147
3335
|
.dcu-wb-project-head[draggable=true]:active,.dcu-wb-session[draggable=true]:active{cursor:grabbing}
|
|
3148
|
-
.dcu-wb-section,.dcu-wb-section:focus,.dcu-wb-section:focus-visible,.dcu-wb-project-head:focus,.dcu-wb-session:focus{outline:0}.dcu-wb-pin-end,.dcu-wb-pin-start{position:
|
|
3336
|
+
.dcu-wb-section,.dcu-wb-section:focus,.dcu-wb-section:focus-visible,.dcu-wb-project-head:focus,.dcu-wb-session:focus{outline:0}.dcu-wb-pinned-list{position:relative}.dcu-wb-pin-end,.dcu-wb-pin-start{position:absolute;left:0;right:0;height:8px;z-index:2;pointer-events:none}.dcu-wb-pin-end.dcu-wb-drop,.dcu-wb-pin-start.dcu-wb-drop{pointer-events:auto}.dcu-wb-pin-start{top:0}.dcu-wb-pin-end{bottom:-8px}.dcu-wb-project.dcu-wb-drop::before,.dcu-wb-session.dcu-wb-drop::before,.dcu-wb-pin-end.dcu-wb-drop::before,.dcu-wb-pin-start.dcu-wb-drop::before{content:"";position:absolute;z-index:2;left:7px;right:8px;top:-8px;height:8px;pointer-events:none;background:radial-gradient(circle at 4px 50%,transparent 1.75px,var(--dsw-alias-state-business-primary) 2px 3.75px,transparent 4px),linear-gradient(var(--dsw-alias-state-business-primary),var(--dsw-alias-state-business-primary)) 10px 50%/calc(100% - 10px) 2px no-repeat}.dcu-wb-pin-start.dcu-wb-drop::before{top:0}.dcu-wb-pinned-list>.dcu-wb-project:first-child.dcu-wb-drop::before{top:-4px}.dcu-wb-project.dcu-wb-drop-after::before,.dcu-wb-session.dcu-wb-drop-after::before{top:auto;bottom:-8px}.dcu-wb-dragging{opacity:.28}.dcu-wb-drag-ghost{position:fixed;top:8px;left:-9999px;z-index:10040;display:flex;align-items:center;gap:8px;max-width:220px;height:30px;padding:0 10px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:var(--dcu-sidebar-hover);box-shadow:0 4px 12px rgba(0,0,0,.24);color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font,inherit);white-space:nowrap;pointer-events:none}.dcu-wb-drag-ghost-icon{display:grid;place-items:center;flex:none;width:16px;height:16px;color:var(--dcu-sidebar-icon)}.dcu-wb-drag-ghost-icon svg{display:block;width:16px;height:16px}.dcu-wb-drag-ghost-title{min-width:0;overflow:hidden;text-overflow:ellipsis}
|
|
3149
3337
|
.dcu-wb-folder{display:grid;place-items:center;flex:none;width:16px;height:20px;color:var(--dcu-sidebar-icon)}.dcu-wb-folder.dcu-wb-folder-current{color:var(--dsw-alias-state-business-primary)}.dcu-wb-brand{display:block;width:16px;height:16px}
|
|
3150
3338
|
.dcu-wb-project-title,.dcu-wb-session-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px}
|
|
3151
3339
|
.dcu-wb-project-title{flex:1;font-weight:400;color:var(--dcu-sidebar-primary)}
|
|
@@ -3181,7 +3369,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3181
3369
|
.dcu-wb-drop-indicator::before{content:"";position:absolute;left:6px;right:0;top:3px;height:2px;border-radius:999px;background:currentColor}
|
|
3182
3370
|
.dcu-wb-drop-indicator::after{content:"";position:absolute;box-sizing:border-box;left:0;top:0;width:8px;height:8px;border:2px solid currentColor;border-radius:50%}
|
|
3183
3371
|
.dcu-wb-project-body:has(>.dcu-wb-session)::after{content:"";display:block;height:4px;pointer-events:none}
|
|
3184
|
-
.dcu-wb-section-body[data-open=true]:has(.dcu-wb-group-order-drop){overflow:visible}
|
|
3372
|
+
.dcu-wb-section-body[data-open=true]:has(.dcu-wb-group-order-drop),.dcu-wb-section-body[data-open=true]:has(.dcu-wb-pin-end),.dcu-wb-section-body[data-open=true]:has(.dcu-wb-pin-start){overflow:visible}
|
|
3185
3373
|
.dcu-wb-collection-body{padding-left:0}
|
|
3186
3374
|
.dcu-wb-collection-body>.dcu-wb-group-member:first-child{padding-top:4px}
|
|
3187
3375
|
.dcu-wb-collection-body .dcu-wb-project-head{padding-left:8px}
|
|
@@ -3223,10 +3411,12 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3223
3411
|
function CodexWorkspaceBrowser(props) {
|
|
3224
3412
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverShell, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexWorkspaceTree, { ...props }) });
|
|
3225
3413
|
}
|
|
3226
|
-
function CodexWorkspaceTree({ wide, useSessions, useSessionPendingInteraction, useWorkspaces, t, archiveSession, deleteSession, deleteWorkspace, forkSession, insertSessionBefore, insertWorkspaceBefore, moveSession, openPath, openSession, renameSession, renameWorkspace, startSession, canDeleteSession }) {
|
|
3414
|
+
function CodexWorkspaceTree({ wide, useSessions, useSessionPendingInteraction, useSessionStatus, useWorkspaces, t, archiveSession, deleteSession, deleteWorkspace, forkSession, insertSessionBefore, insertWorkspaceBefore, moveSession, openPath, openSession, renameSession, renameWorkspace, startSession, canDeleteSession, panelActive = false }) {
|
|
3227
3415
|
const sessions = useSessions((state) => state);
|
|
3228
3416
|
const now = useSharedNow();
|
|
3229
|
-
const pendingInteractions = (useSessionPendingInteraction
|
|
3417
|
+
const pendingInteractions = useHostPendingInteractions(useSessionPendingInteraction, useSessionStatus);
|
|
3418
|
+
const sessionStatus = useHostSessionStatus(useSessionStatus);
|
|
3419
|
+
const selectedId = visibleSelectedSessionId(sessions, panelActive);
|
|
3230
3420
|
const workspaces = useWorkspaces((state) => state);
|
|
3231
3421
|
const baselinesReady = workspaceBaselinesReady(workspaces, sessions);
|
|
3232
3422
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY));
|
|
@@ -3288,6 +3478,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3288
3478
|
setWorkspaceGroupsState(next);
|
|
3289
3479
|
};
|
|
3290
3480
|
const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY));
|
|
3481
|
+
const rowUnread = (id) => sessionRowUnread(unreadSessionIds.includes(id), sessionStatus.get(id), selectedId === id);
|
|
3482
|
+
const rowRunning = (id, session) => sessionIsRunning(session ?? sessions.byId[id], sessionStatus.get(id));
|
|
3291
3483
|
const previousSessionRunningRef = (0, react.useRef)();
|
|
3292
3484
|
const [menu, setMenu] = (0, react.useState)();
|
|
3293
3485
|
const [renameTarget, setRenameTarget] = (0, react.useState)();
|
|
@@ -3407,17 +3599,20 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3407
3599
|
}
|
|
3408
3600
|
}, [baselinesReady, workspaces.items]);
|
|
3409
3601
|
(0, react.useEffect)(() => {
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
}, [sessions.current]);
|
|
3602
|
+
if (selectedId !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== selectedId));
|
|
3603
|
+
}, [selectedId]);
|
|
3413
3604
|
(0, react.useEffect)(() => {
|
|
3414
|
-
const next =
|
|
3605
|
+
const next = sessionRunningFlags(sessions.byId, sessionStatus);
|
|
3415
3606
|
const previous = previousSessionRunningRef.current;
|
|
3416
3607
|
previousSessionRunningRef.current = next;
|
|
3417
3608
|
if (previous === void 0) return;
|
|
3418
|
-
const completed = completedBackgroundSessionIds(previous, next,
|
|
3609
|
+
const completed = completedBackgroundSessionIds(previous, next, selectedId);
|
|
3419
3610
|
if (completed.length > 0) setUnreadSessionIds((ids) => [...completed, ...ids.filter((id) => !completed.includes(id))]);
|
|
3420
|
-
}, [
|
|
3611
|
+
}, [
|
|
3612
|
+
selectedId,
|
|
3613
|
+
sessionStatus,
|
|
3614
|
+
sessions.byId
|
|
3615
|
+
]);
|
|
3421
3616
|
const groups = (0, react.useMemo)(() => {
|
|
3422
3617
|
const archived = workspaces.archivedSessionIds;
|
|
3423
3618
|
const visible = (ids) => visibleSessionIds(ids, sessions.byId, archived);
|
|
@@ -3448,7 +3643,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3448
3643
|
(0, react.useEffect)(() => {
|
|
3449
3644
|
const onProject = (event) => {
|
|
3450
3645
|
const detail = event.detail;
|
|
3451
|
-
const current =
|
|
3646
|
+
const current = selectedId;
|
|
3452
3647
|
const workspace = groups.items.find((item) => current !== void 0 && item.visibleIds.includes(String(current)));
|
|
3453
3648
|
if (workspace === void 0 || detail === void 0) return;
|
|
3454
3649
|
if (detail.toggle === true && isShowing("workspace", workspace.workspaceId)) {
|
|
@@ -3461,7 +3656,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3461
3656
|
title: workspace.title,
|
|
3462
3657
|
path: workspace.path,
|
|
3463
3658
|
count: workspace.visibleIds.length,
|
|
3464
|
-
unreadCount: workspace.visibleIds.filter((id) =>
|
|
3659
|
+
unreadCount: workspace.visibleIds.filter((id) => rowUnread(String(id))).length,
|
|
3465
3660
|
pinned: pinnedWorkspaceIds.includes(String(workspace.workspaceId)),
|
|
3466
3661
|
left: detail.left,
|
|
3467
3662
|
top: detail.top
|
|
@@ -3469,7 +3664,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3469
3664
|
};
|
|
3470
3665
|
const onMenu = (event) => {
|
|
3471
3666
|
const detail = event.detail;
|
|
3472
|
-
const current =
|
|
3667
|
+
const current = selectedId;
|
|
3473
3668
|
if (current === void 0 || detail === void 0) return;
|
|
3474
3669
|
dismissTip();
|
|
3475
3670
|
if (performance.now() - headerMenuPointerAt.current < 500) {
|
|
@@ -3490,9 +3685,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3490
3685
|
};
|
|
3491
3686
|
}, [
|
|
3492
3687
|
groups.items,
|
|
3493
|
-
sessions.current,
|
|
3494
3688
|
menu,
|
|
3495
3689
|
pinnedWorkspaceIds,
|
|
3690
|
+
selectedId,
|
|
3496
3691
|
unreadSessionIds
|
|
3497
3692
|
]);
|
|
3498
3693
|
const projectPinned = (id) => pinnedWorkspaceIds.includes(String(id));
|
|
@@ -3721,7 +3916,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3721
3916
|
};
|
|
3722
3917
|
const canDelete = canDeleteSession?.() === true;
|
|
3723
3918
|
const sessionMenu = (sessionId, path) => sessionMenuItems(t, {
|
|
3724
|
-
unread:
|
|
3919
|
+
unread: rowUnread(sessionId),
|
|
3725
3920
|
path,
|
|
3726
3921
|
includePath: true,
|
|
3727
3922
|
moveTargets: sessionMoveTargets(groups.items, sessionId).map((target) => ({
|
|
@@ -3776,7 +3971,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3776
3971
|
const renderGroup = (workspace, zone) => {
|
|
3777
3972
|
const expandKey = zone === "pinned" ? `pin:${workspace.workspaceId}` : String(workspace.workspaceId);
|
|
3778
3973
|
const isExpanded = expanded[expandKey] ?? true;
|
|
3779
|
-
const currentSessionId =
|
|
3974
|
+
const currentSessionId = selectedId;
|
|
3780
3975
|
const folder = projectFolderPresentation(isExpanded, workspace.visibleIds.some((id) => id === currentSessionId));
|
|
3781
3976
|
const shownIds = workspace.visibleIds;
|
|
3782
3977
|
const menuOpen = menu?.type === "workspace" && menu.id === workspace.workspaceId;
|
|
@@ -3904,7 +4099,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3904
4099
|
title: workspace.title,
|
|
3905
4100
|
path: workspace.path,
|
|
3906
4101
|
count: workspace.visibleIds.length,
|
|
3907
|
-
unreadCount: workspace.visibleIds.filter((id) =>
|
|
4102
|
+
unreadCount: workspace.visibleIds.filter((id) => rowUnread(String(id))).length,
|
|
3908
4103
|
pinned: projectPinned(workspace.workspaceId),
|
|
3909
4104
|
left: box.left,
|
|
3910
4105
|
top: box.top
|
|
@@ -3933,7 +4128,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3933
4128
|
title: workspace.title,
|
|
3934
4129
|
path: workspace.path,
|
|
3935
4130
|
count: workspace.visibleIds.length,
|
|
3936
|
-
unreadCount: workspace.visibleIds.filter((id) =>
|
|
4131
|
+
unreadCount: workspace.visibleIds.filter((id) => rowUnread(String(id))).length,
|
|
3937
4132
|
pinned: projectPinned(workspace.workspaceId),
|
|
3938
4133
|
left: box.left,
|
|
3939
4134
|
top: box.top
|
|
@@ -4001,7 +4196,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4001
4196
|
if (session === void 0) return null;
|
|
4002
4197
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
4003
4198
|
const path = session.cwd ?? workspace.path;
|
|
4004
|
-
const selected =
|
|
4199
|
+
const selected = selectedId === id;
|
|
4005
4200
|
const sessionMenuOpen = menu?.type === "session" && menu.id === id;
|
|
4006
4201
|
const sessionMenuAt = sessionMenuOpen && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
4007
4202
|
x: menu.x,
|
|
@@ -4096,8 +4291,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4096
4291
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRowTitle, { title: session.displayTitle }),
|
|
4097
4292
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionState, {
|
|
4098
4293
|
pendingInteraction,
|
|
4099
|
-
unread:
|
|
4100
|
-
running: session
|
|
4294
|
+
unread: rowUnread(id),
|
|
4295
|
+
running: rowRunning(id, session),
|
|
4101
4296
|
t
|
|
4102
4297
|
}),
|
|
4103
4298
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionTime, { time: formatCompactTime(session.updatedAt, t, now) }),
|
|
@@ -4556,7 +4751,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4556
4751
|
return mountWorkspaceDropIndicator(treeRef.current);
|
|
4557
4752
|
}, [wide, sorting]);
|
|
4558
4753
|
(0, react.useEffect)(() => {
|
|
4559
|
-
const current =
|
|
4754
|
+
const current = selectedId;
|
|
4560
4755
|
if (current === void 0 || lastRevealedSessionIdRef.current === current) return;
|
|
4561
4756
|
const tree = {
|
|
4562
4757
|
workspaces: workspaces.items.map((item) => ({
|
|
@@ -4577,7 +4772,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4577
4772
|
}, [
|
|
4578
4773
|
pinnedWorkspaceIds,
|
|
4579
4774
|
recentIds,
|
|
4580
|
-
|
|
4775
|
+
selectedId,
|
|
4581
4776
|
workspaceGroups,
|
|
4582
4777
|
workspaces.items
|
|
4583
4778
|
]);
|
|
@@ -4847,15 +5042,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4847
5042
|
const session = sessions.byId[id];
|
|
4848
5043
|
if (session === void 0) return null;
|
|
4849
5044
|
const title = session.displayTitle;
|
|
4850
|
-
const unread =
|
|
5045
|
+
const unread = rowUnread(id);
|
|
4851
5046
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
4852
5047
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
4853
5048
|
id,
|
|
4854
5049
|
title,
|
|
4855
|
-
selected:
|
|
5050
|
+
selected: selectedId === id,
|
|
4856
5051
|
menuOpen: menu?.type === "session" && menu.id === id,
|
|
4857
5052
|
unread,
|
|
4858
|
-
running: session
|
|
5053
|
+
running: rowRunning(id, session),
|
|
4859
5054
|
pendingInteraction,
|
|
4860
5055
|
time: formatCompactTime(session.updatedAt, t, now),
|
|
4861
5056
|
t,
|
|
@@ -5550,15 +5745,17 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5550
5745
|
})
|
|
5551
5746
|
});
|
|
5552
5747
|
}
|
|
5553
|
-
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, canDeleteSession, menu, setMenu }) {
|
|
5748
|
+
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useSessionStatus, useWorkspaces, t, canDeleteSession, panelActive = false, menu, setMenu }) {
|
|
5554
5749
|
const sessions = useSessions((state) => state);
|
|
5555
5750
|
const now = useSharedNow();
|
|
5556
5751
|
const workspaces = useWorkspaces?.((state) => state);
|
|
5557
|
-
const pendingInteractions = (useSessionPendingInteraction
|
|
5752
|
+
const pendingInteractions = useHostPendingInteractions(useSessionPendingInteraction, useSessionStatus);
|
|
5753
|
+
const sessionStatus = useHostSessionStatus(useSessionStatus);
|
|
5754
|
+
const selectedId = visibleSelectedSessionId(sessions, panelActive);
|
|
5558
5755
|
const [groups, setGroups] = (0, react.useState)([]);
|
|
5559
5756
|
const [pollError, setPollError] = (0, react.useState)();
|
|
5560
5757
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), CHANNEL_EXPANSION_STORAGE_KEY));
|
|
5561
|
-
const flags = useSessionFlags(
|
|
5758
|
+
const flags = useSessionFlags(selectedId);
|
|
5562
5759
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
5563
5760
|
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
5564
5761
|
setMenu(void 0);
|
|
@@ -5654,10 +5851,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5654
5851
|
children: group.sessions.map((session) => {
|
|
5655
5852
|
const id = session.sessionId;
|
|
5656
5853
|
const title = session.title;
|
|
5657
|
-
const selected =
|
|
5658
|
-
const
|
|
5854
|
+
const selected = selectedId === id;
|
|
5855
|
+
const status = sessionStatus.get(id);
|
|
5856
|
+
const running = sessionIsRunning({ running: session.running === true || sessions.byId[id]?.running === true }, status);
|
|
5659
5857
|
const updatedAt = session.updatedAt ?? sessions.byId[id]?.updatedAt;
|
|
5660
|
-
const unread = flags.unreadSessionIds.includes(id);
|
|
5858
|
+
const unread = sessionRowUnread(flags.unreadSessionIds.includes(id), status, selected);
|
|
5661
5859
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
5662
5860
|
const moveTargets = moveSession === void 0 || workspaces === void 0 ? void 0 : sessionMoveTargets(workspaces.items, id).map((target) => ({
|
|
5663
5861
|
...target,
|
|
@@ -5826,15 +6024,17 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5826
6024
|
})]
|
|
5827
6025
|
});
|
|
5828
6026
|
}
|
|
5829
|
-
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, canDeleteSession, openTaskSettings, menu, setMenu }) {
|
|
6027
|
+
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useSessionStatus, useWorkspaces, t, canDeleteSession, panelActive = false, openTaskSettings, menu, setMenu }) {
|
|
5830
6028
|
const sessions = useSessions((state) => state);
|
|
5831
6029
|
const now = useSharedNow();
|
|
5832
|
-
const pendingInteractions = (useSessionPendingInteraction
|
|
6030
|
+
const pendingInteractions = useHostPendingInteractions(useSessionPendingInteraction, useSessionStatus);
|
|
6031
|
+
const sessionStatus = useHostSessionStatus(useSessionStatus);
|
|
6032
|
+
const selectedId = visibleSelectedSessionId(sessions, panelActive);
|
|
5833
6033
|
const workspaces = useWorkspaces((state) => state);
|
|
5834
6034
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), SCHEDULE_EXPANSION_STORAGE_KEY));
|
|
5835
6035
|
const [groupMenu, setGroupMenu] = (0, react.useState)();
|
|
5836
6036
|
const [archiveGroupTarget, setArchiveGroupTarget] = (0, react.useState)();
|
|
5837
|
-
const flags = useSessionFlags(
|
|
6037
|
+
const flags = useSessionFlags(selectedId);
|
|
5838
6038
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
5839
6039
|
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
5840
6040
|
setMenu(void 0);
|
|
@@ -5963,7 +6163,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5963
6163
|
children: group.sessions.map((session) => {
|
|
5964
6164
|
const id = session.id;
|
|
5965
6165
|
const title = session.title;
|
|
5966
|
-
const
|
|
6166
|
+
const selected = selectedId === id;
|
|
6167
|
+
const status = sessionStatus.get(id);
|
|
6168
|
+
const unread = sessionRowUnread(flags.unreadSessionIds.includes(id), status, selected);
|
|
5967
6169
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
5968
6170
|
const moveTargets = moveSession === void 0 ? void 0 : sessionMoveTargets(workspaces.items ?? [], id).map((target) => ({
|
|
5969
6171
|
...target,
|
|
@@ -5973,10 +6175,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5973
6175
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
5974
6176
|
id,
|
|
5975
6177
|
title,
|
|
5976
|
-
selected
|
|
6178
|
+
selected,
|
|
5977
6179
|
menuOpen: menu?.id === id,
|
|
5978
6180
|
unread,
|
|
5979
|
-
running:
|
|
6181
|
+
running: sessionIsRunning(sessions.byId[id], status),
|
|
5980
6182
|
pendingInteraction,
|
|
5981
6183
|
time: session.updatedAt === void 0 ? void 0 : formatCompactTime(session.updatedAt, t, now),
|
|
5982
6184
|
t,
|
|
@@ -6740,7 +6942,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6740
6942
|
});
|
|
6741
6943
|
}
|
|
6742
6944
|
/** 搜索状态与大侧栏隔离:输入、悬停和开关弹窗都不能让工作区树跟着重渲染。 */
|
|
6743
|
-
const SidebarSearch = (0, react.forwardRef)(function SidebarSearch({ imSettingsAvailable, openSession, startSession, t, useSessions, useWorkspaces, settingsSeat }, ref) {
|
|
6945
|
+
const SidebarSearch = (0, react.forwardRef)(function SidebarSearch({ imSettingsAvailable, openPlugins, openSession, startSession, t, useSessions, useWorkspaces, settingsSeat }, ref) {
|
|
6744
6946
|
const [open, setOpen] = (0, react.useState)(false);
|
|
6745
6947
|
const [query, setQuery] = (0, react.useState)("");
|
|
6746
6948
|
const [activeIndex, setActiveIndex] = (0, react.useState)(0);
|
|
@@ -6758,9 +6960,6 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6758
6960
|
const selectSection = (0, react.useCallback)((label) => {
|
|
6759
6961
|
openSettingsSection(settingsSeat.current, label);
|
|
6760
6962
|
}, [settingsSeat]);
|
|
6761
|
-
const selectPluginSection = (0, react.useCallback)(() => {
|
|
6762
|
-
openSettingsSection(settingsSeat.current, [t("sidebar.marketplace"), t("sidebar.plugins")]);
|
|
6763
|
-
}, [settingsSeat, t]);
|
|
6764
6963
|
const selectExternalSection = (0, react.useCallback)((label) => {
|
|
6765
6964
|
openSettingsSection(settingsSeat.current, label, () => {
|
|
6766
6965
|
selectSection(t("about.nav"));
|
|
@@ -6837,7 +7036,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6837
7036
|
keywords: t("search.settings"),
|
|
6838
7037
|
run: () => {
|
|
6839
7038
|
close();
|
|
6840
|
-
|
|
7039
|
+
openPlugins();
|
|
7040
|
+
}
|
|
7041
|
+
},
|
|
7042
|
+
{
|
|
7043
|
+
id: "settings:plugin-config",
|
|
7044
|
+
group: "settings",
|
|
7045
|
+
label: t("settings.pluginConfig"),
|
|
7046
|
+
keywords: t("search.settings"),
|
|
7047
|
+
run: () => {
|
|
7048
|
+
close();
|
|
7049
|
+
openSettingsSection(settingsSeat.current, t("settings.pluginConfig"));
|
|
6841
7050
|
}
|
|
6842
7051
|
},
|
|
6843
7052
|
{
|
|
@@ -6898,10 +7107,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6898
7107
|
}, [
|
|
6899
7108
|
close,
|
|
6900
7109
|
openImSettings,
|
|
7110
|
+
openPlugins,
|
|
6901
7111
|
openSession,
|
|
6902
7112
|
openSettings,
|
|
6903
7113
|
selectExternalSection,
|
|
6904
|
-
selectPluginSection,
|
|
6905
7114
|
selectSection,
|
|
6906
7115
|
sessions.byId,
|
|
6907
7116
|
sessions.ids,
|
|
@@ -7012,10 +7221,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7012
7221
|
});
|
|
7013
7222
|
});
|
|
7014
7223
|
/** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
|
|
7015
|
-
function CodexSidebar({ globalPanels, footerActions, selectPanel, usePanelInfo = useLegacyPanelInfo, collapsed, width, openSession, startSession, toggleSidebar, archiveSession, canDeleteSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces, prefillNewConversation, newConversationDraft }) {
|
|
7224
|
+
function CodexSidebar({ globalPanels, footerActions, selectPanel, usePanelInfo = useLegacyPanelInfo, collapsed, width, openSession, startSession, toggleSidebar, archiveSession, canDeleteSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useSessionStatus, useWorkspaces, prefillNewConversation, newConversationDraft }) {
|
|
7016
7225
|
const panels = (0, react.useSyncExternalStore)(globalPanels?.subscribe ?? subscribeEmptyCompanionTabs, globalPanels?.getSnapshot ?? getEmptyPanels, globalPanels?.getSnapshot ?? getEmptyPanels);
|
|
7017
7226
|
const visibleFooterActions = (0, react.useSyncExternalStore)(footerActions?.subscribe ?? subscribeEmptyCompanionTabs, footerActions?.getSnapshot ?? getEmptyFooterActions, footerActions?.getSnapshot ?? getEmptyFooterActions);
|
|
7018
7227
|
const activePanelId = usePanelInfo((info) => info.activePanelId);
|
|
7228
|
+
const panelActive = activePanelId !== null && activePanelId !== "";
|
|
7019
7229
|
const panelButtons = (wide) => selectPanel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobalPanelButtons, {
|
|
7020
7230
|
panels,
|
|
7021
7231
|
activeId: activePanelId,
|
|
@@ -7046,8 +7256,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7046
7256
|
const selectSection = (label) => {
|
|
7047
7257
|
openSettingsSection(settingsSeat.current, label);
|
|
7048
7258
|
};
|
|
7049
|
-
const
|
|
7050
|
-
openSettingsSection(settingsSeat.current, [t("sidebar.marketplace"), t("sidebar.
|
|
7259
|
+
const openPlugins = () => {
|
|
7260
|
+
openSettingsSection(settingsSeat.current, [t("sidebar.marketplace"), t("sidebar.builtinPlugins")]);
|
|
7051
7261
|
};
|
|
7052
7262
|
const selectExternalSection = (label) => {
|
|
7053
7263
|
openSettingsSection(settingsSeat.current, label, () => {
|
|
@@ -7166,10 +7376,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7166
7376
|
window.clearTimeout(timer);
|
|
7167
7377
|
};
|
|
7168
7378
|
}, [compact, visualCompact]);
|
|
7169
|
-
const workspaceSlot = (0, react.useMemo)(() =>
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7379
|
+
const workspaceSlot = (0, react.useMemo)(() => {
|
|
7380
|
+
return renderSlot("sidebar.workspaces", {
|
|
7381
|
+
wide: true,
|
|
7382
|
+
expandSidebar,
|
|
7383
|
+
panelActive
|
|
7384
|
+
});
|
|
7385
|
+
}, [
|
|
7386
|
+
expandSidebar,
|
|
7387
|
+
panelActive,
|
|
7388
|
+
renderSlot
|
|
7389
|
+
]);
|
|
7173
7390
|
const scheduleOverviewSlot = (0, react.useMemo)(() => renderSlot("sidebar.schedule", {
|
|
7174
7391
|
wide: true,
|
|
7175
7392
|
expandSidebar,
|
|
@@ -7305,7 +7522,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7305
7522
|
type: "button",
|
|
7306
7523
|
tabIndex: extensionsOpen ? 0 : -1,
|
|
7307
7524
|
onClick: () => {
|
|
7308
|
-
|
|
7525
|
+
openPlugins();
|
|
7309
7526
|
},
|
|
7310
7527
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 }) }), t("sidebar.plugins")]
|
|
7311
7528
|
}),
|
|
@@ -7381,7 +7598,9 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7381
7598
|
renameSession,
|
|
7382
7599
|
useSessions,
|
|
7383
7600
|
useSessionPendingInteraction,
|
|
7601
|
+
useSessionStatus,
|
|
7384
7602
|
useWorkspaces,
|
|
7603
|
+
panelActive,
|
|
7385
7604
|
t
|
|
7386
7605
|
})
|
|
7387
7606
|
}) : imTab === "schedule" && showSchedule ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -7396,7 +7615,9 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7396
7615
|
renameSession,
|
|
7397
7616
|
useSessions,
|
|
7398
7617
|
useSessionPendingInteraction,
|
|
7618
|
+
useSessionStatus,
|
|
7399
7619
|
useWorkspaces,
|
|
7620
|
+
panelActive,
|
|
7400
7621
|
t,
|
|
7401
7622
|
overviewContent: scheduleOverviewSlot,
|
|
7402
7623
|
openTaskSettings: (request) => {
|
|
@@ -7469,7 +7690,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7469
7690
|
className: "dcu-icon",
|
|
7470
7691
|
"aria-label": t("sidebar.plugins"),
|
|
7471
7692
|
onClick: () => {
|
|
7472
|
-
|
|
7693
|
+
openPlugins();
|
|
7473
7694
|
},
|
|
7474
7695
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 })
|
|
7475
7696
|
}),
|
|
@@ -7515,6 +7736,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
7515
7736
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSearch, {
|
|
7516
7737
|
ref: search,
|
|
7517
7738
|
imSettingsAvailable: showChannels,
|
|
7739
|
+
openPlugins,
|
|
7518
7740
|
settingsSeat,
|
|
7519
7741
|
openSession,
|
|
7520
7742
|
startSession,
|
|
@@ -8054,7 +8276,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8054
8276
|
});
|
|
8055
8277
|
}
|
|
8056
8278
|
function NativeConnectorList({ sessionStore, t }) {
|
|
8057
|
-
const sessionId = (0, react.useSyncExternalStore)(sessionStore.subscribe, () => sessionStore.getSnapshot()
|
|
8279
|
+
const sessionId = (0, react.useSyncExternalStore)(sessionStore.subscribe, () => currentSessionId(sessionStore.getSnapshot()));
|
|
8058
8280
|
const [connectors, setConnectors] = (0, react.useState)([]);
|
|
8059
8281
|
const [state, setState] = (0, react.useState)("loading");
|
|
8060
8282
|
const [failure, setFailure] = (0, react.useState)();
|
|
@@ -8209,6 +8431,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8209
8431
|
"settings.search": "搜索设置…",
|
|
8210
8432
|
"settings.personal": "个人",
|
|
8211
8433
|
"settings.integrations": "集成",
|
|
8434
|
+
"settings.pluginConfig": "插件配置",
|
|
8212
8435
|
"settings.records": "记录与应用",
|
|
8213
8436
|
"settings.general": "常规",
|
|
8214
8437
|
"settings.permissions": "权限",
|
|
@@ -8231,6 +8454,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8231
8454
|
"sidebar.skills": "技能",
|
|
8232
8455
|
"sidebar.plugins": "插件",
|
|
8233
8456
|
"sidebar.marketplace": "插件市场",
|
|
8457
|
+
"sidebar.builtinPlugins": "内置插件",
|
|
8234
8458
|
"sidebar.connectors": "连接器",
|
|
8235
8459
|
"sidebar.schedule": "定时任务",
|
|
8236
8460
|
"sidebar.assistant": "IM助理",
|
|
@@ -8497,6 +8721,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8497
8721
|
"settings.search": "Search settings…",
|
|
8498
8722
|
"settings.personal": "Personal",
|
|
8499
8723
|
"settings.integrations": "Integrations",
|
|
8724
|
+
"settings.pluginConfig": "Plugin configuration",
|
|
8500
8725
|
"settings.records": "Records and app",
|
|
8501
8726
|
"settings.general": "General",
|
|
8502
8727
|
"settings.permissions": "Permissions",
|
|
@@ -8519,6 +8744,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8519
8744
|
"sidebar.skills": "Skills",
|
|
8520
8745
|
"sidebar.plugins": "Plugins",
|
|
8521
8746
|
"sidebar.marketplace": "Plugin Market",
|
|
8747
|
+
"sidebar.builtinPlugins": "Built-in plugins",
|
|
8522
8748
|
"sidebar.connectors": "Connectors",
|
|
8523
8749
|
"sidebar.schedule": "Scheduled tasks",
|
|
8524
8750
|
"sidebar.assistant": "IM Assistant",
|
|
@@ -8811,6 +9037,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
8811
9037
|
};
|
|
8812
9038
|
const LABEL_ALIASES = [
|
|
8813
9039
|
[["插件市场", "Plugin Market"], "plugins"],
|
|
9040
|
+
[["内置插件", "Built-in plugins"], "plugins"],
|
|
9041
|
+
[["插件配置", "Plugin configuration"], "plugins"],
|
|
8814
9042
|
[["专家", "Experts"], "experts"],
|
|
8815
9043
|
[["技能", "Skills"], "skills"],
|
|
8816
9044
|
[["插件", "Plugins"], "plugins"],
|
|
@@ -9112,6 +9340,160 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
9112
9340
|
}, "michengai-codex-ui: usage navigation");
|
|
9113
9341
|
}
|
|
9114
9342
|
//#endregion
|
|
9343
|
+
//#region src/client/PluginConfigSection.tsx
|
|
9344
|
+
function bindPluginConfigLocale(bind) {
|
|
9345
|
+
const cache = /* @__PURE__ */ new Map();
|
|
9346
|
+
return (ns) => {
|
|
9347
|
+
const existing = cache.get(ns);
|
|
9348
|
+
if (existing !== void 0) return existing;
|
|
9349
|
+
const translate = bind(ns);
|
|
9350
|
+
cache.set(ns, translate);
|
|
9351
|
+
return translate;
|
|
9352
|
+
};
|
|
9353
|
+
}
|
|
9354
|
+
const FORWARDED_CONFIG_SLOTS = /* @__PURE__ */ new Set([
|
|
9355
|
+
"plugins.item",
|
|
9356
|
+
"plugins.bundle.config",
|
|
9357
|
+
"plugins.row.config"
|
|
9358
|
+
]);
|
|
9359
|
+
var SlotEntryBoundary = class extends react.Component {
|
|
9360
|
+
state = { failed: false };
|
|
9361
|
+
static getDerivedStateFromError() {
|
|
9362
|
+
return { failed: true };
|
|
9363
|
+
}
|
|
9364
|
+
render() {
|
|
9365
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
9366
|
+
}
|
|
9367
|
+
};
|
|
9368
|
+
function isSnapshotSource(value) {
|
|
9369
|
+
return typeof value === "object" && value !== null && typeof value.getSnapshot === "function" && typeof value.subscribe === "function";
|
|
9370
|
+
}
|
|
9371
|
+
function hookPropName(name) {
|
|
9372
|
+
return `use${name[0]?.toUpperCase() ?? ""}${name.slice(1)}`;
|
|
9373
|
+
}
|
|
9374
|
+
function bindSnapshotSelector(source) {
|
|
9375
|
+
const subscribe = (listener) => source.subscribe(listener);
|
|
9376
|
+
const getSnapshot = () => source.getSnapshot();
|
|
9377
|
+
return function useSelected(selector = (value) => value) {
|
|
9378
|
+
return (0, react.useSyncExternalStore)(subscribe, () => selector(getSnapshot()), () => selector(getSnapshot()));
|
|
9379
|
+
};
|
|
9380
|
+
}
|
|
9381
|
+
function bindHookSources(hooks, bound) {
|
|
9382
|
+
for (const [name, source] of Object.entries(hooks ?? {})) if (isSnapshotSource(source)) bound[hookPropName(name)] = bindSnapshotSelector(source);
|
|
9383
|
+
}
|
|
9384
|
+
function bindInjectFace(inject) {
|
|
9385
|
+
try {
|
|
9386
|
+
if (typeof inject !== "function") return {};
|
|
9387
|
+
const face = inject();
|
|
9388
|
+
if (typeof face !== "object" || face === null) return {};
|
|
9389
|
+
const { hooks, keyedHooks, ...rest } = face;
|
|
9390
|
+
const bound = { ...rest };
|
|
9391
|
+
if (keyedHooks !== void 0) bound.keyedHooks = keyedHooks;
|
|
9392
|
+
bindHookSources(hooks, bound);
|
|
9393
|
+
bindHookSources(keyedHooks, bound);
|
|
9394
|
+
return bound;
|
|
9395
|
+
} catch {
|
|
9396
|
+
return {};
|
|
9397
|
+
}
|
|
9398
|
+
}
|
|
9399
|
+
function DelegatedOfficialSlot({ slots, name, owner, opts, bindLocale }) {
|
|
9400
|
+
(0, react.useSyncExternalStore)((listener) => slots.subscribe(name, listener), () => slots.getVersion(name));
|
|
9401
|
+
const nodes = slots.entriesOfSlot(name).filter((entry) => opts?.entryKey !== void 0 ? entry.options.key === opts.entryKey : opts?.only === void 0 || entry.options.id === opts.only).flatMap((entry, index) => {
|
|
9402
|
+
if (typeof entry.component !== "function") return [];
|
|
9403
|
+
const t = entry.locale !== void 0 && bindLocale !== void 0 ? bindLocale(entry.locale) : void 0;
|
|
9404
|
+
return [(0, react.createElement)(SlotEntryBoundary, {
|
|
9405
|
+
key: entry.options.key ?? entry.options.id ?? String(index),
|
|
9406
|
+
fallback: opts?.fallback ?? null,
|
|
9407
|
+
children: (0, react.createElement)(entry.component, {
|
|
9408
|
+
...owner,
|
|
9409
|
+
...bindInjectFace(entry.inject),
|
|
9410
|
+
...t === void 0 ? {} : { t }
|
|
9411
|
+
})
|
|
9412
|
+
})];
|
|
9413
|
+
});
|
|
9414
|
+
return nodes.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9415
|
+
"data-slot": name,
|
|
9416
|
+
style: { display: "contents" },
|
|
9417
|
+
children: nodes
|
|
9418
|
+
}) : opts?.fallback ?? null;
|
|
9419
|
+
}
|
|
9420
|
+
function wrapRenderSlot(settingsRenderSlot, slots, bindLocale) {
|
|
9421
|
+
return (name, owner = {}, opts) => {
|
|
9422
|
+
if (slots !== void 0 && FORWARDED_CONFIG_SLOTS.has(name)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DelegatedOfficialSlot, {
|
|
9423
|
+
slots,
|
|
9424
|
+
name,
|
|
9425
|
+
owner,
|
|
9426
|
+
opts,
|
|
9427
|
+
bindLocale
|
|
9428
|
+
});
|
|
9429
|
+
return typeof settingsRenderSlot === "function" ? settingsRenderSlot(name, owner, opts) : null;
|
|
9430
|
+
};
|
|
9431
|
+
}
|
|
9432
|
+
/** 设置里的官方插件管理页副本。官方卡片要 inject 和文案;单卡崩溃不得拆掉整页。 */
|
|
9433
|
+
function PluginConfigSection({ Official, officialLabel, slots, bindLocale, ...official }) {
|
|
9434
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
9435
|
+
className: "dcu-plugin-config",
|
|
9436
|
+
"aria-label": officialLabel,
|
|
9437
|
+
children: (0, react.createElement)(Official, {
|
|
9438
|
+
...official,
|
|
9439
|
+
renderSlot: wrapRenderSlot(official.renderSlot, slots, bindLocale)
|
|
9440
|
+
})
|
|
9441
|
+
});
|
|
9442
|
+
}
|
|
9443
|
+
function createPluginConfigSection(Official, officialLabel, slots, bindLocale) {
|
|
9444
|
+
return function PluginConfigSectionBound(props) {
|
|
9445
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginConfigSection, {
|
|
9446
|
+
Official,
|
|
9447
|
+
officialLabel: officialLabel(),
|
|
9448
|
+
slots,
|
|
9449
|
+
bindLocale,
|
|
9450
|
+
...props
|
|
9451
|
+
});
|
|
9452
|
+
};
|
|
9453
|
+
}
|
|
9454
|
+
//#endregion
|
|
9455
|
+
//#region src/client/plugin-config.ts
|
|
9456
|
+
const PLUGIN_CONFIG_SECTION_ID = "plugin-config";
|
|
9457
|
+
const OFFICIAL_PLUGIN_MANAGER_NS = "pluginManager";
|
|
9458
|
+
function officialPluginsPage(entry) {
|
|
9459
|
+
if (entry === void 0 || entry.options.key !== "plugins") return void 0;
|
|
9460
|
+
if (typeof entry.component !== "function" || typeof entry.inject !== "function" || entry.locale !== OFFICIAL_PLUGIN_MANAGER_NS) return void 0;
|
|
9461
|
+
return entry.component;
|
|
9462
|
+
}
|
|
9463
|
+
function registerPluginConfigSection(ctx) {
|
|
9464
|
+
const t = ctx.locale.bind(NS);
|
|
9465
|
+
ctx.slots.inject("settings.section", () => {
|
|
9466
|
+
let current;
|
|
9467
|
+
let remove;
|
|
9468
|
+
const refresh = () => {
|
|
9469
|
+
const entry = ctx.slots.entriesOfSlot("main").find((item) => item.options.key === OFFICIAL_PLUGINS_PANEL_ID);
|
|
9470
|
+
if (entry === current) return;
|
|
9471
|
+
remove?.();
|
|
9472
|
+
remove = void 0;
|
|
9473
|
+
current = entry;
|
|
9474
|
+
const Official = officialPluginsPage(entry);
|
|
9475
|
+
if (Official === void 0 || entry?.inject === void 0 || entry.locale !== OFFICIAL_PLUGIN_MANAGER_NS) return;
|
|
9476
|
+
remove = ctx.slots.register({
|
|
9477
|
+
name: "settings.section",
|
|
9478
|
+
id: PLUGIN_CONFIG_SECTION_ID,
|
|
9479
|
+
order: 16,
|
|
9480
|
+
label: () => t("settings.pluginConfig"),
|
|
9481
|
+
locale: entry.locale,
|
|
9482
|
+
inject: entry.inject
|
|
9483
|
+
}, createPluginConfigSection(Official, () => t("settings.pluginConfig"), ctx.slots, bindPluginConfigLocale((ns) => {
|
|
9484
|
+
const translate = ctx.locale.bind(ns);
|
|
9485
|
+
return (key, params) => translate(key, params);
|
|
9486
|
+
})));
|
|
9487
|
+
};
|
|
9488
|
+
const unsubscribe = ctx.slots.subscribe("main", refresh);
|
|
9489
|
+
refresh();
|
|
9490
|
+
return () => {
|
|
9491
|
+
unsubscribe();
|
|
9492
|
+
remove?.();
|
|
9493
|
+
};
|
|
9494
|
+
});
|
|
9495
|
+
}
|
|
9496
|
+
//#endregion
|
|
9115
9497
|
//#region src/client/settings-page-model.ts
|
|
9116
9498
|
function settingsGroup(id) {
|
|
9117
9499
|
if (/archive|about|^usage-statistics$/.test(id)) return "records";
|
|
@@ -9208,11 +9590,16 @@ html[data-dsh-native-backdrop=mica] body[data-ds-dark-theme] :is(.dcu-root,.dcu-
|
|
|
9208
9590
|
html[data-dsh-native-backdrop=mica] body:has(.dcu-settings-page) .dcu-root :is([inert],[inert] *){visibility:hidden!important}
|
|
9209
9591
|
/* 同步隐藏本设置页隔离的外部 portal,保留引导模态及其他组件自己的 inert 语义。 */
|
|
9210
9592
|
body:has(.dcu-settings-page) :is([data-dcu-settings-isolated],[data-dcu-settings-isolated] *){visibility:hidden!important}
|
|
9593
|
+
body:has(.dcu-settings-page) > [role=alert]{visibility:visible!important}
|
|
9211
9594
|
html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-backdrop=mica] body:has(.dcu-settings-page) .dcu-root{background:transparent}
|
|
9212
9595
|
|
|
9213
9596
|
.dcu-settings-inner:has(.dcu-usage-section){height:100%;display:flex;flex-direction:column;padding-bottom:0}
|
|
9214
9597
|
.dcu-settings-inner:has(.dcu-usage-section)>.dcu-settings-heading{display:none}
|
|
9215
9598
|
.dcu-settings-inner:has(.dcu-usage-section)>[data-slot="settings.section"]{display:flex;flex:1;min-height:0;flex-direction:column}
|
|
9599
|
+
.dcu-plugin-config [data-plugin-panel]{height:auto;padding:0;overflow:visible;align-items:stretch;gap:24px}
|
|
9600
|
+
.dcu-plugin-config [data-plugin-panel]>*{max-width:none}
|
|
9601
|
+
.dcu-plugin-config [data-plugin-panel]>header :is(h1,p){display:none}
|
|
9602
|
+
.dcu-plugin-config [data-plugin-panel]>header{justify-content:flex-end}
|
|
9216
9603
|
.dcu-usage-section{display:flex;flex-direction:column;flex:1;min-height:0;gap:16px}
|
|
9217
9604
|
.dcu-usage-section h1{font-size:24px;font-weight:500;margin:0}
|
|
9218
9605
|
.dcu-usage-section p{color:var(--sp-muted)}
|
|
@@ -9273,7 +9660,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9273
9660
|
const rows = (0, react.useSyncExternalStore)(sections.subscribe, sections.getSnapshot);
|
|
9274
9661
|
const steps = (0, react.useSyncExternalStore)(onboarding.subscribe, onboarding.getSnapshot);
|
|
9275
9662
|
const connection = (0, react.useSyncExternalStore)(connectionState.subscribe, connectionState.getSnapshot);
|
|
9276
|
-
const onboardingActive = useSessions((state) =>
|
|
9663
|
+
const onboardingActive = useSessions((state) => isBlankOnboardingSession(state));
|
|
9277
9664
|
const [completed, setCompleted] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
9278
9665
|
const [open, setOpen] = (0, react.useState)(false);
|
|
9279
9666
|
const [activeId, setActiveId] = (0, react.useState)("general");
|
|
@@ -9360,6 +9747,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9360
9747
|
const guideModals = step === void 0 ? [] : settingsOverlays("[role=\"dialog\"][aria-modal=\"true\"],[role=\"alertdialog\"][aria-modal=\"true\"]");
|
|
9361
9748
|
const isolate = (element) => {
|
|
9362
9749
|
if (element.parentElement === document.body && element.hasAttribute("data-dsh-pet-overlay")) return;
|
|
9750
|
+
if (element.parentElement === document.body && element.getAttribute("role") === "alert") return;
|
|
9363
9751
|
if (element === onboardingRoot.current || guideModals.includes(element)) return;
|
|
9364
9752
|
if (guideModals.some((modal) => element.contains(modal))) {
|
|
9365
9753
|
for (const child of element.children) if (child instanceof HTMLElement && !/^(STYLE|SCRIPT|LINK)$/.test(child.tagName)) isolate(child);
|
|
@@ -9390,7 +9778,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9390
9778
|
const keepFocus = (event) => {
|
|
9391
9779
|
const target = event.target;
|
|
9392
9780
|
if (!(target instanceof Node) || page.current === null || !settingsElementAvailable(page.current)) return;
|
|
9393
|
-
if (page.current.contains(target) || onboardingRoot.current?.contains(target) || [...document.querySelectorAll("body > [data-dsh-pet-overlay]")].some((root) => root.contains(target)) || settingsOverlays().some((overlay) => overlay.contains(target))) return;
|
|
9781
|
+
if (page.current.contains(target) || onboardingRoot.current?.contains(target) || [...document.querySelectorAll("body > [data-dsh-pet-overlay], body > [role=alert]")].some((root) => root.contains(target)) || settingsOverlays().some((overlay) => overlay.contains(target))) return;
|
|
9394
9782
|
back.current?.focus();
|
|
9395
9783
|
};
|
|
9396
9784
|
const wrapFocus = (event) => {
|
|
@@ -9398,7 +9786,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9398
9786
|
const items = [
|
|
9399
9787
|
page.current,
|
|
9400
9788
|
onboardingRoot.current,
|
|
9401
|
-
...document.querySelectorAll("body > [data-dsh-pet-overlay]")
|
|
9789
|
+
...document.querySelectorAll("body > [data-dsh-pet-overlay], body > [role=alert]")
|
|
9402
9790
|
].filter((root) => root !== null).flatMap((root) => [...root.querySelectorAll("button,input,select,textarea,a[href],[tabindex]")]).filter((element) => element.tabIndex >= 0 && !element.matches(":disabled") && settingsElementAvailable(element));
|
|
9403
9791
|
const next = event.shiftKey ? items.at(-1) : items[0];
|
|
9404
9792
|
if (document.activeElement === (event.shiftKey ? items[0] : items.at(-1))) {
|
|
@@ -9428,6 +9816,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9428
9816
|
if (main.current !== null) main.current.scrollTop = 0;
|
|
9429
9817
|
}, [active?.id]);
|
|
9430
9818
|
const visible = filterSettingsRows(rows, query);
|
|
9819
|
+
const ownTitle = active?.id === "general" ? t("settings.general") : active?.id === "plugin-config" ? t("settings.pluginConfig") : void 0;
|
|
9431
9820
|
const connectionIndicator = connection === "disconnected" ? "disconnected" : connection === "connecting" ? "connecting" : recovered ? "recovered" : void 0;
|
|
9432
9821
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
9433
9822
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: settingsPageStyles }),
|
|
@@ -9537,8 +9926,8 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
9537
9926
|
"data-settings-section": active?.id,
|
|
9538
9927
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
9539
9928
|
className: "dcu-settings-heading",
|
|
9540
|
-
"data-own-title":
|
|
9541
|
-
children: [
|
|
9929
|
+
"data-own-title": ownTitle !== void 0,
|
|
9930
|
+
children: [ownTitle !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: ownTitle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9542
9931
|
className: "dcu-settings-actions",
|
|
9543
9932
|
children: renderSlot("settings.action", {})
|
|
9544
9933
|
})]
|
|
@@ -10470,7 +10859,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10470
10859
|
}
|
|
10471
10860
|
/** Archive Manager replaces the official ui-workspace row with this optional service. */
|
|
10472
10861
|
function startWorkspaceSession(ctx, workspaceId) {
|
|
10473
|
-
const uiWorkspace = ctx
|
|
10862
|
+
const uiWorkspace = probeService(ctx, "uiWorkspace");
|
|
10474
10863
|
if (hasStartSession(uiWorkspace)) {
|
|
10475
10864
|
uiWorkspace.startSession(workspaceId);
|
|
10476
10865
|
return;
|
|
@@ -10483,6 +10872,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10483
10872
|
}
|
|
10484
10873
|
/** 替换 DSH 的官方 sidebar 插槽,不修改 DSH 源码或会话数据。 */
|
|
10485
10874
|
function apply(ctx) {
|
|
10875
|
+
Object.assign(globalThis, { __dcuCurrentSessionId: currentSessionId });
|
|
10486
10876
|
const widthStorage = browserStorage();
|
|
10487
10877
|
if (widthStorage) initializeComposerWidth(widthStorage);
|
|
10488
10878
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
@@ -10494,6 +10884,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10494
10884
|
registerInputHistory(ctx);
|
|
10495
10885
|
registerSettingsPage(ctx);
|
|
10496
10886
|
registerUsageStatistics(ctx);
|
|
10887
|
+
registerPluginConfigSection(ctx);
|
|
10497
10888
|
const connection = ctx.get("connection");
|
|
10498
10889
|
const openPath = (path) => openPathInHost(connection, path);
|
|
10499
10890
|
ctx.effect(() => observeSlimSidebar(), "michengai-codex-ui: slim sidebar");
|
|
@@ -10505,7 +10896,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10505
10896
|
ctx.effect(() => observeConversationHeader(), "michengai-codex-ui: conversation header");
|
|
10506
10897
|
ctx.effect(() => observeOfficialTurnNavigators(), "michengai-codex-ui: official turn navigator");
|
|
10507
10898
|
const newConversationDraft = createDraftPresenceSource(ctx.sessions.list, () => {
|
|
10508
|
-
const id = ctx.sessions.list.getSnapshot()
|
|
10899
|
+
const id = currentSessionId(ctx.sessions.list.getSnapshot());
|
|
10509
10900
|
const binding = id === void 0 ? void 0 : ctx.sessions.binding(id);
|
|
10510
10901
|
return binding === void 0 ? void 0 : ctx.conversation.input.for(binding.ctx).state;
|
|
10511
10902
|
});
|
|
@@ -10545,12 +10936,12 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10545
10936
|
inject: () => ({
|
|
10546
10937
|
newConversationDraft,
|
|
10547
10938
|
prefillNewConversation: (text) => {
|
|
10548
|
-
const id = ctx.sessions.list.getSnapshot()
|
|
10939
|
+
const id = currentSessionId(ctx.sessions.list.getSnapshot());
|
|
10549
10940
|
const binding = id === void 0 ? void 0 : ctx.sessions.binding(id);
|
|
10550
10941
|
return prefillNewConversation(binding === void 0 ? void 0 : ctx.conversation.input.for(binding.ctx), text);
|
|
10551
10942
|
},
|
|
10552
10943
|
openSession: (sessionId) => {
|
|
10553
|
-
openConversation(ctx
|
|
10944
|
+
openConversation(ctx, ctx.layout, sessionId);
|
|
10554
10945
|
},
|
|
10555
10946
|
startSession: (workspaceId) => {
|
|
10556
10947
|
startWorkspaceSession(ctx, workspaceId);
|
|
@@ -10580,20 +10971,16 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10580
10971
|
locale: NS
|
|
10581
10972
|
}, TurnNavigator));
|
|
10582
10973
|
const forkSession = async (sessionId) => {
|
|
10583
|
-
await runHostAction("fork",
|
|
10584
|
-
const childId = await ctx.sessions.fork({
|
|
10585
|
-
sessionId,
|
|
10586
|
-
increaseTitle: true
|
|
10587
|
-
});
|
|
10588
|
-
openConversation(ctx.sessions, ctx.layout, childId);
|
|
10589
|
-
});
|
|
10974
|
+
await runHostAction("fork", () => forkHostSession(ctx, sessionId));
|
|
10590
10975
|
};
|
|
10591
10976
|
const renameSession = async (sessionId, title) => {
|
|
10592
|
-
const session = ctx.sessions.binding(sessionId)?.session;
|
|
10593
|
-
if (session === void 0) throw new UserFacingError(t("sessions.unknown"));
|
|
10594
10977
|
await runHostAction("rename", async () => {
|
|
10595
|
-
|
|
10596
|
-
|
|
10978
|
+
try {
|
|
10979
|
+
await renameHostSession(ctx, sessionId, title);
|
|
10980
|
+
} catch (reason) {
|
|
10981
|
+
if (reason instanceof UnknownSessionError) throw new UserFacingError(t("sessions.unknown"));
|
|
10982
|
+
throw reason;
|
|
10983
|
+
}
|
|
10597
10984
|
});
|
|
10598
10985
|
};
|
|
10599
10986
|
const deleteSession = async (sessionId) => {
|
|
@@ -10604,7 +10991,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10604
10991
|
if (!result.ok) throw result.error === void 0 ? new UserFacingError(t("sessions.deleteUnavailable")) : result.error;
|
|
10605
10992
|
});
|
|
10606
10993
|
};
|
|
10607
|
-
const archiveSession = (sessionId) => runHostAction("archive", () => ctx
|
|
10994
|
+
const archiveSession = (sessionId) => runHostAction("archive", () => archiveHostSession(ctx, sessionId));
|
|
10608
10995
|
const moveSession = async (sessionId, targetWorkspaceId) => {
|
|
10609
10996
|
try {
|
|
10610
10997
|
await requestSessionMove(sessionId, targetWorkspaceId);
|
|
@@ -10625,22 +11012,36 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10625
11012
|
if (prompt === "") throw new UserFacingError(t("connectors.promptRequired"));
|
|
10626
11013
|
const workspaces = ctx.workspaces.list.getSnapshot();
|
|
10627
11014
|
const sessionSnapshot = ctx.sessions.list.getSnapshot();
|
|
10628
|
-
const
|
|
10629
|
-
const currentWorkspaceId =
|
|
11015
|
+
const selectedSessionId = currentSessionId(sessionSnapshot);
|
|
11016
|
+
const currentWorkspaceId = selectedSessionId === void 0 ? void 0 : workspaces.items.find((workspace) => workspace.sessionIds.includes(selectedSessionId))?.workspaceId;
|
|
10630
11017
|
const baselinesReady = workspaceBaselinesReady(workspaces, sessionSnapshot);
|
|
10631
11018
|
const targetWorkspaceId = currentWorkspaceId ?? (baselinesReady ? recentWorkspaceId(workspaces.items, sessionSnapshot.byId) : void 0);
|
|
10632
11019
|
if (targetWorkspaceId === void 0 && !baselinesReady) throw new UserFacingError(t("connectors.workspacesLoading"));
|
|
10633
11020
|
if (targetWorkspaceId === void 0) throw new UserFacingError(t("connectors.workspaceRequired"));
|
|
10634
|
-
const uiWorkspace = ctx
|
|
10635
|
-
const workspaceNavigation = hasConnectWorkspace(uiWorkspace) ? uiWorkspace : hasConnectWorkspace(ctx.workspaces) ? ctx.workspaces : void 0;
|
|
10636
|
-
if (workspaceNavigation === void 0) throw new UserFacingError(t("connectors.workspaceUnavailable"));
|
|
10637
|
-
const sessionId = await workspaceNavigation.connectWorkspace(targetWorkspaceId);
|
|
11021
|
+
const uiWorkspace = probeService(ctx, "uiWorkspace");
|
|
10638
11022
|
const conversation = ctx.get("conversation");
|
|
10639
11023
|
if (conversation === void 0) throw new UserFacingError(t("connectors.conversationUnavailable"));
|
|
10640
|
-
|
|
10641
|
-
|
|
10642
|
-
|
|
10643
|
-
|
|
11024
|
+
try {
|
|
11025
|
+
if (hasOpenWorkspace(uiWorkspace)) {
|
|
11026
|
+
await Promise.resolve(uiWorkspace.openWorkspace(targetWorkspaceId, (id) => {
|
|
11027
|
+
const binding = ctx.sessions.binding(id);
|
|
11028
|
+
if (binding?.ctx === void 0) throw new UnknownSessionError();
|
|
11029
|
+
conversation.input.for(binding.ctx).setDraft(prompt);
|
|
11030
|
+
}));
|
|
11031
|
+
selectGlobalPanel(ctx.layout, null);
|
|
11032
|
+
return;
|
|
11033
|
+
}
|
|
11034
|
+
const workspaceNavigation = hasConnectWorkspace(uiWorkspace) ? uiWorkspace : hasConnectWorkspace(ctx.workspaces) ? ctx.workspaces : void 0;
|
|
11035
|
+
if (workspaceNavigation === void 0) throw new UserFacingError(t("connectors.workspaceUnavailable"));
|
|
11036
|
+
const sessionId = await workspaceNavigation.connectWorkspace(targetWorkspaceId);
|
|
11037
|
+
await openConversationWithDraft(ctx, ctx.layout, ctx.sessions, sessionId, (binding) => {
|
|
11038
|
+
if (binding.ctx === void 0) throw new UnknownSessionError();
|
|
11039
|
+
conversation.input.for(binding.ctx).setDraft(prompt);
|
|
11040
|
+
});
|
|
11041
|
+
} catch (reason) {
|
|
11042
|
+
if (reason instanceof UnknownSessionError) throw new UserFacingError(t("connectors.sessionPending"));
|
|
11043
|
+
throw reason;
|
|
11044
|
+
}
|
|
10644
11045
|
};
|
|
10645
11046
|
ctx.slots.inject("sidebar.workspaces", () => ctx.slots.register({
|
|
10646
11047
|
name: "sidebar.workspaces",
|
|
@@ -10655,7 +11056,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10655
11056
|
moveSession,
|
|
10656
11057
|
openPath,
|
|
10657
11058
|
openSession: (sessionId) => {
|
|
10658
|
-
openConversation(ctx
|
|
11059
|
+
openConversation(ctx, ctx.layout, sessionId);
|
|
10659
11060
|
},
|
|
10660
11061
|
renameSession,
|
|
10661
11062
|
renameWorkspace: (workspaceId, title) => ctx.workspaces.rename(workspaceId, title),
|
|
@@ -10674,7 +11075,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
|
|
|
10674
11075
|
const openDeepLink = () => {
|
|
10675
11076
|
if (opened || ctx.sessions.list.getSnapshot().byId[sessionId] === void 0) return;
|
|
10676
11077
|
opened = true;
|
|
10677
|
-
openConversation(ctx
|
|
11078
|
+
openConversation(ctx, ctx.layout, sessionId);
|
|
10678
11079
|
};
|
|
10679
11080
|
openDeepLink();
|
|
10680
11081
|
return ctx.sessions.list.subscribe(openDeepLink);
|