dsh-mobile 0.1.0 → 0.1.2

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
@@ -16,7 +16,9 @@
16
16
 
17
17
  <p align="center"><a href="README.md">简体中文</a></p>
18
18
 
19
- > Alpha software. Android is the only supported native app; the iOS client remains an unpublished local experiment and is not built or released. This is a community plugin, not an official DeepSeek product.
19
+ > The native app currently supports Android only; the iOS client remains a local experiment and is not included in builds or releases. This is a DeepSeek Harness community plugin.
20
+ >
21
+ > This release adds compatibility with DeepSeek Harness 0.1.1 and improves mobile interaction and layout.
20
22
 
21
23
  <p align="center"><a href="https://github.com/saya-ch/dsh-mobile/releases"><strong>Download the Android app</strong></a></p>
22
24
 
@@ -41,7 +43,7 @@ A paired device is fully trusted and can operate the DSH on the computer. Use th
41
43
  With an installed `dsh` command:
42
44
 
43
45
  ```powershell
44
- dsh plugin --profile web add dsh-mobile@alpha
46
+ dsh plugin --profile web add dsh-mobile@latest
45
47
  dsh plugin --profile web exec dsh-mobile setup
46
48
  dsh --profile web
47
49
  ```
@@ -50,7 +52,7 @@ From a DeepSeek Harness source checkout:
50
52
 
51
53
  ```powershell
52
54
  corepack enable; pnpm install
53
- pnpm dsh plugin --profile web add dsh-mobile@alpha
55
+ pnpm dsh plugin --profile web add dsh-mobile@latest
54
56
  pnpm dsh plugin --profile web exec dsh-mobile setup
55
57
  pnpm dsh --profile web
56
58
  ```
@@ -134,7 +136,7 @@ See [SECURITY.md](SECURITY.md).
134
136
 
135
137
  | DSH Mobile | Verified DeepSeek Harness releases |
136
138
  | --- | --- |
137
- | `0.1.0` | `0.1.0-rc.5`, `0.1.0-rc.6`, `0.1.0-rc.7`, `0.1.1-rc.2` |
139
+ | `0.1.0–0.1.2` | `0.1.0-rc.5`, `0.1.0-rc.6`, `0.1.0-rc.7`, `0.1.1-rc.2` |
138
140
 
139
141
  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.
140
142
 
package/README.md CHANGED
@@ -21,7 +21,9 @@
21
21
  <a href="README.en.md">English</a>
22
22
  </p>
23
23
 
24
- > Alpha 版本,当前原生 App 仅支持 Android;iOS 客户端仍为未发布的本地开发实验,不进入构建与 Release。本项目为 DeepSeek Harness 社区插件。
24
+ > 当前原生 App 仅支持 Android;iOS 客户端尚处于本地实验阶段,暂不纳入构建与发布。本项目是 DeepSeek Harness 社区插件。
25
+ >
26
+ > 本次更新:适配 DeepSeek Harness 0.1.1,优化移动端交互与布局体验。
25
27
 
26
28
  <p align="center"><a href="https://github.com/saya-ch/dsh-mobile/releases"><strong>下载 Android App</strong></a></p>
27
29
 
@@ -46,7 +48,7 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
46
48
  已经安装 `dsh` 命令:
47
49
 
48
50
  ```powershell
49
- dsh plugin --profile web add dsh-mobile@alpha
51
+ dsh plugin --profile web add dsh-mobile@latest
50
52
  dsh plugin --profile web exec dsh-mobile setup
51
53
  dsh --profile web
52
54
  ```
@@ -55,7 +57,7 @@ dsh --profile web
55
57
 
56
58
  ```powershell
57
59
  corepack enable; pnpm install
58
- pnpm dsh plugin --profile web add dsh-mobile@alpha
60
+ pnpm dsh plugin --profile web add dsh-mobile@latest
59
61
  pnpm dsh plugin --profile web exec dsh-mobile setup
60
62
  pnpm dsh --profile web
61
63
  ```
@@ -140,7 +142,7 @@ flowchart LR
140
142
 
141
143
  | DSH Mobile | 已验证的 DeepSeek Harness |
142
144
  | ------------------ | ------------------------------------------ |
143
- | `0.1.0` | `0.1.0-rc.5`、`0.1.0-rc.6`、`0.1.0-rc.7`、`0.1.1-rc.2` |
145
+ | `0.1.0–0.1.2` | `0.1.0-rc.5`、`0.1.0-rc.6`、`0.1.0-rc.7`、`0.1.1-rc.2` |
144
146
 
145
147
  插件启动时会检查 DSH Host 版本和移动布局所需的前端依赖,遇到未经验证的版本会直接报错而不是带病启动;CI 也会持续跟踪 DSH 主分支的布局契约。升级 DSH 后如遇兼容提示,请先升级 DSH Mobile。
146
148
 
package/lib/client.js CHANGED
@@ -125,12 +125,15 @@ window.__ModuleLoader__.load({
125
125
  .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; }
126
126
  .dsh-mobile-branch-toast[data-visible="true"] { opacity:1; transform:translate(-50%,0); }
127
127
  [data-dsh-mobile-center] [class*="_composer"] { padding-left:8px !important; padding-right:8px !important; padding-bottom:max(8px,env(safe-area-inset-bottom)) !important; }
128
- [data-dsh-mobile-center] [class*="_card"]:has(textarea) [class*="_row"] { display:flex !important; align-items:center !important; gap:4px !important; }
129
- [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; }
130
- [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; }
131
- [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; }
132
- [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; }
133
- [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; }
128
+ /* The desktop composer intentionally wraps whole toolbar groups. On a phone,
129
+ dynamic model and status labels made that row alternate between one and
130
+ two lines. Keep two stable columns and let only the model label shrink. */
131
+ [data-dsh-mobile-composer-row] { display:grid !important; grid-template-columns:max-content minmax(0,1fr) !important; align-items:center !important; gap:4px 8px !important; }
132
+ [data-dsh-mobile-composer-tools] { display:flex !important; flex-wrap:nowrap !important; width:max-content !important; min-width:0 !important; max-width:max-content !important; gap:6px !important; }
133
+ [data-dsh-mobile-composer-trailing] { display:flex !important; flex-wrap:nowrap !important; width:100% !important; min-width:0 !important; max-width:100% !important; gap:6px !important; margin-left:0 !important; justify-content:flex-end !important; }
134
+ [data-dsh-mobile-composer-model] { flex:1 1 0 !important; width:auto !important; min-width:0 !important; max-width:none !important; }
135
+ [data-dsh-mobile-composer-model-trigger] { box-sizing:border-box !important; width:100% !important; max-width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }
136
+ [data-dsh-mobile-composer-model-label] { flex:1 1 auto !important; max-width:none !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }
134
137
  [data-dsh-mobile-center] [class*="_root"]:has(> [class*="_card"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }
135
138
  [data-dsh-mobile-center] [class*="_root"]:has(> [class*="_card"] textarea) > [class=""]:last-child { display:none !important; }
136
139
  }
@@ -270,6 +273,23 @@ window.__ModuleLoader__.load({
270
273
  table.before(wrapper);
271
274
  wrapper.append(table);
272
275
  }
276
+ const composerRow = center.querySelector("[data-composer-card]")?.querySelector(":scope > [data-input-scroll]")?.nextElementSibling;
277
+ if (composerRow instanceof HTMLElement) {
278
+ composerRow.dataset.dshMobileComposerRow = "true";
279
+ const groups = Array.from(composerRow.children).filter((child) => child instanceof HTMLElement);
280
+ const composerTools = groups[0];
281
+ const composerTrailing = groups.at(-1);
282
+ if (composerTools !== void 0) composerTools.dataset.dshMobileComposerTools = "true";
283
+ if (composerTrailing !== void 0 && composerTrailing !== composerTools) {
284
+ composerTrailing.dataset.dshMobileComposerTrailing = "true";
285
+ const modelTrigger = composerTrailing.querySelector("button[aria-label^=\"选择模型\"],button[aria-label^=\"Select model\"]");
286
+ if (modelTrigger !== null) {
287
+ modelTrigger.dataset.dshMobileComposerModelTrigger = "true";
288
+ modelTrigger.parentElement?.setAttribute("data-dsh-mobile-composer-model", "true");
289
+ modelTrigger.querySelector("[class*=\"_triggerLabel\"]")?.setAttribute("data-dsh-mobile-composer-model-label", "true");
290
+ }
291
+ }
292
+ }
273
293
  }
274
294
  if (handle !== void 0) handle.dataset.dshMobileHandle = "true";
275
295
  if (details !== void 0) {
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: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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"}
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 /* The desktop composer intentionally wraps whole toolbar groups. On a phone,\n dynamic model and status labels made that row alternate between one and\n two lines. Keep two stable columns and let only the model label shrink. */\n [data-dsh-mobile-composer-row] { display:grid !important; grid-template-columns:max-content minmax(0,1fr) !important; align-items:center !important; gap:4px 8px !important; }\n [data-dsh-mobile-composer-tools] { display:flex !important; flex-wrap:nowrap !important; width:max-content !important; min-width:0 !important; max-width:max-content !important; gap:6px !important; }\n [data-dsh-mobile-composer-trailing] { display:flex !important; flex-wrap:nowrap !important; width:100% !important; min-width:0 !important; max-width:100% !important; gap:6px !important; margin-left:0 !important; justify-content:flex-end !important; }\n [data-dsh-mobile-composer-model] { flex:1 1 0 !important; width:auto !important; min-width:0 !important; max-width:none !important; }\n [data-dsh-mobile-composer-model-trigger] { box-sizing:border-box !important; width:100% !important; max-width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }\n [data-dsh-mobile-composer-model-label] { flex:1 1 auto !important; max-width:none !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\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 const composerCard = center.querySelector<HTMLElement>('[data-composer-card]')\n const composerRow = composerCard?.querySelector<HTMLElement>(':scope > [data-input-scroll]')?.nextElementSibling\n if (composerRow instanceof HTMLElement) {\n composerRow.dataset.dshMobileComposerRow = 'true'\n const groups = Array.from(composerRow.children).filter((child): child is HTMLElement => child instanceof HTMLElement)\n const composerTools = groups[0]\n const composerTrailing = groups.at(-1)\n if (composerTools !== undefined) composerTools.dataset.dshMobileComposerTools = 'true'\n if (composerTrailing !== undefined && composerTrailing !== composerTools) {\n composerTrailing.dataset.dshMobileComposerTrailing = 'true'\n const modelTrigger = composerTrailing.querySelector<HTMLButtonElement>('button[aria-label^=\"选择模型\"],button[aria-label^=\"Select model\"]')\n if (modelTrigger !== null) {\n modelTrigger.dataset.dshMobileComposerModelTrigger = 'true'\n modelTrigger.parentElement?.setAttribute('data-dsh-mobile-composer-model', 'true')\n modelTrigger.querySelector<HTMLElement>('[class*=\"_triggerLabel\"]')?.setAttribute('data-dsh-mobile-composer-model-label', 'true')\n }\n }\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",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "description": "DeepSeek Harness 移动端适配与安全局域网访问插件,支持 Android App 和手机浏览器。",
6
6
  "type": "module",