@michengai/dsh-codex-ui 0.2.106 → 0.2.108
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 +32 -2
- package/CHANGELOG.zh-CN.md +32 -2
- package/lib/client.js +344 -191
- package/lib/index.d.mts +5 -4
- package/lib/index.mjs +43 -27
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,16 +4,46 @@
|
|
|
4
4
|
|
|
5
5
|
This changelog records recent releases of DSH Codex UI and its one-click installer. Earlier changes remain available in the [Git history](https://github.com/MichengAI/dsh-codex-ui/commits/main).
|
|
6
6
|
|
|
7
|
+
## suite-installer-v0.1.27 - 2026-09-07
|
|
8
|
+
|
|
9
|
+
- Updated the bundled Codex UI to `0.2.108`, including group rename/delete menus and aligned group counts; refreshed exact member versions from the official npm registry.
|
|
10
|
+
|
|
11
|
+
## 0.2.108 - 2026-09-07
|
|
12
|
+
|
|
13
|
+
- Added rename and delete actions to each custom workspace group; the Projects header now keeps only the create-group button. Renaming preserves group membership, ordering, and expansion.
|
|
14
|
+
- Aligned custom-group and Ungrouped counts, kept long names from crowding menu buttons, and improved keyboard focus recovery after renaming.
|
|
15
|
+
- Prevented IME confirmation from submitting new groups and kept rejected names from interfering with preference synchronization.
|
|
16
|
+
- Made case-insensitive name checks independent of system locale while preserving legacy stored group names and memberships.
|
|
17
|
+
|
|
18
|
+
## suite-installer-v0.1.26 - 2026-09-07
|
|
19
|
+
|
|
20
|
+
- Refreshed direct member pins from the official npm registry, including IM Connect `0.1.37`, which withdraws its unfinished proactive delivery feature.
|
|
21
|
+
|
|
22
|
+
## suite-installer-v0.1.25 - 2026-09-07
|
|
23
|
+
|
|
24
|
+
- Updated the bundled Codex UI to `0.2.107` and refreshed direct member versions from the official npm registry for reproducible installation.
|
|
25
|
+
|
|
26
|
+
## 0.2.107 - 2026-09-07
|
|
27
|
+
|
|
28
|
+
- Displayed the running Codex UI version beside the About title and aligned Channel and Schedule session-group layout with Tasks.
|
|
29
|
+
- Restricted dependency update requests to loopback same-origin callers and avoided redundant Desktop reload IPC while preserving independent Web reloads.
|
|
30
|
+
- Standardized the package contract on Node.js 22.19.0+ and pnpm 11.22.0.
|
|
31
|
+
|
|
32
|
+
## suite-installer-v0.1.24 — 2026-09-07
|
|
33
|
+
|
|
34
|
+
- Added BTW side questions and Simplify code cleanup to the Suite, installing all eight companion plugins together.
|
|
35
|
+
- Refreshed and pinned member versions from the official npm registry for reproducible installations.
|
|
36
|
+
- Requires Node.js 22.19.0 or later to support Simplify.
|
|
37
|
+
|
|
7
38
|
## 0.2.106 — 2026-09-07
|
|
8
39
|
|
|
9
40
|
- Added Wallpaper Engine sidebar glass support while keeping settings and search dialogs correctly positioned and clickable.
|
|
10
41
|
- Integrated the billing plugin entry into the sidebar, aligning icon size, colors, typography, and spacing with Settings while preserving billing details and the collapsed entry.
|
|
11
|
-
- Added visual regression assertions. Glass and billing have been verified separately; combined verification remains pending because the current test profile does not include the wallpaper plugin.
|
|
12
42
|
|
|
13
43
|
## suite-installer-v0.1.23 — 2026-09-07
|
|
14
44
|
|
|
15
45
|
- Updated the bundled Codex UI to `0.2.106`, including sidebar glass support and billing entry styling.
|
|
16
|
-
- Other Suite members remain unchanged.
|
|
46
|
+
- Other Suite members remain unchanged.
|
|
17
47
|
|
|
18
48
|
## 0.2.105 — 2026-09-06
|
|
19
49
|
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,16 +4,46 @@
|
|
|
4
4
|
|
|
5
5
|
本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
|
|
6
6
|
|
|
7
|
+
## suite-installer-v0.1.27 - 2026-09-07
|
|
8
|
+
|
|
9
|
+
- 将套件中的 Codex UI 更新至 `0.2.108`,包含分组重命名、删除菜单和数量对齐优化;从官方 npm 刷新并锁定成员版本。
|
|
10
|
+
|
|
11
|
+
## 0.2.108 - 2026-09-07
|
|
12
|
+
|
|
13
|
+
- 为每个自定义工作区分组新增重命名和删除菜单;项目标题栏仅保留新增分组按钮。重命名保留项目归属、排序和展开状态。
|
|
14
|
+
- 对齐自定义分组与“未分组”的数量,避免长名称挤出菜单按钮,并完善重命名后的键盘焦点恢复。
|
|
15
|
+
- 防止新建分组时输入法选词误触发提交,修复名称校验失败影响偏好同步的问题。
|
|
16
|
+
- 统一不依赖系统语言环境的大小写判重规则,同时兼容保留旧分组名称和成员数据。
|
|
17
|
+
|
|
18
|
+
## suite-installer-v0.1.26 - 2026-09-07
|
|
19
|
+
|
|
20
|
+
- 从官方 npm 刷新直装成员版本,包含 IM Connect `0.1.37`,该版本已撤回未完成的主动投递功能。
|
|
21
|
+
|
|
22
|
+
## suite-installer-v0.1.25 - 2026-09-07
|
|
23
|
+
|
|
24
|
+
- 将套件中的 Codex UI 更新至 `0.2.107`,并从官方 npm 刷新直装成员版本,保证安装可复现。
|
|
25
|
+
|
|
26
|
+
## 0.2.107 - 2026-09-07
|
|
27
|
+
|
|
28
|
+
- 在 Codex UI 大标题旁显示当前运行版本,并将频道、定时的会话分组布局与任务页对齐。
|
|
29
|
+
- 将依赖更新请求限制为本机同源调用,并避免 Desktop 重复发送重载 IPC,同时保留独立 Web 的重载能力。
|
|
30
|
+
- 统一包契约为 Node.js 22.19.0+ 与 pnpm 11.22.0。
|
|
31
|
+
|
|
32
|
+
## suite-installer-v0.1.24 — 2026-09-07
|
|
33
|
+
|
|
34
|
+
- 套件新增 BTW 旁问和 Simplify 代码简化,一次安装八个配套插件。
|
|
35
|
+
- 从官方 npm 刷新并锁定成员版本,保证安装结果可复现。
|
|
36
|
+
- 为支持 Simplify,要求 Node.js 22.19.0 或更高版本。
|
|
37
|
+
|
|
7
38
|
## 0.2.106 — 2026-09-07
|
|
8
39
|
|
|
9
40
|
- 新增 Wallpaper Engine 侧栏玻璃兼容,并保持设置和搜索弹窗定位、点击正常。
|
|
10
41
|
- 将费用插件入口融入侧栏,统一与设置入口的图标大小、颜色、字号和间距,保留费用详情及收缩态入口。
|
|
11
|
-
- 补充视觉回归断言。玻璃与费用入口已分别验证;当前测试 profile 不含壁纸插件,组合验收仍待完成。
|
|
12
42
|
|
|
13
43
|
## suite-installer-v0.1.23 — 2026-09-07
|
|
14
44
|
|
|
15
45
|
- 更新套件中的 Codex UI 至 `0.2.106`,包含侧栏玻璃兼容和费用入口样式适配。
|
|
16
|
-
-
|
|
46
|
+
- 其他套件成员保持不变。
|
|
17
47
|
|
|
18
48
|
## 0.2.105 — 2026-09-06
|
|
19
49
|
|
package/lib/client.js
CHANGED
|
@@ -863,8 +863,8 @@ window.__ModuleLoader__.load({
|
|
|
863
863
|
this.code = code;
|
|
864
864
|
}
|
|
865
865
|
};
|
|
866
|
-
/**
|
|
867
|
-
function
|
|
866
|
+
/** 校验结构和归属;存储兼容模式保留旧 locale 下合法的大小写变体名称。 */
|
|
867
|
+
function parseGroups(value, preserveCaseVariants) {
|
|
868
868
|
if (!Array.isArray(value) || value.length > 100) return void 0;
|
|
869
869
|
const groupIds = /* @__PURE__ */ new Set();
|
|
870
870
|
const groupTitles = /* @__PURE__ */ new Set();
|
|
@@ -876,13 +876,14 @@ window.__ModuleLoader__.load({
|
|
|
876
876
|
const id = typeof group.id === "string" ? group.id.trim() : "";
|
|
877
877
|
const title = typeof group.title === "string" ? group.title.trim() : "";
|
|
878
878
|
if (id === "" || id.length > 128 || title === "" || title.length > 80) return void 0;
|
|
879
|
-
|
|
879
|
+
const titleKey = preserveCaseVariants ? title : title.toLowerCase();
|
|
880
|
+
if (groupIds.has(id) || groupTitles.has(titleKey)) return void 0;
|
|
880
881
|
if (!Array.isArray(group.workspaceIds) || group.workspaceIds.length > 1e3) return void 0;
|
|
881
882
|
const normalizedIds = [...new Set(group.workspaceIds)];
|
|
882
883
|
if (!normalizedIds.every((workspaceId) => typeof workspaceId === "string" && workspaceId.trim() !== "" && workspaceId.length <= 256)) return void 0;
|
|
883
884
|
if (normalizedIds.some((workspaceId) => workspaceIds.has(workspaceId))) return void 0;
|
|
884
885
|
groupIds.add(id);
|
|
885
|
-
groupTitles.add(
|
|
886
|
+
groupTitles.add(titleKey);
|
|
886
887
|
normalizedIds.forEach((workspaceId) => workspaceIds.add(workspaceId));
|
|
887
888
|
groups.push({
|
|
888
889
|
id,
|
|
@@ -892,15 +893,30 @@ window.__ModuleLoader__.load({
|
|
|
892
893
|
}
|
|
893
894
|
return groups;
|
|
894
895
|
}
|
|
896
|
+
/** 旧数据可往返保存且不改名;新名称的大小写判重由创建、重命名操作执行。 */
|
|
897
|
+
function parseStoredWorkspaceGroups(value) {
|
|
898
|
+
return parseGroups(value, true);
|
|
899
|
+
}
|
|
895
900
|
/** 新建空分组;项目只有被显式移动后才会进入其中。 */
|
|
896
901
|
function createWorkspaceGroup(groups, group) {
|
|
897
|
-
|
|
902
|
+
if (groups.some((existing) => existing.title.toLowerCase() === group.title.trim().toLowerCase())) throw new WorkspaceGroupError("group-invalid");
|
|
903
|
+
const next = parseStoredWorkspaceGroups([...groups, {
|
|
898
904
|
...group,
|
|
899
905
|
workspaceIds: []
|
|
900
906
|
}]);
|
|
901
907
|
if (next === void 0) throw new WorkspaceGroupError("group-invalid");
|
|
902
908
|
return next;
|
|
903
909
|
}
|
|
910
|
+
/** 仅更改名称,保留分组标识、成员及其顺序。 */
|
|
911
|
+
function renameWorkspaceGroup(groups, groupId, title) {
|
|
912
|
+
if (!groups.some((group) => group.id === groupId)) throw new WorkspaceGroupError("group-missing");
|
|
913
|
+
const normalizedTitle = title.trim();
|
|
914
|
+
if (normalizedTitle === "" || normalizedTitle.length > 80 || groups.some((group) => group.id !== groupId && group.title.toLowerCase() === normalizedTitle.toLowerCase())) throw new WorkspaceGroupError("group-invalid");
|
|
915
|
+
return groups.map((group) => group.id === groupId ? {
|
|
916
|
+
...group,
|
|
917
|
+
title: normalizedTitle
|
|
918
|
+
} : group);
|
|
919
|
+
}
|
|
904
920
|
/** 将项目放入指定分组;未传分组时退回未分组区。 */
|
|
905
921
|
function assignWorkspaceToGroup(groups, workspaceId, groupId) {
|
|
906
922
|
if (workspaceId.trim() === "" || workspaceId.length > 256) throw new WorkspaceGroupError("workspace-invalid");
|
|
@@ -1029,7 +1045,7 @@ window.__ModuleLoader__.load({
|
|
|
1029
1045
|
if (payload === null || typeof payload !== "object") throw new Error("置顶偏好响应格式无效。");
|
|
1030
1046
|
const record = payload;
|
|
1031
1047
|
const workspaceGroupsSupported = Object.prototype.hasOwnProperty.call(record, "workspaceGroups");
|
|
1032
|
-
const workspaceGroups = workspaceGroupsSupported ?
|
|
1048
|
+
const workspaceGroups = workspaceGroupsSupported ? parseStoredWorkspaceGroups(record.workspaceGroups) : [];
|
|
1033
1049
|
if (typeof record.exists !== "boolean" || !Array.isArray(record.pinnedWorkspaceIds) || !record.pinnedWorkspaceIds.every((id) => typeof id === "string") || workspaceGroups === void 0) throw new Error("置顶偏好响应格式无效。");
|
|
1034
1050
|
return {
|
|
1035
1051
|
exists: record.exists,
|
|
@@ -1039,7 +1055,7 @@ window.__ModuleLoader__.load({
|
|
|
1039
1055
|
};
|
|
1040
1056
|
}
|
|
1041
1057
|
async function writeHostWorkspacePreferences(pinnedWorkspaceIds, workspaceGroups, fetcher = fetch) {
|
|
1042
|
-
const groups =
|
|
1058
|
+
const groups = parseStoredWorkspaceGroups([...workspaceGroups]);
|
|
1043
1059
|
if (groups === void 0) throw new Error("工作区分组数据无效。");
|
|
1044
1060
|
const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
|
|
1045
1061
|
method: "PUT",
|
|
@@ -1100,7 +1116,7 @@ window.__ModuleLoader__.load({
|
|
|
1100
1116
|
pendingHostSync: false
|
|
1101
1117
|
};
|
|
1102
1118
|
const record = value;
|
|
1103
|
-
const workspaceGroups = record.version === 1 ?
|
|
1119
|
+
const workspaceGroups = record.version === 1 ? parseStoredWorkspaceGroups(record.workspaceGroups) : void 0;
|
|
1104
1120
|
if (workspaceGroups === void 0 || typeof record.pendingHostSync !== "boolean") return {
|
|
1105
1121
|
workspaceGroups: [],
|
|
1106
1122
|
pendingHostSync: false
|
|
@@ -1118,7 +1134,7 @@ window.__ModuleLoader__.load({
|
|
|
1118
1134
|
}
|
|
1119
1135
|
function saveWorkspaceGroupsCache(storage, groups, pendingHostSync) {
|
|
1120
1136
|
if (storage === void 0) return;
|
|
1121
|
-
const workspaceGroups =
|
|
1137
|
+
const workspaceGroups = parseStoredWorkspaceGroups([...groups]);
|
|
1122
1138
|
if (workspaceGroups === void 0) return;
|
|
1123
1139
|
try {
|
|
1124
1140
|
storage.setItem(WORKSPACE_GROUPS_STORAGE_KEY, JSON.stringify({
|
|
@@ -2199,6 +2215,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2199
2215
|
.dcu-wb-section+.dcu-wb-section{margin-top:12px}
|
|
2200
2216
|
.dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{position:relative;display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px 2px 12px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:0;text-align:left;cursor:pointer}.dcu-wb-section-caret{display:grid;place-items:center;flex:none;width:12px;height:12px;color:currentColor;opacity:0;transform:rotate(0deg);transform-origin:50% 50%;transition:opacity 120ms ease,transform 160ms ease}.dcu-wb-section-head .dcu-wb-section-caret{position:absolute;left:0;top:6px}.dcu-wb-section-caret svg{display:block}.dcu-wb-section-head:hover .dcu-wb-section-caret,.dcu-wb-section-label:focus-visible .dcu-wb-section-caret{opacity:.78}.dcu-wb-section-label[aria-expanded=true] .dcu-wb-section-caret{transform:rotate(90deg)}.dcu-wb-section-body{display:block}.dcu-wb-section-body[data-open=false]{display:none}.dcu-wb-section-body>div{min-height:0}.dcu-wb-section-body[data-open=true]>div{animation:dcu-wb-section-in 140ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-wb-section-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret{transition:none}.dcu-wb-section-body[data-open=true]>div{animation:none}}
|
|
2201
2217
|
.dcu-wb-project{position:relative;min-width:0}
|
|
2218
|
+
.dcu-wb-collection-head .dcu-wb-more{opacity:0;pointer-events:none}
|
|
2219
|
+
.dcu-wb-collection-head:hover .dcu-wb-more,.dcu-wb-collection-head:focus-within .dcu-wb-more,.dcu-wb-collection-head .dcu-wb-more[aria-expanded=true]{opacity:1;pointer-events:auto}
|
|
2220
|
+
@media (pointer:coarse){.dcu-wb-collection-head .dcu-wb-more{opacity:1;pointer-events:auto}}
|
|
2221
|
+
.dcu-wb-collection-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
2222
|
+
.dcu-wb-collection-actions{flex-shrink:0;width:20px}
|
|
2202
2223
|
.dcu-wb-collections{display:grid;min-width:0;gap:4px}.dcu-wb-collection,.dcu-wb-ungrouped{position:relative;min-width:0;overflow:visible}.dcu-wb-collection-head{display:flex;align-items:center;min-height:28px;padding:0 4px;border-radius:6px;transition:background 120ms ease}.dcu-wb-collection-head:hover,.dcu-wb-collection-head:focus-within,.dcu-wb-collection-head.dcu-wb-group-drop{background:var(--dcu-sidebar-hover)}.dcu-wb-collection-head.dcu-wb-group-drop{outline:1px solid var(--dsw-alias-state-business-primary)}.dcu-wb-collection-head[draggable=true],.dcu-wb-collection-head[draggable=true] .dcu-wb-collection-label{cursor:grab}.dcu-wb-collection-head[draggable=true]:active,.dcu-wb-collection-head[draggable=true]:active .dcu-wb-collection-label{cursor:grabbing}.dcu-wb-collection-label{display:flex;align-items:center;gap:5px;min-width:0;flex:1;border:0;padding:4px;background:transparent;color:var(--dcu-sidebar-primary);font:13px/20px var(--dcu-font,inherit);text-align:left;cursor:pointer}.dcu-wb-collection-label .dcu-wb-section-caret{position:static;order:-1;opacity:.78}.dcu-wb-collection-label[aria-expanded=true] .dcu-wb-section-caret{transform:rotate(90deg)}.dcu-wb-collection-count{margin-left:auto;color:var(--dcu-sidebar-secondary);font-variant-numeric:tabular-nums}.dcu-wb-collection-body{position:relative;min-width:0;padding-left:12px}.dcu-wb-collection-body::before{content:"";position:absolute;left:31px;top:0;bottom:8px;width:1px;background:var(--dcu-sidebar-border)}.dcu-wb-group-member{position:relative}.dcu-wb-group-member.dcu-wb-drop::before,.dcu-wb-collection.dcu-wb-group-order-drop::before,.dcu-wb-ungrouped.dcu-wb-group-order-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-group-member.dcu-wb-drop-after::before{top:auto;bottom:-8px}.dcu-wb-collection-body .dcu-wb-project-head{padding-left:12px}
|
|
2203
2224
|
.dcu-wb-collection.dcu-wb-workspace-move-drop,.dcu-wb-ungrouped.dcu-wb-workspace-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}
|
|
2204
2225
|
.dcu-wb-project-head,.dcu-wb-session{position:relative;display:flex;align-items:center;gap:6px;width:100%;min-width:0;border-radius:10px;padding:0 8px;color:var(--dcu-sidebar-primary);cursor:pointer}
|
|
@@ -2305,10 +2326,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2305
2326
|
setPinnedWorkspaceIdsState(next);
|
|
2306
2327
|
};
|
|
2307
2328
|
const setWorkspaceGroups = (update) => {
|
|
2308
|
-
pinnedHostDirtyRef.current = true;
|
|
2309
|
-
workspaceGroupsPendingHostSyncRef.current = true;
|
|
2310
2329
|
const current = workspaceGroupsRef.current;
|
|
2311
2330
|
const next = typeof update === "function" ? update(current) : update;
|
|
2331
|
+
pinnedHostDirtyRef.current = true;
|
|
2332
|
+
workspaceGroupsPendingHostSyncRef.current = true;
|
|
2312
2333
|
workspaceGroupsRef.current = next;
|
|
2313
2334
|
setWorkspaceGroupsState(next);
|
|
2314
2335
|
};
|
|
@@ -2353,7 +2374,12 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2353
2374
|
const [createGroupOpen, setCreateGroupOpen] = (0, react.useState)(false);
|
|
2354
2375
|
const [groupTitleDraft, setGroupTitleDraft] = (0, react.useState)("");
|
|
2355
2376
|
const [deleteGroupId, setDeleteGroupId] = (0, react.useState)();
|
|
2356
|
-
const [
|
|
2377
|
+
const [groupMenuId, setGroupMenuId] = (0, react.useState)();
|
|
2378
|
+
const [renameGroupId, setRenameGroupId] = (0, react.useState)();
|
|
2379
|
+
const [renameGroupDraft, setRenameGroupDraft] = (0, react.useState)("");
|
|
2380
|
+
const [renameGroupError, setRenameGroupError] = (0, react.useState)();
|
|
2381
|
+
const groupActionTriggerRef = (0, react.useRef)();
|
|
2382
|
+
const projectsSectionButtonRef = (0, react.useRef)(null);
|
|
2357
2383
|
(0, react.useEffect)(() => {
|
|
2358
2384
|
writeTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY, expanded);
|
|
2359
2385
|
}, [expanded]);
|
|
@@ -2611,6 +2637,28 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2611
2637
|
setError(userErrorText(reason, t));
|
|
2612
2638
|
}
|
|
2613
2639
|
};
|
|
2640
|
+
const closeRenameGroup = () => {
|
|
2641
|
+
setRenameGroupId(void 0);
|
|
2642
|
+
setRenameGroupDraft("");
|
|
2643
|
+
setRenameGroupError(void 0);
|
|
2644
|
+
const trigger = groupActionTriggerRef.current;
|
|
2645
|
+
const focusTarget = trigger?.isConnected ? trigger : projectsSectionButtonRef.current;
|
|
2646
|
+
groupActionTriggerRef.current = void 0;
|
|
2647
|
+
focusTarget?.focus();
|
|
2648
|
+
};
|
|
2649
|
+
const submitRenameGroup = () => {
|
|
2650
|
+
if (renameGroupId === void 0 || renameGroupDraft.trim() === "") return;
|
|
2651
|
+
if (workspaceGroupsRef.current.find((group) => group.id === renameGroupId)?.title === renameGroupDraft.trim()) {
|
|
2652
|
+
closeRenameGroup();
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
try {
|
|
2656
|
+
setWorkspaceGroups((current) => renameWorkspaceGroup(current, renameGroupId, renameGroupDraft));
|
|
2657
|
+
closeRenameGroup();
|
|
2658
|
+
} catch (reason) {
|
|
2659
|
+
setRenameGroupError(userErrorText(reason, t));
|
|
2660
|
+
}
|
|
2661
|
+
};
|
|
2614
2662
|
const sectionOpen = (id) => expanded[`section:${id}`] ?? true;
|
|
2615
2663
|
const toggleSection = (id) => {
|
|
2616
2664
|
setExpanded((current) => ({
|
|
@@ -3234,7 +3282,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3234
3282
|
setWorkspaceDropTarget(void 0);
|
|
3235
3283
|
setWorkspaceGroups((current) => current.find((candidate) => candidate.workspaceIds.includes(dragged))?.id === groupId ? moveWorkspaceGroupMember(current, dragged, groupId) : assignWorkspaceToGroup(current, dragged, groupId));
|
|
3236
3284
|
},
|
|
3237
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3285
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3238
3286
|
className: `dcu-wb-collection-head${workspaceGroupDragId === groupId ? " dcu-wb-dragging" : ""}`,
|
|
3239
3287
|
draggable: true,
|
|
3240
3288
|
onDragStart: (event) => {
|
|
@@ -3252,7 +3300,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3252
3300
|
setWorkspaceGroupDragId(void 0);
|
|
3253
3301
|
setWorkspaceGroupDropTarget(void 0);
|
|
3254
3302
|
},
|
|
3255
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3303
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3256
3304
|
type: "button",
|
|
3257
3305
|
className: "dcu-wb-collection-label",
|
|
3258
3306
|
"aria-expanded": isExpanded,
|
|
@@ -3277,13 +3325,74 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3277
3325
|
})
|
|
3278
3326
|
})
|
|
3279
3327
|
}),
|
|
3280
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3328
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3329
|
+
className: "dcu-wb-collection-title",
|
|
3330
|
+
children: group.title
|
|
3331
|
+
}),
|
|
3281
3332
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3282
3333
|
className: "dcu-wb-collection-count",
|
|
3283
3334
|
children: members.length
|
|
3284
3335
|
})
|
|
3285
3336
|
]
|
|
3286
|
-
})
|
|
3337
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3338
|
+
className: "dcu-wb-collection-actions",
|
|
3339
|
+
onClick: (event) => {
|
|
3340
|
+
event.stopPropagation();
|
|
3341
|
+
},
|
|
3342
|
+
onDragStart: (event) => {
|
|
3343
|
+
event.preventDefault();
|
|
3344
|
+
event.stopPropagation();
|
|
3345
|
+
},
|
|
3346
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
3347
|
+
open: groupMenuId === groupId,
|
|
3348
|
+
onClose: () => {
|
|
3349
|
+
setGroupMenuId(void 0);
|
|
3350
|
+
},
|
|
3351
|
+
items: [
|
|
3352
|
+
{
|
|
3353
|
+
id: "rename",
|
|
3354
|
+
label: t("workspace.renameGroup"),
|
|
3355
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 16 })
|
|
3356
|
+
},
|
|
3357
|
+
{
|
|
3358
|
+
type: "separator",
|
|
3359
|
+
id: "group-delete-separator"
|
|
3360
|
+
},
|
|
3361
|
+
{
|
|
3362
|
+
id: "delete",
|
|
3363
|
+
label: t("workspace.deleteGroupAction"),
|
|
3364
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 16 }),
|
|
3365
|
+
danger: true
|
|
3366
|
+
}
|
|
3367
|
+
],
|
|
3368
|
+
onSelect: (action) => {
|
|
3369
|
+
setGroupMenuId(void 0);
|
|
3370
|
+
if (action === "rename") {
|
|
3371
|
+
setRenameGroupId(groupId);
|
|
3372
|
+
setRenameGroupDraft(group.title);
|
|
3373
|
+
setRenameGroupError(void 0);
|
|
3374
|
+
}
|
|
3375
|
+
if (action === "delete") setDeleteGroupId(groupId);
|
|
3376
|
+
},
|
|
3377
|
+
portal: true,
|
|
3378
|
+
dense: true,
|
|
3379
|
+
compact: true,
|
|
3380
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3381
|
+
type: "button",
|
|
3382
|
+
className: "dcu-wb-more",
|
|
3383
|
+
draggable: false,
|
|
3384
|
+
"aria-haspopup": "menu",
|
|
3385
|
+
"aria-expanded": groupMenuId === groupId,
|
|
3386
|
+
"aria-label": t("workspace.groupActions", { name: group.title }),
|
|
3387
|
+
title: t("workspace.groupActions", { name: group.title }),
|
|
3388
|
+
onClick: (event) => {
|
|
3389
|
+
groupActionTriggerRef.current = event.currentTarget;
|
|
3390
|
+
setGroupMenuId((current) => current === groupId ? void 0 : groupId);
|
|
3391
|
+
},
|
|
3392
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
3393
|
+
})
|
|
3394
|
+
})
|
|
3395
|
+
})]
|
|
3287
3396
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DisclosureBody, {
|
|
3288
3397
|
className: "dcu-wb-collection-body",
|
|
3289
3398
|
open: isExpanded,
|
|
@@ -3397,9 +3506,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3397
3506
|
setWorkspaceGroups((current) => assignWorkspaceToGroup(current, dragged));
|
|
3398
3507
|
run("workspace-order", () => insertWorkspaceBefore(dragged));
|
|
3399
3508
|
},
|
|
3400
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3509
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3401
3510
|
className: "dcu-wb-collection-head",
|
|
3402
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3511
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3403
3512
|
type: "button",
|
|
3404
3513
|
className: "dcu-wb-collection-label",
|
|
3405
3514
|
"aria-expanded": ungroupedExpanded,
|
|
@@ -3430,7 +3539,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3430
3539
|
children: ungroupedGroups.length
|
|
3431
3540
|
})
|
|
3432
3541
|
]
|
|
3433
|
-
})
|
|
3542
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3543
|
+
className: "dcu-wb-collection-actions",
|
|
3544
|
+
"aria-hidden": "true"
|
|
3545
|
+
})]
|
|
3434
3546
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisclosureBody, {
|
|
3435
3547
|
className: "dcu-wb-collection-body",
|
|
3436
3548
|
open: ungroupedExpanded,
|
|
@@ -3611,6 +3723,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3611
3723
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3612
3724
|
type: "button",
|
|
3613
3725
|
className: "dcu-wb-section-label",
|
|
3726
|
+
ref: projectsSectionButtonRef,
|
|
3614
3727
|
"aria-expanded": sectionOpen("projects"),
|
|
3615
3728
|
onClick: () => {
|
|
3616
3729
|
toggleSection("projects");
|
|
@@ -3632,9 +3745,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3632
3745
|
})
|
|
3633
3746
|
})
|
|
3634
3747
|
})]
|
|
3635
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
3748
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3636
3749
|
className: "dcu-wb-actions",
|
|
3637
|
-
children:
|
|
3750
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3638
3751
|
type: "button",
|
|
3639
3752
|
className: "dcu-wb-more",
|
|
3640
3753
|
"aria-label": t("workspace.createGroup"),
|
|
@@ -3646,36 +3759,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3646
3759
|
setCreateGroupOpen(true);
|
|
3647
3760
|
},
|
|
3648
3761
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 })
|
|
3649
|
-
})
|
|
3650
|
-
open: groupMenuOpen,
|
|
3651
|
-
onClose: () => {
|
|
3652
|
-
setGroupMenuOpen(false);
|
|
3653
|
-
},
|
|
3654
|
-
items: workspaceGroups.map((group) => ({
|
|
3655
|
-
id: group.id,
|
|
3656
|
-
label: t("workspace.deleteGroup", { name: group.title }),
|
|
3657
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 16 }),
|
|
3658
|
-
danger: true
|
|
3659
|
-
})),
|
|
3660
|
-
onSelect: (id) => {
|
|
3661
|
-
setDeleteGroupId(id);
|
|
3662
|
-
setGroupMenuOpen(false);
|
|
3663
|
-
},
|
|
3664
|
-
portal: true,
|
|
3665
|
-
dense: true,
|
|
3666
|
-
compact: true,
|
|
3667
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3668
|
-
type: "button",
|
|
3669
|
-
className: "dcu-wb-more",
|
|
3670
|
-
"aria-label": t("workspace.manageGroups"),
|
|
3671
|
-
title: t("workspace.manageGroups"),
|
|
3672
|
-
onClick: (event) => {
|
|
3673
|
-
event.stopPropagation();
|
|
3674
|
-
setGroupMenuOpen((current) => !current);
|
|
3675
|
-
},
|
|
3676
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
3677
|
-
})
|
|
3678
|
-
})]
|
|
3762
|
+
})
|
|
3679
3763
|
})]
|
|
3680
3764
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3681
3765
|
className: "dcu-wb-section-body",
|
|
@@ -3881,6 +3965,57 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3881
3965
|
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, id));
|
|
3882
3966
|
}
|
|
3883
3967
|
}),
|
|
3968
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3969
|
+
open: renameGroupId !== void 0,
|
|
3970
|
+
onClose: closeRenameGroup,
|
|
3971
|
+
closeLabel: t("sessions.close"),
|
|
3972
|
+
title: t("workspace.renameGroup"),
|
|
3973
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3974
|
+
className: "dcu-wb-rename-actions",
|
|
3975
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3976
|
+
variant: "outline",
|
|
3977
|
+
onClick: closeRenameGroup,
|
|
3978
|
+
children: t("sessions.cancel")
|
|
3979
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3980
|
+
variant: "primary",
|
|
3981
|
+
disabled: renameGroupDraft.trim() === "",
|
|
3982
|
+
onClick: submitRenameGroup,
|
|
3983
|
+
children: t("sessions.save")
|
|
3984
|
+
})]
|
|
3985
|
+
}),
|
|
3986
|
+
children: [
|
|
3987
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3988
|
+
htmlFor: "dcu-workspace-group-name",
|
|
3989
|
+
children: t("workspace.groupName")
|
|
3990
|
+
}),
|
|
3991
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3992
|
+
id: "dcu-workspace-group-name",
|
|
3993
|
+
className: "dcu-wb-rename-input",
|
|
3994
|
+
"aria-label": t("workspace.groupName"),
|
|
3995
|
+
maxLength: 80,
|
|
3996
|
+
value: renameGroupDraft,
|
|
3997
|
+
autoFocus: true,
|
|
3998
|
+
onFocus: (event) => {
|
|
3999
|
+
event.target.select();
|
|
4000
|
+
},
|
|
4001
|
+
onChange: (event) => {
|
|
4002
|
+
setRenameGroupDraft(event.target.value);
|
|
4003
|
+
setRenameGroupError(void 0);
|
|
4004
|
+
},
|
|
4005
|
+
onKeyDown: (event) => {
|
|
4006
|
+
if (event.key === "Enter" && !event.nativeEvent.isComposing && event.keyCode !== 229) {
|
|
4007
|
+
event.preventDefault();
|
|
4008
|
+
submitRenameGroup();
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
4011
|
+
}),
|
|
4012
|
+
renameGroupError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4013
|
+
className: "dcu-wb-error",
|
|
4014
|
+
role: "alert",
|
|
4015
|
+
children: t("sessions.failed", { message: renameGroupError })
|
|
4016
|
+
})
|
|
4017
|
+
]
|
|
4018
|
+
}),
|
|
3884
4019
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3885
4020
|
open: createGroupOpen,
|
|
3886
4021
|
onClose: () => {
|
|
@@ -3918,7 +4053,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3918
4053
|
setError(void 0);
|
|
3919
4054
|
},
|
|
3920
4055
|
onKeyDown: (event) => {
|
|
3921
|
-
if (event.key === "Enter") {
|
|
4056
|
+
if (event.key === "Enter" && !event.nativeEvent.isComposing && event.keyCode !== 229) {
|
|
3922
4057
|
event.preventDefault();
|
|
3923
4058
|
submitCreateGroup();
|
|
3924
4059
|
}
|
|
@@ -4478,77 +4613,80 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4478
4613
|
[group.id]: !isExpanded
|
|
4479
4614
|
}));
|
|
4480
4615
|
}
|
|
4481
|
-
}), isExpanded &&
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
pendingInteraction,
|
|
4501
|
-
t,
|
|
4502
|
-
menuItems: sessionMenuItems(t, {
|
|
4616
|
+
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4617
|
+
className: "dcu-wb-project-body",
|
|
4618
|
+
children: group.sessions.map((session) => {
|
|
4619
|
+
const id = session.sessionId;
|
|
4620
|
+
const title = session.title;
|
|
4621
|
+
const selected = sessions.current === id;
|
|
4622
|
+
const running = session.running || sessions.byId[id]?.running === true;
|
|
4623
|
+
const updatedAt = session.updatedAt ?? sessions.byId[id]?.updatedAt;
|
|
4624
|
+
const unread = flags.unreadSessionIds.includes(id);
|
|
4625
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
4626
|
+
const moveTargets = moveSession === void 0 || workspaces === void 0 ? void 0 : sessionMoveTargets(workspaces.items, id).map((target) => ({
|
|
4627
|
+
...target,
|
|
4628
|
+
id: moveSessionActionId(target.id)
|
|
4629
|
+
}));
|
|
4630
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
4631
|
+
id,
|
|
4632
|
+
title,
|
|
4633
|
+
selected,
|
|
4634
|
+
menuOpen: menu?.id === id,
|
|
4503
4635
|
unread,
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
return;
|
|
4636
|
+
running,
|
|
4637
|
+
pendingInteraction,
|
|
4638
|
+
t,
|
|
4639
|
+
menuItems: sessionMenuItems(t, {
|
|
4640
|
+
unread,
|
|
4641
|
+
moveTargets
|
|
4642
|
+
}),
|
|
4643
|
+
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
4644
|
+
x: menu.x,
|
|
4645
|
+
y: menu.y
|
|
4646
|
+
} : void 0,
|
|
4647
|
+
onOpen: () => {
|
|
4648
|
+
flags.setUnreadSessionIds((ids) => ids.filter((item) => item !== id));
|
|
4649
|
+
openSession(id);
|
|
4650
|
+
},
|
|
4651
|
+
onMenuChange: (open) => {
|
|
4652
|
+
setMenu(open ? { id } : void 0);
|
|
4653
|
+
},
|
|
4654
|
+
onArchive: () => {
|
|
4655
|
+
run("archive", () => archiveSession(id));
|
|
4656
|
+
},
|
|
4657
|
+
onHover: (event) => {
|
|
4658
|
+
const box = hoverCardAnchor(event.currentTarget.getBoundingClientRect());
|
|
4659
|
+
showTip({
|
|
4660
|
+
title,
|
|
4661
|
+
project: label,
|
|
4662
|
+
time: updatedAt === void 0 ? void 0 : formatHoverTime(updatedAt, t),
|
|
4663
|
+
left: box.left,
|
|
4664
|
+
top: box.top
|
|
4665
|
+
});
|
|
4666
|
+
},
|
|
4667
|
+
onLeave: hideTip,
|
|
4668
|
+
onContextMenu: (event) => {
|
|
4669
|
+
event.preventDefault();
|
|
4670
|
+
event.stopPropagation();
|
|
4671
|
+
dismissTip();
|
|
4672
|
+
setMenu({
|
|
4673
|
+
id,
|
|
4674
|
+
x: event.clientX,
|
|
4675
|
+
y: event.clientY
|
|
4676
|
+
});
|
|
4677
|
+
},
|
|
4678
|
+
onSelectAction: (action) => {
|
|
4679
|
+
if (busy !== void 0) return;
|
|
4680
|
+
const targetWorkspaceId = parseMoveSessionActionId(action);
|
|
4681
|
+
if (targetWorkspaceId !== void 0 && moveSession !== void 0) {
|
|
4682
|
+
setMenu(void 0);
|
|
4683
|
+
run("session-move", () => moveSession(id, targetWorkspaceId));
|
|
4684
|
+
return;
|
|
4685
|
+
}
|
|
4686
|
+
dialogs.handleAction(action, id, title);
|
|
4548
4687
|
}
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
}, id);
|
|
4688
|
+
}, id);
|
|
4689
|
+
})
|
|
4552
4690
|
})]
|
|
4553
4691
|
}, group.id);
|
|
4554
4692
|
})
|
|
@@ -4780,74 +4918,77 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4780
4918
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
4781
4919
|
})
|
|
4782
4920
|
})
|
|
4783
|
-
}), isExpanded &&
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
pendingInteraction,
|
|
4800
|
-
t,
|
|
4801
|
-
menuItems: sessionMenuItems(t, {
|
|
4921
|
+
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4922
|
+
className: "dcu-wb-project-body",
|
|
4923
|
+
children: group.sessions.map((session) => {
|
|
4924
|
+
const id = session.id;
|
|
4925
|
+
const title = session.title;
|
|
4926
|
+
const unread = flags.unreadSessionIds.includes(id);
|
|
4927
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
4928
|
+
const moveTargets = moveSession === void 0 ? void 0 : sessionMoveTargets(workspaces.items ?? [], id).map((target) => ({
|
|
4929
|
+
...target,
|
|
4930
|
+
id: moveSessionActionId(target.id)
|
|
4931
|
+
}));
|
|
4932
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
4933
|
+
id,
|
|
4934
|
+
title,
|
|
4935
|
+
selected: sessions.current === id,
|
|
4936
|
+
menuOpen: menu?.id === id,
|
|
4802
4937
|
unread,
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
return;
|
|
4938
|
+
running: session.running,
|
|
4939
|
+
pendingInteraction,
|
|
4940
|
+
t,
|
|
4941
|
+
menuItems: sessionMenuItems(t, {
|
|
4942
|
+
unread,
|
|
4943
|
+
moveTargets
|
|
4944
|
+
}),
|
|
4945
|
+
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
4946
|
+
x: menu.x,
|
|
4947
|
+
y: menu.y
|
|
4948
|
+
} : void 0,
|
|
4949
|
+
onOpen: () => {
|
|
4950
|
+
flags.setUnreadSessionIds((ids) => ids.filter((item) => item !== id));
|
|
4951
|
+
openSession(id);
|
|
4952
|
+
},
|
|
4953
|
+
onMenuChange: (open) => {
|
|
4954
|
+
setMenu(open ? { id } : void 0);
|
|
4955
|
+
},
|
|
4956
|
+
onArchive: () => {
|
|
4957
|
+
run("archive", () => archiveSession(id));
|
|
4958
|
+
},
|
|
4959
|
+
onHover: (event) => {
|
|
4960
|
+
const box = hoverCardAnchor(event.currentTarget.getBoundingClientRect());
|
|
4961
|
+
showTip({
|
|
4962
|
+
title,
|
|
4963
|
+
project: group.label,
|
|
4964
|
+
time: session.updatedAt === void 0 ? void 0 : formatHoverTime(session.updatedAt, t),
|
|
4965
|
+
left: box.left,
|
|
4966
|
+
top: box.top
|
|
4967
|
+
});
|
|
4968
|
+
},
|
|
4969
|
+
onLeave: hideTip,
|
|
4970
|
+
onContextMenu: (event) => {
|
|
4971
|
+
event.preventDefault();
|
|
4972
|
+
event.stopPropagation();
|
|
4973
|
+
dismissTip();
|
|
4974
|
+
setMenu({
|
|
4975
|
+
id,
|
|
4976
|
+
x: event.clientX,
|
|
4977
|
+
y: event.clientY
|
|
4978
|
+
});
|
|
4979
|
+
},
|
|
4980
|
+
onSelectAction: (action) => {
|
|
4981
|
+
if (busy !== void 0) return;
|
|
4982
|
+
const targetWorkspaceId = parseMoveSessionActionId(action);
|
|
4983
|
+
if (targetWorkspaceId !== void 0 && moveSession !== void 0) {
|
|
4984
|
+
setMenu(void 0);
|
|
4985
|
+
run("session-move", () => moveSession(id, targetWorkspaceId));
|
|
4986
|
+
return;
|
|
4987
|
+
}
|
|
4988
|
+
dialogs.handleAction(action, id, title);
|
|
4847
4989
|
}
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
}, id);
|
|
4990
|
+
}, id);
|
|
4991
|
+
})
|
|
4851
4992
|
})]
|
|
4852
4993
|
}, group.id);
|
|
4853
4994
|
})
|
|
@@ -5999,6 +6140,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5999
6140
|
const stylesheet$2 = `
|
|
6000
6141
|
.dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:24px}.dcu-about-dependencies-heading h3{margin:0}.dcu-about-dependencies-heading+.dcu-about-intro{margin-bottom:14px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;line-height:20px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-update-all{min-width:92px}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}.dcu-about-progress{display:grid;grid-template-columns:auto 1fr auto;gap:8px 10px;align-items:center;margin-top:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px}.dcu-about-progress code{min-width:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-progress-pct{color:var(--dsw-alias-label-tertiary);font-size:12px;font-variant-numeric:tabular-nums}.dcu-about-progress-bar{grid-column:1/-1;height:4px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2)}.dcu-about-progress-fill{height:100%;background:var(--dsw-alias-state-business-primary);transition:width .2s ease}.dcu-about-progress-fill[data-wave=true]{width:28%;animation:dcu-about-progress-wave 1.2s ease-in-out infinite}@keyframes dcu-about-progress-wave{0%{transform:translateX(-60%)}100%{transform:translateX(280%)}}
|
|
6001
6142
|
.dcu-about-title-row{display:flex;align-items:center;gap:8px;min-width:0}.dcu-about-links{display:flex;align-items:center;gap:4px}.dcu-about-external-link{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dcu-about-external-link:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dcu-about-external-link:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dcu-about-external-link svg{flex:none}@media(max-width:720px){.dcu-about-title-row{flex-wrap:wrap}}
|
|
6143
|
+
.dcu-about-version{margin-left:8px;color:var(--dsw-alias-label-tertiary);font-family:inherit;font-size:12px;font-weight:500;line-height:18px;letter-spacing:0;white-space:nowrap;vertical-align:baseline}
|
|
6002
6144
|
`;
|
|
6003
6145
|
/** 宿主图标库不提供 GitHub 品牌标识,内联后可离线使用并继承当前文字颜色。 */
|
|
6004
6146
|
function GithubMark16() {
|
|
@@ -6187,6 +6329,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6187
6329
|
}
|
|
6188
6330
|
};
|
|
6189
6331
|
const actionableCount = dependencies.filter((dependency) => !dependency.installed || dependency.updateAvailable).length;
|
|
6332
|
+
const selfVersion = dependencies.find((dependency) => dependency.id === "ui")?.version;
|
|
6190
6333
|
const title = (id) => t(`about.dependency.${id}`);
|
|
6191
6334
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
6192
6335
|
ref: root,
|
|
@@ -6196,7 +6339,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6196
6339
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$2 }),
|
|
6197
6340
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6198
6341
|
className: "dcu-about-title-row",
|
|
6199
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6342
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [t("about.title"), selfVersion === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6343
|
+
className: "dcu-about-version",
|
|
6344
|
+
children: ["v", selfVersion]
|
|
6345
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6200
6346
|
className: "dcu-about-links",
|
|
6201
6347
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
6202
6348
|
className: "dcu-about-external-link",
|
|
@@ -6569,7 +6715,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6569
6715
|
"workspace.deleteGroup": "删除分组“{name}”",
|
|
6570
6716
|
"workspace.deleteGroupAction": "删除分组",
|
|
6571
6717
|
"workspace.deleteGroupDescription": "删除分组只会将其中项目移至未分组,不会删除项目或会话。",
|
|
6572
|
-
"workspace.
|
|
6718
|
+
"workspace.groupActions": "分组“{name}”的操作",
|
|
6719
|
+
"workspace.renameGroup": "重命名分组",
|
|
6573
6720
|
"workspace.recent": "最近",
|
|
6574
6721
|
"workspace.recentEmpty": "无聊天",
|
|
6575
6722
|
"workspace.noChat": "没有聊天",
|
|
@@ -6769,7 +6916,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6769
6916
|
"workspace.deleteGroup": "Delete group {name}",
|
|
6770
6917
|
"workspace.deleteGroupAction": "Delete group",
|
|
6771
6918
|
"workspace.deleteGroupDescription": "Deleting this group moves its projects to Ungrouped. It does not delete projects or conversations.",
|
|
6772
|
-
"workspace.
|
|
6919
|
+
"workspace.groupActions": "Actions for group {name}",
|
|
6920
|
+
"workspace.renameGroup": "Rename group",
|
|
6773
6921
|
"workspace.recent": "Recents",
|
|
6774
6922
|
"workspace.recentEmpty": "No chats",
|
|
6775
6923
|
"workspace.noChat": "No chats",
|
|
@@ -6957,7 +7105,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
6957
7105
|
[["连接器", "Connectors"], "connectors"],
|
|
6958
7106
|
[["定时任务", "Scheduled tasks"], "schedule"],
|
|
6959
7107
|
[["IM助理", "IM Assistant"], "assistant"],
|
|
6960
|
-
[[
|
|
7108
|
+
[[
|
|
7109
|
+
"已归档",
|
|
7110
|
+
"归档会话",
|
|
7111
|
+
"Archived",
|
|
7112
|
+
"Archived sessions"
|
|
7113
|
+
], "archive"],
|
|
6961
7114
|
[["Codex UI"], "about"]
|
|
6962
7115
|
];
|
|
6963
7116
|
/** 按设置导航可见文案解析侧栏同款图标;插件市场复用插件图标。 */
|
package/lib/index.d.mts
CHANGED
|
@@ -4,13 +4,14 @@ type HostRequest = {
|
|
|
4
4
|
method?: string;
|
|
5
5
|
url?: string;
|
|
6
6
|
headers?: Record<string, string | string[] | undefined>;
|
|
7
|
+
socket?: {
|
|
8
|
+
remoteAddress?: string;
|
|
9
|
+
};
|
|
7
10
|
[Symbol.asyncIterator]?: () => AsyncIterator<Uint8Array | string>;
|
|
8
11
|
};
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 且无法被页面伪造)再按 Origin 与 Host 的比对阻断;无这些头的
|
|
13
|
-
* 非浏览器客户端(curl、CLI)仍然放行。
|
|
13
|
+
* 依赖安装会改写用户配置并拉起子进程,只允许回环地址上的同源浏览器请求。
|
|
14
|
+
* Origin、Host 和 Sec-Fetch-Site 都可被非浏览器客户端伪造,不能单独作为授权依据。
|
|
14
15
|
*/
|
|
15
16
|
declare function crossSiteRequest(request: HostRequest): boolean;
|
|
16
17
|
/** 把安装错误收成可给浏览器看的文案:我们自己的中文说明保留,带本地路径的底层错误脱敏。 */
|
package/lib/index.mjs
CHANGED
|
@@ -350,6 +350,10 @@ function requestDesktopHotUpdate(send = process.send) {
|
|
|
350
350
|
send(APPLY_PLUGIN_UPDATES_IPC);
|
|
351
351
|
return true;
|
|
352
352
|
}
|
|
353
|
+
/** Desktop 的包管理服务会自行安排重载;只有独立 Web 子进程需要通知父进程。 */
|
|
354
|
+
function canRequestParentReload(runtime, send = process.send) {
|
|
355
|
+
return runtime.environmentKind === "cli" && typeof send === "function";
|
|
356
|
+
}
|
|
353
357
|
async function recordPendingUpdate(packageName, version, runtime) {
|
|
354
358
|
const pendingPath = resolve(profileDirectory(runtime), PROFILE_PENDING_UPDATES_FILE);
|
|
355
359
|
let packages = [];
|
|
@@ -1442,8 +1446,8 @@ async function moveSessionToWorkspace(services, sessionId, targetWorkspaceId, op
|
|
|
1442
1446
|
movingSessions.delete(sessionId);
|
|
1443
1447
|
}
|
|
1444
1448
|
}
|
|
1445
|
-
/**
|
|
1446
|
-
function
|
|
1449
|
+
/** 校验结构和归属;存储兼容模式保留旧 locale 下合法的大小写变体名称。 */
|
|
1450
|
+
function parseGroups(value, preserveCaseVariants) {
|
|
1447
1451
|
if (!Array.isArray(value) || value.length > 100) return void 0;
|
|
1448
1452
|
const groupIds = /* @__PURE__ */ new Set();
|
|
1449
1453
|
const groupTitles = /* @__PURE__ */ new Set();
|
|
@@ -1455,13 +1459,14 @@ function parseWorkspaceGroups(value) {
|
|
|
1455
1459
|
const id = typeof group.id === "string" ? group.id.trim() : "";
|
|
1456
1460
|
const title = typeof group.title === "string" ? group.title.trim() : "";
|
|
1457
1461
|
if (id === "" || id.length > 128 || title === "" || title.length > 80) return void 0;
|
|
1458
|
-
|
|
1462
|
+
const titleKey = preserveCaseVariants ? title : title.toLowerCase();
|
|
1463
|
+
if (groupIds.has(id) || groupTitles.has(titleKey)) return void 0;
|
|
1459
1464
|
if (!Array.isArray(group.workspaceIds) || group.workspaceIds.length > 1e3) return void 0;
|
|
1460
1465
|
const normalizedIds = [...new Set(group.workspaceIds)];
|
|
1461
1466
|
if (!normalizedIds.every((workspaceId) => typeof workspaceId === "string" && workspaceId.trim() !== "" && workspaceId.length <= 256)) return void 0;
|
|
1462
1467
|
if (normalizedIds.some((workspaceId) => workspaceIds.has(workspaceId))) return void 0;
|
|
1463
1468
|
groupIds.add(id);
|
|
1464
|
-
groupTitles.add(
|
|
1469
|
+
groupTitles.add(titleKey);
|
|
1465
1470
|
normalizedIds.forEach((workspaceId) => workspaceIds.add(workspaceId));
|
|
1466
1471
|
groups.push({
|
|
1467
1472
|
id,
|
|
@@ -1471,6 +1476,10 @@ function parseWorkspaceGroups(value) {
|
|
|
1471
1476
|
}
|
|
1472
1477
|
return groups;
|
|
1473
1478
|
}
|
|
1479
|
+
/** 旧数据可往返保存且不改名;新名称的大小写判重由创建、重命名操作执行。 */
|
|
1480
|
+
function parseStoredWorkspaceGroups(value) {
|
|
1481
|
+
return parseGroups(value, true);
|
|
1482
|
+
}
|
|
1474
1483
|
//#endregion
|
|
1475
1484
|
//#region src/workspace-preferences.ts
|
|
1476
1485
|
const WORKSPACE_PREFERENCES_FILE = ".dsh-codex-ui-preferences.json";
|
|
@@ -1495,7 +1504,7 @@ function parseWorkspacePreferences(value) {
|
|
|
1495
1504
|
workspaceGroups: []
|
|
1496
1505
|
};
|
|
1497
1506
|
if (record.version !== 2) return void 0;
|
|
1498
|
-
const workspaceGroups =
|
|
1507
|
+
const workspaceGroups = parseStoredWorkspaceGroups(record.workspaceGroups);
|
|
1499
1508
|
return workspaceGroups === void 0 ? void 0 : {
|
|
1500
1509
|
version: 2,
|
|
1501
1510
|
pinnedWorkspaceIds,
|
|
@@ -1527,7 +1536,7 @@ let writeQueue = Promise.resolve();
|
|
|
1527
1536
|
/** 串行、原子保存,避免快速拖动排序产生乱序或半截 JSON。 */
|
|
1528
1537
|
function writeWorkspacePreferences(pinnedWorkspaceIds, workspaceGroups = [], path = workspacePreferencesPath()) {
|
|
1529
1538
|
const normalized = parsePinnedWorkspaceIds([...pinnedWorkspaceIds]);
|
|
1530
|
-
const normalizedGroups =
|
|
1539
|
+
const normalizedGroups = parseStoredWorkspaceGroups([...workspaceGroups]);
|
|
1531
1540
|
if (normalized === void 0 || normalizedGroups === void 0) return Promise.reject(/* @__PURE__ */ new Error("工作区偏好数据无效。"));
|
|
1532
1541
|
const task = writeQueue.catch(() => void 0).then(async () => {
|
|
1533
1542
|
await mkdir(dirname(path), { recursive: true });
|
|
@@ -1554,29 +1563,31 @@ const explorerEndpoint = "/api/michengai/codex-ui/open-in-explorer";
|
|
|
1554
1563
|
const preferencesEndpoint = "/api/michengai/codex-ui/preferences";
|
|
1555
1564
|
const sessionMoveEndpoint = "/api/michengai/codex-ui/session-move";
|
|
1556
1565
|
const maxPreferencesBodyBytes = 32768;
|
|
1566
|
+
function isLoopbackAddress(value) {
|
|
1567
|
+
const address = value?.toLowerCase().replace(/^\[|\]$/g, "");
|
|
1568
|
+
return address === "localhost" || address === "localhost." || address === "::1" || address?.startsWith("127.") === true || address?.startsWith("::ffff:127.") === true;
|
|
1569
|
+
}
|
|
1557
1570
|
function headerValue(headers, name) {
|
|
1558
1571
|
const value = headers[name];
|
|
1559
1572
|
if (typeof value === "string") return value;
|
|
1560
1573
|
if (Array.isArray(value)) return value[0];
|
|
1561
1574
|
}
|
|
1562
1575
|
/**
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1565
|
-
* 且无法被页面伪造)再按 Origin 与 Host 的比对阻断;无这些头的
|
|
1566
|
-
* 非浏览器客户端(curl、CLI)仍然放行。
|
|
1576
|
+
* 依赖安装会改写用户配置并拉起子进程,只允许回环地址上的同源浏览器请求。
|
|
1577
|
+
* Origin、Host 和 Sec-Fetch-Site 都可被非浏览器客户端伪造,不能单独作为授权依据。
|
|
1567
1578
|
*/
|
|
1568
1579
|
function crossSiteRequest(request) {
|
|
1580
|
+
if (!isLoopbackAddress(request.socket?.remoteAddress)) return true;
|
|
1569
1581
|
const headers = request.headers;
|
|
1570
|
-
if (headers === void 0) return
|
|
1582
|
+
if (headers === void 0) return true;
|
|
1571
1583
|
const site = headerValue(headers, "sec-fetch-site");
|
|
1572
|
-
if (site
|
|
1573
|
-
if (site !== void 0) return true;
|
|
1584
|
+
if (site !== void 0 && site !== "same-origin") return true;
|
|
1574
1585
|
const origin = headerValue(headers, "origin");
|
|
1575
|
-
if (origin === void 0) return false;
|
|
1576
1586
|
const host = headerValue(headers, "host");
|
|
1577
|
-
if (host === void 0) return true;
|
|
1587
|
+
if (origin === void 0 || host === void 0) return true;
|
|
1578
1588
|
try {
|
|
1579
|
-
|
|
1589
|
+
const url = new URL(origin);
|
|
1590
|
+
return url.protocol !== "http:" && url.protocol !== "https:" || !isLoopbackAddress(url.hostname) || url.host !== host;
|
|
1580
1591
|
} catch {
|
|
1581
1592
|
return true;
|
|
1582
1593
|
}
|
|
@@ -1724,16 +1735,18 @@ function apply(ctx) {
|
|
|
1724
1735
|
"content-type": "application/json; charset=utf-8",
|
|
1725
1736
|
"cache-control": "no-store"
|
|
1726
1737
|
});
|
|
1727
|
-
response.end(JSON.stringify({ error: "
|
|
1738
|
+
response.end(JSON.stringify({ error: "已拒绝非本机同源请求。" }));
|
|
1728
1739
|
return;
|
|
1729
1740
|
}
|
|
1730
1741
|
if (url.searchParams.get("action") === "update-all") {
|
|
1731
|
-
const
|
|
1742
|
+
const runtime = resolveDependencyRuntime(ctx);
|
|
1743
|
+
const notifyParent = canRequestParentReload(runtime);
|
|
1744
|
+
const autoReload = runtime.environmentKind === "desktop" || notifyParent;
|
|
1732
1745
|
let restartAfterResponse = false;
|
|
1733
1746
|
const { dependencies, updatedCount } = await updateAllDependencies(() => {
|
|
1734
|
-
restartAfterResponse =
|
|
1747
|
+
restartAfterResponse = notifyParent;
|
|
1735
1748
|
return restartAfterResponse;
|
|
1736
|
-
},
|
|
1749
|
+
}, runtime);
|
|
1737
1750
|
response.writeHead(200, {
|
|
1738
1751
|
"content-type": "application/json; charset=utf-8",
|
|
1739
1752
|
"cache-control": "no-store"
|
|
@@ -1741,19 +1754,21 @@ function apply(ctx) {
|
|
|
1741
1754
|
response.end(JSON.stringify({
|
|
1742
1755
|
dependencies,
|
|
1743
1756
|
restartRequired: updatedCount > 0,
|
|
1744
|
-
autoReload
|
|
1757
|
+
autoReload
|
|
1745
1758
|
}));
|
|
1746
1759
|
if (restartAfterResponse) setTimeout(() => {
|
|
1747
1760
|
requestDesktopHotUpdate();
|
|
1748
1761
|
}, 150).unref?.();
|
|
1749
1762
|
return;
|
|
1750
1763
|
}
|
|
1751
|
-
const
|
|
1764
|
+
const runtime = resolveDependencyRuntime(ctx);
|
|
1765
|
+
const notifyParent = canRequestParentReload(runtime);
|
|
1766
|
+
const autoReload = runtime.environmentKind === "desktop" || notifyParent;
|
|
1752
1767
|
let restartAfterResponse = false;
|
|
1753
1768
|
const dependencies = await installDependency(url.searchParams.get("dependency"), () => {
|
|
1754
|
-
restartAfterResponse =
|
|
1769
|
+
restartAfterResponse = notifyParent;
|
|
1755
1770
|
return restartAfterResponse;
|
|
1756
|
-
},
|
|
1771
|
+
}, runtime);
|
|
1757
1772
|
response.writeHead(200, {
|
|
1758
1773
|
"content-type": "application/json; charset=utf-8",
|
|
1759
1774
|
"cache-control": "no-store"
|
|
@@ -1761,7 +1776,7 @@ function apply(ctx) {
|
|
|
1761
1776
|
response.end(JSON.stringify({
|
|
1762
1777
|
dependencies,
|
|
1763
1778
|
restartRequired: true,
|
|
1764
|
-
autoReload
|
|
1779
|
+
autoReload
|
|
1765
1780
|
}));
|
|
1766
1781
|
if (restartAfterResponse) setTimeout(() => {
|
|
1767
1782
|
requestDesktopHotUpdate();
|
|
@@ -1807,8 +1822,9 @@ function apply(ctx) {
|
|
|
1807
1822
|
const record = body !== null && typeof body === "object" ? body : void 0;
|
|
1808
1823
|
const pinnedWorkspaceIds = record === void 0 ? void 0 : parsePinnedWorkspaceIds(record.pinnedWorkspaceIds);
|
|
1809
1824
|
const existing = await readWorkspacePreferences();
|
|
1810
|
-
const workspaceGroups = record === void 0 ? void 0 : "workspaceGroups" in record ?
|
|
1811
|
-
|
|
1825
|
+
const workspaceGroups = record === void 0 ? void 0 : "workspaceGroups" in record ? parseStoredWorkspaceGroups(record.workspaceGroups) : existing.workspaceGroups;
|
|
1826
|
+
const introducesTitleConflict = workspaceGroups?.some((group) => !existing.workspaceGroups.some((previous) => previous.id === group.id && previous.title === group.title) && workspaceGroups.some((other) => other.id !== group.id && other.title.toLowerCase() === group.title.toLowerCase())) === true;
|
|
1827
|
+
if (pinnedWorkspaceIds === void 0 || workspaceGroups === void 0 || introducesTitleConflict) {
|
|
1812
1828
|
response.writeHead(400, {
|
|
1813
1829
|
"content-type": "application/json; charset=utf-8",
|
|
1814
1830
|
"cache-control": "no-store"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-codex-ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.108",
|
|
4
4
|
"description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
"homepage": "https://github.com/MichengAI/dsh-codex-ui#readme",
|
|
18
18
|
"type": "module",
|
|
19
19
|
"packageManager": "pnpm@11.22.0",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
22
|
+
},
|
|
20
23
|
"main": "lib/index.mjs",
|
|
21
24
|
"types": "lib/index.d.mts",
|
|
22
25
|
"exports": {
|