dsh-mobile 0.1.0-alpha.35 → 0.1.0-alpha.36

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/README.en.md CHANGED
@@ -55,6 +55,11 @@ pnpm dsh --profile web
55
55
  After starting DSH, open **Mobile Access** in the lower-left sidebar, then:
56
56
 
57
57
  1. Select **Create and copy key** or **Copy pairing link**; the panel shows a pairing QR code.
58
+
59
+ <p align="center">
60
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/desktop-qr.png" width="70%" alt="Mobile Access panel with the pairing QR code">
61
+ </p>
62
+
58
63
  2. In the Android app, tap **Scan QR code** and point the camera at the screen — or tap **Scan**, select the computer, and paste the key or pairing link.
59
64
  3. Pairing establishes persistent device trust; later launches do not ask again.
60
65
 
@@ -68,15 +73,23 @@ Type `/mobile <what you want>` in a DSH conversation, and DSH edits the phone cl
68
73
  /mobile turn the phone UI into an old CRT terminal, with messages scrolling like terminal output
69
74
  ```
70
75
 
76
+ It can also drive computer capabilities the phone can use, like reading the machine's live state:
77
+
78
+ ```text
79
+ /mobile give the phone a cyberpunk-style computer monitor panel that shows live CPU, memory, and disk usage
80
+ ```
81
+
71
82
  Two kinds of changes are supported: the phone UI itself (theme, layout, buttons), and computer capabilities the phone can use (browsing computer files, running programs on the computer). `/mobile` hands the request to the DSH agent, which edits files under the local DSH configuration directory (`$DSH_HOME/mobile-access/`); the phone client applies them automatically. UI changes live in `mobile.css`/`mobile.js`. Computer capabilities come from extensions under `extensions/`, whose `host.mjs` runs with the local user's privileges on the computer. DeepSeek Harness source is not modified.
72
83
 
73
84
  > When using computer-side capabilities, use only content you trust.
74
85
 
75
- The example above, applied:
86
+ The examples above, applied:
76
87
 
77
88
  <p align="center">
78
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-2.png" width="30%" alt="Mobile UI customized into an old CRT terminal">
79
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-1.png" width="30%" alt="Mobile UI customized into an old CRT terminal">
89
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-2.png" width="22%" alt="Mobile UI customized into an old CRT terminal">
90
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-1.png" width="22%" alt="Mobile UI customized into an old CRT terminal">
91
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-2.png" width="22%" style="margin-left:10px" alt="Mobile UI customized into a cyberpunk computer monitor">
92
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-1.png" width="22%" style="margin-left:8px" alt="Mobile UI customized into a cyberpunk computer monitor">
80
93
  </p>
81
94
 
82
95
  ## App or mobile browser
@@ -110,7 +123,7 @@ See [SECURITY.md](SECURITY.md).
110
123
 
111
124
  | DSH Mobile | Verified DeepSeek Harness releases |
112
125
  | --- | --- |
113
- | `0.1.0-alpha.35` | `0.1.0-rc.5`, `0.1.0-rc.6`, `0.1.0-rc.7` |
126
+ | `0.1.0-alpha.36` | `0.1.0-rc.5`, `0.1.0-rc.6`, `0.1.0-rc.7` |
114
127
 
115
128
  At startup, the plugin verifies the DSH Host version and the frontend dependencies required by the mobile layout; an unverified release fails with a clear error instead of serving a broken page. CI also tracks the DSH main branch layout contract. If a DSH upgrade reports an incompatibility, update DSH Mobile first.
116
129
 
package/README.md CHANGED
@@ -60,6 +60,11 @@ pnpm dsh --profile web
60
60
  启动后,在 DeepSeek Harness 左下角打开“移动访问”,然后:
61
61
 
62
62
  1. 点击“生成并复制密钥”或“复制配对链接”,面板会显示配对二维码。
63
+
64
+ <p align="center">
65
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/desktop-qr.png" width="70%" alt="桌面端移动访问面板与配对二维码">
66
+ </p>
67
+
63
68
  2. Android App 点击“扫码配对”,把手机对准电脑屏幕上的二维码即可;也可以点击“扫描”选择电脑后粘贴密钥或配对链接。
64
69
  3. 配对完成后会建立持久设备信任,以后打开 App 无需重复输入。
65
70
 
@@ -73,13 +78,21 @@ pnpm dsh --profile web
73
78
  /mobile 把手机端做成老式终端的样子,让消息像终端输出一样逐行滚动
74
79
  ```
75
80
 
81
+ 也可以让手机端调用电脑端的能力,比如实时读取电脑状态:
82
+
83
+ ```text
84
+ /mobile 为手机端添加赛博朋克风格的电脑监控面板,实时显示电脑的 CPU、内存和磁盘占用
85
+ ```
86
+
76
87
  `/mobile` 把需求交给 DSH 对话中的 agent,由它直接修改本机 `$DSH_HOME/mobile-access/` 下的文件,保存后手机端自动生效。改动分两类:界面和交互在 `mobile.css`/`mobile.js`;需要电脑能力时用 `extensions/` 下的扩展,其 `host.mjs` 以本机用户权限在电脑上运行。不修改 DeepSeek Harness 源码。
77
88
 
78
89
  示例的实际效果:
79
90
 
80
91
  <p align="center">
81
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-2.png" width="30%" alt="/mobile 定制为老式终端界面">
82
- <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-1.png" width="30%" alt="/mobile 定制为老式终端界面">
92
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-2.png" width="22%" alt="/mobile 定制为老式终端界面">
93
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/crt-terminal-1.png" width="22%" alt="/mobile 定制为老式终端界面">
94
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-2.png" width="22%" style="margin-left:10px" alt="/mobile 定制为赛博朋克监控面板">
95
+ <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-1.png" width="22%" style="margin-left:8px" alt="/mobile 定制为赛博朋克监控面板">
83
96
  </p>
84
97
 
85
98
  ## App 与手机浏览器
package/lib/client.js CHANGED
@@ -28,7 +28,7 @@ window.__ModuleLoader__.load({
28
28
  [data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }
29
29
  [data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }
30
30
  [data-dsh-mobile-center] > * { min-width:0 !important; }
31
- [data-dsh-mobile-header] { box-sizing:border-box !important; width:calc(100% - 16px) !important; margin:0 8px !important; min-width:0; padding-top:4px !important; padding-right:8px !important; padding-left:42px !important; }
31
+ [data-dsh-mobile-header] { box-sizing:border-box !important; width:calc(100% - 16px) !important; margin:0 8px !important; min-width:0; padding-top:max(4px,env(safe-area-inset-top)) !important; padding-right:8px !important; padding-left:42px !important; }
32
32
  [data-dsh-mobile-header] [class*="_titleRow"] { box-sizing:border-box !important; display:flex !important; align-items:center !important; min-width:0; min-height:32px !important; height:32px !important; gap:6px !important; padding:0 6px !important; }
33
33
  [data-dsh-mobile-header] [class*="_titleCluster"] { min-width:0; }
34
34
  [data-dsh-mobile-header] [class*="_crumbs"] { min-width:0; overflow:hidden; }
@@ -969,7 +969,7 @@ window.__ModuleLoader__.load({
969
969
  } catch {}
970
970
  }
971
971
  const CONTROL_STYLES = `
972
- .dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:64px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}
972
+ .dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:112px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}
973
973
  .dsh-mobile-control__panel{box-sizing:border-box;width:min(328px,calc(100vw - 32px));padding:16px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:18px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 18px 50px rgb(15 23 42 / 18%)}
974
974
  .dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}
975
975
  .dsh-mobile-control__access{display:flex;align-items:baseline;gap:6px;min-width:0;margin:0 0 12px}.dsh-mobile-control__access[hidden]{display:none}.dsh-mobile-control__access-label{flex:none;color:var(--dsw-alias-label-secondary,#606873);white-space:nowrap}.dsh-mobile-control__access-label::after{content:":"}.dsh-mobile-control__access-link{min-width:0;overflow:hidden;color:#2563eb;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__access-link:hover{text-decoration:underline}.dsh-mobile-control__qr{display:flex;justify-content:center;margin:0 0 12px}.dsh-mobile-control__qr[hidden]{display:none}.dsh-mobile-control__qr img{border-radius:12px;background:#fff;padding:8px}
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["createElement"],"sources":["../src/native-mobile.ts","../src/client.ts"],"sourcesContent":["/** Mobile feature and compatibility rules applied to DSH React surfaces. */\nexport const NATIVE_MOBILE_STYLES = `\n@media (max-width:720px) {\n html.dsh-native-mobile-active,html.dsh-native-mobile-active body { width:100%; height:100%; overflow:hidden; }\n html.dsh-native-mobile-active { --dsh-mobile-motion-duration:200ms; --dsh-mobile-motion-ease:cubic-bezier(.22,1,.36,1); }\n html.dsh-native-mobile-active :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]) { -webkit-tap-highlight-color:transparent; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [role=\"treeitem\"] { -webkit-tap-highlight-color:transparent; touch-action:manipulation; }\n html.dsh-native-mobile-active[data-dsh-mobile-input=\"touch\"] :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]):focus { outline:none !important; }\n html.dsh-native-mobile-active [role=\"tooltip\"] { display:none !important; }\n /* Touch has no persistent hover affordance: keep workspace rows neutral after a tap. */\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] { --dsw-alias-interactive-bg-hover:transparent !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [role=\"treeitem\"]:is(:hover,:active,:focus,[aria-selected=\"true\"]),\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_sessionRow\"][class*=\"_selected\"],\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_searchResultRow\"][class*=\"_selected\"] { background:transparent !important; outline:0 !important; box-shadow:none !important; }\n /* Sidebar row menus are hover-only on desktop. Touch has no hover, so keep\n the ellipsis action visible and give it a reliable hit target. */\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_rowActions\"] { display:inline-flex !important; align-items:center !important; gap:8px !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_sessionRow\"] [class*=\"_time\"] { display:none !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_rowActions\"] button { box-sizing:border-box !important; width:32px !important; min-width:32px !important; height:32px !important; min-height:32px !important; }\n [data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }\n [data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }\n [data-dsh-mobile-center] > * { min-width:0 !important; }\n [data-dsh-mobile-header] { box-sizing:border-box !important; width:calc(100% - 16px) !important; margin:0 8px !important; min-width:0; padding-top:4px !important; padding-right:8px !important; padding-left:42px !important; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { box-sizing:border-box !important; display:flex !important; align-items:center !important; min-width:0; min-height:32px !important; height:32px !important; gap:6px !important; padding:0 6px !important; }\n [data-dsh-mobile-header] [class*=\"_titleCluster\"] { min-width:0; }\n [data-dsh-mobile-header] [class*=\"_crumbs\"] { min-width:0; overflow:hidden; }\n [data-dsh-mobile-header] [class*=\"_crumb\"] { max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { min-width:0; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-header] [class*=\"_headerUtilities\"] { gap:2px !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] { width:40px; min-width:40px; padding:0 !important; overflow:hidden; color:transparent; font-size:0 !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] > * { display:none !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"]::after { color:var(--dsw-text, #171a21); content:\"日志\"; font-size:11px; font-weight:600; }\n [data-dsh-mobile-header] [class*=\"_tabs\"] { box-sizing:border-box !important; width:max-content !important; max-width:calc(100% - 58px) !important; min-height:28px !important; height:28px !important; margin-top:0 !important; padding-left:6px !important; padding-right:6px !important; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_tab\"] { padding-bottom:5px !important; }\n [data-dsh-mobile-header] [class*=\"_tabs\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-sidebar] { position:fixed !important; z-index:240 !important; inset:0 auto 0 0 !important; width:0 !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar-root] { position:fixed !important; z-index:241 !important; inset:0 auto 0 0 !important; height:100dvh !important; transition:width 180ms var(--dsh-mobile-motion-ease),box-shadow 180ms ease !important; }\n [data-dsh-mobile-sidebar][data-open=\"true\"] [data-dsh-mobile-sidebar-root] { width:min(88vw,340px) !important; box-shadow:18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] { width:0 !important; border:0 !important; background:transparent !important; box-shadow:none !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :not(:has([data-dsh-mobile-toggle])) { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) { position:fixed !important; z-index:244 !important; top:env(safe-area-inset-top) !important; left:0 !important; box-sizing:border-box !important; width:50px !important; height:52px !important; padding:4px !important; border:0 !important; background:transparent !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) > :not([data-dsh-mobile-toggle]) { display:none !important; }\n [data-dsh-mobile-toggle] { width:44px !important; height:44px !important; min-width:44px !important; min-height:44px !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle] > svg[class*=\"_railFish\"] { transform:translateY(-4px) !important; }\n .dsh-native-mobile-backdrop { position:fixed; z-index:235; inset:0; border:0; background:rgb(15 23 42 / 32%); }\n .dsh-native-mobile-backdrop:not([hidden]) { animation:dsh-mobile-fade-in var(--dsh-mobile-motion-duration) ease-out; }\n .dsh-native-mobile-backdrop[hidden] { display:none; }\n [data-dsh-mobile-details] { position:fixed !important; z-index:250 !important; inset:0 0 0 auto !important; width:min(94vw,460px) !important; max-width:none !important; transform:translateX(100%); transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); background:var(--dsw-bg, #fff); box-shadow:-18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-details][data-open=\"true\"] { transform:translateX(0); }\n [data-dsh-mobile-handle] { display:none !important; }\n [data-dsh-mobile-settings] { flex-direction:column !important; width:100vw !important; height:100dvh !important; max-width:none !important; border-radius:0 !important; animation:dsh-mobile-panel-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-settings-nav] { flex:none !important; width:100% !important; padding:max(14px,env(safe-area-inset-top)) 12px 8px !important; gap:10px !important; border-bottom:1px solid var(--dsw-alias-border-subtle,#e8ebef); }\n [data-dsh-mobile-settings-nav] [class*=\"_navTitle\"] { padding:0 8px !important; font-size:18px !important; line-height:28px !important; }\n [data-dsh-mobile-settings-list] { flex-direction:row !important; gap:4px !important; overflow-x:auto !important; scrollbar-width:none; }\n [data-dsh-mobile-settings-list]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-settings-list] [class*=\"_navCell\"] { flex:0 0 auto !important; min-width:max-content !important; height:44px !important; padding:10px 12px !important; }\n [data-dsh-mobile-settings-list] [aria-current=\"true\"] { border-color:transparent !important; outline:0 !important; box-shadow:none !important; }\n [data-dsh-mobile-settings-content] { flex:1 1 auto !important; width:100% !important; min-height:0 !important; }\n [data-dsh-mobile-settings-header] { height:48px !important; min-height:48px !important; padding:10px 12px 6px !important; }\n [data-dsh-mobile-settings-header] [class*=\"_close\"] { width:36px !important; height:36px !important; }\n [data-dsh-mobile-settings-options] { box-sizing:border-box !important; width:100% !important; padding:4px 16px max(24px,env(safe-area-inset-bottom)) !important; overflow-x:hidden !important; }\n [data-dsh-mobile-settings-options] > * { width:100% !important; min-width:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] > [class*=\"_row\"] { flex-direction:column !important; align-items:stretch !important; gap:12px !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_rowText\"] { width:100% !important; padding-right:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { box-sizing:border-box !important; align-self:flex-start !important; justify-content:space-between !important; min-width:0 !important; min-height:44px !important; max-width:100% !important; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea,button) { max-width:100%; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea) { box-sizing:border-box; width:100%; min-width:0; }\n [data-dsh-mobile-settings-options] [class*=\"_head\"] { min-width:0; flex-wrap:wrap; }\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:dsh-mobile-view-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-center] textarea { font-size:16px !important; }\n /* Markdown tables use content-sized columns. Small tables fill the phone;\n wider tables keep readable cells and scroll inside their own region. */\n [data-dsh-mobile-table-scroll] { box-sizing:border-box; width:100%; max-width:100%; overflow-x:auto; overscroll-behavior-x:contain; -webkit-overflow-scrolling:touch; }\n [data-dsh-mobile-table-scroll] table { display:table !important; width:max-content !important; min-width:100% !important; max-width:none !important; table-layout:auto !important; }\n [data-dsh-mobile-table-scroll] :is(th,td) { box-sizing:border-box; min-width:8ch; max-width:32ch; overflow-wrap:anywhere; word-break:break-word; vertical-align:top; }\n [data-dsh-mobile-center] pre { max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] :is(img,video,canvas,svg) { max-width:100%; }\n [data-dsh-mobile-message-scroll] { box-sizing:border-box !important; width:100% !important; padding:8px 10px 20px !important; }\n [data-dsh-mobile-message-column] { box-sizing:border-box !important; width:100% !important; max-width:none !important; margin:0 !important; padding:0 !important; gap:10px !important; }\n [data-dsh-mobile-message-column] > * { width:100% !important; max-width:100% !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] { box-sizing:border-box !important; display:grid !important; grid-template-columns:16px minmax(0,1fr) !important; grid-auto-rows:auto !important; align-items:center !important; column-gap:6px !important; width:100% !important; height:auto !important; min-height:40px !important; padding:4px 0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_leading\"] { grid-column:1 !important; grid-row:1 !important; margin-right:0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_title\"] { grid-column:2 !important; grid-row:1 !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_sep\"],[class*=\"_separator\"]) { display:none !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_summary\"],[class*=\"_fileLink\"]) { grid-column:2 !important; grid-row:2 !important; width:100% !important; min-width:0 !important; max-width:100% !important; overflow:hidden !important; line-height:19px !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_summarySuffix\"] { grid-column:2 !important; grid-row:3 !important; margin-left:0 !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { display:grid !important; grid-template-columns:minmax(72px,30%) minmax(0,1fr) !important; gap:4px 10px !important; }\n [data-dsh-mobile-message-column] [class*=\"_ioSection\"] { grid-template-columns:1fr !important; row-gap:4px !important; }\n [data-dsh-mobile-message-column] [class*=\"_body\"] { max-width:100% !important; overflow-wrap:anywhere; }\n [data-dsh-mobile-center] [data-composer-card] ~ [class*=\"_root\"],\n [data-dsh-mobile-center] [data-composer-card] ~ * [class*=\"_root\"] { box-sizing:border-box !important; width:100% !important; max-width:100% !important; margin-bottom:-6px !important; padding:3px 4px 0 !important; font-size:11px !important; line-height:18px !important; white-space:normal !important; overflow:visible !important; text-overflow:clip !important; }\n [data-dsh-mobile-center] [data-composer-card] ~ [class*=\"_root\"] [class*=\"_sep\"],\n [data-dsh-mobile-center] [data-composer-card] ~ * [class*=\"_root\"] [class*=\"_sep\"] { margin:0 6px !important; }\n /* Message runtime details are inline on desktop. Give the clock/runtime\n label its own wrapping row on narrow screens so TTFT and throughput do\n not push the action buttons or clip at the viewport edge. */\n [data-dsh-mobile-center] [class*=\"_actions\"]:has(> [class*=\"_timeStart\"]),\n [data-dsh-mobile-center] [class*=\"_actions\"]:has(> [class*=\"_timeEnd\"]) { box-sizing:border-box !important; width:100% !important; flex-wrap:wrap !important; justify-content:flex-end !important; height:auto !important; min-height:28px !important; row-gap:2px !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"],\n [data-dsh-mobile-center] [class*=\"_timeEnd\"] { box-sizing:border-box !important; flex:1 1 100% !important; order:2 !important; min-width:0 !important; max-width:100% !important; padding:0 !important; line-height:20px !important; text-align:center !important; white-space:normal !important; overflow-wrap:anywhere !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"] { box-sizing:border-box !important; flex:1 1 100% !important; order:2 !important; min-width:0 !important; max-width:100% !important; padding:0 !important; line-height:20px !important; text-align:center !important; white-space:normal !important; overflow-wrap:anywhere !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"] [class*=\"_runTimeDot\"],\n [data-dsh-mobile-center] [class*=\"_timeEnd\"] [class*=\"_runTimeDot\"] { margin:0 6px !important; }\n /* Keep the context meter's legend rows as readable label/value pairs.\n Generic mobile flex rules can otherwise place the rows side by side and\n break Chinese labels in the middle of a word. */\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] { width:min(264px,calc(100vw - 32px)) !important; min-width:0 !important; max-width:calc(100vw - 32px) !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] [class*=\"_rows\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] [class*=\"_rows\"] { display:block !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] [class*=\"_rows\"] > [class*=\"_row\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] [class*=\"_rows\"] > [class*=\"_row\"] { display:flex !important; align-items:center !important; justify-content:space-between !important; width:100% !important; min-width:0 !important; white-space:nowrap !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] :is(dt,dd),\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] :is(dt,dd) { white-space:nowrap !important; word-break:keep-all !important; }\n .dsh-mobile-branch-toast { position:fixed; z-index:300; top:max(12px,env(safe-area-inset-top)); left:50%; max-width:calc(100vw - 32px); box-sizing:border-box; padding:7px 14px; border:1px solid rgb(15 23 42 / 10%); border-radius:999px; background:rgb(15 23 42 / 92%); color:#fff; font-size:13px; line-height:20px; text-align:center; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; opacity:0; pointer-events:none; transform:translate(-50%,-8px); transition:opacity 160ms ease,transform 160ms ease; }\n .dsh-mobile-branch-toast[data-visible=\"true\"] { opacity:1; transform:translate(-50%,0); }\n [data-dsh-mobile-center] [class*=\"_composer\"] { padding-left:8px !important; padding-right:8px !important; padding-bottom:max(8px,env(safe-area-inset-bottom)) !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_row\"] { display:flex !important; align-items:center !important; gap:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_tools\"] { flex:0 0 auto !important; width:auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] { flex:1 1 auto !important; min-width:0 !important; gap:6px !important; margin-left:auto !important; justify-content:flex-end !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] [class*=\"_root\"]:has(button[aria-label^=\"选择模型\"]) { flex:0 1 auto !important; width:auto !important; max-width:min(55vw,220px) !important; min-width:0 !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] { width:auto !important; max-width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] [class*=\"_triggerLabel\"] { max-width:clamp(120px,36vw,210px); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) > [class=\"\"]:last-child { display:none !important; }\n}\n@keyframes dsh-mobile-fade-in { from { opacity:0; } }\n@keyframes dsh-mobile-panel-in { from { opacity:.72; transform:translateY(6px); } }\n@keyframes dsh-mobile-view-in { from { opacity:.58; transform:translateY(5px); } }\n@media (max-width:420px) {\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { max-width:42vw; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { align-self:stretch !important; width:100% !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { grid-template-columns:1fr !important; }\n}\n@media (prefers-reduced-motion:reduce) {\n [data-dsh-mobile-sidebar-root],[data-dsh-mobile-details] { transition:none !important; }\n .dsh-native-mobile-backdrop:not([hidden]),[data-dsh-mobile-settings],\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:none !important; }\n}\n`\n\nfunction classToken(element: Element, suffix: string): boolean {\n return Array.from(element.classList).some(value => value.endsWith(suffix))\n}\n\nfunction firstByClassSuffix(root: ParentNode, suffix: string): HTMLElement | undefined {\n return Array.from(root.querySelectorAll<HTMLElement>('[class]')).find(element => classToken(element, suffix))\n}\n\n/** Add mobile semantics without replacing feature trees. */\nexport function installNativeMobileSurface(): () => void {\n document.documentElement.classList.add('dsh-native-mobile-active')\n const setInputMode = (mode: 'keyboard' | 'touch'): void => {\n document.documentElement.dataset.dshMobileInput = mode\n }\n const onPointerDown = (event: PointerEvent): void => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen') setInputMode('touch')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Tab' || event.key.startsWith('Arrow')) setInputMode('keyboard')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n const backdrop = document.createElement('button')\n backdrop.type = 'button'\n backdrop.className = 'dsh-native-mobile-backdrop'\n backdrop.hidden = true\n backdrop.setAttribute('aria-label', '关闭工作区导航')\n document.body.append(backdrop)\n const branchToast = document.createElement('div')\n branchToast.className = 'dsh-mobile-branch-toast'\n branchToast.setAttribute('role', 'status')\n branchToast.setAttribute('aria-live', 'polite')\n document.body.append(branchToast)\n let branchToastTimer = 0\n const showBranchToast = (): void => {\n const header = document.querySelector<HTMLElement>('[data-dsh-mobile-header]')\n const title = header === null ? undefined : header.querySelector<HTMLElement>('[class*=\"_crumbCurrent\"]')?.textContent?.trim()\n branchToast.textContent = title === undefined ? '当前分支' : `当前分支:${title}`\n branchToast.dataset.visible = 'true'\n if (branchToastTimer !== 0) window.clearTimeout(branchToastTimer)\n branchToastTimer = window.setTimeout(() => {\n branchToast.removeAttribute('data-visible')\n branchToastTimer = 0\n }, 1600)\n }\n const onBranchClick = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const branch = event.target.closest<HTMLButtonElement>('button[aria-label*=\"分支\"],button[aria-label*=\"Branch\"],button[aria-label*=\"branch\"]')\n if (branch === null || branch.hasAttribute('disabled') || branch.getAttribute('aria-disabled') === 'true') return\n window.setTimeout(showBranchToast, 80)\n }\n document.addEventListener('click', onBranchClick, true)\n let frame: HTMLElement | undefined\n let sidebar: HTMLElement | undefined\n let sidebarRoot: HTMLElement | undefined\n let toggle: HTMLButtonElement | undefined\n let viewArea: HTMLElement | undefined\n let scheduled = 0\n let transitionFrame = 0\n let transitionRestartFrame = 0\n let transitionTimer = 0\n let transitionTarget: HTMLElement | undefined\n const animateNavigation = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const trigger = event.target.closest<HTMLElement>('button,a,[role=\"tab\"],[aria-selected]')\n if (trigger === null || trigger.hasAttribute('disabled') || trigger.getAttribute('aria-disabled') === 'true') return\n if (trigger.getAttribute('aria-selected') === 'true' || trigger.getAttribute('aria-current') === 'true') return\n const settingsNavigation = trigger.closest('[data-dsh-mobile-settings-list]') !== null\n const conversationNavigation = trigger.matches('[role=\"tab\"]')\n const sidebarNavigation = trigger.closest('[data-dsh-mobile-sidebar-root]') !== null\n && trigger.closest('[data-dsh-mobile-toggle]') === null\n if (!settingsNavigation && !conversationNavigation && !sidebarNavigation) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n transitionFrame = requestAnimationFrame(() => {\n transitionFrame = 0\n const target = settingsNavigation\n ? document.querySelector<HTMLElement>('[data-dsh-mobile-settings-content]')\n : viewArea\n if (target === null || target === undefined) return\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n target.removeAttribute('data-dsh-mobile-view-transition')\n transitionRestartFrame = requestAnimationFrame(() => {\n transitionRestartFrame = 0\n transitionTarget = target\n target.dataset.dshMobileViewTransition = 'true'\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTimer = window.setTimeout(() => {\n target.removeAttribute('data-dsh-mobile-view-transition')\n if (transitionTarget === target) transitionTarget = undefined\n transitionTimer = 0\n }, 240)\n })\n })\n }\n document.addEventListener('click', animateNavigation)\n\n const sync = (): void => {\n scheduled = 0\n frame = firstByClassSuffix(document, '_frame')\n const dedicatedCenter = document.querySelector<HTMLElement>('.dshm-main') ?? undefined\n if (frame !== undefined) frame.dataset.dshMobileFrame = 'true'\n sidebar = frame === undefined\n ? document.querySelector<HTMLElement>('.dshm-drawer') ?? undefined\n : firstByClassSuffix(frame, '_sidebarCol')\n const center = frame === undefined ? dedicatedCenter : firstByClassSuffix(frame, '_centerCol')\n const details = frame === undefined ? undefined : firstByClassSuffix(frame, '_detailsCol')\n const handle = frame === undefined ? undefined : firstByClassSuffix(frame, '_handle')\n if (center === undefined) return\n if (center !== undefined) {\n center.dataset.dshMobileCenter = 'true'\n center.querySelector<HTMLElement>('header')?.setAttribute('data-dsh-mobile-header', 'true')\n viewArea = firstByClassSuffix(center, '_viewArea')\n if (viewArea !== undefined) viewArea.dataset.dshMobileView = 'true'\n const conversation = center.querySelector<HTMLElement>('[data-conversation-scroll]')\n const messageColumn = conversation === null ? undefined : firstByClassSuffix(conversation, '_column')\n const messageScroll = messageColumn?.parentElement\n if (messageColumn !== undefined && messageScroll !== null && messageScroll !== undefined && classToken(messageScroll, '_scroll')) {\n messageColumn.dataset.dshMobileMessageColumn = 'true'\n messageScroll.dataset.dshMobileMessageScroll = 'true'\n }\n for (const table of center.querySelectorAll<HTMLTableElement>('table')) {\n const parent = table.parentElement\n if (parent?.dataset.dshMobileTableScroll === 'true') continue\n const wrapper = document.createElement('div')\n wrapper.dataset.dshMobileTableScroll = 'true'\n table.before(wrapper)\n wrapper.append(table)\n }\n }\n if (handle !== undefined) handle.dataset.dshMobileHandle = 'true'\n if (details !== undefined) {\n details.dataset.dshMobileDetails = 'true'\n const lastColumn = frame?.style.gridTemplateColumns.trim().split(/\\s+/).at(-1)\n details.dataset.open = String(lastColumn !== undefined && lastColumn !== '0px' && lastColumn !== '0')\n }\n const settings = Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"]')).find(dialog => {\n const directNav = Array.from(dialog.children).find(child => child instanceof HTMLElement && classToken(child, '_nav'))\n return directNav !== undefined\n })\n if (settings !== undefined) {\n settings.dataset.dshMobileSettings = 'true'\n const nav = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_nav')) as HTMLElement | undefined\n const content = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_content')) as HTMLElement | undefined\n if (nav !== undefined) {\n nav.dataset.dshMobileSettingsNav = 'true'\n firstByClassSuffix(nav, '_navList')?.setAttribute('data-dsh-mobile-settings-list', 'true')\n }\n if (content !== undefined) {\n content.dataset.dshMobileSettingsContent = 'true'\n firstByClassSuffix(content, '_header')?.setAttribute('data-dsh-mobile-settings-header', 'true')\n firstByClassSuffix(content, '_options')?.setAttribute('data-dsh-mobile-settings-options', 'true')\n }\n }\n if (sidebar === undefined) return\n sidebar.dataset.dshMobileSidebar = 'true'\n toggle = firstByClassSuffix(sidebar, '_toggle') as HTMLButtonElement | undefined\n let candidate = toggle?.parentElement\n while (candidate !== undefined && candidate !== null && candidate !== sidebar && !classToken(candidate, '_root')) candidate = candidate.parentElement\n sidebarRoot = candidate !== sidebar && candidate !== null ? candidate : undefined\n if (sidebarRoot === undefined) return\n sidebarRoot.dataset.dshMobileSidebarRoot = 'true'\n if (toggle !== undefined) toggle.dataset.dshMobileToggle = 'true'\n const collapsed = classToken(sidebarRoot, '_collapsed')\n sidebar.dataset.open = String(!collapsed)\n backdrop.hidden = collapsed\n }\n const schedule = (): void => { if (scheduled === 0) scheduled = requestAnimationFrame(sync) }\n const observer = new MutationObserver(schedule)\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] })\n backdrop.addEventListener('click', () => { if (sidebar?.dataset.open === 'true') toggle?.click() })\n sync()\n return () => {\n observer.disconnect()\n document.removeEventListener('click', onBranchClick, true)\n if (branchToastTimer !== 0) window.clearTimeout(branchToastTimer)\n branchToast.remove()\n if (scheduled !== 0) cancelAnimationFrame(scheduled)\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', animateNavigation)\n backdrop.remove()\n document.documentElement.classList.remove('dsh-native-mobile-active')\n delete document.documentElement.dataset.dshMobileInput\n }\n}\n","import { createElement } from 'react'\nimport { installNativeMobileSurface, NATIVE_MOBILE_STYLES } from './native-mobile.js'\n\ninterface ClientContext {\n effect(effect: () => void | (() => void), label?: string): void\n slots: {\n inject(key: string, callback: () => (() => void)): () => void\n register(options: { name: string; id: string }, component: (props: { wide: boolean }) => unknown): () => void\n }\n}\n\ninterface MobileExtensionContext {\n readonly document: Document\n readonly request: (path: string, init?: RequestInit) => Promise<Response>\n readonly root: HTMLElement\n readonly window: Window\n}\n\ntype MobileExtensionMount = (context: MobileExtensionContext) => void | (() => void)\ntype MobileSurfacePlacement = 'page' | 'sidebar-action' | 'header-action' | 'composer-dock' | 'settings-section' | 'overlay'\ninterface MobileSurface {\n readonly id: string\n readonly placement: MobileSurfacePlacement\n readonly label: string\n mount(container: HTMLElement): void | (() => void)\n}\ninterface MobileClientApi {\n readonly host: {\n invoke(action: string, input: unknown): Promise<unknown>\n fetch(path: string, init?: RequestInit): Promise<Response>\n }\n readonly ui: {\n registerSurface(surface: MobileSurface): () => void\n open(surfaceId: string): void\n close(surfaceId: string): void\n toast(message: string): void\n }\n readonly native: {\n capabilities(): Promise<readonly string[]>\n invoke(action: string, input?: unknown): Promise<unknown>\n }\n readonly signal: AbortSignal\n readonly document: Document\n readonly window: Window\n}\ninterface MobileClientDefinition {\n readonly apiVersion: 1\n readonly id: string\n activate(api: MobileClientApi): void | (() => void) | Promise<void | (() => void)>\n}\n\ndeclare global {\n interface Window {\n dshMobile?: {\n register(mount: MobileExtensionMount): void\n define(definition: MobileClientDefinition): void\n }\n __DSH_MOBILE_FRONTEND__?: 'dedicated'\n __DSH_MOBILE_NATIVE__?: {\n capabilities(): Promise<readonly string[]> | readonly string[]\n invoke(action: string, input?: unknown): Promise<unknown>\n }\n }\n}\n\nconst queuedDefinitions: MobileClientDefinition[] = []\nlet queuedLegacyMount: MobileExtensionMount | undefined\nif (typeof window !== 'undefined' && window.dshMobile === undefined) {\n window.dshMobile = {\n register: mount => { queuedLegacyMount = mount },\n define: definition => { queuedDefinitions.push(definition) },\n }\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]'\n}\n\nfunction element<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag)\n if (className !== undefined) node.className = className\n return node\n}\n\nasync function requestJson(path: string, init?: RequestInit): Promise<Record<string, unknown>> {\n const response = await fetch(path, { ...init, headers: { 'content-type': 'application/json', ...init?.headers } })\n const body = await response.json() as Record<string, unknown>\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction installControl(): { remove: () => void; toggle: () => void } {\n const root = element('div', 'dsh-mobile-control')\n const panel = element('section', 'dsh-mobile-control__panel'); panel.hidden = true\n panel.setAttribute('aria-label', '移动访问')\n const header = element('header', 'dsh-mobile-control__header')\n const title = element('h2'); title.textContent = '移动访问'\n const close = element('button', 'dsh-mobile-control__close'); close.type = 'button'; close.textContent = '×'; close.setAttribute('aria-label', '收起移动访问')\n const access = element('div', 'dsh-mobile-control__access'); access.hidden = true\n const accessLabel = element('span', 'dsh-mobile-control__access-label'); accessLabel.textContent = '浏览器访问'\n const accessLink = element('a', 'dsh-mobile-control__access-link'); accessLink.target = '_blank'; accessLink.rel = 'noreferrer'\n access.append(accessLabel, accessLink)\n const qrBox = element('div', 'dsh-mobile-control__qr'); qrBox.hidden = true\n const status = element('p', 'dsh-mobile-control__status'); status.textContent = '正在读取状态…'\n const extensionStatus = element('p', 'dsh-mobile-control__extensions'); extensionStatus.hidden = true\n const actions = element('div', 'dsh-mobile-control__actions')\n const toggle = element('button', 'dsh-mobile-control__secondary'); toggle.type = 'button'\n const pair = element('button', 'dsh-mobile-control__primary'); pair.type = 'button'; pair.textContent = '生成并复制密钥'\n const linkPair = element('button', 'dsh-mobile-control__secondary'); linkPair.type = 'button'; linkPair.textContent = '复制配对链接'\n const manageRow = element('div', 'dsh-mobile-control__manage-row')\n const manageDevices = element('button', 'dsh-mobile-control__manage'); manageDevices.type = 'button'; manageDevices.textContent = '管理配对设备'\n const resetAll = element('button', 'dsh-mobile-control__manage'); resetAll.type = 'button'; resetAll.textContent = '清除所有设备'\n manageRow.append(manageDevices, resetAll)\n const devicePanel = element('div', 'dsh-mobile-control__devices'); devicePanel.hidden = true\n header.append(title, close); actions.append(toggle, pair, linkPair); panel.append(header, access, qrBox, status, extensionStatus, actions, manageRow, devicePanel); root.append(panel); document.body.append(root)\n let running = false\n let origin = ''\n const setOpen = (open: boolean): void => {\n panel.hidden = !open\n for (const trigger of document.querySelectorAll('.dsh-mobile-control__trigger')) trigger.setAttribute('aria-expanded', String(open))\n }\n const render = (data: Record<string, unknown>): void => {\n running = data.running === true\n origin = running && typeof data.origin === 'string' ? data.origin : ''\n access.hidden = origin === ''\n accessLink.href = origin\n accessLink.textContent = origin\n accessLink.title = origin\n status.classList.toggle('is-running', running)\n status.textContent = running ? '移动访问已开启。' : '已关闭。DSH 仍只在本机可用。'\n const extensionData = data.extensions\n if (extensionData !== null && typeof extensionData === 'object') {\n const loaded = typeof (extensionData as { loaded?: unknown }).loaded === 'number' ? (extensionData as { loaded: number }).loaded : 0\n const failed = typeof (extensionData as { failed?: unknown }).failed === 'number' ? (extensionData as { failed: number }).failed : 0\n extensionStatus.hidden = false\n extensionStatus.textContent = failed === 0 ? `扩展:${String(loaded)} 个已加载` : `扩展:${String(loaded)} 个已加载,${String(failed)} 个加载失败`\n } else extensionStatus.hidden = true\n if (!running) qrBox.hidden = true\n toggle.textContent = running ? '关闭移动访问' : '开启移动访问'\n pair.disabled = !running\n linkPair.disabled = !running\n manageDevices.disabled = !running\n resetAll.disabled = !running\n }\n const showQr = (svg: string): void => {\n qrBox.replaceChildren()\n if (svg === '') { qrBox.hidden = true; return }\n const image = element('img')\n image.alt = '配对二维码'\n image.width = 176\n image.height = 176\n image.src = `data:image/svg+xml;base64,${btoa(svg)}`\n qrBox.hidden = false\n qrBox.append(image)\n }\n const openPairing = (target: 'key' | 'link'): void => {\n void requestJson('/api/mobile-access/pairing/open', { method: 'POST', body: '{}' }).then(async data => {\n const value = target === 'key'\n ? (typeof data.appKey === 'string' ? data.appKey : '')\n : (typeof data.pairUrl === 'string' ? data.pairUrl : '')\n showQr(typeof data.qrSvg === 'string' ? data.qrSvg : '')\n if (value === '') { status.textContent = '无法生成配对密钥。'; return }\n try {\n await navigator.clipboard.writeText(value)\n status.textContent = target === 'key'\n ? '配对密钥已复制,请粘贴到 Android App。'\n : '配对链接已复制,发给手机后 App 粘贴或浏览器打开即可配对。'\n } catch {\n status.textContent = `请复制${target === 'key' ? '配对密钥' : '配对链接'}:${value}`\n status.classList.add('is-key')\n }\n }, error => { status.textContent = String(error) }).finally(() => {\n pair.disabled = !running\n linkPair.disabled = !running\n })\n }\n toggle.addEventListener('click', () => { toggle.disabled = true; void requestJson('/api/mobile-access/control', { method: 'POST', body: JSON.stringify({ running: !running }) }).then(render, error => { status.textContent = String(error) }).finally(() => { toggle.disabled = false }) })\n const formatTime = (ms: unknown): string => typeof ms === 'number' ? new Date(ms).toLocaleString() : ''\n const renderDevices = (data: Record<string, unknown>): void => {\n const devices = Array.isArray(data.devices) ? data.devices as Record<string, unknown>[] : []\n devicePanel.replaceChildren()\n if (devices.length === 0) {\n const empty = element('p', 'dsh-mobile-control__device-empty'); empty.textContent = '暂无配对设备。'\n devicePanel.append(empty)\n return\n }\n for (const device of devices) {\n const row = element('div', 'dsh-mobile-control__device')\n const label = element('span', 'dsh-mobile-control__device-label')\n label.textContent = typeof device.label === 'string' ? device.label : '设备'\n const meta = element('span', 'dsh-mobile-control__device-meta'); meta.textContent = `到期 ${formatTime(device.expiresAt)}`\n const revoke = element('button', 'dsh-mobile-control__device-revoke'); revoke.type = 'button'; revoke.textContent = '撤销'\n const id = typeof device.id === 'string' ? device.id : ''\n revoke.addEventListener('click', () => {\n void requestJson('/api/mobile-access/devices/revoke', { method: 'POST', body: JSON.stringify({ deviceId: id }) })\n .then(loadDevices, error => { status.textContent = String(error) })\n })\n row.append(label, meta, revoke)\n devicePanel.append(row)\n }\n }\n const loadDevices = (): void => {\n void requestJson('/api/mobile-access/devices').then(renderDevices, error => { status.textContent = String(error) })\n }\n manageDevices.addEventListener('click', () => {\n const show = devicePanel.hidden\n devicePanel.hidden = !show\n if (show) loadDevices()\n })\n resetAll.addEventListener('click', () => {\n if (!window.confirm('确定要移除所有配对设备吗?此操作会立即终止已连接设备。')) return\n void requestJson('/api/mobile-access/devices/reset', { method: 'POST', body: JSON.stringify({ confirm: true }) })\n .then(loadDevices, error => { status.textContent = String(error) })\n })\n pair.addEventListener('click', () => { pair.disabled = true; openPairing('key') })\n linkPair.addEventListener('click', () => { linkPair.disabled = true; openPairing('link') })\n close.addEventListener('click', () => { setOpen(false) })\n const dismiss = (event: PointerEvent): void => {\n if (panel.hidden || !(event.target instanceof Node)) return\n if (!panel.contains(event.target) && !document.querySelector('.dsh-mobile-control__trigger')?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', dismiss)\n void requestJson('/api/mobile-access/control').then(render, error => { status.textContent = String(error) })\n return { remove: () => { document.removeEventListener('pointerdown', dismiss); root.remove() }, toggle: () => { setOpen(panel.hidden !== false) } }\n}\n\nfunction mobileRequest(path: string, init: RequestInit = {}): Promise<Response> {\n const target = new URL(path, location.href)\n if (target.origin !== location.origin) throw new TypeError('mobile extension requests must stay on the DSH origin')\n const headers = new Headers(init.headers)\n const method = (init.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const csrf = document.cookie.split(';').map(value => value.trim()).find(value => value.startsWith('dsh_ma_csrf='))?.slice(12)\n if (csrf !== undefined) headers.set('x-dsh-mobile-csrf', csrf)\n }\n return fetch(target, { ...init, headers, credentials: 'same-origin', cache: 'no-store', redirect: 'error' })\n}\n\nfunction installCustomAssets(): () => void {\n const legacyStyle = element('style'); legacyStyle.dataset.plugin = 'dsh-mobile-custom'; document.head.append(legacyStyle)\n const previous = window.dshMobile\n let legacyMount: MobileExtensionMount | undefined = queuedLegacyMount\n let legacySource = ''\n let legacyRoot: HTMLElement | undefined\n let legacyDispose: (() => void) | undefined\n const definitions = new Map<string, MobileClientDefinition>()\n const active = new Map<string, { readonly controller: AbortController; readonly dispose: () => void; readonly surfaces: Map<string, { readonly dispose: () => void; readonly container: HTMLElement }> }>()\n const styleNodes = new Map<string, HTMLStyleElement>()\n const styleEtags = new Map<string, string>()\n const scriptDigests = new Map<string, string>()\n let manifestEtag = ''\n let expectedDefinitionId: string | undefined\n const SURFACE_HOST_STYLES: Readonly<Record<string, string>> = {\n 'sidebar-action': 'position:fixed;z-index:1100;top:calc(env(safe-area-inset-top) + 8px);left:8px;display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'header-action': 'position:fixed;z-index:1100;top:calc(env(safe-area-inset-top) + 8px);right:8px;display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'composer-dock': 'position:fixed;z-index:1100;bottom:calc(env(safe-area-inset-bottom) + 8px);left:50%;transform:translateX(-50%);display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'settings-section': 'position:fixed;z-index:1100;inset:auto 8px calc(env(safe-area-inset-bottom) + 72px) 8px;max-height:40vh;overflow:auto;pointer-events:none',\n }\n const surfaceHost = (placement: string): HTMLElement | undefined => {\n const existing = document.querySelector<HTMLElement>(`[data-dsh-mobile-surface-host=\"${placement}\"]`)\n if (existing !== null) return existing\n const style = SURFACE_HOST_STYLES[placement]\n if (style === undefined) return undefined\n const host = element('div'); host.dataset.dshMobileSurfaceHost = placement; host.style.cssText = style\n document.body.append(host); return host\n }\n const shellLayer = (): HTMLElement => {\n const existing = document.querySelector<HTMLElement>('[data-dsh-mobile-extension-layer]')\n if (existing !== null) return existing\n const layer = element('div'); layer.dataset.dshMobileExtensionLayer = 'true'; layer.style.cssText = 'position:fixed;inset:0;z-index:1200;pointer-events:none;overflow:hidden'\n document.body.append(layer); return layer\n }\n const toast = (message: string): void => {\n const node = element('div'); node.textContent = message; node.style.cssText = 'position:absolute;top:16px;left:50%;transform:translateX(-50%);padding:9px 14px;border-radius:999px;background:#1f2937;color:white;font:14px system-ui;pointer-events:auto;box-shadow:0 8px 24px #0003'\n shellLayer().append(node); window.setTimeout(() => node.remove(), 2600)\n }\n const materializeNativeFile = (value: unknown): unknown => {\n if (typeof value !== 'object' || value === null || !('base64' in value) || !('name' in value)) return value\n const candidate = value as { base64?: unknown; name?: unknown; type?: unknown }\n if (typeof candidate.base64 !== 'string' || typeof candidate.name !== 'string') return value\n try {\n const encoded = atob(candidate.base64)\n const bytes = Uint8Array.from(encoded, character => character.charCodeAt(0))\n return new File([bytes], candidate.name, { type: typeof candidate.type === 'string' ? candidate.type : 'application/octet-stream' })\n } catch {\n return value\n }\n }\n const invokeNative = async (action: string, input?: unknown): Promise<unknown> => {\n const bridge = window.__DSH_MOBILE_NATIVE__\n if (bridge !== undefined) return materializeNativeFile(await bridge.invoke(action, input))\n if (action === 'share' && typeof navigator.share === 'function') { await navigator.share((input ?? {}) as ShareData); return { ok: true } }\n if (action === 'clipboard.read' && navigator.clipboard !== undefined) return { text: await navigator.clipboard.readText() }\n if (action === 'clipboard.write' && navigator.clipboard !== undefined) { await navigator.clipboard.writeText(typeof input === 'object' && input !== null && 'text' in input ? String((input as { text: unknown }).text) : ''); return { ok: true } }\n if (action === 'files.pick' || action === 'camera.capture') {\n const inputElement = element('input'); inputElement.type = 'file'; inputElement.accept = action === 'camera.capture' ? 'image/*' : '*/*'; if (action === 'camera.capture') inputElement.capture = 'environment';\n return new Promise<File | undefined>(resolve => { inputElement.onchange = () => resolve(inputElement.files?.[0]); inputElement.click() })\n }\n throw new Error('native capability is unavailable')\n }\n const makeApi = (id: string, controller: AbortController): MobileClientApi => {\n const surfaces = active.get(id)?.surfaces ?? new Map()\n const mountSurface = (surface: MobileSurface): (() => void) => {\n if (!/^[a-z][a-z0-9-]{0,63}$/u.test(surface.id) || surface.label.length > 120) throw new Error('invalid mobile surface')\n const container = element('section'); container.dataset.dshMobileSurface = surface.id; container.hidden = surface.placement === 'page' || surface.placement === 'overlay'; container.style.cssText = surface.placement === 'page' || surface.placement === 'overlay' ? 'position:absolute;inset:0;overflow:auto;background:var(--dsw-alias-bg-layer-1,#fff);padding:16px;pointer-events:auto' : 'pointer-events:auto'\n const host = surface.placement === 'page' || surface.placement === 'overlay' ? shellLayer() : surfaceHost(surface.placement) ?? shellLayer()\n host.append(container)\n const mounted = surface.mount(container)\n const dispose = (): void => { if (typeof mounted === 'function') mounted(); container.remove() }\n surfaces.set(surface.id, { dispose, container });\n return () => { if (surfaces.get(surface.id)?.dispose === dispose) surfaces.delete(surface.id); dispose() }\n }\n return {\n host: {\n invoke: (action: string, input: unknown) => mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/actions/${encodeURIComponent(action)}`, { method: 'POST', body: JSON.stringify(input ?? {}) }).then(async response => { const value = await response.json() as unknown; if (!response.ok) throw new Error(typeof value === 'object' && value !== null && 'error' in value ? String((value as { error: unknown }).error) : `HTTP ${String(response.status)}`); return value }),\n fetch: (path: string, init?: RequestInit) => {\n if (!path.startsWith('/') || path.startsWith('//') || path.includes('://')\n || path.split('/').some(part => part === '..' || part === '.')) throw new TypeError('extension routes must be relative')\n return mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/routes${path}`, init)\n },\n },\n ui: { registerSurface: mountSurface, open: id => { const entry = surfaces.get(id); if (entry !== undefined) entry.container.hidden = false }, close: id => { const entry = surfaces.get(id); if (entry !== undefined) entry.container.hidden = true }, toast },\n native: { capabilities: async () => { const bridge = window.__DSH_MOBILE_NATIVE__; return bridge === undefined ? ['files.pick', 'camera.capture', 'share', 'clipboard.read', 'clipboard.write'] : bridge.capabilities() }, invoke: invokeNative },\n signal: controller.signal, document, window,\n }\n }\n const activateDefinition = async (definition: MobileClientDefinition): Promise<void> => {\n const previousActive = active.get(definition.id)\n const controller = new AbortController()\n const surfaces = new Map<string, { readonly dispose: () => void; readonly container: HTMLElement }>()\n active.set(definition.id, { controller, surfaces, dispose: () => { controller.abort(); for (const surface of surfaces.values()) surface.dispose(); surfaces.clear() } })\n try {\n const cleanup = await definition.activate(makeApi(definition.id, controller))\n const current = active.get(definition.id)\n if (current === undefined || current.controller !== controller) { if (typeof cleanup === 'function') cleanup(); return }\n const oldDispose = current.dispose\n active.set(definition.id, { ...current, dispose: () => { if (typeof cleanup === 'function') cleanup(); oldDispose() } })\n previousActive?.dispose()\n } catch {\n active.get(definition.id)?.dispose(); active.delete(definition.id); if (previousActive !== undefined) active.set(definition.id, previousActive)\n }\n }\n const define = (definition: MobileClientDefinition): void => {\n if (definition.apiVersion !== 1 || !/^[a-z][a-z0-9-]{0,63}$/u.test(definition.id) || typeof definition.activate !== 'function') return\n if (expectedDefinitionId !== undefined && definition.id !== expectedDefinitionId) return\n definitions.set(definition.id, definition)\n if (started) void activateDefinition(definition)\n }\n let started = false\n window.dshMobile = Object.freeze({ register: mount => { legacyMount = mount }, define })\n for (const definition of queuedDefinitions.splice(0)) define(definition)\n let legacyJsEtag = ''\n let legacyJsModified = ''\n const refreshLegacy = async (): Promise<void> => {\n try {\n const headers: Record<string, string> = {}\n if (legacyJsEtag !== '') headers['if-none-match'] = legacyJsEtag\n if (legacyJsModified !== '') headers['if-modified-since'] = legacyJsModified\n const response = await fetch('/mobile-access/custom.js', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (!response.ok) return\n legacyJsEtag = response.headers.get('etag') ?? ''\n legacyJsModified = response.headers.get('last-modified') ?? ''\n const next = await response.text(); if (next === legacySource) return; legacySource = next; legacyMount = undefined\n const script = element('script'); script.textContent = `${next}\\n//# sourceURL=dsh-mobile-custom.js`; document.head.append(script); script.remove()\n const mount = legacyMount as MobileExtensionMount | undefined\n if (mount === undefined) return\n const nextRoot = element('div'); nextRoot.dataset.dshMobileExtension = 'true'; document.body.append(nextRoot)\n const nextDispose = mount({ document, request: mobileRequest, root: nextRoot, window })\n legacyDispose?.(); legacyRoot?.remove(); legacyRoot = nextRoot; legacyDispose = typeof nextDispose === 'function' ? nextDispose : undefined\n } catch { /* Preserve the last good customization during reconnects. */ }\n }\n const refreshExtensions = async (): Promise<void> => {\n try {\n const headers: Record<string, string> = {}\n if (manifestEtag !== '') headers['if-none-match'] = manifestEtag\n const response = await fetch('/mobile-access/extensions/manifest', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (!response.ok) return\n manifestEtag = response.headers.get('etag') ?? ''\n const payload = await response.json() as { extensions?: unknown }\n const entries = Array.isArray(payload.extensions) ? payload.extensions as Record<string, unknown>[] : []\n const seen = new Set<string>()\n for (const entry of entries) {\n if (typeof entry.id !== 'string') continue\n seen.add(entry.id)\n const cssUrl = typeof entry.styleUrl === 'string' ? entry.styleUrl : undefined\n if (cssUrl !== undefined) {\n const cssHeaders: Record<string, string> = {}\n const storedEtag = styleEtags.get(entry.id)\n if (storedEtag !== undefined) cssHeaders['if-none-match'] = storedEtag\n const cssResponse = await fetch(cssUrl, { credentials: 'same-origin', cache: 'no-store', headers: cssHeaders })\n if (cssResponse.status === 304) { /* unchanged */ }\n else if (cssResponse.ok) {\n const nextEtag = cssResponse.headers.get('etag'); if (nextEtag !== null && nextEtag !== '') styleEtags.set(entry.id, nextEtag)\n const css = await cssResponse.text(); const oldStyle = styleNodes.get(entry.id)\n if (oldStyle?.textContent !== css) {\n const node = element('style'); node.dataset.dshMobileExtensionStyle = entry.id; node.textContent = css; document.head.append(node); styleNodes.set(entry.id, node); oldStyle?.remove()\n }\n } else continue\n }\n const scriptUrl = typeof entry.scriptUrl === 'string' ? entry.scriptUrl : undefined\n if (scriptUrl !== undefined) {\n const scriptHeaders: Record<string, string> = {}\n const storedDigest = scriptDigests.get(entry.id)\n if (storedDigest !== undefined) scriptHeaders['if-none-match'] = storedDigest\n const scriptResponse = await fetch(scriptUrl, { credentials: 'same-origin', cache: 'no-store', headers: scriptHeaders })\n if (scriptResponse.status === 304) { /* unchanged */ }\n else if (scriptResponse.ok) {\n const source = await scriptResponse.text(); const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(source)); const key = [...new Uint8Array(digest)].map(value => value.toString(16).padStart(2, '0')).join('');\n if (scriptDigests.get(entry.id) !== key) {\n scriptDigests.set(entry.id, key)\n expectedDefinitionId = entry.id\n try { const script = element('script'); script.textContent = `${source}\\n//# sourceURL=dsh-mobile-extension-${entry.id}.js`; document.head.append(script); script.remove() }\n finally { expectedDefinitionId = undefined }\n }\n } else continue\n }\n const definition = definitions.get(entry.id); if (definition !== undefined && !active.has(entry.id)) await activateDefinition(definition)\n }\n for (const [id, current] of active) if (!seen.has(id) && !definitions.has(id) && id !== 'legacy-custom') { current.dispose(); active.delete(id); styleNodes.get(id)?.remove(); styleNodes.delete(id); styleEtags.delete(id); scriptDigests.delete(id) }\n } catch { /* A temporary reconnect failure must not tear down the last good UI. */ }\n }\n started = true\n for (const definition of definitions.values()) void activateDefinition(definition)\n void refreshLegacy(); void refreshExtensions(); void refreshCssLegacy(legacyStyle)\n const timer = window.setInterval(() => { void refreshLegacy(); void refreshExtensions(); void refreshCssLegacy(legacyStyle) }, 3_000)\n return () => { clearInterval(timer); started = false; legacyDispose?.(); legacyRoot?.remove(); legacyStyle.remove(); for (const current of active.values()) current.dispose(); for (const node of styleNodes.values()) node.remove(); const layer = document.querySelector('[data-dsh-mobile-extension-layer]'); layer?.remove(); for (const host of document.querySelectorAll('[data-dsh-mobile-surface-host]')) host.remove(); if (previous === undefined) delete window.dshMobile; else window.dshMobile = previous }\n}\n\nlet cssEtag = ''\nlet cssModified = ''\nasync function refreshCssLegacy(style: HTMLStyleElement): Promise<void> {\n try {\n const headers: Record<string, string> = {}\n if (cssEtag !== '') headers['if-none-match'] = cssEtag\n if (cssModified !== '') headers['if-modified-since'] = cssModified\n const response = await fetch('/mobile-access/custom.css', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (response.ok) {\n cssEtag = response.headers.get('etag') ?? ''\n cssModified = response.headers.get('last-modified') ?? ''\n style.textContent = await response.text()\n }\n } catch { /* Preserve the last good style during reconnects. */ }\n}\n\nconst CONTROL_STYLES = `\n.dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:64px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}\n.dsh-mobile-control__panel{box-sizing:border-box;width:min(328px,calc(100vw - 32px));padding:16px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:18px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 18px 50px rgb(15 23 42 / 18%)}\n.dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}\n.dsh-mobile-control__access{display:flex;align-items:baseline;gap:6px;min-width:0;margin:0 0 12px}.dsh-mobile-control__access[hidden]{display:none}.dsh-mobile-control__access-label{flex:none;color:var(--dsw-alias-label-secondary,#606873);white-space:nowrap}.dsh-mobile-control__access-label::after{content:\":\"}.dsh-mobile-control__access-link{min-width:0;overflow:hidden;color:#2563eb;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__access-link:hover{text-decoration:underline}.dsh-mobile-control__qr{display:flex;justify-content:center;margin:0 0 12px}.dsh-mobile-control__qr[hidden]{display:none}.dsh-mobile-control__qr img{border-radius:12px;background:#fff;padding:8px}\n.dsh-mobile-control__status{margin:0 0 14px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#606873)}.dsh-mobile-control__status::before{display:inline-block;width:8px;height:8px;margin-right:7px;border-radius:50%;background:#98a1ad;content:\"\"}.dsh-mobile-control__status.is-running::before{background:#16a36a}.dsh-mobile-control__status.is-key{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;word-break:break-all}\n.dsh-mobile-control__extensions{margin:0 0 12px;color:var(--dsw-alias-label-secondary,#606873);font-size:12px}\n.dsh-mobile-control__actions{display:flex;flex-wrap:nowrap;gap:6px}.dsh-mobile-control__actions button{flex:1 1 0;min-width:0;min-height:40px;padding:8px 4px;border-radius:10px;font:12px/1.2 system-ui;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-mobile-control__secondary{border:1px solid var(--dsw-alias-border-normal,#cfd5dd);background:transparent;color:inherit}.dsh-mobile-control__primary{border:1px solid #2563eb;background:#2563eb;color:#fff}.dsh-mobile-control__actions button:disabled{cursor:not-allowed;opacity:.45}\n.dsh-mobile-control__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:calc(100% + 8px);height:34px;margin:4px -4px;padding:6px 2px 6px 10px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#16181d);font:14px/22px system-ui;cursor:pointer}.dsh-mobile-control__trigger:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}.dsh-mobile-control__trigger.is-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;justify-content:center;border-radius:50%}.dsh-mobile-control__trigger-icon{position:relative;box-sizing:border-box;flex:none;width:14px;height:19px;border:1.7px solid currentColor;border-radius:3px}.dsh-mobile-control__trigger-icon::after{position:absolute;right:4px;bottom:2px;width:4px;height:1.5px;border-radius:2px;background:currentColor;content:\"\"}.dsh-mobile-control__trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n.dsh-mobile-control__manage-row{display:flex;justify-content:space-between;gap:8px;margin-top:10px}.dsh-mobile-control__manage{flex:1 1 0;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:transparent;color:inherit;font:12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__devices{margin-top:10px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:10px;padding:8px;max-height:220px;overflow-y:auto}.dsh-mobile-control__device-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px;margin:0}.dsh-mobile-control__device{display:flex;align-items:center;gap:8px;padding:6px 2px}.dsh-mobile-control__device + .dsh-mobile-control__device{border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb)}.dsh-mobile-control__device-label{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.dsh-mobile-control__device-meta{flex:none;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;white-space:nowrap}.dsh-mobile-control__device-revoke{flex:none;min-height:28px;padding:4px 8px;border:1px solid #dc2626;border-radius:8px;background:transparent;color:#dc2626;font:12px/1.2 system-ui;cursor:pointer}\n`\n\n/** Mount the desktop control or mobile feature enhancements. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const loopback = isLoopbackHost(location.hostname) && !new URLSearchParams(location.search).has('dsh-mobile-preview')\n const style = element('style'); style.dataset.plugin = 'dsh-mobile'; style.textContent = loopback\n ? CONTROL_STYLES\n : NATIVE_MOBILE_STYLES\n document.head.append(style)\n if (!loopback) {\n const removeCustom = installCustomAssets()\n const removeSurface = installNativeMobileSurface()\n return () => { removeCustom(); removeSurface(); style.remove() }\n }\n const control = installControl()\n const disposeSlot = ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({ name: 'sidebar.footer.action', id: 'dsh-mobile' }, ({ wide }) => createElement('button', {\n 'aria-expanded': false,\n 'aria-label': '移动访问',\n className: `dsh-mobile-control__trigger${wide ? '' : ' is-rail'}`,\n type: 'button',\n title: '移动访问',\n onClick: control.toggle,\n }, createElement('span', { 'aria-hidden': true, className: 'dsh-mobile-control__trigger-icon' }), wide ? createElement('span', { className: 'dsh-mobile-control__trigger-label' }, '移动访问') : undefined)))\n return () => { disposeSlot(); control.remove(); style.remove() }\n }, 'dsh-mobile: stock mobile adaptation and local control')\n}\n\n/** Client services required by the mobile adaptation. */\nexport const inject: readonly string[] = ['slots']\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["createElement"],"sources":["../src/native-mobile.ts","../src/client.ts"],"sourcesContent":["/** Mobile feature and compatibility rules applied to DSH React surfaces. */\nexport const NATIVE_MOBILE_STYLES = `\n@media (max-width:720px) {\n html.dsh-native-mobile-active,html.dsh-native-mobile-active body { width:100%; height:100%; overflow:hidden; }\n html.dsh-native-mobile-active { --dsh-mobile-motion-duration:200ms; --dsh-mobile-motion-ease:cubic-bezier(.22,1,.36,1); }\n html.dsh-native-mobile-active :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]) { -webkit-tap-highlight-color:transparent; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [role=\"treeitem\"] { -webkit-tap-highlight-color:transparent; touch-action:manipulation; }\n html.dsh-native-mobile-active[data-dsh-mobile-input=\"touch\"] :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]):focus { outline:none !important; }\n html.dsh-native-mobile-active [role=\"tooltip\"] { display:none !important; }\n /* Touch has no persistent hover affordance: keep workspace rows neutral after a tap. */\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] { --dsw-alias-interactive-bg-hover:transparent !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [role=\"treeitem\"]:is(:hover,:active,:focus,[aria-selected=\"true\"]),\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_sessionRow\"][class*=\"_selected\"],\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_searchResultRow\"][class*=\"_selected\"] { background:transparent !important; outline:0 !important; box-shadow:none !important; }\n /* Sidebar row menus are hover-only on desktop. Touch has no hover, so keep\n the ellipsis action visible and give it a reliable hit target. */\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_rowActions\"] { display:inline-flex !important; align-items:center !important; gap:8px !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_sessionRow\"] [class*=\"_time\"] { display:none !important; }\n html.dsh-native-mobile-active [data-dsh-mobile-sidebar] [class*=\"_rowActions\"] button { box-sizing:border-box !important; width:32px !important; min-width:32px !important; height:32px !important; min-height:32px !important; }\n [data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }\n [data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }\n [data-dsh-mobile-center] > * { min-width:0 !important; }\n [data-dsh-mobile-header] { box-sizing:border-box !important; width:calc(100% - 16px) !important; margin:0 8px !important; min-width:0; padding-top:max(4px,env(safe-area-inset-top)) !important; padding-right:8px !important; padding-left:42px !important; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { box-sizing:border-box !important; display:flex !important; align-items:center !important; min-width:0; min-height:32px !important; height:32px !important; gap:6px !important; padding:0 6px !important; }\n [data-dsh-mobile-header] [class*=\"_titleCluster\"] { min-width:0; }\n [data-dsh-mobile-header] [class*=\"_crumbs\"] { min-width:0; overflow:hidden; }\n [data-dsh-mobile-header] [class*=\"_crumb\"] { max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { min-width:0; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-header] [class*=\"_headerUtilities\"] { gap:2px !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] { width:40px; min-width:40px; padding:0 !important; overflow:hidden; color:transparent; font-size:0 !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] > * { display:none !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"]::after { color:var(--dsw-text, #171a21); content:\"日志\"; font-size:11px; font-weight:600; }\n [data-dsh-mobile-header] [class*=\"_tabs\"] { box-sizing:border-box !important; width:max-content !important; max-width:calc(100% - 58px) !important; min-height:28px !important; height:28px !important; margin-top:0 !important; padding-left:6px !important; padding-right:6px !important; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_tab\"] { padding-bottom:5px !important; }\n [data-dsh-mobile-header] [class*=\"_tabs\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-sidebar] { position:fixed !important; z-index:240 !important; inset:0 auto 0 0 !important; width:0 !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar-root] { position:fixed !important; z-index:241 !important; inset:0 auto 0 0 !important; height:100dvh !important; transition:width 180ms var(--dsh-mobile-motion-ease),box-shadow 180ms ease !important; }\n [data-dsh-mobile-sidebar][data-open=\"true\"] [data-dsh-mobile-sidebar-root] { width:min(88vw,340px) !important; box-shadow:18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] { width:0 !important; border:0 !important; background:transparent !important; box-shadow:none !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :not(:has([data-dsh-mobile-toggle])) { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) { position:fixed !important; z-index:244 !important; top:env(safe-area-inset-top) !important; left:0 !important; box-sizing:border-box !important; width:50px !important; height:52px !important; padding:4px !important; border:0 !important; background:transparent !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) > :not([data-dsh-mobile-toggle]) { display:none !important; }\n [data-dsh-mobile-toggle] { width:44px !important; height:44px !important; min-width:44px !important; min-height:44px !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle] > svg[class*=\"_railFish\"] { transform:translateY(-4px) !important; }\n .dsh-native-mobile-backdrop { position:fixed; z-index:235; inset:0; border:0; background:rgb(15 23 42 / 32%); }\n .dsh-native-mobile-backdrop:not([hidden]) { animation:dsh-mobile-fade-in var(--dsh-mobile-motion-duration) ease-out; }\n .dsh-native-mobile-backdrop[hidden] { display:none; }\n [data-dsh-mobile-details] { position:fixed !important; z-index:250 !important; inset:0 0 0 auto !important; width:min(94vw,460px) !important; max-width:none !important; transform:translateX(100%); transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); background:var(--dsw-bg, #fff); box-shadow:-18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-details][data-open=\"true\"] { transform:translateX(0); }\n [data-dsh-mobile-handle] { display:none !important; }\n [data-dsh-mobile-settings] { flex-direction:column !important; width:100vw !important; height:100dvh !important; max-width:none !important; border-radius:0 !important; animation:dsh-mobile-panel-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-settings-nav] { flex:none !important; width:100% !important; padding:max(14px,env(safe-area-inset-top)) 12px 8px !important; gap:10px !important; border-bottom:1px solid var(--dsw-alias-border-subtle,#e8ebef); }\n [data-dsh-mobile-settings-nav] [class*=\"_navTitle\"] { padding:0 8px !important; font-size:18px !important; line-height:28px !important; }\n [data-dsh-mobile-settings-list] { flex-direction:row !important; gap:4px !important; overflow-x:auto !important; scrollbar-width:none; }\n [data-dsh-mobile-settings-list]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-settings-list] [class*=\"_navCell\"] { flex:0 0 auto !important; min-width:max-content !important; height:44px !important; padding:10px 12px !important; }\n [data-dsh-mobile-settings-list] [aria-current=\"true\"] { border-color:transparent !important; outline:0 !important; box-shadow:none !important; }\n [data-dsh-mobile-settings-content] { flex:1 1 auto !important; width:100% !important; min-height:0 !important; }\n [data-dsh-mobile-settings-header] { height:48px !important; min-height:48px !important; padding:10px 12px 6px !important; }\n [data-dsh-mobile-settings-header] [class*=\"_close\"] { width:36px !important; height:36px !important; }\n [data-dsh-mobile-settings-options] { box-sizing:border-box !important; width:100% !important; padding:4px 16px max(24px,env(safe-area-inset-bottom)) !important; overflow-x:hidden !important; }\n [data-dsh-mobile-settings-options] > * { width:100% !important; min-width:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] > [class*=\"_row\"] { flex-direction:column !important; align-items:stretch !important; gap:12px !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_rowText\"] { width:100% !important; padding-right:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { box-sizing:border-box !important; align-self:flex-start !important; justify-content:space-between !important; min-width:0 !important; min-height:44px !important; max-width:100% !important; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea,button) { max-width:100%; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea) { box-sizing:border-box; width:100%; min-width:0; }\n [data-dsh-mobile-settings-options] [class*=\"_head\"] { min-width:0; flex-wrap:wrap; }\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:dsh-mobile-view-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-center] textarea { font-size:16px !important; }\n /* Markdown tables use content-sized columns. Small tables fill the phone;\n wider tables keep readable cells and scroll inside their own region. */\n [data-dsh-mobile-table-scroll] { box-sizing:border-box; width:100%; max-width:100%; overflow-x:auto; overscroll-behavior-x:contain; -webkit-overflow-scrolling:touch; }\n [data-dsh-mobile-table-scroll] table { display:table !important; width:max-content !important; min-width:100% !important; max-width:none !important; table-layout:auto !important; }\n [data-dsh-mobile-table-scroll] :is(th,td) { box-sizing:border-box; min-width:8ch; max-width:32ch; overflow-wrap:anywhere; word-break:break-word; vertical-align:top; }\n [data-dsh-mobile-center] pre { max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] :is(img,video,canvas,svg) { max-width:100%; }\n [data-dsh-mobile-message-scroll] { box-sizing:border-box !important; width:100% !important; padding:8px 10px 20px !important; }\n [data-dsh-mobile-message-column] { box-sizing:border-box !important; width:100% !important; max-width:none !important; margin:0 !important; padding:0 !important; gap:10px !important; }\n [data-dsh-mobile-message-column] > * { width:100% !important; max-width:100% !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] { box-sizing:border-box !important; display:grid !important; grid-template-columns:16px minmax(0,1fr) !important; grid-auto-rows:auto !important; align-items:center !important; column-gap:6px !important; width:100% !important; height:auto !important; min-height:40px !important; padding:4px 0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_leading\"] { grid-column:1 !important; grid-row:1 !important; margin-right:0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_title\"] { grid-column:2 !important; grid-row:1 !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_sep\"],[class*=\"_separator\"]) { display:none !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_summary\"],[class*=\"_fileLink\"]) { grid-column:2 !important; grid-row:2 !important; width:100% !important; min-width:0 !important; max-width:100% !important; overflow:hidden !important; line-height:19px !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_summarySuffix\"] { grid-column:2 !important; grid-row:3 !important; margin-left:0 !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { display:grid !important; grid-template-columns:minmax(72px,30%) minmax(0,1fr) !important; gap:4px 10px !important; }\n [data-dsh-mobile-message-column] [class*=\"_ioSection\"] { grid-template-columns:1fr !important; row-gap:4px !important; }\n [data-dsh-mobile-message-column] [class*=\"_body\"] { max-width:100% !important; overflow-wrap:anywhere; }\n [data-dsh-mobile-center] [data-composer-card] ~ [class*=\"_root\"],\n [data-dsh-mobile-center] [data-composer-card] ~ * [class*=\"_root\"] { box-sizing:border-box !important; width:100% !important; max-width:100% !important; margin-bottom:-6px !important; padding:3px 4px 0 !important; font-size:11px !important; line-height:18px !important; white-space:normal !important; overflow:visible !important; text-overflow:clip !important; }\n [data-dsh-mobile-center] [data-composer-card] ~ [class*=\"_root\"] [class*=\"_sep\"],\n [data-dsh-mobile-center] [data-composer-card] ~ * [class*=\"_root\"] [class*=\"_sep\"] { margin:0 6px !important; }\n /* Message runtime details are inline on desktop. Give the clock/runtime\n label its own wrapping row on narrow screens so TTFT and throughput do\n not push the action buttons or clip at the viewport edge. */\n [data-dsh-mobile-center] [class*=\"_actions\"]:has(> [class*=\"_timeStart\"]),\n [data-dsh-mobile-center] [class*=\"_actions\"]:has(> [class*=\"_timeEnd\"]) { box-sizing:border-box !important; width:100% !important; flex-wrap:wrap !important; justify-content:flex-end !important; height:auto !important; min-height:28px !important; row-gap:2px !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"],\n [data-dsh-mobile-center] [class*=\"_timeEnd\"] { box-sizing:border-box !important; flex:1 1 100% !important; order:2 !important; min-width:0 !important; max-width:100% !important; padding:0 !important; line-height:20px !important; text-align:center !important; white-space:normal !important; overflow-wrap:anywhere !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"] { box-sizing:border-box !important; flex:1 1 100% !important; order:2 !important; min-width:0 !important; max-width:100% !important; padding:0 !important; line-height:20px !important; text-align:center !important; white-space:normal !important; overflow-wrap:anywhere !important; }\n [data-dsh-mobile-center] [class*=\"_timeStart\"] [class*=\"_runTimeDot\"],\n [data-dsh-mobile-center] [class*=\"_timeEnd\"] [class*=\"_runTimeDot\"] { margin:0 6px !important; }\n /* Keep the context meter's legend rows as readable label/value pairs.\n Generic mobile flex rules can otherwise place the rows side by side and\n break Chinese labels in the middle of a word. */\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] { width:min(264px,calc(100vw - 32px)) !important; min-width:0 !important; max-width:calc(100vw - 32px) !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] [class*=\"_rows\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] [class*=\"_rows\"] { display:block !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] [class*=\"_rows\"] > [class*=\"_row\"],\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] [class*=\"_rows\"] > [class*=\"_row\"] { display:flex !important; align-items:center !important; justify-content:space-between !important; width:100% !important; min-width:0 !important; white-space:nowrap !important; }\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"上下文\"] :is(dt,dd),\n [data-dsh-mobile-center] [role=\"dialog\"][aria-label*=\"Context\"] :is(dt,dd) { white-space:nowrap !important; word-break:keep-all !important; }\n .dsh-mobile-branch-toast { position:fixed; z-index:300; top:max(12px,env(safe-area-inset-top)); left:50%; max-width:calc(100vw - 32px); box-sizing:border-box; padding:7px 14px; border:1px solid rgb(15 23 42 / 10%); border-radius:999px; background:rgb(15 23 42 / 92%); color:#fff; font-size:13px; line-height:20px; text-align:center; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; opacity:0; pointer-events:none; transform:translate(-50%,-8px); transition:opacity 160ms ease,transform 160ms ease; }\n .dsh-mobile-branch-toast[data-visible=\"true\"] { opacity:1; transform:translate(-50%,0); }\n [data-dsh-mobile-center] [class*=\"_composer\"] { padding-left:8px !important; padding-right:8px !important; padding-bottom:max(8px,env(safe-area-inset-bottom)) !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_row\"] { display:flex !important; align-items:center !important; gap:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_tools\"] { flex:0 0 auto !important; width:auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] { flex:1 1 auto !important; min-width:0 !important; gap:6px !important; margin-left:auto !important; justify-content:flex-end !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] [class*=\"_root\"]:has(button[aria-label^=\"选择模型\"]) { flex:0 1 auto !important; width:auto !important; max-width:min(55vw,220px) !important; min-width:0 !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] { width:auto !important; max-width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] [class*=\"_triggerLabel\"] { max-width:clamp(120px,36vw,210px); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) > [class=\"\"]:last-child { display:none !important; }\n}\n@keyframes dsh-mobile-fade-in { from { opacity:0; } }\n@keyframes dsh-mobile-panel-in { from { opacity:.72; transform:translateY(6px); } }\n@keyframes dsh-mobile-view-in { from { opacity:.58; transform:translateY(5px); } }\n@media (max-width:420px) {\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { max-width:42vw; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { align-self:stretch !important; width:100% !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { grid-template-columns:1fr !important; }\n}\n@media (prefers-reduced-motion:reduce) {\n [data-dsh-mobile-sidebar-root],[data-dsh-mobile-details] { transition:none !important; }\n .dsh-native-mobile-backdrop:not([hidden]),[data-dsh-mobile-settings],\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:none !important; }\n}\n`\n\nfunction classToken(element: Element, suffix: string): boolean {\n return Array.from(element.classList).some(value => value.endsWith(suffix))\n}\n\nfunction firstByClassSuffix(root: ParentNode, suffix: string): HTMLElement | undefined {\n return Array.from(root.querySelectorAll<HTMLElement>('[class]')).find(element => classToken(element, suffix))\n}\n\n/** Add mobile semantics without replacing feature trees. */\nexport function installNativeMobileSurface(): () => void {\n document.documentElement.classList.add('dsh-native-mobile-active')\n const setInputMode = (mode: 'keyboard' | 'touch'): void => {\n document.documentElement.dataset.dshMobileInput = mode\n }\n const onPointerDown = (event: PointerEvent): void => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen') setInputMode('touch')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Tab' || event.key.startsWith('Arrow')) setInputMode('keyboard')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n const backdrop = document.createElement('button')\n backdrop.type = 'button'\n backdrop.className = 'dsh-native-mobile-backdrop'\n backdrop.hidden = true\n backdrop.setAttribute('aria-label', '关闭工作区导航')\n document.body.append(backdrop)\n const branchToast = document.createElement('div')\n branchToast.className = 'dsh-mobile-branch-toast'\n branchToast.setAttribute('role', 'status')\n branchToast.setAttribute('aria-live', 'polite')\n document.body.append(branchToast)\n let branchToastTimer = 0\n const showBranchToast = (): void => {\n const header = document.querySelector<HTMLElement>('[data-dsh-mobile-header]')\n const title = header === null ? undefined : header.querySelector<HTMLElement>('[class*=\"_crumbCurrent\"]')?.textContent?.trim()\n branchToast.textContent = title === undefined ? '当前分支' : `当前分支:${title}`\n branchToast.dataset.visible = 'true'\n if (branchToastTimer !== 0) window.clearTimeout(branchToastTimer)\n branchToastTimer = window.setTimeout(() => {\n branchToast.removeAttribute('data-visible')\n branchToastTimer = 0\n }, 1600)\n }\n const onBranchClick = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const branch = event.target.closest<HTMLButtonElement>('button[aria-label*=\"分支\"],button[aria-label*=\"Branch\"],button[aria-label*=\"branch\"]')\n if (branch === null || branch.hasAttribute('disabled') || branch.getAttribute('aria-disabled') === 'true') return\n window.setTimeout(showBranchToast, 80)\n }\n document.addEventListener('click', onBranchClick, true)\n let frame: HTMLElement | undefined\n let sidebar: HTMLElement | undefined\n let sidebarRoot: HTMLElement | undefined\n let toggle: HTMLButtonElement | undefined\n let viewArea: HTMLElement | undefined\n let scheduled = 0\n let transitionFrame = 0\n let transitionRestartFrame = 0\n let transitionTimer = 0\n let transitionTarget: HTMLElement | undefined\n const animateNavigation = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const trigger = event.target.closest<HTMLElement>('button,a,[role=\"tab\"],[aria-selected]')\n if (trigger === null || trigger.hasAttribute('disabled') || trigger.getAttribute('aria-disabled') === 'true') return\n if (trigger.getAttribute('aria-selected') === 'true' || trigger.getAttribute('aria-current') === 'true') return\n const settingsNavigation = trigger.closest('[data-dsh-mobile-settings-list]') !== null\n const conversationNavigation = trigger.matches('[role=\"tab\"]')\n const sidebarNavigation = trigger.closest('[data-dsh-mobile-sidebar-root]') !== null\n && trigger.closest('[data-dsh-mobile-toggle]') === null\n if (!settingsNavigation && !conversationNavigation && !sidebarNavigation) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n transitionFrame = requestAnimationFrame(() => {\n transitionFrame = 0\n const target = settingsNavigation\n ? document.querySelector<HTMLElement>('[data-dsh-mobile-settings-content]')\n : viewArea\n if (target === null || target === undefined) return\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n target.removeAttribute('data-dsh-mobile-view-transition')\n transitionRestartFrame = requestAnimationFrame(() => {\n transitionRestartFrame = 0\n transitionTarget = target\n target.dataset.dshMobileViewTransition = 'true'\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTimer = window.setTimeout(() => {\n target.removeAttribute('data-dsh-mobile-view-transition')\n if (transitionTarget === target) transitionTarget = undefined\n transitionTimer = 0\n }, 240)\n })\n })\n }\n document.addEventListener('click', animateNavigation)\n\n const sync = (): void => {\n scheduled = 0\n frame = firstByClassSuffix(document, '_frame')\n const dedicatedCenter = document.querySelector<HTMLElement>('.dshm-main') ?? undefined\n if (frame !== undefined) frame.dataset.dshMobileFrame = 'true'\n sidebar = frame === undefined\n ? document.querySelector<HTMLElement>('.dshm-drawer') ?? undefined\n : firstByClassSuffix(frame, '_sidebarCol')\n const center = frame === undefined ? dedicatedCenter : firstByClassSuffix(frame, '_centerCol')\n const details = frame === undefined ? undefined : firstByClassSuffix(frame, '_detailsCol')\n const handle = frame === undefined ? undefined : firstByClassSuffix(frame, '_handle')\n if (center === undefined) return\n if (center !== undefined) {\n center.dataset.dshMobileCenter = 'true'\n center.querySelector<HTMLElement>('header')?.setAttribute('data-dsh-mobile-header', 'true')\n viewArea = firstByClassSuffix(center, '_viewArea')\n if (viewArea !== undefined) viewArea.dataset.dshMobileView = 'true'\n const conversation = center.querySelector<HTMLElement>('[data-conversation-scroll]')\n const messageColumn = conversation === null ? undefined : firstByClassSuffix(conversation, '_column')\n const messageScroll = messageColumn?.parentElement\n if (messageColumn !== undefined && messageScroll !== null && messageScroll !== undefined && classToken(messageScroll, '_scroll')) {\n messageColumn.dataset.dshMobileMessageColumn = 'true'\n messageScroll.dataset.dshMobileMessageScroll = 'true'\n }\n for (const table of center.querySelectorAll<HTMLTableElement>('table')) {\n const parent = table.parentElement\n if (parent?.dataset.dshMobileTableScroll === 'true') continue\n const wrapper = document.createElement('div')\n wrapper.dataset.dshMobileTableScroll = 'true'\n table.before(wrapper)\n wrapper.append(table)\n }\n }\n if (handle !== undefined) handle.dataset.dshMobileHandle = 'true'\n if (details !== undefined) {\n details.dataset.dshMobileDetails = 'true'\n const lastColumn = frame?.style.gridTemplateColumns.trim().split(/\\s+/).at(-1)\n details.dataset.open = String(lastColumn !== undefined && lastColumn !== '0px' && lastColumn !== '0')\n }\n const settings = Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"]')).find(dialog => {\n const directNav = Array.from(dialog.children).find(child => child instanceof HTMLElement && classToken(child, '_nav'))\n return directNav !== undefined\n })\n if (settings !== undefined) {\n settings.dataset.dshMobileSettings = 'true'\n const nav = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_nav')) as HTMLElement | undefined\n const content = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_content')) as HTMLElement | undefined\n if (nav !== undefined) {\n nav.dataset.dshMobileSettingsNav = 'true'\n firstByClassSuffix(nav, '_navList')?.setAttribute('data-dsh-mobile-settings-list', 'true')\n }\n if (content !== undefined) {\n content.dataset.dshMobileSettingsContent = 'true'\n firstByClassSuffix(content, '_header')?.setAttribute('data-dsh-mobile-settings-header', 'true')\n firstByClassSuffix(content, '_options')?.setAttribute('data-dsh-mobile-settings-options', 'true')\n }\n }\n if (sidebar === undefined) return\n sidebar.dataset.dshMobileSidebar = 'true'\n toggle = firstByClassSuffix(sidebar, '_toggle') as HTMLButtonElement | undefined\n let candidate = toggle?.parentElement\n while (candidate !== undefined && candidate !== null && candidate !== sidebar && !classToken(candidate, '_root')) candidate = candidate.parentElement\n sidebarRoot = candidate !== sidebar && candidate !== null ? candidate : undefined\n if (sidebarRoot === undefined) return\n sidebarRoot.dataset.dshMobileSidebarRoot = 'true'\n if (toggle !== undefined) toggle.dataset.dshMobileToggle = 'true'\n const collapsed = classToken(sidebarRoot, '_collapsed')\n sidebar.dataset.open = String(!collapsed)\n backdrop.hidden = collapsed\n }\n const schedule = (): void => { if (scheduled === 0) scheduled = requestAnimationFrame(sync) }\n const observer = new MutationObserver(schedule)\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] })\n backdrop.addEventListener('click', () => { if (sidebar?.dataset.open === 'true') toggle?.click() })\n sync()\n return () => {\n observer.disconnect()\n document.removeEventListener('click', onBranchClick, true)\n if (branchToastTimer !== 0) window.clearTimeout(branchToastTimer)\n branchToast.remove()\n if (scheduled !== 0) cancelAnimationFrame(scheduled)\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', animateNavigation)\n backdrop.remove()\n document.documentElement.classList.remove('dsh-native-mobile-active')\n delete document.documentElement.dataset.dshMobileInput\n }\n}\n","import { createElement } from 'react'\nimport { installNativeMobileSurface, NATIVE_MOBILE_STYLES } from './native-mobile.js'\n\ninterface ClientContext {\n effect(effect: () => void | (() => void), label?: string): void\n slots: {\n inject(key: string, callback: () => (() => void)): () => void\n register(options: { name: string; id: string }, component: (props: { wide: boolean }) => unknown): () => void\n }\n}\n\ninterface MobileExtensionContext {\n readonly document: Document\n readonly request: (path: string, init?: RequestInit) => Promise<Response>\n readonly root: HTMLElement\n readonly window: Window\n}\n\ntype MobileExtensionMount = (context: MobileExtensionContext) => void | (() => void)\ntype MobileSurfacePlacement = 'page' | 'sidebar-action' | 'header-action' | 'composer-dock' | 'settings-section' | 'overlay'\ninterface MobileSurface {\n readonly id: string\n readonly placement: MobileSurfacePlacement\n readonly label: string\n mount(container: HTMLElement): void | (() => void)\n}\ninterface MobileClientApi {\n readonly host: {\n invoke(action: string, input: unknown): Promise<unknown>\n fetch(path: string, init?: RequestInit): Promise<Response>\n }\n readonly ui: {\n registerSurface(surface: MobileSurface): () => void\n open(surfaceId: string): void\n close(surfaceId: string): void\n toast(message: string): void\n }\n readonly native: {\n capabilities(): Promise<readonly string[]>\n invoke(action: string, input?: unknown): Promise<unknown>\n }\n readonly signal: AbortSignal\n readonly document: Document\n readonly window: Window\n}\ninterface MobileClientDefinition {\n readonly apiVersion: 1\n readonly id: string\n activate(api: MobileClientApi): void | (() => void) | Promise<void | (() => void)>\n}\n\ndeclare global {\n interface Window {\n dshMobile?: {\n register(mount: MobileExtensionMount): void\n define(definition: MobileClientDefinition): void\n }\n __DSH_MOBILE_FRONTEND__?: 'dedicated'\n __DSH_MOBILE_NATIVE__?: {\n capabilities(): Promise<readonly string[]> | readonly string[]\n invoke(action: string, input?: unknown): Promise<unknown>\n }\n }\n}\n\nconst queuedDefinitions: MobileClientDefinition[] = []\nlet queuedLegacyMount: MobileExtensionMount | undefined\nif (typeof window !== 'undefined' && window.dshMobile === undefined) {\n window.dshMobile = {\n register: mount => { queuedLegacyMount = mount },\n define: definition => { queuedDefinitions.push(definition) },\n }\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]'\n}\n\nfunction element<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag)\n if (className !== undefined) node.className = className\n return node\n}\n\nasync function requestJson(path: string, init?: RequestInit): Promise<Record<string, unknown>> {\n const response = await fetch(path, { ...init, headers: { 'content-type': 'application/json', ...init?.headers } })\n const body = await response.json() as Record<string, unknown>\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction installControl(): { remove: () => void; toggle: () => void } {\n const root = element('div', 'dsh-mobile-control')\n const panel = element('section', 'dsh-mobile-control__panel'); panel.hidden = true\n panel.setAttribute('aria-label', '移动访问')\n const header = element('header', 'dsh-mobile-control__header')\n const title = element('h2'); title.textContent = '移动访问'\n const close = element('button', 'dsh-mobile-control__close'); close.type = 'button'; close.textContent = '×'; close.setAttribute('aria-label', '收起移动访问')\n const access = element('div', 'dsh-mobile-control__access'); access.hidden = true\n const accessLabel = element('span', 'dsh-mobile-control__access-label'); accessLabel.textContent = '浏览器访问'\n const accessLink = element('a', 'dsh-mobile-control__access-link'); accessLink.target = '_blank'; accessLink.rel = 'noreferrer'\n access.append(accessLabel, accessLink)\n const qrBox = element('div', 'dsh-mobile-control__qr'); qrBox.hidden = true\n const status = element('p', 'dsh-mobile-control__status'); status.textContent = '正在读取状态…'\n const extensionStatus = element('p', 'dsh-mobile-control__extensions'); extensionStatus.hidden = true\n const actions = element('div', 'dsh-mobile-control__actions')\n const toggle = element('button', 'dsh-mobile-control__secondary'); toggle.type = 'button'\n const pair = element('button', 'dsh-mobile-control__primary'); pair.type = 'button'; pair.textContent = '生成并复制密钥'\n const linkPair = element('button', 'dsh-mobile-control__secondary'); linkPair.type = 'button'; linkPair.textContent = '复制配对链接'\n const manageRow = element('div', 'dsh-mobile-control__manage-row')\n const manageDevices = element('button', 'dsh-mobile-control__manage'); manageDevices.type = 'button'; manageDevices.textContent = '管理配对设备'\n const resetAll = element('button', 'dsh-mobile-control__manage'); resetAll.type = 'button'; resetAll.textContent = '清除所有设备'\n manageRow.append(manageDevices, resetAll)\n const devicePanel = element('div', 'dsh-mobile-control__devices'); devicePanel.hidden = true\n header.append(title, close); actions.append(toggle, pair, linkPair); panel.append(header, access, qrBox, status, extensionStatus, actions, manageRow, devicePanel); root.append(panel); document.body.append(root)\n let running = false\n let origin = ''\n const setOpen = (open: boolean): void => {\n panel.hidden = !open\n for (const trigger of document.querySelectorAll('.dsh-mobile-control__trigger')) trigger.setAttribute('aria-expanded', String(open))\n }\n const render = (data: Record<string, unknown>): void => {\n running = data.running === true\n origin = running && typeof data.origin === 'string' ? data.origin : ''\n access.hidden = origin === ''\n accessLink.href = origin\n accessLink.textContent = origin\n accessLink.title = origin\n status.classList.toggle('is-running', running)\n status.textContent = running ? '移动访问已开启。' : '已关闭。DSH 仍只在本机可用。'\n const extensionData = data.extensions\n if (extensionData !== null && typeof extensionData === 'object') {\n const loaded = typeof (extensionData as { loaded?: unknown }).loaded === 'number' ? (extensionData as { loaded: number }).loaded : 0\n const failed = typeof (extensionData as { failed?: unknown }).failed === 'number' ? (extensionData as { failed: number }).failed : 0\n extensionStatus.hidden = false\n extensionStatus.textContent = failed === 0 ? `扩展:${String(loaded)} 个已加载` : `扩展:${String(loaded)} 个已加载,${String(failed)} 个加载失败`\n } else extensionStatus.hidden = true\n if (!running) qrBox.hidden = true\n toggle.textContent = running ? '关闭移动访问' : '开启移动访问'\n pair.disabled = !running\n linkPair.disabled = !running\n manageDevices.disabled = !running\n resetAll.disabled = !running\n }\n const showQr = (svg: string): void => {\n qrBox.replaceChildren()\n if (svg === '') { qrBox.hidden = true; return }\n const image = element('img')\n image.alt = '配对二维码'\n image.width = 176\n image.height = 176\n image.src = `data:image/svg+xml;base64,${btoa(svg)}`\n qrBox.hidden = false\n qrBox.append(image)\n }\n const openPairing = (target: 'key' | 'link'): void => {\n void requestJson('/api/mobile-access/pairing/open', { method: 'POST', body: '{}' }).then(async data => {\n const value = target === 'key'\n ? (typeof data.appKey === 'string' ? data.appKey : '')\n : (typeof data.pairUrl === 'string' ? data.pairUrl : '')\n showQr(typeof data.qrSvg === 'string' ? data.qrSvg : '')\n if (value === '') { status.textContent = '无法生成配对密钥。'; return }\n try {\n await navigator.clipboard.writeText(value)\n status.textContent = target === 'key'\n ? '配对密钥已复制,请粘贴到 Android App。'\n : '配对链接已复制,发给手机后 App 粘贴或浏览器打开即可配对。'\n } catch {\n status.textContent = `请复制${target === 'key' ? '配对密钥' : '配对链接'}:${value}`\n status.classList.add('is-key')\n }\n }, error => { status.textContent = String(error) }).finally(() => {\n pair.disabled = !running\n linkPair.disabled = !running\n })\n }\n toggle.addEventListener('click', () => { toggle.disabled = true; void requestJson('/api/mobile-access/control', { method: 'POST', body: JSON.stringify({ running: !running }) }).then(render, error => { status.textContent = String(error) }).finally(() => { toggle.disabled = false }) })\n const formatTime = (ms: unknown): string => typeof ms === 'number' ? new Date(ms).toLocaleString() : ''\n const renderDevices = (data: Record<string, unknown>): void => {\n const devices = Array.isArray(data.devices) ? data.devices as Record<string, unknown>[] : []\n devicePanel.replaceChildren()\n if (devices.length === 0) {\n const empty = element('p', 'dsh-mobile-control__device-empty'); empty.textContent = '暂无配对设备。'\n devicePanel.append(empty)\n return\n }\n for (const device of devices) {\n const row = element('div', 'dsh-mobile-control__device')\n const label = element('span', 'dsh-mobile-control__device-label')\n label.textContent = typeof device.label === 'string' ? device.label : '设备'\n const meta = element('span', 'dsh-mobile-control__device-meta'); meta.textContent = `到期 ${formatTime(device.expiresAt)}`\n const revoke = element('button', 'dsh-mobile-control__device-revoke'); revoke.type = 'button'; revoke.textContent = '撤销'\n const id = typeof device.id === 'string' ? device.id : ''\n revoke.addEventListener('click', () => {\n void requestJson('/api/mobile-access/devices/revoke', { method: 'POST', body: JSON.stringify({ deviceId: id }) })\n .then(loadDevices, error => { status.textContent = String(error) })\n })\n row.append(label, meta, revoke)\n devicePanel.append(row)\n }\n }\n const loadDevices = (): void => {\n void requestJson('/api/mobile-access/devices').then(renderDevices, error => { status.textContent = String(error) })\n }\n manageDevices.addEventListener('click', () => {\n const show = devicePanel.hidden\n devicePanel.hidden = !show\n if (show) loadDevices()\n })\n resetAll.addEventListener('click', () => {\n if (!window.confirm('确定要移除所有配对设备吗?此操作会立即终止已连接设备。')) return\n void requestJson('/api/mobile-access/devices/reset', { method: 'POST', body: JSON.stringify({ confirm: true }) })\n .then(loadDevices, error => { status.textContent = String(error) })\n })\n pair.addEventListener('click', () => { pair.disabled = true; openPairing('key') })\n linkPair.addEventListener('click', () => { linkPair.disabled = true; openPairing('link') })\n close.addEventListener('click', () => { setOpen(false) })\n const dismiss = (event: PointerEvent): void => {\n if (panel.hidden || !(event.target instanceof Node)) return\n if (!panel.contains(event.target) && !document.querySelector('.dsh-mobile-control__trigger')?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', dismiss)\n void requestJson('/api/mobile-access/control').then(render, error => { status.textContent = String(error) })\n return { remove: () => { document.removeEventListener('pointerdown', dismiss); root.remove() }, toggle: () => { setOpen(panel.hidden !== false) } }\n}\n\nfunction mobileRequest(path: string, init: RequestInit = {}): Promise<Response> {\n const target = new URL(path, location.href)\n if (target.origin !== location.origin) throw new TypeError('mobile extension requests must stay on the DSH origin')\n const headers = new Headers(init.headers)\n const method = (init.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const csrf = document.cookie.split(';').map(value => value.trim()).find(value => value.startsWith('dsh_ma_csrf='))?.slice(12)\n if (csrf !== undefined) headers.set('x-dsh-mobile-csrf', csrf)\n }\n return fetch(target, { ...init, headers, credentials: 'same-origin', cache: 'no-store', redirect: 'error' })\n}\n\nfunction installCustomAssets(): () => void {\n const legacyStyle = element('style'); legacyStyle.dataset.plugin = 'dsh-mobile-custom'; document.head.append(legacyStyle)\n const previous = window.dshMobile\n let legacyMount: MobileExtensionMount | undefined = queuedLegacyMount\n let legacySource = ''\n let legacyRoot: HTMLElement | undefined\n let legacyDispose: (() => void) | undefined\n const definitions = new Map<string, MobileClientDefinition>()\n const active = new Map<string, { readonly controller: AbortController; readonly dispose: () => void; readonly surfaces: Map<string, { readonly dispose: () => void; readonly container: HTMLElement }> }>()\n const styleNodes = new Map<string, HTMLStyleElement>()\n const styleEtags = new Map<string, string>()\n const scriptDigests = new Map<string, string>()\n let manifestEtag = ''\n let expectedDefinitionId: string | undefined\n const SURFACE_HOST_STYLES: Readonly<Record<string, string>> = {\n 'sidebar-action': 'position:fixed;z-index:1100;top:calc(env(safe-area-inset-top) + 8px);left:8px;display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'header-action': 'position:fixed;z-index:1100;top:calc(env(safe-area-inset-top) + 8px);right:8px;display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'composer-dock': 'position:fixed;z-index:1100;bottom:calc(env(safe-area-inset-bottom) + 8px);left:50%;transform:translateX(-50%);display:flex;flex-direction:column;gap:6px;pointer-events:none',\n 'settings-section': 'position:fixed;z-index:1100;inset:auto 8px calc(env(safe-area-inset-bottom) + 72px) 8px;max-height:40vh;overflow:auto;pointer-events:none',\n }\n const surfaceHost = (placement: string): HTMLElement | undefined => {\n const existing = document.querySelector<HTMLElement>(`[data-dsh-mobile-surface-host=\"${placement}\"]`)\n if (existing !== null) return existing\n const style = SURFACE_HOST_STYLES[placement]\n if (style === undefined) return undefined\n const host = element('div'); host.dataset.dshMobileSurfaceHost = placement; host.style.cssText = style\n document.body.append(host); return host\n }\n const shellLayer = (): HTMLElement => {\n const existing = document.querySelector<HTMLElement>('[data-dsh-mobile-extension-layer]')\n if (existing !== null) return existing\n const layer = element('div'); layer.dataset.dshMobileExtensionLayer = 'true'; layer.style.cssText = 'position:fixed;inset:0;z-index:1200;pointer-events:none;overflow:hidden'\n document.body.append(layer); return layer\n }\n const toast = (message: string): void => {\n const node = element('div'); node.textContent = message; node.style.cssText = 'position:absolute;top:16px;left:50%;transform:translateX(-50%);padding:9px 14px;border-radius:999px;background:#1f2937;color:white;font:14px system-ui;pointer-events:auto;box-shadow:0 8px 24px #0003'\n shellLayer().append(node); window.setTimeout(() => node.remove(), 2600)\n }\n const materializeNativeFile = (value: unknown): unknown => {\n if (typeof value !== 'object' || value === null || !('base64' in value) || !('name' in value)) return value\n const candidate = value as { base64?: unknown; name?: unknown; type?: unknown }\n if (typeof candidate.base64 !== 'string' || typeof candidate.name !== 'string') return value\n try {\n const encoded = atob(candidate.base64)\n const bytes = Uint8Array.from(encoded, character => character.charCodeAt(0))\n return new File([bytes], candidate.name, { type: typeof candidate.type === 'string' ? candidate.type : 'application/octet-stream' })\n } catch {\n return value\n }\n }\n const invokeNative = async (action: string, input?: unknown): Promise<unknown> => {\n const bridge = window.__DSH_MOBILE_NATIVE__\n if (bridge !== undefined) return materializeNativeFile(await bridge.invoke(action, input))\n if (action === 'share' && typeof navigator.share === 'function') { await navigator.share((input ?? {}) as ShareData); return { ok: true } }\n if (action === 'clipboard.read' && navigator.clipboard !== undefined) return { text: await navigator.clipboard.readText() }\n if (action === 'clipboard.write' && navigator.clipboard !== undefined) { await navigator.clipboard.writeText(typeof input === 'object' && input !== null && 'text' in input ? String((input as { text: unknown }).text) : ''); return { ok: true } }\n if (action === 'files.pick' || action === 'camera.capture') {\n const inputElement = element('input'); inputElement.type = 'file'; inputElement.accept = action === 'camera.capture' ? 'image/*' : '*/*'; if (action === 'camera.capture') inputElement.capture = 'environment';\n return new Promise<File | undefined>(resolve => { inputElement.onchange = () => resolve(inputElement.files?.[0]); inputElement.click() })\n }\n throw new Error('native capability is unavailable')\n }\n const makeApi = (id: string, controller: AbortController): MobileClientApi => {\n const surfaces = active.get(id)?.surfaces ?? new Map()\n const mountSurface = (surface: MobileSurface): (() => void) => {\n if (!/^[a-z][a-z0-9-]{0,63}$/u.test(surface.id) || surface.label.length > 120) throw new Error('invalid mobile surface')\n const container = element('section'); container.dataset.dshMobileSurface = surface.id; container.hidden = surface.placement === 'page' || surface.placement === 'overlay'; container.style.cssText = surface.placement === 'page' || surface.placement === 'overlay' ? 'position:absolute;inset:0;overflow:auto;background:var(--dsw-alias-bg-layer-1,#fff);padding:16px;pointer-events:auto' : 'pointer-events:auto'\n const host = surface.placement === 'page' || surface.placement === 'overlay' ? shellLayer() : surfaceHost(surface.placement) ?? shellLayer()\n host.append(container)\n const mounted = surface.mount(container)\n const dispose = (): void => { if (typeof mounted === 'function') mounted(); container.remove() }\n surfaces.set(surface.id, { dispose, container });\n return () => { if (surfaces.get(surface.id)?.dispose === dispose) surfaces.delete(surface.id); dispose() }\n }\n return {\n host: {\n invoke: (action: string, input: unknown) => mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/actions/${encodeURIComponent(action)}`, { method: 'POST', body: JSON.stringify(input ?? {}) }).then(async response => { const value = await response.json() as unknown; if (!response.ok) throw new Error(typeof value === 'object' && value !== null && 'error' in value ? String((value as { error: unknown }).error) : `HTTP ${String(response.status)}`); return value }),\n fetch: (path: string, init?: RequestInit) => {\n if (!path.startsWith('/') || path.startsWith('//') || path.includes('://')\n || path.split('/').some(part => part === '..' || part === '.')) throw new TypeError('extension routes must be relative')\n return mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/routes${path}`, init)\n },\n },\n ui: { registerSurface: mountSurface, open: id => { const entry = surfaces.get(id); if (entry !== undefined) entry.container.hidden = false }, close: id => { const entry = surfaces.get(id); if (entry !== undefined) entry.container.hidden = true }, toast },\n native: { capabilities: async () => { const bridge = window.__DSH_MOBILE_NATIVE__; return bridge === undefined ? ['files.pick', 'camera.capture', 'share', 'clipboard.read', 'clipboard.write'] : bridge.capabilities() }, invoke: invokeNative },\n signal: controller.signal, document, window,\n }\n }\n const activateDefinition = async (definition: MobileClientDefinition): Promise<void> => {\n const previousActive = active.get(definition.id)\n const controller = new AbortController()\n const surfaces = new Map<string, { readonly dispose: () => void; readonly container: HTMLElement }>()\n active.set(definition.id, { controller, surfaces, dispose: () => { controller.abort(); for (const surface of surfaces.values()) surface.dispose(); surfaces.clear() } })\n try {\n const cleanup = await definition.activate(makeApi(definition.id, controller))\n const current = active.get(definition.id)\n if (current === undefined || current.controller !== controller) { if (typeof cleanup === 'function') cleanup(); return }\n const oldDispose = current.dispose\n active.set(definition.id, { ...current, dispose: () => { if (typeof cleanup === 'function') cleanup(); oldDispose() } })\n previousActive?.dispose()\n } catch {\n active.get(definition.id)?.dispose(); active.delete(definition.id); if (previousActive !== undefined) active.set(definition.id, previousActive)\n }\n }\n const define = (definition: MobileClientDefinition): void => {\n if (definition.apiVersion !== 1 || !/^[a-z][a-z0-9-]{0,63}$/u.test(definition.id) || typeof definition.activate !== 'function') return\n if (expectedDefinitionId !== undefined && definition.id !== expectedDefinitionId) return\n definitions.set(definition.id, definition)\n if (started) void activateDefinition(definition)\n }\n let started = false\n window.dshMobile = Object.freeze({ register: mount => { legacyMount = mount }, define })\n for (const definition of queuedDefinitions.splice(0)) define(definition)\n let legacyJsEtag = ''\n let legacyJsModified = ''\n const refreshLegacy = async (): Promise<void> => {\n try {\n const headers: Record<string, string> = {}\n if (legacyJsEtag !== '') headers['if-none-match'] = legacyJsEtag\n if (legacyJsModified !== '') headers['if-modified-since'] = legacyJsModified\n const response = await fetch('/mobile-access/custom.js', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (!response.ok) return\n legacyJsEtag = response.headers.get('etag') ?? ''\n legacyJsModified = response.headers.get('last-modified') ?? ''\n const next = await response.text(); if (next === legacySource) return; legacySource = next; legacyMount = undefined\n const script = element('script'); script.textContent = `${next}\\n//# sourceURL=dsh-mobile-custom.js`; document.head.append(script); script.remove()\n const mount = legacyMount as MobileExtensionMount | undefined\n if (mount === undefined) return\n const nextRoot = element('div'); nextRoot.dataset.dshMobileExtension = 'true'; document.body.append(nextRoot)\n const nextDispose = mount({ document, request: mobileRequest, root: nextRoot, window })\n legacyDispose?.(); legacyRoot?.remove(); legacyRoot = nextRoot; legacyDispose = typeof nextDispose === 'function' ? nextDispose : undefined\n } catch { /* Preserve the last good customization during reconnects. */ }\n }\n const refreshExtensions = async (): Promise<void> => {\n try {\n const headers: Record<string, string> = {}\n if (manifestEtag !== '') headers['if-none-match'] = manifestEtag\n const response = await fetch('/mobile-access/extensions/manifest', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (!response.ok) return\n manifestEtag = response.headers.get('etag') ?? ''\n const payload = await response.json() as { extensions?: unknown }\n const entries = Array.isArray(payload.extensions) ? payload.extensions as Record<string, unknown>[] : []\n const seen = new Set<string>()\n for (const entry of entries) {\n if (typeof entry.id !== 'string') continue\n seen.add(entry.id)\n const cssUrl = typeof entry.styleUrl === 'string' ? entry.styleUrl : undefined\n if (cssUrl !== undefined) {\n const cssHeaders: Record<string, string> = {}\n const storedEtag = styleEtags.get(entry.id)\n if (storedEtag !== undefined) cssHeaders['if-none-match'] = storedEtag\n const cssResponse = await fetch(cssUrl, { credentials: 'same-origin', cache: 'no-store', headers: cssHeaders })\n if (cssResponse.status === 304) { /* unchanged */ }\n else if (cssResponse.ok) {\n const nextEtag = cssResponse.headers.get('etag'); if (nextEtag !== null && nextEtag !== '') styleEtags.set(entry.id, nextEtag)\n const css = await cssResponse.text(); const oldStyle = styleNodes.get(entry.id)\n if (oldStyle?.textContent !== css) {\n const node = element('style'); node.dataset.dshMobileExtensionStyle = entry.id; node.textContent = css; document.head.append(node); styleNodes.set(entry.id, node); oldStyle?.remove()\n }\n } else continue\n }\n const scriptUrl = typeof entry.scriptUrl === 'string' ? entry.scriptUrl : undefined\n if (scriptUrl !== undefined) {\n const scriptHeaders: Record<string, string> = {}\n const storedDigest = scriptDigests.get(entry.id)\n if (storedDigest !== undefined) scriptHeaders['if-none-match'] = storedDigest\n const scriptResponse = await fetch(scriptUrl, { credentials: 'same-origin', cache: 'no-store', headers: scriptHeaders })\n if (scriptResponse.status === 304) { /* unchanged */ }\n else if (scriptResponse.ok) {\n const source = await scriptResponse.text(); const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(source)); const key = [...new Uint8Array(digest)].map(value => value.toString(16).padStart(2, '0')).join('');\n if (scriptDigests.get(entry.id) !== key) {\n scriptDigests.set(entry.id, key)\n expectedDefinitionId = entry.id\n try { const script = element('script'); script.textContent = `${source}\\n//# sourceURL=dsh-mobile-extension-${entry.id}.js`; document.head.append(script); script.remove() }\n finally { expectedDefinitionId = undefined }\n }\n } else continue\n }\n const definition = definitions.get(entry.id); if (definition !== undefined && !active.has(entry.id)) await activateDefinition(definition)\n }\n for (const [id, current] of active) if (!seen.has(id) && !definitions.has(id) && id !== 'legacy-custom') { current.dispose(); active.delete(id); styleNodes.get(id)?.remove(); styleNodes.delete(id); styleEtags.delete(id); scriptDigests.delete(id) }\n } catch { /* A temporary reconnect failure must not tear down the last good UI. */ }\n }\n started = true\n for (const definition of definitions.values()) void activateDefinition(definition)\n void refreshLegacy(); void refreshExtensions(); void refreshCssLegacy(legacyStyle)\n const timer = window.setInterval(() => { void refreshLegacy(); void refreshExtensions(); void refreshCssLegacy(legacyStyle) }, 3_000)\n return () => { clearInterval(timer); started = false; legacyDispose?.(); legacyRoot?.remove(); legacyStyle.remove(); for (const current of active.values()) current.dispose(); for (const node of styleNodes.values()) node.remove(); const layer = document.querySelector('[data-dsh-mobile-extension-layer]'); layer?.remove(); for (const host of document.querySelectorAll('[data-dsh-mobile-surface-host]')) host.remove(); if (previous === undefined) delete window.dshMobile; else window.dshMobile = previous }\n}\n\nlet cssEtag = ''\nlet cssModified = ''\nasync function refreshCssLegacy(style: HTMLStyleElement): Promise<void> {\n try {\n const headers: Record<string, string> = {}\n if (cssEtag !== '') headers['if-none-match'] = cssEtag\n if (cssModified !== '') headers['if-modified-since'] = cssModified\n const response = await fetch('/mobile-access/custom.css', { credentials: 'same-origin', cache: 'no-store', headers })\n if (response.status === 304) return\n if (response.ok) {\n cssEtag = response.headers.get('etag') ?? ''\n cssModified = response.headers.get('last-modified') ?? ''\n style.textContent = await response.text()\n }\n } catch { /* Preserve the last good style during reconnects. */ }\n}\n\nconst CONTROL_STYLES = `\n.dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:112px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}\n.dsh-mobile-control__panel{box-sizing:border-box;width:min(328px,calc(100vw - 32px));padding:16px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:18px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 18px 50px rgb(15 23 42 / 18%)}\n.dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}\n.dsh-mobile-control__access{display:flex;align-items:baseline;gap:6px;min-width:0;margin:0 0 12px}.dsh-mobile-control__access[hidden]{display:none}.dsh-mobile-control__access-label{flex:none;color:var(--dsw-alias-label-secondary,#606873);white-space:nowrap}.dsh-mobile-control__access-label::after{content:\":\"}.dsh-mobile-control__access-link{min-width:0;overflow:hidden;color:#2563eb;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__access-link:hover{text-decoration:underline}.dsh-mobile-control__qr{display:flex;justify-content:center;margin:0 0 12px}.dsh-mobile-control__qr[hidden]{display:none}.dsh-mobile-control__qr img{border-radius:12px;background:#fff;padding:8px}\n.dsh-mobile-control__status{margin:0 0 14px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#606873)}.dsh-mobile-control__status::before{display:inline-block;width:8px;height:8px;margin-right:7px;border-radius:50%;background:#98a1ad;content:\"\"}.dsh-mobile-control__status.is-running::before{background:#16a36a}.dsh-mobile-control__status.is-key{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;word-break:break-all}\n.dsh-mobile-control__extensions{margin:0 0 12px;color:var(--dsw-alias-label-secondary,#606873);font-size:12px}\n.dsh-mobile-control__actions{display:flex;flex-wrap:nowrap;gap:6px}.dsh-mobile-control__actions button{flex:1 1 0;min-width:0;min-height:40px;padding:8px 4px;border-radius:10px;font:12px/1.2 system-ui;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-mobile-control__secondary{border:1px solid var(--dsw-alias-border-normal,#cfd5dd);background:transparent;color:inherit}.dsh-mobile-control__primary{border:1px solid #2563eb;background:#2563eb;color:#fff}.dsh-mobile-control__actions button:disabled{cursor:not-allowed;opacity:.45}\n.dsh-mobile-control__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:calc(100% + 8px);height:34px;margin:4px -4px;padding:6px 2px 6px 10px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#16181d);font:14px/22px system-ui;cursor:pointer}.dsh-mobile-control__trigger:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}.dsh-mobile-control__trigger.is-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;justify-content:center;border-radius:50%}.dsh-mobile-control__trigger-icon{position:relative;box-sizing:border-box;flex:none;width:14px;height:19px;border:1.7px solid currentColor;border-radius:3px}.dsh-mobile-control__trigger-icon::after{position:absolute;right:4px;bottom:2px;width:4px;height:1.5px;border-radius:2px;background:currentColor;content:\"\"}.dsh-mobile-control__trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n.dsh-mobile-control__manage-row{display:flex;justify-content:space-between;gap:8px;margin-top:10px}.dsh-mobile-control__manage{flex:1 1 0;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:transparent;color:inherit;font:12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__devices{margin-top:10px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:10px;padding:8px;max-height:220px;overflow-y:auto}.dsh-mobile-control__device-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px;margin:0}.dsh-mobile-control__device{display:flex;align-items:center;gap:8px;padding:6px 2px}.dsh-mobile-control__device + .dsh-mobile-control__device{border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb)}.dsh-mobile-control__device-label{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.dsh-mobile-control__device-meta{flex:none;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;white-space:nowrap}.dsh-mobile-control__device-revoke{flex:none;min-height:28px;padding:4px 8px;border:1px solid #dc2626;border-radius:8px;background:transparent;color:#dc2626;font:12px/1.2 system-ui;cursor:pointer}\n`\n\n/** Mount the desktop control or mobile feature enhancements. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const loopback = isLoopbackHost(location.hostname) && !new URLSearchParams(location.search).has('dsh-mobile-preview')\n const style = element('style'); style.dataset.plugin = 'dsh-mobile'; style.textContent = loopback\n ? CONTROL_STYLES\n : NATIVE_MOBILE_STYLES\n document.head.append(style)\n if (!loopback) {\n const removeCustom = installCustomAssets()\n const removeSurface = installNativeMobileSurface()\n return () => { removeCustom(); removeSurface(); style.remove() }\n }\n const control = installControl()\n const disposeSlot = ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({ name: 'sidebar.footer.action', id: 'dsh-mobile' }, ({ wide }) => createElement('button', {\n 'aria-expanded': false,\n 'aria-label': '移动访问',\n className: `dsh-mobile-control__trigger${wide ? '' : ' is-rail'}`,\n type: 'button',\n title: '移动访问',\n onClick: control.toggle,\n }, createElement('span', { 'aria-hidden': true, className: 'dsh-mobile-control__trigger-icon' }), wide ? createElement('span', { className: 'dsh-mobile-control__trigger-label' }, '移动访问') : undefined)))\n return () => { disposeSlot(); control.remove(); style.remove() }\n }, 'dsh-mobile: stock mobile adaptation and local control')\n}\n\n/** Client services required by the mobile adaptation. */\nexport const inject: readonly string[] = ['slots']\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mobile",
3
- "version": "0.1.0-alpha.35",
3
+ "version": "0.1.0-alpha.36",
4
4
  "private": false,
5
5
  "description": "DeepSeek Harness 移动端适配与安全局域网访问插件,支持 Android App 和手机浏览器。",
6
6
  "type": "module",