@jingyi0605/codingns4dsh 0.1.0 → 0.1.1

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 (216) hide show
  1. package/README.en.md +306 -0
  2. package/README.md +190 -993
  3. package/data/build/dist/client/account-bar.d.ts +2 -2
  4. package/data/build/dist/client/account-bar.js +96 -39
  5. package/data/build/dist/client/bundle.js +13722 -3611
  6. package/data/build/dist/client/cli-catalog.js +20 -3
  7. package/data/build/dist/client/cli-slots.d.ts +5 -0
  8. package/data/build/dist/client/cli-slots.js +57 -7
  9. package/data/build/dist/client/debug/ui.d.ts +1 -1
  10. package/data/build/dist/client/debug/ui.js +62 -32
  11. package/data/build/dist/client/dsh-runtime-version.d.ts +9 -2
  12. package/data/build/dist/client/dsh-runtime-version.js +24 -2
  13. package/data/build/dist/client/features/cli-adapters.d.ts +1 -1
  14. package/data/build/dist/client/features/cli-adapters.js +19 -16
  15. package/data/build/dist/client/features/debug.js +2 -2
  16. package/data/build/dist/client/features/index.d.ts +2 -1
  17. package/data/build/dist/client/features/index.js +3 -1
  18. package/data/build/dist/client/features/lan-access-panel.d.ts +1 -1
  19. package/data/build/dist/client/features/lan-access-panel.js +8 -10
  20. package/data/build/dist/client/features/lan-access.js +1 -1
  21. package/data/build/dist/client/features/login-protection-panel.d.ts +1 -1
  22. package/data/build/dist/client/features/login-protection-panel.js +7 -9
  23. package/data/build/dist/client/features/reverse-proxy-panel.d.ts +1 -1
  24. package/data/build/dist/client/features/reverse-proxy-panel.js +99 -11
  25. package/data/build/dist/client/features/reverse-proxy.d.ts +1 -1
  26. package/data/build/dist/client/features/reverse-proxy.js +19 -18
  27. package/data/build/dist/client/features/terminal-enhancement-panel.d.ts +1 -1
  28. package/data/build/dist/client/features/terminal-enhancement-panel.js +62 -55
  29. package/data/build/dist/client/features/terminal-enhancement.d.ts +1 -1
  30. package/data/build/dist/client/features/terminal-enhancement.js +3 -3
  31. package/data/build/dist/client/features/types.d.ts +14 -3
  32. package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts +1 -1
  33. package/data/build/dist/client/features/workspace-session-enhancement-panel.js +31 -9
  34. package/data/build/dist/client/features/workspace-session-enhancement.js +72 -11
  35. package/data/build/dist/client/git-management.d.ts +16 -0
  36. package/data/build/dist/client/git-management.js +757 -0
  37. package/data/build/dist/client/index.d.ts +3 -2
  38. package/data/build/dist/client/index.js +152 -27
  39. package/data/build/dist/client/locale.js +91 -29
  40. package/data/build/dist/client/quick-phrase-layout.d.ts +49 -0
  41. package/data/build/dist/client/quick-phrase-layout.js +95 -0
  42. package/data/build/dist/client/quick-phrase-slot.d.ts +7 -0
  43. package/data/build/dist/client/quick-phrase-slot.js +370 -0
  44. package/data/build/dist/client/remote-web-context.js +1 -1
  45. package/data/build/dist/client/settings-bridge.d.ts +9 -6
  46. package/data/build/dist/client/settings-bridge.js +51 -27
  47. package/data/build/dist/client/settings-section.d.ts +3 -2
  48. package/data/build/dist/client/settings-section.js +33 -19
  49. package/data/build/dist/client/subscription-slot.d.ts +3 -0
  50. package/data/build/dist/client/subscription-slot.js +108 -16
  51. package/data/build/dist/client/terminal/model.d.ts +14 -2
  52. package/data/build/dist/client/terminal/model.js +109 -21
  53. package/data/build/dist/client/terminal/recovery.d.ts +50 -0
  54. package/data/build/dist/client/terminal/recovery.js +101 -0
  55. package/data/build/dist/client/terminal/ui.d.ts +2 -2
  56. package/data/build/dist/client/terminal/ui.js +49 -11
  57. package/data/build/dist/client/terminal/xterm-view.d.ts +2 -2
  58. package/data/build/dist/client/terminal/xterm-view.js +2 -1
  59. package/data/build/dist/client/theme.d.ts +6 -1
  60. package/data/build/dist/client/theme.js +32 -1
  61. package/data/build/dist/client/workspace-session-archive-dom.d.ts +12 -0
  62. package/data/build/dist/client/workspace-session-archive-dom.js +27 -5
  63. package/data/build/dist/client/workspace-session-visibility-dom.d.ts +30 -0
  64. package/data/build/dist/client/workspace-session-visibility-dom.js +604 -0
  65. package/data/build/dist/dsh-capabilities/client/config-forms-adapter.d.ts +50 -0
  66. package/data/build/dist/dsh-capabilities/client/config-forms-adapter.js +139 -0
  67. package/data/build/dist/dsh-capabilities/client/conversation-adapter.d.ts +7 -0
  68. package/data/build/dist/dsh-capabilities/client/conversation-adapter.js +6 -0
  69. package/data/build/dist/dsh-capabilities/client/locale-adapter.d.ts +9 -0
  70. package/data/build/dist/dsh-capabilities/client/locale-adapter.js +4 -0
  71. package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +10 -0
  72. package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +14 -0
  73. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.d.ts +8 -0
  74. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.js +16 -0
  75. package/data/build/dist/dsh-capabilities/client/sidebar-adapter.d.ts +7 -0
  76. package/data/build/dist/dsh-capabilities/client/sidebar-adapter.js +5 -0
  77. package/data/build/dist/dsh-capabilities/client/theme-adapter.d.ts +6 -0
  78. package/data/build/dist/dsh-capabilities/client/theme-adapter.js +4 -0
  79. package/data/build/dist/dsh-capabilities/client/typert-adapter.d.ts +5 -0
  80. package/data/build/dist/dsh-capabilities/client/typert-adapter.js +4 -0
  81. package/data/build/dist/dsh-capabilities/host/config-forms-adapter.d.ts +19 -0
  82. package/data/build/dist/dsh-capabilities/host/config-forms-adapter.js +45 -0
  83. package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.d.ts +19 -0
  84. package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.js +13 -0
  85. package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.d.ts +8 -0
  86. package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.js +47 -0
  87. package/data/build/dist/dsh-capabilities/host/typert-adapter.d.ts +6 -0
  88. package/data/build/dist/dsh-capabilities/host/typert-adapter.js +4 -0
  89. package/data/build/dist/dsh-capabilities/index.d.ts +6 -0
  90. package/data/build/dist/dsh-capabilities/index.js +6 -0
  91. package/data/build/dist/dsh-capabilities/matrix.d.ts +15 -0
  92. package/data/build/dist/dsh-capabilities/matrix.js +32 -0
  93. package/data/build/dist/dsh-capabilities/registry.d.ts +22 -0
  94. package/data/build/dist/dsh-capabilities/registry.js +196 -0
  95. package/data/build/dist/dsh-capabilities/routes.d.ts +10 -0
  96. package/data/build/dist/dsh-capabilities/routes.js +34 -0
  97. package/data/build/dist/dsh-capabilities/settings-store.d.ts +29 -0
  98. package/data/build/dist/dsh-capabilities/settings-store.js +5 -0
  99. package/data/build/dist/dsh-capabilities/types.d.ts +50 -0
  100. package/data/build/dist/dsh-capabilities/types.js +23 -0
  101. package/data/build/dist/features/registry.d.ts +8 -2
  102. package/data/build/dist/features/registry.js +104 -1
  103. package/data/build/dist/host/auth-session.d.ts +8 -1
  104. package/data/build/dist/host/auth-session.js +28 -6
  105. package/data/build/dist/host/cli-adapters/claude-driver.d.ts +2 -0
  106. package/data/build/dist/host/cli-adapters/claude-driver.js +19 -4
  107. package/data/build/dist/host/cli-adapters/claude-model-options.d.ts +14 -0
  108. package/data/build/dist/host/cli-adapters/claude-model-options.js +157 -0
  109. package/data/build/dist/host/cli-adapters/codex-driver.d.ts +11 -0
  110. package/data/build/dist/host/cli-adapters/codex-driver.js +166 -14
  111. package/data/build/dist/host/cli-adapters/driver.d.ts +2 -0
  112. package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +15 -0
  113. package/data/build/dist/host/cli-adapters/dsh-message-projector.js +120 -29
  114. package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts +4 -1
  115. package/data/build/dist/host/cli-adapters/dsh-tool-history.js +25 -7
  116. package/data/build/dist/host/cli-adapters/feature.js +74 -8
  117. package/data/build/dist/host/cli-adapters/gemini-driver.js +2 -2
  118. package/data/build/dist/host/cli-adapters/grok-driver.js +2 -2
  119. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +4 -2
  120. package/data/build/dist/host/cli-adapters/json-rpc-process.js +8 -9
  121. package/data/build/dist/host/cli-adapters/kimi-driver.js +1 -1
  122. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +17 -0
  123. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +88 -0
  124. package/data/build/dist/host/cli-adapters/legacy-session-settings.d.ts +24 -0
  125. package/data/build/dist/host/cli-adapters/legacy-session-settings.js +162 -0
  126. package/data/build/dist/host/cli-adapters/official-provider-subscription.d.ts +29 -0
  127. package/data/build/dist/host/cli-adapters/official-provider-subscription.js +361 -0
  128. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +2 -0
  129. package/data/build/dist/host/cli-adapters/opencode-driver.js +97 -12
  130. package/data/build/dist/host/cli-adapters/pi-driver.js +69 -23
  131. package/data/build/dist/host/cli-adapters/provider-registry.d.ts +33 -0
  132. package/data/build/dist/host/cli-adapters/provider-registry.js +83 -0
  133. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +25 -3
  134. package/data/build/dist/host/cli-adapters/provider-subscription.js +346 -30
  135. package/data/build/dist/host/cli-adapters/registry.d.ts +6 -0
  136. package/data/build/dist/host/cli-adapters/registry.js +170 -13
  137. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +10 -0
  138. package/data/build/dist/host/cli-adapters/session-store.d.ts +7 -0
  139. package/data/build/dist/host/cli-adapters/session-store.js +39 -1
  140. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +3 -0
  141. package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +3 -0
  142. package/data/build/dist/host/cli-adapters/stream-normalizer.js +22 -2
  143. package/data/build/dist/host/control-api-client.d.ts +3 -3
  144. package/data/build/dist/host/control-api-client.js +2 -1
  145. package/data/build/dist/host/credential-store.js +11 -1
  146. package/data/build/dist/host/dsh-device-runtime.d.ts +4 -0
  147. package/data/build/dist/host/dsh-device-runtime.js +20 -9
  148. package/data/build/dist/host/dsh-runtime-version.d.ts +3 -2
  149. package/data/build/dist/host/dsh-runtime-version.js +71 -2
  150. package/data/build/dist/host/features/auth.js +8 -5
  151. package/data/build/dist/host/features/debug.js +1 -1
  152. package/data/build/dist/host/features/git-management.d.ts +5 -0
  153. package/data/build/dist/host/features/git-management.js +290 -0
  154. package/data/build/dist/host/features/host-status.js +1 -1
  155. package/data/build/dist/host/features/index.d.ts +1 -0
  156. package/data/build/dist/host/features/index.js +3 -0
  157. package/data/build/dist/host/features/terminal-process.js +1 -1
  158. package/data/build/dist/host/features/terminal-status.d.ts +3 -1
  159. package/data/build/dist/host/features/terminal-status.js +3 -1
  160. package/data/build/dist/host/index.d.ts +7 -3
  161. package/data/build/dist/host/index.js +79 -15
  162. package/data/build/dist/host/lan-access-dsh.js +18 -5
  163. package/data/build/dist/host/native-session-bridge.d.ts +23 -1
  164. package/data/build/dist/host/native-session-bridge.js +157 -10
  165. package/data/build/dist/host/rpc-table.d.ts +1 -1
  166. package/data/build/dist/host/rpc.js +60 -10
  167. package/data/build/dist/host/session-migration-repair.d.ts +19 -0
  168. package/data/build/dist/host/session-migration-repair.js +395 -0
  169. package/data/build/dist/host/settings.d.ts +8 -1
  170. package/data/build/dist/host/settings.js +94 -3
  171. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +1 -0
  172. package/data/build/dist/host/terminal/backends/tmux-backend.js +4 -2
  173. package/data/build/dist/host/terminal/controller-factory.d.ts +4 -0
  174. package/data/build/dist/host/terminal/controller-factory.js +26 -7
  175. package/data/build/dist/host/terminal/runtime-manager.d.ts +2 -1
  176. package/data/build/dist/host/terminal/runtime-manager.js +3 -0
  177. package/data/build/dist/host/terminal/startup.d.ts +2 -0
  178. package/data/build/dist/host/terminal/startup.js +2 -1
  179. package/data/build/dist/host/terminal/terminal-controller.d.ts +10 -3
  180. package/data/build/dist/host/terminal/terminal-controller.js +101 -15
  181. package/data/build/dist/host/terminal/terminal-process-service.js +3 -1
  182. package/data/build/dist/host/terminal/terminal-service.d.ts +2 -0
  183. package/data/build/dist/host/terminal/terminal-service.js +10 -0
  184. package/data/build/dist/index.d.ts +6 -2
  185. package/data/build/dist/index.js +8 -2
  186. package/data/build/dist/shared/contracts/cli-adapter.d.ts +14 -0
  187. package/data/build/dist/shared/contracts/config.d.ts +31 -1
  188. package/data/build/dist/shared/contracts/config.js +25 -0
  189. package/data/build/dist/shared/contracts/dsh-device.d.ts +13 -1
  190. package/data/build/dist/shared/contracts/errors.d.ts +1 -1
  191. package/data/build/dist/shared/contracts/feature.d.ts +6 -0
  192. package/data/build/dist/shared/contracts/git.d.ts +82 -0
  193. package/data/build/dist/shared/contracts/git.js +3 -0
  194. package/data/build/dist/shared/contracts/subscription.d.ts +46 -0
  195. package/data/build/dist/shared/contracts/terminal.d.ts +4 -1
  196. package/data/build/dist/shared/contracts/version.d.ts +2 -2
  197. package/data/build/dist/shared/contracts/version.js +4 -6
  198. package/data/build/dist/shared/debug.d.ts +14 -0
  199. package/data/build/dist/shared/debug.js +53 -0
  200. package/data/build/dist/shared/index.d.ts +7 -4
  201. package/data/build/dist/shared/index.js +2 -1
  202. package/data/build/dist/transport/debug.d.ts +1 -1
  203. package/data/build/dist/transport/debug.js +3 -30
  204. package/data/build/dist/transport/dsh-session.js +3 -3
  205. package/data/build/dist/typert.host.d.ts +1 -1
  206. package/data/build/dist/typert.host.js +6 -3
  207. package/data/build/dist/typert.remote-client.d.ts +11 -0
  208. package/data/build/dist/typert.remote-client.js +7 -0
  209. package/dsh.bundle.patch +1 -1
  210. package/package.json +13 -5
  211. package/profile/README.md +4 -4
  212. package/profile/package.json +6 -4
  213. package/profile/scripts/check-dsh-install.mjs +2 -2
  214. package/profile/version.json +2 -2
  215. package/scripts/check-dsh-install.mjs +2 -2
  216. package/version.json +2 -2
@@ -1,9 +1,9 @@
1
1
  import type { CodingNsSettings } from '../shared/contracts/config.js';
2
2
  import type { CodingNsRpcClient } from './features/types.js';
3
- import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
3
+ import type { CodingNsSettingsStore } from '../dsh-capabilities/settings-store.js';
4
4
  export interface AccountBarController {
5
5
  dispose(): void;
6
6
  }
7
7
  /** 在 DSH 设置触发器旁挂载统一账户入口,兼容侧栏横排与收起竖排。 */
8
- export declare function startCodingNsAccountBar(rpc: CodingNsRpcClient, dom?: Document, settings?: SettingsScope<CodingNsSettings>): AccountBarController;
8
+ export declare function startCodingNsAccountBar(rpc: CodingNsRpcClient, dom?: Document, _settings?: CodingNsSettingsStore<CodingNsSettings>): AccountBarController;
9
9
  //# sourceMappingURL=account-bar.d.ts.map
@@ -1,10 +1,12 @@
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';
3
+ import { dshThemeColor } from './theme.js';
2
4
  const SETTINGS_BUTTON_SELECTOR = 'button[aria-label="设置"]';
3
5
  const ACCOUNT_ATTRIBUTE = 'data-codingns-account-button';
4
6
  const MENU_ATTRIBUTE = 'data-codingns-account-menu';
5
7
  const POLL_MS = 5_000;
6
8
  /** 在 DSH 设置触发器旁挂载统一账户入口,兼容侧栏横排与收起竖排。 */
7
- export function startCodingNsAccountBar(rpc, dom, settings) {
9
+ export function startCodingNsAccountBar(rpc, dom, _settings) {
8
10
  const currentDocument = dom ?? (typeof document === 'undefined' ? undefined : document);
9
11
  if (currentDocument === undefined)
10
12
  return { dispose() { } };
@@ -18,8 +20,8 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
18
20
  let rendering = false;
19
21
  let closeMenuListener;
20
22
  let auth = loggedOutSnapshot();
21
- let local = { username: '', enabled: false };
22
- let relayAccessEnabled = false;
23
+ let local = null;
24
+ let localRelay = readRelayLoginIdentity();
23
25
  let status;
24
26
  let latency;
25
27
  let busy = false;
@@ -44,14 +46,13 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
44
46
  const started = performance.now();
45
47
  const [nextAuth, nextLocal, nextStatus] = await Promise.allSettled([
46
48
  call('auth/snapshot', {}),
47
- call('lanAccessDsh/login/get', {}),
49
+ fetchLocalIdentity(root),
48
50
  call('host/status', {}),
49
51
  ]);
50
52
  if (nextAuth.status === 'fulfilled')
51
53
  auth = nextAuth.value;
52
- if (nextLocal.status === 'fulfilled')
53
- local = nextLocal.value;
54
- relayAccessEnabled = settings?.getSnapshot().value?.modules?.reverseProxy === true;
54
+ local = nextLocal.status === 'fulfilled' ? nextLocal.value : null;
55
+ localRelay = readRelayLoginIdentity();
55
56
  if (nextStatus.status === 'fulfilled') {
56
57
  status = nextStatus.value;
57
58
  latency = Math.max(0, Math.round(performance.now() - started));
@@ -68,7 +69,7 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
68
69
  const scan = () => {
69
70
  if (disposed)
70
71
  return;
71
- if (!local.enabled && !relayAccessEnabled) {
72
+ if (!isAccountAuthenticated()) {
72
73
  removeAccountBar();
73
74
  observeDom = true;
74
75
  return;
@@ -100,6 +101,8 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
100
101
  display: 'flex',
101
102
  alignItems: 'center',
102
103
  gap: '4px',
104
+ width: '100%',
105
+ boxSizing: 'border-box',
103
106
  });
104
107
  updateAccountLayout(parent, settings, button);
105
108
  resizeObserver?.disconnect();
@@ -119,7 +122,8 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
119
122
  return;
120
123
  button.dataset.codingnsWide = mode;
121
124
  parent.style.flexDirection = wide ? 'row' : 'column';
122
- parent.style.justifyContent = wide ? 'flex-start' : 'flex-end';
125
+ parent.style.justifyContent = 'flex-end';
126
+ button.style.marginLeft = wide ? 'auto' : '0';
123
127
  button.style.order = wide ? '2' : '1';
124
128
  settings.style.order = wide ? '1' : '2';
125
129
  };
@@ -155,10 +159,11 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
155
159
  };
156
160
  observer = typeof MutationObserver === 'undefined' ? undefined : new MutationObserver(observerCallback);
157
161
  observer?.observe(root.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ['aria-expanded'] });
158
- const unsubscribeSettings = settings?.subscribe(() => {
159
- relayAccessEnabled = settings.getSnapshot().value?.modules?.reverseProxy === true;
162
+ const onLoginProtectionSessionChanged = () => {
163
+ localRelay = readRelayLoginIdentity();
160
164
  renderAll();
161
- });
165
+ };
166
+ root.defaultView?.addEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSessionChanged);
162
167
  timer = setInterval(() => { void refresh(); }, POLL_MS);
163
168
  void refresh();
164
169
  return {
@@ -168,9 +173,9 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
168
173
  disposed = true;
169
174
  if (timer !== undefined)
170
175
  clearInterval(timer);
171
- unsubscribeSettings?.();
172
176
  observer?.disconnect();
173
177
  resizeObserver?.disconnect();
178
+ root.defaultView?.removeEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSessionChanged);
174
179
  if (closeMenuListener !== undefined) {
175
180
  root.removeEventListener('click', closeMenuListener, true);
176
181
  closeMenuListener = undefined;
@@ -188,19 +193,36 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
188
193
  root.querySelectorAll(`button[${ACCOUNT_ATTRIBUTE}]`).forEach((node) => node.remove());
189
194
  }
190
195
  function renderButton(button) {
191
- const identity = auth.account !== null
192
- ? auth.account.email
193
- : auth.status === 'authenticated' ? 'Codingns4DSH'
194
- : local.enabled && local.username ? local.username : '用户';
196
+ const account = activeAccount();
197
+ const identity = account?.identity ?? '用户';
195
198
  button.title = `${identity} · 点击管理登录`;
196
199
  button.setAttribute('aria-label', `用户:${identity}`);
197
- const authKind = auth.account !== null || auth.status === 'authenticated' ? 'codingns' : local.enabled ? 'local' : 'unknown';
198
- button.dataset.codingnsAuth = authKind;
200
+ button.dataset.codingnsAuth = account?.kind ?? 'unknown';
199
201
  const statusDot = button.querySelector('[data-codingns-account-status]');
200
202
  if (statusDot !== null)
201
- statusDot.style.background = authKind === 'unknown'
202
- ? 'var(--dsw-alias-label-tertiary, #8b8d91)'
203
- : 'var(--dsw-alias-state-success-primary, #35b66b)';
203
+ statusDot.style.background = 'var(--dsw-alias-state-success-primary, #35b66b)';
204
+ }
205
+ function activeAccount() {
206
+ const remote = isRemoteContext();
207
+ if (isLoopbackPage() && !remote)
208
+ return null;
209
+ if (local !== null)
210
+ return { kind: 'local', identity: local.username, scope: 'lan' };
211
+ if (!remote)
212
+ return null;
213
+ if (auth.status === 'authenticated' && auth.account !== null) {
214
+ return { kind: 'codingns', identity: auth.account.email };
215
+ }
216
+ if (localRelay !== null)
217
+ return { kind: 'local', identity: localRelay.username, scope: 'relay' };
218
+ return null;
219
+ }
220
+ function isAccountAuthenticated() {
221
+ return activeAccount() !== null;
222
+ }
223
+ function isLoopbackPage() {
224
+ const hostname = root.defaultView?.location.hostname.toLowerCase().replace(/\.$/u, '').replace(/^\[|\]$/gu, '') ?? '';
225
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '::ffff:127.0.0.1';
204
226
  }
205
227
  function toggleMenu(button) {
206
228
  const existing = root.querySelector(`[${MENU_ATTRIBUTE}]`);
@@ -248,10 +270,10 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
248
270
  });
249
271
  }
250
272
  function renderMenu(menu) {
251
- const identity = auth.account !== null
252
- ? auth.account.email
253
- : auth.status === 'authenticated' ? 'Codingns4DSH 账号'
254
- : local.enabled && local.username ? `${local.username}(本地账号)` : '未识别账号';
273
+ const account = activeAccount();
274
+ const identity = account?.kind === 'codingns' ? account.identity
275
+ : account !== null ? `${account.identity}(本地账号)`
276
+ : '未识别账号';
255
277
  const access = relayModeLabel();
256
278
  menu.innerHTML = '';
257
279
  menu.append(textNode(root, identity, 'strong'));
@@ -273,12 +295,21 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
273
295
  busy = true;
274
296
  renderMenu(menu);
275
297
  try {
276
- // 注销目标由当前访问入口决定;LAN 页面上的 Host 可能仍保留中继站
277
- // 会话,但不能因为注销本地登录而一并清掉它。
278
- if (resolveAccountLogoutTarget() === 'relay')
279
- await call('auth/logout', {});
280
- else
298
+ const account = activeAccount();
299
+ if (account?.kind === 'codingns') {
300
+ if (!isRemoteContext() || typeof window === 'undefined' || window.parent === window) {
301
+ throw new Error('Codingns Connect 账号只能从远程访问页面注销');
302
+ }
303
+ // srcdoc 沙箱中的 location.origin 可能为 "null";父页面会按 iframe 窗口校验来源。
304
+ window.parent.postMessage({ kind: 'codingns4dsh:remote-logout' }, '*');
305
+ return;
306
+ }
307
+ else if (account?.scope === 'relay')
308
+ writeLoginProtectionSession(undefined);
309
+ else if (account?.scope === 'lan')
281
310
  await fetch('/__codingns/logout', { credentials: 'include', redirect: 'manual' });
311
+ else
312
+ throw new Error('当前页面没有可注销的账号会话');
282
313
  if (typeof location !== 'undefined')
283
314
  location.reload();
284
315
  }
@@ -289,6 +320,39 @@ export function startCodingNsAccountBar(rpc, dom, settings) {
289
320
  }
290
321
  }
291
322
  }
323
+ async function fetchLocalIdentity(dom) {
324
+ const response = await (dom.defaultView?.fetch.bind(dom.defaultView) ?? fetch)('/__codingns/session', {
325
+ credentials: 'same-origin',
326
+ cache: 'no-store',
327
+ headers: { Accept: 'application/json' },
328
+ });
329
+ if (!response.ok || !response.headers.get('content-type')?.includes('application/json'))
330
+ return null;
331
+ const value = await response.json();
332
+ return value.authenticated === true && typeof value.username === 'string'
333
+ ? { username: value.username }
334
+ : null;
335
+ }
336
+ function readRelayLoginIdentity() {
337
+ const token = readLoginProtectionSession();
338
+ if (token === undefined)
339
+ return null;
340
+ try {
341
+ const encoded = token.split('.', 1)[0];
342
+ if (encoded === undefined)
343
+ return null;
344
+ const padded = encoded.replace(/-/gu, '+').replace(/_/gu, '/');
345
+ const binary = atob(padded.padEnd(Math.ceil(padded.length / 4) * 4, '='));
346
+ const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
347
+ const payload = JSON.parse(new TextDecoder().decode(bytes));
348
+ if (payload.scope !== 'relay' || typeof payload.username !== 'string' || typeof payload.expiresAt !== 'number' || payload.expiresAt <= Date.now())
349
+ return null;
350
+ return { username: payload.username };
351
+ }
352
+ catch {
353
+ return null;
354
+ }
355
+ }
292
356
  function createAccountButton(dom) {
293
357
  const button = dom.createElement('button');
294
358
  button.type = 'button';
@@ -350,7 +414,7 @@ function createAccountIcon(dom) {
350
414
  function createMenu(dom) {
351
415
  const menu = dom.createElement('div');
352
416
  menu.setAttribute(MENU_ATTRIBUTE, '');
353
- Object.assign(menu.style, { position: 'fixed', zIndex: '10000', width: '260px', display: 'flex', flexDirection: 'column', gap: '8px', padding: '12px', boxSizing: 'border-box', color: 'var(--dsw-alias-label-primary, CanvasText)', background: 'var(--dsw-specific-menu, Canvas)', border: '1px solid var(--dsw-alias-border-l2, #d9d9d9)', borderRadius: '8px', boxShadow: 'var(--dsw-elevation-prominent, 0 12px 40px rgba(0,0,0,.25))', fontSize: '12px' });
417
+ Object.assign(menu.style, { position: 'fixed', zIndex: '10000', width: '260px', display: 'flex', flexDirection: 'column', gap: '8px', padding: '12px', boxSizing: 'border-box', color: dshThemeColor.labelPrimary, background: dshThemeColor.menuBackground, border: `1px solid ${dshThemeColor.border}`, borderRadius: '8px', boxShadow: dshThemeColor.prominentShadow, fontSize: '12px' });
354
418
  return menu;
355
419
  }
356
420
  function menuButtonStyle() { return { marginTop: '4px', minHeight: '30px', border: '1px solid var(--dsw-alias-border-l2, #d9d9d9)', borderRadius: '6px', color: 'inherit', background: 'transparent', cursor: 'pointer' }; }
@@ -379,13 +443,6 @@ function formatPercent(value) { return `${Math.round(value)}%`; }
379
443
  function formatBytes(value) { if (value < 1024 ** 3)
380
444
  return `${Math.round(value / 1024 ** 2)} MB`; return `${(value / 1024 ** 3).toFixed(1)} GB`; }
381
445
  function isRemoteContext() { return globalThis.__CODINGNS4DSH_REMOTE_WEB_CONTEXT__ === true; }
382
- function resolveAccountLogoutTarget() {
383
- if (isRemoteContext())
384
- return 'relay';
385
- if (typeof location !== 'undefined' && location.hostname.replace(/\.$/u, '').toLowerCase() === 'dsh.codingns.com')
386
- return 'relay';
387
- return 'local';
388
- }
389
446
  function relayModeLabel() {
390
447
  const state = globalThis;
391
448
  if (state.__CODINGNS4DSH_RELAY_MODE__ === 'relay')