@michengai/dsh-codex-ui 0.2.75 → 0.2.77

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/dist/client.js CHANGED
@@ -590,10 +590,59 @@ window.__ModuleLoader__.load({
590
590
  //#region src/client/pinned-workspaces.ts
591
591
  /** 浏览器本地持久化键;置顶只影响本插件中的工作区分区。 */
592
592
  const PINNED_WORKSPACES_STORAGE_KEY = "dsh-codex-ui.pinned-workspace-ids";
593
+ const WORKSPACE_PREFERENCES_ENDPOINT = "/api/michengai/codex-ui/preferences";
593
594
  /** 清理无效或重复的工作区标识。 */
594
595
  function normalizePinnedWorkspaceIds(ids) {
595
596
  return [...new Set(ids.filter((id) => id.trim() !== ""))];
596
597
  }
598
+ /** 仅在宿主完整基线就绪后清理已经不存在的工作区,避免加载中的临时列表抹掉持久化置顶。 */
599
+ function prunePinnedWorkspaceIds(ids, validIds) {
600
+ const valid = new Set(validIds);
601
+ const next = ids.filter((id) => valid.has(id));
602
+ return next.length === ids.length ? [...ids] : next;
603
+ }
604
+ /** Host 数据优先;首次升级没有 Host 文件时迁移旧 origin 的 localStorage;读取期间的用户操作永远优先。 */
605
+ function resolvePinnedWorkspaceHydration(localIds, host, dirtyIds) {
606
+ if (dirtyIds !== void 0) return {
607
+ ids: normalizePinnedWorkspaceIds(dirtyIds),
608
+ writeHost: true
609
+ };
610
+ if (host.exists) return {
611
+ ids: normalizePinnedWorkspaceIds(host.pinnedWorkspaceIds),
612
+ writeHost: false
613
+ };
614
+ const ids = normalizePinnedWorkspaceIds(localIds);
615
+ return {
616
+ ids,
617
+ writeHost: ids.length > 0
618
+ };
619
+ }
620
+ async function readHostPinnedWorkspaceIds(fetcher = fetch) {
621
+ const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
622
+ method: "GET",
623
+ cache: "no-store",
624
+ signal: AbortSignal.timeout(5e3)
625
+ });
626
+ if (!response.ok) throw new Error(`读取置顶偏好失败:HTTP ${response.status}`);
627
+ const payload = await response.json();
628
+ if (payload === null || typeof payload !== "object") throw new Error("置顶偏好响应格式无效。");
629
+ const record = payload;
630
+ if (typeof record.exists !== "boolean" || !Array.isArray(record.pinnedWorkspaceIds) || !record.pinnedWorkspaceIds.every((id) => typeof id === "string")) throw new Error("置顶偏好响应格式无效。");
631
+ return {
632
+ exists: record.exists,
633
+ pinnedWorkspaceIds: normalizePinnedWorkspaceIds(record.pinnedWorkspaceIds)
634
+ };
635
+ }
636
+ async function writeHostPinnedWorkspaceIds(ids, fetcher = fetch) {
637
+ const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
638
+ method: "PUT",
639
+ cache: "no-store",
640
+ headers: { "content-type": "application/json" },
641
+ body: JSON.stringify({ pinnedWorkspaceIds: normalizePinnedWorkspaceIds(ids) }),
642
+ signal: AbortSignal.timeout(5e3)
643
+ });
644
+ if (!response.ok) throw new Error(`保存置顶偏好失败:HTTP ${response.status}`);
645
+ }
597
646
  /** 在置顶列表中切换一个工作区。 */
598
647
  /** 把工作区插入置顶列表的指定位置;省略锚点时追加到末尾。 */
599
648
  function insertPinnedWorkspace(ids, id, beforeId) {
@@ -1231,7 +1280,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1231
1280
  .dcu-wb *{box-sizing:border-box}
1232
1281
  .dcu-wb-tree{flex:1;min-height:0;overflow-y:auto;padding-bottom:16px;scrollbar-gutter:stable;user-select:none;-webkit-user-select:none}
1233
1282
  .dcu-wb-section+.dcu-wb-section{margin-top:12px}
1234
- .dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0 4px;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:.02em;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 140ms ease,transform 180ms ease}.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:grid;grid-template-rows:0fr;transition:grid-template-rows 220ms ease}.dcu-wb-section-body[data-open=true]{grid-template-rows:1fr}.dcu-wb-section-body>div{overflow:hidden;min-height:0}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret,.dcu-wb-section-body{transition:none}}
1283
+ .dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0 4px;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:.02em;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-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}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret{transition:none}}
1235
1284
  .dcu-wb-project{position:relative}
1236
1285
  .dcu-wb-project-head,.dcu-wb-session{position:relative;display:flex;align-items:center;gap:6px;width:100%;border-radius:8px;padding:0 8px;color:var(--dcu-sidebar-primary);cursor:pointer}
1237
1286
  .dcu-wb-project-head{height:28px;background:transparent;font:inherit;text-align:left}
@@ -1269,7 +1318,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1269
1318
  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}`;
1270
1319
  const WORKSPACE_TREE_STYLE = stylesheet$4 + runningStyles + typographyStyles;
1271
1320
  function storage$1() {
1272
- return typeof window === "undefined" ? void 0 : window.localStorage;
1321
+ if (typeof window === "undefined") return void 0;
1322
+ try {
1323
+ return window.localStorage;
1324
+ } catch {
1325
+ return;
1326
+ }
1327
+ }
1328
+ function sameIds(left, right) {
1329
+ return left.length === right.length && left.every((id, index) => id === right[index]);
1273
1330
  }
1274
1331
  function browserBase() {
1275
1332
  return typeof window === "undefined" || window.location.origin === "null" ? "http://dsh.internal/" : `${window.location.origin}/`;
@@ -1287,7 +1344,33 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1287
1344
  const sessions = useSessions((state) => state);
1288
1345
  const workspaces = useWorkspaces((state) => state);
1289
1346
  const [expanded, setExpanded] = (0, react.useState)({});
1290
- const [pinnedWorkspaceIds, setPinnedWorkspaceIds] = (0, react.useState)(() => readPinnedWorkspaceIds(storage$1()));
1347
+ const [pinnedWorkspaceIds, setPinnedWorkspaceIdsState] = (0, react.useState)(() => readPinnedWorkspaceIds(storage$1()));
1348
+ const pinnedWorkspaceIdsRef = (0, react.useRef)(pinnedWorkspaceIds);
1349
+ pinnedWorkspaceIdsRef.current = pinnedWorkspaceIds;
1350
+ const pinnedHostHydratedRef = (0, react.useRef)(false);
1351
+ const pinnedHostDirtyRef = (0, react.useRef)(false);
1352
+ const pinnedHostSkipWriteRef = (0, react.useRef)();
1353
+ const pinnedHostWriteRef = (0, react.useRef)(Promise.resolve());
1354
+ const workspaceBaselineRef = (0, react.useRef)({
1355
+ ready: false,
1356
+ validIds: []
1357
+ });
1358
+ workspaceBaselineRef.current = {
1359
+ ready: workspaces.baselinesReady === true,
1360
+ validIds: workspaces.items.map((workspace) => String(workspace.workspaceId))
1361
+ };
1362
+ const queuePinnedHostWrite = (ids) => {
1363
+ const snapshot = [...ids];
1364
+ const pending = pinnedHostWriteRef.current.then(() => writeHostPinnedWorkspaceIds(snapshot));
1365
+ pinnedHostWriteRef.current = pending.catch(() => void 0);
1366
+ };
1367
+ const setPinnedWorkspaceIds = (update) => {
1368
+ pinnedHostDirtyRef.current = true;
1369
+ const current = pinnedWorkspaceIdsRef.current;
1370
+ const next = typeof update === "function" ? update(current) : update;
1371
+ pinnedWorkspaceIdsRef.current = next;
1372
+ setPinnedWorkspaceIdsState(next);
1373
+ };
1291
1374
  const [pinnedSessionIds, setPinnedSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY));
1292
1375
  const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY));
1293
1376
  const [menu, setMenu] = (0, react.useState)();
@@ -1303,7 +1386,12 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1303
1386
  const busyRef = (0, react.useRef)();
1304
1387
  const [error, setError] = (0, react.useState)();
1305
1388
  const [workspaceDragId, setWorkspaceDragId] = (0, react.useState)();
1306
- const [workspaceDropTarget, setWorkspaceDropTarget] = (0, react.useState)();
1389
+ const [workspaceDropTarget, setWorkspaceDropTargetState] = (0, react.useState)();
1390
+ const workspaceDropTargetRef = (0, react.useRef)();
1391
+ const setWorkspaceDropTarget = (target) => {
1392
+ workspaceDropTargetRef.current = target;
1393
+ setWorkspaceDropTargetState(target);
1394
+ };
1307
1395
  const [headerMenu, setHeaderMenu] = (0, react.useState)();
1308
1396
  const headerMenuRef = (0, react.useRef)();
1309
1397
  headerMenuRef.current = headerMenu;
@@ -1312,7 +1400,34 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1312
1400
  const [sessionDropTarget, setSessionDropTarget] = (0, react.useState)();
1313
1401
  (0, react.useEffect)(() => {
1314
1402
  savePinnedWorkspaceIds(storage$1(), pinnedWorkspaceIds);
1403
+ if (!pinnedHostHydratedRef.current) return;
1404
+ const skippedHydration = pinnedHostSkipWriteRef.current;
1405
+ pinnedHostSkipWriteRef.current = void 0;
1406
+ if (skippedHydration !== void 0 && sameIds(skippedHydration, pinnedWorkspaceIds)) return;
1407
+ queuePinnedHostWrite(pinnedWorkspaceIds);
1315
1408
  }, [pinnedWorkspaceIds]);
1409
+ (0, react.useEffect)(() => {
1410
+ let alive = true;
1411
+ const localIds = [...pinnedWorkspaceIdsRef.current];
1412
+ readHostPinnedWorkspaceIds().then((host) => {
1413
+ if (!alive) return;
1414
+ const hydration = resolvePinnedWorkspaceHydration(localIds, host, pinnedHostDirtyRef.current ? pinnedWorkspaceIdsRef.current : void 0);
1415
+ const baseline = workspaceBaselineRef.current;
1416
+ const ids = baseline.ready ? prunePinnedWorkspaceIds(hydration.ids, baseline.validIds) : hydration.ids;
1417
+ const writeHost = hydration.writeHost || !sameIds(ids, hydration.ids);
1418
+ pinnedHostHydratedRef.current = true;
1419
+ if (!sameIds(pinnedWorkspaceIdsRef.current, ids)) {
1420
+ pinnedHostSkipWriteRef.current = [...ids];
1421
+ pinnedWorkspaceIdsRef.current = ids;
1422
+ setPinnedWorkspaceIdsState(ids);
1423
+ }
1424
+ savePinnedWorkspaceIds(storage$1(), ids);
1425
+ if (writeHost) queuePinnedHostWrite(ids);
1426
+ }).catch(() => {});
1427
+ return () => {
1428
+ alive = false;
1429
+ };
1430
+ }, []);
1316
1431
  (0, react.useEffect)(() => {
1317
1432
  writeSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
1318
1433
  }, [pinnedSessionIds]);
@@ -1320,10 +1435,12 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1320
1435
  writeSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
1321
1436
  }, [unreadSessionIds]);
1322
1437
  (0, react.useEffect)(() => {
1323
- if (workspaces.items.length === 0) return;
1324
- const valid = new Set(workspaces.items.map((workspace) => String(workspace.workspaceId)));
1325
- setPinnedWorkspaceIds((ids) => ids.filter((id) => valid.has(id)));
1326
- }, [workspaces.items]);
1438
+ if (workspaces.baselinesReady !== true) return;
1439
+ const next = prunePinnedWorkspaceIds(pinnedWorkspaceIdsRef.current, workspaces.items.map((workspace) => String(workspace.workspaceId)));
1440
+ if (sameIds(pinnedWorkspaceIdsRef.current, next)) return;
1441
+ pinnedWorkspaceIdsRef.current = next;
1442
+ setPinnedWorkspaceIdsState(next);
1443
+ }, [workspaces.baselinesReady, workspaces.items]);
1327
1444
  (0, react.useEffect)(() => {
1328
1445
  const current = sessions.current;
1329
1446
  if (current !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== current));
@@ -1533,7 +1650,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1533
1650
  const workspaceId = String(workspace.workspaceId);
1534
1651
  const zoneIds = zone === "pinned" ? pinnedGroupIds : regularGroupIds;
1535
1652
  const dropsBefore = workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === workspaceId;
1536
- const dropsAfterLast = workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === void 0 && zoneIds[zoneIds.length - 1] === workspaceId;
1653
+ const dropsAfterLast = zone === "projects" && workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === void 0 && zoneIds[zoneIds.length - 1] === workspaceId;
1537
1654
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1538
1655
  className: `dcu-wb-project${isCurrentWorkspace ? " dcu-wb-project-current" : ""}${isPinnedHeaderDrop || dropsBefore ? " dcu-wb-drop" : ""}${dropsAfterLast ? " dcu-wb-drop dcu-wb-drop-after" : ""}`,
1539
1656
  onDragOver: (event) => {
@@ -1972,7 +2089,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1972
2089
  onDrop: (event) => {
1973
2090
  event.preventDefault();
1974
2091
  const draggedWorkspace = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
1975
- const target = workspaceDropTarget;
2092
+ const target = workspaceDropTargetRef.current;
1976
2093
  setWorkspaceDragId(void 0);
1977
2094
  setWorkspaceDropTarget(void 0);
1978
2095
  if (draggedWorkspace !== void 0 && target?.zone === "pinned") pinWorkspaceAt(draggedWorkspace, target.beforeId);
@@ -2996,13 +3113,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
2996
3113
  const getEmptyCompanionTabs = () => EMPTY_COMPANION_TABS;
2997
3114
  const stylesheet$3 = `
2998
3115
  .dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--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;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)}
3116
+ [data-dcu-sidebar-frame]{transition:none!important}[data-dcu-sidebar-frame] [data-side=sidebar]{transition:none!important}.dcu-expanded-shell{display:flex;min-height:0;flex:1;flex-direction:column}.dcu-compact-shell{display: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}
2999
3117
  .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}
3000
3118
  .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}
3001
3119
  .dcu-icon:hover,.dcu-menu button:hover:not(:disabled),.dcu-footer-link:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}
3002
3120
  .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}
3003
3121
  .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)}
3004
3122
  .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}
3005
- .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;gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border)}.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:center;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-head,.dcu-compact .dcu-menu,.dcu-compact .dcu-workspaces,.dcu-compact .dcu-brand,.dcu-compact .dcu-im-tabs{display:none}.dcu-compact .dcu-foot{width:36px;margin-top:auto;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}
3123
+ .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;gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border)}.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:center;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;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}
3006
3124
  .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}
3007
3125
  [role="dialog"][aria-labelledby]{width:min(1000px,calc(100vw - 48px));max-width:calc(100vw - 48px);height:min(800px,calc(100vh - 48px))}
3008
3126
  .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)}.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)}.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}
@@ -3043,40 +3161,41 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3043
3161
  })
3044
3162
  });
3045
3163
  }
3046
- /** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
3047
- function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useWorkspaces }) {
3048
- const settingsSeat = (0, react.useRef)(null);
3049
- const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(true);
3050
- const [searchOpen, setSearchOpen] = (0, react.useState)(false);
3051
- const [searchQuery, setSearchQuery] = (0, react.useState)("");
3052
- const [activeSearchIndex, setActiveSearchIndex] = (0, react.useState)(0);
3053
- const [imTab, setImTab] = (0, react.useState)("tasks");
3054
- const companionTabs = (0, react.useSyncExternalStore)(companionSlots?.subscribe ?? subscribeEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs);
3055
- const showChannels = companionTabs.channels;
3056
- const showSchedule = companionTabs.schedule;
3057
- const showCompanionTabs = showChannels || showSchedule;
3164
+ /** 搜索状态与大侧栏隔离:输入、悬停和开关弹窗都不能让工作区树跟着重渲染。 */
3165
+ const SidebarSearch = (0, react.forwardRef)(function SidebarSearch({ openSession, startSession, t, useSessions, useWorkspaces, settingsSeat }, ref) {
3166
+ const [open, setOpen] = (0, react.useState)(false);
3167
+ const [query, setQuery] = (0, react.useState)("");
3168
+ const [activeIndex, setActiveIndex] = (0, react.useState)(0);
3169
+ const deferredQuery = (0, react.useDeferredValue)(query);
3058
3170
  const sessions = useSessions((state) => state);
3059
3171
  const workspaces = useWorkspaces((state) => state);
3060
- const selectSection = (label) => {
3172
+ const close = (0, react.useCallback)(() => {
3173
+ setOpen(false);
3174
+ setQuery("");
3175
+ setActiveIndex(0);
3176
+ }, []);
3177
+ (0, react.useImperativeHandle)(ref, () => ({ open: () => {
3178
+ setOpen(true);
3179
+ } }), []);
3180
+ const selectSection = (0, react.useCallback)((label) => {
3061
3181
  openSettingsSection(settingsSeat.current, label);
3062
- };
3063
- const selectPluginSection = () => {
3182
+ }, [settingsSeat]);
3183
+ const selectPluginSection = (0, react.useCallback)(() => {
3064
3184
  openSettingsSection(settingsSeat.current, [t("sidebar.marketplace"), t("sidebar.plugins")]);
3065
- };
3066
- const selectExternalSection = (label) => {
3185
+ }, [settingsSeat, t]);
3186
+ const selectExternalSection = (0, react.useCallback)((label) => {
3067
3187
  openSettingsSection(settingsSeat.current, label, () => {
3068
3188
  selectSection(t("about.nav"));
3069
3189
  });
3070
- };
3071
- const openSettings = () => {
3190
+ }, [
3191
+ selectSection,
3192
+ settingsSeat,
3193
+ t
3194
+ ]);
3195
+ const openSettings = (0, react.useCallback)(() => {
3072
3196
  settingsSeat.current?.querySelector("[aria-haspopup=\"dialog\"]")?.click();
3073
- };
3074
- const closeSearch = () => {
3075
- setSearchOpen(false);
3076
- setSearchQuery("");
3077
- setActiveSearchIndex(0);
3078
- };
3079
- const searchEntries = (0, react.useMemo)(() => {
3197
+ }, [settingsSeat]);
3198
+ const entries = (0, react.useMemo)(() => {
3080
3199
  const archived = new Set(workspaces.archivedSessionIds);
3081
3200
  const workspaceTitles = new Map(workspaces.items.flatMap((workspace) => workspace.sessionIds.map((sessionId) => [String(sessionId), workspace.title])));
3082
3201
  const sessionEntries = sessions.ids.map((id) => sessions.byId[id]).filter((session) => session !== void 0 && !archived.has(session.id) && isTaskSession(session)).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => ({
@@ -3086,7 +3205,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3086
3205
  keywords: `${session.cwd ?? ""} ${session.id}`,
3087
3206
  detail: workspaceTitles.get(String(session.id)) ?? session.cwd,
3088
3207
  run: () => {
3089
- closeSearch();
3208
+ close();
3090
3209
  openSession(session.id);
3091
3210
  }
3092
3211
  }));
@@ -3097,7 +3216,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3097
3216
  label: t("search.settings"),
3098
3217
  keywords: t("search.settings"),
3099
3218
  run: () => {
3100
- closeSearch();
3219
+ close();
3101
3220
  openSettings();
3102
3221
  }
3103
3222
  },
@@ -3107,7 +3226,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3107
3226
  label: t("sidebar.experts"),
3108
3227
  keywords: t("search.settings"),
3109
3228
  run: () => {
3110
- closeSearch();
3229
+ close();
3111
3230
  selectExternalSection(t("sidebar.experts"));
3112
3231
  }
3113
3232
  },
@@ -3117,7 +3236,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3117
3236
  label: t("sidebar.skills"),
3118
3237
  keywords: t("search.settings"),
3119
3238
  run: () => {
3120
- closeSearch();
3239
+ close();
3121
3240
  selectExternalSection(t("sidebar.skills"));
3122
3241
  }
3123
3242
  },
@@ -3127,7 +3246,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3127
3246
  label: t("sidebar.plugins"),
3128
3247
  keywords: t("search.settings"),
3129
3248
  run: () => {
3130
- closeSearch();
3249
+ close();
3131
3250
  selectPluginSection();
3132
3251
  }
3133
3252
  },
@@ -3137,7 +3256,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3137
3256
  label: t("sidebar.connectors"),
3138
3257
  keywords: t("search.settings"),
3139
3258
  run: () => {
3140
- closeSearch();
3259
+ close();
3141
3260
  selectSection(t("sidebar.connectors"));
3142
3261
  }
3143
3262
  },
@@ -3147,7 +3266,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3147
3266
  label: t("sidebar.schedule"),
3148
3267
  keywords: t("search.settings"),
3149
3268
  run: () => {
3150
- closeSearch();
3269
+ close();
3151
3270
  selectExternalSection(t("sidebar.schedule"));
3152
3271
  }
3153
3272
  },
@@ -3157,7 +3276,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3157
3276
  label: t("sidebar.assistant"),
3158
3277
  keywords: t("search.settings"),
3159
3278
  run: () => {
3160
- closeSearch();
3279
+ close();
3161
3280
  selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3162
3281
  }
3163
3282
  },
@@ -3167,7 +3286,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3167
3286
  label: t("about.nav"),
3168
3287
  keywords: t("search.settings"),
3169
3288
  run: () => {
3170
- closeSearch();
3289
+ close();
3171
3290
  selectSection(t("about.nav"));
3172
3291
  }
3173
3292
  }
@@ -3181,13 +3300,18 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3181
3300
  label: t("sidebar.newTask"),
3182
3301
  keywords: t("search.actions"),
3183
3302
  run: () => {
3184
- closeSearch();
3303
+ close();
3185
3304
  startSession();
3186
3305
  }
3187
3306
  }
3188
3307
  ];
3189
3308
  }, [
3309
+ close,
3190
3310
  openSession,
3311
+ openSettings,
3312
+ selectExternalSection,
3313
+ selectPluginSection,
3314
+ selectSection,
3191
3315
  sessions.byId,
3192
3316
  sessions.ids,
3193
3317
  startSession,
@@ -3195,38 +3319,30 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3195
3319
  workspaces.archivedSessionIds,
3196
3320
  workspaces.items
3197
3321
  ]);
3198
- const searchResults = (0, react.useMemo)(() => filterSidebarSearchItems(searchEntries, searchQuery).slice(0, 12), [searchEntries, searchQuery]);
3322
+ const results = (0, react.useMemo)(() => filterSidebarSearchItems(entries, deferredQuery).slice(0, 12), [deferredQuery, entries]);
3199
3323
  (0, react.useEffect)(() => {
3200
- setActiveSearchIndex(0);
3201
- }, [searchQuery, searchOpen]);
3324
+ setActiveIndex(0);
3325
+ }, [query, open]);
3202
3326
  (0, react.useEffect)(() => {
3203
- if (imTab === "channels" && !showChannels) setImTab("tasks");
3204
- if (imTab === "schedule" && !showSchedule) setImTab("tasks");
3205
- }, [
3206
- imTab,
3207
- showChannels,
3208
- showSchedule
3209
- ]);
3210
- (0, react.useEffect)(() => {
3211
- if (!searchOpen) return;
3327
+ if (!open) return;
3212
3328
  const onKeyDown = (event) => {
3213
3329
  if (event.key === "Escape") {
3214
3330
  event.preventDefault();
3215
- closeSearch();
3331
+ close();
3216
3332
  return;
3217
3333
  }
3218
3334
  if (event.key === "ArrowDown") {
3219
3335
  event.preventDefault();
3220
- setActiveSearchIndex((index) => Math.min(index + 1, Math.max(0, searchResults.length - 1)));
3336
+ setActiveIndex((index) => Math.min(index + 1, Math.max(0, results.length - 1)));
3221
3337
  return;
3222
3338
  }
3223
3339
  if (event.key === "ArrowUp") {
3224
3340
  event.preventDefault();
3225
- setActiveSearchIndex((index) => Math.max(index - 1, 0));
3341
+ setActiveIndex((index) => Math.max(index - 1, 0));
3226
3342
  return;
3227
3343
  }
3228
3344
  if (event.key === "Enter") {
3229
- const entry = searchResults[activeSearchIndex];
3345
+ const entry = results[activeIndex];
3230
3346
  if (entry !== void 0) {
3231
3347
  event.preventDefault();
3232
3348
  entry.run();
@@ -3238,9 +3354,105 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3238
3354
  window.removeEventListener("keydown", onKeyDown);
3239
3355
  };
3240
3356
  }, [
3241
- activeSearchIndex,
3242
- searchOpen,
3243
- searchResults
3357
+ activeIndex,
3358
+ close,
3359
+ open,
3360
+ results
3361
+ ]);
3362
+ if (!open) return null;
3363
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3364
+ className: "dcu-search-scrim",
3365
+ onMouseDown: (event) => {
3366
+ if (event.target === event.currentTarget) close();
3367
+ },
3368
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3369
+ className: "dcu-search-dialog",
3370
+ role: "dialog",
3371
+ "aria-modal": "true",
3372
+ "aria-label": t("sidebar.search"),
3373
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3374
+ className: "dcu-search-input",
3375
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3376
+ autoFocus: true,
3377
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 }),
3378
+ value: query,
3379
+ placeholder: t("search.placeholder"),
3380
+ onChange: (event) => {
3381
+ setQuery(event.target.value);
3382
+ }
3383
+ })
3384
+ }), results.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3385
+ className: "dcu-search-empty",
3386
+ children: t("search.empty")
3387
+ }) : [
3388
+ "sessions",
3389
+ "settings",
3390
+ "actions"
3391
+ ].map((group) => {
3392
+ const grouped = results.filter((entry) => entry.group === group);
3393
+ if (grouped.length === 0) return null;
3394
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3395
+ className: "dcu-search-section",
3396
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3397
+ className: "dcu-search-title",
3398
+ children: t(`search.${group}`)
3399
+ }), grouped.map((entry) => {
3400
+ const index = results.indexOf(entry);
3401
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3402
+ type: "button",
3403
+ className: "dcu-search-row",
3404
+ "data-active": index === activeIndex,
3405
+ onMouseEnter: () => {
3406
+ setActiveIndex(index);
3407
+ },
3408
+ onClick: entry.run,
3409
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3410
+ className: "dcu-search-main",
3411
+ children: entry.label
3412
+ }), entry.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3413
+ className: "dcu-search-detail",
3414
+ children: entry.detail
3415
+ })]
3416
+ }, entry.id);
3417
+ })]
3418
+ }, group);
3419
+ })]
3420
+ })
3421
+ });
3422
+ });
3423
+ /** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
3424
+ function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useWorkspaces }) {
3425
+ const settingsSeat = (0, react.useRef)(null);
3426
+ const search = (0, react.useRef)(null);
3427
+ const toggleSidebarRef = (0, react.useRef)(toggleSidebar);
3428
+ toggleSidebarRef.current = toggleSidebar;
3429
+ const expandSidebar = (0, react.useCallback)(() => {
3430
+ toggleSidebarRef.current();
3431
+ }, []);
3432
+ const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(true);
3433
+ const [imTab, setImTab] = (0, react.useState)("tasks");
3434
+ const companionTabs = (0, react.useSyncExternalStore)(companionSlots?.subscribe ?? subscribeEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs);
3435
+ const showChannels = companionTabs.channels;
3436
+ const showSchedule = companionTabs.schedule;
3437
+ const showCompanionTabs = showChannels || showSchedule;
3438
+ const selectSection = (label) => {
3439
+ openSettingsSection(settingsSeat.current, label);
3440
+ };
3441
+ const selectPluginSection = () => {
3442
+ openSettingsSection(settingsSeat.current, [t("sidebar.marketplace"), t("sidebar.plugins")]);
3443
+ };
3444
+ const selectExternalSection = (label) => {
3445
+ openSettingsSection(settingsSeat.current, label, () => {
3446
+ selectSection(t("about.nav"));
3447
+ });
3448
+ };
3449
+ (0, react.useEffect)(() => {
3450
+ if (imTab === "channels" && !showChannels) setImTab("tasks");
3451
+ if (imTab === "schedule" && !showSchedule) setImTab("tasks");
3452
+ }, [
3453
+ imTab,
3454
+ showChannels,
3455
+ showSchedule
3244
3456
  ]);
3245
3457
  (0, react.useEffect)(() => {
3246
3458
  let startX = 0;
@@ -3277,403 +3489,285 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3277
3489
  window.removeEventListener("pointercancel", onCancel, true);
3278
3490
  };
3279
3491
  }, [toggleSidebar]);
3280
- if (collapsed || width < 80) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
3281
- className: "dcu-root dcu-compact",
3282
- "aria-label": t("sidebar.label"),
3283
- children: [
3284
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$3 }),
3285
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3286
- type: "button",
3287
- className: "dcu-icon",
3288
- "aria-label": t("sidebar.expand"),
3289
- onClick: toggleSidebar,
3290
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
3291
- }),
3292
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3293
- className: "dcu-compact-nav",
3294
- "aria-label": t("sidebar.mainMenu"),
3295
- children: [
3296
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3297
- type: "button",
3298
- className: "dcu-icon",
3299
- "aria-label": t("sidebar.newTask"),
3300
- onClick: () => {
3301
- startSession();
3302
- },
3303
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 })
3304
- }),
3305
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3306
- type: "button",
3307
- className: "dcu-icon",
3308
- "aria-label": t("sidebar.search"),
3309
- onClick: () => {
3310
- setSearchOpen(true);
3311
- },
3312
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 })
3313
- }),
3314
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3315
- type: "button",
3316
- className: "dcu-icon",
3317
- "aria-label": t("sidebar.experts"),
3318
- onClick: () => {
3319
- selectExternalSection(t("sidebar.experts"));
3320
- },
3321
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 16 })
3322
- }),
3323
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3324
- type: "button",
3325
- className: "dcu-icon",
3326
- "aria-label": t("sidebar.skills"),
3327
- onClick: () => {
3328
- selectExternalSection(t("sidebar.skills"));
3329
- },
3330
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutline16, { size: 16 })
3331
- }),
3332
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3333
- type: "button",
3334
- className: "dcu-icon",
3335
- "aria-label": t("sidebar.plugins"),
3336
- onClick: () => {
3337
- selectPluginSection();
3338
- },
3339
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 })
3340
- }),
3341
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3342
- type: "button",
3343
- className: "dcu-icon",
3344
- "aria-label": t("sidebar.connectors"),
3345
- onClick: () => {
3346
- selectSection(t("sidebar.connectors"));
3347
- },
3348
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 })
3349
- }),
3350
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3351
- type: "button",
3352
- className: "dcu-icon",
3353
- "aria-label": t("sidebar.schedule"),
3354
- onClick: () => {
3355
- selectExternalSection(t("sidebar.schedule"));
3356
- },
3357
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleIcon, {})
3358
- }),
3359
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3360
- type: "button",
3361
- className: "dcu-icon",
3362
- "aria-label": t("sidebar.assistant"),
3363
- onClick: () => {
3364
- selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3365
- },
3366
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {})
3367
- })
3368
- ]
3369
- }),
3370
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
3371
- className: "dcu-foot",
3372
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3373
- className: "dcu-footer-actions",
3374
- children: renderSlot("sidebar.footer.action", { wide: false })
3375
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3376
- ref: settingsSeat,
3377
- className: "dcu-settings-seat",
3378
- children: renderSlot("sidebar.settings", { wide: false })
3379
- })]
3380
- }),
3381
- searchOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3382
- className: "dcu-search-scrim",
3383
- onMouseDown: (event) => {
3384
- if (event.target === event.currentTarget) closeSearch();
3385
- },
3386
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3387
- className: "dcu-search-dialog",
3388
- role: "dialog",
3389
- "aria-modal": "true",
3390
- "aria-label": t("sidebar.search"),
3391
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3392
- className: "dcu-search-input",
3393
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3394
- autoFocus: true,
3395
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 }),
3396
- value: searchQuery,
3397
- placeholder: t("search.placeholder"),
3398
- onChange: (event) => {
3399
- setSearchQuery(event.target.value);
3400
- }
3401
- })
3402
- }), searchResults.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3403
- className: "dcu-search-empty",
3404
- children: t("search.empty")
3405
- }) : [
3406
- "sessions",
3407
- "settings",
3408
- "actions"
3409
- ].map((group) => {
3410
- const entries = searchResults.filter((entry) => entry.group === group);
3411
- if (entries.length === 0) return null;
3412
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3413
- className: "dcu-search-section",
3414
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3415
- className: "dcu-search-title",
3416
- children: t(`search.${group}`)
3417
- }), entries.map((entry) => {
3418
- const index = searchResults.indexOf(entry);
3419
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3420
- type: "button",
3421
- className: "dcu-search-row",
3422
- "data-active": index === activeSearchIndex,
3423
- onMouseEnter: () => {
3424
- setActiveSearchIndex(index);
3425
- },
3426
- onClick: entry.run,
3427
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3428
- className: "dcu-search-main",
3429
- children: entry.label
3430
- }), entry.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3431
- className: "dcu-search-detail",
3432
- children: entry.detail
3433
- })]
3434
- }, entry.id);
3435
- })]
3436
- }, group);
3437
- })]
3438
- })
3439
- })
3440
- ]
3441
- });
3492
+ const compact = collapsed || width < 80;
3493
+ const workspaceSlot = (0, react.useMemo)(() => renderSlot("sidebar.workspaces", {
3494
+ wide: true,
3495
+ expandSidebar
3496
+ }), [expandSidebar, renderSlot]);
3442
3497
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
3443
- className: "dcu-root",
3498
+ className: `dcu-root${compact ? " dcu-compact" : ""}`,
3444
3499
  "aria-label": t("sidebar.label"),
3445
3500
  children: [
3446
3501
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$3 }),
3447
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
3448
- className: "dcu-head",
3449
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3450
- type: "button",
3451
- className: "dcu-brand",
3452
- "aria-label": t("sidebar.newTask"),
3453
- onClick: () => {
3454
- startSession();
3455
- },
3456
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.BrandWordmark, { size: 24 })
3457
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3458
- className: "dcu-head-actions",
3459
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3460
- type: "button",
3461
- className: "dcu-icon",
3462
- "aria-label": t("sidebar.collapse"),
3463
- onClick: toggleSidebar,
3464
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
3465
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3466
- type: "button",
3467
- className: "dcu-icon",
3468
- "aria-label": t("sidebar.search"),
3469
- onClick: () => {
3470
- setSearchOpen(true);
3471
- },
3472
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 })
3473
- })]
3474
- })]
3475
- }),
3476
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3477
- className: "dcu-menu",
3478
- "aria-label": t("sidebar.mainMenu"),
3502
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3503
+ className: "dcu-expanded-shell",
3479
3504
  children: [
3480
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3481
- type: "button",
3482
- onClick: () => {
3483
- startSession();
3484
- },
3485
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 }) }), t("sidebar.newTask")]
3486
- }),
3487
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3488
- type: "button",
3489
- "aria-expanded": extensionsOpen,
3490
- onClick: () => {
3491
- setExtensionsOpen((open) => !open);
3492
- },
3493
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEnhanceOutline16, { size: 16 }) }), t("sidebar.extensions")]
3505
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
3506
+ className: "dcu-head",
3507
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3508
+ type: "button",
3509
+ className: "dcu-brand",
3510
+ "aria-label": t("sidebar.newTask"),
3511
+ onClick: () => {
3512
+ startSession();
3513
+ },
3514
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.BrandWordmark, { size: 24 })
3515
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3516
+ className: "dcu-head-actions",
3517
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3518
+ type: "button",
3519
+ className: "dcu-icon",
3520
+ "aria-label": t("sidebar.collapse"),
3521
+ onClick: toggleSidebar,
3522
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
3523
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3524
+ type: "button",
3525
+ className: "dcu-icon",
3526
+ "aria-label": t("sidebar.search"),
3527
+ onClick: () => {
3528
+ search.current?.open();
3529
+ },
3530
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 })
3531
+ })]
3532
+ })]
3494
3533
  }),
3495
- extensionsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3496
- className: "dcu-extension-items",
3534
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3535
+ className: "dcu-menu",
3536
+ "aria-label": t("sidebar.mainMenu"),
3497
3537
  children: [
3498
3538
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3499
3539
  type: "button",
3500
3540
  onClick: () => {
3501
- selectExternalSection(t("sidebar.experts"));
3541
+ startSession();
3502
3542
  },
3503
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 16 }) }), t("sidebar.experts")]
3543
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 }) }), t("sidebar.newTask")]
3504
3544
  }),
3505
3545
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3506
3546
  type: "button",
3547
+ "aria-expanded": extensionsOpen,
3507
3548
  onClick: () => {
3508
- selectExternalSection(t("sidebar.skills"));
3549
+ setExtensionsOpen((open) => !open);
3509
3550
  },
3510
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutline16, { size: 16 }) }), t("sidebar.skills")]
3551
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEnhanceOutline16, { size: 16 }) }), t("sidebar.extensions")]
3552
+ }),
3553
+ extensionsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3554
+ className: "dcu-extension-items",
3555
+ children: [
3556
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3557
+ type: "button",
3558
+ onClick: () => {
3559
+ selectExternalSection(t("sidebar.experts"));
3560
+ },
3561
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 16 }) }), t("sidebar.experts")]
3562
+ }),
3563
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3564
+ type: "button",
3565
+ onClick: () => {
3566
+ selectExternalSection(t("sidebar.skills"));
3567
+ },
3568
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutline16, { size: 16 }) }), t("sidebar.skills")]
3569
+ }),
3570
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3571
+ type: "button",
3572
+ onClick: () => {
3573
+ selectPluginSection();
3574
+ },
3575
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 }) }), t("sidebar.plugins")]
3576
+ }),
3577
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3578
+ type: "button",
3579
+ onClick: () => {
3580
+ selectSection(t("sidebar.connectors"));
3581
+ },
3582
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 }) }), t("sidebar.connectors")]
3583
+ })
3584
+ ]
3511
3585
  }),
3512
3586
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3513
3587
  type: "button",
3514
3588
  onClick: () => {
3515
- selectPluginSection();
3589
+ selectExternalSection(t("sidebar.schedule"));
3516
3590
  },
3517
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 }) }), t("sidebar.plugins")]
3591
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleIcon, {}) }), t("sidebar.schedule")]
3518
3592
  }),
3519
3593
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3520
3594
  type: "button",
3521
3595
  onClick: () => {
3522
- selectSection(t("sidebar.connectors"));
3596
+ selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3523
3597
  },
3524
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 }) }), t("sidebar.connectors")]
3598
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {}) }), t("sidebar.assistant")]
3525
3599
  })
3526
3600
  ]
3527
3601
  }),
3528
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3529
- type: "button",
3530
- onClick: () => {
3531
- selectExternalSection(t("sidebar.schedule"));
3532
- },
3533
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleIcon, {}) }), t("sidebar.schedule")]
3534
- }),
3535
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3536
- type: "button",
3537
- onClick: () => {
3538
- selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3539
- },
3540
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {}) }), t("sidebar.assistant")]
3602
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3603
+ className: showCompanionTabs ? "dcu-workspaces dcu-workspaces-tabs" : "dcu-workspaces",
3604
+ children: [showCompanionTabs && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3605
+ className: "dcu-im-tabs",
3606
+ children: [
3607
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3608
+ type: "button",
3609
+ className: "dcu-im-tab",
3610
+ "data-on": imTab === "tasks",
3611
+ onClick: () => {
3612
+ setImTab("tasks");
3613
+ },
3614
+ children: t("sidebar.tasksTab")
3615
+ }),
3616
+ showChannels && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3617
+ type: "button",
3618
+ className: "dcu-im-tab",
3619
+ "data-on": imTab === "channels",
3620
+ onClick: () => {
3621
+ setImTab("channels");
3622
+ },
3623
+ children: t("sidebar.channelsTab")
3624
+ }),
3625
+ showSchedule && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3626
+ type: "button",
3627
+ className: "dcu-im-tab",
3628
+ "data-on": imTab === "schedule",
3629
+ onClick: () => {
3630
+ setImTab("schedule");
3631
+ },
3632
+ children: t("sidebar.scheduleTab")
3633
+ })
3634
+ ]
3635
+ }), imTab === "channels" && showChannels ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3636
+ className: "dcu-native-workspaces",
3637
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelBrowser, {
3638
+ openSession,
3639
+ archiveSession,
3640
+ deleteSession,
3641
+ forkSession,
3642
+ renameSession,
3643
+ useSessions,
3644
+ t
3645
+ })
3646
+ }) : imTab === "schedule" && showSchedule ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3647
+ className: "dcu-native-workspaces",
3648
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleBrowser, {
3649
+ openSession,
3650
+ archiveSession,
3651
+ deleteSession,
3652
+ forkSession,
3653
+ renameSession,
3654
+ useSessions,
3655
+ useWorkspaces,
3656
+ t
3657
+ })
3658
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3659
+ className: "dcu-native-workspaces",
3660
+ children: workspaceSlot
3661
+ })]
3541
3662
  })
3542
3663
  ]
3543
3664
  }),
3544
3665
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3545
- className: showCompanionTabs ? "dcu-workspaces dcu-workspaces-tabs" : "dcu-workspaces",
3546
- children: [showCompanionTabs && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3547
- className: "dcu-im-tabs",
3666
+ className: "dcu-compact-shell",
3667
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3668
+ type: "button",
3669
+ className: "dcu-icon",
3670
+ "aria-label": t("sidebar.expand"),
3671
+ onClick: toggleSidebar,
3672
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
3673
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
3674
+ className: "dcu-compact-nav",
3675
+ "aria-label": t("sidebar.mainMenu"),
3548
3676
  children: [
3549
3677
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3550
3678
  type: "button",
3551
- className: "dcu-im-tab",
3552
- "data-on": imTab === "tasks",
3679
+ className: "dcu-icon",
3680
+ "aria-label": t("sidebar.newTask"),
3553
3681
  onClick: () => {
3554
- setImTab("tasks");
3682
+ startSession();
3555
3683
  },
3556
- children: t("sidebar.tasksTab")
3684
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 })
3557
3685
  }),
3558
- showChannels && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3686
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3687
+ type: "button",
3688
+ className: "dcu-icon",
3689
+ "aria-label": t("sidebar.search"),
3690
+ onClick: () => {
3691
+ search.current?.open();
3692
+ },
3693
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 })
3694
+ }),
3695
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3559
3696
  type: "button",
3560
- className: "dcu-im-tab",
3561
- "data-on": imTab === "channels",
3697
+ className: "dcu-icon",
3698
+ "aria-label": t("sidebar.experts"),
3562
3699
  onClick: () => {
3563
- setImTab("channels");
3700
+ selectExternalSection(t("sidebar.experts"));
3564
3701
  },
3565
- children: t("sidebar.channelsTab")
3702
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 16 })
3566
3703
  }),
3567
- showSchedule && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3704
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3568
3705
  type: "button",
3569
- className: "dcu-im-tab",
3570
- "data-on": imTab === "schedule",
3706
+ className: "dcu-icon",
3707
+ "aria-label": t("sidebar.skills"),
3571
3708
  onClick: () => {
3572
- setImTab("schedule");
3709
+ selectExternalSection(t("sidebar.skills"));
3573
3710
  },
3574
- children: t("sidebar.scheduleTab")
3711
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutline16, { size: 16 })
3712
+ }),
3713
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3714
+ type: "button",
3715
+ className: "dcu-icon",
3716
+ "aria-label": t("sidebar.plugins"),
3717
+ onClick: () => {
3718
+ selectPluginSection();
3719
+ },
3720
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 })
3721
+ }),
3722
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3723
+ type: "button",
3724
+ className: "dcu-icon",
3725
+ "aria-label": t("sidebar.connectors"),
3726
+ onClick: () => {
3727
+ selectSection(t("sidebar.connectors"));
3728
+ },
3729
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 })
3730
+ }),
3731
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3732
+ type: "button",
3733
+ className: "dcu-icon",
3734
+ "aria-label": t("sidebar.schedule"),
3735
+ onClick: () => {
3736
+ selectExternalSection(t("sidebar.schedule"));
3737
+ },
3738
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleIcon, {})
3739
+ }),
3740
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3741
+ type: "button",
3742
+ className: "dcu-icon",
3743
+ "aria-label": t("sidebar.assistant"),
3744
+ onClick: () => {
3745
+ selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3746
+ },
3747
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {})
3575
3748
  })
3576
3749
  ]
3577
- }), imTab === "channels" && showChannels ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3578
- className: "dcu-native-workspaces",
3579
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelBrowser, {
3580
- openSession,
3581
- archiveSession,
3582
- deleteSession,
3583
- forkSession,
3584
- renameSession,
3585
- useSessions,
3586
- t
3587
- })
3588
- }) : imTab === "schedule" && showSchedule ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3589
- className: "dcu-native-workspaces",
3590
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleBrowser, {
3591
- openSession,
3592
- archiveSession,
3593
- deleteSession,
3594
- forkSession,
3595
- renameSession,
3596
- useSessions,
3597
- useWorkspaces,
3598
- t
3599
- })
3600
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3601
- className: "dcu-native-workspaces",
3602
- children: renderSlot("sidebar.workspaces", {
3603
- wide: true,
3604
- expandSidebar: toggleSidebar
3605
- })
3606
3750
  })]
3607
3751
  }),
3608
3752
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
3609
3753
  className: "dcu-foot",
3610
3754
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3611
3755
  className: "dcu-footer-actions",
3612
- children: renderSlot("sidebar.footer.action", { wide: true })
3756
+ children: renderSlot("sidebar.footer.action", { wide: !compact })
3613
3757
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3614
3758
  ref: settingsSeat,
3615
3759
  className: "dcu-settings-seat",
3616
- children: renderSlot("sidebar.settings", { wide: true })
3760
+ children: renderSlot("sidebar.settings", { wide: !compact })
3617
3761
  })]
3618
3762
  }),
3619
- searchOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3620
- className: "dcu-search-scrim",
3621
- onMouseDown: (event) => {
3622
- if (event.target === event.currentTarget) closeSearch();
3623
- },
3624
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3625
- className: "dcu-search-dialog",
3626
- role: "dialog",
3627
- "aria-modal": "true",
3628
- "aria-label": t("sidebar.search"),
3629
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3630
- className: "dcu-search-input",
3631
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3632
- autoFocus: true,
3633
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 16 }),
3634
- value: searchQuery,
3635
- placeholder: t("search.placeholder"),
3636
- onChange: (event) => {
3637
- setSearchQuery(event.target.value);
3638
- }
3639
- })
3640
- }), searchResults.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3641
- className: "dcu-search-empty",
3642
- children: t("search.empty")
3643
- }) : [
3644
- "sessions",
3645
- "settings",
3646
- "actions"
3647
- ].map((group) => {
3648
- const entries = searchResults.filter((entry) => entry.group === group);
3649
- if (entries.length === 0) return null;
3650
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3651
- className: "dcu-search-section",
3652
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3653
- className: "dcu-search-title",
3654
- children: t(`search.${group}`)
3655
- }), entries.map((entry) => {
3656
- const index = searchResults.indexOf(entry);
3657
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3658
- type: "button",
3659
- className: "dcu-search-row",
3660
- "data-active": index === activeSearchIndex,
3661
- onMouseEnter: () => {
3662
- setActiveSearchIndex(index);
3663
- },
3664
- onClick: entry.run,
3665
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3666
- className: "dcu-search-main",
3667
- children: entry.label
3668
- }), entry.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3669
- className: "dcu-search-detail",
3670
- children: entry.detail
3671
- })]
3672
- }, entry.id);
3673
- })]
3674
- }, group);
3675
- })]
3676
- })
3763
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSearch, {
3764
+ ref: search,
3765
+ settingsSeat,
3766
+ openSession,
3767
+ startSession,
3768
+ t,
3769
+ useSessions,
3770
+ useWorkspaces
3677
3771
  })
3678
3772
  ]
3679
3773
  });
@@ -4339,8 +4433,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4339
4433
  const watchFrame = (next) => {
4340
4434
  if (frame === next) return;
4341
4435
  frameObserver?.disconnect();
4436
+ frame?.removeAttribute("data-dcu-sidebar-frame");
4342
4437
  frame = next;
4343
4438
  if (frame === void 0) return;
4439
+ frame.setAttribute("data-dcu-sidebar-frame", "");
4344
4440
  frameObserver = new MutationObserver(schedule);
4345
4441
  frameObserver.observe(frame, {
4346
4442
  attributes: true,
@@ -4379,6 +4475,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4379
4475
  return () => {
4380
4476
  observer.disconnect();
4381
4477
  frameObserver?.disconnect();
4478
+ frame?.removeAttribute("data-dcu-sidebar-frame");
4382
4479
  if (pending !== void 0) window.cancelAnimationFrame(pending);
4383
4480
  };
4384
4481
  }