@jingyi0605/codingns4dsh 0.1.2 → 0.1.7-rc.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.
Files changed (171) hide show
  1. package/README.en.md +4 -4
  2. package/README.md +14 -5
  3. package/data/build/dist/client/account-bar.js +57 -3
  4. package/data/build/dist/client/bundle.js +36246 -268
  5. package/data/build/dist/client/cli-slots.js +60 -18
  6. package/data/build/dist/client/dsh-h5-bootstrap.d.ts +2 -0
  7. package/data/build/dist/client/dsh-h5-bootstrap.js +79 -13
  8. package/data/build/dist/client/features/file-management-panel.d.ts +5 -0
  9. package/data/build/dist/client/features/file-management-panel.js +48 -0
  10. package/data/build/dist/client/features/file-management.d.ts +4 -0
  11. package/data/build/dist/client/features/file-management.js +50 -0
  12. package/data/build/dist/client/features/index.d.ts +10 -1
  13. package/data/build/dist/client/features/index.js +12 -1
  14. package/data/build/dist/client/features/login-protection-panel.js +1 -1
  15. package/data/build/dist/client/features/login-protection-session.d.ts +2 -0
  16. package/data/build/dist/client/features/login-protection-session.js +18 -0
  17. package/data/build/dist/client/features/peer-host.d.ts +4 -0
  18. package/data/build/dist/client/features/peer-host.js +89 -0
  19. package/data/build/dist/client/features/reverse-proxy-panel.js +23 -7
  20. package/data/build/dist/client/features/reverse-proxy.d.ts +1 -2
  21. package/data/build/dist/client/features/reverse-proxy.js +75 -5
  22. package/data/build/dist/client/features/types.d.ts +9 -0
  23. package/data/build/dist/client/features/workspace-session-enhancement-panel.js +10 -0
  24. package/data/build/dist/client/features/workspace-session-enhancement.js +18 -1
  25. package/data/build/dist/client/file-management-dom.d.ts +12 -0
  26. package/data/build/dist/client/file-management-dom.js +527 -0
  27. package/data/build/dist/client/git-management.js +24 -5
  28. package/data/build/dist/client/host-navigation.d.ts +29 -0
  29. package/data/build/dist/client/host-navigation.js +29 -0
  30. package/data/build/dist/client/host-router.d.ts +3 -0
  31. package/data/build/dist/client/host-router.js +2 -0
  32. package/data/build/dist/client/index.d.ts +6 -1
  33. package/data/build/dist/client/index.js +30 -10
  34. package/data/build/dist/client/locale.js +36 -7
  35. package/data/build/dist/client/peer-host-connection-button.d.ts +13 -0
  36. package/data/build/dist/client/peer-host-connection-button.js +69 -0
  37. package/data/build/dist/client/peer-host-management-api.d.ts +40 -0
  38. package/data/build/dist/client/peer-host-management-api.js +33 -0
  39. package/data/build/dist/client/peer-host-management-panel.d.ts +13 -0
  40. package/data/build/dist/client/peer-host-management-panel.js +181 -0
  41. package/data/build/dist/client/peer-host-native-session-ui.d.ts +60 -0
  42. package/data/build/dist/client/peer-host-native-session-ui.js +372 -0
  43. package/data/build/dist/client/peer-host-scoped-client.d.ts +67 -0
  44. package/data/build/dist/client/peer-host-scoped-client.js +316 -0
  45. package/data/build/dist/client/peer-host-session-controller.d.ts +30 -0
  46. package/data/build/dist/client/peer-host-session-controller.js +95 -0
  47. package/data/build/dist/client/quick-phrase-slot.js +14 -0
  48. package/data/build/dist/client/remote-web-context.js +26 -4
  49. package/data/build/dist/client/session-changed-files-view.d.ts +15 -0
  50. package/data/build/dist/client/session-changed-files-view.js +337 -0
  51. package/data/build/dist/client/settings-bridge.d.ts +14 -4
  52. package/data/build/dist/client/settings-bridge.js +59 -12
  53. package/data/build/dist/client/settings-section.js +17 -4
  54. package/data/build/dist/client/subscription-slot.js +21 -8
  55. package/data/build/dist/client/workspace-session-rightbar-dom.d.ts +28 -0
  56. package/data/build/dist/client/workspace-session-rightbar-dom.js +291 -0
  57. package/data/build/dist/dsh-capabilities/client/config-forms-adapter.js +25 -33
  58. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.d.ts +7 -1
  59. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.js +34 -11
  60. package/data/build/dist/dsh-capabilities/matrix.js +9 -0
  61. package/data/build/dist/dsh-capabilities/routes.js +35 -0
  62. package/data/build/dist/dsh-capabilities/settings-store.d.ts +12 -0
  63. package/data/build/dist/dsh-capabilities/settings-store.js +34 -0
  64. package/data/build/dist/dsh-capabilities/types.d.ts +1 -1
  65. package/data/build/dist/features/host-router.d.ts +26 -0
  66. package/data/build/dist/features/host-router.js +110 -0
  67. package/data/build/dist/features/registry.js +3 -0
  68. package/data/build/dist/host/cli-adapters/codex-driver.d.ts +13 -1
  69. package/data/build/dist/host/cli-adapters/codex-driver.js +528 -72
  70. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +21 -2
  71. package/data/build/dist/host/cli-adapters/command-code-driver.js +408 -105
  72. package/data/build/dist/host/cli-adapters/driver.d.ts +2 -0
  73. package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +2 -0
  74. package/data/build/dist/host/cli-adapters/dsh-message-projector.js +47 -28
  75. package/data/build/dist/host/cli-adapters/dsh-tool-history.js +37 -0
  76. package/data/build/dist/host/cli-adapters/feature.js +94 -10
  77. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +6 -0
  78. package/data/build/dist/host/cli-adapters/json-rpc-process.js +14 -3
  79. package/data/build/dist/host/cli-adapters/kimi-driver.js +3 -3
  80. package/data/build/dist/host/cli-adapters/model-catalog.d.ts +6 -0
  81. package/data/build/dist/host/cli-adapters/model-catalog.js +8 -0
  82. package/data/build/dist/host/cli-adapters/opencode-driver.js +14 -2
  83. package/data/build/dist/host/cli-adapters/pi-driver.js +2 -2
  84. package/data/build/dist/host/cli-adapters/process-utils.d.ts +8 -0
  85. package/data/build/dist/host/cli-adapters/process-utils.js +48 -0
  86. package/data/build/dist/host/cli-adapters/registry.d.ts +6 -1
  87. package/data/build/dist/host/cli-adapters/registry.js +41 -7
  88. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +23 -4
  89. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +3 -0
  90. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +36 -15
  91. package/data/build/dist/host/dsh-device-runtime.d.ts +2 -0
  92. package/data/build/dist/host/dsh-device-runtime.js +55 -29
  93. package/data/build/dist/host/dsh-runtime-version.d.ts +3 -2
  94. package/data/build/dist/host/dsh-runtime-version.js +71 -2
  95. package/data/build/dist/host/features/auth.js +10 -2
  96. package/data/build/dist/host/features/file-management.d.ts +5 -0
  97. package/data/build/dist/host/features/file-management.js +267 -0
  98. package/data/build/dist/host/features/git-management.js +24 -2
  99. package/data/build/dist/host/features/index.d.ts +2 -0
  100. package/data/build/dist/host/features/index.js +6 -0
  101. package/data/build/dist/host/features/peer-host.d.ts +22 -0
  102. package/data/build/dist/host/features/peer-host.js +322 -0
  103. package/data/build/dist/host/features/types.d.ts +4 -0
  104. package/data/build/dist/host/host-router.d.ts +3 -0
  105. package/data/build/dist/host/host-router.js +2 -0
  106. package/data/build/dist/host/index-injection.d.ts +17 -0
  107. package/data/build/dist/host/index-injection.js +24 -0
  108. package/data/build/dist/host/index.d.ts +4 -1
  109. package/data/build/dist/host/index.js +41 -7
  110. package/data/build/dist/host/lan-access-dsh.d.ts +34 -1
  111. package/data/build/dist/host/lan-access-dsh.js +145 -26
  112. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts +52 -0
  113. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js +166 -0
  114. package/data/build/dist/host/modules/peer-host/host-ws-connector.d.ts +31 -0
  115. package/data/build/dist/host/modules/peer-host/host-ws-connector.js +108 -0
  116. package/data/build/dist/host/modules/peer-host/host-ws-proxy-service.d.ts +26 -0
  117. package/data/build/dist/host/modules/peer-host/host-ws-proxy-service.js +159 -0
  118. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.d.ts +50 -0
  119. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.js +97 -0
  120. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.d.ts +19 -0
  121. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.js +54 -0
  122. package/data/build/dist/host/modules/peer-host/peer-host-handshake.d.ts +44 -0
  123. package/data/build/dist/host/modules/peer-host/peer-host-handshake.js +133 -0
  124. package/data/build/dist/host/modules/peer-host/peer-host-relay.d.ts +65 -0
  125. package/data/build/dist/host/modules/peer-host/peer-host-relay.js +196 -0
  126. package/data/build/dist/host/modules/peer-host/peer-host-session.d.ts +42 -0
  127. package/data/build/dist/host/modules/peer-host/peer-host-session.js +152 -0
  128. package/data/build/dist/host/modules/peer-host/peer-host-store.d.ts +92 -0
  129. package/data/build/dist/host/modules/peer-host/peer-host-store.js +323 -0
  130. package/data/build/dist/host/modules/peer-host/peer-host-ws-gateway.d.ts +34 -0
  131. package/data/build/dist/host/modules/peer-host/peer-host-ws-gateway.js +156 -0
  132. package/data/build/dist/host/native-session-bridge.d.ts +18 -2
  133. package/data/build/dist/host/native-session-bridge.js +232 -8
  134. package/data/build/dist/host/remote-web-runtime.js +26 -1
  135. package/data/build/dist/host/rpc.js +8 -3
  136. package/data/build/dist/host/session-changes.d.ts +5 -0
  137. package/data/build/dist/host/session-changes.js +163 -0
  138. package/data/build/dist/host/settings.js +6 -0
  139. package/data/build/dist/index.d.ts +1 -1
  140. package/data/build/dist/index.js +1 -1
  141. package/data/build/dist/shared/contracts/cli-adapter.d.ts +23 -2
  142. package/data/build/dist/shared/contracts/config.d.ts +15 -0
  143. package/data/build/dist/shared/contracts/config.js +10 -0
  144. package/data/build/dist/shared/contracts/dsh-device.d.ts +2 -0
  145. package/data/build/dist/shared/contracts/errors.d.ts +14 -0
  146. package/data/build/dist/shared/contracts/errors.js +15 -0
  147. package/data/build/dist/shared/contracts/feature.d.ts +2 -0
  148. package/data/build/dist/shared/contracts/file-management.d.ts +6 -0
  149. package/data/build/dist/shared/contracts/file-management.js +3 -0
  150. package/data/build/dist/shared/contracts/peer-host.d.ts +116 -15
  151. package/data/build/dist/shared/contracts/peer-host.js +19 -0
  152. package/data/build/dist/shared/contracts/version.d.ts +1 -1
  153. package/data/build/dist/shared/contracts/version.js +1 -1
  154. package/data/build/dist/shared/index.d.ts +4 -3
  155. package/data/build/dist/shared/index.js +2 -2
  156. package/data/build/dist/transport/debug.d.ts +5 -0
  157. package/data/build/dist/transport/debug.js +23 -1
  158. package/data/build/dist/transport/dsh-transport.d.ts +2 -0
  159. package/data/build/dist/transport/dsh-transport.js +11 -0
  160. package/data/build/dist/transport/webrtc-client.d.ts +2 -0
  161. package/data/build/dist/transport/webrtc-client.js +2 -1
  162. package/data/build/dist/transport/webrtc-host.d.ts +2 -0
  163. package/data/build/dist/transport/webrtc-host.js +6 -3
  164. package/data/build/dist/typert.host.d.ts +1 -1
  165. package/data/build/dist/typert.host.js +2 -1
  166. package/dsh.bundle.patch +10 -0
  167. package/package.json +19 -11
  168. package/profile/README.md +2 -2
  169. package/profile/package.json +2 -2
  170. package/profile/version.json +1 -1
  171. package/version.json +1 -1
package/README.en.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  [简体中文](README.md) · **English**
12
12
 
13
- **Current release `@jingyi0605/codingns4dsh@0.1.2`** · DSH **`>=0.1.5-rc.3 <=0.1.7-rc.2`** (validated `0.1.5-rc.3`, `0.1.6-alpha.2`, `0.1.7-rc.2`) · Node **`>= 22.19`** · macOS / Linux / Windows
13
+ **Current release `@jingyi0605/codingns4dsh@0.1.7-rc.2`** · DSH **`>=0.1.5-rc.3 <=0.1.7-rc.2`** (validated `0.1.5-rc.3`, `0.1.6-alpha.2`, `0.1.7-rc.2`) · Node **`>= 22.19`** · macOS / Linux / Windows
14
14
 
15
15
  **[GitHub](https://github.com/jingyi0605/Codingns4DSH)** · **[npm](https://www.npmjs.com/package/@jingyi0605/codingns4dsh)** · **QQ group 1092985965**
16
16
 
@@ -203,7 +203,7 @@ The “access” line tells you whether you entered DSH Web locally, over the LA
203
203
  DSH automatically initializes the `web` profile on first use. You do not need to create a config file or run `--dump-config`:
204
204
 
205
205
  ```bash
206
- dsh plugin --profile web add @jingyi0605/codingns4dsh@0.1.2
206
+ dsh plugin --profile web add @jingyi0605/codingns4dsh@0.1.7-rc.2
207
207
  dsh web
208
208
  ```
209
209
 
@@ -213,7 +213,7 @@ If you do not want to modify the built-in `web` profile, create a separate profi
213
213
 
214
214
  ```bash
215
215
  dsh codingns --from-default-profile web --dump-config
216
- dsh plugin --profile codingns add @jingyi0605/codingns4dsh@0.1.2
216
+ dsh plugin --profile codingns add @jingyi0605/codingns4dsh@0.1.7-rc.2
217
217
  dsh codingns
218
218
  ```
219
219
 
@@ -234,7 +234,7 @@ dsh plugin --profile web remove @jingyi0605/codingns4dsh
234
234
  ```bash
235
235
  git clone https://github.com/jingyi0605/Codingns4DSH.git && cd Codingns4DSH
236
236
  pnpm install && pnpm build
237
- dsh plugin --profile web add "$PWD" # or: npm pack, then add ./jingyi0605-codingns4dsh-0.1.2.tgz
237
+ dsh plugin --profile web add "$PWD" # or: npm pack, then add ./jingyi0605-codingns4dsh-0.1.7-rc.2.tgz
238
238
  dsh web
239
239
  ```
240
240
 
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  **简体中文** · [English](README.en.md)
12
12
 
13
- **当前版本 `@jingyi0605/codingns4dsh@0.1.2`** · DSH **`>=0.1.5-rc.3 <=0.1.7-rc.2`**(已验证 `0.1.5-rc.3`、`0.1.6-alpha.2`、`0.1.7-rc.2`)· Node **`>= 22.19`** · macOS / Linux / Windows
13
+ **当前版本 `@jingyi0605/codingns4dsh@0.1.7-rc.2`** · DSH **`>=0.1.5-rc.3 <=0.1.7-rc.2`**(已验证 `0.1.5-rc.3`、`0.1.6-alpha.2`、`0.1.7-rc.2`)· Node **`>= 22.19`** · macOS / Linux / Windows
14
14
 
15
15
  **[GitHub](https://github.com/jingyi0605/Codingns4DSH)** · **[npm](https://www.npmjs.com/package/@jingyi0605/codingns4dsh)** · **QQ 群 1092985965**
16
16
 
@@ -42,7 +42,7 @@ CodingNS 工作台把会话、Agent 选择器与右侧 Git 面板放在同一界
42
42
 
43
43
  **DSH(DeepSeek Harness)** 是一个编码 Agent 运行框架,由 CLI 和 Web 界面组成,在你的 Workspace 中运行 Agent 循环。
44
44
 
45
- **Codingns4DSH 是一个 DSH 插件 Bundle**(Host 层 + 浏览器层),提供八个模块,全部在 **设置 → Codingns4DSH** 中配置。
45
+ **Codingns4DSH 是一个 DSH 插件 Bundle**(Host 层 + 浏览器层),提供九个模块,全部在 **设置 → Codingns4DSH** 中配置。
46
46
 
47
47
  > 名称说明:本插件名为 **Codingns4DSH**(npm 包 `@jingyi0605/codingns4dsh`,设置页入口显示为 Codingns4DSH);文中单独出现的 **Codingns4DSH** 指提供 Control API、账号与中继隧道的平台服务。
48
48
 
@@ -56,6 +56,7 @@ CodingNS 工作台把会话、Agent 选择器与右侧 Git 面板放在同一界
56
56
  | **中转访问服务** | **在互联网任何位置访问自己的 DSH Web**,端到端加密 | 关 |
57
57
  | **工作区调试** | 按工作区保存启动配置、检查端口、HTTP 服务代理 | 开 |
58
58
  | **Git 仓库管理** | 在右侧 Sidebar 标签页查看改动、暂存文件、提交和 Git 版本历史 | 开 |
59
+ | **PeerHost 聚合工作台** | 当前 Host 代理已握手的其他 DSH Host,按 HostScope 聚合工作区、会话和受控工具 | 关 |
59
60
 
60
61
  DSH 原生部分不会被替换:对话、会话列表、侧栏、设置、权限确认仍然是 DSH 自己的组件。
61
62
 
@@ -137,6 +138,14 @@ DSH 原生部分不会被替换:对话、会话列表、侧栏、设置、权
137
138
 
138
139
  Git 面板通过 DSH 原生右侧 Sidebar 的标签页入口打开,按 Workspace 保存状态并跨会话复用。未初始化的目录可直接初始化仓库;已初始化的仓库支持查看暂存文件和未提交文件、暂存/取消暂存、丢弃更改、填写提交说明、切换分支和浏览提交历史。模块关闭后会移除右侧标签及对应 Host Git RPC,不影响其他模块。
139
140
 
141
+ ### PeerHost 多 Host 工作区
142
+
143
+ PeerHost 是当前 Host 的代理能力,不会切换当前登录 Host。启用后可在管理面板添加局域网 PeerHost,Host 侧保存目标配置和登录态,Client 只提交 `targetHostId` 与完整 `HostScope`(`hostId`、`targetHostId`、`workspaceId`、`sessionId`、`scopeGeneration`)。工作区、会话、聊天输入、实时事件、文件、Git、终端和右侧工具都按作用域路由,单个 PeerHost 故障不会阻塞当前 Host 或其他 PeerHost。
144
+
145
+ 当前已验证的路径包括固定握手、HTTP/WS 正向白名单、Host-to-Host 局域网 `/ws` connector、实时事件过滤、有限指数退避、generation 重建和脱敏诊断。DSH 原生导航或 conversation 容器未提供稳定扩展点时,界面会显示明确的 `degraded`/`unsupported` 状态,不创建 iframe,也不会把远端 Web Context 冒充成原生三栏聚合。
146
+
147
+ 中转 PeerHost 仍保持 `relay_unavailable/degraded`:现有浏览器中转 ticket 和任意公网 URL 不能替代经过验证的 Host-to-Host JSON/WS Transport。当前 Host 的既有局域网访问、中转访问、登录和单 Host 会话语义不受 PeerHost 影响。
148
+
140
149
  ### 模块与设置
141
150
 
142
151
  设置页按模块渲染卡片,开关、说明和「是否需要重启」都来自模块自身的描述;终端外观、局域网映射、登录保护、中转账号等都在对应卡片内配置。
@@ -208,7 +217,7 @@ DSH 设置按钮旁的账户入口会显示登录状态、访问路径与延迟
208
217
  DSH 的 `web` Profile 会在首次使用时自动初始化,不需要手动创建配置文件,也不需要执行 `--dump-config`:
209
218
 
210
219
  ```bash
211
- dsh plugin --profile web add @jingyi0605/codingns4dsh@0.1.2
220
+ dsh plugin --profile web add @jingyi0605/codingns4dsh@0.1.7-rc.2
212
221
  dsh web
213
222
  ```
214
223
 
@@ -218,7 +227,7 @@ dsh web
218
227
 
219
228
  ```bash
220
229
  dsh codingns --from-default-profile web --dump-config
221
- dsh plugin --profile codingns add @jingyi0605/codingns4dsh@0.1.2
230
+ dsh plugin --profile codingns add @jingyi0605/codingns4dsh@0.1.7-rc.2
222
231
  dsh codingns
223
232
  ```
224
233
 
@@ -239,7 +248,7 @@ dsh plugin --profile web remove @jingyi0605/codingns4dsh
239
248
  ```bash
240
249
  git clone https://github.com/jingyi0605/Codingns4DSH.git && cd Codingns4DSH
241
250
  pnpm install && pnpm build
242
- dsh plugin --profile web add "$PWD" # 或 npm pack 后 add ./jingyi0605-codingns4dsh-0.1.2.tgz
251
+ dsh plugin --profile web add "$PWD" # 或 npm pack 后 add ./jingyi0605-codingns4dsh-0.1.7-rc.2.tgz
243
252
  dsh web
244
253
  ```
245
254
 
@@ -1,10 +1,11 @@
1
1
  import { CODINGNS_RPC_CHANNEL } from '../shared/contracts/transport.js';
2
- import { LOGIN_PROTECTION_SESSION_EVENT, readLoginProtectionSession, writeLoginProtectionSession } from './features/login-protection-session.js';
2
+ import { LOGIN_PROTECTION_SESSION_EVENT, readLoginProtectionSession, readLoginProtectionSessionExpiresAt, writeLoginProtectionSession } from './features/login-protection-session.js';
3
3
  import { dshThemeColor } from './theme.js';
4
4
  const SETTINGS_BUTTON_SELECTOR = 'button[aria-label="设置"]';
5
5
  const ACCOUNT_ATTRIBUTE = 'data-codingns-account-button';
6
6
  const MENU_ATTRIBUTE = 'data-codingns-account-menu';
7
7
  const POLL_MS = 5_000;
8
+ const LOGIN_REFRESH_POLL_MS = 30_000;
8
9
  /** 在 DSH 设置触发器旁挂载统一账户入口,兼容侧栏横排与收起竖排。 */
9
10
  export function startCodingNsAccountBar(rpc, dom, _settings) {
10
11
  const currentDocument = dom ?? (typeof document === 'undefined' ? undefined : document);
@@ -13,6 +14,8 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
13
14
  const root = currentDocument;
14
15
  let disposed = false;
15
16
  let timer;
17
+ let loginRefreshTimer;
18
+ let loginRefreshInFlight = false;
16
19
  let observer;
17
20
  let observeDom = true;
18
21
  let resizeObserver;
@@ -21,6 +24,7 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
21
24
  let closeMenuListener;
22
25
  let auth = loggedOutSnapshot();
23
26
  let local = null;
27
+ let localSessionExpiresAt = null;
24
28
  let localRelay = readRelayLoginIdentity();
25
29
  let status;
26
30
  let latency;
@@ -52,6 +56,7 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
52
56
  if (nextAuth.status === 'fulfilled')
53
57
  auth = nextAuth.value;
54
58
  local = nextLocal.status === 'fulfilled' ? nextLocal.value : null;
59
+ localSessionExpiresAt = local?.expiresAt ?? null;
55
60
  localRelay = readRelayLoginIdentity();
56
61
  if (nextStatus.status === 'fulfilled') {
57
62
  status = nextStatus.value;
@@ -165,7 +170,8 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
165
170
  };
166
171
  root.defaultView?.addEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSessionChanged);
167
172
  timer = setInterval(() => { void refresh(); }, POLL_MS);
168
- void refresh();
173
+ loginRefreshTimer = setInterval(() => { void refreshLoginProtection(); }, LOGIN_REFRESH_POLL_MS);
174
+ void refresh().then(() => refreshLoginProtection());
169
175
  return {
170
176
  dispose() {
171
177
  if (disposed)
@@ -173,6 +179,8 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
173
179
  disposed = true;
174
180
  if (timer !== undefined)
175
181
  clearInterval(timer);
182
+ if (loginRefreshTimer !== undefined)
183
+ clearInterval(loginRefreshTimer);
176
184
  observer?.disconnect();
177
185
  resizeObserver?.disconnect();
178
186
  root.defaultView?.removeEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSessionChanged);
@@ -184,6 +192,46 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
184
192
  root.querySelectorAll(`button[${ACCOUNT_ATTRIBUTE}]`).forEach((node) => node.remove());
185
193
  },
186
194
  };
195
+ /** 在票据临近过期时续签,避免每次轮询都无意义地旋转 token。 */
196
+ async function refreshLoginProtection() {
197
+ if (disposed || loginRefreshInFlight)
198
+ return;
199
+ const relayToken = readLoginProtectionSession();
200
+ const relayExpiresAt = readLoginProtectionSessionExpiresAt();
201
+ const shouldRefreshRelay = relayToken !== undefined && relayExpiresAt !== null && relayExpiresAt - Date.now() <= 120_000;
202
+ const shouldRefreshLan = local !== null && (localSessionExpiresAt === null || localSessionExpiresAt - Date.now() <= 120_000);
203
+ if (!shouldRefreshRelay && !shouldRefreshLan)
204
+ return;
205
+ loginRefreshInFlight = true;
206
+ try {
207
+ if (shouldRefreshLan) {
208
+ const response = await (root.defaultView?.fetch.bind(root.defaultView) ?? fetch)('/__codingns/session/refresh', {
209
+ method: 'POST',
210
+ credentials: 'same-origin',
211
+ cache: 'no-store',
212
+ headers: { Accept: 'application/json' },
213
+ });
214
+ if (!response.ok)
215
+ local = null;
216
+ else {
217
+ const value = await response.json();
218
+ localSessionExpiresAt = typeof value.expiresAt === 'number' ? value.expiresAt : null;
219
+ }
220
+ }
221
+ if (shouldRefreshRelay && relayToken !== undefined) {
222
+ const value = await call('lanAccessDsh/login/session/refresh', { token: relayToken, scope: 'relay' });
223
+ if (typeof value.token === 'string' && value.token !== '')
224
+ writeLoginProtectionSession(value.token);
225
+ }
226
+ }
227
+ catch (error) {
228
+ // 网络短暂失败时保留旧会话,下一轮仍会在旧票据到期前重试。
229
+ console.warn('codingns4dsh: 登录保护会话刷新失败', error);
230
+ }
231
+ finally {
232
+ loginRefreshInFlight = false;
233
+ }
234
+ }
187
235
  function removeAccountBar() {
188
236
  if (closeMenuListener !== undefined) {
189
237
  root.removeEventListener('click', closeMenuListener, true);
@@ -321,6 +369,12 @@ export function startCodingNsAccountBar(rpc, dom, _settings) {
321
369
  }
322
370
  }
323
371
  async function fetchLocalIdentity(dom) {
372
+ // Desktop 使用 dsh-app://app,不提供网页侧的本地身份路由。
373
+ // 只有局域网/中转 HTTP 页面才需要查询这个端点;其它协议直接视为未登录,
374
+ // 避免在 Desktop 控制台制造无意义的 404。
375
+ const protocol = dom.defaultView?.location.protocol;
376
+ if (protocol !== 'http:' && protocol !== 'https:')
377
+ return null;
324
378
  const response = await (dom.defaultView?.fetch.bind(dom.defaultView) ?? fetch)('/__codingns/session', {
325
379
  credentials: 'same-origin',
326
380
  cache: 'no-store',
@@ -330,7 +384,7 @@ async function fetchLocalIdentity(dom) {
330
384
  return null;
331
385
  const value = await response.json();
332
386
  return value.authenticated === true && typeof value.username === 'string'
333
- ? { username: value.username }
387
+ ? { username: value.username, ...(typeof value.expiresAt === 'number' ? { expiresAt: value.expiresAt } : {}) }
334
388
  : null;
335
389
  }
336
390
  function readRelayLoginIdentity() {