@artenx/dshb 0.1.10 → 0.1.12
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 +74 -82
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -445,7 +445,7 @@ window.__ModuleLoader__.load({
|
|
|
445
445
|
get: () => true
|
|
446
446
|
});
|
|
447
447
|
ctx.plugin({
|
|
448
|
-
inject: ["slots"
|
|
448
|
+
inject: ["slots"],
|
|
449
449
|
apply: (sub) => {
|
|
450
450
|
sub.slots.inject("settings.section", () => sub.slots.register({
|
|
451
451
|
name: "settings.section",
|
|
@@ -1223,6 +1223,14 @@ window.__ModuleLoader__.load({
|
|
|
1223
1223
|
scrollbar-width: none;
|
|
1224
1224
|
touch-action: pan-x pan-y !important;
|
|
1225
1225
|
}
|
|
1226
|
+
/* xterm uses a transparent helper textarea for all terminal input. Keep it
|
|
1227
|
+
focusable and non-zero-sized so mobile browsers can present their keyboard. */
|
|
1228
|
+
[data-phase] .xterm .xterm-helper-textarea {
|
|
1229
|
+
width: 1px !important;
|
|
1230
|
+
height: 1px !important;
|
|
1231
|
+
opacity: .01 !important;
|
|
1232
|
+
z-index: 1 !important;
|
|
1233
|
+
}
|
|
1226
1234
|
[data-phase] [class*="bodyScroll"]::-webkit-scrollbar,
|
|
1227
1235
|
[data-phase] [class*="ioCard"]::-webkit-scrollbar,
|
|
1228
1236
|
[data-phase] [class*="ioSection"]::-webkit-scrollbar,
|
|
@@ -1555,72 +1563,36 @@ window.__ModuleLoader__.load({
|
|
|
1555
1563
|
"overflow-y",
|
|
1556
1564
|
"box-sizing"
|
|
1557
1565
|
];
|
|
1558
|
-
/**
|
|
1559
|
-
|
|
1560
|
-
* 水平居中(左右各留 8px,绝不贴边/溢出),高度按视口比例封顶并内容滚动,
|
|
1561
|
-
* 触发元素上方空间足够则向上展开、否则向下展开,四边都约束在视口内。
|
|
1562
|
-
* fixed 不受祖先 overflow 裁剪(祖先带 transform 时失效)。
|
|
1563
|
-
*/
|
|
1564
|
-
function positionFixedSheet(el, rootRect, maxWidth, maxHeightRatio) {
|
|
1566
|
+
/** Keep the model menu anchored to its trigger while fitting it in the viewport. */
|
|
1567
|
+
function positionAnchoredMenu(el, triggerRect, maxWidth, maxHeight) {
|
|
1565
1568
|
const margin = 8;
|
|
1566
1569
|
const vw = window.innerWidth;
|
|
1567
1570
|
const vh = window.innerHeight;
|
|
1568
|
-
const width = Math.max(0, Math.min(maxWidth, vw - 16));
|
|
1569
|
-
const left = Math.round((vw - width) / 2);
|
|
1570
|
-
const maxH = Math.round(vh * maxHeightRatio);
|
|
1571
|
-
const spaceAbove = rootRect.top - margin;
|
|
1572
|
-
const spaceBelow = vh - rootRect.bottom - margin;
|
|
1573
|
-
const expandUp = spaceAbove >= 140 && spaceAbove >= spaceBelow;
|
|
1574
|
-
let top;
|
|
1575
|
-
if (expandUp) {
|
|
1576
|
-
const h = Math.min(maxH, Math.max(spaceAbove, 140));
|
|
1577
|
-
top = rootRect.top - margin - h;
|
|
1578
|
-
} else top = rootRect.bottom + margin;
|
|
1579
|
-
top = Math.max(margin, top);
|
|
1580
|
-
el.style.setProperty("position", "fixed", "important");
|
|
1581
|
-
el.style.setProperty("box-sizing", "border-box", "important");
|
|
1582
|
-
el.style.setProperty("width", `${width}px`, "important");
|
|
1583
|
-
el.style.setProperty("left", `${left}px`, "important");
|
|
1584
|
-
el.style.setProperty("right", "auto", "important");
|
|
1585
|
-
el.style.setProperty("top", `${top}px`, "important");
|
|
1586
|
-
el.style.setProperty("bottom", "auto", "important");
|
|
1587
|
-
el.style.setProperty("min-width", "0", "important");
|
|
1588
|
-
el.style.setProperty("max-width", "none", "important");
|
|
1589
|
-
el.style.setProperty("max-height", `${maxH}px`, "important");
|
|
1590
|
-
el.style.setProperty("overflow-y", "auto", "important");
|
|
1591
|
-
}
|
|
1592
|
-
/**
|
|
1593
|
-
* 一级 pane(Model/Effort 单元格小菜单)紧凑浮层:右缘对齐触发按钮右缘
|
|
1594
|
-
* (面板右缘 x = 按钮右缘 x,钳制在视口内 8px 起,避免宽面板超出屏幕左缘时
|
|
1595
|
-
* 被甩到左边贴边),向上展开、空间不足向下展开;宽度跟随内容
|
|
1596
|
-
* (max-content,封顶 min(420, vw-16)),避免小菜单被全宽 sheet 拉远到
|
|
1597
|
-
* 屏幕中间。测量与定位在同一任务内同步完成,无闪烁。
|
|
1598
|
-
*/
|
|
1599
|
-
function positionCompactPanel(el, root, rootRect) {
|
|
1600
|
-
const margin = 8;
|
|
1601
|
-
const vw = window.innerWidth;
|
|
1602
|
-
const trigger = root.querySelector("[class*=\"7KE1Ra_trigger\"], [class*=\"_trigger\"]") ?? root;
|
|
1603
|
-
const anchorRect = trigger === root ? rootRect : trigger.getBoundingClientRect();
|
|
1604
1571
|
el.style.setProperty("position", "fixed", "important");
|
|
1605
1572
|
el.style.setProperty("box-sizing", "border-box", "important");
|
|
1606
1573
|
el.style.setProperty("left", "0", "important");
|
|
1607
|
-
el.style.setProperty("top", "0", "important");
|
|
1608
1574
|
el.style.setProperty("right", "auto", "important");
|
|
1575
|
+
el.style.setProperty("top", "0", "important");
|
|
1609
1576
|
el.style.setProperty("bottom", "auto", "important");
|
|
1610
|
-
el.style.setProperty("width", "max-content", "important");
|
|
1611
1577
|
el.style.setProperty("min-width", "0", "important");
|
|
1612
|
-
el.style.setProperty("max-width", `${Math.min(
|
|
1613
|
-
el.style.setProperty("max-height",
|
|
1614
|
-
el.style.setProperty("overflow-y", "
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
const
|
|
1618
|
-
const
|
|
1619
|
-
const
|
|
1620
|
-
const
|
|
1578
|
+
el.style.setProperty("max-width", `${Math.max(0, Math.min(maxWidth, vw - 16))}px`, "important");
|
|
1579
|
+
el.style.setProperty("max-height", `${Math.max(0, Math.min(maxHeight, vh - 16))}px`, "important");
|
|
1580
|
+
el.style.setProperty("overflow-y", "auto", "important");
|
|
1581
|
+
let width = el.offsetWidth;
|
|
1582
|
+
let height = el.offsetHeight;
|
|
1583
|
+
const spaceAbove = Math.max(0, triggerRect.top - 16);
|
|
1584
|
+
const spaceBelow = Math.max(0, vh - triggerRect.bottom - 16);
|
|
1585
|
+
const expandUp = height <= spaceAbove || spaceAbove >= spaceBelow;
|
|
1586
|
+
const available = expandUp ? spaceAbove : spaceBelow;
|
|
1587
|
+
if (height > available) {
|
|
1588
|
+
el.style.setProperty("max-height", `${Math.max(0, available - margin)}px`, "important");
|
|
1589
|
+
height = el.offsetHeight;
|
|
1590
|
+
width = el.offsetWidth;
|
|
1591
|
+
}
|
|
1592
|
+
const top = expandUp ? triggerRect.top - margin - height : triggerRect.bottom + margin;
|
|
1593
|
+
const left = Math.max(margin, Math.min(triggerRect.right - width, vw - width - margin));
|
|
1621
1594
|
el.style.setProperty("left", `${left}px`, "important");
|
|
1622
|
-
el.style.setProperty("top", `${top}px`, "important");
|
|
1623
|
-
el.style.setProperty("width", `${w}px`, "important");
|
|
1595
|
+
el.style.setProperty("top", `${Math.max(margin, Math.min(top, vh - height - margin))}px`, "important");
|
|
1624
1596
|
}
|
|
1625
1597
|
/**
|
|
1626
1598
|
* 模型名多为纯连字符词(DeepSeek-V4-Flash-Vision-Exp);white-space:normal 下
|
|
@@ -1673,7 +1645,7 @@ window.__ModuleLoader__.load({
|
|
|
1673
1645
|
n.style.removeProperty("font-size");
|
|
1674
1646
|
}
|
|
1675
1647
|
}
|
|
1676
|
-
/** 清除
|
|
1648
|
+
/** 清除 anchored menu 写入的内联样式,交还上游 CSS。 */
|
|
1677
1649
|
function clearFixedSheet(el) {
|
|
1678
1650
|
if (el === null || el === void 0) return;
|
|
1679
1651
|
for (const key of SHEET_PROPS) el.style.removeProperty(key);
|
|
@@ -1683,10 +1655,8 @@ window.__ModuleLoader__.load({
|
|
|
1683
1655
|
* 元素:一级 Model/Effort 单元格列表(cellLabel),点击后切到模型列表(modelName)
|
|
1684
1656
|
* 或档位列表。上游默认 `position:absolute;right:0` 贴触发按钮右缘,触发按钮在
|
|
1685
1657
|
* 可横向滚动的 stats 行内时菜单会整体出屏。两级 pane 都必须接管(不能只按
|
|
1686
|
-
* modelName 匹配,否则一级 pane
|
|
1687
|
-
*
|
|
1688
|
-
* 二级列表走视口级居中 fixed sheet(左右各 8px、高度 45% 视口封顶、
|
|
1689
|
-
* 内容滚动、上方空间不足时向下展开)。
|
|
1658
|
+
* modelName 匹配,否则一级 pane 漏掉)。所有视口都把菜单锚定到触发按钮,
|
|
1659
|
+
* 在上方/下方可用空间中选择更合适的一侧,避免上游空间不足时把菜单钳到屏幕顶端。
|
|
1690
1660
|
*/
|
|
1691
1661
|
function installModelMenuPosition(ctx) {
|
|
1692
1662
|
ctx.effect(() => {
|
|
@@ -1706,37 +1676,41 @@ window.__ModuleLoader__.load({
|
|
|
1706
1676
|
let fittedVw = 0;
|
|
1707
1677
|
let fittedSig = -1;
|
|
1708
1678
|
let fittedMenus = [];
|
|
1679
|
+
let positionedMenus = [];
|
|
1709
1680
|
const sync = () => {
|
|
1710
1681
|
const menus = findMenus();
|
|
1711
|
-
if (!narrow.matches) {
|
|
1712
|
-
if (fittedMenus.length > 0) {
|
|
1713
|
-
for (const menu of fittedMenus) {
|
|
1714
|
-
clearFixedSheet(menu);
|
|
1715
|
-
clearModelNameFit(menu);
|
|
1716
|
-
}
|
|
1717
|
-
fittedVw = 0;
|
|
1718
|
-
fittedSig = -1;
|
|
1719
|
-
fittedMenus = [];
|
|
1720
|
-
window.dispatchEvent(new Event("resize"));
|
|
1721
|
-
}
|
|
1722
|
-
return;
|
|
1723
|
-
}
|
|
1724
1682
|
let vw = 0;
|
|
1725
1683
|
let sig = 0;
|
|
1726
1684
|
const modelMenus = [];
|
|
1685
|
+
const visibleMenus = [];
|
|
1727
1686
|
for (const menu of menus) {
|
|
1728
1687
|
const trigger = findTrigger(menu);
|
|
1729
|
-
if (trigger === null) continue;
|
|
1688
|
+
if (trigger === null || trigger.getAttribute("aria-expanded") !== "true") continue;
|
|
1730
1689
|
const rect = menu.getBoundingClientRect();
|
|
1731
1690
|
if (rect.width === 0 && rect.height === 0) continue;
|
|
1732
|
-
|
|
1691
|
+
positionAnchoredMenu(menu, trigger.getBoundingClientRect(), Math.min(420, window.innerWidth - 16), 360);
|
|
1692
|
+
visibleMenus.push(menu);
|
|
1733
1693
|
if (menu.querySelector("[class*=\"modelName\"]")) {
|
|
1734
|
-
positionFixedSheet(menu, triggerRect, Number.POSITIVE_INFINITY, .45);
|
|
1735
|
-
applyNonBreakingHyphens(menu);
|
|
1736
1694
|
modelMenus.push(menu);
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1695
|
+
if (narrow.matches) {
|
|
1696
|
+
applyNonBreakingHyphens(menu);
|
|
1697
|
+
vw = window.innerWidth;
|
|
1698
|
+
for (const n of menu.querySelectorAll("[class*=\"modelName\"]")) sig += n.textContent?.length ?? 0;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
for (const previous of positionedMenus) {
|
|
1703
|
+
if (visibleMenus.includes(previous)) continue;
|
|
1704
|
+
clearFixedSheet(previous);
|
|
1705
|
+
clearModelNameFit(previous);
|
|
1706
|
+
}
|
|
1707
|
+
positionedMenus = visibleMenus;
|
|
1708
|
+
if (!narrow.matches) {
|
|
1709
|
+
for (const menu of modelMenus) clearModelNameFit(menu);
|
|
1710
|
+
fittedVw = 0;
|
|
1711
|
+
fittedSig = -1;
|
|
1712
|
+
fittedMenus = [];
|
|
1713
|
+
return;
|
|
1740
1714
|
}
|
|
1741
1715
|
const needFit = modelMenus.some((m) => !fittedMenus.includes(m));
|
|
1742
1716
|
if (vw > 0 && (needFit || vw !== fittedVw || sig !== fittedSig)) {
|
|
@@ -1806,6 +1780,23 @@ window.__ModuleLoader__.load({
|
|
|
1806
1780
|
};
|
|
1807
1781
|
}, "dshb-mobile: context panel position");
|
|
1808
1782
|
}
|
|
1783
|
+
function installMobileTerminalInputFocus(ctx) {
|
|
1784
|
+
ctx.effect(() => {
|
|
1785
|
+
const mobile = window.matchMedia(MOBILE_QUERY);
|
|
1786
|
+
const focusInput = (event) => {
|
|
1787
|
+
if (!mobile.matches || !(event.target instanceof Element)) return;
|
|
1788
|
+
const textarea = event.target.closest(".xterm")?.querySelector(".xterm-helper-textarea");
|
|
1789
|
+
if (!textarea || textarea.readOnly) return;
|
|
1790
|
+
textarea.inputMode = "text";
|
|
1791
|
+
textarea.focus({ preventScroll: true });
|
|
1792
|
+
try {
|
|
1793
|
+
navigator.virtualKeyboard?.show?.();
|
|
1794
|
+
} catch {}
|
|
1795
|
+
};
|
|
1796
|
+
document.addEventListener("pointerdown", focusInput, true);
|
|
1797
|
+
return () => document.removeEventListener("pointerdown", focusInput, true);
|
|
1798
|
+
}, "dshb-mobile: terminal input focus");
|
|
1799
|
+
}
|
|
1809
1800
|
/** 目录抽屉切换按钮(仅切换,不含文件浏览/日志导出等功能按钮)。 */
|
|
1810
1801
|
function DrawerToggle({ toggleSidebar }) {
|
|
1811
1802
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -1895,6 +1886,7 @@ window.__ModuleLoader__.load({
|
|
|
1895
1886
|
/** 安装移动端适配:样式 + viewport + 抽屉标记 + 抽屉交互 + 切换按钮。 */
|
|
1896
1887
|
function installMobile(ctx) {
|
|
1897
1888
|
installStyles(ctx);
|
|
1889
|
+
installMobileTerminalInputFocus(ctx);
|
|
1898
1890
|
installViewport(ctx);
|
|
1899
1891
|
installFrameMarker(ctx);
|
|
1900
1892
|
installStatsLine(ctx);
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["SECTION_ID","useState","useCallback","apply","inputStyle","buttonStyle","primaryButtonStyle","secondaryButtonStyle","useState","useCallback","useState","useCallback","apply"],"sources":["../src/client/auth.tsx","../src/client/directory-flow.tsx","../src/client/mobile.tsx","../src/client/workspace-instruction-menu.tsx","../src/client/ui.tsx","../src/client/index.tsx"],"sourcesContent":["import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\n\nexport const inject = ['connection']\n\nconst SECTION_ID = 'auth'\nconst MESSAGE_MS = 5000\n\nfunction useUsername(): [string | undefined, (username: string) => void] {\n const [username, setUsername] = useState<string | undefined>(undefined)\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const res = await fetch('/api/auth/status')\n if (!res.ok) return\n const data = (await res.json()) as { username?: string }\n if (!cancelled && typeof data.username === 'string') setUsername(data.username)\n } catch {\n // best-effort\n }\n })()\n return () => {\n cancelled = true\n }\n }, [])\n return [username, setUsername]\n}\n\ntype Notice = { kind: 'ok' | 'error'; text: string; owner: 'username' | 'password' | 'account' }\n\nexport function AuthSection(_props: PropsRuntime<'settings.section'>): ReactElement {\n const [username, setUsername] = useUsername()\n const [newUsername, setNewUsername] = useState('')\n const [usernamePassword, setUsernamePassword] = useState('')\n const [oldPassword, setOldPassword] = useState('')\n const [newPassword, setNewPassword] = useState('')\n const [confirm, setConfirm] = useState('')\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<Notice | undefined>(undefined)\n const [confirmingSignOut, setConfirmingSignOut] = useState(false)\n\n const flash = useCallback((n: Notice | undefined) => {\n setNotice(n)\n if (n !== undefined) setTimeout(() => setNotice(undefined), MESSAGE_MS)\n }, [])\n\n const signOut = useCallback(async () => {\n setBusy(true)\n try {\n await fetch('/api/auth/logout', { method: 'POST' })\n window.location.href = '/login'\n } catch {\n setBusy(false)\n setConfirmingSignOut(false)\n flash({ kind: 'error', text: '退出失败,请重试', owner: 'account' })\n }\n }, [flash])\n\n const changePassword = useCallback(async () => {\n if (newPassword !== confirm) {\n flash({ kind: 'error', text: '两次输入的新密码不一致', owner: 'password' })\n return\n }\n setBusy(true)\n try {\n const res = await fetch('/api/auth/change-password', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ currentPassword: oldPassword, password: newPassword }),\n })\n const data = (await res.json()) as { error?: string }\n if (res.ok) {\n setOldPassword('')\n setNewPassword('')\n setConfirm('')\n flash({ kind: 'ok', text: '密码已修改', owner: 'password' })\n } else {\n flash({ kind: 'error', text: data.error ?? '修改失败,请重试', owner: 'password' })\n }\n } catch {\n flash({ kind: 'error', text: '修改失败,请重试', owner: 'password' })\n } finally {\n setBusy(false)\n }\n }, [oldPassword, newPassword, confirm, flash])\n\n const changeUsername = useCallback(async () => {\n setBusy(true)\n try {\n const res = await fetch('/api/auth/change-username', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ username: newUsername, currentPassword: usernamePassword }),\n })\n const data = (await res.json()) as { error?: string }\n if (res.ok) {\n setNewUsername('')\n setUsernamePassword('')\n if (newUsername) setUsername(newUsername)\n flash({ kind: 'ok', text: '用户名已更新', owner: 'username' })\n } else {\n flash({ kind: 'error', text: data.error ?? '修改失败,请重试', owner: 'username' })\n }\n } catch {\n flash({ kind: 'error', text: '修改失败,请重试', owner: 'username' })\n } finally {\n setBusy(false)\n }\n }, [newUsername, usernamePassword, flash, setUsername])\n\n const inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n }\n const buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n }\n const primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n }\n const secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n }\n const dangerButtonStyle: CSSProperties = {\n ...buttonStyle,\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n }\n const dangerOutlineButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 24, maxWidth: 420 }}>\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 4px' }}>账号</h2>\n <p style={{ fontSize: 13, opacity: 0.7, margin: '0 0 12px' }}>\n {username !== undefined ? `当前登录:${username}` : '当前登录:管理员'}\n </p>\n <button\n type=\"button\"\n onClick={() => setConfirmingSignOut(true)}\n disabled={busy}\n style={dangerOutlineButtonStyle}\n >\n 退出登录\n </button>\n {confirmingSignOut && (\n <div role=\"alertdialog\" aria-label=\"确认退出登录\" style={{ marginTop: 10, padding: '12px 14px', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8, maxWidth: 320 }}>\n <div style={{ fontSize: 13, marginBottom: 10, color: 'var(--dsw-alias-label-primary)' }}>退出登录将回到登录页</div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8 }}>\n <button type=\"button\" onClick={() => setConfirmingSignOut(false)} disabled={busy} style={{ ...secondaryButtonStyle, height: 32, padding: '0 12px', borderRadius: 16 }}>\n 取消\n </button>\n <button type=\"button\" onClick={() => void signOut()} disabled={busy} style={{ ...dangerOutlineButtonStyle, height: 32, padding: '0 12px', borderRadius: 16, background: 'var(--dsw-alias-interactive-bg-hover-danger)' }}>\n 确认退出\n </button>\n </div>\n </div>\n )}\n {notice?.owner === 'account' && (\n <p style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)', margin: '8px 0 0' }}>{notice.text}</p>\n )}\n </section>\n\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 12px' }}>修改用户名</h2>\n <form onSubmit={(e) => { e.preventDefault(); void changeUsername() }} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 新用户名\n <input type=\"text\" value={newUsername} onChange={(e) => setNewUsername(e.target.value)} autoComplete=\"username\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 当前密码\n <input type=\"password\" value={usernamePassword} onChange={(e) => setUsernamePassword(e.target.value)} autoComplete=\"current-password\" style={inputStyle} />\n </label>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <button type=\"submit\" disabled={busy} style={primaryButtonStyle}>修改用户名</button>\n {notice?.owner === 'username' && <span style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </form>\n </section>\n\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 12px' }}>修改密码</h2>\n <form onSubmit={(e) => { e.preventDefault(); void changePassword() }} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 当前密码\n <input type=\"password\" value={oldPassword} onChange={(e) => setOldPassword(e.target.value)} autoComplete=\"current-password\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 新密码\n <input type=\"password\" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} autoComplete=\"new-password\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 确认新密码\n <input type=\"password\" value={confirm} onChange={(e) => setConfirm(e.target.value)} autoComplete=\"new-password\" style={inputStyle} />\n </label>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <button type=\"submit\" disabled={busy} style={primaryButtonStyle}>修改密码</button>\n {notice?.owner === 'password' && <span style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </form>\n </section>\n </div>\n )\n}\n\nexport function apply(ctx: ClientContext): void {\n const connection = ctx.get('connection') as { isLoopback?: boolean } | undefined\n if (connection !== undefined) {\n Object.defineProperty(connection, 'isLoopback', { configurable: true, get: () => true })\n }\n ctx.plugin({\n inject: ['slots', 'settingsScope'],\n apply: (sub: ClientContext): void => {\n sub.slots.inject('settings.section', () =>\n sub.slots.register({ name: 'settings.section', id: SECTION_ID, order: 100, label: () => '认证' }, AuthSection),\n )\n },\n })\n}\n","import type { DirectoryFlowOwnerProps } from '@deepseek-ai/dsh-client-ui-workspace/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\n\ninterface NodeProfileView {\n id: string\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n status?: { reachable?: boolean }\n}\n\ninterface DirEntry {\n name: string\n path: string\n isDirectory: boolean\n}\n\nconst inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n}\nconst buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n}\nconst primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\nconst secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n}\nconst overlayStyle: CSSProperties = {\n position: 'fixed',\n inset: 0,\n background: 'var(--dsw-alias-overlay-mask, rgba(0,0,0,0.45))',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n}\nconst dialogStyle: CSSProperties = {\n width: 'min(92vw, 560px)',\n maxWidth: '100%',\n maxHeight: '80vh',\n overflow: 'auto',\n overflowX: 'hidden',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: 20,\n boxSizing: 'border-box',\n color: 'var(--dsw-alias-label-primary)',\n}\n\nfunction joinPath(base: string, name: string): string {\n return `${base.replace(/\\/+$/, '')}/${name}`\n}\n\nexport function DirectoryFlowOccupant(props: DirectoryFlowOwnerProps): ReactElement | null {\n const [nodes, setNodes] = useState<NodeProfileView[]>([])\n const [nodeId, setNodeId] = useState<string>('')\n const [path, setPath] = useState('')\n const [entries, setEntries] = useState<DirEntry[]>([])\n const [error, setError] = useState<string | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [newDirName, setNewDirName] = useState('')\n const [pendingInstruction, setPendingInstruction] = useState<string | undefined>(undefined)\n const [instructionDialogOpen, setInstructionDialogOpen] = useState(false)\n\n useEffect(() => {\n if (!props.open) return\n void (async () => {\n try {\n const res = await fetch('/api/dshb/nodes')\n if (!res.ok) return\n const data = (await res.json()) as { nodes?: NodeProfileView[] }\n setNodes(data.nodes ?? [])\n } catch {}\n })()\n }, [props.open])\n\n const browse = useCallback(async (id: string, dir: string) => {\n setError(undefined)\n try {\n const res = await fetch(`/api/dshb/nodes/${id}/browse?path=${encodeURIComponent(dir)}`)\n const data = (await res.json()) as { ok?: boolean; path?: string; entries?: DirEntry[]; error?: string }\n if (!res.ok || !data.ok) {\n setError(data.error ?? '目录读取失败')\n return\n }\n setPath(data.path ?? dir)\n setEntries((data.entries ?? []).filter((e) => e.isDirectory))\n } catch {\n setError('网络错误')\n }\n }, [])\n\n const selectNode = useCallback(\n (id: string) => {\n setNodeId(id)\n setPath('')\n setEntries([])\n setError(undefined)\n void browse(id, '/')\n },\n [browse],\n )\n\n const mkdir = useCallback(async () => {\n if (!newDirName.trim()) return\n setBusy(true)\n setError(undefined)\n try {\n const target = joinPath(path, newDirName.trim())\n const res = await fetch(`/api/dshb/nodes/${nodeId}/mkdir`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ path: target }),\n })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (!res.ok || !data.ok) {\n setError(data.error ?? '创建目录失败')\n return\n }\n setNewDirName('')\n void browse(nodeId, target)\n } catch {\n setError('网络错误')\n } finally {\n setBusy(false)\n }\n }, [newDirName, nodeId, path, browse])\n\n const confirm = useCallback(async () => {\n if (!nodeId || !path) {\n setError('请选择节点与目录')\n return\n }\n setBusy(true)\n setError(undefined)\n try {\n const node = nodes.find((n) => n.id === nodeId)\n if (!node) return\n let pickedPath = path\n if (node.type !== 'local-host') {\n const res = await fetch('/api/dshb/workspaces/bind', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ nodeId, remotePath: path }),\n })\n const data = (await res.json()) as { ok?: boolean; mirrorPath?: string; error?: string }\n if (!res.ok || !data.ok || !data.mirrorPath) {\n setError(data.error ?? '工作区注册失败')\n return\n }\n pickedPath = data.mirrorPath\n }\n props.onPicked(pickedPath)\n if (pendingInstruction !== undefined && pendingInstruction.trim()) {\n savePendingInstruction(pickedPath, pendingInstruction)\n }\n } catch {\n setError('网络错误')\n } finally {\n setBusy(false)\n }\n }, [nodeId, path, nodes, props, pendingInstruction])\n\n if (!props.open) return null\n\n const node = nodes.find((n) => n.id === nodeId)\n\n return (\n <div style={overlayStyle} role=\"dialog\" aria-label=\"添加工作区\">\n <div style={dialogStyle}>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>\n <h2 style={{ margin: 0, fontSize: 16, color: 'var(--dsw-alias-label-primary)' }}>添加工作区</h2>\n <button type=\"button\" onClick={props.onCancel} style={secondaryButtonStyle}>\n 关闭\n </button>\n </div>\n\n <label style={{ display: 'block', fontSize: 12, color: 'var(--dsw-alias-label-secondary)', marginBottom: 4 }}>工作节点</label>\n <select style={{ ...inputStyle, marginBottom: 14 }} value={nodeId} onChange={(e) => selectNode(e.target.value)} disabled={props.busy || busy}>\n <option value=\"\">选择节点…</option>\n {nodes.map((n) => {\n const typeLabel =\n n.type === 'local-host' ? '本地' : n.type === 'remote-ssh' ? '远程 SSH' : n.type === 'local-docker' ? '本地 Docker' : n.type === 'remote-docker' ? '远程 Docker' : n.type\n return (\n <option key={n.id} value={n.id}>\n {n.name}({typeLabel})\n </option>\n )\n })}\n </select>\n\n {nodeId !== '' && (\n <>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>\n <label style={{ fontSize: 12, color: 'var(--dsw-alias-label-secondary)' }}>当前目录({node?.type === 'local-host' ? '本机' : '远端'})</label>\n <button type=\"button\" onClick={() => void browse(nodeId, dirnameOf(path))} disabled={busy} style={secondaryButtonStyle}>\n 上一级\n </button>\n </div>\n <div style={{ ...inputStyle, marginBottom: 8, height: 'auto', minHeight: 32, display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 2, cursor: 'pointer', lineHeight: '32px', overflow: 'hidden' }} onClick={() => void browse(nodeId, path)}>\n {path.split('/').filter(Boolean).length === 0 ? (\n <span style={{ opacity: 0.5 }}>根目录</span>\n ) : (\n <>\n <span onClick={(ev) => { ev.stopPropagation(); void browse(nodeId, '/') }} style={{ cursor: 'pointer', color: 'var(--dsw-alias-label-secondary)' }}>/</span>\n {path.split('/').filter(Boolean).map((seg, i, arr) => {\n const dir = '/' + arr.slice(0, i + 1).join('/')\n return (\n <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 2 }}>\n <span onClick={(ev) => { ev.stopPropagation(); void browse(nodeId, dir) }} style={{ cursor: 'pointer' }}>{seg}</span>\n {i < arr.length - 1 && <span style={{ opacity: 0.4 }}>/</span>}\n </span>\n )\n })}\n </>\n )}\n </div>\n <div style={{ maxHeight: 200, overflow: 'auto', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 6, marginBottom: 10 }}>\n {entries.map((e) => (\n <div key={e.path} onClick={() => void browse(nodeId, e.path)} style={{ padding: '7px 10px', cursor: 'pointer', fontSize: 13, borderRadius: 6, color: 'var(--dsw-alias-label-primary)', display: 'flex', alignItems: 'center', gap: 6, overflow: 'hidden' }} onMouseEnter={(ev) => (ev.currentTarget.style.background = 'var(--dsw-alias-interactive-bg-hover)')} onMouseLeave={(ev) => (ev.currentTarget.style.background = 'transparent')}>\n <span style={{ flexShrink: 0 }}>📁</span>\n <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.name}</span>\n </div>\n ))}\n {entries.length === 0 && <div style={{ padding: 12, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' }}>无子目录</div>}\n </div>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <input style={{ ...inputStyle, flex: 1, minWidth: 0 }} value={newDirName} onChange={(e) => setNewDirName(e.target.value)} placeholder=\"在当前目录下新建子目录…\" onKeyDown={(e) => { if (e.key === 'Enter') void mkdir() }} />\n <button type=\"button\" onClick={() => void mkdir()} disabled={busy || !newDirName.trim()} style={{ ...secondaryButtonStyle, flexShrink: 0, whiteSpace: 'nowrap' }}>\n 新建\n </button>\n </div>\n </>\n )}\n\n {error && <div style={{ fontSize: 13, color: 'var(--dsw-alias-state-error-primary)', marginBottom: 10 }}>{error}</div>}\n\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>\n <button type=\"button\" onClick={props.onCancel} style={secondaryButtonStyle}>\n 取消\n </button>\n <button\n type=\"button\"\n onClick={() => setInstructionDialogOpen(true)}\n disabled={busy || props.busy || !nodeId || !path}\n style={{\n ...secondaryButtonStyle,\n borderColor: pendingInstruction !== undefined && pendingInstruction.trim() ? 'var(--dsw-alias-state-business-primary)' : 'var(--dsw-alias-border-l2)',\n color: pendingInstruction !== undefined && pendingInstruction.trim() ? 'var(--dsw-alias-state-business-primary)' : 'var(--dsw-alias-label-primary)',\n }}\n >\n 指令{pendingInstruction !== undefined && pendingInstruction.trim() ? ' ●' : ''}\n </button>\n <button type=\"button\" onClick={() => void confirm()} disabled={busy || props.busy || !nodeId || !path} style={primaryButtonStyle}>\n 设为工作区\n </button>\n </div>\n </div>\n\n {instructionDialogOpen && (\n <InstructionPreviewDialog\n text={pendingInstruction ?? ''}\n onClose={() => setInstructionDialogOpen(false)}\n onSave={(t) => {\n setPendingInstruction(t)\n setInstructionDialogOpen(false)\n }}\n />\n )}\n </div>\n )\n}\n\nfunction dirnameOf(path: string): string {\n const parts = path.split('/').filter(Boolean)\n parts.pop()\n return parts.length === 0 ? '/' : `/${parts.join('/')}`\n}\n\nconst pendingInstructions = new Map<string, string>()\n\nfunction savePendingInstruction(path: string, text: string): void {\n pendingInstructions.set(path, text)\n void (async () => {\n try {\n let attempts = 0\n const tryResolve = async (): Promise<void> => {\n if (attempts++ > 10) return\n const wks = (window as unknown as { workspaces?: { list?: { getSnapshot?: () => { items?: { workspaceId: string; path: string }[] } } } }).workspaces\n const snap = wks?.list?.getSnapshot?.()\n const items = snap?.items ?? []\n const ws = items.find((w) => w.path === path)\n if (!ws) {\n await new Promise((r) => setTimeout(r, 300))\n return tryResolve()\n }\n await fetch(`/api/dshb/instructions/${ws.workspaceId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text, expectedRevision: 0 }),\n })\n pendingInstructions.delete(path)\n }\n void tryResolve()\n } catch {}\n })()\n}\n\nfunction InstructionPreviewDialog(props: {\n text: string\n onClose: () => void\n onSave: (text: string) => void\n}): ReactElement {\n const [text, setText] = useState(props.text)\n const overlayStyle: CSSProperties = {\n position: 'fixed',\n inset: 0,\n background: 'var(--dsw-alias-overlay-mask, rgba(0,0,0,0.45))',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1100,\n }\n const dialogStyle: CSSProperties = {\n width: 'min(92vw, 600px)',\n maxWidth: '100%',\n maxHeight: '85vh',\n overflow: 'auto',\n overflowX: 'hidden',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: 20,\n boxSizing: 'border-box',\n color: 'var(--dsw-alias-label-primary)',\n }\n return (\n <div style={overlayStyle} onClick={props.onClose}>\n <div style={dialogStyle} onClick={(e) => e.stopPropagation()}>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>\n <h2 style={{ margin: 0, fontSize: 16, color: 'var(--dsw-alias-label-primary)' }}>项目指令</h2>\n <button type=\"button\" onClick={props.onClose} style={secondaryButtonStyle}>关闭</button>\n </div>\n <div style={{ fontSize: 12, color: 'var(--dsw-alias-label-secondary)', marginBottom: 10 }}>\n 工作区创建后,此指令将自动保存为新工作区的项目指令。新对话首次交互时注入。\n </div>\n <textarea\n style={{\n width: '100%',\n minHeight: '280px',\n fontFamily: 'monospace',\n fontSize: 13,\n padding: '12px',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n background: 'var(--dsw-alias-bg-layer-2)',\n color: 'var(--dsw-alias-label-primary)',\n resize: 'vertical',\n boxSizing: 'border-box',\n outline: 'none',\n }}\n value={text}\n onChange={(e) => setText(e.target.value)}\n placeholder=\"留空则不注入指令...\"\n spellCheck={false}\n />\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, marginTop: 14 }}>\n <button type=\"button\" onClick={props.onClose} style={secondaryButtonStyle}>取消</button>\n <button type=\"button\" onClick={() => props.onSave(text)} style={primaryButtonStyle}>确定</button>\n </div>\n </div>\n </div>\n )\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n\n/**\n * dshb 移动端屏幕适配(参考 dsh-web-mobile 实现,仅保留页面适配与目录抽屉\n * 切换,不含文件浏览 / 导出会话日志等功能按钮)。\n *\n * 机制与上游一致:dsh 客户端在窄屏会自动给 AppFrame 加 data-sidebar-collapsed\n * 折叠侧边栏;这里把侧边栏列(frame 的第一个 grid 子元素)用 CSS 抽屉化\n * (绝对定位 + transform 移出/滑入),并在会话头部注入一个切换按钮调用\n * ctx.layout.toggleSidebar()。窄屏判定与上游一致(<1024 且粗指针,避免桌面\n * 小窗误触发)。\n */\nexport const MOBILE_QUERY = '(max-width: 1023px) and (pointer: coarse)'\n\n/** 纯视口宽度判定:与放宽后的 MOBILE_CSS 媒体查询一致(不依赖 pointer 类型)。 */\nconst NARROW_QUERY = '(max-width: 1023px)'\n\nconst FRAME_ATTR = 'data-dshb-mobile'\nconst COLLAPSED_ATTR = 'data-sidebar-collapsed'\n\nconst MOBILE_CSS = `\n/* 仅按视口宽度判定,不绑定 pointer:coarse —— 触屏笔记本 / DevTools 响应式模式\n 常报 pointer:fine,绑定 coarse 会让全部窄屏修复失效。抽屉相关选择器都挂在\n [data-dshb-mobile] 标记上,标记由 JS 的 coarse 判定添加,故放宽 CSS 不会误开抽屉。 */\n@media (max-width: 1023px) {\n html, body { touch-action: pan-y pinch-zoom !important; overscroll-behavior-x: none !important; -webkit-text-size-adjust: 100% !important; text-size-adjust: 100% !important; }\n\n [${FRAME_ATTR}=\"frame\"] {\n box-sizing: border-box !important;\n position: relative !important;\n grid-template-columns: minmax(0, 1fr) 0 0 !important;\n padding-top: env(safe-area-inset-top, 0px) !important;\n }\n\n /* 侧边栏列 -> 抽屉:默认移出屏幕,展开(无 collapsed)时滑入 */\n [${FRAME_ATTR}=\"frame\"] > :first-child {\n position: absolute !important;\n inset: 0 auto 0 0 !important;\n width: max-content;\n max-width: 92vw;\n z-index: 40 !important;\n transform: translateX(-110%);\n transition: transform .28s ease-in-out;\n background: var(--dsw-alias-bg-base, #ffffff);\n padding-top: env(safe-area-inset-top, 0px) !important;\n border-right: none !important;\n touch-action: pan-y pinch-zoom !important;\n }\n [${FRAME_ATTR}=\"frame\"]:not([${COLLAPSED_ATTR}]) > :first-child { transform: none !important; }\n @media (prefers-reduced-motion: reduce) {\n [${FRAME_ATTR}=\"frame\"] > :first-child { transition: none !important; }\n }\n\n /* 拖拽手柄在触屏上无用 */\n [data-side=\"sidebar\"], [data-side=\"details\"] { display: none !important; }\n\n /* 对话区:去桌面滚动条占位,收窄 gutter,字号降一档 */\n [data-phase] [class*=\"_scrollBody\"] { scrollbar-gutter: auto !important; scrollbar-width: none; }\n [data-phase] [class*=\"_scrollBody\"]::-webkit-scrollbar { display: none !important; width: 0; height: 0; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) { padding-left: 20px; padding-right: 20px; font-size: 15px !important; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) p,\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) li,\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) [class*=\"_text_\"] { font-size: 15px !important; }\n [data-phase] table { width: 100%; max-width: 100%; }\n [data-phase] th, [data-phase] td { max-width: none; min-width: 0; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]) img { width: auto !important; max-width: 100% !important; height: auto !important; max-height: 220px !important; }\n [data-phase] [class*=\"_userStack\"], [data-phase] [class*=\"_userStack\"] [class*=\"_bubble\"] { box-sizing: border-box; width: fit-content; max-width: 100%; }\n [data-phase] [class*=\"_actions\"] { overflow: hidden; }\n\n /* 统计行(turns/steps/LLM/TPS):窄屏横向滚动,指标可滑动看全 */\n [${FRAME_ATTR}=\"stats\"] {\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center;\n gap: 6px;\n overflow-x: auto !important;\n max-width: 100% !important;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n [${FRAME_ATTR}=\"stats\"]::-webkit-scrollbar { display: none; }\n [${FRAME_ATTR}=\"stats\"] > * { flex-shrink: 0 !important; white-space: nowrap !important; }\n [${FRAME_ATTR}=\"stats\"] { gap: 6px !important; }\n [class*=\"composerStack\"] { gap: 4px !important; }\n /* stats line 竖线分隔符(|)两边 margin 10px 太松,适度收紧 */\n [data-phase] [class*=\"_sep\"] { margin: 0 3px !important; }\n\n /* 每轮回复下方的统计文字(footer):收紧 actions 内部 gap 与气泡到 footer 间距,减少松散感 */\n [data-phase] [class*=\"_actions\"] { gap: 4px !important; }\n [data-phase] [class*=\"_actions\"] [class*=\"_timeEnd\"] { gap: 4px !important; padding-left: 6px !important; }\n [data-phase] [class*=\"userRow\"], [data-phase] [class*=\"assistantRow\"] { gap: 4px !important; }\n /* 点号(·)左右 margin 10px 太松,收紧并抵消前后空格 */\n [data-phase] [class*=\"_runTimeDot\"] { margin: 0 -2px !important; }\n /* footer 容器各项间距 16px 偏松 */\n [data-phase] [class*=\"_root\"][class*=\"osXY9a\"] { gap: 8px !important; }\n /* footer 统计行窄屏可横向滑动看全,不溢出页面 */\n [data-phase] [class*=\"_actions\"] { max-width: 100% !important; overflow-x: auto !important; scrollbar-width: none; touch-action: pan-x pan-y !important; }\n [data-phase] [class*=\"_actions\"]::-webkit-scrollbar { display: none; }\n\n /* 模型切换菜单:名称完整展示,长名称在菜单项内换行。 */\n [class*=\"_submenu_\"] [class*=\"_itemLabel_\"] {\n overflow: visible !important;\n text-overflow: clip !important;\n white-space: normal !important;\n overflow-wrap: anywhere;\n }\n\n /* 模型选择器(dsh-client-ui-model-selection,CSS 模块前缀 7KE1Ra_):\n 列表内模型名/描述默认 ellipsis 截断,改换行完整显示。除当前 hash 外,\n 再加 modelName 语义匹配,防止上游升级换 hash 后规则失效。\n 注意:必须用 break-word 而非 anywhere —— anywhere 让文字 min-content\n 宽度≈1 字符,配合全局 * {min-width:0} 会把 flex 行内名字列压到 1 字符宽,\n 出现\"一字符就换行\"。break-word 的 min-content 取最长词宽,只在真正\n 放不下时才断词。 */\n [class*=\"7KE1Ra_modelName\"],\n [class*=\"7KE1Ra_description\"],\n [class*=\"modelName\"] {\n white-space: normal !important;\n overflow-wrap: break-word;\n text-overflow: clip !important;\n overflow: visible !important;\n }\n\n /* 模型选择器弹窗:JS(installModelMenuPosition)在窄屏下改为 position:fixed\n 视口级浮层(fixed 不受祖先 overflow 裁剪),这里仅做静态兜底(JS 未生效时\n 仍从触发按钮左缘向右展开、宽度收进视口)。 */\n [class*=\"7KE1Ra_menu\"],\n [class*=\"_menu\"]:has([class*=\"modelName\"]) {\n left: 0 !important;\n right: auto !important;\n width: calc(100vw - 32px) !important;\n min-width: 0 !important;\n max-width: calc(100vw - 32px) !important;\n overflow-y: auto !important;\n max-height: calc(100vh - 120px) !important;\n }\n\n /* 工具调用执行结果/代码/JSON:窄屏可横向滑动。details 抽屉宽 min(92%,420px)\n 较窄,命令行输出/JSON 长行溢出被外层 overflow:hidden 裁剪看不到。命令行输出\n 改 white-space:pre(保持原格式不折行,像终端)+ overflow-x:auto 横向滑动;\n min-width:0+max-width:100% 约束宽度触发滚动。 */\n [data-phase] [class*=\"resultBlockText\"],\n [data-phase] [class*=\"payload\"]:not([class*=\"errorPayload\"]),\n [data-phase] [class*=\"sourceBlockContent\"] {\n white-space: pre !important;\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"resultBlockText\"]::-webkit-scrollbar,\n [data-phase] [class*=\"payload\"]::-webkit-scrollbar,\n [data-phase] [class*=\"sourceBlockContent\"]::-webkit-scrollbar { display: none !important; }\n\n /* JSON 预览/代码块/promptDiff:横向滑动(不折行,保持格式) */\n [data-phase] [class*=\"jsonPayload\"],\n [data-phase] [class*=\"jsonPreview\"],\n [data-phase] [class*=\"promptDiff\"],\n [data-phase] [class*=\"overviewPreview\"],\n [data-phase] [class*=\"resultBlocks\"],\n [data-phase] pre {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"jsonPayload\"]::-webkit-scrollbar,\n [data-phase] [class*=\"jsonPreview\"]::-webkit-scrollbar,\n [data-phase] [class*=\"promptDiff\"]::-webkit-scrollbar,\n [data-phase] [class*=\"overviewPreview\"]::-webkit-scrollbar,\n [data-phase] [class*=\"resultBlocks\"]::-webkit-scrollbar,\n [data-phase] pre::-webkit-scrollbar { display: none !important; }\n\n /* dsh-client-ui-tool 工具卡片(Bash 等命令输出,class 前缀 o3BgMG_):\n bodyScroll/ioSection 只有 overflow-y:auto,横向溢出传到 row{overflow:hidden}\n 被裁剪且无法滑动。给输出容器链设 overflow-x:auto(不覆盖上游 overflow-y),\n 让终端格式长行在卡片内横向滑动。 */\n [data-phase] [class*=\"bodyScroll\"],\n [data-phase] [class*=\"ioCard\"],\n [data-phase] [class*=\"ioSection\"],\n [data-phase] [class*=\"terminalBody\"],\n [data-phase] [class*=\"codeBody\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"bodyScroll\"]::-webkit-scrollbar,\n [data-phase] [class*=\"ioCard\"]::-webkit-scrollbar,\n [data-phase] [class*=\"ioSection\"]::-webkit-scrollbar,\n [data-phase] [class*=\"terminalBody\"]::-webkit-scrollbar,\n [data-phase] [class*=\"codeBody\"]::-webkit-scrollbar { display: none !important; }\n\n /* 终端组件(dsh-web-frontend,CSS 模块前缀 1gdtu_):多行命令上游按行渲染成\n 多个 _promptLine_>_command_ 元素,行级不能各自设 overflow(会变成每行独立\n 滚动)。唯一横向滚动容器是公共祖先 _header_1gdtu_32(本就 overflow-y:auto):\n 行链 _prompt_/_promptLine_/_command_ 全部撑到 max-content 且 overflow 可见,\n 长行内容溢出传入 _header_ 的 scrollWidth,所有行随 _header_ 同步滚动。\n _output_1gdtu_156(输出区)同理以其为唯一容器,_line_ 撑宽不裁剪。 */\n [data-phase] [class*=\"_header_1gdtu_\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n overscroll-behavior-x: contain;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"_prompt_1gdtu_\"],\n [data-phase] [class*=\"_promptLine_1gdtu_\"],\n [data-phase] [class*=\"_command_1gdtu_\"] {\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n /* Android Chrome TextAutosizer 按块宽计算 font boosting,max-content 行宽不一\n 导致各行字号参差;max-height 是其豁免条件,禁用放大并锁定继承字号。 */\n max-height: 999999px !important;\n }\n [data-phase] [class*=\"_command_1gdtu_\"] {\n display: inline-block;\n text-overflow: clip !important;\n white-space: pre !important;\n }\n [data-phase] [class*=\"_copyButton_1gdtu_\"] { position: sticky !important; right: 0; }\n [data-phase] [class*=\"_output_1gdtu_\"] {\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"_output_1gdtu_\"]::-webkit-scrollbar { display: none !important; }\n [data-phase] [class*=\"_line_1gdtu_\"] {\n min-width: max-content !important;\n overflow-x: visible !important;\n max-height: 999999px !important;\n }\n\n /* 复制按钮周边也允许纵向页面手势,避免代码/总结区域形成触控死区。 */\n [data-phase] [class*=\"_copyButton_\"] { touch-action: manipulation !important; }\n [data-phase] [class*=\"_copyAnchor_\"],\n [data-phase] [class*=\"_body_1ye18_\"],\n [data-phase] [class*=\"_root_4qrvp_\"] { touch-action: pan-x pan-y !important; }\n\n /* 上下文用量弹窗(ContextMeter .JObwrW_panel):上游 dsh-client-ui-trajectory 的\n [class*=\"panel\"] 全局规则给它加了 max-width:100%!important,命中本弹窗,使宽度\n 从 264px 塌缩到包含块(.root 28px)宽,内容竖排成竖条。窄屏解除该误伤。 */\n .JObwrW_panel { max-width: none !important; overflow-x: visible !important; }\n\n /* 头部:标题省略,tab 条横向滚动 */\n [${FRAME_ATTR}=\"frame\"] [data-phase] header { padding-left: 44px; padding-right: 8px; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [class*=\"_crumbs\"] { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap !important; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"] { flex-wrap: nowrap; gap: 0 16px; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"]::-webkit-scrollbar { display: none; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"] > button { flex-shrink: 0; white-space: nowrap; }\n\n /* 设置对话框:窄屏近全宽 sheet(排除导出等普通对话框与目录选择器) */\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) {\n position: absolute !important;\n left: 8px !important;\n top: calc(env(safe-area-inset-top, 0px) + 12px) !important;\n width: calc(100vw - 16px) !important;\n max-width: calc(100vw - 16px) !important;\n height: auto !important;\n max-height: calc(100dvh - 24px - env(safe-area-inset-top, 0px)) !important;\n flex-direction: column !important;\n border-radius: 14px !important;\n }\n [aria-modal=\"true\"]:not(:has(> :first-child > :last-child > button)) { max-width: calc(100vw - 32px) !important; }\n /* nav:横排换行(避免 CJK 标签竖排楼梯状),隐藏冗余 caption */\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :first-child {\n width: 100%;\n flex-direction: row !important;\n align-items: center;\n gap: 6px;\n padding: 10px 12px 8px;\n }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :first-child > :first-child { display: none !important; }\n [aria-modal=\"true\"] [class*=\"_navList\"] { flex: 1 1 auto; min-width: 0; flex-direction: row !important; flex-wrap: wrap; gap: 6px; overflow: visible; }\n [aria-modal=\"true\"] [class*=\"_navList\"] > button { flex-shrink: 0; white-space: nowrap; }\n /* 外观模式卡片横排 */\n [aria-modal=\"true\"] [class*=\"_cubeRow\"] { gap: 6px; }\n [aria-modal=\"true\"] [class*=\"_cubeRow\"] > * { flex: 1 1 0; flex-direction: row !important; align-items: center; justify-content: center; gap: 6px; padding: 10px 8px; min-height: 0; }\n /* section 填充 sheet 宽度 */\n [aria-modal=\"true\"] [class*=\"_section\"] { width: 100% !important; max-width: none !important; }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :last-child { flex: 1 1 auto; min-height: 0; }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :last-child > :last-child { padding: 0 12px 24px; }\n\n /* 切换按钮:固定头部左侧 */\n [${FRAME_ATTR}=\"toggle\"] {\n position: absolute !important;\n left: 8px !important;\n top: 12px !important;\n z-index: 2 !important;\n display: inline-flex !important;\n align-items: center; justify-content: center;\n width: 28px; height: 28px;\n padding: 0; border: none; background: none; cursor: pointer; color: inherit;\n -webkit-tap-highlight-color: transparent;\n }\n\n /* 首页/hero(无活跃会话,session header 不存在)的抽屉切换 FAB:\n 浮在顶部相机带下方,避免与 hero 头部内容重叠 */\n [${FRAME_ATTR}=\"fab\"] {\n position: absolute !important;\n top: calc(env(safe-area-inset-top, 0px) + 72px) !important;\n left: 10px !important;\n z-index: 21 !important;\n display: inline-flex !important;\n align-items: center; justify-content: center;\n width: 38px; height: 38px;\n padding: 0;\n border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, .12)) !important;\n border-radius: 50% !important;\n background: var(--dsw-alias-button-floating-fill, #ffffff) !important;\n color: var(--dsw-alias-label-primary, inherit) !important;\n cursor: pointer !important;\n box-shadow: 0 2px 12px rgba(0, 0, 0, .18) !important;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n/* 宽屏 / 鼠标指针:隐藏切换按钮 */\n@media (min-width: 1024px), (pointer: fine) {\n [${FRAME_ATTR}=\"toggle\"], [${FRAME_ATTR}=\"fab\"] { display: none !important; }\n}\n`\n\nfunction findFrame(): HTMLElement | null {\n return document.querySelector('[data-shell-overlay]')?.parentElement ?? null\n}\n\nfunction getFrame(): HTMLElement | null {\n return document.querySelector(`[${FRAME_ATTR}=\"frame\"]`) ?? findFrame()\n}\n\n/** viewport-fit=cover:让 safe-area-inset 生效,内容避开刘海/状态栏。 */\nfunction installViewport(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n const viewport = document.querySelector<HTMLMetaElement>('meta[name=\"viewport\"]')\n if (viewport === null) return () => {}\n const original = viewport.content\n const sync = (): void => {\n viewport.content = narrow.matches\n ? 'width=device-width, initial-scale=1, viewport-fit=cover'\n : original\n }\n sync()\n narrow.addEventListener('change', sync)\n return () => {\n narrow.removeEventListener('change', sync)\n viewport.content = original\n }\n }, 'dshb-mobile: viewport')\n}\n\nfunction installStyles(ctx: ClientContext): void {\n ctx.effect(() => {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dshb-mobile'\n tag.textContent = MOBILE_CSS\n document.head.appendChild(tag)\n // 保持在 head 最后,确保覆盖宿主样式\n setTimeout(() => { if (tag.isConnected) document.head.appendChild(tag) }, 0)\n return () => { tag.remove() }\n }, 'dshb-mobile: styles')\n}\n\n/** 给 AppFrame 打标记(drawer CSS 选择器挂载点),窄屏才打。 */\nfunction installFrameMarker(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n let frame: HTMLElement | null = null\n const clear = (): void => {\n if (frame !== null) frame.removeAttribute(FRAME_ATTR)\n frame = null\n }\n const ensure = (): void => {\n if (!narrow.matches) return\n frame = findFrame()\n if (frame !== null && !frame.hasAttribute(FRAME_ATTR)) frame.setAttribute(FRAME_ATTR, 'frame')\n }\n ensure()\n const mo = new MutationObserver(ensure)\n mo.observe(document.documentElement, { childList: true, subtree: true })\n const onChange = (): void => { if (narrow.matches) ensure(); else clear() }\n narrow.addEventListener('change', onChange)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', onChange)\n clear()\n }\n }, 'dshb-mobile: frame marker')\n}\n\n/**\n * 抽屉打开时覆盖内容区的半透明遮罩,点击关闭;Escape 同样关闭;\n * 点击抽屉内的会话/导航项后关闭抽屉。\n */\nfunction installDrawerInteractions(ctx: ClientContext, toggleSidebar: () => void): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n let backdrop: HTMLElement | null = null\n const drawerOpen = (): boolean => {\n const frame = getFrame()\n return narrow.matches && frame !== null && !frame.hasAttribute(COLLAPSED_ATTR)\n }\n const sync = (): void => {\n if (drawerOpen() && backdrop === null) {\n backdrop = document.createElement('div')\n backdrop.setAttribute(`${FRAME_ATTR}-backdrop`, '')\n backdrop.style.cssText = 'position:fixed;inset:0;z-index:39;background:rgba(0,0,0,.4);-webkit-tap-highlight-color:transparent;'\n backdrop.addEventListener('click', () => toggleSidebar())\n document.body.appendChild(backdrop)\n } else if (!drawerOpen() && backdrop !== null) {\n backdrop.remove()\n backdrop = null\n }\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n if (document.querySelector('[aria-modal=\"true\"]') !== null) return\n if (drawerOpen()) toggleSidebar()\n }\n const onClick = (event: MouseEvent): void => {\n if (!drawerOpen()) return\n const target = event.target\n if (!(target instanceof Element)) return\n const drawer = document.querySelector(`[${FRAME_ATTR}=\"frame\"] > :first-child`)\n if (drawer === null || !drawer.contains(target)) return\n if (target.closest('button, a, [role=\"button\"]') !== null) return\n if (target.closest('[class*=\"newSession\"], [class*=\"sessionRow\"], [role=\"treeitem\"], [class*=\"searchResult\"]') !== null) toggleSidebar()\n }\n sync()\n const mo = new MutationObserver(sync)\n mo.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: [COLLAPSED_ATTR] })\n document.addEventListener('keydown', onKeyDown, true)\n document.addEventListener('click', onClick, true)\n narrow.addEventListener('change', sync)\n return () => {\n mo.disconnect()\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', onClick, true)\n narrow.removeEventListener('change', sync)\n backdrop?.remove()\n }\n }, 'dshb-mobile: drawer interactions')\n}\n\n/** 对话/输入框下方的统计行(turns/steps/LLM/TPS):hashed class 无法直接选,按文本特征标记后由 CSS 横向滚动,避免溢出。 */\nfunction installStatsLine(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n // 统计行文本特征(\"3 轮 · 5 步 · LLM 2.1s · 缓存命中 80%\" 等),hashed class 无法直接选,按文本识别。\n // 含\"轮/步/turns/steps\"即可(footer 不含这些),无需额外排除 footer。\n const STATS_LINE_RE = /(\\d+\\s*轮|\\d+\\s*步|\\bturns\\b|\\bsteps\\b)/\n const isStatsText = (el: Element): boolean => {\n const text = (el.textContent ?? '').trim()\n if (text.length === 0 || text.length > 160) return false\n if (!STATS_LINE_RE.test(text)) return false\n if (el.querySelector('textarea, input, button, select, a') !== null) return false\n return true\n }\n const mark = (): void => {\n if (!narrow.matches) return\n // 清除失效标记:行容器仍含统计特征(轮/步)才保留\n document.querySelectorAll(`[${FRAME_ATTR}=\"stats\"]`).forEach((el) => {\n if (!el.isConnected || !STATS_LINE_RE.test((el.textContent ?? '').trim())) el.removeAttribute(FRAME_ATTR)\n })\n // 候选:含统计特征的短文本元素(全文档搜索,含 composer 内的 stats line),取最浅容器标记\n // 排除 display:contents(无 box,overflow 无效,会误占最浅候选)\n const cands = Array.from(document.querySelectorAll('span, div')).filter((el) => {\n if (!isStatsText(el)) return false\n if (getComputedStyle(el).display === 'contents') return false\n return true\n })\n for (const el of cands) {\n if (el.hasAttribute(FRAME_ATTR)) continue\n let anc = el.parentElement\n let hasOuterCand = false\n while (anc) {\n if (cands.includes(anc)) { hasOuterCand = true; break }\n anc = anc.parentElement\n }\n if (!hasOuterCand) {\n // 标最浅含统计的容器本身(整行),使其可横向滚动\n if (!el.hasAttribute(FRAME_ATTR)) el.setAttribute(FRAME_ATTR, 'stats')\n }\n }\n }\n mark()\n const mo = new MutationObserver(() => { if (narrow.matches) mark() })\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', mark)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', mark)\n }\n }, 'dshb-mobile: stats line')\n}\n\n/** 浮层 fixed 定位需管理的内联样式键,清理时逐一移除以交还上游 CSS。 */\nconst SHEET_PROPS = [\n 'position', 'width', 'left', 'right', 'top', 'bottom',\n 'min-width', 'max-width', 'max-height', 'overflow-y', 'box-sizing',\n] as const\n\n/**\n * 把挂在 composer 内部的绝对定位浮层统一改造成 position:fixed 视口级浮层:\n * 水平居中(左右各留 8px,绝不贴边/溢出),高度按视口比例封顶并内容滚动,\n * 触发元素上方空间足够则向上展开、否则向下展开,四边都约束在视口内。\n * fixed 不受祖先 overflow 裁剪(祖先带 transform 时失效)。\n */\nfunction positionFixedSheet(\n el: HTMLElement,\n rootRect: DOMRect,\n maxWidth: number,\n maxHeightRatio: number,\n): void {\n const margin = 8\n const vw = window.innerWidth\n const vh = window.innerHeight\n const width = Math.max(0, Math.min(maxWidth, vw - margin * 2))\n const left = Math.round((vw - width) / 2)\n const maxH = Math.round(vh * maxHeightRatio)\n const spaceAbove = rootRect.top - margin\n const spaceBelow = vh - rootRect.bottom - margin\n const expandUp = spaceAbove >= 140 && spaceAbove >= spaceBelow\n let top: number\n if (expandUp) {\n const h = Math.min(maxH, Math.max(spaceAbove, 140))\n top = rootRect.top - margin - h\n } else {\n top = rootRect.bottom + margin\n }\n top = Math.max(margin, top)\n el.style.setProperty('position', 'fixed', 'important')\n el.style.setProperty('box-sizing', 'border-box', 'important')\n el.style.setProperty('width', `${width}px`, 'important')\n el.style.setProperty('left', `${left}px`, 'important')\n el.style.setProperty('right', 'auto', 'important')\n el.style.setProperty('top', `${top}px`, 'important')\n el.style.setProperty('bottom', 'auto', 'important')\n el.style.setProperty('min-width', '0', 'important')\n el.style.setProperty('max-width', 'none', 'important')\n el.style.setProperty('max-height', `${maxH}px`, 'important')\n el.style.setProperty('overflow-y', 'auto', 'important')\n}\n\n/**\n * 一级 pane(Model/Effort 单元格小菜单)紧凑浮层:右缘对齐触发按钮右缘\n * (面板右缘 x = 按钮右缘 x,钳制在视口内 8px 起,避免宽面板超出屏幕左缘时\n * 被甩到左边贴边),向上展开、空间不足向下展开;宽度跟随内容\n * (max-content,封顶 min(420, vw-16)),避免小菜单被全宽 sheet 拉远到\n * 屏幕中间。测量与定位在同一任务内同步完成,无闪烁。\n */\nfunction positionCompactPanel(el: HTMLElement, root: HTMLElement, rootRect: DOMRect): void {\n const margin = 8\n const vw = window.innerWidth\n // 锚定触发按钮本身(root 包着按钮,取按钮 rect 更准;换 hash 后按语义类找)\n const trigger =\n root.querySelector<HTMLElement>('[class*=\"7KE1Ra_trigger\"], [class*=\"_trigger\"]') ?? root\n const anchorRect = trigger === root ? rootRect : trigger.getBoundingClientRect()\n el.style.setProperty('position', 'fixed', 'important')\n el.style.setProperty('box-sizing', 'border-box', 'important')\n el.style.setProperty('left', '0', 'important')\n el.style.setProperty('top', '0', 'important')\n el.style.setProperty('right', 'auto', 'important')\n el.style.setProperty('bottom', 'auto', 'important')\n el.style.setProperty('width', 'max-content', 'important')\n el.style.setProperty('min-width', '0', 'important')\n el.style.setProperty('max-width', `${Math.min(420, vw - margin * 2)}px`, 'important')\n el.style.setProperty('max-height', 'none', 'important')\n el.style.setProperty('overflow-y', 'visible', 'important')\n const w = el.offsetWidth\n const h = el.offsetHeight\n const panelRightX = Math.min(anchorRect.right, vw - margin)\n const expandUp = anchorRect.top - margin - h >= margin\n const top = Math.max(margin, expandUp ? anchorRect.top - margin - h : anchorRect.bottom + margin)\n const left = Math.max(margin, panelRightX - w)\n el.style.setProperty('left', `${left}px`, 'important')\n el.style.setProperty('top', `${top}px`, 'important')\n el.style.setProperty('width', `${w}px`, 'important')\n}\n\n/**\n * 模型名多为纯连字符词(DeepSeek-V4-Flash-Vision-Exp);white-space:normal 下\n * 每个 \"-\" 都是软断点,名字一旦超列宽就在第一个连字符处断行(\"换行太早\")。\n * 把 \"-\" 就地换成不换行连字符 U+2011:放得下就整行显示,真超宽时仍由\n * overflow-wrap:break-word 兜底任意断。只改文本节点 data、不换节点,\n * 避免与 React 文本协调冲突;React 重渲染重置文本后由 MutationObserver\n * 重新应用(幂等:换过之后不再有 \"-\")。\n */\nfunction applyNonBreakingHyphens(menu: HTMLElement): void {\n for (const el of Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))) {\n const tn = el.firstChild\n if (tn && tn.nodeType === Node.TEXT_NODE && tn.nodeValue !== null && tn.nodeValue.includes('-')) {\n tn.nodeValue = tn.nodeValue.replace(/-/g, '\\u2011')\n }\n }\n}\n\n/**\n * 模型名\"整行显示、不换行、不截断\":窄屏下把名字列里的所有 .modelName 设为\n * nowrap,并按\"最宽名字 vs 可用列宽\"统一缩小字号(下限 11px,上限 14px),\n * 让最长的名字也恰好放得下——从根上消除\"换行太早\"。只测一次最宽名字\n * (scrollWidth 一次布局读取),缩放结果应用到全部名字,保持同一字号。\n * 调用方按 vw + 名字集合签名缓存,避免每次 DOM 变更都强制作废布局。\n */\nfunction fitModelNameFont(menu: HTMLElement): void {\n const names = Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))\n if (names.length === 0) return\n const col = names[0].parentElement\n if (col === null) return\n const colW = col.clientWidth - 4\n if (colW <= 0) return\n const base = 14\n let longest = names[0]\n for (const n of names) {\n if ((n.textContent?.length ?? 0) > (longest.textContent?.length ?? 0)) longest = n\n }\n const prevWs = longest.style.whiteSpace\n longest.style.whiteSpace = 'nowrap'\n longest.style.fontSize = `${base}px`\n const natural = longest.scrollWidth\n longest.style.whiteSpace = prevWs\n longest.style.fontSize = ''\n const fs = natural > colW ? Math.max(11, Math.min(base, Math.round(base * (colW / natural)))) : base\n for (const n of names) {\n n.style.setProperty('white-space', 'nowrap', 'important')\n n.style.setProperty('font-size', `${fs}px`, 'important')\n }\n}\n\n/** 宽屏(窄屏判定不成立)时复位名字列内联样式,交还上游 CSS(nowrap+ellipsis)。 */\nfunction clearModelNameFit(menu: HTMLElement | null | undefined): void {\n if (menu === null || menu === undefined) return\n for (const n of Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))) {\n n.style.removeProperty('white-space')\n n.style.removeProperty('font-size')\n }\n}\n\n/** 清除 positionFixedSheet 写入的内联样式,交还上游/移动端 CSS 兜底。 */\nfunction clearFixedSheet(el: HTMLElement | null | undefined): void {\n if (el === null || el === undefined) return\n for (const key of SHEET_PROPS) el.style.removeProperty(key)\n}\n\n/**\n * 模型选择弹窗(dsh-client-ui-model-selection)是两级 pane 的同一个 `_7KE1Ra_menu`\n * 元素:一级 Model/Effort 单元格列表(cellLabel),点击后切到模型列表(modelName)\n * 或档位列表。上游默认 `position:absolute;right:0` 贴触发按钮右缘,触发按钮在\n * 可横向滚动的 stats 行内时菜单会整体出屏。两级 pane 都必须接管(不能只按\n * modelName 匹配,否则一级 pane 漏掉)。窄屏下:一级小菜单走紧凑浮层\n * (右缘贴按钮、向上展开,避免全宽 sheet 把小菜单拉到屏幕中间离按钮太远);\n * 二级列表走视口级居中 fixed sheet(左右各 8px、高度 45% 视口封顶、\n * 内容滚动、上方空间不足时向下展开)。\n */\nfunction installModelMenuPosition(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(NARROW_QUERY)\n // 多 tab 场景可能并存多个模型选择器(各自一个 _menu);只处理可见的,\n // 避免 document.querySelector 命中隐藏 tab 的菜单而漏掉用户正在看的那个。\n const findMenus = (): HTMLElement[] => {\n const byHash = Array.from(document.querySelectorAll<HTMLElement>('[class*=\"7KE1Ra_menu\"]'))\n if (byHash.length > 0) return byHash\n // 上游升级换 hash 后回退:语义类匹配(cellLabel 命中一级 pane,modelName 命中二级)\n return Array.from(document.querySelectorAll<HTMLElement>('[class*=\"_menu\"]')).filter((el) =>\n el.querySelector('[class*=\"cellLabel\"], [class*=\"modelName\"]') !== null,\n )\n }\n const findTrigger = (menu: HTMLElement): HTMLElement | null => {\n if (menu.id) {\n const controlled = Array.from(document.querySelectorAll<HTMLElement>('[aria-controls]')).find(\n (el) => el.getAttribute('aria-controls') === menu.id,\n )\n if (controlled) return controlled\n }\n return document.querySelector<HTMLElement>('[class*=\"7KE1Ra_trigger\"][aria-expanded=\"true\"]')\n }\n let fittedVw = 0\n let fittedSig = -1\n let fittedMenus: HTMLElement[] = []\n const sync = (): void => {\n const menus = findMenus()\n if (!narrow.matches) {\n // Desktop: upstream place() owns menu positioning via inline left/top.\n // Only clear DSHB's !important overrides when transitioning FROM narrow\n // mode (fittedMenus non-empty). Clearing on every MutationObserver tick\n // would strip upstream's menuPos and drop the menu off-screen.\n if (fittedMenus.length > 0) {\n for (const menu of fittedMenus) {\n clearFixedSheet(menu)\n clearModelNameFit(menu)\n }\n fittedVw = 0\n fittedSig = -1\n fittedMenus = []\n window.dispatchEvent(new Event('resize'))\n }\n return\n }\n let vw = 0\n let sig = 0\n const modelMenus: HTMLElement[] = []\n for (const menu of menus) {\n // 0.1.5 renders the menu through createPortal(..., document.body), so\n // parentElement is body rather than the trigger root. Match aria-controls\n // to the portal menu id to find the exact trigger across multiple tabs.\n const trigger = findTrigger(menu)\n if (trigger === null) continue\n const rect = menu.getBoundingClientRect()\n // 跳过隐藏 tab / 未打开的菜单(0 尺寸或祖先 display:none)\n if (rect.width === 0 && rect.height === 0) continue\n const triggerRect = trigger.getBoundingClientRect()\n if (menu.querySelector('[class*=\"modelName\"]')) {\n positionFixedSheet(menu, triggerRect, Number.POSITIVE_INFINITY, 0.45)\n applyNonBreakingHyphens(menu)\n modelMenus.push(menu)\n vw = window.innerWidth\n for (const n of menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]')) {\n sig += n.textContent?.length ?? 0\n }\n } else {\n positionCompactPanel(menu, trigger, triggerRect)\n }\n }\n // 菜单关闭再打开时 React 会重建菜单元素(新元素没有任何内联样式),\n // 所以缓存必须含元素身份:vw / 名字集合 / 菜单实例任一变化都要重测,\n // 否则重开的菜单会漏掉 nowrap+缩字而再次换行。\n const needFit = modelMenus.some((m) => !fittedMenus.includes(m))\n if (vw > 0 && (needFit || vw !== fittedVw || sig !== fittedSig)) {\n for (const menu of modelMenus) fitModelNameFont(menu)\n fittedVw = vw\n fittedSig = sig\n fittedMenus = modelMenus\n }\n }\n sync()\n const mo = new MutationObserver(() => requestAnimationFrame(sync))\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', sync)\n window.addEventListener('resize', sync)\n window.addEventListener('scroll', sync, true)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n window.removeEventListener('resize', sync)\n window.removeEventListener('scroll', sync, true)\n }\n }, 'dshb-mobile: model menu position')\n}\n\n/**\n * 上下文用量弹窗(ContextMeter .JObwrW_panel,dsh-client-ui-conversation)上游是\n * `position:absolute; bottom:calc(100%+8px); right:0` 挂 .JObwrW_root 内。窄屏下\n * 改为 fixed 视口浮层,右缘锚定触发按钮右缘、向上展开(用户已验证该形态正常,勿改)。\n */\nfunction installContextPanelPosition(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(NARROW_QUERY)\n const sync = (): void => {\n if (!narrow.matches) return\n const panels = document.querySelectorAll<HTMLElement>('[class*=\"JObwrW_panel\"]')\n for (const panel of Array.from(panels)) {\n const root = panel.parentElement\n if (root === null || !root.className.includes('JObwrW_root')) continue\n const rootRect = root.getBoundingClientRect()\n if (rootRect.width === 0 && rootRect.height === 0) continue\n const gap = 8\n panel.style.setProperty('position', 'fixed', 'important')\n panel.style.setProperty('top', 'auto', 'important')\n panel.style.setProperty('bottom', `${window.innerHeight - rootRect.top + gap}px`, 'important')\n panel.style.setProperty('left', 'auto', 'important')\n panel.style.setProperty('right', `${Math.max(gap, window.innerWidth - rootRect.right)}px`, 'important')\n panel.style.setProperty('max-height', `${Math.max(160, rootRect.top - gap * 2)}px`, 'important')\n panel.style.setProperty('overflow-y', 'auto', 'important')\n }\n }\n sync()\n const mo = new MutationObserver(() => requestAnimationFrame(sync))\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', sync)\n window.addEventListener('resize', sync)\n window.addEventListener('scroll', sync, true)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n window.removeEventListener('resize', sync)\n window.removeEventListener('scroll', sync, true)\n }\n }, 'dshb-mobile: context panel position')\n}\n\ninterface LayoutLike { toggleSidebar(): void }\ninterface SlotsLike {\n inject(name: string, fn: () => unknown): unknown\n register(spec: Record<string, unknown>, component: unknown): unknown\n}\n\n/** 目录抽屉切换按钮(仅切换,不含文件浏览/日志导出等功能按钮)。 */\nfunction DrawerToggle({ toggleSidebar }: { toggleSidebar: () => void }) {\n return (\n <button type=\"button\" data-dshb-mobile=\"toggle\" aria-label=\"打开目录\" title=\"打开目录\" onClick={() => toggleSidebar()}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M6 2.5v11\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n </button>\n )\n}\n\nconst PANEL_ICON_SVG =\n '<svg width=\"18\" height=\"18\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">' +\n '<rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>' +\n '<path d=\"M6 2.5v11\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>' +\n '</svg>'\n\n/**\n * 首页 / hero(无活跃会话)没有 session header,header 上的切换按钮不渲染;\n * 这里在 frame 上注入一个浮动切换按钮(FAB),仅 hero 且抽屉收起时显示。\n */\nfunction installFab(ctx: ClientContext, toggleSidebar: () => void): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n const FAB_ATTR = 'fab'\n const heroPhase = (): boolean => document.querySelector('[data-phase=\"active\"]') === null\n const drawerOpen = (): boolean => {\n const frame = getFrame()\n return frame !== null && !frame.hasAttribute(COLLAPSED_ATTR)\n }\n let fab: HTMLButtonElement | null = null\n const sync = (): void => {\n if (!narrow.matches || !heroPhase() || drawerOpen()) {\n if (fab !== null) {\n fab.remove()\n fab = null\n }\n return\n }\n const frame = getFrame()\n if (frame === null) return\n if (fab !== null && fab.parentElement === frame) return\n fab?.remove()\n fab = document.createElement('button')\n fab.type = 'button'\n fab.setAttribute(FRAME_ATTR, FAB_ATTR)\n fab.setAttribute('aria-label', '打开目录')\n fab.setAttribute('title', '打开目录')\n fab.innerHTML = PANEL_ICON_SVG\n fab.addEventListener('click', toggleSidebar)\n frame.appendChild(fab)\n }\n sync()\n const mo = new MutationObserver(sync)\n mo.observe(document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-phase', 'data-sidebar-collapsed', 'class'],\n })\n narrow.addEventListener('change', sync)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n fab?.remove()\n }\n }, 'dshb-mobile: hero fab')\n}\n\n/** 安装移动端适配:样式 + viewport + 抽屉标记 + 抽屉交互 + 切换按钮。 */\nexport function installMobile(ctx: ClientContext): void {\n installStyles(ctx)\n installViewport(ctx)\n installFrameMarker(ctx)\n installStatsLine(ctx)\n installModelMenuPosition(ctx)\n installContextPanelPosition(ctx)\n const layout = (ctx as unknown as { layout?: LayoutLike }).layout\n const slots = (ctx as unknown as { slots?: SlotsLike }).slots\n if (layout && typeof layout.toggleSidebar === 'function') {\n const toggleSidebar = (): void => layout.toggleSidebar()\n installDrawerInteractions(ctx, toggleSidebar)\n installFab(ctx, toggleSidebar)\n }\n if (slots && layout) {\n slots.inject('conversation.session.header.actions', () =>\n slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'dshb-mobile-toggle',\n order: 10,\n inject: () => ({ toggleSidebar: () => layout.toggleSidebar() }),\n },\n DrawerToggle,\n ),\n )\n }\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n\ninterface WorkspaceItem {\n workspaceId: string\n title: string\n path: string\n}\n\ninterface WorkspaceSnapshotLike {\n items: readonly WorkspaceItem[]\n}\n\ninterface WorkspacesLike {\n list: {\n getSnapshot(): WorkspaceSnapshotLike\n subscribe(listener: () => void): () => void\n }\n}\n\nlet injectedRegistry: WorkspacesLike | undefined\n\nexport function setWorkspaceRegistry(reg: WorkspacesLike): void {\n injectedRegistry = reg\n}\n\nfunction resolveWorkspaceByTitle(title: string): WorkspaceItem | undefined {\n const wks = injectedRegistry\n if (!wks) return undefined\n const items = wks.list.getSnapshot().items\n return items.find((w) => w.title === title)\n}\n\nconst ROW_INJECT_FLAG = 'data-dshb-instr-row-bound'\nconst MENU_INJECT_FLAG = 'data-dshb-instr-menu-bound'\nconst MENU_ITEM_FLAG = 'data-dshb-instr-menu-item'\n\nfunction mountInstructionDialog(workspaceId: string, workspaceTitle: string): void {\n if (!workspaceId) return\n\n const overlay = document.createElement('div')\n overlay.style.cssText = 'position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;background:var(--dsw-alias-overlay-mask,rgba(0,0,0,.45))'\n\n const dialog = document.createElement('div')\n dialog.setAttribute('role', 'dialog')\n dialog.setAttribute('aria-label', `修改 ${workspaceTitle} 的项目指令`)\n dialog.style.cssText = 'box-sizing:border-box;width:min(92vw,600px);max-height:85vh;overflow:auto;padding:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)'\n\n const title = document.createElement('h2')\n title.textContent = `项目指令 - ${workspaceTitle}`\n title.style.cssText = 'margin:0 0 10px;font-size:16px'\n\n const description = document.createElement('div')\n description.textContent = '此内容会注入该工作区的新对话。已有对话继续使用创建时的指令快照。'\n description.style.cssText = 'margin-bottom:10px;font-size:12px;color:var(--dsw-alias-label-secondary)'\n\n const textarea = document.createElement('textarea')\n textarea.placeholder = '留空则不注入指令...'\n textarea.spellcheck = false\n textarea.style.cssText = 'box-sizing:border-box;width:100%;min-height:280px;resize:vertical;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px monospace'\n\n const status = document.createElement('div')\n status.style.cssText = 'min-height:18px;margin-top:6px;font-size:12px;color:var(--dsw-alias-label-secondary)'\n\n const actions = document.createElement('div')\n actions.style.cssText = 'display:flex;justify-content:flex-end;gap:10px;margin-top:14px'\n const cancel = document.createElement('button')\n cancel.type = 'button'\n cancel.textContent = '取消'\n cancel.style.cssText = 'height:36px;padding:0 16px;border:1px solid var(--dsw-alias-border-l2);border-radius:18px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer'\n const save = document.createElement('button')\n save.type = 'button'\n save.textContent = '保存'\n save.style.cssText = 'height:36px;padding:0 16px;border:0;border-radius:18px;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);cursor:pointer'\n\n const close = (): void => overlay.remove()\n cancel.addEventListener('click', close)\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) close()\n })\n dialog.addEventListener('click', (event) => event.stopPropagation())\n textarea.addEventListener('input', () => {\n const bytes = new TextEncoder().encode(textarea.value).length\n status.textContent = `${bytes} / 32768 字节`\n status.style.color = bytes > 32768 ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-secondary)'\n })\n save.addEventListener('click', () => {\n void (async () => {\n const bytes = new TextEncoder().encode(textarea.value).length\n if (bytes > 32768) {\n status.textContent = `指令超过 32768 字节限制(当前 ${bytes} 字节)`\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n return\n }\n save.disabled = true\n save.textContent = '保存中...'\n try {\n const revision = Number(overlay.dataset.revision ?? '0')\n const response = await fetch(`/api/dshb/instructions/${workspaceId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text: textarea.value, expectedRevision: revision }),\n })\n if (!response.ok) {\n const body = await response.json().catch(() => ({})) as { error?: string }\n status.textContent = body.error ?? `保存失败 (${response.status})`\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n return\n }\n close()\n } catch {\n status.textContent = '保存失败'\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n } finally {\n save.disabled = false\n save.textContent = '保存'\n }\n })()\n })\n\n actions.append(cancel, save)\n dialog.append(title, description, textarea, status, actions)\n overlay.append(dialog)\n document.body.append(overlay)\n\n status.textContent = '加载中...'\n void fetch(`/api/dshb/instructions/${workspaceId}`)\n .then(async (response) => {\n if (!response.ok) throw new Error(`读取失败 (${response.status})`)\n return response.json() as Promise<{ text?: string; revision?: number }>\n })\n .then((body) => {\n textarea.value = body.text ?? ''\n overlay.dataset.revision = String(body.revision ?? 0)\n textarea.dispatchEvent(new Event('input'))\n textarea.focus()\n })\n .catch((error: unknown) => {\n status.textContent = error instanceof Error ? error.message : '读取失败'\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n })\n}\n\nexport function registerWorkspaceInstructionMenu(ctx: ClientContext): void {\n const wks = (ctx as unknown as { workspaces?: WorkspacesLike }).workspaces\n if (wks) setWorkspaceRegistry(wks)\n\n let activeWorkspaceTitle = ''\n\n const findWorkspaceRow = (el: Node | null): HTMLElement | null => {\n let node = el instanceof HTMLElement ? el : null\n while (node) {\n if (node.className && typeof node.className === 'string' && node.className.includes('projectRow')) {\n return node\n }\n node = node.parentElement\n }\n return null\n }\n\n const getRowTitle = (row: HTMLElement): string | null => {\n const titleEl = row.querySelector('[class*=\"title\"]')\n if (!titleEl) return null\n return titleEl.textContent ?? null\n }\n\n const injectMenuItem = (menuContainer: HTMLElement): void => {\n if (menuContainer.getAttribute(MENU_INJECT_FLAG) || menuContainer.querySelector(`[${MENU_ITEM_FLAG}]`)) return\n menuContainer.setAttribute(MENU_INJECT_FLAG, '1')\n\n const existingItems = menuContainer.querySelectorAll('button, [role=\"menuitem\"]')\n let refItem: Element | null = null\n for (const item of Array.from(existingItems)) {\n const text = item.textContent ?? ''\n if (text.includes('重命名') || text.includes('Rename')) {\n refItem = item\n break\n }\n }\n if (!refItem) refItem = existingItems[existingItems.length - 1]\n if (!refItem) return\n\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.setAttribute('role', 'menuitem')\n btn.setAttribute(MENU_ITEM_FLAG, '1')\n if (refItem instanceof HTMLElement) {\n btn.className = refItem.className || ''\n btn.style.cssText = refItem.style.cssText\n }\n for (const className of Array.from(btn.classList)) {\n if (/danger|delete/i.test(className)) btn.classList.remove(className)\n }\n btn.style.color = 'var(--dsw-alias-label-primary)'\n btn.style.display = 'flex'\n btn.style.alignItems = 'center'\n btn.style.gap = '8px'\n\n const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n icon.setAttribute('width', '16')\n icon.setAttribute('height', '16')\n icon.setAttribute('viewBox', '0 0 16 16')\n icon.setAttribute('fill', 'none')\n icon.setAttribute('aria-hidden', 'true')\n icon.style.flex = 'none'\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('d', 'M3 11.75V13h1.25l7.37-7.37-1.25-1.25L3 11.75Zm9.59-7.34a.66.66 0 0 0 0-.94l-1.06-1.06a.66.66 0 0 0-.94 0l-.83.83 1.25 1.25.83-.83.75.75Z')\n path.setAttribute('fill', 'currentColor')\n icon.append(path)\n const label = document.createElement('span')\n label.textContent = '修改指令'\n btn.append(icon, label)\n btn.addEventListener('click', (e) => {\n e.stopPropagation()\n e.preventDefault()\n const ws = activeWorkspaceTitle ? resolveWorkspaceByTitle(activeWorkspaceTitle) : undefined\n mountInstructionDialog(ws?.workspaceId ?? '', activeWorkspaceTitle || 'Unknown')\n })\n\n refItem.parentElement?.insertBefore(btn, refItem.nextSibling)\n }\n\n const observer = new MutationObserver(() => {\n const projectRows = document.querySelectorAll('[class*=\"projectRow\"]')\n for (const row of Array.from(projectRows)) {\n const rowEl = row as HTMLElement\n if (rowEl.getAttribute(ROW_INJECT_FLAG)) continue\n rowEl.setAttribute(ROW_INJECT_FLAG, '1')\n const iconBtns = rowEl.querySelectorAll('button[class*=\"iconButton\"]')\n for (const btn of Array.from(iconBtns)) {\n const label = btn.getAttribute('aria-label') ?? ''\n if (label.includes('workspace') || label.includes('操作') || label.includes('actions')) {\n btn.addEventListener('click', () => {\n const title = getRowTitle(rowEl)\n if (title) activeWorkspaceTitle = title\n })\n }\n }\n }\n\n const menuItems = document.querySelectorAll('[role=\"menuitem\"]')\n for (const item of Array.from(menuItems)) {\n const text = item.textContent ?? ''\n if (text.includes('删除') || text.includes('Delete') || text.includes('重命名') || text.includes('Rename')) {\n const container = item.closest('[role=\"menu\"]') ?? item.parentElement\n if (container instanceof HTMLElement && !container.getAttribute(MENU_INJECT_FLAG)) {\n const row = findWorkspaceRow(container)\n if (row) {\n const title = getRowTitle(row)\n if (title) activeWorkspaceTitle = title\n }\n injectMenuItem(container)\n }\n }\n }\n })\n observer.observe(document.body, { childList: true, subtree: true })\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-workspace/client'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport { DirectoryFlowOccupant } from './directory-flow.js'\nimport { installMobile } from './mobile.js'\nimport { registerWorkspaceInstructionMenu } from './workspace-instruction-menu.js'\n\nexport const inject = ['connection', 'workspaces', 'slots', 'layout', 'conversation']\n\nconst SECTION_ID = 'dshb-nodes'\n\ninterface NodeProfileView {\n id: string\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n ssh?: {\n host: string\n port: number\n username: string\n auth: { kind: 'password' | 'key' | 'agent'; keyPath?: string }\n }\n docker?: {\n image?: string\n containerId?: string\n mode?: string\n resources?: { cpus?: number; memoryMB?: number }\n }\n hasSecret: { hasPassword: boolean; hasKey: boolean; hasPassphrase: boolean }\n status?: { reachable?: boolean; lastCheckedAt?: string; error?: string }\n provision?: { state: 'provisioning' | 'ready' | 'failed'; error?: string; containerId?: string; updatedAt: string }\n}\n\ninterface SshConfigEntryView {\n host: string\n port: number\n username: string\n identityFile?: string\n hasIdentityFile: boolean\n hasProxyJump: boolean\n}\n\ninterface FormState {\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n host: string\n port: string\n username: string\n authKind: 'password' | 'key' | 'agent'\n password: string\n privateKey: string\n passphrase: string\n keyPath: string\n dockerImage: string\n dockerCpus: string\n dockerMemory: string\n}\n\nconst EMPTY_FORM: FormState = {\n name: '',\n type: 'remote-ssh',\n host: '',\n port: '22',\n username: '',\n authKind: 'password',\n password: '',\n privateKey: '',\n passphrase: '',\n keyPath: '',\n dockerImage: '',\n dockerCpus: '',\n dockerMemory: '',\n}\n\ntype Notice = { kind: 'ok' | 'error'; text: string } | undefined\n\nconst inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n}\nconst buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n}\nconst primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\nconst secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n}\nconst dangerOutlineButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n}\n\nfunction useNodes(reloadKey: number): NodeProfileView[] {\n const [nodes, setNodes] = useState<NodeProfileView[]>([])\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const res = await fetch('/api/dshb/nodes')\n if (!res.ok) return\n const data = (await res.json()) as { nodes?: NodeProfileView[] }\n if (!cancelled) setNodes(data.nodes ?? [])\n } catch {}\n })()\n return () => {\n cancelled = true\n }\n }, [reloadKey])\n return nodes\n}\n\nexport function NodeSection(_props: PropsRuntime<'settings.section'>): ReactElement {\n const [reloadKey, setReloadKey] = useState(0)\n const nodes = useNodes(reloadKey)\n const [selectedId, setSelectedId] = useState<string | 'new'>('new')\n const [form, setForm] = useState<FormState>(EMPTY_FORM)\n const [notice, setNotice] = useState<Notice>(undefined)\n const [busy, setBusy] = useState(false)\n const [testing, setTesting] = useState(false)\n const [testResult, setTestResult] = useState<string | undefined>(undefined)\n const [sshConfigEntries, setSshConfigEntries] = useState<SshConfigEntryView[]>([])\n const [dockerBusy, setDockerBusy] = useState(false)\n\n const flash = useCallback((n: Notice) => {\n setNotice(n)\n if (n) setTimeout(() => setNotice(undefined), 6000)\n }, [])\n\n const reload = useCallback(() => setReloadKey((k) => k + 1), [])\n\n useEffect(() => {\n void (async () => {\n try {\n const res = await fetch('/api/dshb/ssh-config')\n if (!res.ok) return\n const data = (await res.json()) as { entries?: SshConfigEntryView[] }\n setSshConfigEntries(data.entries ?? [])\n } catch {}\n })()\n }, [])\n\n const selectNode = useCallback(\n (id: string | 'new') => {\n setSelectedId(id)\n setTestResult(undefined)\n setTesting(false)\n setDockerBusy(false)\n if (id === 'new') {\n setForm(EMPTY_FORM)\n return\n }\n const node = nodes.find((n) => n.id === id)\n if (!node) return\n setForm({\n name: node.name,\n type: node.type,\n host: node.ssh?.host ?? '',\n port: String(node.ssh?.port ?? 22),\n username: node.ssh?.username ?? '',\n authKind: node.ssh?.auth.kind ?? 'password',\n password: '',\n privateKey: '',\n passphrase: '',\n keyPath: node.ssh?.auth.keyPath ?? '',\n dockerImage: node.docker?.image ?? '',\n dockerCpus: node.docker?.resources?.cpus != null ? String(node.docker?.resources?.cpus) : '',\n dockerMemory: node.docker?.resources?.memoryMB != null ? String(node.docker?.resources?.memoryMB) : '',\n })\n },\n [nodes],\n )\n\n const importSshConfig = useCallback((entry: SshConfigEntryView) => {\n setForm((f) => ({\n ...f,\n type: 'remote-ssh',\n host: entry.host,\n port: String(entry.port),\n username: entry.username,\n authKind: entry.hasIdentityFile ? 'key' : f.authKind,\n keyPath: entry.identityFile ?? f.keyPath,\n name: f.name || entry.host,\n }))\n setTestResult(undefined)\n flash({ kind: 'ok', text: `已从 ~/.ssh/config 导入 ${entry.host}` })\n }, [flash])\n\n const save = useCallback(async () => {\n if (!form.name.trim()) {\n flash({ kind: 'error', text: '请填写节点名称' })\n return\n }\n setBusy(true)\n try {\n const isRemote = form.type === 'remote-ssh' || form.type === 'remote-docker'\n const isDocker = form.type === 'local-docker' || form.type === 'remote-docker'\n const payload: Record<string, unknown> = {\n name: form.name.trim(),\n type: form.type,\n ssh: isRemote\n ? {\n host: form.host.trim(),\n port: Number(form.port) || 22,\n username: form.username.trim(),\n auth: { kind: form.authKind, ...(form.keyPath.trim() ? { keyPath: form.keyPath.trim() } : {}) },\n }\n : undefined,\n secrets: isRemote\n ? {\n ...(form.password ? { password: form.password } : {}),\n ...(form.privateKey ? { privateKey: form.privateKey } : {}),\n ...(form.passphrase ? { passphrase: form.passphrase } : {}),\n }\n : undefined,\n docker: isDocker\n ? {\n mode: 'managed' as const,\n ...(form.dockerImage.trim() ? { image: form.dockerImage.trim() } : {}),\n ...(form.dockerCpus ? { resources: { cpus: Number(form.dockerCpus) || undefined } } : {}),\n ...(form.dockerMemory ? { resources: { memoryMB: Number(form.dockerMemory) || undefined } } : {}),\n ...(form.dockerCpus && form.dockerMemory ? { resources: { cpus: Number(form.dockerCpus) || undefined, memoryMB: Number(form.dockerMemory) || undefined } } : {}),\n }\n : undefined,\n }\n const url = selectedId === 'new' ? '/api/dshb/nodes' : `/api/dshb/nodes/${selectedId}`\n const res = await fetch(url, {\n method: selectedId === 'new' ? 'POST' : 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n const data = (await res.json()) as { ok?: boolean; error?: string; node?: NodeProfileView }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: selectedId === 'new' ? '节点已创建' : '节点已保存' })\n reload()\n if (data.node) setSelectedId(data.node.id)\n } else {\n flash({ kind: 'error', text: data.error ?? '保存失败' })\n }\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setBusy(false)\n }\n }, [form, selectedId, flash, reload])\n\n const remove = useCallback(async () => {\n if (selectedId === 'new') return\n setBusy(true)\n try {\n const res = await fetch(`/api/dshb/nodes/${selectedId}`, { method: 'DELETE' })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: '节点已删除' })\n setSelectedId('new')\n setForm(EMPTY_FORM)\n reload()\n } else {\n flash({ kind: 'error', text: data.error ?? '删除失败' })\n }\n } catch {\n flash({ kind: 'error', text: '删除失败' })\n } finally {\n setBusy(false)\n }\n }, [selectedId, flash, reload])\n\n const test = useCallback(async () => {\n if (form.type === 'local-host') {\n flash({ kind: 'error', text: '本地节点无需测试连接' })\n return\n }\n const isRemote = form.type === 'remote-ssh' || form.type === 'remote-docker'\n if (isRemote && !form.host.trim()) {\n flash({ kind: 'error', text: '请填写主机地址' })\n return\n }\n setTesting(true)\n setTestResult(undefined)\n try {\n const payload = isRemote ? {\n ssh: {\n host: form.host.trim(),\n port: Number(form.port) || 22,\n username: form.username.trim(),\n auth: { kind: form.authKind, ...(form.keyPath.trim() ? { keyPath: form.keyPath.trim() } : {}) },\n },\n secrets: {\n ...(form.password ? { password: form.password } : {}),\n ...(form.privateKey ? { privateKey: form.privateKey } : {}),\n ...(form.passphrase ? { passphrase: form.passphrase } : {}),\n },\n } : {}\n const url = selectedId === 'new' ? '/api/dshb/nodes/test-unsaved' : `/api/dshb/nodes/${selectedId}/test`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n const data = (await res.json()) as { ok?: boolean; report?: { ok?: boolean; reachable?: boolean; error?: string; category?: string } }\n const r = data.report\n if (r?.ok && r.reachable) {\n setTestResult('连接成功')\n } else {\n const cat = r?.category ? `(${r.category})` : ''\n setTestResult(`${r?.error ?? '连接失败'}${cat}`)\n }\n reload()\n } catch {\n setTestResult('网络错误')\n } finally {\n setTesting(false)\n }\n }, [form, selectedId, reload])\n\n const dockerAction = useCallback(async (action: 'restart' | 'stop' | 'start' | 'provision') => {\n if (selectedId === 'new') return\n if (action === 'provision') {\n setDockerBusy(true)\n try {\n const res = await fetch(`/api/dshb/docker/${selectedId}/provision`, { method: 'POST' })\n const data = (await res.json()) as { ok?: boolean; error?: string; containerId?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: `容器已就绪:${data.containerId?.slice(0, 12) ?? ''}` })\n } else {\n flash({ kind: 'error', text: data.error ?? '拉起失败' })\n }\n reload()\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setDockerBusy(false)\n }\n return\n }\n setDockerBusy(true)\n try {\n const res = await fetch(`/api/dshb/docker/${selectedId}/${action}`, { method: 'POST' })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: action === 'restart' ? '容器已重启' : action === 'stop' ? '容器已停止' : '容器已启动' })\n } else {\n flash({ kind: 'error', text: data.error ?? '操作失败' })\n }\n reload()\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setDockerBusy(false)\n }\n }, [selectedId, flash, reload])\n\n const selectedNode = selectedId === 'new' ? undefined : nodes.find((n) => n.id === selectedId)\n\n return (\n <>\n <style>{`\n @media (max-width:767px){\n .dshb-node-section{flex-direction:column!important}\n .dshb-node-section>div:first-child{width:100%!important;border-right:none!important;border-bottom:1px solid var(--dsw-alias-border-l2);padding-right:0!important;padding-bottom:12px;margin-bottom:12px}\n .dshb-node-section>div:last-child{max-width:100%!important}\n .dshb-form-row{flex-direction:column!important;gap:8px!important}\n .dshb-form-row>label{width:100%!important;flex:none!important}\n }\n `}</style>\n <div className=\"dshb-node-section\" style={{ display: 'flex', gap: 20, minHeight: 320, overflow: 'hidden', maxWidth: '100%', width: '100%', boxSizing: 'border-box' }}>\n <div style={{ width: 200, flexShrink: 0, borderRight: '1px solid var(--dsw-alias-border-l2)', paddingRight: 16 }}>\n <button type=\"button\" onClick={() => selectNode('new')} style={{ ...primaryButtonStyle, width: '100%', marginBottom: 10 }}>\n 新建节点\n </button>\n {nodes.map((n) => (\n <div\n key={n.id}\n onClick={() => selectNode(n.id)}\n style={{\n padding: '8px 10px',\n borderRadius: 6,\n cursor: 'pointer',\n marginBottom: 4,\n background: selectedId === n.id ? 'var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))' : 'transparent',\n fontSize: 13,\n }}\n >\n <div style={{ fontWeight: 500 }}>{n.name}</div>\n <div style={{ fontSize: 11, opacity: 0.7, display: 'flex', alignItems: 'center', gap: 4 }}>\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: '50%',\n background: n.status?.reachable === true ? 'var(--dsw-alias-state-success-primary)' : n.status?.reachable === false ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-dimmed)',\n }}\n />\n {n.type === 'local-host' ? '默认环境(本地)' : n.type === 'remote-ssh' ? '远程 SSH' : n.type === 'local-docker' ? '本地 Docker' : n.type === 'remote-docker' ? '远程 Docker' : n.type}\n <span style={{ marginLeft: 4, color: n.status?.reachable === true ? 'var(--dsw-alias-state-success-primary)' : n.status?.reachable === false ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-dimmed)' }}>\n {n.status?.reachable === true ? '在线' : n.status?.reachable === false ? '离线' : '未知'}\n </span>\n </div>\n {n.provision && (\n <div style={{ fontSize: 11, marginTop: 2, color: n.provision.state === 'ready' ? 'var(--dsw-alias-state-success-primary)' : n.provision.state === 'failed' ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-state-warn-label)' }}>\n {n.provision.state === 'provisioning' ? '容器拉起中…' : n.provision.state === 'ready' ? '容器已就绪' : `容器拉起失败:${n.provision.error ?? '未知错误'}`}\n </div>\n )}\n </div>\n ))}\n {nodes.length === 0 && <div style={{ fontSize: 12, opacity: 0.6 }}>暂无节点</div>}\n </div>\n\n <div style={{ flex: 1, maxWidth: 480, minWidth: 0, overflow: 'hidden' }}>\n {sshConfigEntries.length > 0 && (\n <div style={{ marginBottom: 14 }}>\n <label style={{ fontSize: 12, opacity: 0.75, display: 'block', marginBottom: 4 }}>从 ~/.ssh/config 导入</label>\n <select\n style={inputStyle}\n value=\"\"\n onChange={(e) => {\n const entry = sshConfigEntries[Number(e.target.value)]\n if (entry) importSshConfig(entry)\n e.target.value = ''\n }}\n >\n <option value=\"\">选择主机…</option>\n {sshConfigEntries.map((entry, i) => (\n <option key={entry.host} value={i}>\n {entry.host}:{entry.port}{entry.username ? ` (${entry.username})` : ''}{entry.hasProxyJump ? ' 跳板' : ''}\n </option>\n ))}\n </select>\n </div>\n )}\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 节点名称\n <input style={inputStyle} value={form.name} onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))} placeholder=\"例如:构建机\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 节点类型\n <select style={inputStyle} value={form.type} onChange={(e) => setForm((f) => ({ ...f, type: e.target.value as FormState['type'] }))}>\n <option value=\"remote-ssh\">远程 SSH 宿主机</option>\n <option value=\"remote-docker\">远程 Docker(SSH 通道)</option>\n <option value=\"local-host\">默认环境(本地)</option>\n <option value=\"local-docker\">本地 Docker 容器</option>\n </select>\n </label>\n\n {(form.type === 'remote-ssh' || form.type === 'remote-docker') && (\n <>\n <div className=\"dshb-form-row\" style={{ display: 'flex', gap: 10 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n 主机地址\n <input style={inputStyle} value={form.host} onChange={(e) => setForm((f) => ({ ...f, host: e.target.value }))} placeholder=\"192.168.1.10\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, width: 90 }}>\n 端口\n <input style={inputStyle} value={form.port} onChange={(e) => setForm((f) => ({ ...f, port: e.target.value }))} />\n </label>\n </div>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 用户名\n <input style={inputStyle} value={form.username} onChange={(e) => setForm((f) => ({ ...f, username: e.target.value }))} placeholder=\"root\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 认证方式\n <select style={inputStyle} value={form.authKind} onChange={(e) => setForm((f) => ({ ...f, authKind: e.target.value as FormState['authKind'] }))}>\n <option value=\"password\">密码</option>\n <option value=\"key\">私钥</option>\n <option value=\"agent\">ssh-agent</option>\n </select>\n </label>\n {form.authKind === 'password' && (\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 密码{selectedNode?.hasSecret.hasPassword ? '(已保存,留空保持不变)' : ''}\n <input style={inputStyle} type=\"password\" value={form.password} onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))} autoComplete=\"new-password\" />\n </label>\n )}\n {form.authKind === 'key' && (\n <>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 私钥内容{selectedNode?.hasSecret.hasKey ? '(已保存,留空保持不变)' : ''}\n <textarea style={{ ...inputStyle, minHeight: 90, resize: 'vertical' }} value={form.privateKey} onChange={(e) => setForm((f) => ({ ...f, privateKey: e.target.value }))} placeholder=\"-----BEGIN OPENSSH PRIVATE KEY-----\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 私钥 passphrase(可选)\n <input style={inputStyle} type=\"password\" value={form.passphrase} onChange={(e) => setForm((f) => ({ ...f, passphrase: e.target.value }))} autoComplete=\"new-password\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 或私钥文件路径(可选,优先使用内容)\n <input style={inputStyle} value={form.keyPath} onChange={(e) => setForm((f) => ({ ...f, keyPath: e.target.value }))} placeholder=\"~/.ssh/id_ed25519\" />\n </label>\n </>\n )}\n </>\n )}\n\n {(form.type === 'local-docker' || form.type === 'remote-docker') && (\n <>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 镜像地址\n <input style={inputStyle} value={form.dockerImage} onChange={(e) => setForm((f) => ({ ...f, dockerImage: e.target.value }))} placeholder=\"alpine:latest\" />\n </label>\n <div className=\"dshb-form-row\" style={{ display: 'flex', gap: 10 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n CPU 核数(可选)\n <input style={inputStyle} value={form.dockerCpus} onChange={(e) => setForm((f) => ({ ...f, dockerCpus: e.target.value }))} placeholder=\"2\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n 内存 MB(可选)\n <input style={inputStyle} value={form.dockerMemory} onChange={(e) => setForm((f) => ({ ...f, dockerMemory: e.target.value }))} placeholder=\"512\" />\n </label>\n </div>\n </>\n )}\n\n {testResult !== undefined && (\n <div style={{ fontSize: 13, color: testResult === '连接成功' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{testResult}</div>\n )}\n\n <div style={{ display: 'flex', gap: 10, marginTop: 6, flexWrap: 'wrap' }}>\n <button type=\"button\" onClick={() => void save()} disabled={busy} style={primaryButtonStyle}>\n {selectedId === 'new' ? '创建节点' : '保存'}\n </button>\n {(form.type === 'remote-ssh' || form.type === 'remote-docker' || (selectedId !== 'new' && form.type === 'local-docker')) && (\n <button type=\"button\" onClick={() => void test()} disabled={busy || testing} style={secondaryButtonStyle}>\n {testing ? '测试中…' : '测试连接'}\n </button>\n )}\n {selectedId !== 'new' && (form.type === 'local-docker' || form.type === 'remote-docker') && (\n <>\n <button type=\"button\" onClick={() => void dockerAction('provision')} disabled={busy || dockerBusy} style={primaryButtonStyle}>\n {dockerBusy ? '操作中…' : '拉起容器'}\n </button>\n <button type=\"button\" onClick={() => void dockerAction('restart')} disabled={busy || dockerBusy} style={secondaryButtonStyle}>\n {dockerBusy ? '操作中…' : '重启容器'}\n </button>\n <button type=\"button\" onClick={() => void dockerAction('stop')} disabled={busy || dockerBusy} style={secondaryButtonStyle}>\n {dockerBusy ? '操作中…' : '停止容器'}\n </button>\n </>\n )}\n {selectedId !== 'new' && (\n <button type=\"button\" onClick={() => void remove()} disabled={busy} style={dangerOutlineButtonStyle}>\n 删除\n </button>\n )}\n {notice && <span style={{ fontSize: 13, alignSelf: 'center', color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </div>\n </div>\n </div>\n </>\n )\n}\n\nexport function apply(ctx: ClientContext): void {\n const globalStyle = document.createElement('style')\n globalStyle.textContent = `\n /* 仅在页面根阻止整页横向滚动。绝对定位浮层(模型菜单、上下文统计面板等)\n 依赖祖先 overflow:visible 才能展开到输入框之外,禁止给任何中间祖先加裁剪。 */\n html, body { overflow-x: hidden !important; max-width: 100vw !important }\n * { min-width: 0 !important; }\n table { display: block !important; overflow-x: auto !important; }\n img, video, canvas, svg { max-width: 100% !important; height: auto !important }\n pre, code { white-space: pre-wrap !important; word-break: break-all !important }\n input, select, textarea { max-width: 100% !important; }\n /* 上下文用量弹窗 .JObwrW_panel(ContextMeter):解除宽度塌缩并允许溢出显示。\n JObwrW_ 为上游 CSS 模块 hash,上游升级需同步。 */\n .JObwrW_panel { max-width: none !important; overflow: visible !important; }\n /* 子代理切换弹窗(dsh-client-ui-subagent):menu 是 flex column + max-height + overflow:auto,\n position:fixed 经 portal 渲染。子代理很多时 flex 压缩 node(flex-shrink:1 默认),\n 文字挤压且不触发滚动。给 node flex-shrink:0 让 menu 整体 overflow:auto 滚动。 */\n [class*=\"_menu\"] [class*=\"_node\"] { flex-shrink: 0 !important; }\n /* 模型选择弹窗(dsh-client-ui-model-selection):Ra_menu 上游 max-width 420px,\n 长模型名单行放不下被 ellipsis 截断。放宽到 720px 让模型名单行完整显示。\n [class*=\"Ra_menu\"] 精确匹配模型弹窗,避免误伤其他菜单。Ra_ 为 hash,上游升级需同步。 */\n [class*=\"Ra_menu\"] { max-width: 720px !important; width: auto !important; }\n /* 终端组件(dsh-web-frontend,CSS 模块前缀 1gdtu_)桌面端修复:上游 _command_ 默认\n overflow:hidden+text-overflow:ellipsis,LLM 调 bash 的长命令在桌面端被省略号\n 截断、看不到完整内容(输出区 _output_ 本就可横向滚动,唯命令区不行)。宽屏与\n mobile.tsx 的窄屏规则等效:行链 _prompt_/_promptLine_/_command_ 撑到 max-content、\n overflow 可见,长行溢出传入 _header_(本就 overflow-y:auto)的 scrollWidth,整个\n 命令区随 _header_ 横向滚动;copyButton 贴右缘保持可见。与窄屏规则共用 1gdtu_\n hash,上游升级需同步。桌面保留可见滚动条(不隐藏、不加 touch-action)。 */\n @media (min-width: 1024px) {\n [data-phase] [class*=\"_header_1gdtu_\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n }\n [data-phase] [class*=\"_prompt_1gdtu_\"],\n [data-phase] [class*=\"_promptLine_1gdtu_\"],\n [data-phase] [class*=\"_command_1gdtu_\"] {\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n }\n [data-phase] [class*=\"_command_1gdtu_\"] {\n display: inline-block;\n text-overflow: clip !important;\n white-space: pre !important;\n }\n [data-phase] [class*=\"_copyButton_1gdtu_\"] { position: sticky !important; right: 0; top: 0; }\n }\n `\n document.head.appendChild(globalStyle)\n\n installMobile(ctx)\n\n registerWorkspaceInstructionMenu(ctx)\n\n ctx.plugin({\n inject: ['slots'],\n apply: (sub: ClientContext): void => {\n sub.slots.inject('settings.section', () =>\n sub.slots.register({ name: 'settings.section', id: SECTION_ID, order: 110, label: () => '工作节点' }, NodeSection),\n )\n /* 上游 dsh-client-ui-directory-picker-browse 以默认 priority 0 注册同一 slot;\n priority 升序遮蔽(lowest renders),用 -10 抢占渲染,避免同优先级抛错。 */\n sub.slots.inject('conversation.hero.workspace.directoryFlow', () =>\n sub.slots.register({ name: 'conversation.hero.workspace.directoryFlow', priority: -10 }, DirectoryFlowOccupant),\n )\n sub.slots.inject('sidebar.workspaces.directoryFlow', () =>\n sub.slots.register({ name: 'sidebar.workspaces.directoryFlow', priority: -10 }, DirectoryFlowOccupant),\n )\n },\n })\n\n const workspaces = (ctx as unknown as { workspaces?: { openPath(p: string): Promise<void> } }).workspaces\n if (workspaces && typeof workspaces.openPath === 'function') {\n const originalOpenPath = workspaces.openPath.bind(workspaces)\n workspaces.openPath = async (path: string): Promise<void> => {\n try {\n const res = await fetch(`/api/dshb/remote/bound?path=${encodeURIComponent(path)}`)\n if (res.ok) {\n const data = (await res.json()) as { bound?: boolean; kind?: 'file' | 'dir'; error?: string }\n if (data.bound) {\n if (data.kind !== 'file') return originalOpenPath(path)\n const a = document.createElement('a')\n a.href = `/api/dshb/remote/file?path=${encodeURIComponent(path)}`\n a.download = ''\n document.body.appendChild(a)\n a.click()\n a.remove()\n return\n }\n }\n } catch {\n // 探测失败则回退宿主原生打开\n }\n return originalOpenPath(path)\n }\n }\n\n const ICON_SVG: Record<string, string> = {\n auth: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 7C9.3807 7 10.5 5.8807 10.5 4.5C10.5 3.1193 9.3807 2 8 2C6.6193 2 5.5 3.1193 5.5 4.5C5.5 5.8807 6.6193 7 8 7Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3 14C3 11.2386 5.2386 9 8 9C10.7614 9 13 11.2386 13 14\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n 'dshb-nodes': `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"3.5\" cy=\"4\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"12.5\" cy=\"4\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"8\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M3.5 6V8C3.5 9.1 4.4 10 5.5 10H8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/><path d=\"M12.5 6V8C12.5 9.1 11.6 10 10.5 10H8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>`,\n }\n const ICON_LABELS: Record<string, string> = { '认证': 'auth', '工作节点': 'dshb-nodes' }\n\n const observer = new MutationObserver(() => {\n const cells = document.querySelectorAll('button[class*=\"navCell\"]')\n for (const cell of Array.from(cells)) {\n const label = cell.querySelector('span[class*=\"navLabel\"]')\n if (!label) continue\n const text = label.textContent ?? ''\n const iconKey = ICON_LABELS[text]\n if (!iconKey) continue\n const iconSlot = cell.querySelector('[class*=\"navIcon\"]')\n if (!iconSlot) continue\n if (iconSlot.getAttribute('data-dshb-icon') === iconKey) continue\n iconSlot.innerHTML = ICON_SVG[iconKey] ?? ''\n iconSlot.setAttribute('data-dshb-icon', iconKey)\n }\n })\n observer.observe(document.body, { childList: true, subtree: true })\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport { apply as applyAuth } from './auth.js'\nimport { apply as applyUi } from './ui.js'\n\nexport const inject = ['connection', 'workspaces', 'slots', 'layout', 'conversation']\n\nexport function apply(ctx: ClientContext): void {\n applyAuth(ctx)\n applyUi(ctx)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["SECTION_ID","useState","useCallback","apply","inputStyle","buttonStyle","primaryButtonStyle","secondaryButtonStyle","useState","useCallback","useState","useCallback","apply"],"sources":["../src/client/auth.tsx","../src/client/directory-flow.tsx","../src/client/mobile.tsx","../src/client/workspace-instruction-menu.tsx","../src/client/ui.tsx","../src/client/index.tsx"],"sourcesContent":["import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\n\nexport const inject = ['connection']\n\nconst SECTION_ID = 'auth'\nconst MESSAGE_MS = 5000\n\nfunction useUsername(): [string | undefined, (username: string) => void] {\n const [username, setUsername] = useState<string | undefined>(undefined)\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const res = await fetch('/api/auth/status')\n if (!res.ok) return\n const data = (await res.json()) as { username?: string }\n if (!cancelled && typeof data.username === 'string') setUsername(data.username)\n } catch {\n // best-effort\n }\n })()\n return () => {\n cancelled = true\n }\n }, [])\n return [username, setUsername]\n}\n\ntype Notice = { kind: 'ok' | 'error'; text: string; owner: 'username' | 'password' | 'account' }\n\nexport function AuthSection(_props: PropsRuntime<'settings.section'>): ReactElement {\n const [username, setUsername] = useUsername()\n const [newUsername, setNewUsername] = useState('')\n const [usernamePassword, setUsernamePassword] = useState('')\n const [oldPassword, setOldPassword] = useState('')\n const [newPassword, setNewPassword] = useState('')\n const [confirm, setConfirm] = useState('')\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<Notice | undefined>(undefined)\n const [confirmingSignOut, setConfirmingSignOut] = useState(false)\n\n const flash = useCallback((n: Notice | undefined) => {\n setNotice(n)\n if (n !== undefined) setTimeout(() => setNotice(undefined), MESSAGE_MS)\n }, [])\n\n const signOut = useCallback(async () => {\n setBusy(true)\n try {\n await fetch('/api/auth/logout', { method: 'POST' })\n window.location.href = '/login'\n } catch {\n setBusy(false)\n setConfirmingSignOut(false)\n flash({ kind: 'error', text: '退出失败,请重试', owner: 'account' })\n }\n }, [flash])\n\n const changePassword = useCallback(async () => {\n if (newPassword !== confirm) {\n flash({ kind: 'error', text: '两次输入的新密码不一致', owner: 'password' })\n return\n }\n setBusy(true)\n try {\n const res = await fetch('/api/auth/change-password', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ currentPassword: oldPassword, password: newPassword }),\n })\n const data = (await res.json()) as { error?: string }\n if (res.ok) {\n setOldPassword('')\n setNewPassword('')\n setConfirm('')\n flash({ kind: 'ok', text: '密码已修改', owner: 'password' })\n } else {\n flash({ kind: 'error', text: data.error ?? '修改失败,请重试', owner: 'password' })\n }\n } catch {\n flash({ kind: 'error', text: '修改失败,请重试', owner: 'password' })\n } finally {\n setBusy(false)\n }\n }, [oldPassword, newPassword, confirm, flash])\n\n const changeUsername = useCallback(async () => {\n setBusy(true)\n try {\n const res = await fetch('/api/auth/change-username', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ username: newUsername, currentPassword: usernamePassword }),\n })\n const data = (await res.json()) as { error?: string }\n if (res.ok) {\n setNewUsername('')\n setUsernamePassword('')\n if (newUsername) setUsername(newUsername)\n flash({ kind: 'ok', text: '用户名已更新', owner: 'username' })\n } else {\n flash({ kind: 'error', text: data.error ?? '修改失败,请重试', owner: 'username' })\n }\n } catch {\n flash({ kind: 'error', text: '修改失败,请重试', owner: 'username' })\n } finally {\n setBusy(false)\n }\n }, [newUsername, usernamePassword, flash, setUsername])\n\n const inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n }\n const buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n }\n const primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n }\n const secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n }\n const dangerButtonStyle: CSSProperties = {\n ...buttonStyle,\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n }\n const dangerOutlineButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n }\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 24, maxWidth: 420 }}>\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 4px' }}>账号</h2>\n <p style={{ fontSize: 13, opacity: 0.7, margin: '0 0 12px' }}>\n {username !== undefined ? `当前登录:${username}` : '当前登录:管理员'}\n </p>\n <button\n type=\"button\"\n onClick={() => setConfirmingSignOut(true)}\n disabled={busy}\n style={dangerOutlineButtonStyle}\n >\n 退出登录\n </button>\n {confirmingSignOut && (\n <div role=\"alertdialog\" aria-label=\"确认退出登录\" style={{ marginTop: 10, padding: '12px 14px', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8, maxWidth: 320 }}>\n <div style={{ fontSize: 13, marginBottom: 10, color: 'var(--dsw-alias-label-primary)' }}>退出登录将回到登录页</div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8 }}>\n <button type=\"button\" onClick={() => setConfirmingSignOut(false)} disabled={busy} style={{ ...secondaryButtonStyle, height: 32, padding: '0 12px', borderRadius: 16 }}>\n 取消\n </button>\n <button type=\"button\" onClick={() => void signOut()} disabled={busy} style={{ ...dangerOutlineButtonStyle, height: 32, padding: '0 12px', borderRadius: 16, background: 'var(--dsw-alias-interactive-bg-hover-danger)' }}>\n 确认退出\n </button>\n </div>\n </div>\n )}\n {notice?.owner === 'account' && (\n <p style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)', margin: '8px 0 0' }}>{notice.text}</p>\n )}\n </section>\n\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 12px' }}>修改用户名</h2>\n <form onSubmit={(e) => { e.preventDefault(); void changeUsername() }} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 新用户名\n <input type=\"text\" value={newUsername} onChange={(e) => setNewUsername(e.target.value)} autoComplete=\"username\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 当前密码\n <input type=\"password\" value={usernamePassword} onChange={(e) => setUsernamePassword(e.target.value)} autoComplete=\"current-password\" style={inputStyle} />\n </label>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <button type=\"submit\" disabled={busy} style={primaryButtonStyle}>修改用户名</button>\n {notice?.owner === 'username' && <span style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </form>\n </section>\n\n <section>\n <h2 style={{ fontSize: 16, fontWeight: 600, margin: '0 0 12px' }}>修改密码</h2>\n <form onSubmit={(e) => { e.preventDefault(); void changePassword() }} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 当前密码\n <input type=\"password\" value={oldPassword} onChange={(e) => setOldPassword(e.target.value)} autoComplete=\"current-password\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 新密码\n <input type=\"password\" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} autoComplete=\"new-password\" style={inputStyle} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 确认新密码\n <input type=\"password\" value={confirm} onChange={(e) => setConfirm(e.target.value)} autoComplete=\"new-password\" style={inputStyle} />\n </label>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <button type=\"submit\" disabled={busy} style={primaryButtonStyle}>修改密码</button>\n {notice?.owner === 'password' && <span style={{ fontSize: 13, color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </form>\n </section>\n </div>\n )\n}\n\nexport function apply(ctx: ClientContext): void {\n const connection = ctx.get('connection') as { isLoopback?: boolean } | undefined\n if (connection !== undefined) {\n Object.defineProperty(connection, 'isLoopback', { configurable: true, get: () => true })\n }\n ctx.plugin({\n inject: ['slots'],\n apply: (sub: ClientContext): void => {\n sub.slots.inject('settings.section', () =>\n sub.slots.register({ name: 'settings.section', id: SECTION_ID, order: 100, label: () => '认证' }, AuthSection),\n )\n },\n })\n}\n","import type { DirectoryFlowOwnerProps } from '@deepseek-ai/dsh-client-ui-workspace/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\n\ninterface NodeProfileView {\n id: string\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n status?: { reachable?: boolean }\n}\n\ninterface DirEntry {\n name: string\n path: string\n isDirectory: boolean\n}\n\nconst inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n}\nconst buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n}\nconst primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\nconst secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n}\nconst overlayStyle: CSSProperties = {\n position: 'fixed',\n inset: 0,\n background: 'var(--dsw-alias-overlay-mask, rgba(0,0,0,0.45))',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n}\nconst dialogStyle: CSSProperties = {\n width: 'min(92vw, 560px)',\n maxWidth: '100%',\n maxHeight: '80vh',\n overflow: 'auto',\n overflowX: 'hidden',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: 20,\n boxSizing: 'border-box',\n color: 'var(--dsw-alias-label-primary)',\n}\n\nfunction joinPath(base: string, name: string): string {\n return `${base.replace(/\\/+$/, '')}/${name}`\n}\n\nexport function DirectoryFlowOccupant(props: DirectoryFlowOwnerProps): ReactElement | null {\n const [nodes, setNodes] = useState<NodeProfileView[]>([])\n const [nodeId, setNodeId] = useState<string>('')\n const [path, setPath] = useState('')\n const [entries, setEntries] = useState<DirEntry[]>([])\n const [error, setError] = useState<string | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [newDirName, setNewDirName] = useState('')\n const [pendingInstruction, setPendingInstruction] = useState<string | undefined>(undefined)\n const [instructionDialogOpen, setInstructionDialogOpen] = useState(false)\n\n useEffect(() => {\n if (!props.open) return\n void (async () => {\n try {\n const res = await fetch('/api/dshb/nodes')\n if (!res.ok) return\n const data = (await res.json()) as { nodes?: NodeProfileView[] }\n setNodes(data.nodes ?? [])\n } catch {}\n })()\n }, [props.open])\n\n const browse = useCallback(async (id: string, dir: string) => {\n setError(undefined)\n try {\n const res = await fetch(`/api/dshb/nodes/${id}/browse?path=${encodeURIComponent(dir)}`)\n const data = (await res.json()) as { ok?: boolean; path?: string; entries?: DirEntry[]; error?: string }\n if (!res.ok || !data.ok) {\n setError(data.error ?? '目录读取失败')\n return\n }\n setPath(data.path ?? dir)\n setEntries((data.entries ?? []).filter((e) => e.isDirectory))\n } catch {\n setError('网络错误')\n }\n }, [])\n\n const selectNode = useCallback(\n (id: string) => {\n setNodeId(id)\n setPath('')\n setEntries([])\n setError(undefined)\n void browse(id, '/')\n },\n [browse],\n )\n\n const mkdir = useCallback(async () => {\n if (!newDirName.trim()) return\n setBusy(true)\n setError(undefined)\n try {\n const target = joinPath(path, newDirName.trim())\n const res = await fetch(`/api/dshb/nodes/${nodeId}/mkdir`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ path: target }),\n })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (!res.ok || !data.ok) {\n setError(data.error ?? '创建目录失败')\n return\n }\n setNewDirName('')\n void browse(nodeId, target)\n } catch {\n setError('网络错误')\n } finally {\n setBusy(false)\n }\n }, [newDirName, nodeId, path, browse])\n\n const confirm = useCallback(async () => {\n if (!nodeId || !path) {\n setError('请选择节点与目录')\n return\n }\n setBusy(true)\n setError(undefined)\n try {\n const node = nodes.find((n) => n.id === nodeId)\n if (!node) return\n let pickedPath = path\n if (node.type !== 'local-host') {\n const res = await fetch('/api/dshb/workspaces/bind', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ nodeId, remotePath: path }),\n })\n const data = (await res.json()) as { ok?: boolean; mirrorPath?: string; error?: string }\n if (!res.ok || !data.ok || !data.mirrorPath) {\n setError(data.error ?? '工作区注册失败')\n return\n }\n pickedPath = data.mirrorPath\n }\n props.onPicked(pickedPath)\n if (pendingInstruction !== undefined && pendingInstruction.trim()) {\n savePendingInstruction(pickedPath, pendingInstruction)\n }\n } catch {\n setError('网络错误')\n } finally {\n setBusy(false)\n }\n }, [nodeId, path, nodes, props, pendingInstruction])\n\n if (!props.open) return null\n\n const node = nodes.find((n) => n.id === nodeId)\n\n return (\n <div style={overlayStyle} role=\"dialog\" aria-label=\"添加工作区\">\n <div style={dialogStyle}>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>\n <h2 style={{ margin: 0, fontSize: 16, color: 'var(--dsw-alias-label-primary)' }}>添加工作区</h2>\n <button type=\"button\" onClick={props.onCancel} style={secondaryButtonStyle}>\n 关闭\n </button>\n </div>\n\n <label style={{ display: 'block', fontSize: 12, color: 'var(--dsw-alias-label-secondary)', marginBottom: 4 }}>工作节点</label>\n <select style={{ ...inputStyle, marginBottom: 14 }} value={nodeId} onChange={(e) => selectNode(e.target.value)} disabled={props.busy || busy}>\n <option value=\"\">选择节点…</option>\n {nodes.map((n) => {\n const typeLabel =\n n.type === 'local-host' ? '本地' : n.type === 'remote-ssh' ? '远程 SSH' : n.type === 'local-docker' ? '本地 Docker' : n.type === 'remote-docker' ? '远程 Docker' : n.type\n return (\n <option key={n.id} value={n.id}>\n {n.name}({typeLabel})\n </option>\n )\n })}\n </select>\n\n {nodeId !== '' && (\n <>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>\n <label style={{ fontSize: 12, color: 'var(--dsw-alias-label-secondary)' }}>当前目录({node?.type === 'local-host' ? '本机' : '远端'})</label>\n <button type=\"button\" onClick={() => void browse(nodeId, dirnameOf(path))} disabled={busy} style={secondaryButtonStyle}>\n 上一级\n </button>\n </div>\n <div style={{ ...inputStyle, marginBottom: 8, height: 'auto', minHeight: 32, display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 2, cursor: 'pointer', lineHeight: '32px', overflow: 'hidden' }} onClick={() => void browse(nodeId, path)}>\n {path.split('/').filter(Boolean).length === 0 ? (\n <span style={{ opacity: 0.5 }}>根目录</span>\n ) : (\n <>\n <span onClick={(ev) => { ev.stopPropagation(); void browse(nodeId, '/') }} style={{ cursor: 'pointer', color: 'var(--dsw-alias-label-secondary)' }}>/</span>\n {path.split('/').filter(Boolean).map((seg, i, arr) => {\n const dir = '/' + arr.slice(0, i + 1).join('/')\n return (\n <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 2 }}>\n <span onClick={(ev) => { ev.stopPropagation(); void browse(nodeId, dir) }} style={{ cursor: 'pointer' }}>{seg}</span>\n {i < arr.length - 1 && <span style={{ opacity: 0.4 }}>/</span>}\n </span>\n )\n })}\n </>\n )}\n </div>\n <div style={{ maxHeight: 200, overflow: 'auto', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 6, marginBottom: 10 }}>\n {entries.map((e) => (\n <div key={e.path} onClick={() => void browse(nodeId, e.path)} style={{ padding: '7px 10px', cursor: 'pointer', fontSize: 13, borderRadius: 6, color: 'var(--dsw-alias-label-primary)', display: 'flex', alignItems: 'center', gap: 6, overflow: 'hidden' }} onMouseEnter={(ev) => (ev.currentTarget.style.background = 'var(--dsw-alias-interactive-bg-hover)')} onMouseLeave={(ev) => (ev.currentTarget.style.background = 'transparent')}>\n <span style={{ flexShrink: 0 }}>📁</span>\n <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.name}</span>\n </div>\n ))}\n {entries.length === 0 && <div style={{ padding: 12, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' }}>无子目录</div>}\n </div>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <input style={{ ...inputStyle, flex: 1, minWidth: 0 }} value={newDirName} onChange={(e) => setNewDirName(e.target.value)} placeholder=\"在当前目录下新建子目录…\" onKeyDown={(e) => { if (e.key === 'Enter') void mkdir() }} />\n <button type=\"button\" onClick={() => void mkdir()} disabled={busy || !newDirName.trim()} style={{ ...secondaryButtonStyle, flexShrink: 0, whiteSpace: 'nowrap' }}>\n 新建\n </button>\n </div>\n </>\n )}\n\n {error && <div style={{ fontSize: 13, color: 'var(--dsw-alias-state-error-primary)', marginBottom: 10 }}>{error}</div>}\n\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10 }}>\n <button type=\"button\" onClick={props.onCancel} style={secondaryButtonStyle}>\n 取消\n </button>\n <button\n type=\"button\"\n onClick={() => setInstructionDialogOpen(true)}\n disabled={busy || props.busy || !nodeId || !path}\n style={{\n ...secondaryButtonStyle,\n borderColor: pendingInstruction !== undefined && pendingInstruction.trim() ? 'var(--dsw-alias-state-business-primary)' : 'var(--dsw-alias-border-l2)',\n color: pendingInstruction !== undefined && pendingInstruction.trim() ? 'var(--dsw-alias-state-business-primary)' : 'var(--dsw-alias-label-primary)',\n }}\n >\n 指令{pendingInstruction !== undefined && pendingInstruction.trim() ? ' ●' : ''}\n </button>\n <button type=\"button\" onClick={() => void confirm()} disabled={busy || props.busy || !nodeId || !path} style={primaryButtonStyle}>\n 设为工作区\n </button>\n </div>\n </div>\n\n {instructionDialogOpen && (\n <InstructionPreviewDialog\n text={pendingInstruction ?? ''}\n onClose={() => setInstructionDialogOpen(false)}\n onSave={(t) => {\n setPendingInstruction(t)\n setInstructionDialogOpen(false)\n }}\n />\n )}\n </div>\n )\n}\n\nfunction dirnameOf(path: string): string {\n const parts = path.split('/').filter(Boolean)\n parts.pop()\n return parts.length === 0 ? '/' : `/${parts.join('/')}`\n}\n\nconst pendingInstructions = new Map<string, string>()\n\nfunction savePendingInstruction(path: string, text: string): void {\n pendingInstructions.set(path, text)\n void (async () => {\n try {\n let attempts = 0\n const tryResolve = async (): Promise<void> => {\n if (attempts++ > 10) return\n const wks = (window as unknown as { workspaces?: { list?: { getSnapshot?: () => { items?: { workspaceId: string; path: string }[] } } } }).workspaces\n const snap = wks?.list?.getSnapshot?.()\n const items = snap?.items ?? []\n const ws = items.find((w) => w.path === path)\n if (!ws) {\n await new Promise((r) => setTimeout(r, 300))\n return tryResolve()\n }\n await fetch(`/api/dshb/instructions/${ws.workspaceId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text, expectedRevision: 0 }),\n })\n pendingInstructions.delete(path)\n }\n void tryResolve()\n } catch {}\n })()\n}\n\nfunction InstructionPreviewDialog(props: {\n text: string\n onClose: () => void\n onSave: (text: string) => void\n}): ReactElement {\n const [text, setText] = useState(props.text)\n const overlayStyle: CSSProperties = {\n position: 'fixed',\n inset: 0,\n background: 'var(--dsw-alias-overlay-mask, rgba(0,0,0,0.45))',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1100,\n }\n const dialogStyle: CSSProperties = {\n width: 'min(92vw, 600px)',\n maxWidth: '100%',\n maxHeight: '85vh',\n overflow: 'auto',\n overflowX: 'hidden',\n background: 'var(--dsw-alias-bg-layer-1)',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 12,\n padding: 20,\n boxSizing: 'border-box',\n color: 'var(--dsw-alias-label-primary)',\n }\n return (\n <div style={overlayStyle} onClick={props.onClose}>\n <div style={dialogStyle} onClick={(e) => e.stopPropagation()}>\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>\n <h2 style={{ margin: 0, fontSize: 16, color: 'var(--dsw-alias-label-primary)' }}>项目指令</h2>\n <button type=\"button\" onClick={props.onClose} style={secondaryButtonStyle}>关闭</button>\n </div>\n <div style={{ fontSize: 12, color: 'var(--dsw-alias-label-secondary)', marginBottom: 10 }}>\n 工作区创建后,此指令将自动保存为新工作区的项目指令。新对话首次交互时注入。\n </div>\n <textarea\n style={{\n width: '100%',\n minHeight: '280px',\n fontFamily: 'monospace',\n fontSize: 13,\n padding: '12px',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n background: 'var(--dsw-alias-bg-layer-2)',\n color: 'var(--dsw-alias-label-primary)',\n resize: 'vertical',\n boxSizing: 'border-box',\n outline: 'none',\n }}\n value={text}\n onChange={(e) => setText(e.target.value)}\n placeholder=\"留空则不注入指令...\"\n spellCheck={false}\n />\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, marginTop: 14 }}>\n <button type=\"button\" onClick={props.onClose} style={secondaryButtonStyle}>取消</button>\n <button type=\"button\" onClick={() => props.onSave(text)} style={primaryButtonStyle}>确定</button>\n </div>\n </div>\n </div>\n )\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n\n/**\n * dshb 移动端屏幕适配(参考 dsh-web-mobile 实现,仅保留页面适配与目录抽屉\n * 切换,不含文件浏览 / 导出会话日志等功能按钮)。\n *\n * 机制与上游一致:dsh 客户端在窄屏会自动给 AppFrame 加 data-sidebar-collapsed\n * 折叠侧边栏;这里把侧边栏列(frame 的第一个 grid 子元素)用 CSS 抽屉化\n * (绝对定位 + transform 移出/滑入),并在会话头部注入一个切换按钮调用\n * ctx.layout.toggleSidebar()。窄屏判定与上游一致(<1024 且粗指针,避免桌面\n * 小窗误触发)。\n */\nexport const MOBILE_QUERY = '(max-width: 1023px) and (pointer: coarse)'\n\n/** 纯视口宽度判定:与放宽后的 MOBILE_CSS 媒体查询一致(不依赖 pointer 类型)。 */\nconst NARROW_QUERY = '(max-width: 1023px)'\n\nconst FRAME_ATTR = 'data-dshb-mobile'\nconst COLLAPSED_ATTR = 'data-sidebar-collapsed'\n\nconst MOBILE_CSS = `\n/* 仅按视口宽度判定,不绑定 pointer:coarse —— 触屏笔记本 / DevTools 响应式模式\n 常报 pointer:fine,绑定 coarse 会让全部窄屏修复失效。抽屉相关选择器都挂在\n [data-dshb-mobile] 标记上,标记由 JS 的 coarse 判定添加,故放宽 CSS 不会误开抽屉。 */\n@media (max-width: 1023px) {\n html, body { touch-action: pan-y pinch-zoom !important; overscroll-behavior-x: none !important; -webkit-text-size-adjust: 100% !important; text-size-adjust: 100% !important; }\n\n [${FRAME_ATTR}=\"frame\"] {\n box-sizing: border-box !important;\n position: relative !important;\n grid-template-columns: minmax(0, 1fr) 0 0 !important;\n padding-top: env(safe-area-inset-top, 0px) !important;\n }\n\n /* 侧边栏列 -> 抽屉:默认移出屏幕,展开(无 collapsed)时滑入 */\n [${FRAME_ATTR}=\"frame\"] > :first-child {\n position: absolute !important;\n inset: 0 auto 0 0 !important;\n width: max-content;\n max-width: 92vw;\n z-index: 40 !important;\n transform: translateX(-110%);\n transition: transform .28s ease-in-out;\n background: var(--dsw-alias-bg-base, #ffffff);\n padding-top: env(safe-area-inset-top, 0px) !important;\n border-right: none !important;\n touch-action: pan-y pinch-zoom !important;\n }\n [${FRAME_ATTR}=\"frame\"]:not([${COLLAPSED_ATTR}]) > :first-child { transform: none !important; }\n @media (prefers-reduced-motion: reduce) {\n [${FRAME_ATTR}=\"frame\"] > :first-child { transition: none !important; }\n }\n\n /* 拖拽手柄在触屏上无用 */\n [data-side=\"sidebar\"], [data-side=\"details\"] { display: none !important; }\n\n /* 对话区:去桌面滚动条占位,收窄 gutter,字号降一档 */\n [data-phase] [class*=\"_scrollBody\"] { scrollbar-gutter: auto !important; scrollbar-width: none; }\n [data-phase] [class*=\"_scrollBody\"]::-webkit-scrollbar { display: none !important; width: 0; height: 0; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) { padding-left: 20px; padding-right: 20px; font-size: 15px !important; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) p,\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) li,\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):has(p) [class*=\"_text_\"] { font-size: 15px !important; }\n [data-phase] table { width: 100%; max-width: 100%; }\n [data-phase] th, [data-phase] td { max-width: none; min-width: 0; }\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]) img { width: auto !important; max-width: 100% !important; height: auto !important; max-height: 220px !important; }\n [data-phase] [class*=\"_userStack\"], [data-phase] [class*=\"_userStack\"] [class*=\"_bubble\"] { box-sizing: border-box; width: fit-content; max-width: 100%; }\n [data-phase] [class*=\"_actions\"] { overflow: hidden; }\n\n /* 统计行(turns/steps/LLM/TPS):窄屏横向滚动,指标可滑动看全 */\n [${FRAME_ATTR}=\"stats\"] {\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center;\n gap: 6px;\n overflow-x: auto !important;\n max-width: 100% !important;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n [${FRAME_ATTR}=\"stats\"]::-webkit-scrollbar { display: none; }\n [${FRAME_ATTR}=\"stats\"] > * { flex-shrink: 0 !important; white-space: nowrap !important; }\n [${FRAME_ATTR}=\"stats\"] { gap: 6px !important; }\n [class*=\"composerStack\"] { gap: 4px !important; }\n /* stats line 竖线分隔符(|)两边 margin 10px 太松,适度收紧 */\n [data-phase] [class*=\"_sep\"] { margin: 0 3px !important; }\n\n /* 每轮回复下方的统计文字(footer):收紧 actions 内部 gap 与气泡到 footer 间距,减少松散感 */\n [data-phase] [class*=\"_actions\"] { gap: 4px !important; }\n [data-phase] [class*=\"_actions\"] [class*=\"_timeEnd\"] { gap: 4px !important; padding-left: 6px !important; }\n [data-phase] [class*=\"userRow\"], [data-phase] [class*=\"assistantRow\"] { gap: 4px !important; }\n /* 点号(·)左右 margin 10px 太松,收紧并抵消前后空格 */\n [data-phase] [class*=\"_runTimeDot\"] { margin: 0 -2px !important; }\n /* footer 容器各项间距 16px 偏松 */\n [data-phase] [class*=\"_root\"][class*=\"osXY9a\"] { gap: 8px !important; }\n /* footer 统计行窄屏可横向滑动看全,不溢出页面 */\n [data-phase] [class*=\"_actions\"] { max-width: 100% !important; overflow-x: auto !important; scrollbar-width: none; touch-action: pan-x pan-y !important; }\n [data-phase] [class*=\"_actions\"]::-webkit-scrollbar { display: none; }\n\n /* 模型切换菜单:名称完整展示,长名称在菜单项内换行。 */\n [class*=\"_submenu_\"] [class*=\"_itemLabel_\"] {\n overflow: visible !important;\n text-overflow: clip !important;\n white-space: normal !important;\n overflow-wrap: anywhere;\n }\n\n /* 模型选择器(dsh-client-ui-model-selection,CSS 模块前缀 7KE1Ra_):\n 列表内模型名/描述默认 ellipsis 截断,改换行完整显示。除当前 hash 外,\n 再加 modelName 语义匹配,防止上游升级换 hash 后规则失效。\n 注意:必须用 break-word 而非 anywhere —— anywhere 让文字 min-content\n 宽度≈1 字符,配合全局 * {min-width:0} 会把 flex 行内名字列压到 1 字符宽,\n 出现\"一字符就换行\"。break-word 的 min-content 取最长词宽,只在真正\n 放不下时才断词。 */\n [class*=\"7KE1Ra_modelName\"],\n [class*=\"7KE1Ra_description\"],\n [class*=\"modelName\"] {\n white-space: normal !important;\n overflow-wrap: break-word;\n text-overflow: clip !important;\n overflow: visible !important;\n }\n\n /* 模型选择器弹窗:JS(installModelMenuPosition)在窄屏下改为 position:fixed\n 视口级浮层(fixed 不受祖先 overflow 裁剪),这里仅做静态兜底(JS 未生效时\n 仍从触发按钮左缘向右展开、宽度收进视口)。 */\n [class*=\"7KE1Ra_menu\"],\n [class*=\"_menu\"]:has([class*=\"modelName\"]) {\n left: 0 !important;\n right: auto !important;\n width: calc(100vw - 32px) !important;\n min-width: 0 !important;\n max-width: calc(100vw - 32px) !important;\n overflow-y: auto !important;\n max-height: calc(100vh - 120px) !important;\n }\n\n /* 工具调用执行结果/代码/JSON:窄屏可横向滑动。details 抽屉宽 min(92%,420px)\n 较窄,命令行输出/JSON 长行溢出被外层 overflow:hidden 裁剪看不到。命令行输出\n 改 white-space:pre(保持原格式不折行,像终端)+ overflow-x:auto 横向滑动;\n min-width:0+max-width:100% 约束宽度触发滚动。 */\n [data-phase] [class*=\"resultBlockText\"],\n [data-phase] [class*=\"payload\"]:not([class*=\"errorPayload\"]),\n [data-phase] [class*=\"sourceBlockContent\"] {\n white-space: pre !important;\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"resultBlockText\"]::-webkit-scrollbar,\n [data-phase] [class*=\"payload\"]::-webkit-scrollbar,\n [data-phase] [class*=\"sourceBlockContent\"]::-webkit-scrollbar { display: none !important; }\n\n /* JSON 预览/代码块/promptDiff:横向滑动(不折行,保持格式) */\n [data-phase] [class*=\"jsonPayload\"],\n [data-phase] [class*=\"jsonPreview\"],\n [data-phase] [class*=\"promptDiff\"],\n [data-phase] [class*=\"overviewPreview\"],\n [data-phase] [class*=\"resultBlocks\"],\n [data-phase] pre {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"jsonPayload\"]::-webkit-scrollbar,\n [data-phase] [class*=\"jsonPreview\"]::-webkit-scrollbar,\n [data-phase] [class*=\"promptDiff\"]::-webkit-scrollbar,\n [data-phase] [class*=\"overviewPreview\"]::-webkit-scrollbar,\n [data-phase] [class*=\"resultBlocks\"]::-webkit-scrollbar,\n [data-phase] pre::-webkit-scrollbar { display: none !important; }\n\n /* dsh-client-ui-tool 工具卡片(Bash 等命令输出,class 前缀 o3BgMG_):\n bodyScroll/ioSection 只有 overflow-y:auto,横向溢出传到 row{overflow:hidden}\n 被裁剪且无法滑动。给输出容器链设 overflow-x:auto(不覆盖上游 overflow-y),\n 让终端格式长行在卡片内横向滑动。 */\n [data-phase] [class*=\"bodyScroll\"],\n [data-phase] [class*=\"ioCard\"],\n [data-phase] [class*=\"ioSection\"],\n [data-phase] [class*=\"terminalBody\"],\n [data-phase] [class*=\"codeBody\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n /* xterm uses a transparent helper textarea for all terminal input. Keep it\n focusable and non-zero-sized so mobile browsers can present their keyboard. */\n [data-phase] .xterm .xterm-helper-textarea {\n width: 1px !important;\n height: 1px !important;\n opacity: .01 !important;\n z-index: 1 !important;\n }\n [data-phase] [class*=\"bodyScroll\"]::-webkit-scrollbar,\n [data-phase] [class*=\"ioCard\"]::-webkit-scrollbar,\n [data-phase] [class*=\"ioSection\"]::-webkit-scrollbar,\n [data-phase] [class*=\"terminalBody\"]::-webkit-scrollbar,\n [data-phase] [class*=\"codeBody\"]::-webkit-scrollbar { display: none !important; }\n\n /* 终端组件(dsh-web-frontend,CSS 模块前缀 1gdtu_):多行命令上游按行渲染成\n 多个 _promptLine_>_command_ 元素,行级不能各自设 overflow(会变成每行独立\n 滚动)。唯一横向滚动容器是公共祖先 _header_1gdtu_32(本就 overflow-y:auto):\n 行链 _prompt_/_promptLine_/_command_ 全部撑到 max-content 且 overflow 可见,\n 长行内容溢出传入 _header_ 的 scrollWidth,所有行随 _header_ 同步滚动。\n _output_1gdtu_156(输出区)同理以其为唯一容器,_line_ 撑宽不裁剪。 */\n [data-phase] [class*=\"_header_1gdtu_\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n overscroll-behavior-x: contain;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"_prompt_1gdtu_\"],\n [data-phase] [class*=\"_promptLine_1gdtu_\"],\n [data-phase] [class*=\"_command_1gdtu_\"] {\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n /* Android Chrome TextAutosizer 按块宽计算 font boosting,max-content 行宽不一\n 导致各行字号参差;max-height 是其豁免条件,禁用放大并锁定继承字号。 */\n max-height: 999999px !important;\n }\n [data-phase] [class*=\"_command_1gdtu_\"] {\n display: inline-block;\n text-overflow: clip !important;\n white-space: pre !important;\n }\n [data-phase] [class*=\"_copyButton_1gdtu_\"] { position: sticky !important; right: 0; }\n [data-phase] [class*=\"_output_1gdtu_\"] {\n overflow-x: auto !important;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n touch-action: pan-x pan-y !important;\n }\n [data-phase] [class*=\"_output_1gdtu_\"]::-webkit-scrollbar { display: none !important; }\n [data-phase] [class*=\"_line_1gdtu_\"] {\n min-width: max-content !important;\n overflow-x: visible !important;\n max-height: 999999px !important;\n }\n\n /* 复制按钮周边也允许纵向页面手势,避免代码/总结区域形成触控死区。 */\n [data-phase] [class*=\"_copyButton_\"] { touch-action: manipulation !important; }\n [data-phase] [class*=\"_copyAnchor_\"],\n [data-phase] [class*=\"_body_1ye18_\"],\n [data-phase] [class*=\"_root_4qrvp_\"] { touch-action: pan-x pan-y !important; }\n\n /* 上下文用量弹窗(ContextMeter .JObwrW_panel):上游 dsh-client-ui-trajectory 的\n [class*=\"panel\"] 全局规则给它加了 max-width:100%!important,命中本弹窗,使宽度\n 从 264px 塌缩到包含块(.root 28px)宽,内容竖排成竖条。窄屏解除该误伤。 */\n .JObwrW_panel { max-width: none !important; overflow-x: visible !important; }\n\n /* 头部:标题省略,tab 条横向滚动 */\n [${FRAME_ATTR}=\"frame\"] [data-phase] header { padding-left: 44px; padding-right: 8px; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [class*=\"_crumbs\"] { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap !important; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"] { flex-wrap: nowrap; gap: 0 16px; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"]::-webkit-scrollbar { display: none; }\n [${FRAME_ATTR}=\"frame\"] [data-phase] header [role=\"tablist\"] > button { flex-shrink: 0; white-space: nowrap; }\n\n /* 设置对话框:窄屏近全宽 sheet(排除导出等普通对话框与目录选择器) */\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) {\n position: absolute !important;\n left: 8px !important;\n top: calc(env(safe-area-inset-top, 0px) + 12px) !important;\n width: calc(100vw - 16px) !important;\n max-width: calc(100vw - 16px) !important;\n height: auto !important;\n max-height: calc(100dvh - 24px - env(safe-area-inset-top, 0px)) !important;\n flex-direction: column !important;\n border-radius: 14px !important;\n }\n [aria-modal=\"true\"]:not(:has(> :first-child > :last-child > button)) { max-width: calc(100vw - 32px) !important; }\n /* nav:横排换行(避免 CJK 标签竖排楼梯状),隐藏冗余 caption */\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :first-child {\n width: 100%;\n flex-direction: row !important;\n align-items: center;\n gap: 6px;\n padding: 10px 12px 8px;\n }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :first-child > :first-child { display: none !important; }\n [aria-modal=\"true\"] [class*=\"_navList\"] { flex: 1 1 auto; min-width: 0; flex-direction: row !important; flex-wrap: wrap; gap: 6px; overflow: visible; }\n [aria-modal=\"true\"] [class*=\"_navList\"] > button { flex-shrink: 0; white-space: nowrap; }\n /* 外观模式卡片横排 */\n [aria-modal=\"true\"] [class*=\"_cubeRow\"] { gap: 6px; }\n [aria-modal=\"true\"] [class*=\"_cubeRow\"] > * { flex: 1 1 0; flex-direction: row !important; align-items: center; justify-content: center; gap: 6px; padding: 10px 8px; min-height: 0; }\n /* section 填充 sheet 宽度 */\n [aria-modal=\"true\"] [class*=\"_section\"] { width: 100% !important; max-width: none !important; }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :last-child { flex: 1 1 auto; min-height: 0; }\n [aria-modal=\"true\"]:has(> :first-child > :last-child > button):not(:has([role=\"navigation\"])):not(:has([class*=\"ZuhsRW\"])) > :last-child > :last-child { padding: 0 12px 24px; }\n\n /* 切换按钮:固定头部左侧 */\n [${FRAME_ATTR}=\"toggle\"] {\n position: absolute !important;\n left: 8px !important;\n top: 12px !important;\n z-index: 2 !important;\n display: inline-flex !important;\n align-items: center; justify-content: center;\n width: 28px; height: 28px;\n padding: 0; border: none; background: none; cursor: pointer; color: inherit;\n -webkit-tap-highlight-color: transparent;\n }\n\n /* 首页/hero(无活跃会话,session header 不存在)的抽屉切换 FAB:\n 浮在顶部相机带下方,避免与 hero 头部内容重叠 */\n [${FRAME_ATTR}=\"fab\"] {\n position: absolute !important;\n top: calc(env(safe-area-inset-top, 0px) + 72px) !important;\n left: 10px !important;\n z-index: 21 !important;\n display: inline-flex !important;\n align-items: center; justify-content: center;\n width: 38px; height: 38px;\n padding: 0;\n border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, .12)) !important;\n border-radius: 50% !important;\n background: var(--dsw-alias-button-floating-fill, #ffffff) !important;\n color: var(--dsw-alias-label-primary, inherit) !important;\n cursor: pointer !important;\n box-shadow: 0 2px 12px rgba(0, 0, 0, .18) !important;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n/* 宽屏 / 鼠标指针:隐藏切换按钮 */\n@media (min-width: 1024px), (pointer: fine) {\n [${FRAME_ATTR}=\"toggle\"], [${FRAME_ATTR}=\"fab\"] { display: none !important; }\n}\n`\n\nfunction findFrame(): HTMLElement | null {\n return document.querySelector('[data-shell-overlay]')?.parentElement ?? null\n}\n\nfunction getFrame(): HTMLElement | null {\n return document.querySelector(`[${FRAME_ATTR}=\"frame\"]`) ?? findFrame()\n}\n\n/** viewport-fit=cover:让 safe-area-inset 生效,内容避开刘海/状态栏。 */\nfunction installViewport(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n const viewport = document.querySelector<HTMLMetaElement>('meta[name=\"viewport\"]')\n if (viewport === null) return () => {}\n const original = viewport.content\n const sync = (): void => {\n viewport.content = narrow.matches\n ? 'width=device-width, initial-scale=1, viewport-fit=cover'\n : original\n }\n sync()\n narrow.addEventListener('change', sync)\n return () => {\n narrow.removeEventListener('change', sync)\n viewport.content = original\n }\n }, 'dshb-mobile: viewport')\n}\n\nfunction installStyles(ctx: ClientContext): void {\n ctx.effect(() => {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dshb-mobile'\n tag.textContent = MOBILE_CSS\n document.head.appendChild(tag)\n // 保持在 head 最后,确保覆盖宿主样式\n setTimeout(() => { if (tag.isConnected) document.head.appendChild(tag) }, 0)\n return () => { tag.remove() }\n }, 'dshb-mobile: styles')\n}\n\n/** 给 AppFrame 打标记(drawer CSS 选择器挂载点),窄屏才打。 */\nfunction installFrameMarker(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n let frame: HTMLElement | null = null\n const clear = (): void => {\n if (frame !== null) frame.removeAttribute(FRAME_ATTR)\n frame = null\n }\n const ensure = (): void => {\n if (!narrow.matches) return\n frame = findFrame()\n if (frame !== null && !frame.hasAttribute(FRAME_ATTR)) frame.setAttribute(FRAME_ATTR, 'frame')\n }\n ensure()\n const mo = new MutationObserver(ensure)\n mo.observe(document.documentElement, { childList: true, subtree: true })\n const onChange = (): void => { if (narrow.matches) ensure(); else clear() }\n narrow.addEventListener('change', onChange)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', onChange)\n clear()\n }\n }, 'dshb-mobile: frame marker')\n}\n\n/**\n * 抽屉打开时覆盖内容区的半透明遮罩,点击关闭;Escape 同样关闭;\n * 点击抽屉内的会话/导航项后关闭抽屉。\n */\nfunction installDrawerInteractions(ctx: ClientContext, toggleSidebar: () => void): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n let backdrop: HTMLElement | null = null\n const drawerOpen = (): boolean => {\n const frame = getFrame()\n return narrow.matches && frame !== null && !frame.hasAttribute(COLLAPSED_ATTR)\n }\n const sync = (): void => {\n if (drawerOpen() && backdrop === null) {\n backdrop = document.createElement('div')\n backdrop.setAttribute(`${FRAME_ATTR}-backdrop`, '')\n backdrop.style.cssText = 'position:fixed;inset:0;z-index:39;background:rgba(0,0,0,.4);-webkit-tap-highlight-color:transparent;'\n backdrop.addEventListener('click', () => toggleSidebar())\n document.body.appendChild(backdrop)\n } else if (!drawerOpen() && backdrop !== null) {\n backdrop.remove()\n backdrop = null\n }\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n if (document.querySelector('[aria-modal=\"true\"]') !== null) return\n if (drawerOpen()) toggleSidebar()\n }\n const onClick = (event: MouseEvent): void => {\n if (!drawerOpen()) return\n const target = event.target\n if (!(target instanceof Element)) return\n const drawer = document.querySelector(`[${FRAME_ATTR}=\"frame\"] > :first-child`)\n if (drawer === null || !drawer.contains(target)) return\n if (target.closest('button, a, [role=\"button\"]') !== null) return\n if (target.closest('[class*=\"newSession\"], [class*=\"sessionRow\"], [role=\"treeitem\"], [class*=\"searchResult\"]') !== null) toggleSidebar()\n }\n sync()\n const mo = new MutationObserver(sync)\n mo.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: [COLLAPSED_ATTR] })\n document.addEventListener('keydown', onKeyDown, true)\n document.addEventListener('click', onClick, true)\n narrow.addEventListener('change', sync)\n return () => {\n mo.disconnect()\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', onClick, true)\n narrow.removeEventListener('change', sync)\n backdrop?.remove()\n }\n }, 'dshb-mobile: drawer interactions')\n}\n\n/** 对话/输入框下方的统计行(turns/steps/LLM/TPS):hashed class 无法直接选,按文本特征标记后由 CSS 横向滚动,避免溢出。 */\nfunction installStatsLine(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n // 统计行文本特征(\"3 轮 · 5 步 · LLM 2.1s · 缓存命中 80%\" 等),hashed class 无法直接选,按文本识别。\n // 含\"轮/步/turns/steps\"即可(footer 不含这些),无需额外排除 footer。\n const STATS_LINE_RE = /(\\d+\\s*轮|\\d+\\s*步|\\bturns\\b|\\bsteps\\b)/\n const isStatsText = (el: Element): boolean => {\n const text = (el.textContent ?? '').trim()\n if (text.length === 0 || text.length > 160) return false\n if (!STATS_LINE_RE.test(text)) return false\n if (el.querySelector('textarea, input, button, select, a') !== null) return false\n return true\n }\n const mark = (): void => {\n if (!narrow.matches) return\n // 清除失效标记:行容器仍含统计特征(轮/步)才保留\n document.querySelectorAll(`[${FRAME_ATTR}=\"stats\"]`).forEach((el) => {\n if (!el.isConnected || !STATS_LINE_RE.test((el.textContent ?? '').trim())) el.removeAttribute(FRAME_ATTR)\n })\n // 候选:含统计特征的短文本元素(全文档搜索,含 composer 内的 stats line),取最浅容器标记\n // 排除 display:contents(无 box,overflow 无效,会误占最浅候选)\n const cands = Array.from(document.querySelectorAll('span, div')).filter((el) => {\n if (!isStatsText(el)) return false\n if (getComputedStyle(el).display === 'contents') return false\n return true\n })\n for (const el of cands) {\n if (el.hasAttribute(FRAME_ATTR)) continue\n let anc = el.parentElement\n let hasOuterCand = false\n while (anc) {\n if (cands.includes(anc)) { hasOuterCand = true; break }\n anc = anc.parentElement\n }\n if (!hasOuterCand) {\n // 标最浅含统计的容器本身(整行),使其可横向滚动\n if (!el.hasAttribute(FRAME_ATTR)) el.setAttribute(FRAME_ATTR, 'stats')\n }\n }\n }\n mark()\n const mo = new MutationObserver(() => { if (narrow.matches) mark() })\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', mark)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', mark)\n }\n }, 'dshb-mobile: stats line')\n}\n\n/** 浮层 fixed 定位需管理的内联样式键,清理时逐一移除以交还上游 CSS。 */\nconst SHEET_PROPS = [\n 'position', 'width', 'left', 'right', 'top', 'bottom',\n 'min-width', 'max-width', 'max-height', 'overflow-y', 'box-sizing',\n] as const\n\n/** Keep the model menu anchored to its trigger while fitting it in the viewport. */\nfunction positionAnchoredMenu(el: HTMLElement, triggerRect: DOMRect, maxWidth: number, maxHeight: number): void {\n const margin = 8\n const vw = window.innerWidth\n const vh = window.innerHeight\n el.style.setProperty('position', 'fixed', 'important')\n el.style.setProperty('box-sizing', 'border-box', 'important')\n el.style.setProperty('left', '0', 'important')\n el.style.setProperty('right', 'auto', 'important')\n el.style.setProperty('top', '0', 'important')\n el.style.setProperty('bottom', 'auto', 'important')\n el.style.setProperty('min-width', '0', 'important')\n el.style.setProperty('max-width', `${Math.max(0, Math.min(maxWidth, vw - margin * 2))}px`, 'important')\n el.style.setProperty('max-height', `${Math.max(0, Math.min(maxHeight, vh - margin * 2))}px`, 'important')\n el.style.setProperty('overflow-y', 'auto', 'important')\n let width = el.offsetWidth\n let height = el.offsetHeight\n const spaceAbove = Math.max(0, triggerRect.top - margin * 2)\n const spaceBelow = Math.max(0, vh - triggerRect.bottom - margin * 2)\n const expandUp = height <= spaceAbove || spaceAbove >= spaceBelow\n const available = expandUp ? spaceAbove : spaceBelow\n if (height > available) {\n el.style.setProperty('max-height', `${Math.max(0, available - margin)}px`, 'important')\n height = el.offsetHeight\n width = el.offsetWidth\n }\n const top = expandUp ? triggerRect.top - margin - height : triggerRect.bottom + margin\n const left = Math.max(margin, Math.min(triggerRect.right - width, vw - width - margin))\n el.style.setProperty('left', `${left}px`, 'important')\n el.style.setProperty('top', `${Math.max(margin, Math.min(top, vh - height - margin))}px`, 'important')\n}\n\n/**\n * 模型名多为纯连字符词(DeepSeek-V4-Flash-Vision-Exp);white-space:normal 下\n * 每个 \"-\" 都是软断点,名字一旦超列宽就在第一个连字符处断行(\"换行太早\")。\n * 把 \"-\" 就地换成不换行连字符 U+2011:放得下就整行显示,真超宽时仍由\n * overflow-wrap:break-word 兜底任意断。只改文本节点 data、不换节点,\n * 避免与 React 文本协调冲突;React 重渲染重置文本后由 MutationObserver\n * 重新应用(幂等:换过之后不再有 \"-\")。\n */\nfunction applyNonBreakingHyphens(menu: HTMLElement): void {\n for (const el of Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))) {\n const tn = el.firstChild\n if (tn && tn.nodeType === Node.TEXT_NODE && tn.nodeValue !== null && tn.nodeValue.includes('-')) {\n tn.nodeValue = tn.nodeValue.replace(/-/g, '\\u2011')\n }\n }\n}\n\n/**\n * 模型名\"整行显示、不换行、不截断\":窄屏下把名字列里的所有 .modelName 设为\n * nowrap,并按\"最宽名字 vs 可用列宽\"统一缩小字号(下限 11px,上限 14px),\n * 让最长的名字也恰好放得下——从根上消除\"换行太早\"。只测一次最宽名字\n * (scrollWidth 一次布局读取),缩放结果应用到全部名字,保持同一字号。\n * 调用方按 vw + 名字集合签名缓存,避免每次 DOM 变更都强制作废布局。\n */\nfunction fitModelNameFont(menu: HTMLElement): void {\n const names = Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))\n if (names.length === 0) return\n const col = names[0].parentElement\n if (col === null) return\n const colW = col.clientWidth - 4\n if (colW <= 0) return\n const base = 14\n let longest = names[0]\n for (const n of names) {\n if ((n.textContent?.length ?? 0) > (longest.textContent?.length ?? 0)) longest = n\n }\n const prevWs = longest.style.whiteSpace\n longest.style.whiteSpace = 'nowrap'\n longest.style.fontSize = `${base}px`\n const natural = longest.scrollWidth\n longest.style.whiteSpace = prevWs\n longest.style.fontSize = ''\n const fs = natural > colW ? Math.max(11, Math.min(base, Math.round(base * (colW / natural)))) : base\n for (const n of names) {\n n.style.setProperty('white-space', 'nowrap', 'important')\n n.style.setProperty('font-size', `${fs}px`, 'important')\n }\n}\n\n/** 宽屏(窄屏判定不成立)时复位名字列内联样式,交还上游 CSS(nowrap+ellipsis)。 */\nfunction clearModelNameFit(menu: HTMLElement | null | undefined): void {\n if (menu === null || menu === undefined) return\n for (const n of Array.from(menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]'))) {\n n.style.removeProperty('white-space')\n n.style.removeProperty('font-size')\n }\n}\n\n/** 清除 anchored menu 写入的内联样式,交还上游 CSS。 */\nfunction clearFixedSheet(el: HTMLElement | null | undefined): void {\n if (el === null || el === undefined) return\n for (const key of SHEET_PROPS) el.style.removeProperty(key)\n}\n\n/**\n * 模型选择弹窗(dsh-client-ui-model-selection)是两级 pane 的同一个 `_7KE1Ra_menu`\n * 元素:一级 Model/Effort 单元格列表(cellLabel),点击后切到模型列表(modelName)\n * 或档位列表。上游默认 `position:absolute;right:0` 贴触发按钮右缘,触发按钮在\n * 可横向滚动的 stats 行内时菜单会整体出屏。两级 pane 都必须接管(不能只按\n * modelName 匹配,否则一级 pane 漏掉)。所有视口都把菜单锚定到触发按钮,\n * 在上方/下方可用空间中选择更合适的一侧,避免上游空间不足时把菜单钳到屏幕顶端。\n */\nfunction installModelMenuPosition(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(NARROW_QUERY)\n // 多 tab 场景可能并存多个模型选择器(各自一个 _menu);只处理可见的,\n // 避免 document.querySelector 命中隐藏 tab 的菜单而漏掉用户正在看的那个。\n const findMenus = (): HTMLElement[] => {\n const byHash = Array.from(document.querySelectorAll<HTMLElement>('[class*=\"7KE1Ra_menu\"]'))\n if (byHash.length > 0) return byHash\n // 上游升级换 hash 后回退:语义类匹配(cellLabel 命中一级 pane,modelName 命中二级)\n return Array.from(document.querySelectorAll<HTMLElement>('[class*=\"_menu\"]')).filter((el) =>\n el.querySelector('[class*=\"cellLabel\"], [class*=\"modelName\"]') !== null,\n )\n }\n const findTrigger = (menu: HTMLElement): HTMLElement | null => {\n if (menu.id) {\n const controlled = Array.from(document.querySelectorAll<HTMLElement>('[aria-controls]')).find(\n (el) => el.getAttribute('aria-controls') === menu.id,\n )\n if (controlled) return controlled\n }\n return document.querySelector<HTMLElement>('[class*=\"7KE1Ra_trigger\"][aria-expanded=\"true\"]')\n }\n let fittedVw = 0\n let fittedSig = -1\n let fittedMenus: HTMLElement[] = []\n let positionedMenus: HTMLElement[] = []\n const sync = (): void => {\n const menus = findMenus()\n let vw = 0\n let sig = 0\n const modelMenus: HTMLElement[] = []\n const visibleMenus: HTMLElement[] = []\n for (const menu of menus) {\n // 0.1.5 renders the menu through createPortal(..., document.body), so\n // parentElement is body rather than the trigger root. Match aria-controls\n // to the portal menu id to find the exact trigger across multiple tabs.\n const trigger = findTrigger(menu)\n if (trigger === null || trigger.getAttribute('aria-expanded') !== 'true') continue\n const rect = menu.getBoundingClientRect()\n // 跳过隐藏 tab / 未打开的菜单(0 尺寸或祖先 display:none)\n if (rect.width === 0 && rect.height === 0) continue\n const triggerRect = trigger.getBoundingClientRect()\n positionAnchoredMenu(menu, triggerRect, Math.min(420, window.innerWidth - 16), 360)\n visibleMenus.push(menu)\n if (menu.querySelector('[class*=\"modelName\"]')) {\n modelMenus.push(menu)\n if (narrow.matches) {\n applyNonBreakingHyphens(menu)\n vw = window.innerWidth\n for (const n of menu.querySelectorAll<HTMLElement>('[class*=\"modelName\"]')) {\n sig += n.textContent?.length ?? 0\n }\n }\n }\n }\n for (const previous of positionedMenus) {\n if (visibleMenus.includes(previous)) continue\n clearFixedSheet(previous)\n clearModelNameFit(previous)\n }\n positionedMenus = visibleMenus\n if (!narrow.matches) {\n for (const menu of modelMenus) clearModelNameFit(menu)\n fittedVw = 0\n fittedSig = -1\n fittedMenus = []\n return\n }\n // 菜单关闭再打开时 React 会重建菜单元素(新元素没有任何内联样式),\n // 所以缓存必须含元素身份:vw / 名字集合 / 菜单实例任一变化都要重测,\n // 否则重开的菜单会漏掉 nowrap+缩字而再次换行。\n const needFit = modelMenus.some((m) => !fittedMenus.includes(m))\n if (vw > 0 && (needFit || vw !== fittedVw || sig !== fittedSig)) {\n for (const menu of modelMenus) fitModelNameFont(menu)\n fittedVw = vw\n fittedSig = sig\n fittedMenus = modelMenus\n }\n }\n sync()\n const mo = new MutationObserver(() => requestAnimationFrame(sync))\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', sync)\n window.addEventListener('resize', sync)\n window.addEventListener('scroll', sync, true)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n window.removeEventListener('resize', sync)\n window.removeEventListener('scroll', sync, true)\n }\n }, 'dshb-mobile: model menu position')\n}\n\n/**\n * 上下文用量弹窗(ContextMeter .JObwrW_panel,dsh-client-ui-conversation)上游是\n * `position:absolute; bottom:calc(100%+8px); right:0` 挂 .JObwrW_root 内。窄屏下\n * 改为 fixed 视口浮层,右缘锚定触发按钮右缘、向上展开(用户已验证该形态正常,勿改)。\n */\nfunction installContextPanelPosition(ctx: ClientContext): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(NARROW_QUERY)\n const sync = (): void => {\n if (!narrow.matches) return\n const panels = document.querySelectorAll<HTMLElement>('[class*=\"JObwrW_panel\"]')\n for (const panel of Array.from(panels)) {\n const root = panel.parentElement\n if (root === null || !root.className.includes('JObwrW_root')) continue\n const rootRect = root.getBoundingClientRect()\n if (rootRect.width === 0 && rootRect.height === 0) continue\n const gap = 8\n panel.style.setProperty('position', 'fixed', 'important')\n panel.style.setProperty('top', 'auto', 'important')\n panel.style.setProperty('bottom', `${window.innerHeight - rootRect.top + gap}px`, 'important')\n panel.style.setProperty('left', 'auto', 'important')\n panel.style.setProperty('right', `${Math.max(gap, window.innerWidth - rootRect.right)}px`, 'important')\n panel.style.setProperty('max-height', `${Math.max(160, rootRect.top - gap * 2)}px`, 'important')\n panel.style.setProperty('overflow-y', 'auto', 'important')\n }\n }\n sync()\n const mo = new MutationObserver(() => requestAnimationFrame(sync))\n mo.observe(document.documentElement, { childList: true, subtree: true })\n narrow.addEventListener('change', sync)\n window.addEventListener('resize', sync)\n window.addEventListener('scroll', sync, true)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n window.removeEventListener('resize', sync)\n window.removeEventListener('scroll', sync, true)\n }\n }, 'dshb-mobile: context panel position')\n}\n\nfunction installMobileTerminalInputFocus(ctx: ClientContext): void {\n ctx.effect(() => {\n const mobile = window.matchMedia(MOBILE_QUERY)\n const focusInput = (event: PointerEvent): void => {\n if (!mobile.matches || !(event.target instanceof Element)) return\n const terminal = event.target.closest('.xterm')\n const textarea = terminal?.querySelector<HTMLTextAreaElement>('.xterm-helper-textarea')\n if (!textarea || textarea.readOnly) return\n textarea.inputMode = 'text'\n textarea.focus({ preventScroll: true })\n try {\n const virtualKeyboard = (navigator as Navigator & { virtualKeyboard?: { show?: () => void } }).virtualKeyboard\n virtualKeyboard?.show?.()\n } catch {\n // The focus event still opens the keyboard on browsers without VirtualKeyboard API.\n }\n }\n document.addEventListener('pointerdown', focusInput, true)\n return () => document.removeEventListener('pointerdown', focusInput, true)\n }, 'dshb-mobile: terminal input focus')\n}\n\ninterface LayoutLike { toggleSidebar(): void }\ninterface SlotsLike {\n inject(name: string, fn: () => unknown): unknown\n register(spec: Record<string, unknown>, component: unknown): unknown\n}\n\n/** 目录抽屉切换按钮(仅切换,不含文件浏览/日志导出等功能按钮)。 */\nfunction DrawerToggle({ toggleSidebar }: { toggleSidebar: () => void }) {\n return (\n <button type=\"button\" data-dshb-mobile=\"toggle\" aria-label=\"打开目录\" title=\"打开目录\" onClick={() => toggleSidebar()}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M6 2.5v11\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n </button>\n )\n}\n\nconst PANEL_ICON_SVG =\n '<svg width=\"18\" height=\"18\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">' +\n '<rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>' +\n '<path d=\"M6 2.5v11\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>' +\n '</svg>'\n\n/**\n * 首页 / hero(无活跃会话)没有 session header,header 上的切换按钮不渲染;\n * 这里在 frame 上注入一个浮动切换按钮(FAB),仅 hero 且抽屉收起时显示。\n */\nfunction installFab(ctx: ClientContext, toggleSidebar: () => void): void {\n ctx.effect(() => {\n const narrow = window.matchMedia(MOBILE_QUERY)\n const FAB_ATTR = 'fab'\n const heroPhase = (): boolean => document.querySelector('[data-phase=\"active\"]') === null\n const drawerOpen = (): boolean => {\n const frame = getFrame()\n return frame !== null && !frame.hasAttribute(COLLAPSED_ATTR)\n }\n let fab: HTMLButtonElement | null = null\n const sync = (): void => {\n if (!narrow.matches || !heroPhase() || drawerOpen()) {\n if (fab !== null) {\n fab.remove()\n fab = null\n }\n return\n }\n const frame = getFrame()\n if (frame === null) return\n if (fab !== null && fab.parentElement === frame) return\n fab?.remove()\n fab = document.createElement('button')\n fab.type = 'button'\n fab.setAttribute(FRAME_ATTR, FAB_ATTR)\n fab.setAttribute('aria-label', '打开目录')\n fab.setAttribute('title', '打开目录')\n fab.innerHTML = PANEL_ICON_SVG\n fab.addEventListener('click', toggleSidebar)\n frame.appendChild(fab)\n }\n sync()\n const mo = new MutationObserver(sync)\n mo.observe(document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-phase', 'data-sidebar-collapsed', 'class'],\n })\n narrow.addEventListener('change', sync)\n return () => {\n mo.disconnect()\n narrow.removeEventListener('change', sync)\n fab?.remove()\n }\n }, 'dshb-mobile: hero fab')\n}\n\n/** 安装移动端适配:样式 + viewport + 抽屉标记 + 抽屉交互 + 切换按钮。 */\nexport function installMobile(ctx: ClientContext): void {\n installStyles(ctx)\n installMobileTerminalInputFocus(ctx)\n installViewport(ctx)\n installFrameMarker(ctx)\n installStatsLine(ctx)\n installModelMenuPosition(ctx)\n installContextPanelPosition(ctx)\n const layout = (ctx as unknown as { layout?: LayoutLike }).layout\n const slots = (ctx as unknown as { slots?: SlotsLike }).slots\n if (layout && typeof layout.toggleSidebar === 'function') {\n const toggleSidebar = (): void => layout.toggleSidebar()\n installDrawerInteractions(ctx, toggleSidebar)\n installFab(ctx, toggleSidebar)\n }\n if (slots && layout) {\n slots.inject('conversation.session.header.actions', () =>\n slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'dshb-mobile-toggle',\n order: 10,\n inject: () => ({ toggleSidebar: () => layout.toggleSidebar() }),\n },\n DrawerToggle,\n ),\n )\n }\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\n\ninterface WorkspaceItem {\n workspaceId: string\n title: string\n path: string\n}\n\ninterface WorkspaceSnapshotLike {\n items: readonly WorkspaceItem[]\n}\n\ninterface WorkspacesLike {\n list: {\n getSnapshot(): WorkspaceSnapshotLike\n subscribe(listener: () => void): () => void\n }\n}\n\nlet injectedRegistry: WorkspacesLike | undefined\n\nexport function setWorkspaceRegistry(reg: WorkspacesLike): void {\n injectedRegistry = reg\n}\n\nfunction resolveWorkspaceByTitle(title: string): WorkspaceItem | undefined {\n const wks = injectedRegistry\n if (!wks) return undefined\n const items = wks.list.getSnapshot().items\n return items.find((w) => w.title === title)\n}\n\nconst ROW_INJECT_FLAG = 'data-dshb-instr-row-bound'\nconst MENU_INJECT_FLAG = 'data-dshb-instr-menu-bound'\nconst MENU_ITEM_FLAG = 'data-dshb-instr-menu-item'\n\nfunction mountInstructionDialog(workspaceId: string, workspaceTitle: string): void {\n if (!workspaceId) return\n\n const overlay = document.createElement('div')\n overlay.style.cssText = 'position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;background:var(--dsw-alias-overlay-mask,rgba(0,0,0,.45))'\n\n const dialog = document.createElement('div')\n dialog.setAttribute('role', 'dialog')\n dialog.setAttribute('aria-label', `修改 ${workspaceTitle} 的项目指令`)\n dialog.style.cssText = 'box-sizing:border-box;width:min(92vw,600px);max-height:85vh;overflow:auto;padding:20px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)'\n\n const title = document.createElement('h2')\n title.textContent = `项目指令 - ${workspaceTitle}`\n title.style.cssText = 'margin:0 0 10px;font-size:16px'\n\n const description = document.createElement('div')\n description.textContent = '此内容会注入该工作区的新对话。已有对话继续使用创建时的指令快照。'\n description.style.cssText = 'margin-bottom:10px;font-size:12px;color:var(--dsw-alias-label-secondary)'\n\n const textarea = document.createElement('textarea')\n textarea.placeholder = '留空则不注入指令...'\n textarea.spellcheck = false\n textarea.style.cssText = 'box-sizing:border-box;width:100%;min-height:280px;resize:vertical;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px monospace'\n\n const status = document.createElement('div')\n status.style.cssText = 'min-height:18px;margin-top:6px;font-size:12px;color:var(--dsw-alias-label-secondary)'\n\n const actions = document.createElement('div')\n actions.style.cssText = 'display:flex;justify-content:flex-end;gap:10px;margin-top:14px'\n const cancel = document.createElement('button')\n cancel.type = 'button'\n cancel.textContent = '取消'\n cancel.style.cssText = 'height:36px;padding:0 16px;border:1px solid var(--dsw-alias-border-l2);border-radius:18px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer'\n const save = document.createElement('button')\n save.type = 'button'\n save.textContent = '保存'\n save.style.cssText = 'height:36px;padding:0 16px;border:0;border-radius:18px;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);cursor:pointer'\n\n const close = (): void => overlay.remove()\n cancel.addEventListener('click', close)\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) close()\n })\n dialog.addEventListener('click', (event) => event.stopPropagation())\n textarea.addEventListener('input', () => {\n const bytes = new TextEncoder().encode(textarea.value).length\n status.textContent = `${bytes} / 32768 字节`\n status.style.color = bytes > 32768 ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-secondary)'\n })\n save.addEventListener('click', () => {\n void (async () => {\n const bytes = new TextEncoder().encode(textarea.value).length\n if (bytes > 32768) {\n status.textContent = `指令超过 32768 字节限制(当前 ${bytes} 字节)`\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n return\n }\n save.disabled = true\n save.textContent = '保存中...'\n try {\n const revision = Number(overlay.dataset.revision ?? '0')\n const response = await fetch(`/api/dshb/instructions/${workspaceId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ text: textarea.value, expectedRevision: revision }),\n })\n if (!response.ok) {\n const body = await response.json().catch(() => ({})) as { error?: string }\n status.textContent = body.error ?? `保存失败 (${response.status})`\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n return\n }\n close()\n } catch {\n status.textContent = '保存失败'\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n } finally {\n save.disabled = false\n save.textContent = '保存'\n }\n })()\n })\n\n actions.append(cancel, save)\n dialog.append(title, description, textarea, status, actions)\n overlay.append(dialog)\n document.body.append(overlay)\n\n status.textContent = '加载中...'\n void fetch(`/api/dshb/instructions/${workspaceId}`)\n .then(async (response) => {\n if (!response.ok) throw new Error(`读取失败 (${response.status})`)\n return response.json() as Promise<{ text?: string; revision?: number }>\n })\n .then((body) => {\n textarea.value = body.text ?? ''\n overlay.dataset.revision = String(body.revision ?? 0)\n textarea.dispatchEvent(new Event('input'))\n textarea.focus()\n })\n .catch((error: unknown) => {\n status.textContent = error instanceof Error ? error.message : '读取失败'\n status.style.color = 'var(--dsw-alias-state-error-primary)'\n })\n}\n\nexport function registerWorkspaceInstructionMenu(ctx: ClientContext): void {\n const wks = (ctx as unknown as { workspaces?: WorkspacesLike }).workspaces\n if (wks) setWorkspaceRegistry(wks)\n\n let activeWorkspaceTitle = ''\n\n const findWorkspaceRow = (el: Node | null): HTMLElement | null => {\n let node = el instanceof HTMLElement ? el : null\n while (node) {\n if (node.className && typeof node.className === 'string' && node.className.includes('projectRow')) {\n return node\n }\n node = node.parentElement\n }\n return null\n }\n\n const getRowTitle = (row: HTMLElement): string | null => {\n const titleEl = row.querySelector('[class*=\"title\"]')\n if (!titleEl) return null\n return titleEl.textContent ?? null\n }\n\n const injectMenuItem = (menuContainer: HTMLElement): void => {\n if (menuContainer.getAttribute(MENU_INJECT_FLAG) || menuContainer.querySelector(`[${MENU_ITEM_FLAG}]`)) return\n menuContainer.setAttribute(MENU_INJECT_FLAG, '1')\n\n const existingItems = menuContainer.querySelectorAll('button, [role=\"menuitem\"]')\n let refItem: Element | null = null\n for (const item of Array.from(existingItems)) {\n const text = item.textContent ?? ''\n if (text.includes('重命名') || text.includes('Rename')) {\n refItem = item\n break\n }\n }\n if (!refItem) refItem = existingItems[existingItems.length - 1]\n if (!refItem) return\n\n const btn = document.createElement('button')\n btn.type = 'button'\n btn.setAttribute('role', 'menuitem')\n btn.setAttribute(MENU_ITEM_FLAG, '1')\n if (refItem instanceof HTMLElement) {\n btn.className = refItem.className || ''\n btn.style.cssText = refItem.style.cssText\n }\n for (const className of Array.from(btn.classList)) {\n if (/danger|delete/i.test(className)) btn.classList.remove(className)\n }\n btn.style.color = 'var(--dsw-alias-label-primary)'\n btn.style.display = 'flex'\n btn.style.alignItems = 'center'\n btn.style.gap = '8px'\n\n const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n icon.setAttribute('width', '16')\n icon.setAttribute('height', '16')\n icon.setAttribute('viewBox', '0 0 16 16')\n icon.setAttribute('fill', 'none')\n icon.setAttribute('aria-hidden', 'true')\n icon.style.flex = 'none'\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('d', 'M3 11.75V13h1.25l7.37-7.37-1.25-1.25L3 11.75Zm9.59-7.34a.66.66 0 0 0 0-.94l-1.06-1.06a.66.66 0 0 0-.94 0l-.83.83 1.25 1.25.83-.83.75.75Z')\n path.setAttribute('fill', 'currentColor')\n icon.append(path)\n const label = document.createElement('span')\n label.textContent = '修改指令'\n btn.append(icon, label)\n btn.addEventListener('click', (e) => {\n e.stopPropagation()\n e.preventDefault()\n const ws = activeWorkspaceTitle ? resolveWorkspaceByTitle(activeWorkspaceTitle) : undefined\n mountInstructionDialog(ws?.workspaceId ?? '', activeWorkspaceTitle || 'Unknown')\n })\n\n refItem.parentElement?.insertBefore(btn, refItem.nextSibling)\n }\n\n const observer = new MutationObserver(() => {\n const projectRows = document.querySelectorAll('[class*=\"projectRow\"]')\n for (const row of Array.from(projectRows)) {\n const rowEl = row as HTMLElement\n if (rowEl.getAttribute(ROW_INJECT_FLAG)) continue\n rowEl.setAttribute(ROW_INJECT_FLAG, '1')\n const iconBtns = rowEl.querySelectorAll('button[class*=\"iconButton\"]')\n for (const btn of Array.from(iconBtns)) {\n const label = btn.getAttribute('aria-label') ?? ''\n if (label.includes('workspace') || label.includes('操作') || label.includes('actions')) {\n btn.addEventListener('click', () => {\n const title = getRowTitle(rowEl)\n if (title) activeWorkspaceTitle = title\n })\n }\n }\n }\n\n const menuItems = document.querySelectorAll('[role=\"menuitem\"]')\n for (const item of Array.from(menuItems)) {\n const text = item.textContent ?? ''\n if (text.includes('删除') || text.includes('Delete') || text.includes('重命名') || text.includes('Rename')) {\n const container = item.closest('[role=\"menu\"]') ?? item.parentElement\n if (container instanceof HTMLElement && !container.getAttribute(MENU_INJECT_FLAG)) {\n const row = findWorkspaceRow(container)\n if (row) {\n const title = getRowTitle(row)\n if (title) activeWorkspaceTitle = title\n }\n injectMenuItem(container)\n }\n }\n }\n })\n observer.observe(document.body, { childList: true, subtree: true })\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-workspace/client'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { CSSProperties, ReactElement } from 'react'\nimport { useCallback, useEffect, useState } from 'react'\nimport { DirectoryFlowOccupant } from './directory-flow.js'\nimport { installMobile } from './mobile.js'\nimport { registerWorkspaceInstructionMenu } from './workspace-instruction-menu.js'\n\nexport const inject = ['connection', 'workspaces', 'slots', 'layout', 'conversation']\n\nconst SECTION_ID = 'dshb-nodes'\n\ninterface NodeProfileView {\n id: string\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n ssh?: {\n host: string\n port: number\n username: string\n auth: { kind: 'password' | 'key' | 'agent'; keyPath?: string }\n }\n docker?: {\n image?: string\n containerId?: string\n mode?: string\n resources?: { cpus?: number; memoryMB?: number }\n }\n hasSecret: { hasPassword: boolean; hasKey: boolean; hasPassphrase: boolean }\n status?: { reachable?: boolean; lastCheckedAt?: string; error?: string }\n provision?: { state: 'provisioning' | 'ready' | 'failed'; error?: string; containerId?: string; updatedAt: string }\n}\n\ninterface SshConfigEntryView {\n host: string\n port: number\n username: string\n identityFile?: string\n hasIdentityFile: boolean\n hasProxyJump: boolean\n}\n\ninterface FormState {\n name: string\n type: 'local-host' | 'local-docker' | 'remote-ssh' | 'remote-docker'\n host: string\n port: string\n username: string\n authKind: 'password' | 'key' | 'agent'\n password: string\n privateKey: string\n passphrase: string\n keyPath: string\n dockerImage: string\n dockerCpus: string\n dockerMemory: string\n}\n\nconst EMPTY_FORM: FormState = {\n name: '',\n type: 'remote-ssh',\n host: '',\n port: '22',\n username: '',\n authKind: 'password',\n password: '',\n privateKey: '',\n passphrase: '',\n keyPath: '',\n dockerImage: '',\n dockerCpus: '',\n dockerMemory: '',\n}\n\ntype Notice = { kind: 'ok' | 'error'; text: string } | undefined\n\nconst inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n height: 32,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n fontSize: 14,\n fontFamily: 'inherit',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n outline: 'none',\n}\nconst buttonStyle: CSSProperties = {\n boxSizing: 'border-box',\n height: 36,\n padding: '0 14px',\n borderRadius: 18,\n fontSize: 14,\n lineHeight: '22px',\n fontFamily: 'inherit',\n cursor: 'pointer',\n border: 'none',\n display: 'inline-flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 4,\n}\nconst primaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\nconst secondaryButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-primary)',\n background: 'transparent',\n}\nconst dangerOutlineButtonStyle: CSSProperties = {\n ...buttonStyle,\n border: '1px solid var(--dsw-alias-state-error-primary)',\n color: 'var(--dsw-alias-state-error-primary)',\n background: 'transparent',\n}\n\nfunction useNodes(reloadKey: number): NodeProfileView[] {\n const [nodes, setNodes] = useState<NodeProfileView[]>([])\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const res = await fetch('/api/dshb/nodes')\n if (!res.ok) return\n const data = (await res.json()) as { nodes?: NodeProfileView[] }\n if (!cancelled) setNodes(data.nodes ?? [])\n } catch {}\n })()\n return () => {\n cancelled = true\n }\n }, [reloadKey])\n return nodes\n}\n\nexport function NodeSection(_props: PropsRuntime<'settings.section'>): ReactElement {\n const [reloadKey, setReloadKey] = useState(0)\n const nodes = useNodes(reloadKey)\n const [selectedId, setSelectedId] = useState<string | 'new'>('new')\n const [form, setForm] = useState<FormState>(EMPTY_FORM)\n const [notice, setNotice] = useState<Notice>(undefined)\n const [busy, setBusy] = useState(false)\n const [testing, setTesting] = useState(false)\n const [testResult, setTestResult] = useState<string | undefined>(undefined)\n const [sshConfigEntries, setSshConfigEntries] = useState<SshConfigEntryView[]>([])\n const [dockerBusy, setDockerBusy] = useState(false)\n\n const flash = useCallback((n: Notice) => {\n setNotice(n)\n if (n) setTimeout(() => setNotice(undefined), 6000)\n }, [])\n\n const reload = useCallback(() => setReloadKey((k) => k + 1), [])\n\n useEffect(() => {\n void (async () => {\n try {\n const res = await fetch('/api/dshb/ssh-config')\n if (!res.ok) return\n const data = (await res.json()) as { entries?: SshConfigEntryView[] }\n setSshConfigEntries(data.entries ?? [])\n } catch {}\n })()\n }, [])\n\n const selectNode = useCallback(\n (id: string | 'new') => {\n setSelectedId(id)\n setTestResult(undefined)\n setTesting(false)\n setDockerBusy(false)\n if (id === 'new') {\n setForm(EMPTY_FORM)\n return\n }\n const node = nodes.find((n) => n.id === id)\n if (!node) return\n setForm({\n name: node.name,\n type: node.type,\n host: node.ssh?.host ?? '',\n port: String(node.ssh?.port ?? 22),\n username: node.ssh?.username ?? '',\n authKind: node.ssh?.auth.kind ?? 'password',\n password: '',\n privateKey: '',\n passphrase: '',\n keyPath: node.ssh?.auth.keyPath ?? '',\n dockerImage: node.docker?.image ?? '',\n dockerCpus: node.docker?.resources?.cpus != null ? String(node.docker?.resources?.cpus) : '',\n dockerMemory: node.docker?.resources?.memoryMB != null ? String(node.docker?.resources?.memoryMB) : '',\n })\n },\n [nodes],\n )\n\n const importSshConfig = useCallback((entry: SshConfigEntryView) => {\n setForm((f) => ({\n ...f,\n type: 'remote-ssh',\n host: entry.host,\n port: String(entry.port),\n username: entry.username,\n authKind: entry.hasIdentityFile ? 'key' : f.authKind,\n keyPath: entry.identityFile ?? f.keyPath,\n name: f.name || entry.host,\n }))\n setTestResult(undefined)\n flash({ kind: 'ok', text: `已从 ~/.ssh/config 导入 ${entry.host}` })\n }, [flash])\n\n const save = useCallback(async () => {\n if (!form.name.trim()) {\n flash({ kind: 'error', text: '请填写节点名称' })\n return\n }\n setBusy(true)\n try {\n const isRemote = form.type === 'remote-ssh' || form.type === 'remote-docker'\n const isDocker = form.type === 'local-docker' || form.type === 'remote-docker'\n const payload: Record<string, unknown> = {\n name: form.name.trim(),\n type: form.type,\n ssh: isRemote\n ? {\n host: form.host.trim(),\n port: Number(form.port) || 22,\n username: form.username.trim(),\n auth: { kind: form.authKind, ...(form.keyPath.trim() ? { keyPath: form.keyPath.trim() } : {}) },\n }\n : undefined,\n secrets: isRemote\n ? {\n ...(form.password ? { password: form.password } : {}),\n ...(form.privateKey ? { privateKey: form.privateKey } : {}),\n ...(form.passphrase ? { passphrase: form.passphrase } : {}),\n }\n : undefined,\n docker: isDocker\n ? {\n mode: 'managed' as const,\n ...(form.dockerImage.trim() ? { image: form.dockerImage.trim() } : {}),\n ...(form.dockerCpus ? { resources: { cpus: Number(form.dockerCpus) || undefined } } : {}),\n ...(form.dockerMemory ? { resources: { memoryMB: Number(form.dockerMemory) || undefined } } : {}),\n ...(form.dockerCpus && form.dockerMemory ? { resources: { cpus: Number(form.dockerCpus) || undefined, memoryMB: Number(form.dockerMemory) || undefined } } : {}),\n }\n : undefined,\n }\n const url = selectedId === 'new' ? '/api/dshb/nodes' : `/api/dshb/nodes/${selectedId}`\n const res = await fetch(url, {\n method: selectedId === 'new' ? 'POST' : 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n const data = (await res.json()) as { ok?: boolean; error?: string; node?: NodeProfileView }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: selectedId === 'new' ? '节点已创建' : '节点已保存' })\n reload()\n if (data.node) setSelectedId(data.node.id)\n } else {\n flash({ kind: 'error', text: data.error ?? '保存失败' })\n }\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setBusy(false)\n }\n }, [form, selectedId, flash, reload])\n\n const remove = useCallback(async () => {\n if (selectedId === 'new') return\n setBusy(true)\n try {\n const res = await fetch(`/api/dshb/nodes/${selectedId}`, { method: 'DELETE' })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: '节点已删除' })\n setSelectedId('new')\n setForm(EMPTY_FORM)\n reload()\n } else {\n flash({ kind: 'error', text: data.error ?? '删除失败' })\n }\n } catch {\n flash({ kind: 'error', text: '删除失败' })\n } finally {\n setBusy(false)\n }\n }, [selectedId, flash, reload])\n\n const test = useCallback(async () => {\n if (form.type === 'local-host') {\n flash({ kind: 'error', text: '本地节点无需测试连接' })\n return\n }\n const isRemote = form.type === 'remote-ssh' || form.type === 'remote-docker'\n if (isRemote && !form.host.trim()) {\n flash({ kind: 'error', text: '请填写主机地址' })\n return\n }\n setTesting(true)\n setTestResult(undefined)\n try {\n const payload = isRemote ? {\n ssh: {\n host: form.host.trim(),\n port: Number(form.port) || 22,\n username: form.username.trim(),\n auth: { kind: form.authKind, ...(form.keyPath.trim() ? { keyPath: form.keyPath.trim() } : {}) },\n },\n secrets: {\n ...(form.password ? { password: form.password } : {}),\n ...(form.privateKey ? { privateKey: form.privateKey } : {}),\n ...(form.passphrase ? { passphrase: form.passphrase } : {}),\n },\n } : {}\n const url = selectedId === 'new' ? '/api/dshb/nodes/test-unsaved' : `/api/dshb/nodes/${selectedId}/test`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n const data = (await res.json()) as { ok?: boolean; report?: { ok?: boolean; reachable?: boolean; error?: string; category?: string } }\n const r = data.report\n if (r?.ok && r.reachable) {\n setTestResult('连接成功')\n } else {\n const cat = r?.category ? `(${r.category})` : ''\n setTestResult(`${r?.error ?? '连接失败'}${cat}`)\n }\n reload()\n } catch {\n setTestResult('网络错误')\n } finally {\n setTesting(false)\n }\n }, [form, selectedId, reload])\n\n const dockerAction = useCallback(async (action: 'restart' | 'stop' | 'start' | 'provision') => {\n if (selectedId === 'new') return\n if (action === 'provision') {\n setDockerBusy(true)\n try {\n const res = await fetch(`/api/dshb/docker/${selectedId}/provision`, { method: 'POST' })\n const data = (await res.json()) as { ok?: boolean; error?: string; containerId?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: `容器已就绪:${data.containerId?.slice(0, 12) ?? ''}` })\n } else {\n flash({ kind: 'error', text: data.error ?? '拉起失败' })\n }\n reload()\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setDockerBusy(false)\n }\n return\n }\n setDockerBusy(true)\n try {\n const res = await fetch(`/api/dshb/docker/${selectedId}/${action}`, { method: 'POST' })\n const data = (await res.json()) as { ok?: boolean; error?: string }\n if (res.ok && data.ok) {\n flash({ kind: 'ok', text: action === 'restart' ? '容器已重启' : action === 'stop' ? '容器已停止' : '容器已启动' })\n } else {\n flash({ kind: 'error', text: data.error ?? '操作失败' })\n }\n reload()\n } catch {\n flash({ kind: 'error', text: '网络错误' })\n } finally {\n setDockerBusy(false)\n }\n }, [selectedId, flash, reload])\n\n const selectedNode = selectedId === 'new' ? undefined : nodes.find((n) => n.id === selectedId)\n\n return (\n <>\n <style>{`\n @media (max-width:767px){\n .dshb-node-section{flex-direction:column!important}\n .dshb-node-section>div:first-child{width:100%!important;border-right:none!important;border-bottom:1px solid var(--dsw-alias-border-l2);padding-right:0!important;padding-bottom:12px;margin-bottom:12px}\n .dshb-node-section>div:last-child{max-width:100%!important}\n .dshb-form-row{flex-direction:column!important;gap:8px!important}\n .dshb-form-row>label{width:100%!important;flex:none!important}\n }\n `}</style>\n <div className=\"dshb-node-section\" style={{ display: 'flex', gap: 20, minHeight: 320, overflow: 'hidden', maxWidth: '100%', width: '100%', boxSizing: 'border-box' }}>\n <div style={{ width: 200, flexShrink: 0, borderRight: '1px solid var(--dsw-alias-border-l2)', paddingRight: 16 }}>\n <button type=\"button\" onClick={() => selectNode('new')} style={{ ...primaryButtonStyle, width: '100%', marginBottom: 10 }}>\n 新建节点\n </button>\n {nodes.map((n) => (\n <div\n key={n.id}\n onClick={() => selectNode(n.id)}\n style={{\n padding: '8px 10px',\n borderRadius: 6,\n cursor: 'pointer',\n marginBottom: 4,\n background: selectedId === n.id ? 'var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))' : 'transparent',\n fontSize: 13,\n }}\n >\n <div style={{ fontWeight: 500 }}>{n.name}</div>\n <div style={{ fontSize: 11, opacity: 0.7, display: 'flex', alignItems: 'center', gap: 4 }}>\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: '50%',\n background: n.status?.reachable === true ? 'var(--dsw-alias-state-success-primary)' : n.status?.reachable === false ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-dimmed)',\n }}\n />\n {n.type === 'local-host' ? '默认环境(本地)' : n.type === 'remote-ssh' ? '远程 SSH' : n.type === 'local-docker' ? '本地 Docker' : n.type === 'remote-docker' ? '远程 Docker' : n.type}\n <span style={{ marginLeft: 4, color: n.status?.reachable === true ? 'var(--dsw-alias-state-success-primary)' : n.status?.reachable === false ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-dimmed)' }}>\n {n.status?.reachable === true ? '在线' : n.status?.reachable === false ? '离线' : '未知'}\n </span>\n </div>\n {n.provision && (\n <div style={{ fontSize: 11, marginTop: 2, color: n.provision.state === 'ready' ? 'var(--dsw-alias-state-success-primary)' : n.provision.state === 'failed' ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-state-warn-label)' }}>\n {n.provision.state === 'provisioning' ? '容器拉起中…' : n.provision.state === 'ready' ? '容器已就绪' : `容器拉起失败:${n.provision.error ?? '未知错误'}`}\n </div>\n )}\n </div>\n ))}\n {nodes.length === 0 && <div style={{ fontSize: 12, opacity: 0.6 }}>暂无节点</div>}\n </div>\n\n <div style={{ flex: 1, maxWidth: 480, minWidth: 0, overflow: 'hidden' }}>\n {sshConfigEntries.length > 0 && (\n <div style={{ marginBottom: 14 }}>\n <label style={{ fontSize: 12, opacity: 0.75, display: 'block', marginBottom: 4 }}>从 ~/.ssh/config 导入</label>\n <select\n style={inputStyle}\n value=\"\"\n onChange={(e) => {\n const entry = sshConfigEntries[Number(e.target.value)]\n if (entry) importSshConfig(entry)\n e.target.value = ''\n }}\n >\n <option value=\"\">选择主机…</option>\n {sshConfigEntries.map((entry, i) => (\n <option key={entry.host} value={i}>\n {entry.host}:{entry.port}{entry.username ? ` (${entry.username})` : ''}{entry.hasProxyJump ? ' 跳板' : ''}\n </option>\n ))}\n </select>\n </div>\n )}\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 节点名称\n <input style={inputStyle} value={form.name} onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))} placeholder=\"例如:构建机\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 节点类型\n <select style={inputStyle} value={form.type} onChange={(e) => setForm((f) => ({ ...f, type: e.target.value as FormState['type'] }))}>\n <option value=\"remote-ssh\">远程 SSH 宿主机</option>\n <option value=\"remote-docker\">远程 Docker(SSH 通道)</option>\n <option value=\"local-host\">默认环境(本地)</option>\n <option value=\"local-docker\">本地 Docker 容器</option>\n </select>\n </label>\n\n {(form.type === 'remote-ssh' || form.type === 'remote-docker') && (\n <>\n <div className=\"dshb-form-row\" style={{ display: 'flex', gap: 10 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n 主机地址\n <input style={inputStyle} value={form.host} onChange={(e) => setForm((f) => ({ ...f, host: e.target.value }))} placeholder=\"192.168.1.10\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, width: 90 }}>\n 端口\n <input style={inputStyle} value={form.port} onChange={(e) => setForm((f) => ({ ...f, port: e.target.value }))} />\n </label>\n </div>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 用户名\n <input style={inputStyle} value={form.username} onChange={(e) => setForm((f) => ({ ...f, username: e.target.value }))} placeholder=\"root\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 认证方式\n <select style={inputStyle} value={form.authKind} onChange={(e) => setForm((f) => ({ ...f, authKind: e.target.value as FormState['authKind'] }))}>\n <option value=\"password\">密码</option>\n <option value=\"key\">私钥</option>\n <option value=\"agent\">ssh-agent</option>\n </select>\n </label>\n {form.authKind === 'password' && (\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 密码{selectedNode?.hasSecret.hasPassword ? '(已保存,留空保持不变)' : ''}\n <input style={inputStyle} type=\"password\" value={form.password} onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))} autoComplete=\"new-password\" />\n </label>\n )}\n {form.authKind === 'key' && (\n <>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 私钥内容{selectedNode?.hasSecret.hasKey ? '(已保存,留空保持不变)' : ''}\n <textarea style={{ ...inputStyle, minHeight: 90, resize: 'vertical' }} value={form.privateKey} onChange={(e) => setForm((f) => ({ ...f, privateKey: e.target.value }))} placeholder=\"-----BEGIN OPENSSH PRIVATE KEY-----\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 私钥 passphrase(可选)\n <input style={inputStyle} type=\"password\" value={form.passphrase} onChange={(e) => setForm((f) => ({ ...f, passphrase: e.target.value }))} autoComplete=\"new-password\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 或私钥文件路径(可选,优先使用内容)\n <input style={inputStyle} value={form.keyPath} onChange={(e) => setForm((f) => ({ ...f, keyPath: e.target.value }))} placeholder=\"~/.ssh/id_ed25519\" />\n </label>\n </>\n )}\n </>\n )}\n\n {(form.type === 'local-docker' || form.type === 'remote-docker') && (\n <>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13 }}>\n 镜像地址\n <input style={inputStyle} value={form.dockerImage} onChange={(e) => setForm((f) => ({ ...f, dockerImage: e.target.value }))} placeholder=\"alpine:latest\" />\n </label>\n <div className=\"dshb-form-row\" style={{ display: 'flex', gap: 10 }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n CPU 核数(可选)\n <input style={inputStyle} value={form.dockerCpus} onChange={(e) => setForm((f) => ({ ...f, dockerCpus: e.target.value }))} placeholder=\"2\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 13, flex: 1, minWidth: 0 }}>\n 内存 MB(可选)\n <input style={inputStyle} value={form.dockerMemory} onChange={(e) => setForm((f) => ({ ...f, dockerMemory: e.target.value }))} placeholder=\"512\" />\n </label>\n </div>\n </>\n )}\n\n {testResult !== undefined && (\n <div style={{ fontSize: 13, color: testResult === '连接成功' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{testResult}</div>\n )}\n\n <div style={{ display: 'flex', gap: 10, marginTop: 6, flexWrap: 'wrap' }}>\n <button type=\"button\" onClick={() => void save()} disabled={busy} style={primaryButtonStyle}>\n {selectedId === 'new' ? '创建节点' : '保存'}\n </button>\n {(form.type === 'remote-ssh' || form.type === 'remote-docker' || (selectedId !== 'new' && form.type === 'local-docker')) && (\n <button type=\"button\" onClick={() => void test()} disabled={busy || testing} style={secondaryButtonStyle}>\n {testing ? '测试中…' : '测试连接'}\n </button>\n )}\n {selectedId !== 'new' && (form.type === 'local-docker' || form.type === 'remote-docker') && (\n <>\n <button type=\"button\" onClick={() => void dockerAction('provision')} disabled={busy || dockerBusy} style={primaryButtonStyle}>\n {dockerBusy ? '操作中…' : '拉起容器'}\n </button>\n <button type=\"button\" onClick={() => void dockerAction('restart')} disabled={busy || dockerBusy} style={secondaryButtonStyle}>\n {dockerBusy ? '操作中…' : '重启容器'}\n </button>\n <button type=\"button\" onClick={() => void dockerAction('stop')} disabled={busy || dockerBusy} style={secondaryButtonStyle}>\n {dockerBusy ? '操作中…' : '停止容器'}\n </button>\n </>\n )}\n {selectedId !== 'new' && (\n <button type=\"button\" onClick={() => void remove()} disabled={busy} style={dangerOutlineButtonStyle}>\n 删除\n </button>\n )}\n {notice && <span style={{ fontSize: 13, alignSelf: 'center', color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</span>}\n </div>\n </div>\n </div>\n </div>\n </>\n )\n}\n\nexport function apply(ctx: ClientContext): void {\n const globalStyle = document.createElement('style')\n globalStyle.textContent = `\n /* 仅在页面根阻止整页横向滚动。绝对定位浮层(模型菜单、上下文统计面板等)\n 依赖祖先 overflow:visible 才能展开到输入框之外,禁止给任何中间祖先加裁剪。 */\n html, body { overflow-x: hidden !important; max-width: 100vw !important }\n * { min-width: 0 !important; }\n table { display: block !important; overflow-x: auto !important; }\n img, video, canvas, svg { max-width: 100% !important; height: auto !important }\n pre, code { white-space: pre-wrap !important; word-break: break-all !important }\n input, select, textarea { max-width: 100% !important; }\n /* 上下文用量弹窗 .JObwrW_panel(ContextMeter):解除宽度塌缩并允许溢出显示。\n JObwrW_ 为上游 CSS 模块 hash,上游升级需同步。 */\n .JObwrW_panel { max-width: none !important; overflow: visible !important; }\n /* 子代理切换弹窗(dsh-client-ui-subagent):menu 是 flex column + max-height + overflow:auto,\n position:fixed 经 portal 渲染。子代理很多时 flex 压缩 node(flex-shrink:1 默认),\n 文字挤压且不触发滚动。给 node flex-shrink:0 让 menu 整体 overflow:auto 滚动。 */\n [class*=\"_menu\"] [class*=\"_node\"] { flex-shrink: 0 !important; }\n /* 模型选择弹窗(dsh-client-ui-model-selection):Ra_menu 上游 max-width 420px,\n 长模型名单行放不下被 ellipsis 截断。放宽到 720px 让模型名单行完整显示。\n [class*=\"Ra_menu\"] 精确匹配模型弹窗,避免误伤其他菜单。Ra_ 为 hash,上游升级需同步。 */\n [class*=\"Ra_menu\"] { max-width: 720px !important; width: auto !important; }\n /* 终端组件(dsh-web-frontend,CSS 模块前缀 1gdtu_)桌面端修复:上游 _command_ 默认\n overflow:hidden+text-overflow:ellipsis,LLM 调 bash 的长命令在桌面端被省略号\n 截断、看不到完整内容(输出区 _output_ 本就可横向滚动,唯命令区不行)。宽屏与\n mobile.tsx 的窄屏规则等效:行链 _prompt_/_promptLine_/_command_ 撑到 max-content、\n overflow 可见,长行溢出传入 _header_(本就 overflow-y:auto)的 scrollWidth,整个\n 命令区随 _header_ 横向滚动;copyButton 贴右缘保持可见。与窄屏规则共用 1gdtu_\n hash,上游升级需同步。桌面保留可见滚动条(不隐藏、不加 touch-action)。 */\n @media (min-width: 1024px) {\n [data-phase] [class*=\"_header_1gdtu_\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n overflow-x: auto !important;\n }\n [data-phase] [class*=\"_prompt_1gdtu_\"],\n [data-phase] [class*=\"_promptLine_1gdtu_\"],\n [data-phase] [class*=\"_command_1gdtu_\"] {\n min-width: max-content !important;\n max-width: none !important;\n overflow: visible !important;\n }\n [data-phase] [class*=\"_command_1gdtu_\"] {\n display: inline-block;\n text-overflow: clip !important;\n white-space: pre !important;\n }\n [data-phase] [class*=\"_copyButton_1gdtu_\"] { position: sticky !important; right: 0; top: 0; }\n }\n `\n document.head.appendChild(globalStyle)\n\n installMobile(ctx)\n\n registerWorkspaceInstructionMenu(ctx)\n\n ctx.plugin({\n inject: ['slots'],\n apply: (sub: ClientContext): void => {\n sub.slots.inject('settings.section', () =>\n sub.slots.register({ name: 'settings.section', id: SECTION_ID, order: 110, label: () => '工作节点' }, NodeSection),\n )\n /* 上游 dsh-client-ui-directory-picker-browse 以默认 priority 0 注册同一 slot;\n priority 升序遮蔽(lowest renders),用 -10 抢占渲染,避免同优先级抛错。 */\n sub.slots.inject('conversation.hero.workspace.directoryFlow', () =>\n sub.slots.register({ name: 'conversation.hero.workspace.directoryFlow', priority: -10 }, DirectoryFlowOccupant),\n )\n sub.slots.inject('sidebar.workspaces.directoryFlow', () =>\n sub.slots.register({ name: 'sidebar.workspaces.directoryFlow', priority: -10 }, DirectoryFlowOccupant),\n )\n },\n })\n\n const workspaces = (ctx as unknown as { workspaces?: { openPath(p: string): Promise<void> } }).workspaces\n if (workspaces && typeof workspaces.openPath === 'function') {\n const originalOpenPath = workspaces.openPath.bind(workspaces)\n workspaces.openPath = async (path: string): Promise<void> => {\n try {\n const res = await fetch(`/api/dshb/remote/bound?path=${encodeURIComponent(path)}`)\n if (res.ok) {\n const data = (await res.json()) as { bound?: boolean; kind?: 'file' | 'dir'; error?: string }\n if (data.bound) {\n if (data.kind !== 'file') return originalOpenPath(path)\n const a = document.createElement('a')\n a.href = `/api/dshb/remote/file?path=${encodeURIComponent(path)}`\n a.download = ''\n document.body.appendChild(a)\n a.click()\n a.remove()\n return\n }\n }\n } catch {\n // 探测失败则回退宿主原生打开\n }\n return originalOpenPath(path)\n }\n }\n\n const ICON_SVG: Record<string, string> = {\n auth: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 7C9.3807 7 10.5 5.8807 10.5 4.5C10.5 3.1193 9.3807 2 8 2C6.6193 2 5.5 3.1193 5.5 4.5C5.5 5.8807 6.6193 7 8 7Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3 14C3 11.2386 5.2386 9 8 9C10.7614 9 13 11.2386 13 14\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n 'dshb-nodes': `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"3.5\" cy=\"4\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"12.5\" cy=\"4\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"8\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M3.5 6V8C3.5 9.1 4.4 10 5.5 10H8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/><path d=\"M12.5 6V8C12.5 9.1 11.6 10 10.5 10H8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>`,\n }\n const ICON_LABELS: Record<string, string> = { '认证': 'auth', '工作节点': 'dshb-nodes' }\n\n const observer = new MutationObserver(() => {\n const cells = document.querySelectorAll('button[class*=\"navCell\"]')\n for (const cell of Array.from(cells)) {\n const label = cell.querySelector('span[class*=\"navLabel\"]')\n if (!label) continue\n const text = label.textContent ?? ''\n const iconKey = ICON_LABELS[text]\n if (!iconKey) continue\n const iconSlot = cell.querySelector('[class*=\"navIcon\"]')\n if (!iconSlot) continue\n if (iconSlot.getAttribute('data-dshb-icon') === iconKey) continue\n iconSlot.innerHTML = ICON_SVG[iconKey] ?? ''\n iconSlot.setAttribute('data-dshb-icon', iconKey)\n }\n })\n observer.observe(document.body, { childList: true, subtree: true })\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport { apply as applyAuth } from './auth.js'\nimport { apply as applyUi } from './ui.js'\n\nexport const inject = ['connection', 'workspaces', 'slots', 'layout', 'conversation']\n\nexport function apply(ctx: ClientContext): void {\n applyAuth(ctx)\n applyUi(ctx)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artenx/dshb",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Routes DSH filesystem, shell, subprocess, and PTY operations to local, SSH, and Docker execution nodes, with a node registry, an authentication gate, a mobile-aware management UI, and per-workspace custom project instructions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|