@michengai/dsh-codex-ui 0.2.87 → 0.2.89
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 +43 -0
- package/CHANGELOG.zh-CN.md +43 -0
- package/dist/client.js +544 -78
- package/dist/index.mjs +37 -4
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,49 @@
|
|
|
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
|
+
## 0.2.89 — 2026-08-27
|
|
8
|
+
|
|
9
|
+
Companion release: `@michengai/dsh-codex-suite-installer@0.1.6`.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Persisted workspace, channel, and scheduled-task folder expansion independently across refreshes with versioned, failure-safe browser storage.
|
|
14
|
+
- Added scheduled-task list/overview switching, direct task-settings navigation, and group archive actions.
|
|
15
|
+
- Added Node.js 22/24 CI for pushes and pull requests, and made the tag Release workflow run the full test suite before creating a release.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Stopped classifying ordinary conversations as scheduled tasks from an editable timestamp-shaped title; automation ownership now requires the stable session ID prefix.
|
|
20
|
+
- Made group archive continue after individual failures, clean local pin/unread state only for successful items, and leave failures selected for retry.
|
|
21
|
+
- Validated scheduled-task settings requests at runtime, guarded browser storage access, and extended lazy Settings navigation to four seconds.
|
|
22
|
+
- Restricted the Windows Explorer Host endpoint to exact registered workspace roots, rejecting drive roots, UNC paths, relative paths, children, and unrelated absolute paths.
|
|
23
|
+
- Reduced compatibility observer work by filtering unrelated conversation, permission, and Settings DOM mutations before scheduling scans.
|
|
24
|
+
|
|
25
|
+
### Release process
|
|
26
|
+
|
|
27
|
+
- Aligned the root package, lightweight installer, private legacy Suite snapshot, member pins, and version-contract assertions; the aggregate Suite remains retired.
|
|
28
|
+
- Corrected the installer command and executable name in local-verification help and READMEs, and added a build contract for the client bundle's static runtime modules.
|
|
29
|
+
- Tracked and refreshed the current handoff documentation under `docs/00-交接入口/` while leaving historical documentation ignored.
|
|
30
|
+
- Hardened the Windows installer against shell metacharacters in `DSH_BIN`.
|
|
31
|
+
|
|
32
|
+
## 0.2.88 — 2026-08-26
|
|
33
|
+
|
|
34
|
+
Companion release: `@michengai/dsh-codex-suite-installer@0.1.5`.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Replaced the lightweight **Settings → Connectors** tool list with the complete `dsh-mcp-connector` marketplace and connection manager whenever that optional external plugin is installed.
|
|
39
|
+
- Kept the existing **Connectors** home/sidebar action as the single entry point and suppressed the external plugin's separate launcher in both expanded and compact Codex sidebar layouts.
|
|
40
|
+
- Preserved the original current-session MCP tool directory as an automatic fallback when `dsh-mcp-connector` is absent or its Web UI is unavailable.
|
|
41
|
+
|
|
42
|
+
### Compatibility
|
|
43
|
+
|
|
44
|
+
- Added a same-origin, source-validated Prompt bridge that creates or reuses a workspace session and places the selected marketplace Prompt into its draft.
|
|
45
|
+
- Synchronized the embedded marketplace with the DSH-selected light or dark theme without modifying the externally maintained plugin or making it a required dependency.
|
|
46
|
+
- Updated the lightweight installer to pin Codex UI `0.2.88`; the legacy aggregate Suite remains private and unpublished.
|
|
47
|
+
|
|
48
|
+
Published packages: [`@michengai/dsh-codex-ui@0.2.88`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.88) and [`@michengai/dsh-codex-suite-installer@0.1.5`](https://www.npmjs.com/package/@michengai/dsh-codex-suite-installer/v/0.1.5).
|
|
49
|
+
|
|
7
50
|
## 0.2.87 — 2026-08-26
|
|
8
51
|
|
|
9
52
|
Companion release: `@michengai/dsh-codex-suite-installer@0.1.4`.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,6 +4,49 @@
|
|
|
4
4
|
|
|
5
5
|
本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
|
|
6
6
|
|
|
7
|
+
## 0.2.89 — 2026-08-27
|
|
8
|
+
|
|
9
|
+
配套版本:`@michengai/dsh-codex-suite-installer@0.1.6`。
|
|
10
|
+
|
|
11
|
+
### 新增
|
|
12
|
+
|
|
13
|
+
- 工作区、频道和定时任务文件夹分别持久化展开/折叠状态;存储带版本,损坏或不可用时安全回退。
|
|
14
|
+
- 定时任务侧栏增加列表/概览切换、直接打开任务设置和整组归档。
|
|
15
|
+
- main push 与 PR 在 Node.js 22/24 上运行 CI;tag Release 创建版本前也必须通过完整测试。
|
|
16
|
+
|
|
17
|
+
### 修复
|
|
18
|
+
|
|
19
|
+
- 不再根据用户可编辑的时间戳格式标题把普通会话误判为定时任务;自动化归属只认稳定的会话 ID 前缀。
|
|
20
|
+
- 整组归档遇到单项失败时继续处理后续会话,只清理成功项的本地置顶/未读状态,并保留失败项供重试。
|
|
21
|
+
- 为定时任务设置请求增加运行时校验,保护浏览器存储访问,并把设置壳慢加载等待时间延长到 4 秒。
|
|
22
|
+
- Windows Explorer Host 端点只允许打开已注册的精确工作区根,拒绝盘符根、UNC、相对路径、子路径与无关绝对路径。
|
|
23
|
+
- 会话、权限和设置 DOM 兼容观察先过滤无关变更,再调度扫描,降低流式输出期间的额外工作。
|
|
24
|
+
|
|
25
|
+
### 发布流程
|
|
26
|
+
|
|
27
|
+
- 对齐根包、轻量安装器、私有旧 Suite 快照、成员钉版和版本契约断言;聚合 Suite 继续停止发布。
|
|
28
|
+
- 修正本地验证说明中的安装器路径、帮助与错误前缀,并增加客户端 bundle 静态运行时模块的构建契约。
|
|
29
|
+
- 将 `docs/00-交接入口/` 纳入版本控制并按当前实现更新,其他历史文档继续忽略。
|
|
30
|
+
- 拒绝 `DSH_BIN` 中的 Windows shell 元字符,收紧安装器调用边界。
|
|
31
|
+
|
|
32
|
+
## 0.2.88 — 2026-08-26
|
|
33
|
+
|
|
34
|
+
配套版本:`@michengai/dsh-codex-suite-installer@0.1.5`。
|
|
35
|
+
|
|
36
|
+
### 调整
|
|
37
|
+
|
|
38
|
+
- 安装外部可选插件 `dsh-mcp-connector` 时,用其完整的市场与连接管理界面替换轻量的“设置 → 连接器”工具列表。
|
|
39
|
+
- 首页/侧边栏继续以“连接器”作为唯一入口,展开与收缩状态下均不再显示外部插件单独注入的启动入口。
|
|
40
|
+
- 未安装 `dsh-mcp-connector` 或其 Web UI 不可用时,自动回退到原有的当前会话 MCP 工具目录。
|
|
41
|
+
|
|
42
|
+
### 兼容性
|
|
43
|
+
|
|
44
|
+
- 增加同源且校验消息来源的 Prompt 桥接,可创建或复用工作区会话,并把市场中的 Prompt 写入新会话草稿。
|
|
45
|
+
- 让内嵌市场跟随 DSH 当前选择的明暗主题;不修改外部插件,也不将其变为强制依赖。
|
|
46
|
+
- 轻量安装器同步固定 Codex UI `0.2.88`;旧聚合 Suite 继续保持私有且不发布。
|
|
47
|
+
|
|
48
|
+
发布包:[`@michengai/dsh-codex-ui@0.2.88`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.88) 与 [`@michengai/dsh-codex-suite-installer@0.1.5`](https://www.npmjs.com/package/@michengai/dsh-codex-suite-installer/v/0.1.5)。
|
|
49
|
+
|
|
7
50
|
## 0.2.87 — 2026-08-26
|
|
8
51
|
|
|
9
52
|
配套版本:`@michengai/dsh-codex-suite-installer@0.1.4`。
|
package/dist/client.js
CHANGED
|
@@ -19,7 +19,8 @@ window.__ModuleLoader__.load({
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
let cancelPendingNavigation;
|
|
22
|
-
|
|
22
|
+
const SETTINGS_NAVIGATION_TIMEOUT_MS = 4e3;
|
|
23
|
+
function openSettingsSection(root, label, onMissing, onSelected) {
|
|
23
24
|
const labels = typeof label === "string" ? [label] : label;
|
|
24
25
|
const trigger = root?.querySelector("[aria-haspopup=\"dialog\"]");
|
|
25
26
|
if (trigger === null || trigger === void 0) {
|
|
@@ -47,6 +48,7 @@ window.__ModuleLoader__.load({
|
|
|
47
48
|
if (target === void 0) return false;
|
|
48
49
|
cleanup();
|
|
49
50
|
target.click();
|
|
51
|
+
onSelected?.();
|
|
50
52
|
return true;
|
|
51
53
|
};
|
|
52
54
|
const schedule = () => {
|
|
@@ -61,7 +63,7 @@ window.__ModuleLoader__.load({
|
|
|
61
63
|
cleanup();
|
|
62
64
|
console.warn(`[michengai-codex-ui] 未找到设置分区:${labels.join(" / ")}`);
|
|
63
65
|
onMissing?.();
|
|
64
|
-
},
|
|
66
|
+
}, SETTINGS_NAVIGATION_TIMEOUT_MS);
|
|
65
67
|
observer.observe(document.body, {
|
|
66
68
|
childList: true,
|
|
67
69
|
subtree: true
|
|
@@ -564,26 +566,33 @@ window.__ModuleLoader__.load({
|
|
|
564
566
|
]
|
|
565
567
|
});
|
|
566
568
|
}
|
|
567
|
-
function GroupHead({ expanded, title, icon, onToggle }) {
|
|
569
|
+
function GroupHead({ expanded, title, icon, onToggle, actions, menuOpen }) {
|
|
568
570
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
569
|
-
className:
|
|
571
|
+
className: `dcu-wb-project-head${menuOpen === true ? " dcu-wb-menu-open" : ""}`,
|
|
570
572
|
role: "treeitem",
|
|
571
573
|
"aria-expanded": expanded,
|
|
572
574
|
tabIndex: 0,
|
|
573
575
|
onClick: onToggle,
|
|
574
576
|
onKeyDown: (event) => {
|
|
575
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
577
|
+
if (event.target === event.currentTarget && (event.key === "Enter" || event.key === " ")) {
|
|
576
578
|
event.preventDefault();
|
|
577
579
|
onToggle();
|
|
578
580
|
}
|
|
579
581
|
},
|
|
580
|
-
children: [
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
582
|
+
children: [
|
|
583
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
584
|
+
className: "dcu-wb-folder",
|
|
585
|
+
children: icon
|
|
586
|
+
}),
|
|
587
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
588
|
+
className: "dcu-wb-project-title",
|
|
589
|
+
children: title
|
|
590
|
+
}),
|
|
591
|
+
actions !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
592
|
+
className: "dcu-wb-actions",
|
|
593
|
+
children: actions
|
|
594
|
+
})
|
|
595
|
+
]
|
|
587
596
|
});
|
|
588
597
|
}
|
|
589
598
|
//#endregion
|
|
@@ -931,9 +940,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
931
940
|
style.textContent = CONVERSATION_HEADER_STYLE;
|
|
932
941
|
doc.head.append(style);
|
|
933
942
|
}
|
|
934
|
-
|
|
943
|
+
const CONVERSATION_DECORATION_SELECTOR = "header, [data-conversation-scroll], [data-chat-flow-kind=\"user\"], [data-pending-steering]";
|
|
944
|
+
function conversationDecorationMutation(records) {
|
|
945
|
+
const relevant = (node) => node instanceof Element && (node.matches(CONVERSATION_DECORATION_SELECTOR) || node.closest("header, [data-chat-flow-kind=\"user\"], [data-pending-steering]") !== null || node.querySelector(CONVERSATION_DECORATION_SELECTOR) !== null);
|
|
946
|
+
return records.some((record) => relevant(record.target) || [...record.addedNodes].some(relevant) || [...record.removedNodes].some(relevant));
|
|
947
|
+
}
|
|
948
|
+
/** 观察会话顶栏与用户气泡;只对相关子树变更按帧合并,流式回答不会触发全文档扫描。 */
|
|
935
949
|
function observeConversationHeader(doc = document) {
|
|
936
|
-
if (doc.head === null) return () => {};
|
|
950
|
+
if (doc.head === null || doc.body === null) return () => {};
|
|
937
951
|
ensureStyle(doc);
|
|
938
952
|
ensureUserBubbleStyle(doc);
|
|
939
953
|
let applying = false;
|
|
@@ -965,8 +979,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
965
979
|
frame = window.requestAnimationFrame(run);
|
|
966
980
|
};
|
|
967
981
|
sync();
|
|
968
|
-
const observer = new MutationObserver(
|
|
969
|
-
|
|
982
|
+
const observer = new MutationObserver((records) => {
|
|
983
|
+
if (conversationDecorationMutation(records)) sync();
|
|
984
|
+
});
|
|
985
|
+
observer.observe(doc.body, {
|
|
970
986
|
childList: true,
|
|
971
987
|
subtree: true
|
|
972
988
|
});
|
|
@@ -1163,9 +1179,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1163
1179
|
]
|
|
1164
1180
|
});
|
|
1165
1181
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1182
|
+
//#endregion
|
|
1183
|
+
//#region src/client/schedule-sessions.ts
|
|
1184
|
+
const AUTOMATION_SESSION_PREFIX = "dsh-automation-session-";
|
|
1185
|
+
function isScheduleSession(id, _title) {
|
|
1186
|
+
return id.startsWith(AUTOMATION_SESSION_PREFIX);
|
|
1169
1187
|
}
|
|
1170
1188
|
function scheduleGroupName(title) {
|
|
1171
1189
|
const name = /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2})\s*-\s*(.+)$/.exec(title.trim())?.[2]?.trim();
|
|
@@ -1188,6 +1206,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1188
1206
|
return [...groups.values()].map((group) => ({
|
|
1189
1207
|
...group,
|
|
1190
1208
|
sessions: [...group.sessions].sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))
|
|
1209
|
+
})).sort((left, right) => left.label.localeCompare(right.label, "zh-CN", {
|
|
1210
|
+
numeric: true,
|
|
1211
|
+
sensitivity: "base"
|
|
1191
1212
|
}));
|
|
1192
1213
|
}
|
|
1193
1214
|
//#endregion
|
|
@@ -1297,6 +1318,40 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1297
1318
|
return fallback !== void 0 && fallback.trim() !== "" ? fallback : void 0;
|
|
1298
1319
|
}
|
|
1299
1320
|
//#endregion
|
|
1321
|
+
//#region src/client/tree-expansion.ts
|
|
1322
|
+
const WORKSPACE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.workspace-expansion.v1";
|
|
1323
|
+
const CHANNEL_EXPANSION_STORAGE_KEY = "dsh-codex-ui.channel-expansion.v1";
|
|
1324
|
+
const SCHEDULE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.schedule-expansion.v1";
|
|
1325
|
+
const MAX_EXPANSION_ENTRIES = 500;
|
|
1326
|
+
const MAX_EXPANSION_KEY_LENGTH = 512;
|
|
1327
|
+
function browserStorage() {
|
|
1328
|
+
if (typeof window === "undefined") return void 0;
|
|
1329
|
+
try {
|
|
1330
|
+
return window.localStorage;
|
|
1331
|
+
} catch {
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
function parseTreeExpansionState(value) {
|
|
1336
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
|
|
1337
|
+
const entries = Object.entries(value).filter(([key, expanded]) => key.length > 0 && key.length <= MAX_EXPANSION_KEY_LENGTH && typeof expanded === "boolean").slice(0, MAX_EXPANSION_ENTRIES);
|
|
1338
|
+
return Object.fromEntries(entries);
|
|
1339
|
+
}
|
|
1340
|
+
function readTreeExpansionState(storage, key) {
|
|
1341
|
+
if (storage === void 0) return {};
|
|
1342
|
+
try {
|
|
1343
|
+
return parseTreeExpansionState(JSON.parse(storage.getItem(key) ?? "{}"));
|
|
1344
|
+
} catch {
|
|
1345
|
+
return {};
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
function writeTreeExpansionState(storage, key, state) {
|
|
1349
|
+
if (storage === void 0) return;
|
|
1350
|
+
try {
|
|
1351
|
+
storage.setItem(key, JSON.stringify(parseTreeExpansionState(state)));
|
|
1352
|
+
} catch {}
|
|
1353
|
+
}
|
|
1354
|
+
//#endregion
|
|
1300
1355
|
//#region src/client/CodexWorkspaceBrowser.tsx
|
|
1301
1356
|
const stylesheet$4 = `
|
|
1302
1357
|
.dcu-wb{--dcu-wb-inset:4px;display:flex;flex:1;min-height:0;flex-direction:column;padding:4px var(--dcu-wb-inset) 8px;color:var(--dcu-sidebar-primary)}
|
|
@@ -1342,12 +1397,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1342
1397
|
const typographyStyles = `.dcu-wb{font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-tertiary);font-size:13px;font-weight:400;letter-spacing:.02em}.dcu-wb-project-title{font-size:14px;line-height:20px;font-weight:400;color:var(--dcu-sidebar-primary)}.dcu-wb-session-title{font-size:14px;line-height:20px;font-weight:400;color:var(--dcu-sidebar-secondary)}.dcu-wb-session.dcu-wb-selected .dcu-wb-session-title,.dcu-wb-session:hover .dcu-wb-session-title{color:var(--dcu-sidebar-primary)}.dcu-wb-empty{color:var(--dcu-sidebar-tertiary);font-size:13px;line-height:18px}.dcu-wb-nochat{padding:0 8px 4px 28px;color:var(--dcu-sidebar-tertiary);font-size:14px;line-height:20px}`;
|
|
1343
1398
|
const WORKSPACE_TREE_STYLE = stylesheet$4 + runningStyles + typographyStyles;
|
|
1344
1399
|
function storage$1() {
|
|
1345
|
-
|
|
1346
|
-
try {
|
|
1347
|
-
return window.localStorage;
|
|
1348
|
-
} catch {
|
|
1349
|
-
return;
|
|
1350
|
-
}
|
|
1400
|
+
return browserStorage();
|
|
1351
1401
|
}
|
|
1352
1402
|
function sameIds(left, right) {
|
|
1353
1403
|
return left.length === right.length && left.every((id, index) => id === right[index]);
|
|
@@ -1367,7 +1417,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1367
1417
|
function CodexWorkspaceTree({ wide, useSessions, useWorkspaces, t, archiveSession, deleteSession, deleteWorkspace, forkSession, insertSessionBefore, insertWorkspaceBefore, openPath, openSession, renameSession, renameWorkspace, startSession }) {
|
|
1368
1418
|
const sessions = useSessions((state) => state);
|
|
1369
1419
|
const workspaces = useWorkspaces((state) => state);
|
|
1370
|
-
const [expanded, setExpanded] = (0, react.useState)(
|
|
1420
|
+
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY));
|
|
1371
1421
|
const [pinnedWorkspaceIds, setPinnedWorkspaceIdsState] = (0, react.useState)(() => readPinnedWorkspaceIds(storage$1()));
|
|
1372
1422
|
const pinnedWorkspaceIdsRef = (0, react.useRef)(pinnedWorkspaceIds);
|
|
1373
1423
|
pinnedWorkspaceIdsRef.current = pinnedWorkspaceIds;
|
|
@@ -1422,6 +1472,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1422
1472
|
const headerMenuPointerAt = (0, react.useRef)(0);
|
|
1423
1473
|
const [sessionDrag, setSessionDrag] = (0, react.useState)();
|
|
1424
1474
|
const [sessionDropTarget, setSessionDropTarget] = (0, react.useState)();
|
|
1475
|
+
(0, react.useEffect)(() => {
|
|
1476
|
+
writeTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY, expanded);
|
|
1477
|
+
}, [expanded]);
|
|
1425
1478
|
(0, react.useEffect)(() => {
|
|
1426
1479
|
savePinnedWorkspaceIds(storage$1(), pinnedWorkspaceIds);
|
|
1427
1480
|
if (!pinnedHostHydratedRef.current) return;
|
|
@@ -2545,7 +2598,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2545
2598
|
//#endregion
|
|
2546
2599
|
//#region src/client/session-row-actions.tsx
|
|
2547
2600
|
function storage() {
|
|
2548
|
-
return
|
|
2601
|
+
return browserStorage();
|
|
2549
2602
|
}
|
|
2550
2603
|
/** 频道/定时共用的本地置顶与未读标记。 */
|
|
2551
2604
|
function useSessionFlags(current) {
|
|
@@ -2796,7 +2849,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2796
2849
|
const sessions = useSessions((state) => state);
|
|
2797
2850
|
const [groups, setGroups] = (0, react.useState)([]);
|
|
2798
2851
|
const [pollError, setPollError] = (0, react.useState)();
|
|
2799
|
-
const [expanded, setExpanded] = (0, react.useState)(
|
|
2852
|
+
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), CHANNEL_EXPANSION_STORAGE_KEY));
|
|
2800
2853
|
const flags = useSessionFlags(sessions.current);
|
|
2801
2854
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
2802
2855
|
const { busy, error, setError, run } = useBusyAction(() => {
|
|
@@ -2811,6 +2864,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2811
2864
|
setMenu(void 0);
|
|
2812
2865
|
setError(void 0);
|
|
2813
2866
|
});
|
|
2867
|
+
(0, react.useEffect)(() => {
|
|
2868
|
+
writeTreeExpansionState(browserStorage(), CHANNEL_EXPANSION_STORAGE_KEY, expanded);
|
|
2869
|
+
}, [expanded]);
|
|
2814
2870
|
(0, react.useEffect)(() => {
|
|
2815
2871
|
let disposed = false;
|
|
2816
2872
|
let active;
|
|
@@ -2960,6 +3016,23 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2960
3016
|
});
|
|
2961
3017
|
}
|
|
2962
3018
|
//#endregion
|
|
3019
|
+
//#region src/client/schedule-group-actions.ts
|
|
3020
|
+
/** 尝试归档整组并保留逐项结果,避免首个失败让后续会话永远不执行。 */
|
|
3021
|
+
async function archiveScheduleGroup(sessionIds, archiveSession) {
|
|
3022
|
+
const archivedIds = [];
|
|
3023
|
+
const failedIds = [];
|
|
3024
|
+
for (const sessionId of sessionIds) try {
|
|
3025
|
+
await archiveSession(sessionId);
|
|
3026
|
+
archivedIds.push(sessionId);
|
|
3027
|
+
} catch {
|
|
3028
|
+
failedIds.push(sessionId);
|
|
3029
|
+
}
|
|
3030
|
+
return {
|
|
3031
|
+
archivedIds,
|
|
3032
|
+
failedIds
|
|
3033
|
+
};
|
|
3034
|
+
}
|
|
3035
|
+
//#endregion
|
|
2963
3036
|
//#region src/client/ScheduleBrowser.tsx
|
|
2964
3037
|
function ScheduleClock() {
|
|
2965
3038
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
@@ -2979,7 +3052,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2979
3052
|
/** 定时树:数据来自会话快照,行/菜单/悬停与任务树共用。 */
|
|
2980
3053
|
function ScheduleBrowser(props) {
|
|
2981
3054
|
const [menu, setMenu] = (0, react.useState)();
|
|
2982
|
-
|
|
3055
|
+
const [view, setView] = (0, react.useState)("runs");
|
|
3056
|
+
if (props.overviewContent === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverShell, {
|
|
2983
3057
|
blocked: menu !== void 0,
|
|
2984
3058
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleBrowserTree, {
|
|
2985
3059
|
...props,
|
|
@@ -2987,11 +3061,50 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2987
3061
|
setMenu
|
|
2988
3062
|
})
|
|
2989
3063
|
});
|
|
3064
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3065
|
+
className: "dcu-schedule-browser",
|
|
3066
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3067
|
+
className: "dcu-schedule-views",
|
|
3068
|
+
role: "tablist",
|
|
3069
|
+
"aria-label": props.t("sidebar.scheduleTab"),
|
|
3070
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3071
|
+
type: "button",
|
|
3072
|
+
role: "tab",
|
|
3073
|
+
"aria-selected": view === "runs",
|
|
3074
|
+
onClick: () => {
|
|
3075
|
+
setMenu(void 0);
|
|
3076
|
+
setView("runs");
|
|
3077
|
+
},
|
|
3078
|
+
children: props.t("sidebar.runsTab")
|
|
3079
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3080
|
+
type: "button",
|
|
3081
|
+
role: "tab",
|
|
3082
|
+
"aria-selected": view === "overview",
|
|
3083
|
+
onClick: () => {
|
|
3084
|
+
setMenu(void 0);
|
|
3085
|
+
setView("overview");
|
|
3086
|
+
},
|
|
3087
|
+
children: props.t("sidebar.overviewTab")
|
|
3088
|
+
})]
|
|
3089
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3090
|
+
className: "dcu-schedule-pane",
|
|
3091
|
+
children: view === "runs" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverShell, {
|
|
3092
|
+
blocked: menu !== void 0,
|
|
3093
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleBrowserTree, {
|
|
3094
|
+
...props,
|
|
3095
|
+
menu,
|
|
3096
|
+
setMenu
|
|
3097
|
+
})
|
|
3098
|
+
}) : props.overviewContent
|
|
3099
|
+
})]
|
|
3100
|
+
});
|
|
2990
3101
|
}
|
|
2991
|
-
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, useWorkspaces, t, menu, setMenu }) {
|
|
3102
|
+
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, useWorkspaces, t, openTaskSettings, menu, setMenu }) {
|
|
2992
3103
|
const sessions = useSessions((state) => state);
|
|
2993
3104
|
const workspaces = useWorkspaces((state) => state);
|
|
2994
|
-
const [expanded, setExpanded] = (0, react.useState)(
|
|
3105
|
+
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), SCHEDULE_EXPANSION_STORAGE_KEY));
|
|
3106
|
+
const [groupMenu, setGroupMenu] = (0, react.useState)();
|
|
3107
|
+
const [archiveGroupTarget, setArchiveGroupTarget] = (0, react.useState)();
|
|
2995
3108
|
const flags = useSessionFlags(sessions.current);
|
|
2996
3109
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
2997
3110
|
const { busy, error, setError, run } = useBusyAction(() => {
|
|
@@ -3006,6 +3119,26 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3006
3119
|
setMenu(void 0);
|
|
3007
3120
|
setError(void 0);
|
|
3008
3121
|
});
|
|
3122
|
+
const groupMenuItems = [
|
|
3123
|
+
{
|
|
3124
|
+
id: "task-settings",
|
|
3125
|
+
label: t("schedule.taskSettings"),
|
|
3126
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 })
|
|
3127
|
+
},
|
|
3128
|
+
{
|
|
3129
|
+
type: "separator",
|
|
3130
|
+
id: "group-separator"
|
|
3131
|
+
},
|
|
3132
|
+
{
|
|
3133
|
+
id: "archive-group",
|
|
3134
|
+
label: t("schedule.archiveGroup"),
|
|
3135
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 }),
|
|
3136
|
+
danger: true
|
|
3137
|
+
}
|
|
3138
|
+
];
|
|
3139
|
+
(0, react.useEffect)(() => {
|
|
3140
|
+
writeTreeExpansionState(browserStorage(), SCHEDULE_EXPANSION_STORAGE_KEY, expanded);
|
|
3141
|
+
}, [expanded]);
|
|
3009
3142
|
const groups = (0, react.useMemo)(() => {
|
|
3010
3143
|
const archived = new Set(workspaces.archivedSessionIds ?? []);
|
|
3011
3144
|
return groupScheduleSessions((sessions.ids ?? Object.keys(sessions.byId)).flatMap((id) => {
|
|
@@ -3049,12 +3182,52 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3049
3182
|
expanded: isExpanded,
|
|
3050
3183
|
title: group.label,
|
|
3051
3184
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleClock, {}),
|
|
3185
|
+
menuOpen: groupMenu === group.id,
|
|
3052
3186
|
onToggle: () => {
|
|
3053
3187
|
setExpanded((current) => ({
|
|
3054
3188
|
...current,
|
|
3055
3189
|
[group.id]: !isExpanded
|
|
3056
3190
|
}));
|
|
3057
|
-
}
|
|
3191
|
+
},
|
|
3192
|
+
actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
3193
|
+
open: groupMenu === group.id,
|
|
3194
|
+
onClose: () => {
|
|
3195
|
+
setGroupMenu(void 0);
|
|
3196
|
+
},
|
|
3197
|
+
items: groupMenuItems,
|
|
3198
|
+
onSelect: (action) => {
|
|
3199
|
+
setGroupMenu(void 0);
|
|
3200
|
+
if (action === "task-settings") {
|
|
3201
|
+
setMenu(void 0);
|
|
3202
|
+
openTaskSettings?.({
|
|
3203
|
+
name: group.label,
|
|
3204
|
+
sessionIds: group.sessions.map((session) => session.id)
|
|
3205
|
+
});
|
|
3206
|
+
}
|
|
3207
|
+
if (action === "archive-group") {
|
|
3208
|
+
setError(void 0);
|
|
3209
|
+
setArchiveGroupTarget({
|
|
3210
|
+
id: group.id,
|
|
3211
|
+
label: group.label,
|
|
3212
|
+
sessionIds: group.sessions.map((session) => session.id)
|
|
3213
|
+
});
|
|
3214
|
+
}
|
|
3215
|
+
},
|
|
3216
|
+
portal: true,
|
|
3217
|
+
dense: true,
|
|
3218
|
+
compact: true,
|
|
3219
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3220
|
+
type: "button",
|
|
3221
|
+
className: "dcu-wb-more",
|
|
3222
|
+
"aria-label": t("schedule.groupActions", { name: group.label }),
|
|
3223
|
+
onClick: (event) => {
|
|
3224
|
+
event.stopPropagation();
|
|
3225
|
+
setMenu(void 0);
|
|
3226
|
+
setGroupMenu((current) => current === group.id ? void 0 : group.id);
|
|
3227
|
+
},
|
|
3228
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
3229
|
+
})
|
|
3230
|
+
})
|
|
3058
3231
|
}), isExpanded && group.sessions.map((session) => {
|
|
3059
3232
|
const id = session.id;
|
|
3060
3233
|
const title = session.title;
|
|
@@ -3127,6 +3300,73 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3127
3300
|
error,
|
|
3128
3301
|
...dialogs,
|
|
3129
3302
|
setError
|
|
3303
|
+
}),
|
|
3304
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3305
|
+
open: archiveGroupTarget !== void 0,
|
|
3306
|
+
onClose: () => {
|
|
3307
|
+
if (busy !== "archive-group") {
|
|
3308
|
+
setArchiveGroupTarget(void 0);
|
|
3309
|
+
setError(void 0);
|
|
3310
|
+
}
|
|
3311
|
+
},
|
|
3312
|
+
closeLabel: t("sessions.close"),
|
|
3313
|
+
title: t("schedule.archiveGroup"),
|
|
3314
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3315
|
+
className: "dcu-wb-rename-actions",
|
|
3316
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3317
|
+
variant: "outline",
|
|
3318
|
+
disabled: busy === "archive-group",
|
|
3319
|
+
onClick: () => {
|
|
3320
|
+
setArchiveGroupTarget(void 0);
|
|
3321
|
+
setError(void 0);
|
|
3322
|
+
},
|
|
3323
|
+
children: t("sessions.cancel")
|
|
3324
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3325
|
+
variant: "outline",
|
|
3326
|
+
className: "dcu-wb-delete-button",
|
|
3327
|
+
disabled: busy === "archive-group",
|
|
3328
|
+
onClick: () => {
|
|
3329
|
+
if (archiveGroupTarget === void 0) return;
|
|
3330
|
+
const target = archiveGroupTarget;
|
|
3331
|
+
run("archive-group", async () => {
|
|
3332
|
+
const result = await archiveScheduleGroup(target.sessionIds, (id) => archiveSession(id));
|
|
3333
|
+
flags.setPinnedSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3334
|
+
flags.setUnreadSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3335
|
+
if (result.failedIds.length > 0) {
|
|
3336
|
+
setArchiveGroupTarget({
|
|
3337
|
+
...target,
|
|
3338
|
+
sessionIds: result.failedIds
|
|
3339
|
+
});
|
|
3340
|
+
throw new Error(t("schedule.archiveGroupPartial", {
|
|
3341
|
+
archived: result.archivedIds.length,
|
|
3342
|
+
failed: result.failedIds.length
|
|
3343
|
+
}));
|
|
3344
|
+
}
|
|
3345
|
+
setArchiveGroupTarget(void 0);
|
|
3346
|
+
});
|
|
3347
|
+
},
|
|
3348
|
+
children: t("schedule.archiveGroupConfirm")
|
|
3349
|
+
})]
|
|
3350
|
+
}),
|
|
3351
|
+
children: [
|
|
3352
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3353
|
+
className: "dcu-wb-delete-copy",
|
|
3354
|
+
children: archiveGroupTarget === void 0 ? "" : t("schedule.archiveGroupDescription", {
|
|
3355
|
+
name: archiveGroupTarget.label,
|
|
3356
|
+
count: archiveGroupTarget.sessionIds.length
|
|
3357
|
+
})
|
|
3358
|
+
}),
|
|
3359
|
+
busy === "archive-group" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3360
|
+
className: "dcu-wb-error",
|
|
3361
|
+
role: "status",
|
|
3362
|
+
children: t("schedule.archiveGroupPending")
|
|
3363
|
+
}),
|
|
3364
|
+
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3365
|
+
className: "dcu-wb-error",
|
|
3366
|
+
role: "alert",
|
|
3367
|
+
children: t("sessions.failed", { message: error })
|
|
3368
|
+
})
|
|
3369
|
+
]
|
|
3130
3370
|
})
|
|
3131
3371
|
]
|
|
3132
3372
|
});
|
|
@@ -3229,20 +3469,52 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3229
3469
|
};
|
|
3230
3470
|
}
|
|
3231
3471
|
//#endregion
|
|
3472
|
+
//#region src/client/automation-task-settings.ts
|
|
3473
|
+
const AUTOMATION_TASK_SETTINGS_EVENT = "dsh-automation:open-task-settings";
|
|
3474
|
+
const AUTOMATION_TASK_SETTINGS_STORAGE_KEY = "dsh-automation:pending-task-settings";
|
|
3475
|
+
function parseAutomationTaskSettingsRequest(value) {
|
|
3476
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
3477
|
+
const record = value;
|
|
3478
|
+
if (typeof record.name !== "string" || record.name.trim() === "" || !Array.isArray(record.sessionIds) || record.sessionIds.some((id) => typeof id !== "string" || id === "")) return void 0;
|
|
3479
|
+
if (record.automationId !== void 0 && (typeof record.automationId !== "string" || record.automationId.trim() === "")) return void 0;
|
|
3480
|
+
return {
|
|
3481
|
+
...typeof record.automationId === "string" ? { automationId: record.automationId } : {},
|
|
3482
|
+
name: record.name,
|
|
3483
|
+
sessionIds: [...record.sessionIds]
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3486
|
+
/** 定时设置页可能切换分区后才挂载:先保存一次性请求,再通知已挂载实例。 */
|
|
3487
|
+
function requestAutomationTaskSettings(request) {
|
|
3488
|
+
if (typeof window === "undefined") return;
|
|
3489
|
+
const validated = parseAutomationTaskSettingsRequest(request);
|
|
3490
|
+
if (validated === void 0) return;
|
|
3491
|
+
try {
|
|
3492
|
+
window.sessionStorage.setItem(AUTOMATION_TASK_SETTINGS_STORAGE_KEY, JSON.stringify(validated));
|
|
3493
|
+
} catch {}
|
|
3494
|
+
window.dispatchEvent(new CustomEvent(AUTOMATION_TASK_SETTINGS_EVENT, { detail: validated }));
|
|
3495
|
+
}
|
|
3496
|
+
function clearAutomationTaskSettingsRequest() {
|
|
3497
|
+
if (typeof window === "undefined") return;
|
|
3498
|
+
try {
|
|
3499
|
+
window.sessionStorage.removeItem(AUTOMATION_TASK_SETTINGS_STORAGE_KEY);
|
|
3500
|
+
} catch {}
|
|
3501
|
+
}
|
|
3502
|
+
//#endregion
|
|
3232
3503
|
//#region src/client/CodexSidebar.tsx
|
|
3233
3504
|
const subscribeEmptyCompanionTabs = () => () => {};
|
|
3234
3505
|
const getEmptyCompanionTabs = () => EMPTY_COMPANION_TABS;
|
|
3235
3506
|
const SIDEBAR_COLLAPSE_SETTLE_MS = 140;
|
|
3236
3507
|
const stylesheet$3 = `
|
|
3237
3508
|
.dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-wide-width:240px;--dcu-sidebar-primary:#393d3e;--dcu-sidebar-secondary:#676b6c;--dcu-sidebar-tertiary:#9a9f9f;--dcu-sidebar-navigation:#4e5253;--dcu-sidebar-icon:#4e5253;--dcu-sidebar-hover:#dfe8e5;--dcu-sidebar-border:rgba(37,46,41,.10);--dcu-tip-bg:#ffffff;--dcu-tip-shadow:0 10px 32px rgba(31,39,36,.22);height:100%;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden;background:#eef7f5;color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font)}body[data-ds-dark-theme] .dcu-root{background:#1d2120;--dcu-sidebar-primary:#b9bab9;--dcu-sidebar-secondary:#909191;--dcu-sidebar-tertiary:#666867;--dcu-sidebar-navigation:#b9bab9;--dcu-sidebar-icon:#afafaf;--dcu-sidebar-hover:#303432;--dcu-sidebar-border:rgba(255,255,255,.08);--dcu-tip-bg:#2a2e2c;--dcu-tip-shadow:0 10px 30px rgba(0,0,0,.28)}
|
|
3238
|
-
.dcu-expanded-shell{display:flex;width:var(--dcu-sidebar-wide-width);min-height:0;flex:1 0
|
|
3509
|
+
.dcu-expanded-shell{display:flex;width:var(--dcu-sidebar-wide-width);min-height:0;flex:1 1 0;overflow:hidden;flex-direction:column;transform-origin:left center;transition:opacity 140ms ease-out,transform 180ms cubic-bezier(.16,1,.3,1);animation:dcu-sidebar-expanded-in 180ms cubic-bezier(.16,1,.3,1)}.dcu-compact-shell{display:none;width:56px}.dcu-root.dcu-collapsing .dcu-expanded-shell{opacity:0;transform:translateX(-6px);pointer-events:none}.dcu-root.dcu-compact .dcu-expanded-shell{display:none}.dcu-root.dcu-compact .dcu-compact-shell{display:flex;min-height:0;flex:1;flex-direction:column;align-items:center;animation:dcu-sidebar-compact-in 140ms ease-out}@keyframes dcu-sidebar-expanded-in{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}@keyframes dcu-sidebar-compact-in{from{opacity:0;transform:translateX(-4px)}to{opacity:1;transform:none}}
|
|
3239
3510
|
.dcu-root *{box-sizing:border-box}.dcu-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:8px;height:60px;padding:8px 8px 8px 12px}.dcu-brand{border:0;background:transparent;color:inherit;padding:0;display:flex;align-items:center;min-width:0;overflow:hidden}.dcu-brand svg{display:block;width:auto;max-width:100%;height:24px;min-width:0}.dcu-head-actions{display:grid;grid-auto-flow:column;grid-auto-columns:28px;align-items:center;column-gap:8px;height:28px}
|
|
3240
3511
|
.dcu-icon,.dcu-menu button,.dcu-footer-link{appearance:none;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.dcu-icon{display:grid;place-items:center;width:36px;height:36px;border-radius:8px;color:var(--dcu-sidebar-icon)}.dcu-head .dcu-icon{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;margin:0;padding:0;border-radius:50%;line-height:0}.dcu-head .dcu-icon svg{display:block;width:16px;height:16px}
|
|
3241
3512
|
.dcu-icon:hover,.dcu-menu button:hover:not(:disabled),.dcu-footer-link:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}
|
|
3242
3513
|
.dcu-menu{padding:0 6px 8px;display:grid;gap:2px}.dcu-menu button,.dcu-footer-link{display:grid;grid-template-columns:20px minmax(0,1fr);column-gap:8px;align-items:center;width:100%;min-height:36px;padding:0 4px;border-radius:8px;color:var(--dcu-sidebar-navigation);font-size:14px;line-height:20px;text-align:left;font-weight:400}
|
|
3243
3514
|
.dcu-menu-icon{display:grid;place-items:center start;width:20px;height:20px}.dcu-menu-icon svg,.dcu-footer-link svg{display:block;width:16px;height:16px;color:var(--dcu-sidebar-icon)}.dcu-menu button:disabled{color:var(--dcu-sidebar-secondary);cursor:default;opacity:1}.dcu-menu button:disabled svg{color:var(--dcu-sidebar-secondary)}
|
|
3244
3515
|
.dcu-extension-items{display:grid;gap:1px;margin:1px 0 4px 28px}.dcu-extension-items button{min-height:32px;color:var(--dcu-sidebar-secondary);font-size:13px;font-weight:400}
|
|
3245
|
-
.dcu-workspaces{display:flex;min-height:0;flex:1;flex-direction:column;margin-top:2px;padding-top:8px;border-top:1px solid var(--dcu-sidebar-border)}.dcu-workspaces.dcu-workspaces-tabs{padding-top:0;border-top:0}.dcu-im-tabs{display:flex;gap:16px;margin:0 8px 12px;padding:0;border-bottom:1px solid var(--dcu-sidebar-border)}.dcu-im-tab{appearance:none;border:0;background:transparent;color:var(--dcu-sidebar-secondary);padding:8px 0 7px;font:14px/22px var(--dcu-font);font-weight:500;cursor:pointer}.dcu-im-tab[data-on=true]{color:var(--dcu-sidebar-primary);font-weight:600;box-shadow:inset 0 -2px 0 currentColor}.dcu-native-workspaces{display:flex;min-height:0;flex:1}.dcu-native-workspaces>*{min-width:0;flex:1}.dcu-native-workspaces .ima-tabs,.dcu-native-workspaces [role=tablist]{display:none!important}.dcu-foot{display:grid;width:var(--dcu-sidebar-wide-width);gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border);transition:opacity 120ms ease-out,transform 160ms cubic-bezier(.16,1,.3,1)}.dcu-root.dcu-collapsing>.dcu-foot{opacity:0;transform:translateX(-4px);pointer-events:none}.dcu-footer-actions:empty,.dcu-settings-seat:empty{display:none}.dcu-settings-seat>button{width:100%;min-height:36px;padding-left:4px!important;color:var(--dcu-sidebar-navigation);font:14px/20px var(--dcu-font);font-weight:400}.dcu-compact{width:100%;align-items:flex-start;overflow:hidden;padding:10px 0 8px}.dcu-compact-nav{display:flex;flex:1;min-height:0;flex-direction:column;align-items:center;gap:2px;overflow:auto;padding:6px 0}.dcu-compact .dcu-icon{width:36px;height:36px;flex:none}.dcu-compact .dcu-foot{width:36px;margin-top:auto;margin-left:10px;padding:8px 0;border-top:0}.dcu-compact .dcu-settings-seat{width:36px;overflow:hidden}.dcu-compact .dcu-settings-seat>button{display:grid;place-items:center;width:36px;min-height:36px;padding:0!important;font-size:0!important;line-height:0}.dcu-compact .dcu-settings-seat>button svg{width:16px;height:16px}.dcu-compact .dcu-footer-link{display:flex;justify-content:center;width:36px;padding:0;font-size:0}.dcu-compact .dcu-footer-link svg{width:16px;height:16px}
|
|
3516
|
+
.dcu-workspaces{display:flex;min-height:0;flex:1;flex-direction:column;margin-top:2px;padding-top:8px;border-top:1px solid var(--dcu-sidebar-border)}.dcu-workspaces.dcu-workspaces-tabs{padding-top:0;border-top:0}.dcu-im-tabs{display:flex;gap:16px;margin:0 8px 12px;padding:0;border-bottom:1px solid var(--dcu-sidebar-border)}.dcu-im-tab{appearance:none;border:0;background:transparent;color:var(--dcu-sidebar-secondary);padding:8px 0 7px;font:14px/22px var(--dcu-font);font-weight:500;cursor:pointer}.dcu-im-tab[data-on=true]{color:var(--dcu-sidebar-primary);font-weight:600;box-shadow:inset 0 -2px 0 currentColor}.dcu-native-workspaces{display:flex;min-height:0;flex:1}.dcu-native-workspaces>*{min-width:0;flex:1}.dcu-native-workspaces .ima-tabs,.dcu-native-workspaces [role=tablist]{display:none!important}.dcu-schedule-browser{display:flex;min-height:0;flex:1;flex-direction:column}.dcu-native-workspaces .dcu-schedule-views{display:flex!important;flex:none;min-height:30px;margin:0 8px 8px;padding:2px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:rgba(255,255,255,.025)}.dcu-schedule-views button{appearance:none;flex:1;min-width:0;height:24px;border:0;border-radius:6px;background:transparent;color:var(--dcu-sidebar-secondary);font:600 12px/18px var(--dcu-font);cursor:pointer}.dcu-schedule-views button[aria-selected=true]{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary);box-shadow:inset 0 0 0 1px var(--dcu-sidebar-border)}.dcu-schedule-pane{display:flex;min-height:0;flex:1}.dcu-schedule-pane>*{min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]{display:flex!important;width:100%;min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]>.dsh-st-rail{width:100%;min-width:0;padding-right:8px;scrollbar-gutter:auto}.dcu-schedule-pane .dsh-st-overview{padding-right:8px}.dcu-foot{display:grid;width:var(--dcu-sidebar-wide-width);gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border);transition:opacity 120ms ease-out,transform 160ms cubic-bezier(.16,1,.3,1)}.dcu-root.dcu-collapsing>.dcu-foot{opacity:0;transform:translateX(-4px);pointer-events:none}.dcu-footer-actions:empty,.dcu-settings-seat:empty{display:none}.dcu-settings-seat>button{width:100%;min-height:36px;padding-left:4px!important;color:var(--dcu-sidebar-navigation);font:14px/20px var(--dcu-font);font-weight:400}.dcu-compact{width:100%;align-items:flex-start;overflow:hidden;padding:10px 0 8px}.dcu-compact-nav{display:flex;flex:1;min-height:0;flex-direction:column;align-items:center;gap:2px;overflow:auto;padding:6px 0}.dcu-compact .dcu-icon{width:36px;height:36px;flex:none}.dcu-compact .dcu-foot{width:36px;margin-top:auto;margin-left:10px;padding:8px 0;border-top:0}.dcu-compact .dcu-settings-seat{width:36px;overflow:hidden}.dcu-compact .dcu-settings-seat>button{display:grid;place-items:center;width:36px;min-height:36px;padding:0!important;font-size:0!important;line-height:0}.dcu-compact .dcu-settings-seat>button svg{width:16px;height:16px}.dcu-compact .dcu-footer-link{display:flex;justify-content:center;width:36px;padding:0;font-size:0}.dcu-compact .dcu-footer-link svg{width:16px;height:16px}
|
|
3517
|
+
.dcu-native-workspaces{flex-direction:column}.dcu-native-workspaces>[data-mcp-connector-top-mount=true]{flex:none}.dcu-root .mcpConnectorLauncher,.dcu-root [data-mcp-connector-top-mount=true]{display:none!important}
|
|
3246
3518
|
.dcu-dependency-notice{margin:0 10px 8px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;padding:8px;color:var(--dcu-sidebar-secondary);font-size:12px;line-height:18px}
|
|
3247
3519
|
[role="dialog"][aria-labelledby]{width:min(1000px,calc(100vw - 48px));max-width:calc(100vw - 48px);height:min(800px,calc(100vh - 48px))}
|
|
3248
3520
|
.dcu-search-scrim{position:fixed;z-index:10020;inset:0;display:flex;justify-content:center;align-items:flex-start;padding:72px 20px;background:color-mix(in srgb,#000 48%,transparent);animation:dcu-search-scrim-in 140ms ease-out}.dcu-search-dialog{width:min(560px,100%);max-height:min(640px,calc(100vh - 120px));overflow:auto;border:1px solid var(--dcu-sidebar-border);border-radius:16px;padding:10px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv4);animation:dcu-search-dialog-in 180ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-search-scrim-in{from{opacity:0}to{opacity:1}}@keyframes dcu-search-dialog-in{from{opacity:0;transform:translateY(-6px) scale(.985)}to{opacity:1;transform:none}}.dcu-search-input{margin-bottom:8px}.dcu-search-section{padding:6px 0}.dcu-search-title{padding:0 8px 4px;color:var(--dcu-sidebar-tertiary);font-size:12px;font-weight:600}.dcu-search-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;width:100%;min-height:34px;border:0;border-radius:8px;padding:6px 8px;background:transparent;color:var(--dcu-sidebar-primary);font:inherit;text-align:left;cursor:pointer}.dcu-search-row:hover,.dcu-search-row[data-active=true]{background:var(--dcu-sidebar-hover)}.dcu-search-main{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-search-detail{max-width:160px;overflow:hidden;color:var(--dcu-sidebar-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-search-empty{padding:18px 8px;color:var(--dcu-sidebar-tertiary);font-size:13px}@media (prefers-reduced-motion:reduce){.dcu-expanded-shell,.dcu-root.dcu-compact .dcu-compact-shell,.dcu-foot,.dcu-search-scrim,.dcu-search-dialog{animation:none;transition:none}}
|
|
@@ -3644,6 +3916,32 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3644
3916
|
wide: true,
|
|
3645
3917
|
expandSidebar
|
|
3646
3918
|
}), [expandSidebar, renderSlot]);
|
|
3919
|
+
const scheduleOverviewSlot = (0, react.useMemo)(() => renderSlot("sidebar.schedule", {
|
|
3920
|
+
wide: true,
|
|
3921
|
+
expandSidebar,
|
|
3922
|
+
openSession,
|
|
3923
|
+
archiveSession,
|
|
3924
|
+
deleteSession,
|
|
3925
|
+
forkSession,
|
|
3926
|
+
renameSession,
|
|
3927
|
+
openPath,
|
|
3928
|
+
useSessions,
|
|
3929
|
+
useWorkspaces,
|
|
3930
|
+
view: "overview",
|
|
3931
|
+
showViewSwitch: false
|
|
3932
|
+
}), [
|
|
3933
|
+
archiveSession,
|
|
3934
|
+
companionTabs.schedule,
|
|
3935
|
+
deleteSession,
|
|
3936
|
+
expandSidebar,
|
|
3937
|
+
forkSession,
|
|
3938
|
+
openPath,
|
|
3939
|
+
openSession,
|
|
3940
|
+
renameSession,
|
|
3941
|
+
renderSlot,
|
|
3942
|
+
useSessions,
|
|
3943
|
+
useWorkspaces
|
|
3944
|
+
]);
|
|
3647
3945
|
const sidebarStyle = { "--dcu-sidebar-wide-width": `${lastWideWidth.current}px` };
|
|
3648
3946
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
3649
3947
|
className: `dcu-root${visualCompact ? " dcu-compact" : ""}${collapsing ? " dcu-collapsing" : ""}`,
|
|
@@ -3805,7 +4103,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3805
4103
|
renameSession,
|
|
3806
4104
|
useSessions,
|
|
3807
4105
|
useWorkspaces,
|
|
3808
|
-
t
|
|
4106
|
+
t,
|
|
4107
|
+
overviewContent: scheduleOverviewSlot,
|
|
4108
|
+
openTaskSettings: (request) => {
|
|
4109
|
+
openSettingsSection(settingsSeat.current, t("sidebar.schedule"), () => {
|
|
4110
|
+
clearAutomationTaskSettingsRequest();
|
|
4111
|
+
selectSection(t("about.nav"));
|
|
4112
|
+
}, () => {
|
|
4113
|
+
requestAutomationTaskSettings(request);
|
|
4114
|
+
});
|
|
4115
|
+
}
|
|
3809
4116
|
})
|
|
3810
4117
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3811
4118
|
className: "dcu-native-workspaces",
|
|
@@ -4190,16 +4497,82 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4190
4497
|
}
|
|
4191
4498
|
//#endregion
|
|
4192
4499
|
//#region src/client/ConnectorsSection.tsx
|
|
4500
|
+
const MCP_CONNECTOR_UI = "/mcp-connector/ui/";
|
|
4501
|
+
const PROMPT_REQUEST_TYPE = "mcp-connector:start-session";
|
|
4502
|
+
const PROMPT_RESULT_TYPE = "mcp-connector:start-session-result";
|
|
4193
4503
|
const stylesheet$1 = `
|
|
4194
|
-
.dcu-connectors{color:var(--dsw-alias-label-primary)}.dcu-connectors h2{margin:0;font-size:18px}.dcu-connectors p{margin:6px 0 18px;color:var(--dsw-alias-label-secondary);font-size:12px}.dcu-connector-list{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:9px}.dcu-connector{padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-connector:last-child{border-bottom:0}.dcu-connector-head{display:flex;align-items:center;gap:8px;font-weight:650}.dcu-connector-meta{margin:3px 0 8px;color:var(--dsw-alias-label-tertiary);font-size:11px}.dcu-connector-tool{padding:5px 0 0 24px;color:var(--dsw-alias-label-secondary);font-size:12px}.dcu-connector-tool span{display:block;margin-top:1px;color:var(--dsw-alias-label-tertiary);font-size:11px}.dcu-connector-empty{padding:20px 8px;color:var(--dsw-alias-label-secondary);text-align:center}
|
|
4504
|
+
.dcu-connectors{color:var(--dsw-alias-label-primary)}.dcu-connectors h2{margin:0;font-size:18px}.dcu-connectors p{margin:6px 0 18px;color:var(--dsw-alias-label-secondary);font-size:12px}.dcu-connector-frame{display:block;width:100%;height:clamp(420px,calc(100vh - 160px),700px);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-base);color-scheme:light dark}.dcu-connector-list{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:9px}.dcu-connector{padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-connector:last-child{border-bottom:0}.dcu-connector-head{display:flex;align-items:center;gap:8px;font-weight:650}.dcu-connector-meta{margin:3px 0 8px;color:var(--dsw-alias-label-tertiary);font-size:11px}.dcu-connector-tool{padding:5px 0 0 24px;color:var(--dsw-alias-label-secondary);font-size:12px}.dcu-connector-tool span{display:block;margin-top:1px;color:var(--dsw-alias-label-tertiary);font-size:11px}.dcu-connector-empty{padding:20px 8px;color:var(--dsw-alias-label-secondary);text-align:center}
|
|
4195
4505
|
`;
|
|
4506
|
+
const frameLightTheme = `:root{color-scheme:light;--bg:#f8f9fb;--card:#fff;--line:#e5e7eb;--text:#111827;--text-2:#4b5563;--muted:#9ca3af;--accent:#4f46e5;--accent-hover:#4338ca;--accent-light:#eef2ff;--ok:#059669;--ok-bg:#ecfdf5;--warn:#d97706;--warn-bg:#fffbeb;--bad:#dc2626;--bad-bg:#fef2f2;--shadow:0 1px 3px rgba(0,0,0,.08),0 1px 2px rgba(0,0,0,.06);--shadow-lg:0 10px 25px rgba(0,0,0,.1)}`;
|
|
4507
|
+
const frameDarkTheme = `:root{color-scheme:dark;--bg:#111318;--card:#1b1e25;--line:#30343d;--text:#f3f4f6;--text-2:#c4c8d0;--muted:#8e96a3;--accent:#818cf8;--accent-hover:#6366f1;--accent-light:#252750;--ok:#34d399;--ok-bg:#0d3027;--warn:#fbbf24;--warn-bg:#35280b;--bad:#f87171;--bad-bg:#3b171b;--shadow:0 1px 3px rgba(0,0,0,.35);--shadow-lg:0 16px 35px rgba(0,0,0,.45)}`;
|
|
4196
4508
|
function isConnector(value) {
|
|
4197
4509
|
if (value === null || typeof value !== "object") return false;
|
|
4198
4510
|
const item = value;
|
|
4199
4511
|
return typeof item.name === "string" && Array.isArray(item.tools) && item.tools.every((tool) => tool !== null && typeof tool === "object" && typeof tool.name === "string" && typeof tool.description === "string");
|
|
4200
4512
|
}
|
|
4201
|
-
|
|
4202
|
-
|
|
4513
|
+
function isPromptRequest(value) {
|
|
4514
|
+
if (value === null || typeof value !== "object") return false;
|
|
4515
|
+
const item = value;
|
|
4516
|
+
return item.type === PROMPT_REQUEST_TYPE && typeof item.requestId === "string" && item.requestId !== "" && typeof item.prompt === "string" && item.prompt.trim() !== "";
|
|
4517
|
+
}
|
|
4518
|
+
function syncFrameTheme(frame) {
|
|
4519
|
+
const doc = frame?.contentDocument;
|
|
4520
|
+
if (doc === null || doc === void 0) return;
|
|
4521
|
+
let style = doc.head.querySelector("style[data-michengai-host-theme]");
|
|
4522
|
+
if (style === null) {
|
|
4523
|
+
style = doc.createElement("style");
|
|
4524
|
+
style.dataset.michengaiHostTheme = "true";
|
|
4525
|
+
doc.head.append(style);
|
|
4526
|
+
}
|
|
4527
|
+
style.textContent = document.body.hasAttribute("data-ds-dark-theme") ? frameDarkTheme : frameLightTheme;
|
|
4528
|
+
}
|
|
4529
|
+
function ConnectorMarket({ startPromptSession }) {
|
|
4530
|
+
const frameRef = (0, react.useRef)(null);
|
|
4531
|
+
(0, react.useEffect)(() => {
|
|
4532
|
+
const onMessage = (event) => {
|
|
4533
|
+
const frameWindow = frameRef.current?.contentWindow;
|
|
4534
|
+
if (event.origin !== window.location.origin || frameWindow === null || frameWindow === void 0 || event.source !== frameWindow) return;
|
|
4535
|
+
if (!isPromptRequest(event.data)) return;
|
|
4536
|
+
const { requestId, prompt } = event.data;
|
|
4537
|
+
const reply = (ok, message) => {
|
|
4538
|
+
frameWindow.postMessage({
|
|
4539
|
+
type: PROMPT_RESULT_TYPE,
|
|
4540
|
+
requestId,
|
|
4541
|
+
ok,
|
|
4542
|
+
message
|
|
4543
|
+
}, window.location.origin);
|
|
4544
|
+
};
|
|
4545
|
+
startPromptSession(prompt).then(() => {
|
|
4546
|
+
reply(true, "已带入新会话");
|
|
4547
|
+
}, (error) => {
|
|
4548
|
+
reply(false, error instanceof Error ? error.message : String(error));
|
|
4549
|
+
});
|
|
4550
|
+
};
|
|
4551
|
+
const syncTheme = () => {
|
|
4552
|
+
syncFrameTheme(frameRef.current);
|
|
4553
|
+
};
|
|
4554
|
+
const observer = new MutationObserver(syncTheme);
|
|
4555
|
+
observer.observe(document.body, {
|
|
4556
|
+
attributes: true,
|
|
4557
|
+
attributeFilter: ["data-ds-dark-theme"]
|
|
4558
|
+
});
|
|
4559
|
+
window.addEventListener("message", onMessage);
|
|
4560
|
+
return () => {
|
|
4561
|
+
observer.disconnect();
|
|
4562
|
+
window.removeEventListener("message", onMessage);
|
|
4563
|
+
};
|
|
4564
|
+
}, [startPromptSession]);
|
|
4565
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
4566
|
+
ref: frameRef,
|
|
4567
|
+
className: "dcu-connector-frame",
|
|
4568
|
+
src: MCP_CONNECTOR_UI,
|
|
4569
|
+
title: "MCP连接器",
|
|
4570
|
+
onLoad: () => {
|
|
4571
|
+
syncFrameTheme(frameRef.current);
|
|
4572
|
+
}
|
|
4573
|
+
});
|
|
4574
|
+
}
|
|
4575
|
+
function NativeConnectorList({ sessionStore, t }) {
|
|
4203
4576
|
const sessionId = (0, react.useSyncExternalStore)(sessionStore.subscribe, () => sessionStore.getSnapshot().current);
|
|
4204
4577
|
const [connectors, setConnectors] = (0, react.useState)([]);
|
|
4205
4578
|
const [state, setState] = (0, react.useState)("loading");
|
|
@@ -4225,46 +4598,74 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4225
4598
|
controller.abort();
|
|
4226
4599
|
};
|
|
4227
4600
|
}, [sessionId]);
|
|
4601
|
+
if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4602
|
+
className: "dcu-connector-empty",
|
|
4603
|
+
children: t("connectors.openSession")
|
|
4604
|
+
});
|
|
4605
|
+
if (state === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4606
|
+
className: "dcu-connector-empty",
|
|
4607
|
+
children: t("connectors.loading")
|
|
4608
|
+
});
|
|
4609
|
+
if (state === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4610
|
+
className: "dcu-connector-empty",
|
|
4611
|
+
children: t("connectors.failed")
|
|
4612
|
+
});
|
|
4613
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4614
|
+
className: "dcu-connector-list",
|
|
4615
|
+
children: [connectors.map((connector) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
4616
|
+
className: "dcu-connector",
|
|
4617
|
+
children: [
|
|
4618
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4619
|
+
className: "dcu-connector-head",
|
|
4620
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 }), connector.name]
|
|
4621
|
+
}),
|
|
4622
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4623
|
+
className: "dcu-connector-meta",
|
|
4624
|
+
children: t("connectors.toolCount", { count: connector.tools.length })
|
|
4625
|
+
}),
|
|
4626
|
+
connector.tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4627
|
+
className: "dcu-connector-tool",
|
|
4628
|
+
children: [tool.name, tool.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tool.description })]
|
|
4629
|
+
}, tool.name))
|
|
4630
|
+
]
|
|
4631
|
+
}, connector.name)), connectors.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4632
|
+
className: "dcu-connector-empty",
|
|
4633
|
+
children: t("connectors.empty")
|
|
4634
|
+
})]
|
|
4635
|
+
});
|
|
4636
|
+
}
|
|
4637
|
+
/** 安装 dsh-mcp-connector 时显示完整市场,否则回退到当前会话的 MCP 工具目录。 */
|
|
4638
|
+
function ConnectorsSection({ sessionStore, startPromptSession, t }) {
|
|
4639
|
+
const [marketAvailable, setMarketAvailable] = (0, react.useState)();
|
|
4640
|
+
(0, react.useEffect)(() => {
|
|
4641
|
+
const controller = new AbortController();
|
|
4642
|
+
fetch(MCP_CONNECTOR_UI, {
|
|
4643
|
+
method: "HEAD",
|
|
4644
|
+
cache: "no-store",
|
|
4645
|
+
signal: controller.signal
|
|
4646
|
+
}).then((response) => {
|
|
4647
|
+
if (!controller.signal.aborted) setMarketAvailable(response.ok);
|
|
4648
|
+
}).catch(() => {
|
|
4649
|
+
if (!controller.signal.aborted) setMarketAvailable(false);
|
|
4650
|
+
});
|
|
4651
|
+
return () => {
|
|
4652
|
+
controller.abort();
|
|
4653
|
+
};
|
|
4654
|
+
}, []);
|
|
4228
4655
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4229
4656
|
className: "dcu-connectors",
|
|
4230
4657
|
"aria-label": t("connectors.title"),
|
|
4231
|
-
children: [
|
|
4232
|
-
|
|
4658
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$1 }), marketAvailable === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4659
|
+
className: "dcu-connector-empty",
|
|
4660
|
+
children: t("connectors.loading")
|
|
4661
|
+
}) : marketAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorMarket, { startPromptSession }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4233
4662
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("connectors.title") }),
|
|
4234
4663
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("connectors.description") }),
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
}) : state === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4239
|
-
className: "dcu-connector-empty",
|
|
4240
|
-
children: t("connectors.loading")
|
|
4241
|
-
}) : state === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4242
|
-
className: "dcu-connector-empty",
|
|
4243
|
-
children: t("connectors.failed")
|
|
4244
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4245
|
-
className: "dcu-connector-list",
|
|
4246
|
-
children: [connectors.map((connector) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
4247
|
-
className: "dcu-connector",
|
|
4248
|
-
children: [
|
|
4249
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4250
|
-
className: "dcu-connector-head",
|
|
4251
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 }), connector.name]
|
|
4252
|
-
}),
|
|
4253
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4254
|
-
className: "dcu-connector-meta",
|
|
4255
|
-
children: t("connectors.toolCount", { count: connector.tools.length })
|
|
4256
|
-
}),
|
|
4257
|
-
connector.tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4258
|
-
className: "dcu-connector-tool",
|
|
4259
|
-
children: [tool.name, tool.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tool.description })]
|
|
4260
|
-
}, tool.name))
|
|
4261
|
-
]
|
|
4262
|
-
}, connector.name)), connectors.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4263
|
-
className: "dcu-connector-empty",
|
|
4264
|
-
children: t("connectors.empty")
|
|
4265
|
-
})]
|
|
4664
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeConnectorList, {
|
|
4665
|
+
sessionStore,
|
|
4666
|
+
t
|
|
4266
4667
|
})
|
|
4267
|
-
]
|
|
4668
|
+
] })]
|
|
4268
4669
|
});
|
|
4269
4670
|
}
|
|
4270
4671
|
//#endregion
|
|
@@ -4290,6 +4691,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4290
4691
|
"sidebar.tasksTab": "任务",
|
|
4291
4692
|
"sidebar.channelsTab": "频道",
|
|
4292
4693
|
"sidebar.scheduleTab": "定时",
|
|
4694
|
+
"sidebar.runsTab": "执行记录",
|
|
4695
|
+
"sidebar.overviewTab": "任务总览",
|
|
4293
4696
|
"channels.empty": "还没有频道会话。先在设置 → IM助理 里连接渠道。",
|
|
4294
4697
|
"channels.loadError": "无法读取频道会话。",
|
|
4295
4698
|
"channel.dingtalk": "钉钉",
|
|
@@ -4300,6 +4703,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4300
4703
|
"channel.qq": "QQ",
|
|
4301
4704
|
"channel.telegram": "Telegram",
|
|
4302
4705
|
"schedule.empty": "还没有定时任务运行记录。",
|
|
4706
|
+
"schedule.groupActions": "{name} 的任务操作",
|
|
4707
|
+
"schedule.taskSettings": "任务设置",
|
|
4708
|
+
"schedule.archiveGroup": "归档整组会话",
|
|
4709
|
+
"schedule.archiveGroupConfirm": "确认归档",
|
|
4710
|
+
"schedule.archiveGroupDescription": "将归档“{name}”下的 {count} 个会话。归档后可以在“设置 → 已归档”中恢复。",
|
|
4711
|
+
"schedule.archiveGroupPending": "正在归档整组会话…",
|
|
4712
|
+
"schedule.archiveGroupPartial": "已归档 {archived} 个会话,另有 {failed} 个失败。可以重试剩余会话。",
|
|
4303
4713
|
"search.placeholder": "搜索会话、设置和操作",
|
|
4304
4714
|
"search.empty": "没有匹配的结果。",
|
|
4305
4715
|
"search.sessions": "会话",
|
|
@@ -4413,6 +4823,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4413
4823
|
"sidebar.tasksTab": "Tasks",
|
|
4414
4824
|
"sidebar.channelsTab": "Channels",
|
|
4415
4825
|
"sidebar.scheduleTab": "Schedule",
|
|
4826
|
+
"sidebar.runsTab": "Run history",
|
|
4827
|
+
"sidebar.overviewTab": "Task overview",
|
|
4416
4828
|
"channels.empty": "No channel conversations yet. Connect a channel in Settings → IM Assistant.",
|
|
4417
4829
|
"channels.loadError": "Could not load channel conversations.",
|
|
4418
4830
|
"channel.dingtalk": "DingTalk",
|
|
@@ -4423,6 +4835,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4423
4835
|
"channel.qq": "QQ",
|
|
4424
4836
|
"channel.telegram": "Telegram",
|
|
4425
4837
|
"schedule.empty": "No scheduled-task runs yet.",
|
|
4838
|
+
"schedule.groupActions": "Task actions for {name}",
|
|
4839
|
+
"schedule.taskSettings": "Task settings",
|
|
4840
|
+
"schedule.archiveGroup": "Archive all conversations",
|
|
4841
|
+
"schedule.archiveGroupConfirm": "Archive all",
|
|
4842
|
+
"schedule.archiveGroupDescription": "Archive all {count} conversations for “{name}”. You can restore them later in Settings → Archived.",
|
|
4843
|
+
"schedule.archiveGroupPending": "Archiving conversations…",
|
|
4844
|
+
"schedule.archiveGroupPartial": "Archived {archived} conversations; {failed} failed. You can retry the remaining conversations.",
|
|
4426
4845
|
"search.placeholder": "Search conversations, settings, and actions",
|
|
4427
4846
|
"search.empty": "No matching results.",
|
|
4428
4847
|
"search.sessions": "Conversations",
|
|
@@ -4600,11 +5019,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4600
5019
|
if (typeof document === "undefined" || document.body === null) return () => {};
|
|
4601
5020
|
let applying = false;
|
|
4602
5021
|
let frame;
|
|
5022
|
+
const pendingRoots = /* @__PURE__ */ new Set([document]);
|
|
4603
5023
|
const apply = () => {
|
|
4604
5024
|
if (applying) return;
|
|
4605
5025
|
applying = true;
|
|
5026
|
+
const roots = [...pendingRoots];
|
|
5027
|
+
pendingRoots.clear();
|
|
4606
5028
|
try {
|
|
4607
|
-
applySettingsNavIcons(
|
|
5029
|
+
for (const root of roots) applySettingsNavIcons(root);
|
|
4608
5030
|
} finally {
|
|
4609
5031
|
applying = false;
|
|
4610
5032
|
}
|
|
@@ -4617,7 +5039,18 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4617
5039
|
});
|
|
4618
5040
|
};
|
|
4619
5041
|
apply();
|
|
4620
|
-
const observer = new MutationObserver(
|
|
5042
|
+
const observer = new MutationObserver((records) => {
|
|
5043
|
+
for (const record of records) {
|
|
5044
|
+
const button = (record.target.nodeType === 1 ? record.target : record.target.parentElement)?.closest("[role=\"dialog\"] nav button");
|
|
5045
|
+
if (button !== null && button !== void 0) pendingRoots.add(button.closest("[role=\"dialog\"]") ?? document);
|
|
5046
|
+
for (const node of record.addedNodes) {
|
|
5047
|
+
if (!(node instanceof Element)) continue;
|
|
5048
|
+
if (node.matches("[role=\"dialog\"] nav button")) pendingRoots.add(node.closest("[role=\"dialog\"]") ?? document);
|
|
5049
|
+
else if (node.querySelector("[role=\"dialog\"] nav button") !== null) pendingRoots.add(node);
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
if (pendingRoots.size > 0) schedule();
|
|
5053
|
+
});
|
|
4621
5054
|
observer.observe(document.body, {
|
|
4622
5055
|
childList: true,
|
|
4623
5056
|
subtree: true
|
|
@@ -4695,12 +5128,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4695
5128
|
if (typeof document === "undefined" || document.body === null) return () => {};
|
|
4696
5129
|
let applying = false;
|
|
4697
5130
|
let frame;
|
|
5131
|
+
const pendingRoots = /* @__PURE__ */ new Set([document]);
|
|
4698
5132
|
const apply = () => {
|
|
4699
5133
|
if (applying) return;
|
|
4700
5134
|
applying = true;
|
|
4701
5135
|
const active = locale.getSnapshot?.().active ?? document.documentElement.lang ?? window.navigator.language ?? "zh";
|
|
5136
|
+
const roots = [...pendingRoots];
|
|
5137
|
+
pendingRoots.clear();
|
|
4702
5138
|
try {
|
|
4703
|
-
localizePermissionLabels(
|
|
5139
|
+
for (const root of roots) localizePermissionLabels(root, active);
|
|
4704
5140
|
} finally {
|
|
4705
5141
|
applying = false;
|
|
4706
5142
|
}
|
|
@@ -4713,13 +5149,26 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4713
5149
|
});
|
|
4714
5150
|
};
|
|
4715
5151
|
apply();
|
|
4716
|
-
const observer = new MutationObserver(
|
|
5152
|
+
const observer = new MutationObserver((records) => {
|
|
5153
|
+
for (const record of records) {
|
|
5154
|
+
const control = (record.target.nodeType === 1 ? record.target : record.target.parentElement)?.closest(INTERACTIVE_SELECTOR);
|
|
5155
|
+
if (control !== null && control !== void 0) pendingRoots.add(control);
|
|
5156
|
+
for (const node of record.addedNodes) {
|
|
5157
|
+
if (!(node instanceof Element)) continue;
|
|
5158
|
+
if (node.matches(INTERACTIVE_SELECTOR) || node.querySelector(INTERACTIVE_SELECTOR) !== null) pendingRoots.add(node);
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
5161
|
+
if (pendingRoots.size > 0) schedule();
|
|
5162
|
+
});
|
|
4717
5163
|
observer.observe(document.body, {
|
|
4718
5164
|
childList: true,
|
|
4719
5165
|
characterData: true,
|
|
4720
5166
|
subtree: true
|
|
4721
5167
|
});
|
|
4722
|
-
const unsubscribe = locale.subscribe?.(
|
|
5168
|
+
const unsubscribe = locale.subscribe?.(() => {
|
|
5169
|
+
pendingRoots.add(document);
|
|
5170
|
+
schedule();
|
|
5171
|
+
}) ?? (() => {});
|
|
4723
5172
|
return () => {
|
|
4724
5173
|
observer.disconnect();
|
|
4725
5174
|
unsubscribe();
|
|
@@ -4975,7 +5424,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4975
5424
|
"workspaces",
|
|
4976
5425
|
"layout",
|
|
4977
5426
|
"locale",
|
|
4978
|
-
"connection"
|
|
5427
|
+
"connection",
|
|
5428
|
+
"conversation"
|
|
4979
5429
|
];
|
|
4980
5430
|
function hasDeleteSession(value) {
|
|
4981
5431
|
return value !== null && typeof value === "object" && "deleteSession" in value && typeof value.deleteSession === "function";
|
|
@@ -5063,6 +5513,21 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5063
5513
|
const result = await registry.deleteSession(sessionId);
|
|
5064
5514
|
if (!result.ok) throw new Error(result.error?.message ?? t("sessions.deleteUnavailable"));
|
|
5065
5515
|
};
|
|
5516
|
+
const startConnectorPromptSession = async (promptText) => {
|
|
5517
|
+
const prompt = promptText.trim();
|
|
5518
|
+
if (prompt === "") throw new Error("Prompt 不能为空");
|
|
5519
|
+
const workspaces = ctx.workspaces.list.getSnapshot();
|
|
5520
|
+
const currentSessionId = ctx.sessions.list.getSnapshot().current;
|
|
5521
|
+
const targetWorkspaceId = (currentSessionId === void 0 ? void 0 : workspaces.items.find((workspace) => workspace.sessionIds.includes(currentSessionId))?.workspaceId) ?? workspaces.recentWorkspaceId;
|
|
5522
|
+
if (targetWorkspaceId === void 0) throw new Error("请先选择一个工作空间,再使用示例 Prompt");
|
|
5523
|
+
const sessionId = await ctx.workspaces.connectWorkspace(targetWorkspaceId);
|
|
5524
|
+
const conversation = ctx.get("conversation");
|
|
5525
|
+
if (conversation === void 0) throw new Error("DSH 对话服务尚未就绪,请稍后重试");
|
|
5526
|
+
const binding = ctx.sessions.binding(sessionId);
|
|
5527
|
+
if (binding === void 0) throw new Error("新会话尚未就绪,请稍后重试");
|
|
5528
|
+
conversation.input.for(binding.ctx).setDraft(prompt);
|
|
5529
|
+
ctx.sessions.open(sessionId);
|
|
5530
|
+
};
|
|
5066
5531
|
ctx.slots.inject("sidebar.workspaces", () => ctx.slots.register({
|
|
5067
5532
|
name: "sidebar.workspaces",
|
|
5068
5533
|
priority: -1,
|
|
@@ -5106,6 +5571,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
5106
5571
|
icon: "connector",
|
|
5107
5572
|
inject: () => ({
|
|
5108
5573
|
sessionStore: ctx.sessions.list,
|
|
5574
|
+
startPromptSession: startConnectorPromptSession,
|
|
5109
5575
|
t
|
|
5110
5576
|
})
|
|
5111
5577
|
}, ConnectorsSection));
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { mkdir, readFile, rename, rm, unlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
4
|
+
import { basename, dirname, isAbsolute, join, resolve, sep, win32 } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
//#region src/dependencies.ts
|
|
@@ -514,6 +514,28 @@ async function installDependenciesLocked(ids, requestHotUpdate) {
|
|
|
514
514
|
return dependencyStatuses();
|
|
515
515
|
}
|
|
516
516
|
//#endregion
|
|
517
|
+
//#region src/explorer-path-policy.ts
|
|
518
|
+
function normalizedWindowsPath(path) {
|
|
519
|
+
if (!win32.isAbsolute(path)) return void 0;
|
|
520
|
+
const normalized = win32.normalize(path.trim()).replace(/[\\/]+$/, "");
|
|
521
|
+
const root = win32.parse(normalized).root;
|
|
522
|
+
if (root.startsWith("\\\\") || normalized.toLocaleLowerCase("en-US") === root.replace(/[\\/]+$/, "").toLocaleLowerCase("en-US")) return;
|
|
523
|
+
return normalized;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* 仅允许打开注册表中已有的工作区根目录。
|
|
527
|
+
* 不接受子目录、盘符根或 UNC,避免同源页面把 Host 端点当成任意路径启动器。
|
|
528
|
+
*/
|
|
529
|
+
function authorizedExplorerWorkspacePath(path, workspaceRoots) {
|
|
530
|
+
const target = normalizedWindowsPath(path);
|
|
531
|
+
if (target === void 0) return void 0;
|
|
532
|
+
const targetKey = target.toLocaleLowerCase("en-US");
|
|
533
|
+
for (const root of workspaceRoots) {
|
|
534
|
+
const normalizedRoot = normalizedWindowsPath(root);
|
|
535
|
+
if (normalizedRoot !== void 0 && normalizedRoot.toLocaleLowerCase("en-US") === targetKey) return normalizedRoot;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
//#endregion
|
|
517
539
|
//#region src/host-services.ts
|
|
518
540
|
function requireService(ctx, key, method) {
|
|
519
541
|
const service = ctx.get(key);
|
|
@@ -525,7 +547,8 @@ function hostServices(ctx) {
|
|
|
525
547
|
return {
|
|
526
548
|
webServer: requireService(ctx, "webServer", "register"),
|
|
527
549
|
agents: requireService(ctx, "agents", "get"),
|
|
528
|
-
tools: requireService(ctx, "tools", "schemas")
|
|
550
|
+
tools: requireService(ctx, "tools", "schemas"),
|
|
551
|
+
workspaceRegistry: requireService(ctx, "workspaceRegistry", "list")
|
|
529
552
|
};
|
|
530
553
|
}
|
|
531
554
|
//#endregion
|
|
@@ -869,7 +892,8 @@ async function readRequestBody(request, maxBytes = maxPreferencesBodyBytes) {
|
|
|
869
892
|
const inject = [
|
|
870
893
|
"webServer",
|
|
871
894
|
"agents",
|
|
872
|
-
"tools"
|
|
895
|
+
"tools",
|
|
896
|
+
"workspaceRegistry"
|
|
873
897
|
];
|
|
874
898
|
/** 提供不泄露地址、命令和凭证的连接器目录。 */
|
|
875
899
|
function apply(ctx) {
|
|
@@ -1100,7 +1124,16 @@ function apply(ctx) {
|
|
|
1100
1124
|
response.end(JSON.stringify({ error: "目录路径无效。" }));
|
|
1101
1125
|
return;
|
|
1102
1126
|
}
|
|
1103
|
-
|
|
1127
|
+
const authorizedPath = authorizedExplorerWorkspacePath(body.path, host.workspaceRegistry.list().map((workspace) => workspace.path));
|
|
1128
|
+
if (authorizedPath === void 0) {
|
|
1129
|
+
response.writeHead(403, {
|
|
1130
|
+
"content-type": "application/json; charset=utf-8",
|
|
1131
|
+
"cache-control": "no-store"
|
|
1132
|
+
});
|
|
1133
|
+
response.end(JSON.stringify({ error: "仅允许打开已注册的工作区目录。" }));
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
await foregroundExplorer.open(authorizedPath);
|
|
1104
1137
|
response.writeHead(200, {
|
|
1105
1138
|
"content-type": "application/json; charset=utf-8",
|
|
1106
1139
|
"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.89",
|
|
4
4
|
"description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"homepage": "https://github.com/MichengAI/dsh-codex-ui#readme",
|
|
18
18
|
"type": "module",
|
|
19
|
+
"packageManager": "pnpm@11.22.0",
|
|
19
20
|
"main": "dist/index.mjs",
|
|
20
21
|
"types": "dist/index.d.mts",
|
|
21
22
|
"exports": {
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"scripts": {
|
|
57
58
|
"build": "tsc --noEmit && tsdown",
|
|
58
59
|
"typecheck": "tsc --noEmit",
|
|
59
|
-
"test": "pnpm run typecheck && vitest run
|
|
60
|
+
"test": "pnpm run typecheck && vitest run && tsdown && node tests/run-assertions.mjs"
|
|
60
61
|
},
|
|
61
62
|
"peerDependencies": {
|
|
62
63
|
"@deepseek-ai/cordis": ">=4.0.1 <5.0.0",
|