@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
@@ -0,0 +1,95 @@
1
+ /**
2
+ * 快捷短语按钮在 DSH 输入工具栏里的落位。
3
+ *
4
+ * DSH 原生结构是「添加附件按钮 → 权限/规划组 → conversation.input.left 槽位」,
5
+ * 槽位里的控件默认排在权限组件右边。这里不改 DOM 顺序,只给这些项各加一个 flex order:
6
+ * 三者仍共用宿主工具栏的 flex 行,既不互相覆盖,间距也由宿主 gap 统一决定。
7
+ */
8
+ export const QUICK_PHRASE_TRIGGER_ORDER = 1;
9
+ export const QUICK_PHRASE_PERMISSION_ORDER = 2;
10
+ /** 快捷短语两侧保留的间距比例:只留宿主原生间距的一半,入口更紧凑。 */
11
+ export const QUICK_PHRASE_GAP_SCALE = 0.5;
12
+ /** 读不到宿主 gap 时按 DSH 当前的 12px 估算,留出一半间距。 */
13
+ export const QUICK_PHRASE_FALLBACK_MARGIN = -6;
14
+ /**
15
+ * 把快捷短语按钮排到添加附件按钮之后、权限设置组件之前。
16
+ * @param request - 快捷短语根节点与添加附件按钮。
17
+ * @param environment - 计算样式读取入口。
18
+ * @returns 被重排的工具栏项、工具栏行与还原函数。
19
+ */
20
+ export function applyQuickPhraseOrder(request, environment = {}) {
21
+ const computedStyle = environment.computedStyle ?? ((element) => getComputedStyle(element));
22
+ const container = findFlexContainer(request.addButton, computedStyle);
23
+ const following = container === null ? [] : findItemsAfterAddButton(container, request, computedStyle);
24
+ if (following.length === 0)
25
+ return { reordered: [], container, dispose: () => undefined };
26
+ const original = following.map((item) => item.style.order);
27
+ for (const item of following)
28
+ item.style.order = String(QUICK_PHRASE_PERMISSION_ORDER);
29
+ return {
30
+ reordered: following,
31
+ container,
32
+ dispose: () => {
33
+ following.forEach((item, index) => {
34
+ item.style.order = original[index] ?? '';
35
+ });
36
+ },
37
+ };
38
+ }
39
+ /**
40
+ * 快捷短语两侧要用的负外边距:把宿主原生 gap 收窄到 {@link QUICK_PHRASE_GAP_SCALE}。
41
+ * @param container - 承载工具栏项的 flex 行。
42
+ * @param environment - 计算样式读取入口。
43
+ * @returns 左右外边距(px,负值)。
44
+ */
45
+ export function readQuickPhraseMargin(container, environment = {}) {
46
+ if (container === null)
47
+ return QUICK_PHRASE_FALLBACK_MARGIN;
48
+ const computedStyle = environment.computedStyle ?? ((element) => getComputedStyle(element));
49
+ const gap = Number.parseFloat(computedStyle(container).columnGap ?? '');
50
+ if (!Number.isFinite(gap) || gap <= 0)
51
+ return QUICK_PHRASE_FALLBACK_MARGIN;
52
+ return -gap * (1 - QUICK_PHRASE_GAP_SCALE);
53
+ }
54
+ /** 添加附件按钮之后、快捷短语之前的工具栏项。 */
55
+ function findItemsAfterAddButton(container, request, computedStyle) {
56
+ const items = layoutItems(container, computedStyle);
57
+ const addIndex = items.findIndex((item) => item.contains(request.addButton));
58
+ if (addIndex < 0)
59
+ return [];
60
+ return items.slice(addIndex + 1).filter((item) => !item.contains(request.trigger));
61
+ }
62
+ /** 最近的 flex/grid 布局容器;找不到说明宿主工具栏结构变了,此时保持原生顺序。 */
63
+ function findFlexContainer(node, computedStyle) {
64
+ let current = node.parentElement;
65
+ while (current !== null) {
66
+ const display = computedStyle(current).display;
67
+ if (display === 'flex' || display === 'inline-flex' || display === 'grid')
68
+ return current;
69
+ current = current.parentElement;
70
+ }
71
+ return null;
72
+ }
73
+ /** 展开工具栏里真正参与布局的项:display: contents 的槽位锚点穿透,display: none 的隐藏节点跳过。 */
74
+ function layoutItems(container, computedStyle) {
75
+ const items = [];
76
+ const visit = (parent) => {
77
+ for (const child of parent.children) {
78
+ const display = computedStyle(child).display;
79
+ if (display === 'none')
80
+ continue;
81
+ if (display === 'contents') {
82
+ visit(child);
83
+ continue;
84
+ }
85
+ if (isStylable(child))
86
+ items.push(child);
87
+ }
88
+ };
89
+ visit(container);
90
+ return items;
91
+ }
92
+ function isStylable(element) {
93
+ return element.style !== undefined;
94
+ }
95
+ //# sourceMappingURL=quick-phrase-layout.js.map
@@ -0,0 +1,7 @@
1
+ import type { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
2
+ import { type CodingNsSettings } from '../shared/contracts/config.js';
3
+ import type { CodingNsSettingsStore } from '../dsh-capabilities/settings-store.js';
4
+ import { type CodingNsLocale } from './locale.js';
5
+ /** 在添加文件按钮右侧的输入工具区挂载插件自己的快捷会话入口。 */
6
+ export declare function registerQuickPhraseSlot(slots: SlotRegistry, settings: CodingNsSettingsStore<CodingNsSettings>, locale: CodingNsLocale): () => void;
7
+ //# sourceMappingURL=quick-phrase-slot.d.ts.map
@@ -0,0 +1,370 @@
1
+ import { createElement, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { DEFAULT_QUICK_PHRASES } from '../shared/contracts/config.js';
3
+ import { useCodingNsTranslator } from './locale.js';
4
+ import { applyQuickPhraseOrder, QUICK_PHRASE_FALLBACK_MARGIN, QUICK_PHRASE_TRIGGER_ORDER, readQuickPhraseMargin } from './quick-phrase-layout.js';
5
+ import { dshPopupSurfaceStyle, dshThemeColor } from './theme.js';
6
+ const QUICK_PHRASE_FALLBACK_SIZE = 28;
7
+ const QUICK_PHRASE_FALLBACK_ICON_SIZE = 14;
8
+ /** 在添加文件按钮右侧的输入工具区挂载插件自己的快捷会话入口。 */
9
+ export function registerQuickPhraseSlot(slots, settings, locale) {
10
+ const t = locale.bind('codingns');
11
+ return slots.inject('conversation.input.left', () => slots.register({
12
+ name: 'conversation.input.left',
13
+ id: 'codingns4dsh-quick-phrases',
14
+ order: 0,
15
+ label: t('workspace.quickPhrasesTrigger'),
16
+ inject: () => ({ settings, locale }),
17
+ }, QuickPhraseSlot));
18
+ }
19
+ function QuickPhraseSlot(props) {
20
+ const t = useCodingNsTranslator(props.locale);
21
+ const draft = props.useInput((value) => value.draft);
22
+ const [phrases, setPhrases] = useState(() => readQuickPhrases(props.settings));
23
+ const [open, setOpen] = useState(false);
24
+ const [addOpen, setAddOpen] = useState(false);
25
+ const [newPhrase, setNewPhrase] = useState('');
26
+ const [draggingId, setDraggingId] = useState(null);
27
+ const [saving, setSaving] = useState(false);
28
+ const [saveError, setSaveError] = useState(false);
29
+ const quickPhraseRootRef = useRef(null);
30
+ const [triggerSize, setTriggerSize] = useState({ width: QUICK_PHRASE_FALLBACK_SIZE, height: QUICK_PHRASE_FALLBACK_SIZE });
31
+ const [iconSize, setIconSize] = useState(QUICK_PHRASE_FALLBACK_ICON_SIZE);
32
+ const [triggerMargin, setTriggerMargin] = useState(QUICK_PHRASE_FALLBACK_MARGIN);
33
+ const [messageAreaBounds, setMessageAreaBounds] = useState(null);
34
+ useEffect(() => {
35
+ const sync = () => setPhrases(readQuickPhrases(props.settings));
36
+ sync();
37
+ const workspaceSettings = props.settings.getSnapshot().value?.workspaceSessionEnhancement;
38
+ if (workspaceSettings?.quickPhrasesSeeded === false && workspaceSettings.quickPhrases.length === 0) {
39
+ void props.settings.mutate([
40
+ { op: 'set', path: ['workspaceSessionEnhancement', 'quickPhrases'], value: DEFAULT_QUICK_PHRASES.map((phrase) => ({ ...phrase })) },
41
+ { op: 'set', path: ['workspaceSessionEnhancement', 'quickPhrasesSeeded'], value: true },
42
+ ]).catch(() => undefined);
43
+ }
44
+ return props.settings.subscribe(sync);
45
+ }, [props.settings]);
46
+ useEffect(() => {
47
+ if (!open && !addOpen)
48
+ return;
49
+ const closeOnEscape = (event) => {
50
+ if (event.key !== 'Escape')
51
+ return;
52
+ if (addOpen)
53
+ setAddOpen(false);
54
+ else
55
+ setOpen(false);
56
+ };
57
+ document.addEventListener('keydown', closeOnEscape);
58
+ return () => document.removeEventListener('keydown', closeOnEscape);
59
+ }, [addOpen, open]);
60
+ useLayoutEffect(() => {
61
+ const root = quickPhraseRootRef.current;
62
+ if (root === null || typeof document === 'undefined')
63
+ return;
64
+ const addButton = findAddButton(root);
65
+ if (addButton === null)
66
+ return;
67
+ // 顺序、尺寸和间距都取自添加附件按钮所在的工具栏行,三者共用一个 flex 布局。
68
+ const order = applyQuickPhraseOrder({ trigger: root, addButton });
69
+ const positioningParent = findPositioningParent(root);
70
+ const update = () => {
71
+ const addRect = addButton.getBoundingClientRect();
72
+ const nextSize = addRect.width > 0 && addRect.height > 0
73
+ ? { width: addRect.width, height: addRect.height }
74
+ : { width: QUICK_PHRASE_FALLBACK_SIZE, height: QUICK_PHRASE_FALLBACK_SIZE };
75
+ setTriggerSize((current) => (current.width === nextSize.width && current.height === nextSize.height ? current : nextSize));
76
+ const iconRect = addButton.querySelector('svg')?.getBoundingClientRect();
77
+ const nextIconSize = iconRect !== undefined && iconRect.width > 0 ? iconRect.width : QUICK_PHRASE_FALLBACK_ICON_SIZE;
78
+ setIconSize((current) => (current === nextIconSize ? current : nextIconSize));
79
+ const nextMargin = readQuickPhraseMargin(order.container);
80
+ setTriggerMargin((current) => (current === nextMargin ? current : nextMargin));
81
+ const parentRect = positioningParent?.getBoundingClientRect();
82
+ const nextBounds = { left: parentRect?.left ?? 0, width: parentRect?.width ?? window.innerWidth };
83
+ setMessageAreaBounds((current) => (current !== null && current.left === nextBounds.left && current.width === nextBounds.width ? current : nextBounds));
84
+ };
85
+ update();
86
+ const observer = typeof globalThis.ResizeObserver === 'function'
87
+ ? new globalThis.ResizeObserver(update)
88
+ : undefined;
89
+ observer?.observe(addButton);
90
+ // 工具栏宽度变化会切换宿主的容器查询 gap,间距要跟着重算。
91
+ if (order.container !== null)
92
+ observer?.observe(order.container);
93
+ window.addEventListener('resize', update);
94
+ document.addEventListener('scroll', update, true);
95
+ return () => {
96
+ observer?.disconnect();
97
+ window.removeEventListener('resize', update);
98
+ document.removeEventListener('scroll', update, true);
99
+ order.dispose();
100
+ };
101
+ }, [draft.length === 0]);
102
+ const persistPhrases = (next) => {
103
+ setPhrases(next);
104
+ setSaving(true);
105
+ void props.settings.mutate([{
106
+ op: 'set',
107
+ path: ['workspaceSessionEnhancement', 'quickPhrases'],
108
+ value: next,
109
+ }, {
110
+ op: 'set',
111
+ path: ['workspaceSessionEnhancement', 'quickPhrasesSeeded'],
112
+ value: true,
113
+ }]).then((accepted) => setSaveError(!accepted)).catch(() => setSaveError(true)).finally(() => setSaving(false));
114
+ };
115
+ const addPhrase = () => {
116
+ const text = newPhrase.trim();
117
+ if (text === '' || saving)
118
+ return;
119
+ const id = typeof globalThis.crypto?.randomUUID === 'function'
120
+ ? globalThis.crypto.randomUUID()
121
+ : `quick-${Date.now()}-${Math.random().toString(36).slice(2)}`;
122
+ persistPhrases([...phrases, { id, text }]);
123
+ setNewPhrase('');
124
+ setAddOpen(false);
125
+ };
126
+ const removePhrase = (id) => {
127
+ if (!saving)
128
+ persistPhrases(phrases.filter((phrase) => phrase.id !== id));
129
+ };
130
+ const movePhrase = (fromId, toId) => {
131
+ if (fromId === toId || saving)
132
+ return;
133
+ const from = phrases.findIndex((phrase) => phrase.id === fromId);
134
+ const to = phrases.findIndex((phrase) => phrase.id === toId);
135
+ if (from < 0 || to < 0)
136
+ return;
137
+ const next = [...phrases];
138
+ const [moved] = next.splice(from, 1);
139
+ if (moved === undefined)
140
+ return;
141
+ next.splice(to, 0, moved);
142
+ persistPhrases(next);
143
+ };
144
+ const enabled = props.settings.getSnapshot().value?.workspaceSessionEnhancement?.showQuickPhrases
145
+ ?? true;
146
+ if (!enabled || draft.length > 0) {
147
+ return null;
148
+ }
149
+ const openAddDialog = () => {
150
+ setNewPhrase('');
151
+ setAddOpen(true);
152
+ };
153
+ return createElement('div', {
154
+ ref: quickPhraseRootRef,
155
+ // 负外边距把工具栏 gap 收窄到一半,两侧对称,不覆盖相邻控件。
156
+ style: { ...quickPhraseRootStyle, marginLeft: triggerMargin, marginRight: triggerMargin },
157
+ }, createElement('button', {
158
+ type: 'button',
159
+ 'aria-label': t('workspace.quickPhrasesTrigger'),
160
+ title: t('workspace.quickPhrasesTrigger'),
161
+ 'aria-haspopup': 'dialog',
162
+ 'aria-expanded': open,
163
+ onClick: () => setOpen((value) => !value),
164
+ style: { ...quickPhraseTriggerStyle, width: triggerSize.width, height: triggerSize.height },
165
+ }, createElement('svg', {
166
+ width: iconSize,
167
+ height: iconSize,
168
+ // 收紧到图形自身边界,让 14px 的图标和添加附件按钮的图标视觉尺寸一致。
169
+ viewBox: '4 4 16 20',
170
+ fill: 'none',
171
+ stroke: 'currentColor',
172
+ strokeWidth: 2,
173
+ 'aria-hidden': true,
174
+ }, createElement('path', { d: 'M7 8h10' }), createElement('path', { d: 'M7 12h8' }), createElement('path', { d: 'M7 16h5' }), createElement('path', { d: 'M5 5h14v14H9l-4 4V5z' }))), open && createElement('div', {
175
+ role: 'dialog',
176
+ 'aria-label': t('workspace.quickPhrasesDialogLabel'),
177
+ 'aria-modal': true,
178
+ style: {
179
+ ...quickPhraseOverlayStyle,
180
+ ...(messageAreaBounds === null ? {} : { left: messageAreaBounds.left, right: 'auto', width: messageAreaBounds.width }),
181
+ },
182
+ onPointerDown: () => setOpen(false),
183
+ }, createElement('div', {
184
+ style: quickPhraseDialogStyle,
185
+ onPointerDown: (event) => event.stopPropagation(),
186
+ }, createElement('div', { style: quickPhraseHeaderStyle }, createElement('div', { style: { minWidth: 0 } }, createElement('strong', { style: quickPhraseTitleStyle }, t('workspace.quickPhrasesTitle')), createElement('p', { style: quickPhraseHintStyle }, t('workspace.quickPhrasesHint'))), createElement('div', { style: quickPhraseHeaderActionsStyle }, createElement('button', {
187
+ type: 'button',
188
+ 'aria-label': t('workspace.quickPhrasesAdd'),
189
+ title: t('workspace.quickPhrasesAdd'),
190
+ onClick: openAddDialog,
191
+ style: quickPhraseIconButtonStyle,
192
+ }, createElement('svg', { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, 'aria-hidden': true }, createElement('path', { d: 'M12 5v14' }), createElement('path', { d: 'M5 12h14' }))), createElement('button', {
193
+ type: 'button',
194
+ 'aria-label': t('workspace.quickPhrasesClose'),
195
+ title: t('workspace.quickPhrasesClose'),
196
+ onClick: () => setOpen(false),
197
+ style: quickPhraseCloseStyle,
198
+ }, '×'))), saveError && createElement('div', { role: 'alert', style: quickPhraseSaveErrorStyle }, t('workspace.quickPhrasesSaveFailed')), phrases.length === 0
199
+ ? createElement('div', { role: 'status', style: quickPhraseEmptyStyle }, t('workspace.quickPhrasesEmpty'))
200
+ : createElement('div', { style: quickPhraseListStyle }, ...phrases.map((phrase) => createElement('div', {
201
+ key: phrase.id,
202
+ draggable: !saving,
203
+ onDragStart: () => setDraggingId(phrase.id),
204
+ onDragOver: (event) => event.preventDefault(),
205
+ onDrop: () => {
206
+ if (draggingId !== null)
207
+ movePhrase(draggingId, phrase.id);
208
+ setDraggingId(null);
209
+ },
210
+ onDragEnd: () => setDraggingId(null),
211
+ style: { ...quickPhraseItemStyle, ...(draggingId === phrase.id ? quickPhraseDraggingStyle : {}) },
212
+ }, createElement('button', {
213
+ type: 'button',
214
+ onClick: () => {
215
+ props.inputActions.setDraft(phrase.text);
216
+ setOpen(false);
217
+ },
218
+ style: quickPhraseTextButtonStyle,
219
+ }, phrase.text), createElement('span', { role: 'img', 'aria-label': t('workspace.quickPhrasesDrag'), title: t('workspace.quickPhrasesDrag'), style: quickPhraseDragHandleStyle }, '⋮⋮'), createElement('button', {
220
+ type: 'button',
221
+ disabled: saving,
222
+ 'aria-label': t('workspace.quickPhrasesDelete'),
223
+ title: t('workspace.quickPhrasesDelete'),
224
+ onClick: () => removePhrase(phrase.id),
225
+ style: quickPhraseDeleteStyle,
226
+ }, '×')))))), addOpen && createElement('div', {
227
+ role: 'dialog',
228
+ 'aria-label': t('workspace.quickPhrasesAddDialogLabel'),
229
+ 'aria-modal': true,
230
+ style: {
231
+ ...quickPhraseEditorOverlayStyle,
232
+ ...(messageAreaBounds === null ? {} : { left: messageAreaBounds.left, right: 'auto', width: messageAreaBounds.width }),
233
+ },
234
+ onPointerDown: (event) => {
235
+ event.stopPropagation();
236
+ setAddOpen(false);
237
+ },
238
+ }, createElement('div', {
239
+ style: quickPhraseEditorStyle,
240
+ onPointerDown: (event) => event.stopPropagation(),
241
+ }, createElement('div', { style: quickPhraseEditorHeaderStyle }, createElement('strong', { style: quickPhraseTitleStyle }, t('workspace.quickPhrasesAdd')), createElement('button', {
242
+ type: 'button',
243
+ 'aria-label': t('workspace.quickPhrasesCancel'),
244
+ title: t('workspace.quickPhrasesCancel'),
245
+ onClick: () => setAddOpen(false),
246
+ style: quickPhraseCloseStyle,
247
+ }, '×')), createElement('input', {
248
+ type: 'text',
249
+ value: newPhrase,
250
+ disabled: saving,
251
+ autoFocus: true,
252
+ placeholder: t('workspace.quickPhrasesPlaceholder'),
253
+ onChange: (event) => setNewPhrase(event.currentTarget.value),
254
+ onKeyDown: (event) => {
255
+ if (event.key === 'Enter') {
256
+ event.preventDefault();
257
+ addPhrase();
258
+ }
259
+ },
260
+ style: quickPhraseEditorInputStyle,
261
+ }), createElement('div', { style: quickPhraseEditorActionsStyle }, createElement('button', {
262
+ type: 'button',
263
+ onClick: () => setAddOpen(false),
264
+ style: quickPhraseCancelButtonStyle,
265
+ }, t('workspace.quickPhrasesCancel')), createElement('button', {
266
+ type: 'button',
267
+ disabled: saving || newPhrase.trim() === '',
268
+ onClick: addPhrase,
269
+ style: quickPhraseAddButtonStyle,
270
+ }, t('workspace.quickPhrasesAdd'))))));
271
+ }
272
+ function findAddButton(root) {
273
+ let scope = root.parentElement;
274
+ while (scope !== null) {
275
+ const button = Array.from(scope.querySelectorAll('button.uV2eYG_add'))
276
+ .find(isVisibleElement) ?? null;
277
+ if (button !== null)
278
+ return button;
279
+ scope = scope.parentElement;
280
+ }
281
+ return Array.from(document.querySelectorAll('button.uV2eYG_add'))
282
+ .find(isVisibleElement) ?? null;
283
+ }
284
+ function findPositioningParent(root) {
285
+ let current = root.parentElement;
286
+ while (current !== null) {
287
+ if (getComputedStyle(current).position !== 'static')
288
+ return current;
289
+ current = current.parentElement;
290
+ }
291
+ return null;
292
+ }
293
+ function isVisibleElement(element) {
294
+ const rect = element.getBoundingClientRect();
295
+ const style = getComputedStyle(element);
296
+ return rect.width > 0 && rect.height > 0 && style.display !== 'none' && style.visibility !== 'hidden';
297
+ }
298
+ function readQuickPhrases(settings) {
299
+ const workspaceSettings = settings.getSnapshot().value?.workspaceSessionEnhancement;
300
+ const value = workspaceSettings?.quickPhrases;
301
+ if (!Array.isArray(value))
302
+ return DEFAULT_QUICK_PHRASES;
303
+ if (value.length === 0 && workspaceSettings?.quickPhrasesSeeded === false)
304
+ return DEFAULT_QUICK_PHRASES;
305
+ return value.filter((phrase) => (typeof phrase?.id === 'string' && phrase.id.length > 0
306
+ && typeof phrase.text === 'string' && phrase.text.length > 0));
307
+ }
308
+ const quickPhraseRootStyle = {
309
+ // 与 DSH 工具栏同一个 flex 行:靠 order 排在权限组件之前,间距由宿主的 gap 决定。
310
+ display: 'inline-flex',
311
+ alignItems: 'center',
312
+ order: QUICK_PHRASE_TRIGGER_ORDER,
313
+ flex: '0 0 auto',
314
+ };
315
+ const quickPhraseTriggerStyle = {
316
+ display: 'inline-flex',
317
+ alignItems: 'center',
318
+ justifyContent: 'center',
319
+ width: QUICK_PHRASE_FALLBACK_SIZE,
320
+ height: QUICK_PHRASE_FALLBACK_SIZE,
321
+ flex: '0 0 auto',
322
+ padding: 0,
323
+ border: 0,
324
+ borderRadius: '50%',
325
+ color: dshThemeColor.labelSecondary,
326
+ background: 'transparent',
327
+ cursor: 'pointer',
328
+ };
329
+ const quickPhraseOverlayStyle = {
330
+ position: 'fixed',
331
+ inset: 0,
332
+ zIndex: 1400,
333
+ display: 'flex',
334
+ alignItems: 'center',
335
+ justifyContent: 'center',
336
+ padding: 20,
337
+ boxSizing: 'border-box',
338
+ background: 'transparent',
339
+ };
340
+ const quickPhraseDialogStyle = {
341
+ ...dshPopupSurfaceStyle,
342
+ width: 'min(100%, 720px)',
343
+ maxHeight: 'min(720px, 90vh)',
344
+ overflow: 'auto',
345
+ boxSizing: 'border-box',
346
+ padding: 24,
347
+ borderRadius: 12,
348
+ };
349
+ const quickPhraseHeaderStyle = { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, paddingBottom: 16, borderBottom: `1px solid ${dshThemeColor.border}` };
350
+ const quickPhraseHeaderActionsStyle = { display: 'flex', alignItems: 'center', gap: 8, flex: '0 0 auto' };
351
+ const quickPhraseTitleStyle = { display: 'block', color: dshThemeColor.labelPrimary, fontSize: 20, lineHeight: 1.3 };
352
+ const quickPhraseHintStyle = { margin: '6px 0 0', color: dshThemeColor.labelSecondary, fontSize: 13, lineHeight: 1.5 };
353
+ const quickPhraseCloseStyle = { width: 32, height: 32, flex: '0 0 auto', border: 0, borderRadius: 16, color: dshThemeColor.labelSecondary, background: dshThemeColor.surfaceSubtle, fontSize: 24, lineHeight: 1, cursor: 'pointer' };
354
+ const quickPhraseIconButtonStyle = { width: 32, height: 32, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: 0, border: 0, borderRadius: 8, color: dshThemeColor.labelSecondary, background: dshThemeColor.surfaceSubtle, cursor: 'pointer' };
355
+ const quickPhraseEditorOverlayStyle = { ...quickPhraseOverlayStyle, zIndex: 1410, background: 'transparent' };
356
+ const quickPhraseEditorStyle = { ...dshPopupSurfaceStyle, width: 'min(100%, 520px)', boxSizing: 'border-box', padding: 24, borderRadius: 12 };
357
+ const quickPhraseEditorHeaderStyle = { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, paddingBottom: 16, borderBottom: `1px solid ${dshThemeColor.border}` };
358
+ const quickPhraseEditorInputStyle = { width: '100%', minHeight: 92, marginTop: 16, boxSizing: 'border-box', padding: '10px 12px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 8, color: dshThemeColor.labelPrimary, background: dshThemeColor.inputBackground, fontSize: 14, lineHeight: 1.5, resize: 'vertical' };
359
+ const quickPhraseEditorActionsStyle = { display: 'flex', justifyContent: 'flex-end', gap: 8, paddingTop: 16 };
360
+ const quickPhraseCancelButtonStyle = { minHeight: 36, padding: '8px 14px', border: `1px solid ${dshThemeColor.border}`, borderRadius: 8, color: dshThemeColor.labelPrimary, background: 'transparent', fontSize: 13, cursor: 'pointer' };
361
+ const quickPhraseAddButtonStyle = { flex: '0 0 auto', minHeight: 36, padding: '8px 14px', border: 0, borderRadius: 8, color: dshThemeColor.switchThumb, background: dshThemeColor.accent, fontSize: 13, cursor: 'pointer' };
362
+ const quickPhraseListStyle = { display: 'flex', flexDirection: 'column', gap: 8, paddingTop: 16 };
363
+ const quickPhraseItemStyle = { display: 'flex', alignItems: 'center', gap: 8, width: '100%', minHeight: 48, padding: '7px 8px 7px 14px', boxSizing: 'border-box', border: `1px solid ${dshThemeColor.border}`, borderRadius: 8, color: dshThemeColor.labelPrimary, background: dshThemeColor.surfaceSubtle };
364
+ const quickPhraseDraggingStyle = { opacity: 0.55, borderColor: dshThemeColor.accent };
365
+ const quickPhraseTextButtonStyle = { flex: '1 1 auto', minWidth: 0, padding: 0, border: 0, color: dshThemeColor.labelPrimary, background: 'transparent', textAlign: 'left', fontSize: 13, lineHeight: 1.5, cursor: 'pointer', overflowWrap: 'anywhere' };
366
+ const quickPhraseDragHandleStyle = { flex: '0 0 24px', color: dshThemeColor.labelTertiary, textAlign: 'center', fontSize: 18, lineHeight: 1, cursor: 'grab', userSelect: 'none' };
367
+ const quickPhraseDeleteStyle = { width: 30, height: 30, flex: '0 0 30px', padding: 0, border: 0, borderRadius: 8, color: dshThemeColor.error, background: 'transparent', fontSize: 20, lineHeight: 1, cursor: 'pointer' };
368
+ const quickPhraseSaveErrorStyle = { color: dshThemeColor.error, fontSize: 12, lineHeight: 1.4 };
369
+ const quickPhraseEmptyStyle = { padding: '28px 0 10px', color: dshThemeColor.labelSecondary, textAlign: 'center', fontSize: 13 };
370
+ //# sourceMappingURL=quick-phrase-slot.js.map
@@ -348,7 +348,7 @@ export class RemoteDshWebContext {
348
348
  }
349
349
  function createBridgeScript() {
350
350
  return `(() => {
351
- // 远程 DSH Web 已经运行在外层 DSH-Codingns4DSH Tunnel 内。
351
+ // 远程 DSH Web 已经运行在外层 Codingns4DSH Tunnel 内。
352
352
  // 内嵌的 codingns4dsh Client 仍需加载其插件代码和界面,但不能再次启动
353
353
  // 自己的 Relay/WebRTC,否则会把信令 WebSocket 当成本地 DSH Web 路径转发,
354
354
  // 形成递归连接并持续触发 /signaling/signal 失败。
@@ -1,13 +1,14 @@
1
- import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
1
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
2
2
  import type { CodingNsSettings } from '../shared/contracts/config.js';
3
3
  import type { CodingNsRpcClient } from './features/types.js';
4
+ import type { CodingNsSettingsSnapshot, CodingNsSettingsStore } from '../dsh-capabilities/settings-store.js';
4
5
  type SettingsMutation = Parameters<SettingsScope<CodingNsSettings>['mutate']>[0];
5
6
  type SnapshotListener = () => void;
6
7
  /**
7
8
  * 把 DSH 本地设置和远程 Host 设置 RPC 统一成一个设置作用域。
8
9
  * 非回环页面使用 RPC,回环页面完全复用 DSH 的原生设置传输。
9
10
  */
10
- export declare class CodingNsSettingsBridge implements SettingsScope<CodingNsSettings> {
11
+ export declare class CodingNsSettingsBridge implements CodingNsSettingsStore<CodingNsSettings> {
11
12
  private readonly local;
12
13
  private readonly rpc;
13
14
  private snapshot;
@@ -16,17 +17,19 @@ export declare class CodingNsSettingsBridge implements SettingsScope<CodingNsSet
16
17
  private remoteLoad;
17
18
  private remoteLoaded;
18
19
  constructor(local: SettingsScope<CodingNsSettings>, rpc: CodingNsRpcClient);
19
- getSnapshot(): SettingsScopeSnapshot<CodingNsSettings>;
20
+ getSnapshot(): CodingNsSettingsSnapshot<CodingNsSettings>;
20
21
  subscribe(listener: SnapshotListener): () => void;
21
22
  load(): Promise<void>;
22
- set(field: string, value: unknown): Promise<void>;
23
- unset(field: string): Promise<void>;
24
- mutate(ops: SettingsMutation, expectedRevision?: number): Promise<void>;
23
+ set(field: string, value: unknown): Promise<boolean>;
24
+ unset(field: string): Promise<boolean>;
25
+ mutate(ops: SettingsMutation, expectedRevision?: number): Promise<boolean>;
25
26
  dispose(): void;
26
27
  private call;
27
28
  private publish;
28
29
  private isRemote;
29
30
  }
31
+ /** 调用 Codingns4DSH Host RPC,并兼容 DSH 原生连接与普通 Web API 回退。 */
32
+ export declare function callCodingNsRpc<T>(rpc: CodingNsRpcClient, endpoint: string, payload: unknown): Promise<T>;
30
33
  export declare function createCodingNsSettingsBridge(local: SettingsScope<CodingNsSettings>, rpc: CodingNsRpcClient): CodingNsSettingsBridge;
31
34
  export {};
32
35
  //# sourceMappingURL=settings-bridge.d.ts.map