@artenx/dshb 0.1.18 → 0.1.20
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/auth/decorate-webserver.d.ts +2 -1
- package/lib/auth/decorate-webserver.js +21 -10
- package/lib/auth/decorate-webserver.js.map +1 -1
- package/lib/auth/gate.d.ts +3 -1
- package/lib/auth/gate.js +18 -1
- package/lib/auth/gate.js.map +1 -1
- package/lib/auth/index.js +11 -3
- package/lib/auth/index.js.map +1 -1
- package/lib/auth/webserver.d.ts +3 -1
- package/lib/auth/webserver.js +10 -1
- package/lib/auth/webserver.js.map +1 -1
- package/lib/client.js +2157 -567
- package/lib/client.js.map +1 -1
- package/lib/core/index.js +72 -4
- package/lib/core/index.js.map +1 -1
- package/lib/core/node-registry.d.ts +2 -108
- package/lib/core/node-registry.js +43 -2
- package/lib/core/node-registry.js.map +1 -1
- package/lib/core/routes.d.ts +4 -3
- package/lib/core/routes.js +67 -23
- package/lib/core/routes.js.map +1 -1
- package/lib/core/sync/coordinator.d.ts +48 -0
- package/lib/core/sync/coordinator.js +247 -0
- package/lib/core/sync/coordinator.js.map +1 -0
- package/lib/core/sync/host-key.d.ts +2 -0
- package/lib/core/sync/host-key.js +71 -0
- package/lib/core/sync/host-key.js.map +1 -0
- package/lib/core/sync/internal-routes.d.ts +9 -0
- package/lib/core/sync/internal-routes.js +236 -0
- package/lib/core/sync/internal-routes.js.map +1 -0
- package/lib/core/sync/model.d.ts +2 -0
- package/lib/core/sync/model.js +106 -0
- package/lib/core/sync/model.js.map +1 -0
- package/lib/core/sync/node-sync.d.ts +2 -0
- package/lib/core/sync/node-sync.js +660 -0
- package/lib/core/sync/node-sync.js.map +1 -0
- package/lib/core/sync/offline-archive.d.ts +55 -0
- package/lib/core/sync/offline-archive.js +673 -0
- package/lib/core/sync/offline-archive.js.map +1 -0
- package/lib/core/sync/offline-journal.d.ts +22 -0
- package/lib/core/sync/offline-journal.js +74 -0
- package/lib/core/sync/offline-journal.js.map +1 -0
- package/lib/core/sync/offline-routes.d.ts +7 -0
- package/lib/core/sync/offline-routes.js +192 -0
- package/lib/core/sync/offline-routes.js.map +1 -0
- package/lib/core/sync/peer-manager.d.ts +56 -0
- package/lib/core/sync/peer-manager.js +258 -0
- package/lib/core/sync/peer-manager.js.map +1 -0
- package/lib/core/sync/protocol.d.ts +2 -0
- package/lib/core/sync/protocol.js +124 -0
- package/lib/core/sync/protocol.js.map +1 -0
- package/lib/core/sync/remote-helper.d.ts +5 -0
- package/lib/core/sync/remote-helper.js +160 -0
- package/lib/core/sync/remote-helper.js.map +1 -0
- package/lib/core/sync/revision.d.ts +2 -0
- package/lib/core/sync/revision.js +77 -0
- package/lib/core/sync/revision.js.map +1 -0
- package/lib/core/sync/routes.d.ts +9 -0
- package/lib/core/sync/routes.js +339 -0
- package/lib/core/sync/routes.js.map +1 -0
- package/lib/core/sync/scheduler.d.ts +14 -0
- package/lib/core/sync/scheduler.js +81 -0
- package/lib/core/sync/scheduler.js.map +1 -0
- package/lib/core/sync/session-journal.d.ts +2 -0
- package/lib/core/sync/session-journal.js +191 -0
- package/lib/core/sync/session-journal.js.map +1 -0
- package/lib/core/sync/session-routes.d.ts +7 -0
- package/lib/core/sync/session-routes.js +67 -0
- package/lib/core/sync/session-routes.js.map +1 -0
- package/lib/core/sync/session-sync.d.ts +2 -0
- package/lib/core/sync/session-sync.js +2 -0
- package/lib/core/sync/ssh-transport.d.ts +2 -0
- package/lib/core/sync/ssh-transport.js +408 -0
- package/lib/core/sync/ssh-transport.js.map +1 -0
- package/lib/core/sync/stores.d.ts +3 -0
- package/lib/core/sync/stores.js +385 -0
- package/lib/core/sync/stores.js.map +1 -0
- package/lib/core/test.d.ts +1 -1
- package/lib/core/workspace-bindings.d.ts +2 -28
- package/lib/core/workspace-bindings.js +14 -14
- package/lib/core/workspace-bindings.js.map +1 -1
- package/lib/core/workspace-instruction-context.d.ts +3 -2260
- package/lib/core/workspace-instruction-context.js +104 -2
- package/lib/core/workspace-instruction-context.js.map +1 -0
- package/lib/core/workspace-instruction-routes.d.ts +1 -1
- package/lib/core/workspace-instructions.d.ts +2 -68
- package/lib/core/workspace-instructions.js +13 -0
- package/lib/core/workspace-instructions.js.map +1 -1
- package/lib/core/workspaces.d.ts +4 -3
- package/lib/core/workspaces.js +17 -1
- package/lib/core/workspaces.js.map +1 -1
- package/lib/host-key-C5afhAUd.d.ts +30 -0
- package/lib/index-VF8bcBeX.d.ts +2293 -0
- package/lib/{workspace-instruction-context-DytAmaPY.js → lib-gdtU_WKT.js} +159 -102
- package/lib/lib-gdtU_WKT.js.map +1 -0
- package/lib/model-BP7Gw1yk.d.ts +104 -0
- package/lib/node-registry-BTnnM5-k.d.ts +112 -0
- package/lib/node-sync-3Z9QLz2n.d.ts +89 -0
- package/lib/protocol-CV7LGE44.d.ts +35 -0
- package/lib/revision-C9sOlDZ6.d.ts +25 -0
- package/lib/router/router-fs.d.ts +12 -3
- package/lib/router/router-fs.js.map +1 -1
- package/lib/session-journal-pgPqcWn9.d.ts +40 -0
- package/lib/session-sync-EdfwUON5.js +2177 -0
- package/lib/session-sync-EdfwUON5.js.map +1 -0
- package/lib/session-sync-g6qKZzjV.d.ts +1252 -0
- package/lib/ssh-transport-BcIiLxsX.d.ts +55 -0
- package/lib/stores-CKyEt0yk.d.ts +31 -0
- package/lib/workspace-bindings-CsB0TIJB.d.ts +28 -0
- package/lib/workspace-instructions-DirYYiku.d.ts +69 -0
- package/package.json +20 -1
- package/lib/workspace-instruction-context-DytAmaPY.js.map +0 -1
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'],\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, workspaceTitle: string): 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 = resolveWorkspaceByTitle(workspaceTitle)\n mountInstructionDialog(ws?.workspaceId ?? '', workspaceTitle)\n })\n\n refItem.parentElement?.insertBefore(btn, refItem.nextSibling)\n }\n\n const scan = (): void => {\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('操作') || label.toLowerCase().includes('actions')) {\n btn.addEventListener('click', () => {\n const isMenuOpen = rowEl.className.includes('menuOpen')\n activeWorkspaceTitle = isMenuOpen ? '' : (getRowTitle(rowEl) ?? '')\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 // Newer DSH renders workspace menus in a portal under document.body.\n const title = row ? getRowTitle(row) : activeWorkspaceTitle\n if (!title) continue\n injectMenuItem(container, title)\n activeWorkspaceTitle = ''\n }\n }\n }\n }\n\n const observer = new MutationObserver(scan)\n observer.observe(document.body, { childList: true, subtree: true })\n scan()\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 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","inputStyle","useState","buttonStyle","useState","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/sync-peer-form.ts","../src/client/sync-peers.tsx","../src/client/sync-offline.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 sync?: { importedVia?: 'peer' | 'offline'; sourceName?: string; pendingRemoval?: 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 const selectableNodes = nodes.filter((item) => !item.sync?.pendingRemoval)\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 {selectableNodes.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.sync?.importedVia === 'peer' && n.sync.sourceName ? ` · 同步自 ${n.sync.sourceName}` : ''})\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, workspaceTitle: string): 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 = resolveWorkspaceByTitle(workspaceTitle)\n mountInstructionDialog(ws?.workspaceId ?? '', workspaceTitle)\n })\n\n refItem.parentElement?.insertBefore(btn, refItem.nextSibling)\n }\n\n const scan = (): void => {\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('操作') || label.toLowerCase().includes('actions')) {\n btn.addEventListener('click', () => {\n const isMenuOpen = rowEl.className.includes('menuOpen')\n activeWorkspaceTitle = isMenuOpen ? '' : (getRowTitle(rowEl) ?? '')\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 // Newer DSH renders workspace menus in a portal under document.body.\n const title = row ? getRowTitle(row) : activeWorkspaceTitle\n if (!title) continue\n injectMenuItem(container, title)\n activeWorkspaceTitle = ''\n }\n }\n }\n }\n\n const observer = new MutationObserver(scan)\n observer.observe(document.body, { childList: true, subtree: true })\n scan()\n}\n","export interface SyncPeerSecretFlags {\n hasPassword: boolean\n hasKey: boolean\n hasPassphrase: boolean\n}\n\nexport interface SyncPeerForm {\n name: string\n host: string\n port: string\n username: string\n authKind: 'password' | 'key'\n password: string\n privateKey: string\n passphrase: string\n remoteDshHome: string\n remoteProfile: string\n remoteWebPort: string\n direction: 'pull' | 'bidirectional'\n schedule: 'manual' | 'every-5m'\n syncSessions: boolean\n enabled: boolean\n}\n\nexport interface SyncPeerFormView extends Omit<SyncPeerForm, 'password' | 'privateKey' | 'passphrase' | 'port' | 'remoteWebPort' | 'remoteDshHome' | 'remoteProfile'> {\n port: number\n remoteDshHome?: string\n remoteProfile?: string\n remoteWebPort?: number\n hasSecret: SyncPeerSecretFlags\n}\n\nexport const EMPTY_SYNC_PEER_FORM: SyncPeerForm = {\n name: '',\n host: '',\n port: '22',\n username: '',\n authKind: 'password',\n password: '',\n privateKey: '',\n passphrase: '',\n remoteDshHome: '',\n remoteProfile: '',\n remoteWebPort: '',\n direction: 'pull',\n schedule: 'manual',\n syncSessions: false,\n enabled: true,\n}\n\nexport interface SyncPeerFormRequest {\n fields: Record<string, unknown>\n secrets: Record<string, string>\n}\n\nfunction validPort(value: string): boolean {\n const port = Number(value)\n return Number.isInteger(port) && port >= 1 && port <= 65535\n}\n\nexport function syncPeerFormError(form: SyncPeerForm, savedSecrets?: SyncPeerSecretFlags): string | undefined {\n if (!form.name.trim() || !form.host.trim() || !form.username.trim()) return '请填写名称、SSH 主机和系统账号'\n if (!validPort(form.port)) return 'SSH 端口必须在 1 到 65535 之间'\n if (form.remoteWebPort.trim() && !validPort(form.remoteWebPort)) return '远端 Web 端口必须在 1 到 65535 之间'\n if (form.authKind === 'password' && !form.password && !savedSecrets?.hasPassword) return '请填写 SSH 密码'\n if (form.authKind === 'key' && !form.privateKey && !savedSecrets?.hasKey) return '请填写 SSH 私钥内容'\n return undefined\n}\n\nexport function toSyncPeerForm(peer: SyncPeerFormView): SyncPeerForm {\n return {\n name: peer.name,\n host: peer.host,\n port: String(peer.port),\n username: peer.username,\n authKind: peer.authKind,\n password: '',\n privateKey: '',\n passphrase: '',\n remoteDshHome: peer.remoteDshHome ?? '',\n remoteProfile: peer.remoteProfile ?? '',\n remoteWebPort: peer.remoteWebPort == null ? '' : String(peer.remoteWebPort),\n direction: peer.direction,\n schedule: peer.schedule,\n syncSessions: peer.syncSessions,\n enabled: peer.enabled,\n }\n}\n\nexport function buildSyncPeerFormRequest(form: SyncPeerForm): SyncPeerFormRequest {\n const fields: Record<string, unknown> = {\n name: form.name.trim(),\n host: form.host.trim(),\n port: Number(form.port),\n username: form.username.trim(),\n authKind: form.authKind,\n direction: form.direction,\n schedule: form.schedule,\n syncSessions: form.syncSessions,\n enabled: form.enabled,\n ...(form.remoteDshHome.trim() ? { remoteDshHome: form.remoteDshHome.trim() } : {}),\n ...(form.remoteProfile.trim() ? { remoteProfile: form.remoteProfile.trim() } : {}),\n ...(form.remoteWebPort.trim() ? { remoteWebPort: Number(form.remoteWebPort) } : {}),\n }\n const secrets: Record<string, string> = {}\n if (form.authKind === 'password') {\n if (form.password) secrets.password = form.password\n } else {\n if (form.privateKey) secrets.privateKey = form.privateKey\n if (form.passphrase) secrets.passphrase = form.passphrase\n }\n return { fields, secrets }\n}\n","import type { CSSProperties, ReactElement } from 'react'\nimport { useEffect, useState } from 'react'\nimport {\n buildSyncPeerFormRequest,\n EMPTY_SYNC_PEER_FORM,\n syncPeerFormError,\n toSyncPeerForm,\n type SyncPeerForm,\n type SyncPeerFormView,\n} from './sync-peer-form.js'\n\ninterface SyncPeerView extends SyncPeerFormView {\n id: string\n hostKeyFingerprint?: string\n progress?: {\n lastRunAt?: string\n lastSuccessAt?: string\n lastRunStatus?: 'running' | 'succeeded' | 'failed'\n lastErrorMessage?: string\n lastResult?: {\n imported: number\n exported: number\n skipped: number\n pendingRemoval: number\n importedSessions: number\n exportedSessions: number\n skippedSessions: number\n }\n }\n}\n\ninterface SyncSessionArchiveView {\n branchId: string\n originInstanceId: string\n originSessionId: string\n localSessionId: string\n archivedAt: string\n}\n\nfunction shortenSessionId(id: string): string {\n const suffix = id.replace(/^session-sync-/, '')\n return `${suffix.slice(0, 8)}…${suffix.slice(-4)}`\n}\n\nfunction copyText(value: string): void {\n void navigator.clipboard?.writeText(value)\n}\n\nfunction resultSummary(peer: SyncPeerView): string | undefined {\n const result = peer.progress?.lastResult\n if (!result) return undefined\n return `节点导入 ${result.imported}、导出 ${result.exported};会话导入 ${result.importedSessions}、导出 ${result.exportedSessions};跳过 ${result.skipped}`\n}\n\ninterface HostKeyChallenge {\n code: 'host-key-untrusted' | 'host-key-changed'\n fingerprint: string\n expected?: string\n}\n\ntype Notice = { kind: 'ok' | 'error'; text: string } | undefined\n\nasync function readJsonResponse<T>(response: Response, fallback: string): Promise<T> {\n try {\n return await response.json() as T\n } catch {\n const message = response.status === 404\n ? '同步 API 尚未加载,请重启 DSH 服务后重试'\n : `${fallback}:服务器返回了无效响应(HTTP ${response.status})`\n throw new Error(message)\n }\n}\n\nconst inputStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n padding: '0 10px',\n minHeight: 34,\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}\n\nconst btn: CSSProperties = {\n boxSizing: 'border-box',\n height: 32,\n padding: '0 12px',\n borderRadius: 8,\n fontSize: 13,\n fontFamily: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n whiteSpace: 'nowrap',\n flexShrink: 0,\n}\n\nconst primaryBtn: CSSProperties = {\n ...btn,\n border: 'none',\n background: 'var(--dsw-alias-button-primary-fill)',\n color: 'var(--dsw-alias-label-primary-foreground)',\n}\n\nconst secondaryBtn: CSSProperties = {\n ...btn,\n border: '1px solid var(--dsw-alias-border-l2)',\n background: 'transparent',\n color: 'var(--dsw-alias-label-primary)',\n}\n\nconst dangerBtn: CSSProperties = {\n ...btn,\n border: '1px solid var(--dsw-alias-state-error-primary, #f87171)',\n background: 'transparent',\n color: 'var(--dsw-alias-state-error-primary, #f87171)',\n}\n\nconst label: CSSProperties = {\n fontSize: 12,\n fontWeight: 500,\n opacity: 0.75,\n color: 'var(--dsw-alias-label-primary)',\n marginBottom: 4,\n display: 'block',\n}\n\nconst field: CSSProperties = {\n marginBottom: 14,\n}\n\nconst hint: CSSProperties = {\n fontSize: 11,\n opacity: 0.5,\n color: 'var(--dsw-alias-label-primary)',\n marginTop: 3,\n}\n\nconst groupTitle: CSSProperties = {\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n opacity: 0.45,\n marginBottom: 12,\n paddingBottom: 6,\n borderBottom: '1px solid var(--dsw-alias-border-l2)',\n}\n\nconst required: CSSProperties = {\n color: 'var(--dsw-alias-state-error-primary, #f87171)',\n}\n\nexport function SyncPeersSection(): ReactElement {\n const [reloadKey, setReloadKey] = useState(0)\n const [peers, setPeers] = useState<SyncPeerView[]>([])\n const [archives, setArchives] = useState<SyncSessionArchiveView[]>([])\n const [selectedId, setSelectedId] = useState<string | 'new'>('new')\n const [form, setForm] = useState<SyncPeerForm>(EMPTY_SYNC_PEER_FORM)\n const [busy, setBusy] = useState(false)\n const [probing, setProbing] = useState(false)\n const [syncing, setSyncing] = useState(false)\n const [notice, setNotice] = useState<Notice>(undefined)\n const [hostKeyChallenge, setHostKeyChallenge] = useState<HostKeyChallenge | undefined>(undefined)\n\n useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const response = await fetch('/api/dshb/sync/peers')\n const data = await readJsonResponse<{ peers?: SyncPeerView[]; error?: string }>(response, '读取同步节点失败')\n if (!response.ok) throw new Error(data.error ?? '读取同步节点失败')\n if (!cancelled) setPeers(data.peers ?? [])\n const archiveResponse = await fetch('/api/dshb/sync/archives')\n const archiveData = await readJsonResponse<{ archives?: SyncSessionArchiveView[]; error?: string }>(archiveResponse, '读取会话归档失败')\n if (!archiveResponse.ok) throw new Error(archiveData.error ?? '读取会话归档失败')\n if (!cancelled) setArchives(archiveData.archives ?? [])\n } catch (error) {\n if (!cancelled) setNotice({ kind: 'error', text: error instanceof Error ? error.message : '读取同步节点失败' })\n }\n })()\n return () => { cancelled = true }\n }, [reloadKey])\n\n useEffect(() => {\n const interval = syncing || peers.some((peer) => peer.progress?.lastRunStatus === 'running') ? 3_000 : 15_000\n const timer = setInterval(() => setReloadKey((key) => key + 1), interval)\n return () => clearInterval(timer)\n }, [peers, syncing])\n\n const reload = (): void => setReloadKey((key) => key + 1)\n const selectedPeer = selectedId === 'new' ? undefined : peers.find((peer) => peer.id === selectedId)\n const runningCount = peers.filter((peer) => peer.progress?.lastRunStatus === 'running').length\n\n const statusLabel = (peer: SyncPeerView): string => {\n const status = peer.progress?.lastRunStatus\n if (!peer.enabled) return '已停用'\n if (status === 'running') return '同步中'\n if (status === 'failed') return '上次失败'\n if (status === 'succeeded') return '上次成功'\n return '尚未同步'\n }\n\n const select = (id: string | 'new'): void => {\n setSelectedId(id)\n setNotice(undefined)\n setHostKeyChallenge(undefined)\n const peer = id === 'new' ? undefined : peers.find((item) => item.id === id)\n setForm(peer ? toSyncPeerForm(peer) : EMPTY_SYNC_PEER_FORM)\n }\n\n const save = async (): Promise<void> => {\n const formError = syncPeerFormError(form, selectedPeer?.hasSecret)\n if (formError) {\n setNotice({ kind: 'error', text: formError })\n return\n }\n const request = buildSyncPeerFormRequest(form)\n const payload = { ...request.fields, secrets: request.secrets }\n setBusy(true)\n try {\n const response = await fetch(selectedId === 'new' ? '/api/dshb/sync/peers' : `/api/dshb/sync/peers/${selectedId}`, {\n method: selectedId === 'new' ? 'POST' : 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n const data = await readJsonResponse<{ ok?: boolean; peer?: SyncPeerView; error?: string }>(response, '保存同步节点失败')\n if (!response.ok || !data.ok || !data.peer) throw new Error(data.error ?? '保存同步节点失败')\n setNotice({ kind: 'ok', text: selectedId === 'new' ? '同步节点已创建' : '同步节点已保存' })\n setHostKeyChallenge(undefined)\n setSelectedId(data.peer.id)\n setForm(toSyncPeerForm(data.peer))\n reload()\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : '保存同步节点失败' })\n } finally {\n setBusy(false)\n }\n }\n\n const probe = async (): Promise<void> => {\n if (selectedId === 'new') return\n setProbing(true)\n setHostKeyChallenge(undefined)\n try {\n const response = await fetch(`/api/dshb/sync/peers/${selectedId}/probe`, { method: 'POST' })\n const data = await readJsonResponse<{\n ok?: boolean\n code?: string\n fingerprint?: string\n expected?: string\n handshake?: { instanceId?: string }\n error?: string\n }>(response, 'SSH 测试失败')\n if (data.code === 'host-key-untrusted' || data.code === 'host-key-changed') {\n setHostKeyChallenge({\n code: data.code,\n fingerprint: data.fingerprint ?? '',\n ...(data.expected ? { expected: data.expected } : {}),\n })\n return\n }\n if (!response.ok || !data.ok) throw new Error(data.error ?? 'SSH 测试失败')\n setNotice({ kind: 'ok', text: `SSH 和 DSHB 握手成功(${data.handshake?.instanceId ?? '远端实例'})` })\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : 'SSH 测试失败' })\n } finally {\n setProbing(false)\n }\n }\n\n const trustObservedHostKey = async (): Promise<void> => {\n if (selectedId === 'new' || !hostKeyChallenge) return\n const confirmation = hostKeyChallenge.code === 'host-key-changed'\n ? `远端 SSH 主机指纹已变化。\\n当前保存:${hostKeyChallenge.expected}\\n本次观察:${hostKeyChallenge.fingerprint}\\n确认信任新指纹?`\n : `首次连接观察到 SSH 主机指纹:\\n${hostKeyChallenge.fingerprint}\\n请核对后确认信任。`\n if (!window.confirm(confirmation)) return\n setProbing(true)\n try {\n const response = await fetch(`/api/dshb/sync/peers/${selectedId}/trust-host-key`, { method: 'POST' })\n const data = await readJsonResponse<{ ok?: boolean; error?: string; peer?: SyncPeerView }>(response, '保存 SSH 主机信任失败')\n if (!response.ok || !data.ok || !data.peer) throw new Error(data.error ?? '保存 SSH 主机信任失败')\n setHostKeyChallenge(undefined)\n setForm(toSyncPeerForm(data.peer))\n reload()\n setNotice({ kind: 'ok', text: '主机指纹已保存,正在重新验证连接' })\n await probe()\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : '保存 SSH 主机信任失败' })\n } finally {\n setProbing(false)\n }\n }\n\n const runSync = async (): Promise<void> => {\n if (selectedId === 'new' || !selectedPeer?.enabled) return\n setSyncing(true)\n try {\n const response = await fetch(`/api/dshb/sync/peers/${selectedId}/run`, { method: 'POST' })\n const data = await readJsonResponse<{\n ok?: boolean\n accepted?: boolean\n error?: string\n }>(response, '同步失败')\n if (!response.ok || !data.ok || !data.accepted) throw new Error(data.error ?? '同步失败')\n const startedAt = new Date().toISOString()\n setPeers((current) => current.map((peer) => peer.id === selectedId ? {\n ...peer,\n progress: { ...peer.progress, lastRunAt: startedAt, lastRunStatus: 'running' },\n } : peer))\n setNotice({ kind: 'ok', text: '同步作业已启动,状态会自动更新' })\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : '同步失败' })\n } finally {\n setSyncing(false)\n }\n }\n\n const restoreArchive = async (branchId: string): Promise<void> => {\n const archive = archives.find((entry) => entry.branchId === branchId)\n if (!archive || !window.confirm(`恢复会话 ${archive.originSessionId} 的归档版本?当前版本将保留在归档中。`)) return\n setBusy(true)\n try {\n const response = await fetch(`/api/dshb/sync/archives/${branchId}/restore`, { method: 'POST' })\n const data = await readJsonResponse<{ ok?: boolean; error?: string }>(response, '恢复会话归档失败')\n if (!response.ok || !data.ok) throw new Error(data.error ?? '恢复会话归档失败')\n setNotice({ kind: 'ok', text: '会话归档已恢复为当前版本' })\n reload()\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : '恢复会话归档失败' })\n } finally {\n setBusy(false)\n }\n }\n\n const progressLabel = (peer: SyncPeerView): string => {\n if (peer.progress?.lastRunStatus === 'running') return '同步中'\n if (peer.progress?.lastRunStatus === 'failed') return `上次失败:${peer.progress.lastErrorMessage ?? '同步失败'}`\n if (peer.progress?.lastSuccessAt) return `上次成功:${new Date(peer.progress.lastSuccessAt).toLocaleString()}`\n return '尚未同步'\n }\n\n const remove = async (): Promise<void> => {\n if (selectedId === 'new' || !window.confirm('删除此同步节点及其连接凭据?')) return\n setBusy(true)\n try {\n const response = await fetch(`/api/dshb/sync/peers/${selectedId}`, { method: 'DELETE' })\n const data = await readJsonResponse<{ ok?: boolean; error?: string }>(response, '删除同步节点失败')\n if (!response.ok || !data.ok) throw new Error(data.error ?? '删除同步节点失败')\n setNotice({ kind: 'ok', text: '同步节点已删除' })\n setSelectedId('new')\n setForm(EMPTY_SYNC_PEER_FORM)\n reload()\n } catch (error) {\n setNotice({ kind: 'error', text: error instanceof Error ? error.message : '删除同步节点失败' })\n } finally {\n setBusy(false)\n }\n }\n\n const isNew = selectedId === 'new'\n const syncInProgress = syncing || selectedPeer?.progress?.lastRunStatus === 'running'\n const selectedSummary = selectedPeer ? resultSummary(selectedPeer) : undefined\n\n return (\n <>\n <style>{`\n .dshb-sync-peer-tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:20px;padding-bottom:14px;border-bottom:1px solid var(--dsw-alias-border-l2)}\n .dshb-sync-peer-tab{padding:5px 12px;border-radius:16px;font-size:12px;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);white-space:nowrap;flex-shrink:0}\n .dshb-sync-peer-tab.active{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:transparent}\n .dshb-sync-peer-tab:hover:not(.active){background:var(--dsw-alias-interactive-bg-hover)}\n .dshb-sync-peer-add{width:28px;height:28px;padding:0;border-radius:50%;font-size:16px;line-height:1;opacity:.65}\n .dshb-sync-peer-add:hover{opacity:1}\n .dshb-sync-peer-status{font-size:11px;opacity:.6;margin-top:2px;display:block}\n .dshb-sync-peer-tab{max-width:220px;overflow:hidden;text-overflow:ellipsis}\n .dshb-sync-peer-tab.running{border-color:var(--dsw-alias-button-primary-fill)}\n .dshb-sync-peer-tab.failed{border-color:var(--dsw-alias-state-error-primary, #f87171)}\n .dshb-sync-peer-add{width:28px;height:28px;padding:0;border-radius:50%;font-size:16px;line-height:1;opacity:.65}\n .dshb-sync-peer-add:hover{opacity:1}\n .dshb-sync-peer-status{font-size:11px;opacity:.6;margin-top:2px;display:block}\n .dshb-sync-two-col{display:grid;grid-template-columns:1fr 1fr;gap:0 16px}\n @media(max-width:600px){.dshb-sync-two-col{grid-template-columns:1fr}}\n\n `}</style>\n\n {/* 节点切换标签页 */}\n <div className=\"dshb-sync-peer-tabs\">\n <button\n type=\"button\"\n className=\"dshb-sync-peer-tab dshb-sync-peer-add\"\n aria-label=\"新增同步节点\"\n title=\"新增同步节点\"\n onClick={() => select('new')}\n >\n +\n </button>\n {peers.map((peer) => (\n <button\n key={peer.id}\n type=\"button\"\n className={`dshb-sync-peer-tab${selectedId === peer.id ? ' active' : ''}${peer.progress?.lastRunStatus === 'running' ? ' running' : ''}${peer.progress?.lastRunStatus === 'failed' ? ' failed' : ''}`}\n onClick={() => select(peer.id)}\n title={`${peer.name} · ${statusLabel(peer)}`}\n aria-label={`同步节点 ${peer.name},${statusLabel(peer)}`}\n >\n {peer.name}\n <span className=\"dshb-sync-peer-status\">{statusLabel(peer)}</span>\n </button>\n ))}\n {runningCount > 0 && <span style={{ fontSize: 11, alignSelf: 'center', opacity: 0.65 }}>{runningCount} 个同步作业进行中</span>}\n {peers.length === 0 && (\n <span style={{ fontSize: 12, opacity: 0.5, alignSelf: 'center' }}>点击“+”添加第一个同步节点</span>\n )}\n </div>\n\n {/* 表单 */}\n {selectedPeer && (\n <div role=\"status\" style={{\n maxWidth: 560, marginBottom: 16, padding: '12px 14px',\n border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 10,\n background: 'var(--dsw-alias-bg-layer-1)', fontSize: 12,\n }}>\n <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'baseline' }}>\n <strong>{progressLabel(selectedPeer)}</strong>\n <button type=\"button\" onClick={reload} style={{ ...secondaryBtn, height: 26, fontSize: 11 }}>刷新</button>\n </div>\n {selectedSummary && <div style={{ marginTop: 6, opacity: 0.72, lineHeight: 1.55 }}>{selectedSummary}</div>}\n {selectedPeer.progress?.lastErrorMessage && <div style={{ marginTop: 6, color: 'var(--dsw-alias-state-error-primary, #f87171)', lineHeight: 1.55 }}>{selectedPeer.progress.lastErrorMessage}</div>}\n {syncInProgress && <div style={{ marginTop: 6, opacity: 0.6 }}>大工作区或大量会话可能需要数分钟,页面每 3 秒更新进度。</div>}\n </div>\n )}\n <div style={{ maxWidth: 560 }}>\n\n {/* 连接信息 */}\n <div style={groupTitle}>连接信息</div>\n\n <div style={field}>\n <span style={label}>节点名称 <span style={required}>*</span></span>\n <input style={inputStyle} value={form.name} placeholder=\"例如:生产服务器\"\n onChange={(e) => setForm((c) => ({ ...c, name: e.target.value }))} />\n </div>\n\n <div className=\"dshb-sync-two-col\">\n <div style={field}>\n <span style={label}>SSH 主机 <span style={required}>*</span></span>\n <input style={inputStyle} value={form.host} placeholder=\"sync.example.com\"\n onChange={(e) => setForm((c) => ({ ...c, host: e.target.value }))} />\n </div>\n <div style={field}>\n <span style={label}>SSH 端口 <span style={required}>*</span></span>\n <input style={inputStyle} inputMode=\"numeric\" value={form.port} placeholder=\"22\"\n onChange={(e) => setForm((c) => ({ ...c, port: e.target.value }))} />\n </div>\n </div>\n\n <div style={field}>\n <span style={label}>SSH 系统账号 <span style={required}>*</span></span>\n <input style={inputStyle} value={form.username} placeholder=\"root\"\n onChange={(e) => setForm((c) => ({ ...c, username: e.target.value }))} />\n </div>\n\n {/* 认证方式 */}\n <div style={{ ...groupTitle, marginTop: 20 }}>认证方式</div>\n\n <div style={field}>\n <span style={label}>认证类型</span>\n <select style={inputStyle} value={form.authKind}\n onChange={(e) => setForm((c) => ({ ...c, authKind: e.target.value as SyncPeerForm['authKind'] }))}>\n <option value=\"password\">密码</option>\n <option value=\"key\">私钥</option>\n </select>\n </div>\n\n {form.authKind === 'password' ? (\n <div style={field}>\n <span style={label}>\n SSH 密码\n {selectedPeer?.hasSecret.hasPassword && <span style={{ fontWeight: 400, opacity: 0.55 }}>(已保存,留空保持不变)</span>}\n </span>\n <input style={inputStyle} type=\"password\" autoComplete=\"new-password\" value={form.password}\n placeholder={selectedPeer?.hasSecret.hasPassword ? '••••••••' : ''}\n onChange={(e) => setForm((c) => ({ ...c, password: e.target.value }))} />\n </div>\n ) : (\n <>\n <div style={field}>\n <span style={label}>\n 私钥内容\n {selectedPeer?.hasSecret.hasKey && <span style={{ fontWeight: 400, opacity: 0.55 }}>(已保存,留空保持不变)</span>}\n </span>\n <textarea\n style={{ ...inputStyle, minHeight: 100, padding: '10px', resize: 'vertical', fontFamily: 'monospace', fontSize: 12 }}\n value={form.privateKey}\n placeholder=\"-----BEGIN OPENSSH PRIVATE KEY-----\"\n onChange={(e) => setForm((c) => ({ ...c, privateKey: e.target.value }))}\n />\n </div>\n <div style={field}>\n <span style={label}>\n 私钥 passphrase\n <span style={{ fontWeight: 400, opacity: 0.55 }}>\n {selectedPeer?.hasSecret.hasPassphrase ? '(已保存,留空保持不变)' : '(可选)'}\n </span>\n </span>\n <input style={inputStyle} type=\"password\" autoComplete=\"new-password\" value={form.passphrase}\n onChange={(e) => setForm((c) => ({ ...c, passphrase: e.target.value }))} />\n </div>\n </>\n )}\n\n {/* 远端配置 */}\n <div style={{ ...groupTitle, marginTop: 20 }}>远端配置</div>\n\n <div style={field}>\n <span style={label}>远端 DSH_HOME</span>\n <input style={inputStyle} value={form.remoteDshHome} placeholder=\"默认使用 SSH 账号的 ~/.dsh\"\n onChange={(e) => setForm((c) => ({ ...c, remoteDshHome: e.target.value }))} />\n <div style={hint}>远端 DSH 数据目录,留空使用默认路径</div>\n </div>\n\n <div className=\"dshb-sync-two-col\">\n <div style={field}>\n <span style={label}>远端 profile</span>\n <input style={inputStyle} value={form.remoteProfile} placeholder=\"web\"\n onChange={(e) => setForm((c) => ({ ...c, remoteProfile: e.target.value }))} />\n </div>\n <div style={field}>\n <span style={label}>远端 Web 端口</span>\n <input style={inputStyle} inputMode=\"numeric\" value={form.remoteWebPort} placeholder=\"3080\"\n onChange={(e) => setForm((c) => ({ ...c, remoteWebPort: e.target.value }))} />\n <div style={hint}>留空使用默认 3080</div>\n </div>\n </div>\n\n {/* 同步策略 */}\n <div style={{ ...groupTitle, marginTop: 20 }}>同步策略</div>\n\n <div className=\"dshb-sync-two-col\">\n <div style={field}>\n <span style={label}>同步方向</span>\n <select style={inputStyle} value={form.direction}\n onChange={(e) => setForm((c) => ({ ...c, direction: e.target.value as SyncPeerForm['direction'] }))}>\n <option value=\"pull\">单向拉取到本机</option>\n <option value=\"bidirectional\">双向同步</option>\n </select>\n </div>\n <div style={field}>\n <span style={label}>同步时机</span>\n <select style={inputStyle} value={form.schedule}\n onChange={(e) => setForm((c) => ({ ...c, schedule: e.target.value as SyncPeerForm['schedule'] }))}>\n <option value=\"manual\">手动</option>\n <option value=\"every-5m\">每 5 分钟</option>\n </select>\n </div>\n </div>\n\n <div style={{ ...field, display: 'flex', flexDirection: 'column', gap: 10 }}>\n <label style={{ display: 'flex', alignItems: 'flex-start', gap: 8, cursor: 'pointer' }}>\n <input type=\"checkbox\" checked={form.syncSessions} style={{ marginTop: 2 }}\n onChange={(e) => setForm((c) => ({ ...c, syncSessions: e.target.checked }))} />\n <span>\n <span style={{ fontSize: 13 }}>同步工作区会话</span>\n <span style={{ display: 'block', fontSize: 11, opacity: 0.5, marginTop: 2 }}>\n 覆盖已绑定 SSH 或 Docker 远程节点的工作区,保留冲突分支供恢复\n </span>\n </span>\n </label>\n <label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>\n <input type=\"checkbox\" checked={form.enabled}\n onChange={(e) => setForm((c) => ({ ...c, enabled: e.target.checked }))} />\n <span style={{ fontSize: 13 }}>启用此同步节点</span>\n </label>\n </div>\n\n {/* 主机指纹 */}\n {selectedPeer?.hostKeyFingerprint && (\n <div style={field}>\n <span style={label}>已信任 SSH 主机指纹</span>\n <code style={{ fontSize: 11, opacity: 0.6, overflowWrap: 'anywhere', fontFamily: 'monospace' }}>\n {selectedPeer.hostKeyFingerprint}\n </code>\n </div>\n )}\n\n {/* 指纹确认 */}\n {hostKeyChallenge && (\n <div style={{\n ...field,\n padding: '12px 14px',\n border: '1px solid var(--dsw-alias-state-warn-label, #f59e0b)',\n borderRadius: 10,\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n fontSize: 12,\n }}>\n <strong>{hostKeyChallenge.code === 'host-key-changed' ? '主机指纹发生变化' : '首次连接需要确认主机身份'}</strong>\n {hostKeyChallenge.expected && (\n <div style={{ overflowWrap: 'anywhere' }}>已保存:<code>{hostKeyChallenge.expected}</code></div>\n )}\n <div style={{ overflowWrap: 'anywhere' }}>本次观察:<code>{hostKeyChallenge.fingerprint}</code></div>\n <button type=\"button\" onClick={() => void trustObservedHostKey()} disabled={busy || probing}\n style={{ ...secondaryBtn, alignSelf: 'flex-start', marginTop: 4 }}>\n 信任本次观察的指纹\n </button>\n </div>\n )}\n\n {/* 通知 */}\n {notice && (\n <div style={{\n ...field,\n padding: '10px 14px',\n borderRadius: 8,\n fontSize: 13,\n background: notice.kind === 'ok'\n ? 'var(--dsw-alias-state-success-bg, rgba(34,197,94,.1))'\n : 'var(--dsw-alias-state-error-bg, rgba(248,113,113,.1))',\n color: notice.kind === 'ok'\n ? 'var(--dsw-alias-state-success-primary, #22c55e)'\n : 'var(--dsw-alias-state-error-primary, #f87171)',\n }}>\n {notice.text}\n </div>\n )}\n\n {/* 操作按钮 */}\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 4, marginBottom: 16 }}>\n <button type=\"button\" onClick={() => void save()} disabled={busy} style={primaryBtn}>\n {busy ? '保存中…' : isNew ? '创建同步节点' : '保存同步节点'}\n </button>\n {!isNew && (\n <button type=\"button\" onClick={() => void probe()} disabled={busy || probing} style={secondaryBtn}>\n {probing ? '测试中…' : '测试 SSH 握手'}\n </button>\n )}\n {!isNew && (\n <button type=\"button\" onClick={() => void runSync()} disabled={busy || probing || syncInProgress || !selectedPeer?.enabled} style={secondaryBtn}>\n {syncInProgress ? '同步中…' : '立即同步'}\n </button>\n )}\n {!isNew && (\n <button type=\"button\" onClick={() => void remove()} disabled={busy} style={dangerBtn}>\n 删除\n </button>\n )}\n </div>\n\n <div style={{ fontSize: 12, opacity: 0.45, marginBottom: 24 }}>\n 节点与会话数据通过 SSH 执行通道传输;会话附件与 spill 对象随 session bundle 一并校验。\n </div>\n\n </div>\n\n {/* 会话冲突归档 */}\n <div style={{ borderTop: '1px solid var(--dsw-alias-border-l2)', paddingTop: 16, maxWidth: 560 }}>\n <h3 style={{ margin: '0 0 6px', fontSize: 13, fontWeight: 600, opacity: 0.7 }}>会话冲突归档</h3>\n <div style={{ fontSize: 11, opacity: 0.55, lineHeight: 1.55, marginBottom: 12 }}>\n 冲突的旧版本会保留在这里;恢复版本后,原当前版本也会进入归档。\n </div>\n {archives.length === 0 ? (\n <div style={{ fontSize: 12, opacity: 0.5 }}>暂无待恢复的会话分支</div>\n ) : (\n archives.map((archive) => (\n <div key={archive.branchId} style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n padding: '10px 12px',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n marginBottom: 8,\n }}>\n <div style={{ minWidth: 0 }}>\n <div style={{ fontSize: 13, display: 'flex', gap: 8, alignItems: 'baseline', flexWrap: 'wrap' }}>\n <code title={archive.originSessionId}>{shortenSessionId(archive.originSessionId)}</code>\n <button type=\"button\" title=\"复制完整会话 ID\" aria-label=\"复制完整会话 ID\" onClick={() => copyText(archive.originSessionId)} style={{ ...secondaryBtn, height: 22, padding: '0 6px', fontSize: 10 }}>复制 ID</button>\n </div>\n <div style={{ fontSize: 11, opacity: 0.5, marginTop: 3 }}>归档于 {new Date(archive.archivedAt).toLocaleString()}</div>\n </div>\n <button type=\"button\" onClick={() => void restoreArchive(archive.branchId)} disabled={busy} style={secondaryBtn}>\n 恢复版本\n </button>\n </div>\n ))\n )}\n </div>\n </>\n )\n}\n","import type { CSSProperties, ReactElement } from 'react'\nimport { useState } from 'react'\n\ntype Notice = { kind: 'ok' | 'error'; text: string } | undefined\n\nconst fieldStyle: CSSProperties = {\n width: '100%',\n boxSizing: 'border-box',\n minHeight: 36,\n padding: '8px 10px',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n font: 'inherit',\n}\n\nconst buttonStyle: CSSProperties = {\n minHeight: 36,\n padding: '0 14px',\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 18,\n background: 'transparent',\n color: 'var(--dsw-alias-label-primary)',\n font: 'inherit',\n cursor: 'pointer',\n}\n\nfunction passwordError(value: string): string | undefined {\n const bytes = new TextEncoder().encode(value).byteLength\n if (bytes < 8 || bytes > 1024) return '包密码需为 8-1024 个 UTF-8 字节'\n if (value.includes('\\0')) return '包密码包含无效字符'\n return undefined\n}\n\nasync function responseError(response: Response, fallback: string): Promise<Error> {\n try {\n const data = await response.json() as { error?: string }\n return new Error(data.error ?? fallback)\n } catch {\n return new Error(fallback)\n }\n}\n\nexport function SyncOfflineSection(props: { onImported?: () => void }): ReactElement {\n const [exportPassword, setExportPassword] = useState('')\n const [confirmPassword, setConfirmPassword] = useState('')\n const [includeSessions, setIncludeSessions] = useState(false)\n const [importPassword, setImportPassword] = useState('')\n const [file, setFile] = useState<File | undefined>(undefined)\n const [fileInputKey, setFileInputKey] = useState(0)\n const [busy, setBusy] = useState<'export' | 'import' | undefined>(undefined)\n const [status, setStatus] = useState('')\n const [notice, setNotice] = useState<Notice>(undefined)\n\n const exportArchive = async (): Promise<void> => {\n const error = passwordError(exportPassword)\n if (error) { setNotice({ kind: 'error', text: error }); return }\n if (exportPassword !== confirmPassword) { setNotice({ kind: 'error', text: '两次输入的包密码不一致' }); return }\n setBusy('export')\n setStatus('正在生成并加密归档…')\n setNotice(undefined)\n try {\n const response = await fetch('/api/dshb/sync/offline/export', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ password: exportPassword, includeSessions }),\n })\n if (!response.ok) throw await responseError(response, '导出离线配置失败')\n const blob = await response.blob()\n const url = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = url\n anchor.download = `dshb-sync-${new Date().toISOString().slice(0, 10)}.dshb-sync`\n document.body.append(anchor)\n anchor.click()\n anchor.remove()\n window.setTimeout(() => URL.revokeObjectURL(url), 1000)\n setExportPassword('')\n setConfirmPassword('')\n setNotice({ kind: 'ok', text: '加密配置包已生成并下载' })\n } catch (caught) {\n setNotice({ kind: 'error', text: caught instanceof Error ? caught.message : '导出离线配置失败' })\n } finally {\n setBusy(undefined)\n setStatus('')\n setExportPassword('')\n setConfirmPassword('')\n }\n }\n\n const importArchive = async (): Promise<void> => {\n const error = passwordError(importPassword)\n if (error) { setNotice({ kind: 'error', text: error }); return }\n if (!file) { setNotice({ kind: 'error', text: '请选择 .dshb-sync 文件' }); return }\n if (file.size > 128 * 1024 * 1024) { setNotice({ kind: 'error', text: '归档文件超过 128 MiB 上限' }); return }\n setBusy('import')\n setStatus('正在准备安全上传…')\n setNotice(undefined)\n try {\n const tokenResponse = await fetch('/api/dshb/sync/offline/import', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ password: importPassword }),\n })\n const tokenData = await tokenResponse.json() as { ok?: boolean; uploadToken?: string; error?: string }\n if (!tokenResponse.ok || !tokenData.ok || !tokenData.uploadToken) throw new Error(tokenData.error ?? '准备离线导入失败')\n\n setStatus('正在上传、解密并校验归档…')\n const response = await fetch(`/api/dshb/sync/offline/import/${tokenData.uploadToken}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/octet-stream' },\n body: file,\n })\n if (!response.ok) throw await responseError(response, '导入离线配置失败')\n const data = await response.json() as {\n ok?: boolean\n result?: { nodes?: { created: number; updated: number; deleted: number; skipped: number }; sessions?: { created: number; updated: number; archived: number; deleted: number; skipped: number } }\n error?: string\n }\n if (!data.ok || !data.result) throw new Error(data.error ?? '导入离线配置失败')\n const nodes = data.result.nodes\n const sessions = data.result.sessions\n setNotice({\n kind: 'ok',\n text: `导入完成:节点新增 ${nodes?.created ?? 0}、更新 ${nodes?.updated ?? 0}、删除 ${nodes?.deleted ?? 0}${sessions ? `;会话新增 ${sessions.created}、更新 ${sessions.updated}、归档 ${sessions.archived}` : ''}`,\n })\n setImportPassword('')\n setFile(undefined)\n setFileInputKey((key) => key + 1)\n props.onImported?.()\n } catch (caught) {\n setNotice({ kind: 'error', text: caught instanceof Error ? caught.message : '导入离线配置失败' })\n } finally {\n setBusy(undefined)\n setStatus('')\n setImportPassword('')\n }\n }\n\n return (\n <div style={{ flex: 1, minWidth: 0, width: '100%', maxWidth: 900 }}>\n <style>{`.dshb-sync-offline-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:16px;align-items:start}.dshb-sync-offline-card{border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:16px;background:var(--dsw-alias-bg-layer-1);min-width:0}.dshb-sync-offline-hint{font-size:12px;line-height:1.5;opacity:.68;margin:0 0 12px}.dshb-sync-offline-actions{margin-top:2px}.dshb-sync-offline-actions button{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dshb-sync-offline-file{max-width:100%;width:100%;box-sizing:border-box;font-size:12px;line-height:1.5}.dshb-sync-offline-file::file-selector-button{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:600px){.dshb-sync-offline-grid{grid-template-columns:1fr;gap:12px}.dshb-sync-offline-actions{display:flex}.dshb-sync-offline-actions button{width:100%}}`}</style>\n <div style={{ marginBottom: 14, fontSize: 13, lineHeight: 1.55, opacity: 0.75, maxWidth: '72ch' }}>\n 通过加密文件在实例间迁移远程节点和可选会话,适用于网络隔离或备份恢复。\n </div>\n <div className=\"dshb-sync-offline-grid\">\n <section className=\"dshb-sync-offline-card\" style={{ borderTop: '3px solid var(--dsw-alias-button-primary-fill)' }}>\n <h3 style={{ margin: '0 0 6px', fontSize: 16 }}>导出加密配置包</h3>\n <p className=\"dshb-sync-offline-hint\">\n 默认导出远程节点配置与凭据;勾选后可包含可映射的工作区会话。同步 peer 凭据和本地节点不会进入导出包。\n </p>\n <div style={{ display: 'grid', gap: 10 }}>\n <label style={{ display: 'grid', gap: 4, fontSize: 13 }}>\n 包密码\n <input style={fieldStyle} type=\"password\" autoComplete=\"new-password\" value={exportPassword} disabled={busy !== undefined} onChange={(event) => setExportPassword(event.target.value)} />\n </label>\n <label style={{ display: 'grid', gap: 4, fontSize: 13 }}>\n 确认包密码\n <input style={fieldStyle} type=\"password\" autoComplete=\"new-password\" value={confirmPassword} disabled={busy !== undefined} onChange={(event) => setConfirmPassword(event.target.value)} />\n </label>\n <label style={{ display: 'flex', alignItems: 'flex-start', gap: 8, fontSize: 13 }}>\n <input type=\"checkbox\" checked={includeSessions} disabled={busy !== undefined} onChange={(event) => setIncludeSessions(event.target.checked)} />\n <span>包含可映射的远程工作区会话<span style={{ display: 'block', fontSize: 11, opacity: 0.65, marginTop: 3 }}>包含会话日志与附件,导出文件可能较大。</span></span>\n </label>\n <div className=\"dshb-sync-offline-actions\"><button type=\"button\" style={buttonStyle} disabled={busy !== undefined} onClick={() => void exportArchive()}>{busy === 'export' ? '正在导出…' : '导出 .dshb-sync'}</button></div>\n </div>\n </section>\n\n <section className=\"dshb-sync-offline-card\" style={{ borderTop: '3px solid var(--dsw-alias-border-l2)' }}>\n <h3 style={{ margin: '0 0 6px', fontSize: 16 }}>导入加密配置包</h3>\n <p className=\"dshb-sync-offline-hint\">\n 先验证密码、格式、摘要、路径和空间,再应用配置。同一来源的重复导入会按身份去重。\n </p>\n <div style={{ display: 'grid', gap: 10 }}>\n <label style={{ display: 'grid', gap: 4, fontSize: 13 }}>\n 归档文件\n <input className=\"dshb-sync-offline-file\" key={fileInputKey} type=\"file\" accept=\".dshb-sync,application/octet-stream\" disabled={busy !== undefined} onChange={(event) => setFile(event.target.files?.[0])} />\n </label>\n <div style={{ fontSize: 12, opacity: 0.7, minHeight: 18, wordBreak: 'break-all' }}>\n {file ? <><strong>{file.name}</strong><span style={{ marginLeft: 6 }}>{(file.size / 1024 / 1024).toFixed(2)} MiB / 上限 128 MiB</span></> : '尚未选择文件,支持 .dshb-sync,最大 128 MiB'}\n </div>\n <label style={{ display: 'grid', gap: 4, fontSize: 13 }}>\n 包密码\n <input style={fieldStyle} type=\"password\" autoComplete=\"current-password\" value={importPassword} disabled={busy !== undefined} onChange={(event) => setImportPassword(event.target.value)} />\n </label>\n <div className=\"dshb-sync-offline-actions\"><button type=\"button\" style={buttonStyle} disabled={busy !== undefined || !file} onClick={() => void importArchive()}>{busy === 'import' ? '正在导入…' : '验证并导入'}</button></div>\n </div>\n </section>\n </div>\n {status && <div role=\"status\" style={{ marginTop: 14, padding: '10px 12px', border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8, fontSize: 13, opacity: 0.8 }}>{status}</div>}\n {notice && <div role=\"status\" style={{ marginTop: 14, padding: '10px 12px', borderRadius: 8, fontSize: 13, background: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-bg, rgba(34,197,94,.1))' : 'var(--dsw-alias-state-error-bg, rgba(248,113,113,.1))', color: notice.kind === 'ok' ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' }}>{notice.text}</div>}\n <div style={{ marginTop: 14, fontSize: 11, lineHeight: 1.6, opacity: 0.55 }}>\n 加密配置包包含敏感凭据,请妥善保存并仅在可信实例间传输。\n </div>\n </div>\n )\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'\nimport { SyncPeersSection } from './sync-peers.js'\nimport { SyncOfflineSection } from './sync-offline.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 sync?: { importedVia?: 'peer' | 'offline'; sourceName?: string; pendingRemoval: boolean; credentialsRequired?: boolean }\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 [panel, setPanel] = useState<'nodes' | 'sync' | 'offline'>('nodes')\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, display: 'flex', flexDirection: 'column', minHeight: 0 }}>\n <button type=\"button\" onClick={() => { setPanel('nodes'); selectNode('new') }} style={{ ...secondaryButtonStyle, width: '100%', marginBottom: 10, borderRadius: 8, background: panel !== 'offline' ? 'var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))' : 'transparent' }}>\n 节点列表\n </button>\n <div style={{ flex: '0 1 auto', minHeight: 0, maxHeight: 'min(60vh, 480px)', overflowY: 'auto' }}>\n {nodes.map((n) => (\n <div\n key={n.id}\n onClick={() => { setPanel('nodes'); 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, display: 'flex', alignItems: 'center', gap: 4 }}>\n {n.name}\n {n.sync?.importedVia === 'peer' && <span aria-label={`同步自 ${n.sync.sourceName ?? 'peer'}`} title={`同步自 ${n.sync.sourceName ?? 'peer'}`} style={{ fontSize: 12, opacity: 0.7 }}>↗</span>}\n </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 {n.sync?.pendingRemoval && <div style={{ fontSize: 11, marginTop: 2, color: 'var(--dsw-alias-state-warn-label)' }}>等待工作区解绑后删除</div>}\n {n.sync?.credentialsRequired && <div style={{ fontSize: 11, marginTop: 2, color: 'var(--dsw-alias-state-warn-label)' }}>同步源未包含可迁移凭据</div>}\n </div>\n ))}\n {nodes.length === 0 && <div style={{ fontSize: 12, opacity: 0.6 }}>暂无节点</div>}\n </div>\n </div>\n\n <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>\n <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', paddingBottom: 8, marginBottom: 10, borderBottom: '1px solid var(--dsw-alias-border-l2)' }}>\n <button type=\"button\" onClick={() => { setPanel('nodes'); selectNode('new') }} style={{ ...(panel === 'nodes' ? primaryButtonStyle : secondaryButtonStyle), height: 32, padding: '0 16px', borderRadius: 8 }}>\n 新建\n </button>\n <button type=\"button\" onClick={() => setPanel('sync')} style={{ ...(panel === 'sync' ? primaryButtonStyle : secondaryButtonStyle), height: 32, padding: '0 16px', borderRadius: 8 }}>\n 同步\n </button>\n <button type=\"button\" onClick={() => setPanel('offline')} style={{ ...(panel === 'offline' ? primaryButtonStyle : secondaryButtonStyle), height: 32, padding: '0 12px', borderRadius: 8 }}>\n 导入/导出\n </button>\n </div>\n <div style={{ flex: 1, minWidth: 0, overflowY: 'auto', overflowX: 'hidden' }}>\n {panel === 'sync' ? <>\n <div role=\"note\" style={{ padding: '10px 12px', marginBottom: 12, border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8, background: 'var(--dsw-alias-bg-layer-1)' }}>\n <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 4 }}>节点与会话同步</div>\n <div style={{ fontSize: 12, lineHeight: 1.45, opacity: 0.72 }}>\n 通过 SSH 在 DSHB 实例间同步远端节点配置,支持单向拉取和双向同步;也可选择同步已映射工作区的会话与附件。首次连接需确认 SSH 主机指纹。\n </div>\n </div>\n <SyncPeersSection />\n </> : panel === 'offline' ? <SyncOfflineSection onImported={reload} /> : <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 </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 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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"}
|