@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,8 +1,9 @@
1
1
  import { createElement, useEffect, useState } from 'react';
2
2
  import { CODINGNS_TERMINAL_ENHANCEMENT_FIELD, DEFAULT_TERMINAL_ENHANCEMENT_SETTINGS, } from '../../shared/contracts/config.js';
3
3
  import { CODINGNS_RPC_CHANNEL } from '../../shared/contracts/transport.js';
4
- import { dshFormRootStyle, dshSettingsButtonStyle, dshSettingsFieldLabelStyle, dshSettingsFieldStyle, dshSettingsHelpStyle, dshSettingsNoteStyle, dshSettingsRowStyle, dshThemeColor, } from '../theme.js';
4
+ import { dshFormRootStyle, dshSettingsButtonStyle, dshSettingsFieldLabelStyle, dshSettingsFieldStyle, dshSettingsGridStyle, dshSettingsHelpStyle, dshSettingsNoteStyle, dshSettingsRowStyle, dshSettingsSectionHeaderStyle, dshThemeColor, } from '../theme.js';
5
5
  import { useCodingNsTranslator } from '../locale.js';
6
+ import { debugInfo, debugWarn } from '../../shared/debug.js';
6
7
  const profileLabels = {
7
8
  system: 'terminal.systemRecommended',
8
9
  zsh: 'zsh',
@@ -12,15 +13,12 @@ const profileLabels = {
12
13
  'git-bash': 'Git Bash',
13
14
  };
14
15
  /** 终端默认行为与外观设置;终端 UI 由独立 Sidebar 模块负责。 */
15
- export function TerminalEnhancementPanel({ services, enabled, snapshot }) {
16
+ export function TerminalEnhancementPanel({ services, enabled, snapshot, notify }) {
16
17
  const t = useCodingNsTranslator(services.locale);
17
18
  const value = snapshot.value?.terminalEnhancement ?? DEFAULT_TERMINAL_ENHANCEMENT_SETTINGS;
18
- const [fontFamily, setFontFamily] = useState(value.appearance.fontFamily ?? '');
19
- const [message, setMessage] = useState('');
19
+ const appearance = resolveAppearance(value.appearance);
20
20
  const [hostStatus, setHostStatus] = useState(null);
21
21
  const disabled = !enabled || snapshot.status === 'loading' || !snapshot.writable;
22
- const customDisabled = disabled || value.appearance.theme !== 'custom';
23
- useEffect(() => setFontFamily(value.appearance.fontFamily ?? ''), [value.appearance.fontFamily]);
24
22
  useEffect(() => {
25
23
  let active = true;
26
24
  void callTerminalStatus(services.rpc)
@@ -28,38 +26,45 @@ export function TerminalEnhancementPanel({ services, enabled, snapshot }) {
28
26
  setHostStatus(status); })
29
27
  .catch((error) => {
30
28
  if (active)
31
- setMessage(error instanceof Error ? error.message : String(error));
29
+ notify({ kind: 'error', message: error instanceof Error ? error.message : String(error) });
32
30
  });
33
31
  return () => { active = false; };
34
32
  }, [services.rpc]);
35
33
  const save = (next) => {
36
- setMessage('');
34
+ debugInfo('codingns4dsh: client terminal settings write begin', {
35
+ field: CODINGNS_TERMINAL_ENHANCEMENT_FIELD,
36
+ bindingScope: next.bindingScope ?? 'workspace',
37
+ });
37
38
  void services.settings.set(CODINGNS_TERMINAL_ENHANCEMENT_FIELD, next)
38
- .then(() => setMessage(t('terminal.saved')))
39
- .catch((error) => setMessage(error instanceof Error ? error.message : String(error)));
39
+ .then((written) => {
40
+ if (!written) {
41
+ debugWarn('codingns4dsh: client terminal settings write rejected');
42
+ throw new Error(t('terminal.saveRejected'));
43
+ }
44
+ debugInfo('codingns4dsh: client terminal settings write success', {
45
+ bindingScope: next.bindingScope ?? 'workspace',
46
+ });
47
+ notify({ kind: 'success', message: t('terminal.saved') });
48
+ })
49
+ .catch((error) => notify({ kind: 'error', message: error instanceof Error ? error.message : String(error) }));
40
50
  };
41
51
  const updateAppearance = (patch) => {
42
- save({ ...value, appearance: { ...value.appearance, ...patch } });
52
+ save({ ...value, appearance: { ...value.appearance, theme: 'custom', ...patch } });
43
53
  };
44
- const saveFontFamily = () => {
45
- try {
46
- updateAppearance({ fontFamily: normalizeFontFamily(fontFamily) });
47
- }
48
- catch (error) {
49
- setMessage(error instanceof Error ? error.message : String(error));
50
- }
54
+ const resetAppearance = () => {
55
+ save({ ...value, appearance: { ...DEFAULT_TERMINAL_ENHANCEMENT_SETTINGS.appearance, theme: 'custom' } });
51
56
  };
52
57
  return createElement('div', {
53
58
  'aria-disabled': disabled,
54
59
  style: { ...dshFormRootStyle, display: 'flex', flexDirection: 'column', gap: 16, opacity: disabled ? 0.5 : 1, pointerEvents: disabled ? 'none' : 'auto' },
55
60
  }, createElement('div', { role: 'note', style: noteStyle }, t('terminal.restartNote')), createElement('div', { role: 'status', style: noteStyle }, hostStatus === null
56
61
  ? t('terminal.readingStatus')
57
- : t('terminal.currentStatus', { status: hostStatus.effectiveEnabled ? t('terminal.enhanced') : t('terminal.basic'), platform: platformLabel(hostStatus.platform, t) })), createElement(Field, { label: t('terminal.newDefault') }, createElement('select', {
62
+ : t('terminal.currentStatus', { status: hostStatus.effectiveEnabled ? t('terminal.enhanced') : t('terminal.basic'), platform: platformLabel(hostStatus.platform, t) })), createElement(Field, { label: t('terminal.newDefault'), help: t('terminal.defaultProfileHelp') }, createElement('select', {
58
63
  value: value.defaultProfile,
59
64
  disabled,
60
65
  onChange: (event) => save({ ...value, defaultProfile: event.currentTarget.value }),
61
66
  style: fieldStyle,
62
- }, ...profileOptions(value.defaultProfile, hostStatus, t).map((profile) => createElement('option', { key: profile.profileId, value: profile.profileId, disabled: !profile.available }, profile.label))), createElement('small', { style: helpStyle }, t('terminal.defaultProfileHelp')), hostStatus?.fallbackReason === undefined ? null : createElement('small', { style: helpStyle }, hostStatus.fallbackReason)), createElement(Field, { label: t('terminal.bindingScope') }, createElement('select', {
67
+ }, ...profileOptions(value.defaultProfile, hostStatus, t).map((profile) => createElement('option', { key: profile.profileId, value: profile.profileId, disabled: !profile.available }, profile.label))), hostStatus?.fallbackReason === undefined ? null : createElement('small', { style: helpStyle }, hostStatus.fallbackReason)), createElement(Field, { label: t('terminal.bindingScope'), help: t('terminal.workspaceBindingHelp') }, createElement('select', {
63
68
  value: value.bindingScope ?? 'workspace',
64
69
  disabled,
65
70
  onChange: (event) => save({
@@ -67,42 +72,50 @@ export function TerminalEnhancementPanel({ services, enabled, snapshot }) {
67
72
  bindingScope: event.currentTarget.value === 'session' ? 'session' : 'workspace',
68
73
  }),
69
74
  style: fieldStyle,
70
- }, createElement('option', { value: 'workspace' }, t('terminal.workspaceBinding')), createElement('option', { value: 'session' }, t('terminal.sessionBinding'))), createElement('small', { style: helpStyle }, t('terminal.workspaceBindingHelp'))), createElement(Field, { label: t('terminal.theme') }, createElement('select', {
71
- value: value.appearance.theme,
72
- disabled,
73
- onChange: (event) => updateAppearance({ theme: event.currentTarget.value === 'custom' ? 'custom' : 'inherit' }),
74
- style: fieldStyle,
75
- }, createElement('option', { value: 'inherit' }, t('terminal.inheritDshTheme')), createElement('option', { value: 'custom' }, t('terminal.custom')))), createElement(ColorField, { label: t('terminal.background'), value: value.appearance.background, disabled: customDisabled, onChange: (background) => updateAppearance({ background }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), createElement(ColorField, { label: t('terminal.foreground'), value: value.appearance.foreground, disabled: customDisabled, onChange: (foreground) => updateAppearance({ foreground }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), createElement(ColorField, { label: t('terminal.cursorColor'), value: value.appearance.cursorColor, disabled: customDisabled, onChange: (cursorColor) => updateAppearance({ cursorColor }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), createElement(Field, { label: t('terminal.font') }, createElement('div', { style: rowStyle }, createElement('input', {
76
- type: 'text', value: fontFamily, maxLength: 128, disabled: customDisabled,
77
- placeholder: t('terminal.inheritFont'),
78
- onChange: (event) => setFontFamily(event.currentTarget.value),
79
- onBlur: saveFontFamily,
80
- style: { ...fieldStyle, flex: 1, minWidth: 0 },
81
- }), createElement(ResetButton, { disabled: customDisabled || value.appearance.fontFamily === null, onClick: () => { setFontFamily(''); updateAppearance({ fontFamily: null }); }, label: t('terminal.resetInherit') }))), createElement(NumberField, { label: t('terminal.fontSize'), value: value.appearance.fontSize, min: 10, max: 32, step: 1, disabled: customDisabled, onChange: (fontSize) => updateAppearance({ fontSize }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), createElement(NumberField, { label: t('terminal.lineHeight'), value: value.appearance.lineHeight, min: 1, max: 2, step: 0.1, disabled: customDisabled, onChange: (lineHeight) => updateAppearance({ lineHeight }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), createElement(Field, { label: t('terminal.cursorShape') }, createElement('select', {
82
- value: value.appearance.cursorStyle ?? '', disabled: customDisabled,
83
- onChange: (event) => updateAppearance({ cursorStyle: parseCursorStyle(event.currentTarget.value) }),
84
- style: fieldStyle,
85
- }, createElement('option', { value: '' }, t('terminal.cursorInherit')), createElement('option', { value: 'block' }, t('terminal.cursorBlock')), createElement('option', { value: 'bar' }, t('terminal.cursorBar')), createElement('option', { value: 'underline' }, t('terminal.cursorUnderline')))), createElement(Field, { label: t('terminal.cursorBlink') }, createElement('div', { style: rowStyle }, createElement('label', { style: { display: 'inline-flex', alignItems: 'center', gap: 8 } }, createElement('input', {
75
+ }, createElement('option', { value: 'workspace' }, t('terminal.workspaceBinding')), createElement('option', { value: 'session' }, t('terminal.sessionBinding')))), createElement('div', { style: dshSettingsSectionHeaderStyle }, createElement('h3', { style: { margin: 0, color: dshThemeColor.labelPrimary, fontSize: 14, lineHeight: 1.35 } }, t('terminal.appearanceTitle')), createElement('button', { type: 'button', disabled, onClick: resetAppearance, style: { ...buttonStyle, minWidth: 132 } }, t('terminal.resetAppearance'))), createElement('div', { style: dshSettingsGridStyle }, createElement(ColorField, { label: t('terminal.background'), value: appearance.background, disabled, onChange: (background) => updateAppearance({ background }) }), createElement(ColorField, { label: t('terminal.foreground'), value: appearance.foreground, disabled, onChange: (foreground) => updateAppearance({ foreground }) }), createElement(ColorField, { label: t('terminal.cursorColor'), value: appearance.cursorColor, disabled, onChange: (cursorColor) => updateAppearance({ cursorColor }) }), createElement(Field, { label: t('terminal.cursorBlink') }, createElement('label', { style: { display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 36, opacity: disabled ? 0.6 : 1 } }, createElement('input', {
86
76
  type: 'checkbox', role: 'switch', 'aria-label': t('terminal.cursorBlink'),
87
- checked: value.appearance.cursorBlink ?? false, disabled: customDisabled,
77
+ checked: appearance.cursorBlink, disabled,
88
78
  onChange: (event) => updateAppearance({ cursorBlink: event.currentTarget.checked }),
89
- }), value.appearance.cursorBlink === null ? t('terminal.inherit') : (value.appearance.cursorBlink ? t('terminal.cursorOn') : t('terminal.cursorOff'))), createElement(ResetButton, { disabled: customDisabled || value.appearance.cursorBlink === null, onClick: () => updateAppearance({ cursorBlink: null }), label: t('terminal.resetInherit') }))), createElement(NumberField, { label: t('terminal.scrollback'), value: value.appearance.scrollback, min: 1000, max: 100000, step: 1000, disabled, onChange: (scrollback) => updateAppearance({ scrollback }), inheritLabel: t('terminal.inherit'), resetLabel: t('terminal.resetInherit') }), message && createElement('div', { role: 'status', style: { color: message.includes('已保存') ? dshThemeColor.success : dshThemeColor.error } }, message));
79
+ }), appearance.cursorBlink ? t('terminal.cursorOn') : t('terminal.cursorOff'))), createElement(NumberField, { label: t('terminal.fontSize'), value: appearance.fontSize, min: 10, max: 32, step: 1, disabled, onChange: (fontSize) => updateAppearance({ fontSize }) }), createElement(NumberField, { label: t('terminal.lineHeight'), value: appearance.lineHeight, min: 1, max: 2, step: 0.1, disabled, onChange: (lineHeight) => updateAppearance({ lineHeight }) }), createElement(Field, { label: t('terminal.cursorShape') }, createElement('select', {
80
+ value: appearance.cursorStyle, disabled,
81
+ onChange: (event) => updateAppearance({ cursorStyle: parseCursorStyle(event.currentTarget.value) }),
82
+ style: fieldStyle,
83
+ }, createElement('option', { value: 'block' }, t('terminal.cursorBlock')), createElement('option', { value: 'bar' }, t('terminal.cursorBar')), createElement('option', { value: 'underline' }, t('terminal.cursorUnderline')))), createElement(NumberField, { label: t('terminal.scrollback'), value: appearance.scrollback, min: 1000, max: 100000, step: 1000, disabled, onChange: (scrollback) => updateAppearance({ scrollback }) })));
84
+ }
85
+ function Field({ label, help, children }) {
86
+ return createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 6 } }, createElement('div', { style: fieldHeadingStyle }, createElement('span', { style: dshSettingsFieldLabelStyle }, label), help === undefined ? null : createElement(InfoButton, { label: help })), children);
90
87
  }
91
- function Field({ label, children }) {
92
- return createElement('label', { style: { display: 'flex', flexDirection: 'column', gap: 6 } }, createElement('span', { style: dshSettingsFieldLabelStyle }, label), children);
88
+ function InfoButton({ label }) {
89
+ return createElement('button', {
90
+ type: 'button',
91
+ title: label,
92
+ 'aria-label': label,
93
+ style: infoButtonStyle,
94
+ }, 'ⓘ');
93
95
  }
94
- function ColorField({ label, value, disabled, onChange, inheritLabel, resetLabel }) {
95
- return createElement(Field, { label }, createElement('div', { style: rowStyle }, createElement('input', { type: 'color', value: value ?? '#000000', disabled, 'aria-label': label, onChange: (event) => onChange(event.currentTarget.value), style: { width: 48, height: 34 } }), createElement('code', { style: { flex: 1 } }, value ?? inheritLabel), createElement(ResetButton, { disabled: disabled || value === null, onClick: () => onChange(null), label: resetLabel })));
96
+ function ColorField({ label, value, disabled, onChange }) {
97
+ return createElement(Field, { label }, createElement('div', { style: rowStyle }, createElement('input', { type: 'color', value, disabled, 'aria-label': label, onChange: (event) => onChange(event.currentTarget.value), style: { width: 48, height: 34 } }), createElement('code', { style: { flex: 1 } }, value)));
96
98
  }
97
- function NumberField({ label, value, min, max, step, disabled, onChange, inheritLabel, resetLabel }) {
99
+ function NumberField({ label, value, min, max, step, disabled, onChange }) {
98
100
  return createElement(Field, { label }, createElement('div', { style: rowStyle }, createElement('input', {
99
- type: 'number', value: value ?? '', min, max, step, disabled, placeholder: inheritLabel,
101
+ type: 'number', value, min, max, step, disabled,
100
102
  onChange: (event) => onChange(event.currentTarget.value === '' ? null : Number(event.currentTarget.value)),
101
103
  style: { ...fieldStyle, flex: 1, minWidth: 0 },
102
- }), createElement(ResetButton, { disabled: disabled || value === null, onClick: () => onChange(null), label: resetLabel })));
104
+ })));
103
105
  }
104
- function ResetButton({ disabled, onClick, label }) {
105
- return createElement('button', { type: 'button', disabled, onClick, style: buttonStyle }, label);
106
+ /** 将旧配置中的 null 映射为 xterm 当前实际使用的默认值,设置页始终显示可编辑值。 */
107
+ function resolveAppearance(appearance) {
108
+ const foreground = appearance.foreground ?? '#f3f3f3';
109
+ return {
110
+ background: appearance.background ?? '#111111',
111
+ foreground,
112
+ cursorColor: appearance.cursorColor ?? foreground,
113
+ fontSize: appearance.fontSize ?? 13,
114
+ lineHeight: appearance.lineHeight ?? 1,
115
+ cursorStyle: appearance.cursorStyle ?? 'block',
116
+ cursorBlink: appearance.cursorBlink ?? true,
117
+ scrollback: appearance.scrollback ?? 1000,
118
+ };
106
119
  }
107
120
  function profileOptions(selected, status, t) {
108
121
  if (status === null)
@@ -141,14 +154,6 @@ async function callTerminalStatus(rpc) {
141
154
  throw new Error(response.error.message);
142
155
  return response.value;
143
156
  }
144
- function normalizeFontFamily(value) {
145
- const trimmed = value.trim();
146
- if (trimmed === '')
147
- return null;
148
- if (trimmed.length > 128 || /[\u0000-\u001F\u007F]/u.test(trimmed))
149
- throw new TypeError('字体名称格式无效');
150
- return trimmed;
151
- }
152
157
  function parseCursorStyle(value) {
153
158
  return value === 'block' || value === 'bar' || value === 'underline' ? value : null;
154
159
  }
@@ -157,4 +162,6 @@ const buttonStyle = { ...dshSettingsButtonStyle, flex: '0 0 auto', minWidth: 92
157
162
  const rowStyle = dshSettingsRowStyle;
158
163
  const helpStyle = dshSettingsHelpStyle;
159
164
  const noteStyle = dshSettingsNoteStyle;
165
+ const fieldHeadingStyle = { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 };
166
+ const infoButtonStyle = { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 20, height: 20, flex: '0 0 20px', padding: 0, border: `1px solid ${dshThemeColor.border}`, borderRadius: '50%', color: dshThemeColor.labelSecondary, background: dshThemeColor.surfaceSubtle, cursor: 'help', fontSize: 12, lineHeight: 1 };
160
167
  //# sourceMappingURL=terminal-enhancement-panel.js.map
@@ -1,4 +1,4 @@
1
1
  import type { CodingNsClientFeatureModule } from './types.js';
2
- /** “终端强化”只切换 backend;插件 controller 与 Sidebar UI 始终存在。 */
2
+ /** “终端增强”只切换 backend;插件 controller 与 Sidebar UI 始终存在。 */
3
3
  export declare const terminalEnhancementFeature: CodingNsClientFeatureModule;
4
4
  //# sourceMappingURL=terminal-enhancement.d.ts.map
@@ -1,15 +1,15 @@
1
1
  import { TerminalEnhancementPanel } from './terminal-enhancement-panel.js';
2
- /** “终端强化”只切换 backend;插件 controller 与 Sidebar UI 始终存在。 */
2
+ /** “终端增强”只切换 backend;插件 controller 与 Sidebar UI 始终存在。 */
3
3
  export const terminalEnhancementFeature = {
4
4
  descriptor: {
5
5
  name: 'terminalEnhancement',
6
- version: '0.1.0',
6
+ version: '0.1.1',
7
7
  enabledByDefault: false,
8
8
  dependencies: [],
9
9
  runtime: 'client',
10
10
  activation: 'restart',
11
11
  ui: {
12
- label: '终端强化',
12
+ label: '终端增强',
13
13
  description: '配置持久终端的默认 shell 与插件终端外观。启用和禁用均需重启 DSH。',
14
14
  labelKey: 'feature.terminal.label',
15
15
  descriptionKey: 'feature.terminal.description',
@@ -1,10 +1,10 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
3
  import type { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
4
- import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
5
4
  import type { FeatureModule } from '../../shared/contracts/feature.js';
6
5
  import type { CodingNsSettings } from '../../shared/contracts/config.js';
7
6
  import type { CodingNsLocale } from '../locale.js';
7
+ import type { CodingNsSettingsSnapshot, CodingNsSettingsStore } from '../../dsh-capabilities/settings-store.js';
8
8
  /** 一次 Codingns4DSH RPC 的结果,与 DSH Connection 的结果形状一致。 */
9
9
  export type CodingNsRpcResult = {
10
10
  readonly ok: true;
@@ -24,10 +24,12 @@ export interface CodingNsRpcClient {
24
24
  export interface CodingNsClientServices {
25
25
  /** 当前 DSH 实际运行版本,由 Host 注入。 */
26
26
  readonly dshVersion: string;
27
- readonly settings: SettingsScope<CodingNsSettings>;
27
+ readonly settings: CodingNsSettingsStore<CodingNsSettings>;
28
28
  readonly rpc: CodingNsRpcClient;
29
29
  /** DSH Typert Remote;归档会话模块只通过运行时探测调用可选方法。 */
30
30
  readonly remote?: unknown;
31
+ /** Codingns4DSH 自有终端 Remote;调试页不能依赖已停用的 DSH 官方 terminal。 */
32
+ readonly terminalRemote?: () => unknown;
31
33
  /** DSH 语言运行时;所有 Client 文案都从 Codingns4DSH 命名空间读取。 */
32
34
  readonly locale: CodingNsLocale;
33
35
  /** DSH 对话装配服务;用于注册不写入 Session 的流式临时节点。 */
@@ -37,6 +39,13 @@ export interface CodingNsClientServices {
37
39
  /** 当前 Client Cordis 上下文;只供需要注册 DSH UI Slot 的功能模块使用。 */
38
40
  readonly uiContext?: Context;
39
41
  }
42
+ /** 设置页统一反馈的提示级别。 */
43
+ export type SettingsNoticeKind = 'success' | 'error' | 'info';
44
+ /** 由功能面板提交给设置页顶部 Toast 的反馈。 */
45
+ export interface SettingsNotice {
46
+ readonly kind: SettingsNoticeKind;
47
+ readonly message: string;
48
+ }
40
49
  /** 设置卡片传给模块面板的属性。 */
41
50
  export interface FeaturePanelProps {
42
51
  /** 宿主注入的服务,与模块 start 中拿到的是同一份。 */
@@ -44,7 +53,9 @@ export interface FeaturePanelProps {
44
53
  /** 当前是否启用;未启用时面板需要自行灰显并禁用输入。 */
45
54
  readonly enabled: boolean;
46
55
  /** 设置快照,用于读取表单初值和可写状态。 */
47
- readonly snapshot: SettingsScopeSnapshot<CodingNsSettings>;
56
+ readonly snapshot: CodingNsSettingsSnapshot<CodingNsSettings>;
57
+ /** 将设置写入结果显示在设置区域顶部。 */
58
+ readonly notify: (notice: SettingsNotice) => void;
48
59
  }
49
60
  /**
50
61
  * 可在浏览器侧启停、并可出现在设置页的功能模块。
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import type { FeaturePanelProps } from './types.js';
3
3
  /** 工作区会话增强的单列设置面板。 */
4
- export declare function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot }: FeaturePanelProps): ReactElement;
4
+ export declare function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot, notify }: FeaturePanelProps): ReactElement;
5
5
  //# sourceMappingURL=workspace-session-enhancement-panel.d.ts.map
@@ -1,22 +1,26 @@
1
- import { createElement, useState } from 'react';
1
+ import { createElement } from 'react';
2
2
  import { CODINGNS_WORKSPACE_SESSION_ENHANCEMENT_FIELD, DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS, } from '../../shared/contracts/config.js';
3
3
  import { dshFormRootStyle, dshSettingsHelpStyle, dshSettingsListRowStyle, dshThemeColor, } from '../theme.js';
4
4
  import { useCodingNsTranslator } from '../locale.js';
5
5
  /** 工作区会话增强的单列设置面板。 */
6
- export function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot }) {
6
+ export function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot, notify }) {
7
7
  const t = useCodingNsTranslator(services.locale);
8
- const [writeError, setWriteError] = useState(null);
9
8
  const value = snapshot.value?.workspaceSessionEnhancement
10
9
  ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS;
11
10
  const disabled = !enabled || snapshot.status === 'loading' || !snapshot.writable;
12
11
  const updateSetting = (field, nextValue) => {
13
- setWriteError(null);
14
12
  void services.settings.mutate([{
15
13
  op: 'set',
16
14
  path: [CODINGNS_WORKSPACE_SESSION_ENHANCEMENT_FIELD, field],
17
15
  value: nextValue,
18
- }]).catch((cause) => {
19
- setWriteError(cause instanceof Error ? cause.message : String(cause));
16
+ }]).then((accepted) => {
17
+ if (!accepted) {
18
+ notify({ kind: 'error', message: t('settings.moduleWriteRejected') });
19
+ return;
20
+ }
21
+ notify({ kind: 'success', message: '工作区会话设置已保存' });
22
+ }).catch((cause) => {
23
+ notify({ kind: 'error', message: cause instanceof Error ? cause.message : String(cause) });
20
24
  });
21
25
  };
22
26
  return createElement('div', {
@@ -41,6 +45,16 @@ export function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot }
41
45
  style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
42
46
  })), createElement('label', {
43
47
  style: dshSettingsListRowStyle,
48
+ }, createElement('span', { style: { minWidth: 0 } }, createElement('strong', { style: { display: 'block', fontSize: 13, lineHeight: 1.4 } }, t('workspace.showWorkspaceHiding')), createElement('span', { style: { display: 'block', marginTop: 3, ...dshSettingsHelpStyle } }, t('workspace.workspaceHidingDescription'))), createElement('input', {
49
+ type: 'checkbox',
50
+ role: 'switch',
51
+ 'aria-label': t('workspace.showWorkspaceHiding'),
52
+ checked: value.showWorkspaceHiding,
53
+ disabled,
54
+ onChange: (event) => updateSetting('showWorkspaceHiding', event.currentTarget.checked),
55
+ style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
56
+ })), createElement('label', {
57
+ style: dshSettingsListRowStyle,
44
58
  }, createElement('span', { style: { minWidth: 0 } }, createElement('strong', { style: { display: 'block', fontSize: 13, lineHeight: 1.4 } }, t('workspace.showSubscriptionUsage')), createElement('span', { style: { display: 'block', marginTop: 3, ...dshSettingsHelpStyle } }, t('workspace.subscriptionUsageDescription'))), createElement('input', {
45
59
  type: 'checkbox',
46
60
  role: 'switch',
@@ -59,8 +73,16 @@ export function WorkspaceSessionEnhancementPanel({ services, enabled, snapshot }
59
73
  disabled,
60
74
  onChange: (event) => updateSetting('showArchivedSessions', event.currentTarget.checked),
61
75
  style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
62
- })), writeError === null
63
- ? null
64
- : createElement('div', { role: 'alert', style: { color: dshThemeColor.error, fontSize: 12 } }, writeError));
76
+ })), createElement('label', {
77
+ style: dshSettingsListRowStyle,
78
+ }, createElement('span', { style: { minWidth: 0 } }, createElement('strong', { style: { display: 'block', fontSize: 13, lineHeight: 1.4 } }, t('workspace.showQuickPhrases')), createElement('span', { style: { display: 'block', marginTop: 3, ...dshSettingsHelpStyle } }, t('workspace.quickPhrasesDescription'))), createElement('input', {
79
+ type: 'checkbox',
80
+ role: 'switch',
81
+ 'aria-label': t('workspace.showQuickPhrases'),
82
+ checked: value.showQuickPhrases,
83
+ disabled,
84
+ onChange: (event) => updateSetting('showQuickPhrases', event.currentTarget.checked),
85
+ style: { flex: '0 0 auto', accentColor: dshThemeColor.accent },
86
+ })));
65
87
  }
66
88
  //# sourceMappingURL=workspace-session-enhancement-panel.js.map
@@ -2,19 +2,21 @@ import { DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS } from '../../shared/con
2
2
  import { clearSessionAdapters, fetchSessionAdapters, replaceSessionAdapters, } from '../session-adapter-cache.js';
3
3
  import { startWorkspaceSessionLogoDom } from '../workspace-session-logo-dom.js';
4
4
  import { startWorkspaceSessionArchiveDom } from '../workspace-session-archive-dom.js';
5
+ import { startWorkspaceSessionVisibilityDom } from '../workspace-session-visibility-dom.js';
5
6
  import { WorkspaceSessionEnhancementPanel } from './workspace-session-enhancement-panel.js';
6
7
  import { registerSubscriptionSlot } from '../subscription-slot.js';
8
+ import { registerQuickPhraseSlot } from '../quick-phrase-slot.js';
7
9
  /** DSH 0.1.6 原生会话行增强:Logo 与归档会话入口共用同一生命周期。 */
8
10
  export const workspaceSessionEnhancementFeature = {
9
11
  descriptor: {
10
12
  name: 'workspaceSessionEnhancement',
11
- version: '0.1.0',
13
+ version: '0.1.1',
12
14
  enabledByDefault: false,
13
15
  dependencies: ['cliAdapters'],
14
16
  runtime: 'client',
15
17
  ui: {
16
18
  label: '工作区会话增强',
17
- description: '在原生工作区会话行显示 Agent Logo、归档入口和订阅/用量信息。',
19
+ description: '在原生工作区会话行显示 Agent Logo、归档入口、工作区隐藏/恢复入口和订阅/用量信息,并提供本地快捷会话。',
18
20
  labelKey: 'feature.workspaceSession.label',
19
21
  descriptionKey: 'feature.workspaceSession.description',
20
22
  order: 35,
@@ -27,17 +29,45 @@ export const workspaceSessionEnhancementFeature = {
27
29
  let generation = 0;
28
30
  let logoDom;
29
31
  let archiveDom;
32
+ let visibilityDom;
33
+ let adapterRefreshTimer;
30
34
  let disposeSubscription;
35
+ let disposeQuickPhrases;
31
36
  const disableLogo = () => {
32
37
  generation += 1;
33
38
  logoDom?.dispose();
34
39
  logoDom = undefined;
40
+ if (adapterRefreshTimer !== undefined) {
41
+ globalThis.clearInterval(adapterRefreshTimer);
42
+ adapterRefreshTimer = undefined;
43
+ }
35
44
  clearSessionAdapters();
36
45
  };
37
46
  const enableArchive = () => {
38
47
  if (archiveDom === undefined)
39
48
  archiveDom = startWorkspaceSessionArchiveDom({ remote: context.services.remote });
40
49
  };
50
+ const enableWorkspaceVisibility = (hiddenWorkspaceIds) => {
51
+ if (visibilityDom === undefined) {
52
+ visibilityDom = startWorkspaceSessionVisibilityDom({
53
+ remote: context.services.remote,
54
+ hiddenWorkspaceIds,
55
+ onHiddenWorkspaceIdsChange: async (ids) => {
56
+ await context.services.settings.mutate([{
57
+ op: 'set',
58
+ path: ['workspaceSessionEnhancement', 'hiddenWorkspaceIds'],
59
+ value: [...ids],
60
+ }]);
61
+ },
62
+ });
63
+ return;
64
+ }
65
+ visibilityDom.setHiddenWorkspaceIds(hiddenWorkspaceIds);
66
+ };
67
+ const disableWorkspaceVisibility = () => {
68
+ visibilityDom?.dispose();
69
+ visibilityDom = undefined;
70
+ };
41
71
  const enableSubscription = () => {
42
72
  if (disposeSubscription !== undefined || context.services.slots === undefined)
43
73
  return;
@@ -47,26 +77,43 @@ export const workspaceSessionEnhancementFeature = {
47
77
  disposeSubscription?.();
48
78
  disposeSubscription = undefined;
49
79
  };
80
+ const enableQuickPhrases = () => {
81
+ if (disposeQuickPhrases !== undefined || context.services.slots === undefined || context.services.locale === undefined)
82
+ return;
83
+ disposeQuickPhrases = registerQuickPhraseSlot(context.services.slots, context.services.settings, context.services.locale);
84
+ };
85
+ const disableQuickPhrases = () => {
86
+ disposeQuickPhrases?.();
87
+ disposeQuickPhrases = undefined;
88
+ };
50
89
  const disposeAll = () => {
51
90
  disableLogo();
52
91
  archiveDom?.dispose();
53
92
  archiveDom = undefined;
93
+ disableWorkspaceVisibility();
54
94
  disableSubscription();
95
+ disableQuickPhrases();
55
96
  };
56
97
  const enableLogo = () => {
57
98
  if (logoDom !== undefined)
58
99
  return;
59
100
  const currentGeneration = ++generation;
60
101
  logoDom = startWorkspaceSessionLogoDom();
61
- void fetchSessionAdapters(context.services.rpc)
62
- .then((bindings) => {
63
- if (generation !== currentGeneration || logoDom === undefined)
64
- return;
65
- replaceSessionAdapters(bindings);
66
- logoDom.refresh();
67
- archiveDom?.refresh();
68
- })
69
- .catch(() => undefined);
102
+ const refreshAdapters = () => {
103
+ void fetchSessionAdapters(context.services.rpc)
104
+ .then((bindings) => {
105
+ if (generation !== currentGeneration || logoDom === undefined)
106
+ return;
107
+ replaceSessionAdapters(bindings);
108
+ logoDom.refresh();
109
+ archiveDom?.refresh();
110
+ })
111
+ .catch(() => undefined);
112
+ };
113
+ refreshAdapters();
114
+ // 旧会话在 DSH 中按需加载;加载后 Host 才能识别其适配器。定期拉取
115
+ // 脱敏映射,确保侧栏不会一直停留在首次扫描时的默认 DSH 图标。
116
+ adapterRefreshTimer = globalThis.setInterval(refreshAdapters, 2_000);
70
117
  };
71
118
  const sync = () => {
72
119
  const workspaceSettings = context.services.settings.getSnapshot().value?.workspaceSessionEnhancement;
@@ -78,6 +125,14 @@ export const workspaceSessionEnhancementFeature = {
78
125
  archiveDom?.dispose();
79
126
  archiveDom = undefined;
80
127
  }
128
+ const showWorkspaceHiding = workspaceSettings?.showWorkspaceHiding
129
+ ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS.showWorkspaceHiding;
130
+ const hiddenWorkspaceIds = workspaceSettings?.hiddenWorkspaceIds
131
+ ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS.hiddenWorkspaceIds;
132
+ if (showWorkspaceHiding)
133
+ enableWorkspaceVisibility(hiddenWorkspaceIds);
134
+ else
135
+ disableWorkspaceVisibility();
81
136
  const showAdapterLogo = workspaceSettings?.showAdapterLogo
82
137
  ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS.showAdapterLogo;
83
138
  if (showAdapterLogo)
@@ -90,6 +145,12 @@ export const workspaceSessionEnhancementFeature = {
90
145
  enableSubscription();
91
146
  else
92
147
  disableSubscription();
148
+ const showQuickPhrases = workspaceSettings?.showQuickPhrases
149
+ ?? DEFAULT_WORKSPACE_SESSION_ENHANCEMENT_SETTINGS.showQuickPhrases;
150
+ if (showQuickPhrases)
151
+ enableQuickPhrases();
152
+ else
153
+ disableQuickPhrases();
93
154
  };
94
155
  sync();
95
156
  const unsubscribe = context.services.settings.subscribe(sync);
@@ -0,0 +1,16 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type { CodingNsClientFeatureModule, CodingNsRpcClient } from './features/types.js';
3
+ export declare const GIT_PROVIDER_ID = "codingns4dsh/git";
4
+ export declare const GIT_KIND = "git";
5
+ /** 兼容早期调用方使用的面板标识;实际注册已迁移到右侧 Sidebar。 */
6
+ export declare const GIT_PANEL_ID = "codingns4dsh/git";
7
+ type GitServices = {
8
+ readonly rpc: CodingNsRpcClient;
9
+ readonly remote?: unknown;
10
+ };
11
+ /** 注册 DSH 右侧 Sidebar 的 Git 标签类型,数据按 Workspace 复用。 */
12
+ export declare function registerGitManagementUi(ctx: Context, services: GitServices): () => void;
13
+ export declare function resolveGitWorkspaceId(remote: unknown, sessionId: string): Promise<string | undefined>;
14
+ export declare const gitManagementFeature: CodingNsClientFeatureModule;
15
+ export {};
16
+ //# sourceMappingURL=git-management.d.ts.map