dsh-agent-plugins-market 0.9.0 → 0.9.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 (358) hide show
  1. package/README.md +64 -154
  2. package/README.zh.md +74 -164
  3. package/assets/dsh-agent-plugins.png +0 -0
  4. package/client/client.js +5371 -1085
  5. package/client/client.js.map +1 -1
  6. package/lib/index.js +2 -257
  7. package/lib/{application → packages/market-bundle/src/application}/catalog.js +207 -41
  8. package/lib/{application → packages/market-bundle/src/application}/details.js +73 -29
  9. package/lib/packages/market-bundle/src/application/extension-inventory.js +408 -0
  10. package/lib/packages/market-bundle/src/application/extension-project.js +64 -0
  11. package/lib/packages/market-bundle/src/application/resource-inventory.js +96 -0
  12. package/lib/packages/market-bundle/src/application/server-config.js +9 -0
  13. package/lib/packages/market-bundle/src/application/suite-queries.js +86 -0
  14. package/lib/packages/market-bundle/src/index.js +372 -0
  15. package/lib/{runtime/host → packages/market-bundle/src/platform}/feedback-tool.js +2 -2
  16. package/lib/{runtime/host → packages/market-bundle/src/platform}/settings-namespace.js +55 -7
  17. package/lib/packages/market-bundle/src/platform/settings-schema.js +25 -0
  18. package/lib/packages/market-bundle/src/routes-extension-presets.js +161 -0
  19. package/lib/packages/market-bundle/src/routes-resources.js +127 -0
  20. package/lib/{routes.js → packages/market-bundle/src/routes.js} +225 -21
  21. package/lib/packages/market-bundle/src/runtime-adapters.js +57 -0
  22. package/lib/packages/market-bundle/src/session-extension.js +337 -0
  23. package/lib/{application → packages/market-catalog/src/application}/catalog-context.js +7 -4
  24. package/lib/{application → packages/market-catalog/src/application}/install-store.js +3 -3
  25. package/lib/{application → packages/market-catalog/src/application}/snapshot-cache.js +100 -11
  26. package/lib/{application → packages/market-catalog/src/application}/source-store.js +24 -11
  27. package/lib/{application → packages/market-catalog/src/application}/state/state-store.js +1 -1
  28. package/lib/{application → packages/market-catalog/src/application}/state/storage-migration.js +1 -1
  29. package/lib/packages/market-catalog/src/index.js +19 -0
  30. package/lib/{catalog → packages/market-catalog/src/scanning}/archive.js +1 -1
  31. package/lib/{catalog → packages/market-catalog/src/scanning}/codex-mcp.js +1 -1
  32. package/lib/{catalog → packages/market-catalog/src/scanning}/component-files.js +2 -2
  33. package/lib/{catalog → packages/market-catalog/src/scanning}/manifests.js +2 -2
  34. package/lib/{catalog → packages/market-catalog/src/scanning}/native-project.js +1 -1
  35. package/lib/{catalog → packages/market-catalog/src/scanning}/paths.js +1 -1
  36. package/lib/{catalog → packages/market-catalog/src/scanning}/plugin-variables.js +21 -1
  37. package/lib/{catalog → packages/market-catalog/src/scanning}/scan-resolvers.js +35 -2
  38. package/lib/{catalog → packages/market-catalog/src/scanning}/skills-parse.js +40 -10
  39. package/lib/{catalog → packages/market-catalog/src/scanning}/validate.js +15 -2
  40. package/lib/packages/market-contracts/src/contracts/extension-presets.js +125 -0
  41. package/lib/{contracts → packages/market-contracts/src/contracts}/market.js +33 -5
  42. package/lib/packages/market-contracts/src/contracts/mcp-overrides.js +2 -0
  43. package/lib/packages/market-contracts/src/contracts/resource-window.js +29 -0
  44. package/lib/packages/market-contracts/src/contracts/settings.js +130 -0
  45. package/lib/packages/market-contracts/src/contracts/surface-toggles.js +29 -0
  46. package/lib/packages/market-contracts/src/contracts/translation.js +28 -0
  47. package/lib/packages/market-contracts/src/index.js +4 -0
  48. package/lib/{model → packages/market-contracts/src/model}/layouts.js +11 -0
  49. package/lib/{application → packages/market-contracts/src/ports}/ports.js +3 -0
  50. package/lib/{application/mcp/mcp-redaction.js → packages/market-contracts/src/redaction.js} +17 -1
  51. package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-direct-config.js +2 -2
  52. package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-server-state.js +1 -1
  53. package/lib/{application → packages/market-lsp/src/application}/lsp/lsp-status.js +20 -3
  54. package/lib/{application → packages/market-lsp/src/application}/lsp/profile-seam.js +1 -1
  55. package/lib/packages/market-lsp/src/application/lsp/validation.js +46 -0
  56. package/lib/{application → packages/market-lsp/src/application}/lsp-service.js +61 -3
  57. package/lib/packages/market-lsp/src/index.js +8 -0
  58. package/lib/{runtime → packages/market-lsp/src/runtime}/lsp/lsp-mounts.js +79 -40
  59. package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-backend.js +0 -16
  60. package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-config.js +104 -21
  61. package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-direct-config.js +12 -4
  62. package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-overrides.js +4 -4
  63. package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-status.js +49 -10
  64. package/lib/packages/market-mcp/src/application/mcp/validation.js +63 -0
  65. package/lib/{application → packages/market-mcp/src/application}/mcp-service.js +111 -91
  66. package/lib/packages/market-mcp/src/index.js +10 -0
  67. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/bridge.js +12 -9
  68. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/connection.js +1 -1
  69. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/oauth.js +1 -1
  70. package/lib/packages/market-mcp/src/runtime/mcp/bridge/tool-ownership.js +26 -0
  71. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/tools.js +1 -1
  72. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-auth-record.js +35 -4
  73. package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-mounts.js +35 -4
  74. package/lib/packages/market-runtime/src/adapter-contracts.js +1 -0
  75. package/lib/packages/market-runtime/src/application/command-resources.js +74 -0
  76. package/lib/packages/market-runtime/src/application/extension-authorization.js +27 -0
  77. package/lib/packages/market-runtime/src/application/extension-hook-selection.js +56 -0
  78. package/lib/packages/market-runtime/src/application/extension-suite-declarations.js +57 -0
  79. package/lib/packages/market-runtime/src/application/extension-suite-selection.js +84 -0
  80. package/lib/packages/market-runtime/src/application/fs-probe.js +43 -0
  81. package/lib/packages/market-runtime/src/application/panel-resources.js +370 -0
  82. package/lib/{application → packages/market-runtime/src/application}/panels/user-hooks.js +2 -2
  83. package/lib/{application → packages/market-runtime/src/application}/panels/user-store.js +53 -13
  84. package/lib/{application → packages/market-runtime/src/application}/project-agent-roles.js +20 -11
  85. package/lib/packages/market-runtime/src/application/state/extension-presets.js +144 -0
  86. package/lib/packages/market-runtime/src/application/state/resource-favorites.js +90 -0
  87. package/lib/packages/market-runtime/src/application/state/resource-filters.js +2 -0
  88. package/lib/packages/market-runtime/src/application/state/surface-toggles.js +10 -0
  89. package/lib/packages/market-runtime/src/application/state/workspace-policy.js +56 -0
  90. package/lib/packages/market-runtime/src/catalog-port.js +1 -0
  91. package/lib/packages/market-runtime/src/extension-service.js +1 -0
  92. package/lib/packages/market-runtime/src/index.js +31 -0
  93. package/lib/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-router.js +74 -79
  94. package/lib/packages/market-runtime/src/runtime/agents/agent-teams-seat.js +58 -0
  95. package/lib/{runtime → packages/market-runtime/src/runtime}/agents/subagent-catalog.js +89 -21
  96. package/lib/packages/market-runtime/src/runtime/agents/team-coordination.js +51 -0
  97. package/lib/packages/market-runtime/src/runtime/agents/teammate-role-runtime.js +241 -0
  98. package/lib/packages/market-runtime/src/runtime/agents/teammate-role-tool.js +130 -0
  99. package/lib/{runtime → packages/market-runtime/src/runtime}/core/reconcile-scheduler.js +2 -2
  100. package/lib/packages/market-runtime/src/runtime/core/reconciler.js +457 -0
  101. package/lib/packages/market-runtime/src/runtime/host/command-name-allocator.js +168 -0
  102. package/lib/packages/market-runtime/src/runtime/host/extension-progress.js +120 -0
  103. package/lib/packages/market-runtime/src/runtime/host/extension-runtime.js +405 -0
  104. package/lib/packages/market-runtime/src/runtime/host/extension-session-state.js +839 -0
  105. package/lib/packages/market-runtime/src/runtime/host/extension-tool-gates.js +96 -0
  106. package/lib/{runtime → packages/market-runtime/src/runtime}/host/failure-detail.js +1 -1
  107. package/lib/{runtime → packages/market-runtime/src/runtime}/host/host-locale.js +2 -0
  108. package/lib/packages/market-runtime/src/runtime/host/menu-row-identities.js +38 -0
  109. package/lib/packages/market-runtime/src/runtime/host/resource-filter-service.js +81 -0
  110. package/lib/packages/market-runtime/src/runtime/host/scoped-contributors.js +304 -0
  111. package/lib/packages/market-runtime/src/runtime/host/surface-toggle-service.js +15 -0
  112. package/lib/packages/market-runtime/src/runtime/panels/user-commands.js +211 -0
  113. package/lib/{runtime → packages/market-runtime/src/runtime}/panels/user-panels.js +34 -14
  114. package/lib/packages/market-runtime/src/runtime/surfaces/commands-mounts.js +256 -0
  115. package/lib/packages/market-runtime/src/runtime/surfaces/extension-hooks.js +294 -0
  116. package/lib/packages/market-runtime/src/runtime/surfaces/hook-dry-run.js +122 -0
  117. package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/hooks-mounts.js +1 -1
  118. package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/project-runtime.js +23 -13
  119. package/lib/packages/market-runtime/src/runtime/surfaces/skills-provider.js +241 -0
  120. package/lib/packages/market-translation/src/application/state/translation-cache.js +122 -0
  121. package/lib/packages/market-translation/src/application/translation/chain.js +99 -0
  122. package/lib/packages/market-translation/src/application/translation/document.js +384 -0
  123. package/lib/packages/market-translation/src/application/translation/localizer.js +642 -0
  124. package/lib/packages/market-translation/src/application/translation/service.js +113 -0
  125. package/lib/packages/market-translation/src/application/translation/unit.js +19 -0
  126. package/lib/packages/market-translation/src/index.js +4 -0
  127. package/lib/packages/market-translation/src/runtime/host/llm-translator.js +278 -0
  128. package/lib/packages/market-translation/src/runtime/host/machine-translator.js +152 -0
  129. package/lib/packages/market-translation/src/runtime/host/text-masking.js +96 -0
  130. package/lib/packages/market-translation/src/runtime/host/translation-providers.js +116 -0
  131. package/lib/types/index.d.ts +2 -130
  132. package/lib/types/{application → packages/market-bundle/src/application}/catalog.d.ts +117 -22
  133. package/lib/types/packages/market-bundle/src/application/details.d.ts +24 -0
  134. package/lib/types/packages/market-bundle/src/application/extension-inventory.d.ts +45 -0
  135. package/lib/types/packages/market-bundle/src/application/extension-project.d.ts +26 -0
  136. package/lib/types/packages/market-bundle/src/application/resource-inventory.d.ts +42 -0
  137. package/lib/types/packages/market-bundle/src/application/server-config.d.ts +9 -0
  138. package/lib/types/packages/market-bundle/src/application/suite-queries.d.ts +84 -0
  139. package/lib/types/packages/market-bundle/src/index.d.ts +125 -0
  140. package/lib/types/{runtime/host → packages/market-bundle/src/platform}/settings-namespace.d.ts +44 -9
  141. package/lib/types/{application/mcp/mcp-backend.d.ts → packages/market-bundle/src/platform/settings-schema.d.ts} +13 -28
  142. package/lib/types/packages/market-bundle/src/routes-extension-presets.d.ts +15 -0
  143. package/lib/types/packages/market-bundle/src/routes-resources.d.ts +17 -0
  144. package/lib/types/packages/market-bundle/src/routes.d.ts +32 -0
  145. package/lib/types/packages/market-bundle/src/runtime-adapters.d.ts +42 -0
  146. package/lib/types/packages/market-bundle/src/session-extension.d.ts +62 -0
  147. package/lib/types/{application → packages/market-catalog/src/application}/catalog-context.d.ts +11 -3
  148. package/lib/types/{application → packages/market-catalog/src/application}/install-store.d.ts +1 -1
  149. package/lib/types/{application → packages/market-catalog/src/application}/regions.d.ts +1 -1
  150. package/lib/types/{application → packages/market-catalog/src/application}/snapshot-cache.d.ts +44 -2
  151. package/lib/types/{application → packages/market-catalog/src/application}/source-store.d.ts +12 -3
  152. package/lib/types/{application → packages/market-catalog/src/application}/state/state-store.d.ts +1 -1
  153. package/lib/types/packages/market-catalog/src/index.d.ts +22 -0
  154. package/lib/types/{catalog → packages/market-catalog/src/scanning}/archive.d.ts +1 -1
  155. package/lib/types/{catalog → packages/market-catalog/src/scanning}/codex-mcp.d.ts +1 -1
  156. package/lib/types/{catalog → packages/market-catalog/src/scanning}/component-files.d.ts +1 -1
  157. package/lib/types/{catalog → packages/market-catalog/src/scanning}/lsp-spec.d.ts +1 -1
  158. package/lib/types/{catalog → packages/market-catalog/src/scanning}/manifests.d.ts +3 -3
  159. package/lib/types/{catalog → packages/market-catalog/src/scanning}/native-project.d.ts +2 -2
  160. package/lib/types/{catalog → packages/market-catalog/src/scanning}/plugin-variables.d.ts +12 -1
  161. package/lib/types/{catalog → packages/market-catalog/src/scanning}/project-config.d.ts +2 -2
  162. package/lib/types/{catalog → packages/market-catalog/src/scanning}/project-hooks.d.ts +2 -2
  163. package/lib/types/{catalog → packages/market-catalog/src/scanning}/scan-pipeline.d.ts +1 -1
  164. package/lib/types/{catalog → packages/market-catalog/src/scanning}/scan-resolvers.d.ts +3 -3
  165. package/lib/types/{catalog → packages/market-catalog/src/scanning}/source-catalog.d.ts +1 -1
  166. package/lib/types/{catalog → packages/market-catalog/src/scanning}/suite-components.d.ts +1 -1
  167. package/lib/types/{catalog → packages/market-catalog/src/scanning}/suite-scanner.d.ts +1 -1
  168. package/lib/types/{catalog → packages/market-catalog/src/scanning}/surfaces.d.ts +1 -1
  169. package/lib/types/{catalog → packages/market-catalog/src/scanning}/validate.d.ts +1 -1
  170. package/lib/types/packages/market-contracts/src/contracts/extension-presets.d.ts +237 -0
  171. package/lib/types/{contracts → packages/market-contracts/src/contracts}/market.d.ts +87 -16
  172. package/lib/types/packages/market-contracts/src/contracts/mcp-overrides.d.ts +39 -0
  173. package/lib/types/{contracts → packages/market-contracts/src/contracts}/mcp-status.d.ts +9 -0
  174. package/lib/types/packages/market-contracts/src/contracts/resource-window.d.ts +70 -0
  175. package/lib/types/packages/market-contracts/src/contracts/settings.d.ts +121 -0
  176. package/lib/types/packages/market-contracts/src/contracts/surface-toggles.d.ts +28 -0
  177. package/lib/types/packages/market-contracts/src/contracts/translation.d.ts +81 -0
  178. package/lib/types/{runtime → packages/market-contracts/src}/host/plugin-message-source.d.ts +1 -1
  179. package/lib/types/packages/market-contracts/src/index.d.ts +5 -0
  180. package/lib/types/{model → packages/market-contracts/src/model}/layouts.d.ts +7 -0
  181. package/lib/types/{model → packages/market-contracts/src/model}/types.d.ts +2 -2
  182. package/lib/types/packages/market-contracts/src/ports/ports.d.ts +183 -0
  183. package/lib/types/{application → packages/market-contracts/src/ports}/queries.d.ts +27 -6
  184. package/lib/types/{application/mcp/mcp-redaction.d.ts → packages/market-contracts/src/redaction.d.ts} +2 -0
  185. package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-direct-config.d.ts +1 -1
  186. package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-status.d.ts +21 -5
  187. package/lib/types/packages/market-lsp/src/application/lsp/validation.d.ts +8 -0
  188. package/lib/types/{application → packages/market-lsp/src/application}/lsp-service.d.ts +19 -6
  189. package/lib/types/packages/market-lsp/src/index.d.ts +8 -0
  190. package/lib/types/{runtime → packages/market-lsp/src/runtime}/lsp/lsp-mounts.d.ts +26 -6
  191. package/lib/types/packages/market-mcp/src/application/mcp/mcp-backend.d.ts +28 -0
  192. package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-bridge-config.d.ts +1 -1
  193. package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-config.d.ts +2 -2
  194. package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-direct-config.d.ts +6 -1
  195. package/lib/types/{application → packages/market-mcp/src/application}/mcp/mcp-overrides.d.ts +4 -38
  196. package/lib/types/packages/market-mcp/src/application/mcp/mcp-status.d.ts +40 -0
  197. package/lib/types/{application/server-config.d.ts → packages/market-mcp/src/application/mcp/validation.d.ts} +2 -10
  198. package/lib/types/{application → packages/market-mcp/src/application}/mcp-service.d.ts +22 -16
  199. package/lib/types/packages/market-mcp/src/index.d.ts +12 -0
  200. package/lib/types/packages/market-mcp/src/runtime/mcp/bridge/tool-ownership.d.ts +14 -0
  201. package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-auth-record.d.ts +4 -0
  202. package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-mounts.d.ts +19 -3
  203. package/lib/types/packages/market-runtime/src/adapter-contracts.d.ts +89 -0
  204. package/lib/types/{application → packages/market-runtime/src/application}/agent-roles.d.ts +2 -0
  205. package/lib/types/packages/market-runtime/src/application/command-resources.d.ts +26 -0
  206. package/lib/types/packages/market-runtime/src/application/extension-authorization.d.ts +12 -0
  207. package/lib/types/packages/market-runtime/src/application/extension-hook-selection.d.ts +23 -0
  208. package/lib/types/packages/market-runtime/src/application/extension-suite-declarations.d.ts +10 -0
  209. package/lib/types/packages/market-runtime/src/application/extension-suite-selection.d.ts +30 -0
  210. package/lib/types/packages/market-runtime/src/application/fs-probe.d.ts +12 -0
  211. package/lib/types/packages/market-runtime/src/application/panel-resources.d.ts +100 -0
  212. package/lib/types/{application → packages/market-runtime/src/application}/panels/user-hooks.d.ts +1 -1
  213. package/lib/types/packages/market-runtime/src/application/project-agent-roles.d.ts +10 -0
  214. package/lib/types/packages/market-runtime/src/application/state/extension-presets.d.ts +24 -0
  215. package/lib/types/packages/market-runtime/src/application/state/resource-favorites.d.ts +9 -0
  216. package/lib/types/packages/market-runtime/src/application/state/resource-filters.d.ts +2 -0
  217. package/lib/types/packages/market-runtime/src/application/state/surface-toggles.d.ts +6 -0
  218. package/lib/types/packages/market-runtime/src/application/state/workspace-policy.d.ts +19 -0
  219. package/lib/types/packages/market-runtime/src/catalog-port.d.ts +30 -0
  220. package/lib/types/packages/market-runtime/src/extension-service.d.ts +14 -0
  221. package/lib/types/packages/market-runtime/src/index.d.ts +41 -0
  222. package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-router.d.ts +66 -31
  223. package/lib/types/packages/market-runtime/src/runtime/agents/agent-teams-seat.d.ts +41 -0
  224. package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/subagent-catalog.d.ts +34 -2
  225. package/lib/types/packages/market-runtime/src/runtime/agents/team-coordination.d.ts +8 -0
  226. package/lib/types/packages/market-runtime/src/runtime/agents/teammate-role-runtime.d.ts +74 -0
  227. package/lib/types/packages/market-runtime/src/runtime/agents/teammate-role-tool.d.ts +6 -0
  228. package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/reconcile-scheduler.d.ts +5 -2
  229. package/lib/types/packages/market-runtime/src/runtime/core/reconciler.d.ts +141 -0
  230. package/lib/types/packages/market-runtime/src/runtime/host/command-name-allocator.d.ts +132 -0
  231. package/lib/types/packages/market-runtime/src/runtime/host/extension-progress.d.ts +91 -0
  232. package/lib/types/packages/market-runtime/src/runtime/host/extension-runtime.d.ts +77 -0
  233. package/lib/types/packages/market-runtime/src/runtime/host/extension-session-state.d.ts +242 -0
  234. package/lib/types/packages/market-runtime/src/runtime/host/extension-tool-gates.d.ts +38 -0
  235. package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/host-locale.d.ts +1 -1
  236. package/lib/types/packages/market-runtime/src/runtime/host/menu-row-identities.d.ts +50 -0
  237. package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/model-catalog.d.ts +1 -1
  238. package/lib/types/packages/market-runtime/src/runtime/host/resource-filter-service.d.ts +34 -0
  239. package/lib/types/packages/market-runtime/src/runtime/host/scoped-contributors.d.ts +58 -0
  240. package/lib/types/packages/market-runtime/src/runtime/host/surface-toggle-service.d.ts +10 -0
  241. package/lib/types/packages/market-runtime/src/runtime/panels/user-commands.d.ts +74 -0
  242. package/lib/types/{runtime → packages/market-runtime/src/runtime}/panels/user-panels.d.ts +7 -1
  243. package/lib/types/packages/market-runtime/src/runtime/surfaces/commands-mounts.d.ts +81 -0
  244. package/lib/types/packages/market-runtime/src/runtime/surfaces/extension-hooks.d.ts +59 -0
  245. package/lib/types/packages/market-runtime/src/runtime/surfaces/hook-dry-run.d.ts +91 -0
  246. package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/hooks-mounts.d.ts +1 -1
  247. package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/project-runtime.d.ts +8 -5
  248. package/lib/types/packages/market-runtime/src/runtime/surfaces/skills-provider.d.ts +71 -0
  249. package/lib/types/packages/market-translation/src/application/state/translation-cache.d.ts +56 -0
  250. package/lib/types/packages/market-translation/src/application/translation/chain.d.ts +47 -0
  251. package/lib/types/packages/market-translation/src/application/translation/document.d.ts +54 -0
  252. package/lib/types/packages/market-translation/src/application/translation/localizer.d.ts +325 -0
  253. package/lib/types/packages/market-translation/src/application/translation/service.d.ts +89 -0
  254. package/lib/types/packages/market-translation/src/application/translation/unit.d.ts +35 -0
  255. package/lib/types/packages/market-translation/src/index.d.ts +4 -0
  256. package/lib/types/packages/market-translation/src/runtime/host/llm-translator.d.ts +30 -0
  257. package/lib/types/packages/market-translation/src/runtime/host/machine-translator.d.ts +52 -0
  258. package/lib/types/packages/market-translation/src/runtime/host/text-masking.d.ts +42 -0
  259. package/lib/types/packages/market-translation/src/runtime/host/translation-providers.d.ts +42 -0
  260. package/locale/en.json +6 -0
  261. package/locale/zh.json +6 -0
  262. package/package.json +47 -10
  263. package/schemas/README.md +4 -4
  264. package/schemas/agent-plugins/spec.md +2 -2
  265. package/schemas/com.deepseek.harness/spec.md +1 -1
  266. package/schemas/skill-collection/spec.md +10 -2
  267. package/lib/application/panel-resources.js +0 -161
  268. package/lib/application/server-config.js +0 -109
  269. package/lib/contracts/settings.js +0 -63
  270. package/lib/runtime/core/reconciler.js +0 -100
  271. package/lib/runtime/panels/user-commands.js +0 -105
  272. package/lib/runtime/surfaces/commands-mounts.js +0 -186
  273. package/lib/runtime/surfaces/skills-provider.js +0 -160
  274. package/lib/types/application/details.d.ts +0 -7
  275. package/lib/types/application/mcp/mcp-status.d.ts +0 -24
  276. package/lib/types/application/panel-resources.d.ts +0 -28
  277. package/lib/types/application/ports.d.ts +0 -86
  278. package/lib/types/application/project-agent-roles.d.ts +0 -3
  279. package/lib/types/contracts/settings.d.ts +0 -59
  280. package/lib/types/routes.d.ts +0 -16
  281. package/lib/types/runtime/core/reconciler.d.ts +0 -58
  282. package/lib/types/runtime/panels/user-commands.d.ts +0 -27
  283. package/lib/types/runtime/surfaces/commands-mounts.d.ts +0 -48
  284. package/lib/types/runtime/surfaces/skills-provider.d.ts +0 -23
  285. /package/lib/{application → packages/market-catalog/src/application}/deadline.js +0 -0
  286. /package/lib/{application → packages/market-catalog/src/application}/json-file.js +0 -0
  287. /package/lib/{application → packages/market-catalog/src/application}/regions.js +0 -0
  288. /package/lib/{catalog → packages/market-catalog/src/scanning}/fs-probes.js +0 -0
  289. /package/lib/{catalog → packages/market-catalog/src/scanning}/git.js +0 -0
  290. /package/lib/{catalog → packages/market-catalog/src/scanning}/lsp-spec.js +0 -0
  291. /package/lib/{catalog → packages/market-catalog/src/scanning}/project-config.js +0 -0
  292. /package/lib/{catalog → packages/market-catalog/src/scanning}/project-hooks.js +0 -0
  293. /package/lib/{catalog → packages/market-catalog/src/scanning}/scan-pipeline.js +0 -0
  294. /package/lib/{catalog → packages/market-catalog/src/scanning}/source-catalog.js +0 -0
  295. /package/lib/{catalog → packages/market-catalog/src/scanning}/suite-components.js +0 -0
  296. /package/lib/{catalog → packages/market-catalog/src/scanning}/suite-scanner.js +0 -0
  297. /package/lib/{catalog → packages/market-catalog/src/scanning}/surfaces.js +0 -0
  298. /package/lib/{contracts → packages/market-contracts/src/contracts}/lsp-status.js +0 -0
  299. /package/lib/{contracts → packages/market-contracts/src/contracts}/lsp.js +0 -0
  300. /package/lib/{contracts → packages/market-contracts/src/contracts}/mcp-status.js +0 -0
  301. /package/lib/{contracts → packages/market-contracts/src/contracts}/mcp.js +0 -0
  302. /package/lib/{runtime → packages/market-contracts/src}/host/plugin-message-source.js +0 -0
  303. /package/lib/{model → packages/market-contracts/src/model}/command-names.js +0 -0
  304. /package/lib/{model → packages/market-contracts/src/model}/preset-source.js +0 -0
  305. /package/lib/{model → packages/market-contracts/src/model}/types.js +0 -0
  306. /package/lib/{application → packages/market-contracts/src/ports}/queries.js +0 -0
  307. /package/lib/{application → packages/market-mcp/src/application}/mcp/mcp-bridge-config.js +0 -0
  308. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-contract.js +0 -0
  309. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-seams.js +0 -0
  310. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/plugin-identity.js +0 -0
  311. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/projection.js +0 -0
  312. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/transport.js +0 -0
  313. /package/lib/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-credentials.js +0 -0
  314. /package/lib/{application → packages/market-runtime/src/application}/agent-roles.js +0 -0
  315. /package/lib/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-names.js +0 -0
  316. /package/lib/{runtime → packages/market-runtime/src/runtime}/core/context.js +0 -0
  317. /package/lib/{runtime → packages/market-runtime/src/runtime}/core/mount-lifecycle.js +0 -0
  318. /package/lib/{runtime → packages/market-runtime/src/runtime}/core/source-auto-update.js +0 -0
  319. /package/lib/{runtime → packages/market-runtime/src/runtime}/core/timer-seat.js +0 -0
  320. /package/lib/{runtime → packages/market-runtime/src/runtime}/host/model-catalog.js +0 -0
  321. /package/lib/{runtime → packages/market-runtime/src/runtime}/host/shell-path.js +0 -0
  322. /package/lib/{runtime → packages/market-runtime/src/runtime}/host/tool-registry-observer.js +0 -0
  323. /package/lib/{runtime → packages/market-runtime/src/runtime}/surfaces/dynamic-context.js +0 -0
  324. /package/lib/types/{runtime/host → packages/market-bundle/src/platform}/feedback-tool.d.ts +0 -0
  325. /package/lib/types/{application → packages/market-catalog/src/application}/deadline.d.ts +0 -0
  326. /package/lib/types/{application → packages/market-catalog/src/application}/json-file.d.ts +0 -0
  327. /package/lib/types/{application → packages/market-catalog/src/application}/state/storage-migration.d.ts +0 -0
  328. /package/lib/types/{catalog → packages/market-catalog/src/scanning}/fs-probes.d.ts +0 -0
  329. /package/lib/types/{catalog → packages/market-catalog/src/scanning}/git.d.ts +0 -0
  330. /package/lib/types/{catalog → packages/market-catalog/src/scanning}/paths.d.ts +0 -0
  331. /package/lib/types/{catalog → packages/market-catalog/src/scanning}/skills-parse.d.ts +0 -0
  332. /package/lib/types/{contracts → packages/market-contracts/src/contracts}/lsp-status.d.ts +0 -0
  333. /package/lib/types/{contracts → packages/market-contracts/src/contracts}/lsp.d.ts +0 -0
  334. /package/lib/types/{contracts → packages/market-contracts/src/contracts}/mcp.d.ts +0 -0
  335. /package/lib/types/{model → packages/market-contracts/src/model}/command-names.d.ts +0 -0
  336. /package/lib/types/{model → packages/market-contracts/src/model}/preset-source.d.ts +0 -0
  337. /package/lib/types/{application → packages/market-lsp/src/application}/lsp/lsp-server-state.d.ts +0 -0
  338. /package/lib/types/{application → packages/market-lsp/src/application}/lsp/profile-seam.d.ts +0 -0
  339. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/bridge.d.ts +0 -0
  340. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/connection.d.ts +0 -0
  341. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-contract.d.ts +0 -0
  342. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/host-seams.d.ts +0 -0
  343. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/oauth.d.ts +0 -0
  344. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/plugin-identity.d.ts +0 -0
  345. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/projection.d.ts +0 -0
  346. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/tools.d.ts +0 -0
  347. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/bridge/transport.d.ts +0 -0
  348. /package/lib/types/{runtime → packages/market-mcp/src/runtime}/mcp/mcp-credentials.d.ts +0 -0
  349. /package/lib/types/{application → packages/market-runtime/src/application}/panels/user-store.d.ts +0 -0
  350. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/agents/agent-role-names.d.ts +0 -0
  351. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/context.d.ts +0 -0
  352. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/mount-lifecycle.d.ts +0 -0
  353. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/source-auto-update.d.ts +0 -0
  354. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/core/timer-seat.d.ts +0 -0
  355. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/failure-detail.d.ts +0 -0
  356. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/shell-path.d.ts +0 -0
  357. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/host/tool-registry-observer.d.ts +0 -0
  358. /package/lib/types/{runtime → packages/market-runtime/src/runtime}/surfaces/dynamic-context.d.ts +0 -0
@@ -0,0 +1,113 @@
1
+ import { chunkDocument, translateMarkdownDocument } from './document.js';
2
+ import { TranslationLocalizer } from './localizer.js';
3
+ import { collectUnits } from './unit.js';
4
+ export class TranslationService {
5
+ localizer;
6
+ constructor(options) {
7
+ this.localizer = new TranslationLocalizer(options);
8
+ }
9
+ /** Read the persisted cache once, before the first {@link translateFields} read. */
10
+ load() {
11
+ return this.localizer.load();
12
+ }
13
+ /** Cancel timers and drop queued work; in-flight calls finish and are persisted. */
14
+ dispose() {
15
+ this.localizer.dispose();
16
+ }
17
+ /** Drop every cached translation, in memory and on disk. */
18
+ clear() {
19
+ return this.localizer.clear();
20
+ }
21
+ /** Apply a live display-preference change: off cancels unfinished work, on forgets failures. */
22
+ onEnabledChanged() {
23
+ this.localizer.onEnabledChanged();
24
+ }
25
+ /** Wait until the queue drains or the deadline passes. */
26
+ settle(deadlineMs) {
27
+ return this.localizer.settle(deadlineMs);
28
+ }
29
+ /**
30
+ * Translate one entity's description for a surface.
31
+ *
32
+ * Only the description is a translatable field: a name is an identity the user
33
+ * types, greps, and matches against upstream documentation, so the collector
34
+ * hands back no unit for one. Nothing here waits on a provider: an uncached
35
+ * field answers with the upstream text and reports itself pending.
36
+ *
37
+ * A description longer than one chunk travels in chunks, exactly as a
38
+ * document body does ({@link localizeText}), so the size of an upstream field
39
+ * is never a reason for a provider call to be cut off.
40
+ *
41
+ * Exposed for the panel and status surfaces that build their own rows; it is
42
+ * not part of the HTTP route surface.
43
+ * @param surface - the surface the entity belongs to.
44
+ * @param id - the entity's stable identity inside that surface.
45
+ * @param fields - the entity's upstream name and description.
46
+ * @param locale - the host locale this read resolved once; there is no
47
+ * default, because a default would re-read the host preference per entity and
48
+ * make a read's cost scale with its row count.
49
+ * @returns the translated fields and how many of them are still pending.
50
+ */
51
+ translateFields(surface, id, fields, locale) {
52
+ const translated = {};
53
+ let pending = 0;
54
+ for (const unit of collectUnits(surface, id, fields)) {
55
+ const result = this.localizeText(unit.surface, unit.id, unit.role ?? 'description', unit.text, locale);
56
+ pending += result.pending;
57
+ if (result.text !== unit.text)
58
+ translated.translatedDescription = result.text;
59
+ }
60
+ return { fields: translated, pending };
61
+ }
62
+ /**
63
+ * Translate one authored text, chunk by chunk, and reassemble it exactly.
64
+ *
65
+ * Every text the layer sends travels the way a document does: split on blank
66
+ * lines into chunks one request may carry, fenced code passed through
67
+ * verbatim, and the authored text between chunks re-emitted rather than
68
+ * synthesized — so a text nothing was translated for comes back byte for
69
+ * byte, and a translated one keeps the author's own blank lines. A
70
+ * description is chunked for the same reason a document is: the model hop
71
+ * sizes one call's output from the source it carries, and a text that exceeds
72
+ * that budget is cut off mid-generation, which fails the batch and retires the
73
+ * provider for the rest of the session.
74
+ * @param surface - the surface the entity belongs to.
75
+ * @param id - the entity's stable identity inside that surface.
76
+ * @param role - which text of the entity this is; the cache key's role slot.
77
+ * @param text - the authored text.
78
+ * @param locale - the interface language this read resolved once.
79
+ * @returns the reassembled text and how many of its chunks are still in flight.
80
+ */
81
+ localizeText(surface, id, role, text, locale) {
82
+ const chunks = chunkDocument(text);
83
+ if (chunks.length === 0)
84
+ return { text, pending: 0 };
85
+ let pending = 0;
86
+ const parts = [];
87
+ for (const chunk of chunks) {
88
+ if (!chunk.translatable) {
89
+ parts.push(chunk.text, chunk.separator);
90
+ continue;
91
+ }
92
+ const result = this.localizer.localize({ surface, id, role, text: chunk.text }, locale);
93
+ if (result.pending)
94
+ pending += 1;
95
+ parts.push(result.text, chunk.separator);
96
+ }
97
+ return { text: parts.join(''), pending };
98
+ }
99
+ /**
100
+ * Translate paragraphs in one complete Markdown tree. The provider receives
101
+ * prose only. Links, code, math, references and nested containers remain local.
102
+ * The result includes a translated document and paragraph-paired Markdown.
103
+ * Unchanged output preserves the source bytes. Changed output preserves the
104
+ * parsed structure and uses canonical Markdown formatting. Pending paragraphs
105
+ * remain authored until complete. The retry flag resets only this document
106
+ * failure budgets and the provider breaker, without clearing cached successes.
107
+ */
108
+ translateDocument(surface, id, text, locale, retry = false) {
109
+ if (retry)
110
+ this.localizer.retryDocument(surface, id);
111
+ return translateMarkdownDocument(text, (paragraph, parts) => this.localizer.localizeParagraph({ surface, id, role: 'document', text: paragraph }, parts, locale));
112
+ }
113
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Collect units for one entity, skipping empty or undefined text.
3
+ *
4
+ * Descriptions only: a name is an identifier the user types and matches against
5
+ * upstream documentation, and translating one made it harder to recognize than
6
+ * the original. The text is carried verbatim — the emptiness check trims, but
7
+ * the unit does not, so the cache key stays tied to what upstream authored.
8
+ * @param surface - the surface the entity belongs to.
9
+ * @param id - the entity's stable identity inside that surface.
10
+ * @param fields - the entity's upstream name and description.
11
+ * @returns the units to translate.
12
+ */
13
+ export function collectUnits(surface, id, fields) {
14
+ return isTranslatable(fields.description) ? [{ surface, id, text: fields.description }] : [];
15
+ }
16
+ /** Whether a field holds text worth sending to a translation backend. */
17
+ function isTranslatable(text) {
18
+ return typeof text === 'string' && text.trim() !== '';
19
+ }
@@ -0,0 +1,4 @@
1
+ /** Explicit cross-domain entry surface. Internal modules are not import targets for siblings. */
2
+ export { TranslationService } from './application/translation/service.js';
3
+ export { createLlmTranslator } from './runtime/host/llm-translator.js';
4
+ export { createTranslationProviders } from './runtime/host/translation-providers.js';
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Translate a batch of texts through the host's own LLM service.
3
+ *
4
+ * This is the only place the translation layer talks to a model. It follows the
5
+ * harness auxiliary-call shape (packages/session/session-title-llm): resolve a
6
+ * route, stream through ctx.llm.stream, assemble the chunks with
7
+ * BlockAssembler, and reject on a terminal finish reason.
8
+ *
9
+ * The route is the user default model, read at call time from
10
+ * agentDefaultModel -- the same selection the harness uses for its own
11
+ * auxiliary calls, so the market never invents a model the deployment did not
12
+ * configure. purpose is deliberately omitted: the published
13
+ * GenerateOptions.purpose accepts only compaction and session-title, and
14
+ * neither describes a translation. Omitting it keeps the call on the ordinary
15
+ * route with no model-hidden transport metadata.
16
+ * @module runtime/host/llm-translator
17
+ */
18
+ import { BlockAssembler, createUserMessage } from '@deepseek-ai/dsh-llm';
19
+ import { pluginMarketSource } from '../../../../market-contracts/src/host/plugin-message-source.js';
20
+ /** Bound the call: a stalled model must not pin a translation slot forever. */
21
+ const TRANSLATE_TIMEOUT_MS = 30_000;
22
+ /**
23
+ * Conservative output allowances, not tokenizer measurements. English output
24
+ * can expand Chinese source substantially; its 1.5 allowance is paired with
25
+ * the localizer's smaller English-target batches. Chinese retains the 0.6
26
+ * estimate. Both remain bounded by MAX_OUTPUT_TOKENS_CAP.
27
+ */
28
+ const OUTPUT_TOKENS_PER_SOURCE_CHAR = { zh: 0.6, en: 1.5 };
29
+ /** Floor for one call, so a short text still has room for its own output. */
30
+ const MIN_OUTPUT_TOKENS = 512;
31
+ /** Ceiling for one call, so a large one cannot ask for an unbounded generation. */
32
+ export const MAX_OUTPUT_TOKENS_CAP = 4_096;
33
+ /**
34
+ * The output budget for one call carrying this much source text.
35
+ *
36
+ * Sized from the source rather than from the text count: what a call has to
37
+ * answer is the expansion of the text it was handed, so a batch of one long
38
+ * text and a batch of twenty short ones are budgeted by the same rule.
39
+ * @param sourceChars - characters in the user turn this call will send.
40
+ * @param locale - target language; English uses the larger expansion allowance.
41
+ * @returns the output token ceiling to ask the route for.
42
+ */
43
+ export function outputTokenBudget(sourceChars, locale = 'zh') {
44
+ const ratio = locale.toLowerCase().startsWith('en') ? OUTPUT_TOKENS_PER_SOURCE_CHAR.en : OUTPUT_TOKENS_PER_SOURCE_CHAR.zh;
45
+ return Math.min(Math.max(Math.ceil(sourceChars * ratio), MIN_OUTPUT_TOKENS), MAX_OUTPUT_TOKENS_CAP);
46
+ }
47
+ /**
48
+ * Batch separator: a line holding only two percent signs.
49
+ *
50
+ * A model asked to translate several segments at once needs an unambiguous
51
+ * boundary, and this one cannot appear inside ordinary prose.
52
+ */
53
+ const BATCH_SEPARATOR = '\n\n%%\n\n';
54
+ const BATCH_SEPARATOR_PATTERN = /\r?\n[ \t]*%%[ \t]*\r?\n/;
55
+ /**
56
+ * The language name a target tag is asked for in.
57
+ *
58
+ * A model reads a language name, not a tag: `zh` alone is answered in
59
+ * Traditional as often as in Simplified. The layer resolves the interface
60
+ * preference to the language the market actually renders ({@link
61
+ * resolveTranslationTarget}) before the chain is called, so the tags that reach
62
+ * here are few; the table names the spellings a caller may still hand in,
63
+ * because a tag that names a script should be answered in that script rather
64
+ * than left for the model to interpret.
65
+ */
66
+ const TARGET_LANGUAGE_NAMES = {
67
+ zh: 'Simplified Chinese',
68
+ 'zh-hans': 'Simplified Chinese',
69
+ 'zh-cn': 'Simplified Chinese',
70
+ 'zh-sg': 'Simplified Chinese',
71
+ 'zh-hant': 'Traditional Chinese',
72
+ 'zh-tw': 'Traditional Chinese',
73
+ 'zh-hk': 'Traditional Chinese',
74
+ en: 'English'
75
+ };
76
+ /** The language to translate into, named for the prompt. */
77
+ function targetLanguageName(locale) {
78
+ return TARGET_LANGUAGE_NAMES[locale.toLowerCase()] ?? locale;
79
+ }
80
+ /**
81
+ * Stable instruction; the target language and the batch flag are the variables.
82
+ * @param locale - target locale id.
83
+ * @param batched - whether the user turn carries several segments.
84
+ * @returns the system prompt for this call.
85
+ */
86
+ function systemPrompt(locale, batched) {
87
+ const lines = [
88
+ 'You translate plugin marketplace text for a developer tool.',
89
+ 'Translate the user text into ' + targetLanguageName(locale) + '.',
90
+ 'Preserve product names, package names, acronyms (MCP, LSP, DSH, CLI), and URLs exactly as written.',
91
+ 'Keep the tone factual and concise. Output the translation alone: no quotes, no notes, no alternatives.'
92
+ ];
93
+ if (batched) {
94
+ lines.push('The input holds several segments separated by a line containing only two percent signs.', 'Return the same number of segments in the same order, separated the same way.', 'Never use that separator for anything else, and never merge or split segments.');
95
+ }
96
+ return lines.join(' ');
97
+ }
98
+ /**
99
+ * The user turn carrying the text.
100
+ *
101
+ * Built through the host factory rather than as a literal: a UserMessage
102
+ * carries a stable id and a source tag, and hand-writing one would fabricate
103
+ * both. The source is this plugin declared producer identity -- the turn is an
104
+ * instruction this plugin sends, not text the user typed.
105
+ * @param text - the masked text to translate.
106
+ * @returns the user message to send.
107
+ */
108
+ function userMessage(text) {
109
+ return createUserMessage({ content: [{ type: 'text', text }], source: pluginMarketSource() });
110
+ }
111
+ /**
112
+ * Read the route the deployment selected, or undefined.
113
+ * @param host - the plugin context, read structurally.
114
+ * @returns the resolved route, or undefined when no model is configured.
115
+ */
116
+ function readRoute(host) {
117
+ try {
118
+ const service = host.get?.('agentDefaultModel');
119
+ const selection = service?.currentSelection();
120
+ if (selection === undefined)
121
+ return undefined;
122
+ if (typeof selection.provider !== 'string' || typeof selection.model !== 'string')
123
+ return undefined;
124
+ if (selection.provider.length === 0 || selection.model.length === 0)
125
+ return undefined;
126
+ const effort = typeof selection.reasoningEffort === 'string' && selection.reasoningEffort.length > 0 ? selection.reasoningEffort : undefined;
127
+ return { provider: selection.provider, model: selection.model, ...(effort === undefined ? {} : { reasoningEffort: effort }) };
128
+ }
129
+ catch {
130
+ // A half-provisioned service is indistinguishable from an absent one.
131
+ return undefined;
132
+ }
133
+ }
134
+ /**
135
+ * Choose the reasoning effort for one translation call.
136
+ *
137
+ * Translating a sentence is mechanical, and the DeepSeek adapter default is
138
+ * high -- leaving the effort unset would spend reasoning tokens on every one of
139
+ * hundreds of texts. So the call asks for off first and keeps the user own
140
+ * selection only if the route refuses it: an unsupported effort rejects at
141
+ * validation rather than reaching the provider, and a model that genuinely
142
+ * requires reasoning still gets a working call instead of a failure.
143
+ *
144
+ * The user selection is forwarded rather than overridden when it is already
145
+ * explicit, because that is a choice they made for this deployment.
146
+ * @param llm - live LLM runtime owning effort validation, when it exposes it.
147
+ * @param route - the resolved provider/model route.
148
+ * @param signal - cancellation for the capability lookup.
149
+ * @returns the effort to send, or undefined to accept the adapter default.
150
+ */
151
+ async function chooseEffort(llm, route, signal) {
152
+ if (route.reasoningEffort !== undefined)
153
+ return route.reasoningEffort;
154
+ if (llm.resolveCallConfig === undefined)
155
+ return undefined;
156
+ try {
157
+ await llm.resolveCallConfig({ provider: route.provider, model: route.model, reasoningEffort: 'off' }, signal);
158
+ return 'off';
159
+ }
160
+ catch {
161
+ // The route does not accept off; fall back to its own default.
162
+ return undefined;
163
+ }
164
+ }
165
+ /**
166
+ * Translate a terminal finish reason into an auxiliary-call failure.
167
+ * @param finish - the assembled finish reason.
168
+ * @returns the error to throw, or undefined when the stream ended normally.
169
+ */
170
+ function finishError(finish) {
171
+ switch (finish.kind) {
172
+ case 'stop':
173
+ return undefined;
174
+ case 'error':
175
+ case 'aborted': {
176
+ const error = new Error(finish.failure.message);
177
+ error.code = finish.failure.code;
178
+ return error;
179
+ }
180
+ case 'max-tokens':
181
+ return new Error('translation reached the output token limit');
182
+ case 'tool-calls':
183
+ return new Error('translation unexpectedly requested a tool');
184
+ default:
185
+ return new Error('translation stopped for an unsupported reason: ' + String(finish.kind));
186
+ }
187
+ }
188
+ /**
189
+ * Collect the assistant text from one stream, rejecting on a terminal failure.
190
+ * @param stream - the chunk stream from the LLM service.
191
+ * @param signal - cancellation, checked between chunks.
192
+ * @returns the assembled assistant text.
193
+ */
194
+ async function collectText(stream, signal) {
195
+ const assembler = new BlockAssembler();
196
+ for await (const chunk of stream) {
197
+ signal.throwIfAborted();
198
+ assembler.push(chunk);
199
+ }
200
+ signal.throwIfAborted();
201
+ const terminal = finishError(assembler.finish);
202
+ if (terminal !== undefined)
203
+ throw terminal;
204
+ const blocks = assembler.blocks();
205
+ const text = blocks
206
+ .filter((block) => block.type === 'text')
207
+ .map(block => block.text)
208
+ .join(' ')
209
+ .trim();
210
+ if (text.length === 0)
211
+ throw new Error('the model returned no text');
212
+ return text;
213
+ }
214
+ /**
215
+ * Build the model-backed provider over one plugin context.
216
+ *
217
+ * Every read is deferred to the call, because the LLM and default-model
218
+ * services provision after apply() returns; a value captured here would stay
219
+ * undefined for the life of the process. available() therefore re-resolves the
220
+ * route on each question, and a deployment with no model configured never
221
+ * queues work nothing can complete.
222
+ * @param host - the plugin context, read structurally so tests can pass a stub.
223
+ * @returns a provider bound to this context.
224
+ */
225
+ export function createLlmTranslator(host) {
226
+ return {
227
+ id: 'llm',
228
+ available: () => readRoute(host) !== undefined && host.get?.('llm') !== undefined,
229
+ async translate(request) {
230
+ request.signal.throwIfAborted();
231
+ const llm = host.get?.('llm');
232
+ const route = readRoute(host);
233
+ if (llm === undefined || route === undefined)
234
+ throw new Error('the DSH model service is unavailable');
235
+ const texts = request.texts;
236
+ if (texts.length === 0)
237
+ return [];
238
+ const batched = texts.length > 1;
239
+ // One controller merges caller cancellation with the call deadline, so a
240
+ // stalled provider cannot hold a translation slot open.
241
+ const controller = new AbortController();
242
+ const onAbort = () => controller.abort();
243
+ request.signal.addEventListener('abort', onAbort, { once: true });
244
+ const timeout = setTimeout(onAbort, TRANSLATE_TIMEOUT_MS);
245
+ timeout.unref?.();
246
+ try {
247
+ const effort = await chooseEffort(llm, route, controller.signal);
248
+ controller.signal.throwIfAborted();
249
+ // The budget is sized from what this call actually carries: the batch
250
+ // separator is part of the turn, and a text longer than any earlier
251
+ // batch is what the response has to cover.
252
+ const source = batched ? texts.join(BATCH_SEPARATOR) : (texts[0] ?? '');
253
+ const options = {
254
+ provider: route.provider,
255
+ model: route.model,
256
+ system: systemPrompt(request.locale, batched),
257
+ messages: [userMessage(source)],
258
+ maxTokens: outputTokenBudget(source.length, request.locale),
259
+ temperature: 0,
260
+ ...(effort === undefined ? {} : { reasoningEffort: effort }),
261
+ signal: controller.signal
262
+ };
263
+ const answer = await collectText(llm.stream(options), controller.signal);
264
+ if (!batched)
265
+ return [answer];
266
+ const segments = answer.split(BATCH_SEPARATOR_PATTERN).map(segment => segment.trim());
267
+ if (segments.length !== texts.length) {
268
+ throw new Error('the model returned ' + String(segments.length) + ' of ' + String(texts.length) + ' segments');
269
+ }
270
+ return segments;
271
+ }
272
+ finally {
273
+ clearTimeout(timeout);
274
+ request.signal.removeEventListener('abort', onAbort);
275
+ }
276
+ }
277
+ };
278
+ }
@@ -0,0 +1,152 @@
1
+ /** Google's public web-translation endpoint, the one the Translate widget calls. */
2
+ const GOOGLE_ENDPOINT = 'https://translate-pa.googleapis.com/v1/translateHtml';
3
+ /**
4
+ * The key the endpoint above expects. It is a public, browser-embedded key
5
+ * rather than a credential issued to this plugin — the same value ships inside
6
+ * every page that renders Google's translate widget, so it identifies the
7
+ * calling application and grants nothing.
8
+ */
9
+ const GOOGLE_API_KEY = 'AIzaSyATBXajvzQLTDHEQbcpq0Ihe0vWDHmO520';
10
+ /** Microsoft's consumer endpoint, the one Edge's translate feature calls. */
11
+ const MICROSOFT_ENDPOINT = 'https://edge.microsoft.com/translate/translatetext';
12
+ /** Auto-detect each request item; user-authored text can be Chinese or English. */
13
+ const SOURCE_LANGUAGE = 'auto';
14
+ /** How much of an error body to quote before it stops being diagnostic. */
15
+ const ERROR_BODY_LIMIT = 200;
16
+ /**
17
+ * Google's target language id.
18
+ *
19
+ * Google reads a bare `zh` as Simplified Chinese already, so the host's own
20
+ * value needs no qualification. A tag that names a script or region more
21
+ * precisely than the host does — `zh-Hant`, `ja` — is forwarded as authored
22
+ * rather than flattened to its primary subtag, which would silently answer in
23
+ * the wrong script.
24
+ */
25
+ function googleTargetLanguage(locale) {
26
+ return locale.toLowerCase() === 'zh' ? 'zh' : locale;
27
+ }
28
+ /**
29
+ * Microsoft's target language id.
30
+ *
31
+ * This endpoint picks the script from the tag itself, so the host's bare `zh`
32
+ * — which names no script — has to be qualified to reach Simplified Chinese.
33
+ * A tag that already names one is forwarded as authored, so `zh-Hant` still
34
+ * answers in Traditional.
35
+ */
36
+ function microsoftTargetLanguage(locale) {
37
+ return locale.toLowerCase() === 'zh' ? 'zh-Hans' : locale;
38
+ }
39
+ /** One error's message, whatever was thrown. */
40
+ function reason(error) {
41
+ return error instanceof Error ? error.message : String(error);
42
+ }
43
+ /**
44
+ * POST a JSON body and read the JSON answer, with the endpoint named in every
45
+ * failure so a chain log says which hop broke.
46
+ */
47
+ async function postJson(provider, url, init) {
48
+ let response;
49
+ try {
50
+ response = await fetch(url, init);
51
+ }
52
+ catch (error) {
53
+ throw new Error(`${provider} translate: ${reason(error)}`, { cause: error });
54
+ }
55
+ if (!response.ok) {
56
+ const detail = await response.text().catch(() => '');
57
+ throw new Error(`${provider} translate: HTTP ${String(response.status)}${detail === '' ? '' : `: ${detail.slice(0, ERROR_BODY_LIMIT)}`}`);
58
+ }
59
+ try {
60
+ const payload = await response.json();
61
+ return payload;
62
+ }
63
+ catch (error) {
64
+ throw new Error(`${provider} translate: unreadable response body: ${reason(error)}`, { cause: error });
65
+ }
66
+ }
67
+ /** Read the first translation out of one Microsoft answer entry, or undefined. */
68
+ function microsoftEntryText(entry) {
69
+ if (typeof entry !== 'object' || entry === null)
70
+ return undefined;
71
+ const translations = entry['translations'];
72
+ if (!Array.isArray(translations))
73
+ return undefined;
74
+ const first = translations[0];
75
+ if (typeof first !== 'object' || first === null)
76
+ return undefined;
77
+ const text = first['text'];
78
+ return typeof text === 'string' ? text : undefined;
79
+ }
80
+ /**
81
+ * Accept one answer batch only when it lines up with the request.
82
+ *
83
+ * A batch endpoint that answers short has dropped a unit somewhere, and a
84
+ * positionally aligned result would silently pair translations with the wrong
85
+ * entity. Rejecting the whole batch costs one fallback hop and keeps every
86
+ * answer attached to its own text.
87
+ */
88
+ function requireBatch(provider, value, expected) {
89
+ const expectedText = `${provider} translate: expected ${String(expected)} results`;
90
+ if (!Array.isArray(value))
91
+ throw new Error(`${expectedText}, got not an array`);
92
+ if (value.length !== expected)
93
+ throw new Error(`${expectedText}, got ${String(value.length)}`);
94
+ // A well-sized batch whose entries carry no text is a different fault from a
95
+ // short batch, and the two need different words to be diagnosable.
96
+ const unreadable = value.filter(item => typeof item !== 'string').length;
97
+ if (unreadable > 0)
98
+ throw new Error(`${expectedText}, but ${String(unreadable)} carried no text`);
99
+ return value;
100
+ }
101
+ /**
102
+ * Translate one batch through Google's public endpoint.
103
+ *
104
+ * The body is the endpoint's own protobuf-JSON envelope: a single triple of
105
+ * texts, source language and target language, tagged `wt_lib` so the answer
106
+ * comes back as a plain array rather than as the widget's HTML payload.
107
+ * @param request - the batch, its target locale and cancellation.
108
+ * @returns the translations and the provider id.
109
+ * @throws when the request fails, the endpoint refuses it, or the answer does not line up.
110
+ */
111
+ export async function googleTranslate(request) {
112
+ if (request.texts.length === 0)
113
+ return { texts: [], provider: 'google' };
114
+ const payload = await postJson('google', GOOGLE_ENDPOINT, {
115
+ method: 'POST',
116
+ headers: {
117
+ 'content-type': 'application/json+protobuf',
118
+ 'x-goog-api-key': GOOGLE_API_KEY
119
+ },
120
+ body: JSON.stringify([[request.texts, SOURCE_LANGUAGE, googleTargetLanguage(request.locale)], 'wt_lib']),
121
+ signal: request.signal
122
+ });
123
+ // The answer is one array of arrays; the outer one carries the batch.
124
+ const batch = Array.isArray(payload) ? payload[0] : undefined;
125
+ return { texts: requireBatch('google', batch, request.texts.length), provider: 'google' };
126
+ }
127
+ /**
128
+ * Translate one batch through Microsoft's public endpoint.
129
+ *
130
+ * The body is the bare string array, and the languages ride the query string.
131
+ * `isEnterpriseClient=false` selects the consumer backend, which is the one
132
+ * that answers without authentication.
133
+ * @param request - the batch, its target locale and cancellation.
134
+ * @returns the translations and the provider id.
135
+ * @throws when the request fails, the endpoint refuses it, or the answer does not line up.
136
+ */
137
+ export async function microsoftTranslate(request) {
138
+ if (request.texts.length === 0)
139
+ return { texts: [], provider: 'microsoft' };
140
+ const query = new URLSearchParams({
141
+ to: microsoftTargetLanguage(request.locale),
142
+ isEnterpriseClient: 'false'
143
+ });
144
+ const payload = await postJson('microsoft', `${MICROSOFT_ENDPOINT}?${query.toString()}`, {
145
+ method: 'POST',
146
+ headers: { 'content-type': 'application/json' },
147
+ body: JSON.stringify(request.texts),
148
+ signal: request.signal
149
+ });
150
+ const texts = Array.isArray(payload) ? payload.map(microsoftEntryText) : payload;
151
+ return { texts: requireBatch('microsoft', texts, request.texts.length), provider: 'microsoft' };
152
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Mask the spans a machine engine corrupts, then restore them from its answer.
3
+ *
4
+ * Neither keyless endpoint leaves technical text alone: Google's HTML aligner
5
+ * escapes a bare `<`, and Microsoft folds angle brackets into pseudo-tags. The
6
+ * spans those engines damage — inline code, URLs, tag fragments and `${VAR}`
7
+ * paths — are exactly what a catalog description is made of, and the fixed terms
8
+ * are the ones an engine likes to paraphrase. Sending a bracketed token instead
9
+ * keeps the payload plain, and the restore table puts the original text back.
10
+ *
11
+ * The same table is the integrity check. An answer is accepted only when every
12
+ * placeholder it recorded comes back exactly once and nothing placeholder-shaped
13
+ * was invented, so a truncated or rewritten answer is discarded rather than
14
+ * rendered with a stray `⟦C1⟧` in it.
15
+ * @module runtime/host/text-masking
16
+ */
17
+ /**
18
+ * The masking passes, widest span first.
19
+ *
20
+ * Order is load-bearing, in two places. Inline code runs first because its body
21
+ * may contain every other span, and angle-bracket fragments run before URLs
22
+ * because a markdown autolink is one fragment: masking the URL first would
23
+ * leave its bare `<` behind for the engine to escape, while masking the
24
+ * fragment first keeps the whole span intact.
25
+ */
26
+ const MASK_RULES = [
27
+ { letter: 'D', pattern: /⟪d\d+⟫/g },
28
+ { letter: 'C', pattern: /`[^`]*`/g },
29
+ { letter: 'T', pattern: /<[^>]{0,200}>/g },
30
+ { letter: 'U', pattern: /https?:\/\/\S+/g },
31
+ { letter: 'V', pattern: /\$\{[A-Z_][A-Z0-9_]*\}/g },
32
+ { letter: 'H', pattern: /[<>&]/g },
33
+ { letter: 'K', pattern: /\b(?:MCP|LSP|DSH|CLI|API|JSON|HTTP|URL|SDK)\b/g }
34
+ ];
35
+ /** The placeholder shape: a category letter and a 1-based index between U+27E6 and U+27E7. */
36
+ const PLACEHOLDER_PATTERN = '⟦[A-Z]\\d+⟧';
37
+ /** Every placeholder-shaped token in one string, in order of appearance. */
38
+ function placeholderTokens(text) {
39
+ return text.match(new RegExp(PLACEHOLDER_PATTERN, 'g')) ?? [];
40
+ }
41
+ /**
42
+ * Replace every span the engines damage with a numbered placeholder.
43
+ * @param input - the upstream text, exactly as authored.
44
+ * @returns the text to send, and the table that restores it.
45
+ */
46
+ export function maskText(input) {
47
+ const placeholders = new Map();
48
+ let text = input;
49
+ for (const rule of MASK_RULES) {
50
+ let index = 0;
51
+ text = text
52
+ .split(/(⟦[A-Z]\d+⟧)/g)
53
+ .map(part => {
54
+ if (/^⟦[A-Z]\d+⟧$/.test(part))
55
+ return part;
56
+ return part.replace(rule.pattern, match => {
57
+ index += 1;
58
+ const placeholder = `⟦${rule.letter}${index}⟧`;
59
+ placeholders.set(placeholder, match);
60
+ return placeholder;
61
+ });
62
+ })
63
+ .join('');
64
+ }
65
+ return { text, placeholders };
66
+ }
67
+ /**
68
+ * Put every masked span back, or reject the answer.
69
+ *
70
+ * An answer is rejected — `undefined`, so the caller discards the item instead
71
+ * of caching it — when a placeholder is missing, arrives twice, or when the
72
+ * engine invented one of its own. A short answer that dropped a placeholder
73
+ * would otherwise restore a sentence with a hole in it, and an invented one
74
+ * would render as literal brackets.
75
+ * @param masked - the text the engine returned.
76
+ * @param placeholders - the table {@link maskText} produced for that text.
77
+ * @returns the restored text, or `undefined` when the answer cannot be trusted.
78
+ */
79
+ export function unmaskText(masked, placeholders) {
80
+ const seen = new Map();
81
+ for (const token of placeholderTokens(masked))
82
+ seen.set(token, (seen.get(token) ?? 0) + 1);
83
+ // Counting both directions rejects a dropped, duplicated and invented
84
+ // placeholder with one comparison: the answer carries exactly the table's
85
+ // keys, each of them once.
86
+ if (seen.size !== placeholders.size)
87
+ return undefined;
88
+ for (const [token, count] of seen) {
89
+ if (count !== 1 || !placeholders.has(token))
90
+ return undefined;
91
+ }
92
+ let restored = masked;
93
+ for (const [placeholder, original] of placeholders)
94
+ restored = restored.split(placeholder).join(original);
95
+ return restored;
96
+ }