@michengai/dsh-codex-ui 1.1.25 → 1.1.27

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/lib/client.js CHANGED
@@ -2291,7 +2291,7 @@ window.__ModuleLoader__.load({
2291
2291
  const HEADER_PROJECT_TIP_EVENT = "dcu-header-project-tip";
2292
2292
  const HEADER_SESSION_MENU_EVENT = "dcu-header-session-menu";
2293
2293
  const CONVERSATION_HEADER_STYLE = `
2294
- header:has([data-dcu-inline-tabs]){box-sizing:border-box;display:flex;flex-wrap:nowrap;align-items:center;gap:10px;min-height:34px;padding-top:3px;padding-bottom:3px;border-bottom:0}
2294
+ header:has([data-dcu-inline-tabs]){box-sizing:border-box;display:flex;flex-wrap:nowrap;align-items:center;gap:10px;min-height:var(--dcu-header-height,34px);padding-top:calc((var(--dcu-header-height,34px) - 28px)/2);padding-bottom:calc((var(--dcu-header-height,34px) - 28px)/2);border-bottom:0}
2295
2295
  header:has([data-dcu-inline-tabs]):after{display:none;content:none}
2296
2296
  header:has([data-dcu-inline-tabs]) [class*="titleRow"],header:has([data-dcu-inline-tabs]) [class*="titleCluster"]{display:contents}
2297
2297
  header:has([data-dcu-inline-tabs]) [class*="crumbs"]{order:1;flex:0 1 auto;min-width:0}
@@ -6458,6 +6458,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
6458
6458
  if (marked !== null) return marked;
6459
6459
  for (const node of root.querySelectorAll("div")) if (parseSidebarGrid(node.style.gridTemplateColumns) !== void 0) return node;
6460
6460
  }
6461
+ /** Settings is portaled to body, so explicitly carry over the expanded width. */
6462
+ function settingsSidebarWidth(root) {
6463
+ const frame = findSidebarFrame(root);
6464
+ const expanded = Number.parseFloat(frame?.style.getPropertyValue("--dcu-sidebar-expanded-width") ?? "");
6465
+ if (Number.isFinite(expanded) && expanded >= 240) return expanded;
6466
+ const width = frame === void 0 ? void 0 : parseSidebarGrid(frame.style.gridTemplateColumns)?.sidebar;
6467
+ return width !== void 0 && width >= 240 ? width : 240;
6468
+ }
6461
6469
  /** 同步侧栏网格和拖拽柄,保证两者始终使用同一个可见宽度。 */
6462
6470
  function applySidebarWidth(frame, width) {
6463
6471
  const tracks = parseSidebarGrid(frame.style.gridTemplateColumns);
@@ -6981,21 +6989,21 @@ body[data-ds-dark-theme] [data-conversation-scroll] [data-trigger-menu]{backgrou
6981
6989
  body[data-we-sidebar-glass] .dcu-root{position:relative;background:transparent}body[data-we-sidebar-glass] .dcu-root::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background-color:color-mix(in srgb,var(--we-sidebar-color,#fff) calc(var(--we-sidebar-alpha,.15)*.66*100%),transparent);background-image:linear-gradient(180deg,rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.14)),rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.04)) 38%,rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.01)));-webkit-backdrop-filter:blur(var(--we-sidebar-blur,16px)) saturate(var(--we-sidebar-saturate,1.8)) brightness(var(--we-glass-brightness,1.04)) contrast(1.01);backdrop-filter:blur(var(--we-sidebar-blur,16px)) saturate(var(--we-sidebar-saturate,1.8)) brightness(var(--we-glass-brightness,1.04)) contrast(1.01);box-shadow:inset 0 1px 0 rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.32)),inset 0 -1px 0 rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.08)),inset 0 0 0 .5px rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.06))}body[data-ds-dark-theme][data-we-sidebar-glass] .dcu-root::before{background-color:color-mix(in srgb,var(--we-sidebar-color,#fff) calc(var(--we-sidebar-alpha,.15)*.33*100%),transparent)}body[data-we-appwindow][data-we-sidebar-glass] .dcu-root::before{-webkit-backdrop-filter:none;backdrop-filter:none}@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){body[data-we-sidebar-glass] .dcu-root{background:#eef7f5}body[data-ds-dark-theme][data-we-sidebar-glass] .dcu-root{background:#1d2120}body[data-we-sidebar-glass] .dcu-root::before{display:none}}
6982
6990
  body[data-we-sidebar-glass] .dcu-expanded-shell,body[data-we-sidebar-glass] .dcu-compact-shell,body[data-we-sidebar-glass] .dcu-foot{position:relative}
6983
6991
  .dcu-expanded-shell{display:flex;width:100%;min-height:0;flex:1 1 0;overflow:hidden;flex-direction:column;transform-origin:left center;transition:opacity 500ms cubic-bezier(.16,1,.3,1),transform 500ms cubic-bezier(.16,1,.3,1);animation:dcu-sidebar-expanded-in 500ms 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}}
6984
- .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}
6992
+ .dcu-root *{box-sizing:border-box}.dcu-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:8px;flex:none;height:var(--dcu-header-height,34px);padding:calc((var(--dcu-header-height,34px) - 28px)/2) 8px calc((var(--dcu-header-height,34px) - 28px)/2) 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}
6985
6993
  .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}
6986
6994
  .dcu-icon:hover,.dcu-menu button:hover:not(:disabled),.dcu-footer-link:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}
6987
6995
  .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}
6988
6996
  .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)}
6989
6997
  .dcu-extensions-group{display:grid}.dcu-extension-leading{position:relative;display:block;width:16px;height:16px}.dcu-extension-leading svg{position:absolute;inset:0;transition:opacity 140ms ease-out,transform 220ms cubic-bezier(.16,1,.3,1)}.dcu-extension-default-icon{opacity:1}.dcu-extension-state-arrow{opacity:0;transform:rotate(0)}.dcu-extensions-group:hover .dcu-extension-default-icon,.dcu-extensions-toggle:focus-visible .dcu-extension-default-icon{opacity:0}.dcu-extensions-group:hover .dcu-extension-state-arrow,.dcu-extensions-toggle:focus-visible .dcu-extension-state-arrow{opacity:1}.dcu-extensions-toggle[aria-expanded=true] .dcu-extension-state-arrow{transform:rotate(90deg)}.dcu-extension-panel{display:grid;grid-template-rows:1fr;opacity:1;transition:grid-template-rows 220ms cubic-bezier(.16,1,.3,1),opacity 160ms ease-out}.dcu-extension-panel[data-open=false]{grid-template-rows:0fr;opacity:0;pointer-events:none}.dcu-extension-panel-inner{position:relative;min-height:0;overflow:hidden}.dcu-extension-items{position:relative;display:grid;gap:1px;margin:1px 0 4px 28px}.dcu-extension-items::before{content:"";position:absolute;left:-16px;top:0;bottom:4px;width:1px;background:var(--dcu-sidebar-border)}.dcu-extension-items button{grid-template-columns:minmax(0,1fr);min-height:32px;color:var(--dcu-sidebar-secondary);font-size:13px;font-weight:400}.dcu-extension-items .dcu-menu-icon{display:none}
6990
- .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(--dsw-font-family);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(--dsw-font-family);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:100%;gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border);transition:opacity 500ms cubic-bezier(.16,1,.3,1),transform 500ms 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(--dsw-font-family);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}
6998
+ .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(--dsw-font-family);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(--dsw-font-family);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:100%;gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border);transition:opacity 500ms cubic-bezier(.16,1,.3,1),transform 500ms 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(--dsw-font-family);font-weight:400}.dcu-compact{width:100%;align-items:flex-start;overflow:hidden;padding:calc((var(--dcu-header-height,34px) - 28px)/2) 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}
6991
6999
  .dcu-settings-seat [data-slot="settings.trigger"]{color:var(--dcu-sidebar-navigation)}
6992
7000
  .dcu-settings-seat [data-slot="settings.trigger"]>svg{color:var(--dcu-sidebar-icon)}
6993
7001
  /* 宿主列负责缩放,宽态内容保持展开宽度,避免中文竖排与工作区逐帧重排。 */
6994
7002
  .dcu-expanded-shell,.dcu-root:not(.dcu-compact)>.dcu-foot{width:var(--dcu-sidebar-expanded-width,240px);flex-shrink:0}
6995
7003
  /* 对齐 Codex 的半秒布局节奏;显式声明避免依赖宿主主题的动画 token。 */
6996
7004
  .dcu-root{position:relative}
6997
- .dcu-root.dcu-collapsing .dcu-compact-shell{position:absolute;left:0;top:10px;bottom:8px;display:flex;flex-direction:column;align-items:center;animation:dcu-sidebar-compact-in 500ms cubic-bezier(.16,1,.3,1)}
6998
- .dcu-root.dcu-collapsing .dcu-compact-shell .dcu-icon{width:36px;height:36px;flex:none}
7005
+ .dcu-root.dcu-collapsing .dcu-compact-shell{position:absolute;left:0;top:calc((var(--dcu-header-height,34px) - 28px)/2);bottom:8px;display:flex;flex-direction:column;align-items:center;animation:dcu-sidebar-compact-in 500ms cubic-bezier(.16,1,.3,1)}
7006
+ .dcu-root.dcu-collapsing .dcu-compact-shell .dcu-icon{width:36px;height:36px;flex:none}.dcu-root .dcu-compact-shell>.dcu-icon,.dcu-root.dcu-collapsing .dcu-compact-shell>.dcu-icon{width:28px;height:28px;flex:none;margin:0;padding:0;border-radius:50%}
6999
7007
  /* 收尾仅移除宽态层,窄轨不重复淡入,否则会在半秒处闪烁。 */
7000
7008
  .dcu-root.dcu-compact .dcu-compact-shell{animation:none}
7001
7009
  [data-dcu-codex-sidebar-initialized]{transition:grid-template-columns 500ms cubic-bezier(.16,1,.3,1)}
@@ -7021,8 +7029,11 @@ body[data-ds-dark-theme] [data-conversation-scroll]{--dcu-composer-bg:var(--dsw-
7021
7029
  [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div>div{gap:4px}
7022
7030
  [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div>div>div{gap:4px}
7023
7031
  [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div :is(button,select):not([role]){min-height:28px;height:28px}
7024
- [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]{width:28px;transform:none;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base)}
7025
- [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]:hover:not(:disabled){background:var(--dsw-alias-label-secondary)}
7032
+ /* 保留 Codex 黑白发送键;使用独立主题颜色,避免壁纸的透明表面令牌影响 currentColor 箭头。 */
7033
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]{width:28px;transform:none;background:#0f1115;color:#fff}
7034
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]:hover:not(:disabled){background:#40434a}
7035
+ body[data-ds-dark-theme] [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]{background:#fff;color:#0f1115}
7036
+ body[data-ds-dark-theme] [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]:hover:not(:disabled){background:#d5d7dc}
7026
7037
  [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div :is(button,select):focus-visible{outline:2px solid var(--dsw-alias-label-secondary);outline-offset:2px}
7027
7038
  @supports(corner-shape:superellipse(1.5)){[data-conversation-scroll] [data-composer-card]{border-radius:25px;corner-shape:superellipse(1.5)}}
7028
7039
  @media(max-width:639px){[data-conversation-scroll]{--dcu-composer-shadow:0 0 0 1px #0000000a,0 2px 8px #0000000a,0 4px 40px 8px #00000006}}
@@ -7876,638 +7887,6 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7876
7887
  }
7877
7888
  CodexSidebar.displayName = "michengai-codex-ui";
7878
7889
  //#endregion
7879
- //#region src/dependencies.ts
7880
- const MANAGED_DEPENDENCIES = [
7881
- {
7882
- id: "ui",
7883
- packageName: "@michengai/dsh-codex-ui"
7884
- },
7885
- {
7886
- id: "experts",
7887
- packageName: "@michengai/dsh-agency-agents"
7888
- },
7889
- {
7890
- id: "skills",
7891
- packageName: "@michengai/dsh-skills-manager"
7892
- },
7893
- {
7894
- id: "archive",
7895
- packageName: "@michengai/dsh-archive-manager"
7896
- },
7897
- {
7898
- id: "im",
7899
- packageName: "@michengai/dsh-im-connect"
7900
- },
7901
- {
7902
- id: "schedule",
7903
- packageName: "@michengai/dsh-automation"
7904
- },
7905
- {
7906
- id: "btw",
7907
- packageName: "@michengai/dsh-btw"
7908
- },
7909
- {
7910
- id: "simplify",
7911
- packageName: "@michengai/dsh-simplify"
7912
- },
7913
- {
7914
- id: "pua",
7915
- packageName: "@michengai/dsh-pua"
7916
- },
7917
- {
7918
- id: "review",
7919
- packageName: "@michengai/dsh-code-review"
7920
- },
7921
- {
7922
- id: "pet",
7923
- packageName: "@michengai/dsh-codex-pet"
7924
- },
7925
- {
7926
- id: "market",
7927
- packageName: "dshmarket"
7928
- }
7929
- ];
7930
- //#endregion
7931
- //#region src/client/AboutSection.tsx
7932
- const PROJECT_HOMEPAGES = Object.fromEntries(MANAGED_DEPENDENCIES.map(({ id, packageName }) => [id, id === "market" ? "https://dshmarket.com" : `https://github.com/MichengAI/${packageName.split("/")[1]}`]));
7933
- const PROGRESS_PHASES = /* @__PURE__ */ new Set([
7934
- "resolving",
7935
- "downloading",
7936
- "linking",
7937
- "building"
7938
- ]);
7939
- const endpoint = CODEX_UI_API_ENDPOINTS.dependencies;
7940
- const stylesheet$2 = `
7941
- .dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:24px}.dcu-about-dependencies-heading h3{margin:0}.dcu-about-dependencies-heading+.dcu-about-intro{margin-bottom:14px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;line-height:20px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-update-all{min-width:92px}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}.dcu-about-progress{display:grid;grid-template-columns:auto 1fr auto;gap:8px 10px;align-items:center;margin-top:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px}.dcu-about-progress code{min-width:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-progress-pct{color:var(--dsw-alias-label-tertiary);font-size:12px;font-variant-numeric:tabular-nums}.dcu-about-progress-bar{grid-column:1/-1;height:4px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2)}.dcu-about-progress-fill{height:100%;background:var(--dsw-alias-state-business-primary);transition:width .2s ease}.dcu-about-progress-fill[data-wave=true]{width:28%;animation:dcu-about-progress-wave 1.2s ease-in-out infinite}@keyframes dcu-about-progress-wave{0%{transform:translateX(-60%)}100%{transform:translateX(280%)}}
7942
- .dcu-about-title-row{display:flex;align-items:center;gap:8px;min-width:0}.dcu-about-links{display:flex;align-items:center;gap:4px}.dcu-about-external-link{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dcu-about-external-link:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dcu-about-external-link:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dcu-about-external-link svg{flex:none}@media(max-width:720px){.dcu-about-title-row{flex-wrap:wrap}}
7943
- .dcu-about-version{margin-left:8px;color:var(--dsw-alias-label-tertiary);font-family:inherit;font-size:12px;font-weight:500;line-height:18px;letter-spacing:0;white-space:nowrap;vertical-align:baseline}
7944
- .dcu-about-project-link{color:inherit;text-decoration:none}.dcu-about-project-link:hover{text-decoration:underline;text-underline-offset:3px}.dcu-about-project-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;border-radius:2px}
7945
- .dcu-about-name-row{display:flex;align-items:center;gap:10px;min-width:0}.dcu-about-name-row .dcu-about-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-downloads{display:inline-flex;align-items:center;gap:4px;flex:none;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:20px;font-weight:400;font-variant-numeric:tabular-nums;text-decoration:none;white-space:nowrap}.dcu-about-downloads svg{flex:none;opacity:.75}.dcu-about-downloads:hover{color:var(--dsw-alias-label-primary)}.dcu-about-downloads:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px;border-radius:2px}@media(max-width:480px){.dcu-about-dependency{flex-wrap:wrap;gap:8px}.dcu-about-copy{flex-basis:100%}}
7946
- `;
7947
- /** 宿主图标库不提供 GitHub 品牌标识,内联后可离线使用并继承当前文字颜色。 */
7948
- function GithubMark16() {
7949
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
7950
- viewBox: "0 0 16 16",
7951
- width: 16,
7952
- height: 16,
7953
- "aria-hidden": "true",
7954
- focusable: "false",
7955
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
7956
- fill: "currentColor",
7957
- d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z"
7958
- })
7959
- });
7960
- }
7961
- function isDependencyStatus(value) {
7962
- if (value === null || typeof value !== "object") return false;
7963
- const status = value;
7964
- return MANAGED_DEPENDENCIES.some((dependency) => dependency.id === status.id) && typeof status.packageName === "string" && typeof status.installed === "boolean" && typeof status.updateAvailable === "boolean";
7965
- }
7966
- function isInstallProgress(value) {
7967
- if (value === null || typeof value !== "object") return false;
7968
- const progress = value;
7969
- const phase = progress.phase;
7970
- const total = progress.total;
7971
- const percent = progress.percent;
7972
- const currentPackage = progress.currentPackage;
7973
- return typeof progress.active === "boolean" && typeof progress.target === "string" && typeof progress.seconds === "number" && Number.isInteger(progress.seconds) && progress.seconds >= 0 && typeof progress.lastLine === "string" && (phase === null || typeof phase === "string" && PROGRESS_PHASES.has(phase)) && typeof progress.done === "number" && Number.isInteger(progress.done) && progress.done >= 0 && (total === null || typeof total === "number" && Number.isInteger(total) && total >= 0) && (percent === null || typeof percent === "number" && Number.isFinite(percent) && percent >= 0 && percent <= 100) && (currentPackage === null || typeof currentPackage === "string");
7974
- }
7975
- function progressLabel(progress, t) {
7976
- if (progress.phase !== null) {
7977
- const current = progress.currentPackage === null || progress.currentPackage === "" ? "" : ` · ${progress.currentPackage}`;
7978
- const done = progress.done > 0 ? ` · ${t("about.packagesDone").replace("{0}", String(progress.done))}` : "";
7979
- return `${t(`about.progress.${progress.phase}`)}${current}${done}`;
7980
- }
7981
- if (progress.lastLine !== "") return `${progress.lastLine} (${progress.seconds}s)`;
7982
- return t("about.progressHint");
7983
- }
7984
- /** Codex UI 的功能说明、配套管理插件状态与受限安装入口。 */
7985
- function AboutSection({ t }) {
7986
- const [dependencies, setDependencies] = (0, react.useState)([]);
7987
- const [state, setState] = (0, react.useState)("loading");
7988
- const [installing, setInstalling] = (0, react.useState)();
7989
- const [progress, setProgress] = (0, react.useState)();
7990
- const [message, setMessage] = (0, react.useState)();
7991
- const [refreshFailed, setRefreshFailed] = (0, react.useState)(false);
7992
- const [loadFailure, setLoadFailure] = (0, react.useState)();
7993
- const alive = (0, react.useRef)(true);
7994
- const root = (0, react.useRef)(null);
7995
- const stateRef = (0, react.useRef)("loading");
7996
- const requestId = (0, react.useRef)(0);
7997
- const installingRef = (0, react.useRef)();
7998
- stateRef.current = state;
7999
- (0, react.useEffect)(() => {
8000
- alive.current = true;
8001
- return () => {
8002
- alive.current = false;
8003
- };
8004
- }, []);
8005
- const load = (0, react.useCallback)(async (signal) => {
8006
- const currentRequest = ++requestId.current;
8007
- if (stateRef.current !== "ready") setState("loading");
8008
- try {
8009
- const response = await fetch(endpoint, {
8010
- cache: "no-store",
8011
- signal
8012
- });
8013
- if (!response.ok) throw new BusinessRequestError(response.status);
8014
- const payload = await response.json();
8015
- if (signal?.aborted || currentRequest !== requestId.current) return;
8016
- if (!Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error();
8017
- setDependencies(payload.dependencies);
8018
- setState("ready");
8019
- setRefreshFailed(false);
8020
- setLoadFailure(void 0);
8021
- } catch (error) {
8022
- if (signal?.aborted || error instanceof DOMException && error.name === "AbortError" || currentRequest !== requestId.current) return;
8023
- setLoadFailure(error);
8024
- if (stateRef.current === "ready") setRefreshFailed(true);
8025
- else setState("failed");
8026
- }
8027
- }, []);
8028
- (0, react.useEffect)(() => {
8029
- const node = root.current;
8030
- const controller = new AbortController();
8031
- const refresh = () => {
8032
- load(controller.signal);
8033
- };
8034
- refresh();
8035
- if (node === null || typeof IntersectionObserver === "undefined") return () => {
8036
- controller.abort();
8037
- };
8038
- let initialized = false;
8039
- let wasVisible = false;
8040
- const observer = new IntersectionObserver((entries) => {
8041
- const visible = entries.some((entry) => entry.isIntersecting);
8042
- if (!initialized) {
8043
- initialized = true;
8044
- wasVisible = visible;
8045
- return;
8046
- }
8047
- if (visible && !wasVisible) refresh();
8048
- wasVisible = visible;
8049
- }, { threshold: .2 });
8050
- observer.observe(node);
8051
- return () => {
8052
- controller.abort();
8053
- observer.disconnect();
8054
- };
8055
- }, [load]);
8056
- (0, react.useEffect)(() => {
8057
- if (installing === void 0) {
8058
- setProgress(void 0);
8059
- return;
8060
- }
8061
- let cancelled = false;
8062
- const pull = async () => {
8063
- try {
8064
- const response = await fetch(`${endpoint}?action=progress`, { cache: "no-store" });
8065
- const payload = await response.json();
8066
- if (cancelled || !response.ok || !isInstallProgress(payload.progress)) return;
8067
- setProgress(payload.progress);
8068
- } catch {
8069
- if (!cancelled) return;
8070
- }
8071
- };
8072
- pull();
8073
- const timer = window.setInterval(() => {
8074
- pull();
8075
- }, 800);
8076
- return () => {
8077
- cancelled = true;
8078
- window.clearInterval(timer);
8079
- };
8080
- }, [installing]);
8081
- const install = async (id) => {
8082
- if (installingRef.current !== void 0) return;
8083
- installingRef.current = id;
8084
- setInstalling(id);
8085
- setMessage(void 0);
8086
- try {
8087
- const response = await fetch(`${endpoint}?dependency=${encodeURIComponent(id)}`, { method: "POST" });
8088
- if ([
8089
- 401,
8090
- 403,
8091
- 503
8092
- ].includes(response.status)) throw new BusinessRequestError(response.status);
8093
- const payload = await response.json();
8094
- if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error(typeof payload.error === "string" ? payload.error : t("about.installFailed"));
8095
- if (!alive.current) return;
8096
- setDependencies(payload.dependencies);
8097
- setState("ready");
8098
- setRefreshFailed(false);
8099
- setMessage({
8100
- error: false,
8101
- text: payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
8102
- });
8103
- } catch (error) {
8104
- if (!alive.current) return;
8105
- setMessage({
8106
- error: true,
8107
- text: installErrorText(error, t)
8108
- });
8109
- } finally {
8110
- installingRef.current = void 0;
8111
- if (alive.current) setInstalling(void 0);
8112
- }
8113
- };
8114
- const updateAll = async () => {
8115
- if (installingRef.current !== void 0) return;
8116
- installingRef.current = "all";
8117
- setInstalling("all");
8118
- setMessage(void 0);
8119
- try {
8120
- const response = await fetch(`${endpoint}?action=update-all`, { method: "POST" });
8121
- if ([
8122
- 401,
8123
- 403,
8124
- 503
8125
- ].includes(response.status)) throw new BusinessRequestError(response.status);
8126
- const payload = await response.json();
8127
- if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error(typeof payload.error === "string" ? payload.error : t("about.installFailed"));
8128
- if (!alive.current) return;
8129
- setDependencies(payload.dependencies);
8130
- setState("ready");
8131
- setRefreshFailed(false);
8132
- setMessage({
8133
- error: false,
8134
- text: payload.restartRequired === false ? t("about.upToDate") : payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
8135
- });
8136
- } catch (error) {
8137
- if (!alive.current) return;
8138
- setMessage({
8139
- error: true,
8140
- text: installErrorText(error, t)
8141
- });
8142
- } finally {
8143
- installingRef.current = void 0;
8144
- if (alive.current) setInstalling(void 0);
8145
- }
8146
- };
8147
- const actionableCount = dependencies.filter((dependency) => !dependency.installed || dependency.updateAvailable).length;
8148
- const selfVersion = dependencies.find((dependency) => dependency.id === "ui")?.version;
8149
- const title = (id) => t(`about.dependency.${id}`);
8150
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8151
- ref: root,
8152
- className: "dcu-about",
8153
- "aria-label": t("about.nav"),
8154
- children: [
8155
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$2 }),
8156
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8157
- className: "dcu-about-title-row",
8158
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [t("about.title"), selfVersion === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8159
- className: "dcu-about-version",
8160
- children: ["v", selfVersion]
8161
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8162
- className: "dcu-about-links",
8163
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8164
- className: "dcu-about-external-link",
8165
- href: "https://github.com/MichengAI/dsh-codex-ui",
8166
- target: "_blank",
8167
- rel: "noreferrer",
8168
- "aria-label": t("about.viewProject"),
8169
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GithubMark16, {}), t("about.viewProject")]
8170
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8171
- className: "dcu-about-external-link",
8172
- href: "https://github.com/MichengAI/dsh-codex-ui/issues",
8173
- target: "_blank",
8174
- rel: "noreferrer",
8175
- "aria-label": t("about.feedback"),
8176
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconListPenOutlineMedium, {}), t("about.feedback")]
8177
- })]
8178
- })]
8179
- }),
8180
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8181
- className: "dcu-about-intro",
8182
- children: t("about.description")
8183
- }),
8184
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("about.features") }),
8185
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
8186
- className: "dcu-about-features",
8187
- children: [
8188
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.sidebar") }),
8189
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.search") }),
8190
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.workspace") }),
8191
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.sessions") }),
8192
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.conversation") }),
8193
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.navigator") })
8194
- ]
8195
- }),
8196
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8197
- className: "dcu-about-dependencies-heading",
8198
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("about.dependencies") }), state === "ready" && actionableCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8199
- className: "dcu-about-install dcu-about-update-all",
8200
- type: "button",
8201
- "aria-busy": installing === "all",
8202
- disabled: installing !== void 0,
8203
- onClick: () => {
8204
- updateAll();
8205
- },
8206
- children: [installing === "all" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, { size: 14 }), installing === "all" ? t("about.updatingAll") : t("about.updateAll")]
8207
- })]
8208
- }),
8209
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8210
- className: "dcu-about-intro",
8211
- children: t("about.dependenciesDescription")
8212
- }),
8213
- state === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8214
- className: "dcu-about-message",
8215
- role: "status",
8216
- children: t("about.loading")
8217
- }) : state === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8218
- className: "dcu-about-message",
8219
- "data-error": "true",
8220
- role: "alert",
8221
- children: t(businessRequestErrorKey(loadFailure) ?? "about.statusFailed")
8222
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8223
- className: "dcu-about-dependencies",
8224
- "aria-busy": installing !== void 0,
8225
- children: dependencies.map((dependency) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
8226
- className: "dcu-about-dependency",
8227
- children: [
8228
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8229
- className: "dcu-about-copy",
8230
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8231
- className: "dcu-about-name-row",
8232
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8233
- className: "dcu-about-name dcu-about-project-link",
8234
- href: PROJECT_HOMEPAGES[dependency.id],
8235
- target: "_blank",
8236
- rel: "noreferrer",
8237
- children: title(dependency.id)
8238
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8239
- className: "dcu-about-downloads",
8240
- href: `https://www.npmjs.com/package/${dependency.packageName}`,
8241
- target: "_blank",
8242
- rel: "noreferrer",
8243
- title: t("about.downloadsSource"),
8244
- "aria-label": `${dependency.packageName} · ${t("about.totalDownloads")} · ${typeof dependency.totalDownloads === "number" && Number.isSafeInteger(dependency.totalDownloads) && dependency.totalDownloads >= 0 ? dependency.totalDownloads.toLocaleString() : t("about.downloadsUnavailable")}`,
8245
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, {
8246
- size: 12,
8247
- "aria-hidden": "true"
8248
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8249
- className: "dcu-about-downloads-count",
8250
- children: typeof dependency.totalDownloads === "number" && Number.isSafeInteger(dependency.totalDownloads) && dependency.totalDownloads >= 0 ? dependency.totalDownloads.toLocaleString() : "—"
8251
- })]
8252
- })]
8253
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8254
- className: "dcu-about-package",
8255
- title: dependency.packageName,
8256
- children: [
8257
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8258
- className: "dcu-about-project-link",
8259
- href: PROJECT_HOMEPAGES[dependency.id],
8260
- target: "_blank",
8261
- rel: "noreferrer",
8262
- children: dependency.packageName
8263
- }),
8264
- dependency.version === void 0 ? "" : ` · ${dependency.version}`,
8265
- dependency.updateAvailable && dependency.latestVersion !== void 0 ? ` → ${dependency.latestVersion}` : ""
8266
- ]
8267
- })]
8268
- }),
8269
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8270
- className: "dcu-about-status",
8271
- "data-installed": dependency.installed,
8272
- "data-update": dependency.updateAvailable,
8273
- children: [dependency.installed && !dependency.updateAvailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheckOutlineMedium, { size: 14 }), dependency.updateAvailable ? t("about.updateAvailable") : dependency.installed ? t("about.installed") : t("about.missing")]
8274
- }),
8275
- (!dependency.installed || dependency.updateAvailable) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8276
- className: "dcu-about-install",
8277
- type: "button",
8278
- disabled: installing !== void 0,
8279
- onClick: () => {
8280
- install(dependency.id);
8281
- },
8282
- children: [installing === dependency.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, { size: 14 }), installing === dependency.id ? t("about.installing") : dependency.updateAvailable ? t("about.update") : t("about.install")]
8283
- })
8284
- ]
8285
- }, dependency.id))
8286
- }),
8287
- installing !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8288
- className: "dcu-about-progress",
8289
- role: "status",
8290
- children: [
8291
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) }),
8292
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: progress === void 0 ? t("about.progressHint") : progressLabel(progress, t) }),
8293
- progress?.percent !== null && progress?.percent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8294
- className: "dcu-about-progress-pct",
8295
- children: [progress.percent, "%"]
8296
- }),
8297
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8298
- className: "dcu-about-progress-bar",
8299
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8300
- className: "dcu-about-progress-fill",
8301
- "data-wave": progress?.percent === null || progress?.percent === void 0,
8302
- style: progress?.percent === null || progress?.percent === void 0 ? void 0 : { width: `${progress.percent}%` }
8303
- })
8304
- })
8305
- ]
8306
- }),
8307
- refreshFailed && state === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8308
- className: "dcu-about-message",
8309
- "data-error": "true",
8310
- role: "status",
8311
- children: t(businessRequestErrorKey(loadFailure) ?? "about.refreshFailed")
8312
- }),
8313
- message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8314
- className: "dcu-about-message",
8315
- "data-error": message.error,
8316
- role: message.error ? "alert" : "status",
8317
- children: message.text
8318
- })
8319
- ]
8320
- });
8321
- }
8322
- //#endregion
8323
- //#region src/client/ConnectorsSection.tsx
8324
- const MCP_CONNECTOR_UI = "/mcp-connector/ui/";
8325
- const PROMPT_REQUEST_TYPE = "mcp-connector:start-session";
8326
- const PROMPT_RESULT_TYPE = "mcp-connector:start-session-result";
8327
- const stylesheet$1 = `
8328
- .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}
8329
- `;
8330
- const frameLightTheme = `:root{color-scheme:light;--bg:#fff;--card:#fafafa;--line:#e5e5e5;--text:#303030;--text-2:#737373;--muted:#767676;--accent:#303030;--accent-hover:#171717;--accent-light:#e9e9e9;--dcu-action:#303030;--dcu-action-hover:#171717;--dcu-on-action:#fff;--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)}`;
8331
- const frameDarkTheme = `:root{color-scheme:dark;--bg:#181818;--card:#232323;--line:#333;--text:#dedede;--text-2:#a1a1a1;--muted:#929292;--accent:#dedede;--accent-hover:#fff;--accent-light:#303332;--dcu-action:#383838;--dcu-action-hover:#454545;--dcu-on-action:#eee;--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)}`;
8332
- const frameSurfaceTheme = `
8333
- .card.featured{border-color:var(--line)}
8334
- .card:hover,.card.featured:hover{border-color:var(--muted)}
8335
- .btn:not(.ghost):not(.danger):not(.status-warning):not(.status-bad),.icon-btn.primary,.btn-primary,.prompt-item .send-btn{background:var(--dcu-action);border-color:var(--dcu-action);color:var(--dcu-on-action)}
8336
- .btn:not(.ghost):not(.danger):not(.status-warning):not(.status-bad):hover,.icon-btn.primary:hover,.btn-primary:hover,.prompt-item .send-btn:hover{background:var(--dcu-action-hover);border-color:var(--dcu-action-hover)}
8337
- `;
8338
- function isConnector(value) {
8339
- if (value === null || typeof value !== "object") return false;
8340
- const item = value;
8341
- 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");
8342
- }
8343
- function isPromptRequest(value) {
8344
- if (value === null || typeof value !== "object") return false;
8345
- const item = value;
8346
- return item.type === PROMPT_REQUEST_TYPE && typeof item.requestId === "string" && item.requestId !== "" && typeof item.prompt === "string" && item.prompt.trim() !== "";
8347
- }
8348
- function syncFrameTheme(frame) {
8349
- const doc = frame?.contentDocument;
8350
- if (doc === null || doc === void 0) return;
8351
- let style = doc.head.querySelector("style[data-michengai-host-theme]");
8352
- if (style === null) {
8353
- style = doc.createElement("style");
8354
- style.dataset.michengaiHostTheme = "true";
8355
- doc.head.append(style);
8356
- }
8357
- style.textContent = (document.body.hasAttribute("data-ds-dark-theme") ? frameDarkTheme : frameLightTheme) + frameSurfaceTheme;
8358
- }
8359
- function ConnectorMarket({ startPromptSession, t }) {
8360
- const frameRef = (0, react.useRef)(null);
8361
- (0, react.useEffect)(() => {
8362
- const onMessage = (event) => {
8363
- const frameWindow = frameRef.current?.contentWindow;
8364
- if (event.origin !== window.location.origin || frameWindow === null || frameWindow === void 0 || event.source !== frameWindow) return;
8365
- if (!isPromptRequest(event.data)) return;
8366
- const { requestId, prompt } = event.data;
8367
- const reply = (ok, message) => {
8368
- frameWindow.postMessage({
8369
- type: PROMPT_RESULT_TYPE,
8370
- requestId,
8371
- ok,
8372
- message
8373
- }, window.location.origin);
8374
- };
8375
- startPromptSession(prompt).then(() => {
8376
- reply(true, t("connectors.promptReady"));
8377
- }, (error) => {
8378
- reply(false, userErrorText(error, t));
8379
- });
8380
- };
8381
- const syncTheme = () => {
8382
- syncFrameTheme(frameRef.current);
8383
- };
8384
- const observer = new MutationObserver(syncTheme);
8385
- observer.observe(document.body, {
8386
- attributes: true,
8387
- attributeFilter: ["data-ds-dark-theme"]
8388
- });
8389
- window.addEventListener("message", onMessage);
8390
- return () => {
8391
- observer.disconnect();
8392
- window.removeEventListener("message", onMessage);
8393
- };
8394
- }, [startPromptSession, t]);
8395
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
8396
- ref: frameRef,
8397
- className: "dcu-connector-frame",
8398
- src: MCP_CONNECTOR_UI,
8399
- title: t("connectors.title"),
8400
- onLoad: () => {
8401
- syncFrameTheme(frameRef.current);
8402
- }
8403
- });
8404
- }
8405
- function NativeConnectorList({ sessionStore, t }) {
8406
- const sessionId = (0, react.useSyncExternalStore)(sessionStore.subscribe, () => currentSessionId(sessionStore.getSnapshot()));
8407
- const [connectors, setConnectors] = (0, react.useState)([]);
8408
- const [state, setState] = (0, react.useState)("loading");
8409
- const [failure, setFailure] = (0, react.useState)();
8410
- (0, react.useEffect)(() => {
8411
- if (sessionId === void 0) {
8412
- setConnectors([]);
8413
- setState("ready");
8414
- return;
8415
- }
8416
- const controller = new AbortController();
8417
- setState("loading");
8418
- fetch(`${CODEX_UI_API_ENDPOINTS.connectors}?sessionId=${encodeURIComponent(sessionId)}`, { signal: controller.signal }).then(async (response) => {
8419
- if (!response.ok) throw new BusinessRequestError(response.status);
8420
- const payload = await response.json();
8421
- if (!Array.isArray(payload.connectors) || !payload.connectors.every(isConnector)) throw new Error("连接器目录返回格式无效。");
8422
- if (!controller.signal.aborted) setConnectors(payload.connectors);
8423
- }).then(() => {
8424
- if (!controller.signal.aborted) setState("ready");
8425
- }).catch((error) => {
8426
- if (!controller.signal.aborted) {
8427
- setFailure(error);
8428
- setState("failed");
8429
- }
8430
- });
8431
- return () => {
8432
- controller.abort();
8433
- };
8434
- }, [sessionId]);
8435
- if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8436
- className: "dcu-connector-empty",
8437
- children: t("connectors.openSession")
8438
- });
8439
- if (state === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8440
- className: "dcu-connector-empty",
8441
- children: t("connectors.loading")
8442
- });
8443
- if (state === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8444
- className: "dcu-connector-empty",
8445
- role: "alert",
8446
- children: t(businessRequestErrorKey(failure) ?? "connectors.failed")
8447
- });
8448
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8449
- className: "dcu-connector-list",
8450
- children: [connectors.map((connector) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
8451
- className: "dcu-connector",
8452
- children: [
8453
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8454
- className: "dcu-connector-head",
8455
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLinkOutlineMedium, { size: 16 }), connector.name]
8456
- }),
8457
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8458
- className: "dcu-connector-meta",
8459
- children: t("connectors.toolCount", { count: connector.tools.length })
8460
- }),
8461
- connector.tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8462
- className: "dcu-connector-tool",
8463
- children: [tool.name, tool.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tool.description })]
8464
- }, tool.name))
8465
- ]
8466
- }, connector.name)), connectors.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8467
- className: "dcu-connector-empty",
8468
- children: t("connectors.empty")
8469
- })]
8470
- });
8471
- }
8472
- /** 安装 dsh-mcp-connector 时显示完整市场,否则回退到当前会话的 MCP 工具目录。 */
8473
- function ConnectorsSection({ sessionStore, startPromptSession, t }) {
8474
- const [marketAvailable, setMarketAvailable] = (0, react.useState)();
8475
- (0, react.useEffect)(() => {
8476
- const controller = new AbortController();
8477
- fetch(MCP_CONNECTOR_UI, {
8478
- method: "GET",
8479
- cache: "no-store",
8480
- signal: controller.signal
8481
- }).then((response) => {
8482
- response.body?.cancel().catch(() => {});
8483
- if (!controller.signal.aborted) setMarketAvailable(response.ok);
8484
- }).catch(() => {
8485
- if (!controller.signal.aborted) setMarketAvailable(false);
8486
- });
8487
- return () => {
8488
- controller.abort();
8489
- };
8490
- }, []);
8491
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8492
- className: "dcu-connectors",
8493
- "aria-label": t("connectors.title"),
8494
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$1 }), marketAvailable === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8495
- className: "dcu-connector-empty",
8496
- children: t("connectors.loading")
8497
- }) : marketAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorMarket, {
8498
- startPromptSession,
8499
- t
8500
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8501
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("connectors.title") }),
8502
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("connectors.description") }),
8503
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeConnectorList, {
8504
- sessionStore,
8505
- t
8506
- })
8507
- ] })]
8508
- });
8509
- }
8510
- //#endregion
8511
7890
  //#region src/client/locales.ts
8512
7891
  /** 本插件独占的界面文案命名空间。 */
8513
7892
  const NS = "michengai.codexUi";
@@ -9079,6 +8458,688 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
9079
8458
  "sessionTitle.type.research": "Research",
9080
8459
  "meta.locale": "en-US"
9081
8460
  };
8461
+ //#endregion
8462
+ //#region src/client/SidebarExpandControl.tsx
8463
+ const SIDEBAR_EXPAND_STYLE = `
8464
+ .dcu-shell-expand{appearance:none;border:0;background:transparent;color:var(--dsw-alias-label-secondary);display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border-radius:50%;cursor:pointer;-webkit-app-region:no-drag}
8465
+ .dcu-shell-expand svg{display:block;width:16px;height:16px}
8466
+ .dcu-shell-expand:hover{background:var(--dsw-alias-interactive-bg-hover)}
8467
+ .dcu-shell-expand:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}
8468
+ .dcu-shell-expand-windows{display:none;position:fixed;left:12px;top:calc((var(--dsh-windows-titlebar-height,40px) - 28px) / 2);z-index:30}
8469
+ html[data-windows-titlebar] [data-sidebar-collapsed] [data-shell-overlay] .dcu-shell-expand-windows{display:inline-flex}
8470
+ html[data-windows-titlebar]:has([data-sidebar-collapsed] .dcu-shell-expand-windows){--dsh-windows-menu-start:48px}
8471
+ html[data-windows-titlebar][data-fullscreen] .dcu-shell-expand-windows{top:3px}
8472
+ html[data-windows-titlebar][data-fullscreen] [data-sidebar-collapsed]{--dsh-frame-leading-clearance:60px}
8473
+ html[data-windows-titlebar][data-fullscreen] [data-sidebar-collapsed] header:has([data-dcu-inline-tabs]){padding-inline-start:60px}
8474
+ `;
8475
+ /** The host mounts shell.leading only for a collapsed macOS sidebar. Windows
8476
+ * uses shell.overlay so the caption button survives the zero-width column. */
8477
+ function SidebarExpandControl({ toggleSidebar, t, windows = false }) {
8478
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: SIDEBAR_EXPAND_STYLE }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8479
+ type: "button",
8480
+ className: `dcu-shell-expand${windows ? " dcu-shell-expand-windows" : ""}`,
8481
+ "aria-label": t("sidebar.expand"),
8482
+ onClick: toggleSidebar,
8483
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconPanelLeftOutlineMedium, { size: 16 })
8484
+ })] });
8485
+ }
8486
+ function registerSidebarExpandControls(ctx) {
8487
+ ctx.slots.inject("shell.leading", () => ctx.slots.register({
8488
+ name: "shell.leading",
8489
+ registrant: "michengai-codex-ui",
8490
+ locale: NS,
8491
+ inject: () => ({
8492
+ toggleSidebar: () => {
8493
+ ctx.layout.toggleSidebar();
8494
+ },
8495
+ windows: false
8496
+ })
8497
+ }, SidebarExpandControl));
8498
+ ctx.slots.inject("shell.overlay", () => ctx.slots.register({
8499
+ name: "shell.overlay",
8500
+ id: "michengai-codex-ui-sidebar-expand",
8501
+ registrant: "michengai-codex-ui",
8502
+ locale: NS,
8503
+ inject: () => ({
8504
+ toggleSidebar: () => {
8505
+ ctx.layout.toggleSidebar();
8506
+ },
8507
+ windows: true
8508
+ })
8509
+ }, SidebarExpandControl));
8510
+ }
8511
+ //#endregion
8512
+ //#region src/dependencies.ts
8513
+ const MANAGED_DEPENDENCIES = [
8514
+ {
8515
+ id: "ui",
8516
+ packageName: "@michengai/dsh-codex-ui"
8517
+ },
8518
+ {
8519
+ id: "experts",
8520
+ packageName: "@michengai/dsh-agency-agents"
8521
+ },
8522
+ {
8523
+ id: "skills",
8524
+ packageName: "@michengai/dsh-skills-manager"
8525
+ },
8526
+ {
8527
+ id: "archive",
8528
+ packageName: "@michengai/dsh-archive-manager"
8529
+ },
8530
+ {
8531
+ id: "im",
8532
+ packageName: "@michengai/dsh-im-connect"
8533
+ },
8534
+ {
8535
+ id: "schedule",
8536
+ packageName: "@michengai/dsh-automation"
8537
+ },
8538
+ {
8539
+ id: "btw",
8540
+ packageName: "@michengai/dsh-btw"
8541
+ },
8542
+ {
8543
+ id: "simplify",
8544
+ packageName: "@michengai/dsh-simplify"
8545
+ },
8546
+ {
8547
+ id: "pua",
8548
+ packageName: "@michengai/dsh-pua"
8549
+ },
8550
+ {
8551
+ id: "review",
8552
+ packageName: "@michengai/dsh-code-review"
8553
+ },
8554
+ {
8555
+ id: "pet",
8556
+ packageName: "@michengai/dsh-codex-pet"
8557
+ },
8558
+ {
8559
+ id: "market",
8560
+ packageName: "dshmarket"
8561
+ }
8562
+ ];
8563
+ //#endregion
8564
+ //#region src/client/AboutSection.tsx
8565
+ const PROJECT_HOMEPAGES = Object.fromEntries(MANAGED_DEPENDENCIES.map(({ id, packageName }) => [id, id === "market" ? "https://dshmarket.com" : `https://github.com/MichengAI/${packageName.split("/")[1]}`]));
8566
+ const PROGRESS_PHASES = /* @__PURE__ */ new Set([
8567
+ "resolving",
8568
+ "downloading",
8569
+ "linking",
8570
+ "building"
8571
+ ]);
8572
+ const endpoint = CODEX_UI_API_ENDPOINTS.dependencies;
8573
+ const stylesheet$2 = `
8574
+ .dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:24px}.dcu-about-dependencies-heading h3{margin:0}.dcu-about-dependencies-heading+.dcu-about-intro{margin-bottom:14px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;line-height:20px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-update-all{min-width:92px}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}.dcu-about-progress{display:grid;grid-template-columns:auto 1fr auto;gap:8px 10px;align-items:center;margin-top:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px}.dcu-about-progress code{min-width:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-progress-pct{color:var(--dsw-alias-label-tertiary);font-size:12px;font-variant-numeric:tabular-nums}.dcu-about-progress-bar{grid-column:1/-1;height:4px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2)}.dcu-about-progress-fill{height:100%;background:var(--dsw-alias-state-business-primary);transition:width .2s ease}.dcu-about-progress-fill[data-wave=true]{width:28%;animation:dcu-about-progress-wave 1.2s ease-in-out infinite}@keyframes dcu-about-progress-wave{0%{transform:translateX(-60%)}100%{transform:translateX(280%)}}
8575
+ .dcu-about-title-row{display:flex;align-items:center;gap:8px;min-width:0}.dcu-about-links{display:flex;align-items:center;gap:4px}.dcu-about-external-link{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dcu-about-external-link:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dcu-about-external-link:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dcu-about-external-link svg{flex:none}@media(max-width:720px){.dcu-about-title-row{flex-wrap:wrap}}
8576
+ .dcu-about-version{margin-left:8px;color:var(--dsw-alias-label-tertiary);font-family:inherit;font-size:12px;font-weight:500;line-height:18px;letter-spacing:0;white-space:nowrap;vertical-align:baseline}
8577
+ .dcu-about-project-link{color:inherit;text-decoration:none}.dcu-about-project-link:hover{text-decoration:underline;text-underline-offset:3px}.dcu-about-project-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;border-radius:2px}
8578
+ .dcu-about-name-row{display:flex;align-items:center;gap:10px;min-width:0}.dcu-about-name-row .dcu-about-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-downloads{display:inline-flex;align-items:center;gap:4px;flex:none;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:20px;font-weight:400;font-variant-numeric:tabular-nums;text-decoration:none;white-space:nowrap}.dcu-about-downloads svg{flex:none;opacity:.75}.dcu-about-downloads:hover{color:var(--dsw-alias-label-primary)}.dcu-about-downloads:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px;border-radius:2px}@media(max-width:480px){.dcu-about-dependency{flex-wrap:wrap;gap:8px}.dcu-about-copy{flex-basis:100%}}
8579
+ `;
8580
+ /** 宿主图标库不提供 GitHub 品牌标识,内联后可离线使用并继承当前文字颜色。 */
8581
+ function GithubMark16() {
8582
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
8583
+ viewBox: "0 0 16 16",
8584
+ width: 16,
8585
+ height: 16,
8586
+ "aria-hidden": "true",
8587
+ focusable: "false",
8588
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
8589
+ fill: "currentColor",
8590
+ d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z"
8591
+ })
8592
+ });
8593
+ }
8594
+ function isDependencyStatus(value) {
8595
+ if (value === null || typeof value !== "object") return false;
8596
+ const status = value;
8597
+ return MANAGED_DEPENDENCIES.some((dependency) => dependency.id === status.id) && typeof status.packageName === "string" && typeof status.installed === "boolean" && typeof status.updateAvailable === "boolean";
8598
+ }
8599
+ function isInstallProgress(value) {
8600
+ if (value === null || typeof value !== "object") return false;
8601
+ const progress = value;
8602
+ const phase = progress.phase;
8603
+ const total = progress.total;
8604
+ const percent = progress.percent;
8605
+ const currentPackage = progress.currentPackage;
8606
+ return typeof progress.active === "boolean" && typeof progress.target === "string" && typeof progress.seconds === "number" && Number.isInteger(progress.seconds) && progress.seconds >= 0 && typeof progress.lastLine === "string" && (phase === null || typeof phase === "string" && PROGRESS_PHASES.has(phase)) && typeof progress.done === "number" && Number.isInteger(progress.done) && progress.done >= 0 && (total === null || typeof total === "number" && Number.isInteger(total) && total >= 0) && (percent === null || typeof percent === "number" && Number.isFinite(percent) && percent >= 0 && percent <= 100) && (currentPackage === null || typeof currentPackage === "string");
8607
+ }
8608
+ function progressLabel(progress, t) {
8609
+ if (progress.phase !== null) {
8610
+ const current = progress.currentPackage === null || progress.currentPackage === "" ? "" : ` · ${progress.currentPackage}`;
8611
+ const done = progress.done > 0 ? ` · ${t("about.packagesDone").replace("{0}", String(progress.done))}` : "";
8612
+ return `${t(`about.progress.${progress.phase}`)}${current}${done}`;
8613
+ }
8614
+ if (progress.lastLine !== "") return `${progress.lastLine} (${progress.seconds}s)`;
8615
+ return t("about.progressHint");
8616
+ }
8617
+ /** Codex UI 的功能说明、配套管理插件状态与受限安装入口。 */
8618
+ function AboutSection({ t }) {
8619
+ const [dependencies, setDependencies] = (0, react.useState)([]);
8620
+ const [state, setState] = (0, react.useState)("loading");
8621
+ const [installing, setInstalling] = (0, react.useState)();
8622
+ const [progress, setProgress] = (0, react.useState)();
8623
+ const [message, setMessage] = (0, react.useState)();
8624
+ const [refreshFailed, setRefreshFailed] = (0, react.useState)(false);
8625
+ const [loadFailure, setLoadFailure] = (0, react.useState)();
8626
+ const alive = (0, react.useRef)(true);
8627
+ const root = (0, react.useRef)(null);
8628
+ const stateRef = (0, react.useRef)("loading");
8629
+ const requestId = (0, react.useRef)(0);
8630
+ const installingRef = (0, react.useRef)();
8631
+ stateRef.current = state;
8632
+ (0, react.useEffect)(() => {
8633
+ alive.current = true;
8634
+ return () => {
8635
+ alive.current = false;
8636
+ };
8637
+ }, []);
8638
+ const load = (0, react.useCallback)(async (signal) => {
8639
+ const currentRequest = ++requestId.current;
8640
+ if (stateRef.current !== "ready") setState("loading");
8641
+ try {
8642
+ const response = await fetch(endpoint, {
8643
+ cache: "no-store",
8644
+ signal
8645
+ });
8646
+ if (!response.ok) throw new BusinessRequestError(response.status);
8647
+ const payload = await response.json();
8648
+ if (signal?.aborted || currentRequest !== requestId.current) return;
8649
+ if (!Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error();
8650
+ setDependencies(payload.dependencies);
8651
+ setState("ready");
8652
+ setRefreshFailed(false);
8653
+ setLoadFailure(void 0);
8654
+ } catch (error) {
8655
+ if (signal?.aborted || error instanceof DOMException && error.name === "AbortError" || currentRequest !== requestId.current) return;
8656
+ setLoadFailure(error);
8657
+ if (stateRef.current === "ready") setRefreshFailed(true);
8658
+ else setState("failed");
8659
+ }
8660
+ }, []);
8661
+ (0, react.useEffect)(() => {
8662
+ const node = root.current;
8663
+ const controller = new AbortController();
8664
+ const refresh = () => {
8665
+ load(controller.signal);
8666
+ };
8667
+ refresh();
8668
+ if (node === null || typeof IntersectionObserver === "undefined") return () => {
8669
+ controller.abort();
8670
+ };
8671
+ let initialized = false;
8672
+ let wasVisible = false;
8673
+ const observer = new IntersectionObserver((entries) => {
8674
+ const visible = entries.some((entry) => entry.isIntersecting);
8675
+ if (!initialized) {
8676
+ initialized = true;
8677
+ wasVisible = visible;
8678
+ return;
8679
+ }
8680
+ if (visible && !wasVisible) refresh();
8681
+ wasVisible = visible;
8682
+ }, { threshold: .2 });
8683
+ observer.observe(node);
8684
+ return () => {
8685
+ controller.abort();
8686
+ observer.disconnect();
8687
+ };
8688
+ }, [load]);
8689
+ (0, react.useEffect)(() => {
8690
+ if (installing === void 0) {
8691
+ setProgress(void 0);
8692
+ return;
8693
+ }
8694
+ let cancelled = false;
8695
+ const pull = async () => {
8696
+ try {
8697
+ const response = await fetch(`${endpoint}?action=progress`, { cache: "no-store" });
8698
+ const payload = await response.json();
8699
+ if (cancelled || !response.ok || !isInstallProgress(payload.progress)) return;
8700
+ setProgress(payload.progress);
8701
+ } catch {
8702
+ if (!cancelled) return;
8703
+ }
8704
+ };
8705
+ pull();
8706
+ const timer = window.setInterval(() => {
8707
+ pull();
8708
+ }, 800);
8709
+ return () => {
8710
+ cancelled = true;
8711
+ window.clearInterval(timer);
8712
+ };
8713
+ }, [installing]);
8714
+ const install = async (id) => {
8715
+ if (installingRef.current !== void 0) return;
8716
+ installingRef.current = id;
8717
+ setInstalling(id);
8718
+ setMessage(void 0);
8719
+ try {
8720
+ const response = await fetch(`${endpoint}?dependency=${encodeURIComponent(id)}`, { method: "POST" });
8721
+ if ([
8722
+ 401,
8723
+ 403,
8724
+ 503
8725
+ ].includes(response.status)) throw new BusinessRequestError(response.status);
8726
+ const payload = await response.json();
8727
+ if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error(typeof payload.error === "string" ? payload.error : t("about.installFailed"));
8728
+ if (!alive.current) return;
8729
+ setDependencies(payload.dependencies);
8730
+ setState("ready");
8731
+ setRefreshFailed(false);
8732
+ setMessage({
8733
+ error: false,
8734
+ text: payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
8735
+ });
8736
+ } catch (error) {
8737
+ if (!alive.current) return;
8738
+ setMessage({
8739
+ error: true,
8740
+ text: installErrorText(error, t)
8741
+ });
8742
+ } finally {
8743
+ installingRef.current = void 0;
8744
+ if (alive.current) setInstalling(void 0);
8745
+ }
8746
+ };
8747
+ const updateAll = async () => {
8748
+ if (installingRef.current !== void 0) return;
8749
+ installingRef.current = "all";
8750
+ setInstalling("all");
8751
+ setMessage(void 0);
8752
+ try {
8753
+ const response = await fetch(`${endpoint}?action=update-all`, { method: "POST" });
8754
+ if ([
8755
+ 401,
8756
+ 403,
8757
+ 503
8758
+ ].includes(response.status)) throw new BusinessRequestError(response.status);
8759
+ const payload = await response.json();
8760
+ if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error(typeof payload.error === "string" ? payload.error : t("about.installFailed"));
8761
+ if (!alive.current) return;
8762
+ setDependencies(payload.dependencies);
8763
+ setState("ready");
8764
+ setRefreshFailed(false);
8765
+ setMessage({
8766
+ error: false,
8767
+ text: payload.restartRequired === false ? t("about.upToDate") : payload.autoReload === false ? t("about.restartManually") : t("about.restartRequired")
8768
+ });
8769
+ } catch (error) {
8770
+ if (!alive.current) return;
8771
+ setMessage({
8772
+ error: true,
8773
+ text: installErrorText(error, t)
8774
+ });
8775
+ } finally {
8776
+ installingRef.current = void 0;
8777
+ if (alive.current) setInstalling(void 0);
8778
+ }
8779
+ };
8780
+ const actionableCount = dependencies.filter((dependency) => !dependency.installed || dependency.updateAvailable).length;
8781
+ const selfVersion = dependencies.find((dependency) => dependency.id === "ui")?.version;
8782
+ const title = (id) => t(`about.dependency.${id}`);
8783
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8784
+ ref: root,
8785
+ className: "dcu-about",
8786
+ "aria-label": t("about.nav"),
8787
+ children: [
8788
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$2 }),
8789
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8790
+ className: "dcu-about-title-row",
8791
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", { children: [t("about.title"), selfVersion === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8792
+ className: "dcu-about-version",
8793
+ children: ["v", selfVersion]
8794
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8795
+ className: "dcu-about-links",
8796
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8797
+ className: "dcu-about-external-link",
8798
+ href: "https://github.com/MichengAI/dsh-codex-ui",
8799
+ target: "_blank",
8800
+ rel: "noreferrer",
8801
+ "aria-label": t("about.viewProject"),
8802
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GithubMark16, {}), t("about.viewProject")]
8803
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8804
+ className: "dcu-about-external-link",
8805
+ href: "https://github.com/MichengAI/dsh-codex-ui/issues",
8806
+ target: "_blank",
8807
+ rel: "noreferrer",
8808
+ "aria-label": t("about.feedback"),
8809
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconListPenOutlineMedium, {}), t("about.feedback")]
8810
+ })]
8811
+ })]
8812
+ }),
8813
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8814
+ className: "dcu-about-intro",
8815
+ children: t("about.description")
8816
+ }),
8817
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("about.features") }),
8818
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
8819
+ className: "dcu-about-features",
8820
+ children: [
8821
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.sidebar") }),
8822
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.search") }),
8823
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.workspace") }),
8824
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.sessions") }),
8825
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.conversation") }),
8826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.navigator") })
8827
+ ]
8828
+ }),
8829
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8830
+ className: "dcu-about-dependencies-heading",
8831
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("about.dependencies") }), state === "ready" && actionableCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8832
+ className: "dcu-about-install dcu-about-update-all",
8833
+ type: "button",
8834
+ "aria-busy": installing === "all",
8835
+ disabled: installing !== void 0,
8836
+ onClick: () => {
8837
+ updateAll();
8838
+ },
8839
+ children: [installing === "all" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, { size: 14 }), installing === "all" ? t("about.updatingAll") : t("about.updateAll")]
8840
+ })]
8841
+ }),
8842
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8843
+ className: "dcu-about-intro",
8844
+ children: t("about.dependenciesDescription")
8845
+ }),
8846
+ state === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8847
+ className: "dcu-about-message",
8848
+ role: "status",
8849
+ children: t("about.loading")
8850
+ }) : state === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8851
+ className: "dcu-about-message",
8852
+ "data-error": "true",
8853
+ role: "alert",
8854
+ children: t(businessRequestErrorKey(loadFailure) ?? "about.statusFailed")
8855
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8856
+ className: "dcu-about-dependencies",
8857
+ "aria-busy": installing !== void 0,
8858
+ children: dependencies.map((dependency) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
8859
+ className: "dcu-about-dependency",
8860
+ children: [
8861
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8862
+ className: "dcu-about-copy",
8863
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8864
+ className: "dcu-about-name-row",
8865
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8866
+ className: "dcu-about-name dcu-about-project-link",
8867
+ href: PROJECT_HOMEPAGES[dependency.id],
8868
+ target: "_blank",
8869
+ rel: "noreferrer",
8870
+ children: title(dependency.id)
8871
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
8872
+ className: "dcu-about-downloads",
8873
+ href: `https://www.npmjs.com/package/${dependency.packageName}`,
8874
+ target: "_blank",
8875
+ rel: "noreferrer",
8876
+ title: t("about.downloadsSource"),
8877
+ "aria-label": `${dependency.packageName} · ${t("about.totalDownloads")} · ${typeof dependency.totalDownloads === "number" && Number.isSafeInteger(dependency.totalDownloads) && dependency.totalDownloads >= 0 ? dependency.totalDownloads.toLocaleString() : t("about.downloadsUnavailable")}`,
8878
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, {
8879
+ size: 12,
8880
+ "aria-hidden": "true"
8881
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8882
+ className: "dcu-about-downloads-count",
8883
+ children: typeof dependency.totalDownloads === "number" && Number.isSafeInteger(dependency.totalDownloads) && dependency.totalDownloads >= 0 ? dependency.totalDownloads.toLocaleString() : "—"
8884
+ })]
8885
+ })]
8886
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8887
+ className: "dcu-about-package",
8888
+ title: dependency.packageName,
8889
+ children: [
8890
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8891
+ className: "dcu-about-project-link",
8892
+ href: PROJECT_HOMEPAGES[dependency.id],
8893
+ target: "_blank",
8894
+ rel: "noreferrer",
8895
+ children: dependency.packageName
8896
+ }),
8897
+ dependency.version === void 0 ? "" : ` · ${dependency.version}`,
8898
+ dependency.updateAvailable && dependency.latestVersion !== void 0 ? ` → ${dependency.latestVersion}` : ""
8899
+ ]
8900
+ })]
8901
+ }),
8902
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8903
+ className: "dcu-about-status",
8904
+ "data-installed": dependency.installed,
8905
+ "data-update": dependency.updateAvailable,
8906
+ children: [dependency.installed && !dependency.updateAvailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheckOutlineMedium, { size: 14 }), dependency.updateAvailable ? t("about.updateAvailable") : dependency.installed ? t("about.installed") : t("about.missing")]
8907
+ }),
8908
+ (!dependency.installed || dependency.updateAvailable) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
8909
+ className: "dcu-about-install",
8910
+ type: "button",
8911
+ disabled: installing !== void 0,
8912
+ onClick: () => {
8913
+ install(dependency.id);
8914
+ },
8915
+ children: [installing === dependency.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutlineMedium, { size: 14 }), installing === dependency.id ? t("about.installing") : dependency.updateAvailable ? t("about.update") : t("about.install")]
8916
+ })
8917
+ ]
8918
+ }, dependency.id))
8919
+ }),
8920
+ installing !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8921
+ className: "dcu-about-progress",
8922
+ role: "status",
8923
+ children: [
8924
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLoadingOutlineMedium, { size: 14 }) }),
8925
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: progress === void 0 ? t("about.progressHint") : progressLabel(progress, t) }),
8926
+ progress?.percent !== null && progress?.percent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8927
+ className: "dcu-about-progress-pct",
8928
+ children: [progress.percent, "%"]
8929
+ }),
8930
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8931
+ className: "dcu-about-progress-bar",
8932
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8933
+ className: "dcu-about-progress-fill",
8934
+ "data-wave": progress?.percent === null || progress?.percent === void 0,
8935
+ style: progress?.percent === null || progress?.percent === void 0 ? void 0 : { width: `${progress.percent}%` }
8936
+ })
8937
+ })
8938
+ ]
8939
+ }),
8940
+ refreshFailed && state === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8941
+ className: "dcu-about-message",
8942
+ "data-error": "true",
8943
+ role: "status",
8944
+ children: t(businessRequestErrorKey(loadFailure) ?? "about.refreshFailed")
8945
+ }),
8946
+ message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8947
+ className: "dcu-about-message",
8948
+ "data-error": message.error,
8949
+ role: message.error ? "alert" : "status",
8950
+ children: message.text
8951
+ })
8952
+ ]
8953
+ });
8954
+ }
8955
+ //#endregion
8956
+ //#region src/client/ConnectorsSection.tsx
8957
+ const MCP_CONNECTOR_UI = "/mcp-connector/ui/";
8958
+ const PROMPT_REQUEST_TYPE = "mcp-connector:start-session";
8959
+ const PROMPT_RESULT_TYPE = "mcp-connector:start-session-result";
8960
+ const stylesheet$1 = `
8961
+ .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}
8962
+ `;
8963
+ const frameLightTheme = `:root{color-scheme:light;--bg:#fff;--card:#fafafa;--line:#e5e5e5;--text:#303030;--text-2:#737373;--muted:#767676;--accent:#303030;--accent-hover:#171717;--accent-light:#e9e9e9;--dcu-action:#303030;--dcu-action-hover:#171717;--dcu-on-action:#fff;--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)}`;
8964
+ const frameDarkTheme = `:root{color-scheme:dark;--bg:#181818;--card:#232323;--line:#333;--text:#dedede;--text-2:#a1a1a1;--muted:#929292;--accent:#dedede;--accent-hover:#fff;--accent-light:#303332;--dcu-action:#383838;--dcu-action-hover:#454545;--dcu-on-action:#eee;--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)}`;
8965
+ const frameSurfaceTheme = `
8966
+ .card.featured{border-color:var(--line)}
8967
+ .card:hover,.card.featured:hover{border-color:var(--muted)}
8968
+ .btn:not(.ghost):not(.danger):not(.status-warning):not(.status-bad),.icon-btn.primary,.btn-primary,.prompt-item .send-btn{background:var(--dcu-action);border-color:var(--dcu-action);color:var(--dcu-on-action)}
8969
+ .btn:not(.ghost):not(.danger):not(.status-warning):not(.status-bad):hover,.icon-btn.primary:hover,.btn-primary:hover,.prompt-item .send-btn:hover{background:var(--dcu-action-hover);border-color:var(--dcu-action-hover)}
8970
+ `;
8971
+ function isConnector(value) {
8972
+ if (value === null || typeof value !== "object") return false;
8973
+ const item = value;
8974
+ 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");
8975
+ }
8976
+ function isPromptRequest(value) {
8977
+ if (value === null || typeof value !== "object") return false;
8978
+ const item = value;
8979
+ return item.type === PROMPT_REQUEST_TYPE && typeof item.requestId === "string" && item.requestId !== "" && typeof item.prompt === "string" && item.prompt.trim() !== "";
8980
+ }
8981
+ function syncFrameTheme(frame) {
8982
+ const doc = frame?.contentDocument;
8983
+ if (doc === null || doc === void 0) return;
8984
+ let style = doc.head.querySelector("style[data-michengai-host-theme]");
8985
+ if (style === null) {
8986
+ style = doc.createElement("style");
8987
+ style.dataset.michengaiHostTheme = "true";
8988
+ doc.head.append(style);
8989
+ }
8990
+ style.textContent = (document.body.hasAttribute("data-ds-dark-theme") ? frameDarkTheme : frameLightTheme) + frameSurfaceTheme;
8991
+ }
8992
+ function ConnectorMarket({ startPromptSession, t }) {
8993
+ const frameRef = (0, react.useRef)(null);
8994
+ (0, react.useEffect)(() => {
8995
+ const onMessage = (event) => {
8996
+ const frameWindow = frameRef.current?.contentWindow;
8997
+ if (event.origin !== window.location.origin || frameWindow === null || frameWindow === void 0 || event.source !== frameWindow) return;
8998
+ if (!isPromptRequest(event.data)) return;
8999
+ const { requestId, prompt } = event.data;
9000
+ const reply = (ok, message) => {
9001
+ frameWindow.postMessage({
9002
+ type: PROMPT_RESULT_TYPE,
9003
+ requestId,
9004
+ ok,
9005
+ message
9006
+ }, window.location.origin);
9007
+ };
9008
+ startPromptSession(prompt).then(() => {
9009
+ reply(true, t("connectors.promptReady"));
9010
+ }, (error) => {
9011
+ reply(false, userErrorText(error, t));
9012
+ });
9013
+ };
9014
+ const syncTheme = () => {
9015
+ syncFrameTheme(frameRef.current);
9016
+ };
9017
+ const observer = new MutationObserver(syncTheme);
9018
+ observer.observe(document.body, {
9019
+ attributes: true,
9020
+ attributeFilter: ["data-ds-dark-theme"]
9021
+ });
9022
+ window.addEventListener("message", onMessage);
9023
+ return () => {
9024
+ observer.disconnect();
9025
+ window.removeEventListener("message", onMessage);
9026
+ };
9027
+ }, [startPromptSession, t]);
9028
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
9029
+ ref: frameRef,
9030
+ className: "dcu-connector-frame",
9031
+ src: MCP_CONNECTOR_UI,
9032
+ title: t("connectors.title"),
9033
+ onLoad: () => {
9034
+ syncFrameTheme(frameRef.current);
9035
+ }
9036
+ });
9037
+ }
9038
+ function NativeConnectorList({ sessionStore, t }) {
9039
+ const sessionId = (0, react.useSyncExternalStore)(sessionStore.subscribe, () => currentSessionId(sessionStore.getSnapshot()));
9040
+ const [connectors, setConnectors] = (0, react.useState)([]);
9041
+ const [state, setState] = (0, react.useState)("loading");
9042
+ const [failure, setFailure] = (0, react.useState)();
9043
+ (0, react.useEffect)(() => {
9044
+ if (sessionId === void 0) {
9045
+ setConnectors([]);
9046
+ setState("ready");
9047
+ return;
9048
+ }
9049
+ const controller = new AbortController();
9050
+ setState("loading");
9051
+ fetch(`${CODEX_UI_API_ENDPOINTS.connectors}?sessionId=${encodeURIComponent(sessionId)}`, { signal: controller.signal }).then(async (response) => {
9052
+ if (!response.ok) throw new BusinessRequestError(response.status);
9053
+ const payload = await response.json();
9054
+ if (!Array.isArray(payload.connectors) || !payload.connectors.every(isConnector)) throw new Error("连接器目录返回格式无效。");
9055
+ if (!controller.signal.aborted) setConnectors(payload.connectors);
9056
+ }).then(() => {
9057
+ if (!controller.signal.aborted) setState("ready");
9058
+ }).catch((error) => {
9059
+ if (!controller.signal.aborted) {
9060
+ setFailure(error);
9061
+ setState("failed");
9062
+ }
9063
+ });
9064
+ return () => {
9065
+ controller.abort();
9066
+ };
9067
+ }, [sessionId]);
9068
+ if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9069
+ className: "dcu-connector-empty",
9070
+ children: t("connectors.openSession")
9071
+ });
9072
+ if (state === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9073
+ className: "dcu-connector-empty",
9074
+ children: t("connectors.loading")
9075
+ });
9076
+ if (state === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9077
+ className: "dcu-connector-empty",
9078
+ role: "alert",
9079
+ children: t(businessRequestErrorKey(failure) ?? "connectors.failed")
9080
+ });
9081
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9082
+ className: "dcu-connector-list",
9083
+ children: [connectors.map((connector) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
9084
+ className: "dcu-connector",
9085
+ children: [
9086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9087
+ className: "dcu-connector-head",
9088
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconLinkOutlineMedium, { size: 16 }), connector.name]
9089
+ }),
9090
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9091
+ className: "dcu-connector-meta",
9092
+ children: t("connectors.toolCount", { count: connector.tools.length })
9093
+ }),
9094
+ connector.tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9095
+ className: "dcu-connector-tool",
9096
+ children: [tool.name, tool.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tool.description })]
9097
+ }, tool.name))
9098
+ ]
9099
+ }, connector.name)), connectors.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9100
+ className: "dcu-connector-empty",
9101
+ children: t("connectors.empty")
9102
+ })]
9103
+ });
9104
+ }
9105
+ /** 安装 dsh-mcp-connector 时显示完整市场,否则回退到当前会话的 MCP 工具目录。 */
9106
+ function ConnectorsSection({ sessionStore, startPromptSession, t }) {
9107
+ const [marketAvailable, setMarketAvailable] = (0, react.useState)();
9108
+ (0, react.useEffect)(() => {
9109
+ const controller = new AbortController();
9110
+ fetch(MCP_CONNECTOR_UI, {
9111
+ method: "GET",
9112
+ cache: "no-store",
9113
+ signal: controller.signal
9114
+ }).then((response) => {
9115
+ response.body?.cancel().catch(() => {});
9116
+ if (!controller.signal.aborted) setMarketAvailable(response.ok);
9117
+ }).catch(() => {
9118
+ if (!controller.signal.aborted) setMarketAvailable(false);
9119
+ });
9120
+ return () => {
9121
+ controller.abort();
9122
+ };
9123
+ }, []);
9124
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9125
+ className: "dcu-connectors",
9126
+ "aria-label": t("connectors.title"),
9127
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$1 }), marketAvailable === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9128
+ className: "dcu-connector-empty",
9129
+ children: t("connectors.loading")
9130
+ }) : marketAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorMarket, {
9131
+ startPromptSession,
9132
+ t
9133
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
9134
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("connectors.title") }),
9135
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("connectors.description") }),
9136
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeConnectorList, {
9137
+ sessionStore,
9138
+ t
9139
+ })
9140
+ ] })]
9141
+ });
9142
+ }
9082
9143
  const HIDDEN_FOOTER_ACTION_IDS = /* @__PURE__ */ new Set(["context-overview"]);
9083
9144
  function visibleFooterActions(slots) {
9084
9145
  return slots.entriesOfSlot("sidebar.footer.action").flatMap(({ options }) => {
@@ -9429,7 +9490,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
9429
9490
  //#region src/client/settings-page-styles.ts
9430
9491
  /** Codex 设置页的局部 tokens 与布局,不覆盖宿主其他弹窗。 */
9431
9492
  const settingsPageStyles = `
9432
- .dcu-settings-page{--sp-bg:#fff;--sp-nav:var(--dcu-sidebar-background,#eef7f5);--sp-card:#fafafa;--sp-border:#e5e5e5;--sp-text:#303030;--sp-muted:#737373;--sp-hover:#e9e9e9;--sp-active:#e4e4e4;position:fixed;inset:0;z-index:1000;display:grid;grid-template-columns:clamp(240px,var(--dcu-sidebar-expanded-width,275px),min(520px,calc(100vw - 320px))) minmax(0,1fr);background:var(--sp-bg);color:var(--sp-text);font:14px/1.5 var(--dsw-font-family);text-align:left;isolation:isolate}
9493
+ .dcu-settings-page{--sp-bg:#fff;--sp-nav:var(--dcu-sidebar-background,#eef7f5);--sp-card:#fafafa;--sp-border:#e5e5e5;--sp-text:#303030;--sp-muted:#737373;--sp-hover:#e9e9e9;--sp-active:#e4e4e4;position:fixed;inset:0;z-index:1000;display:grid;grid-template-columns:clamp(240px,var(--dcu-sidebar-expanded-width,240px),min(520px,calc(100vw - 320px))) minmax(0,1fr);background:var(--sp-bg);color:var(--sp-text);font:14px/1.5 var(--dsw-font-family);text-align:left;isolation:isolate}
9433
9494
  body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:var(--dcu-sidebar-background,#1d2120);--sp-card:#232323;--sp-border:#333;--sp-text:#dedede;--sp-muted:#a1a1a1;--sp-hover:#292c2b;--sp-active:#303332;color-scheme:dark}
9434
9495
  .dcu-settings-page *{box-sizing:border-box}
9435
9496
  .dcu-settings-page button,.dcu-settings-page input{font:inherit}
@@ -9629,6 +9690,9 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
9629
9690
  (0, react.useEffect)(() => () => {
9630
9691
  exitAnimation.current?.cancel();
9631
9692
  }, []);
9693
+ (0, react.useLayoutEffect)(() => {
9694
+ if (open && page.current !== null) page.current.style.setProperty("--dcu-sidebar-expanded-width", `${settingsSidebarWidth(document)}px`);
9695
+ }, [open]);
9632
9696
  (0, react.useEffect)(() => {
9633
9697
  if (!onboardingActive) setCompleted(/* @__PURE__ */ new Set());
9634
9698
  }, [onboardingActive]);
@@ -10824,6 +10888,7 @@ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-back
10824
10888
  const companionSlots = createCompanionTabSource(ctx.slots);
10825
10889
  const globalPanels = createGlobalPanelSource(ctx.slots, ctx.locale);
10826
10890
  const footerActions = createFooterActionSource(ctx.slots);
10891
+ registerSidebarExpandControls(ctx);
10827
10892
  ctx.slots.inject("sidebar", () => ctx.slots.register({
10828
10893
  name: "sidebar",
10829
10894
  registrant: "michengai-codex-ui",