@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
@@ -1,4 +1,5 @@
1
- import { createElement, useEffect, useState } from 'react';
1
+ import { createElement, useEffect, useRef, useState } from 'react';
2
+ import { sameSettingsValue } from '../../dsh-capabilities/settings-store.js';
2
3
  import { CODINGNS_CONTROL_STATION_URL, CODINGNS_CONTROL_BASE_URL_FIELD, CODINGNS_CONTROL_BASE_URLS_FIELD, CODINGNS_H5_LOGIN_URL, DEFAULT_CODINGNS_CONTROL_BASE_URLS, } from '../../shared/contracts/config.js';
3
4
  import { CODINGNS_RPC_CHANNEL } from '../../shared/contracts/transport.js';
4
5
  import { dshFormRootStyle, dshPopupSurfaceStyle, dshSettingsButtonStyle, dshSettingsFieldLabelStyle, dshSettingsFieldStyle, dshSettingsNoteStyle, dshSettingsPrimaryButtonStyle, dshSettingsRowStyle, dshThemeColor, } from '../theme.js';
@@ -25,14 +26,23 @@ export function ReverseProxyPanel({ services, enabled, snapshot, notify }) {
25
26
  const [selectedDeviceId, setSelectedDeviceId] = useState('');
26
27
  const [busy, setBusy] = useState(false);
27
28
  const [h5UrlCopied, setH5UrlCopied] = useState(false);
29
+ // 设置快照更新与写入互相触发时必须能收敛:同一个目标地址只写入一次,
30
+ // 否则一旦 Host 规范化或拒绝写入,就会形成 effect → publish → effect 的
31
+ // 无限重渲染(React #185)。
32
+ const lastPersistedControlBaseUrl = useRef(null);
28
33
  useEffect(() => {
29
34
  const saved = snapshot.value?.controlBaseUrl;
30
35
  const resolved = resolveControlBaseUrl(saved);
31
- setControlBaseUrls(uniqueControlBaseUrls(snapshot.value?.controlBaseUrls, resolved));
32
- setControlBaseUrl(resolved);
33
- if (snapshot.status === 'ready' && snapshot.writable && saved !== resolved) {
34
- void settings.set(CODINGNS_CONTROL_BASE_URL_FIELD, resolved).catch(() => undefined);
35
- }
36
+ const nextUrls = uniqueControlBaseUrls(snapshot.value?.controlBaseUrls, resolved);
37
+ // 内容未变化时保留原有状态引用,避免设置通知引起无意义的渲染。
38
+ setControlBaseUrls((current) => (sameSettingsValue(current, nextUrls) ? current : nextUrls));
39
+ setControlBaseUrl((current) => (current === resolved ? current : resolved));
40
+ if (snapshot.status !== 'ready' || !snapshot.writable || saved === resolved)
41
+ return;
42
+ if (lastPersistedControlBaseUrl.current === resolved)
43
+ return;
44
+ lastPersistedControlBaseUrl.current = resolved;
45
+ void settings.set(CODINGNS_CONTROL_BASE_URL_FIELD, resolved).catch(() => undefined);
36
46
  }, [settings, snapshot.status, snapshot.writable, snapshot.value?.controlBaseUrl, snapshot.value?.controlBaseUrls]);
37
47
  useEffect(() => {
38
48
  void callCodingNsRpc(rpc, 'auth/snapshot', {})
@@ -106,7 +116,13 @@ export function ReverseProxyPanel({ services, enabled, snapshot, notify }) {
106
116
  async function loadDevicesInternal() {
107
117
  const next = await callCodingNsRpc(rpc, 'auth/dsh/device/list', {});
108
118
  setDevices(next);
109
- const preferred = next.devices.find((device) => device.online && device.status === 'active')?.dshDeviceId ?? '';
119
+ const hasCurrentDevice = typeof next.currentDeviceId === 'string' && next.currentDeviceId.length > 0;
120
+ const current = !hasCurrentDevice
121
+ ? undefined
122
+ : next.devices.find((device) => device.dshDeviceId === next.currentDeviceId && device.status === 'active');
123
+ const preferred = hasCurrentDevice
124
+ ? current?.dshDeviceId ?? ''
125
+ : next.devices.find((device) => device.online && device.status === 'active')?.dshDeviceId ?? '';
110
126
  setSelectedDeviceId(preferred);
111
127
  }
112
128
  const addControlBaseUrl = async () => {
@@ -1,5 +1,4 @@
1
- import type { CodingNsClientFeatureModule } from './types.js';
2
- import type { CodingNsRpcClient } from './types.js';
1
+ import type { CodingNsClientFeatureModule, CodingNsRpcClient } from './types.js';
3
2
  /**
4
3
  * 中转访问服务模块。
5
4
  *
@@ -2,6 +2,7 @@ import { ReverseProxyPanel } from './reverse-proxy-panel.js';
2
2
  import { startDshH5Bootstrap } from '../dsh-h5-bootstrap.js';
3
3
  import { callCodingNsRpc } from '../settings-bridge.js';
4
4
  import { LOGIN_PROTECTION_SESSION_EVENT, readLoginProtectionSession } from './login-protection-session.js';
5
+ import { CODINGNS_DSH_ERROR_CODES } from '../../shared/index.js';
5
6
  function isRemoteWebContext() {
6
7
  return globalThis.__CODINGNS4DSH_REMOTE_WEB_CONTEXT__ === true;
7
8
  }
@@ -32,24 +33,42 @@ export const reverseProxyFeature = {
32
33
  * 接入连接后,流与订阅必须登记到 context.resources,由停用自动清理。
33
34
  */
34
35
  start(context) {
36
+ const runtime = globalThis;
37
+ const epoch = Symbol('codingns4dsh.reverse-proxy');
38
+ runtime.__CODINGNS4DSH_REVERSE_PROXY_EPOCH__ = epoch;
39
+ const isCurrent = () => runtime.__CODINGNS4DSH_REVERSE_PROXY_EPOCH__ === epoch;
35
40
  if (isRemoteWebContext()) {
36
41
  // 远程 DSH Web 的外层已经拥有有效 Tunnel;这里只保留设置 UI 和其它
37
42
  // 插件贡献,禁止同一页面重新申请票据并建立第二条中继连接。
38
- return () => { };
43
+ return () => { if (isCurrent())
44
+ delete runtime.__CODINGNS4DSH_REVERSE_PROXY_EPOCH__; };
45
+ }
46
+ // 页面级 Transport 已经在启动期由 DSH 或 Desktop 登记,动态功能不能在
47
+ // Cordis 启动后再次接管全局 Connection:两个 owner 会竞争同一个
48
+ // generation,插件自己的中继连接还会覆盖页面真实的传输实现。
49
+ // 独立 H5 页面使用专用入口(startDshH5BrowserBootstrap),不经过功能模块。
50
+ if (hasPageConnection(context.services)) {
51
+ return () => { if (isCurrent())
52
+ delete runtime.__CODINGNS4DSH_REVERSE_PROXY_EPOCH__; };
39
53
  }
40
54
  const abort = new AbortController();
41
55
  let disposeConnection;
42
56
  let retryTimer;
43
57
  let stopped = false;
44
58
  let waitingForLogin = false;
59
+ let attemptInFlight = false;
60
+ let connected = false;
61
+ let transportUnavailable = false;
45
62
  const onLoginProtectionSession = () => {
46
63
  waitingForLogin = false;
47
- void attempt();
64
+ if (!connected)
65
+ void attempt();
48
66
  };
49
67
  globalThis.addEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSession);
50
68
  const attempt = async () => {
51
- if (stopped || waitingForLogin)
69
+ if (!isCurrent() || stopped || waitingForLogin || connected || transportUnavailable || attemptInFlight)
52
70
  return;
71
+ attemptInFlight = true;
53
72
  try {
54
73
  const auth = await readAuthSnapshot(context.services.rpc);
55
74
  if (auth.status !== 'authenticated') {
@@ -62,19 +81,38 @@ export const reverseProxyFeature = {
62
81
  waitingForLogin = true;
63
82
  return;
64
83
  }
84
+ if (!isCurrent())
85
+ return;
65
86
  const dispose = await startBrowserRelayConnection(context.services.rpc, abort.signal, loginProtectionToken);
87
+ if (!isCurrent()) {
88
+ await dispose();
89
+ return;
90
+ }
66
91
  if (stopped || abort.signal.aborted) {
67
92
  await dispose();
68
93
  return;
69
94
  }
70
95
  disposeConnection = dispose;
96
+ connected = true;
97
+ if (retryTimer !== undefined) {
98
+ clearTimeout(retryTimer);
99
+ retryTimer = undefined;
100
+ }
71
101
  }
72
102
  catch (error) {
73
- if (stopped || abort.signal.aborted)
103
+ if (!isCurrent() || stopped || abort.signal.aborted)
104
+ return;
105
+ if (isTransportAlreadyRegistered(error)) {
106
+ // 这是生命周期冲突,不是网络瞬断;继续定时重试只会刷屏。
107
+ transportUnavailable = true;
74
108
  return;
109
+ }
75
110
  console.error('codingns4dsh: 中继连接建立失败,将在稍后重试', error);
76
111
  scheduleRetry();
77
112
  }
113
+ finally {
114
+ attemptInFlight = false;
115
+ }
78
116
  };
79
117
  const scheduleRetry = () => {
80
118
  if (retryTimer !== undefined || stopped || abort.signal.aborted)
@@ -84,18 +122,50 @@ export const reverseProxyFeature = {
84
122
  void attempt();
85
123
  return async () => {
86
124
  stopped = true;
125
+ connected = false;
87
126
  globalThis.removeEventListener(LOGIN_PROTECTION_SESSION_EVENT, onLoginProtectionSession);
88
127
  abort.abort();
89
128
  if (retryTimer !== undefined)
90
129
  clearTimeout(retryTimer);
91
130
  await disposeConnection?.();
131
+ if (isCurrent())
132
+ delete runtime.__CODINGNS4DSH_REVERSE_PROXY_EPOCH__;
92
133
  };
93
134
  },
94
135
  settingsPanel: ReverseProxyPanel,
95
136
  };
137
+ /**
138
+ * 本页是否已经由 DSH Client 持有页面级 Connection。
139
+ *
140
+ * 功能模块运行在 DSH Client 内部,页面级 Transport 已由 DSH 或 Desktop 在启动期
141
+ * 登记。这里只读取显式的连接服务:页面级 Transport 全局同时被 Desktop 壳、Host
142
+ * 启动页注入行和中继 iframe 桥三方写入,用它的存在性推断运行环境无法区分
143
+ * 「Desktop 页面」「Host 自己的 Web 页面」和「普通浏览器页面」,一旦它的写入策略
144
+ * 变化,中继模块的启停就会跟着漂移。
145
+ */
146
+ function hasPageConnection(services) {
147
+ const ctx = services.uiContext;
148
+ if (ctx === undefined || typeof ctx.get !== 'function')
149
+ return false;
150
+ try {
151
+ return ctx.get('connection') !== undefined;
152
+ }
153
+ catch {
154
+ return false;
155
+ }
156
+ }
157
+ function isTransportAlreadyRegistered(error) {
158
+ return typeof error === 'object' && error !== null
159
+ && error.code === CODINGNS_DSH_ERROR_CODES.TRANSPORT_NOT_READY;
160
+ }
96
161
  /** 浏览器侧真实中继连接;refresh token 和 access token 只经过 Host RPC。 */
97
162
  export async function startBrowserRelayConnection(rpc, signal, loginProtectionToken) {
98
- const bootstrap = await startDshH5Bootstrap({ rpc, signal, ...(loginProtectionToken === undefined ? {} : { loginProtectionToken }) });
163
+ const bootstrap = await startDshH5Bootstrap({
164
+ rpc,
165
+ signal,
166
+ ...(loginProtectionToken === undefined ? {} : { loginProtectionToken }),
167
+ getLoginProtectionToken: readLoginProtectionSession,
168
+ });
99
169
  const state = globalThis;
100
170
  state.__CODINGNS4DSH_RELAY_MODE__ = bootstrap.relayMode;
101
171
  return async () => {
@@ -5,6 +5,9 @@ import type { FeatureModule } from '../../shared/contracts/feature.js';
5
5
  import type { CodingNsSettings } from '../../shared/contracts/config.js';
6
6
  import type { CodingNsLocale } from '../locale.js';
7
7
  import type { CodingNsSettingsSnapshot, CodingNsSettingsStore } from '../../dsh-capabilities/settings-store.js';
8
+ import type { PeerHostScopedClient } from '../peer-host-scoped-client.js';
9
+ import type { HostRouter } from '../host-router.js';
10
+ import type { PeerHostSessionController } from '../peer-host-session-controller.js';
8
11
  /** 一次 Codingns4DSH RPC 的结果,与 DSH Connection 的结果形状一致。 */
9
12
  export type CodingNsRpcResult = {
10
13
  readonly ok: true;
@@ -26,6 +29,12 @@ export interface CodingNsClientServices {
26
29
  readonly dshVersion: string;
27
30
  readonly settings: CodingNsSettingsStore<CodingNsSettings>;
28
31
  readonly rpc: CodingNsRpcClient;
32
+ /** PeerHost 远端资源适配器;请求始终绑定 HostScope。 */
33
+ readonly peerHost: PeerHostScopedClient;
34
+ /** 所有跨 Host 资源共用的 generation 路由器。 */
35
+ readonly hostRouter: HostRouter;
36
+ /** 远端会话的唯一控制入口;与 hostRouter 共享 generation 和清理生命周期。 */
37
+ readonly peerHostSession: PeerHostSessionController;
29
38
  /** DSH Typert Remote;归档会话模块只通过运行时探测调用可选方法。 */
30
39
  readonly remote?: unknown;
31
40
  /** Codingns4DSH 自有终端 Remote;调试页不能依赖已停用的 DSH 官方 terminal。 */
@@ -83,6 +83,16 @@ export function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot,
83
83
  disabled,
84
84
  onChange: (event) => updateSetting('showQuickPhrases', event.currentTarget.checked),
85
85
  style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
86
+ })), createElement('label', {
87
+ style: dshSettingsListRowStyle,
88
+ }, createElement('span', { style: { minWidth: 0 } }, createElement('strong', { style: { display: 'block', fontSize: 13, lineHeight: 1.4 } }, t('workspace.rememberConversationRightbarRatio')), createElement('span', { style: { display: 'block', marginTop: 3, ...dshSettingsHelpStyle } }, t('workspace.rememberConversationRightbarRatioDescription'))), createElement('input', {
89
+ type: 'checkbox',
90
+ role: 'switch',
91
+ 'aria-label': t('workspace.rememberConversationRightbarRatio'),
92
+ checked: value.rememberConversationRightbarRatio,
93
+ disabled,
94
+ onChange: (event) => updateSetting('rememberConversationRightbarRatio', event.currentTarget.checked),
95
+ style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
86
96
  })));
87
97
  }
88
98
  //# sourceMappingURL=workspace-session-enhancement-panel.js.map
@@ -6,6 +6,7 @@ import { startWorkspaceSessionVisibilityDom } from '../workspace-session-visibil
6
6
  import { WorkspaceSessionEnhancementPanel } from './workspace-session-enhancement-panel.js';
7
7
  import { registerSubscriptionSlot } from '../subscription-slot.js';
8
8
  import { registerQuickPhraseSlot } from '../quick-phrase-slot.js';
9
+ import { startWorkspaceSessionRightbarDom } from '../workspace-session-rightbar-dom.js';
9
10
  /** DSH 0.1.6 原生会话行增强:Logo 与归档会话入口共用同一生命周期。 */
10
11
  export const workspaceSessionEnhancementFeature = {
11
12
  descriptor: {
@@ -16,7 +17,7 @@ export const workspaceSessionEnhancementFeature = {
16
17
  runtime: 'client',
17
18
  ui: {
18
19
  label: '工作区会话增强',
19
- description: '在原生工作区会话行显示 Agent Logo、归档入口、工作区隐藏/恢复入口和订阅/用量信息,并提供本地快捷会话。',
20
+ description: '在原生工作区会话行显示 Agent Logo、归档入口、工作区隐藏/恢复入口和订阅/用量信息,提供本地快捷会话,并可记忆对话窗口与右侧栏宽度比例。',
20
21
  labelKey: 'feature.workspaceSession.label',
21
22
  descriptionKey: 'feature.workspaceSession.description',
22
23
  order: 35,
@@ -30,6 +31,7 @@ export const workspaceSessionEnhancementFeature = {
30
31
  let logoDom;
31
32
  let archiveDom;
32
33
  let visibilityDom;
34
+ let rightbarDom;
33
35
  let adapterRefreshTimer;
34
36
  let disposeSubscription;
35
37
  let disposeQuickPhrases;
@@ -68,6 +70,14 @@ export const workspaceSessionEnhancementFeature = {
68
70
  visibilityDom?.dispose();
69
71
  visibilityDom = undefined;
70
72
  };
73
+ const enableRightbarMemory = () => {
74
+ if (rightbarDom === undefined)
75
+ rightbarDom = startWorkspaceSessionRightbarDom();
76
+ };
77
+ const disableRightbarMemory = () => {
78
+ rightbarDom?.dispose();
79
+ rightbarDom = undefined;
80
+ };
71
81
  const enableSubscription = () => {
72
82
  if (disposeSubscription !== undefined || context.services.slots === undefined)
73
83
  return;
@@ -91,6 +101,7 @@ export const workspaceSessionEnhancementFeature = {
91
101
  archiveDom?.dispose();
92
102
  archiveDom = undefined;
93
103
  disableWorkspaceVisibility();
104
+ disableRightbarMemory();
94
105
  disableSubscription();
95
106
  disableQuickPhrases();
96
107
  };
@@ -151,6 +162,12 @@ export const workspaceSessionEnhancementFeature = {
151
162
  enableQuickPhrases();
152
163
  else
153
164
  disableQuickPhrases();
165
+ const rememberConversationRightbarRatio = workspaceSettings?.rememberConversationRightbarRatio
166
+ ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS.rememberConversationRightbarRatio;
167
+ if (rememberConversationRightbarRatio)
168
+ enableRightbarMemory();
169
+ else
170
+ disableRightbarMemory();
154
171
  };
155
172
  sync();
156
173
  const unsubscribe = context.services.settings.subscribe(sync);
@@ -0,0 +1,12 @@
1
+ import type { CodingNsRpcClient } from './features/types.js';
2
+ export interface FileManagementDomOptions {
3
+ readonly menuEnhancement: boolean;
4
+ readonly fileEditor: boolean;
5
+ }
6
+ export interface FileManagementDomController {
7
+ setOptions(options: FileManagementDomOptions): void;
8
+ dispose(): void;
9
+ }
10
+ /** 给 DSH 原生文件树和文本查看器补充文件操作,不接管 DSH 自己的渲染状态。 */
11
+ export declare function startFileManagementDom(rpc: CodingNsRpcClient, initialOptions: FileManagementDomOptions): FileManagementDomController;
12
+ //# sourceMappingURL=file-management-dom.d.ts.map