@dsh-workbench/shared 0.3.11 → 1.0.0-beta.0

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 (371) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/api/blocker-table.d.ts +3 -3
  4. package/dist/api/blocker-table.js +47 -23
  5. package/dist/api/dsh.d.ts +1 -1
  6. package/dist/api/workbench-client.js +2 -1
  7. package/dist/components/Activity.css +0 -1
  8. package/dist/components/ApprovalDetail.css +1 -2
  9. package/dist/components/ApprovalDetail.d.ts +1 -1
  10. package/dist/components/ApprovalPlan.css +0 -1
  11. package/dist/components/Card.css +0 -1
  12. package/dist/components/Card.d.ts +1 -1
  13. package/dist/components/CardBoundary.d.ts +1 -1
  14. package/dist/components/CardHead.css +0 -1
  15. package/dist/components/CardHead.d.ts +1 -1
  16. package/dist/components/ChoiceGroup.css +1 -2
  17. package/dist/components/ConfirmBar.d.ts +1 -1
  18. package/dist/components/ConfirmBar.js +1 -1
  19. package/dist/components/Form.css +1 -1
  20. package/dist/components/FormActions.js +1 -1
  21. package/dist/components/LongTaskRow.css +1 -2
  22. package/dist/components/LongTaskRow.d.ts +1 -1
  23. package/dist/components/LongTaskRow.js +1 -1
  24. package/dist/components/Note.css +0 -1
  25. package/dist/components/ResourceStates.css +0 -1
  26. package/dist/components/SettingsSection.css +0 -1
  27. package/dist/components/Spinner.css +0 -1
  28. package/dist/components/Stack.css +0 -1
  29. package/dist/components/StateBlock.css +0 -1
  30. package/dist/components/board-module.d.ts +3 -3
  31. package/dist/components/icons.d.ts +1 -1
  32. package/dist/components/icons.js +11 -4
  33. package/dist/config/constants.d.ts +2 -2
  34. package/dist/config/constants.js +2 -2
  35. package/dist/contract/adapters.d.ts +10 -0
  36. package/dist/contract/cli.d.ts +3 -0
  37. package/dist/contract/data.d.ts +126 -0
  38. package/dist/{api → contract}/facts.d.ts +12 -3
  39. package/dist/{api → contract}/facts.js +19 -1
  40. package/dist/contract/needs.d.ts +132 -0
  41. package/dist/contract/needs.js +232 -0
  42. package/dist/contract/plugin-source.d.ts +1 -0
  43. package/dist/contract/protocol/bundle-install.d.ts +136 -0
  44. package/dist/contract/protocol/bundle-install.js +12 -0
  45. package/dist/contract/protocol/config-sync.d.ts +55 -0
  46. package/dist/contract/protocol/config-sync.js +2 -0
  47. package/dist/contract/protocol/diy.d.ts +4 -0
  48. package/dist/contract/protocol/diy.js +4 -0
  49. package/dist/contract/protocol/dsh-plugins.d.ts +11 -0
  50. package/dist/contract/protocol/dsh-plugins.js +1 -0
  51. package/dist/contract/protocol/long-tasks.d.ts +13 -0
  52. package/dist/contract/protocol/long-tasks.js +1 -0
  53. package/dist/contract/protocol/market-index.d.ts +195 -0
  54. package/dist/contract/protocol/market-index.js +7 -0
  55. package/dist/contract/protocol/platform.d.ts +44 -0
  56. package/dist/contract/protocol/platform.js +1 -0
  57. package/dist/contract/protocol/preflight-wake.d.ts +7 -0
  58. package/dist/contract/protocol/preflight-wake.js +1 -0
  59. package/dist/contract/protocol/profile-create.d.ts +30 -0
  60. package/dist/contract/protocol/profile-create.js +2 -0
  61. package/dist/contract/protocol/sidebar-edition.d.ts +14 -0
  62. package/dist/contract/protocol/sidebar-edition.js +2 -0
  63. package/dist/contract/protocol/unit-manifests.d.ts +6 -0
  64. package/dist/contract/protocol/unit-manifests.js +1 -0
  65. package/dist/contract/unit-board.js +1 -0
  66. package/dist/contract/unit-capability.d.ts +34 -0
  67. package/dist/contract/unit-capability.js +1 -0
  68. package/dist/{host → contract}/unit-declaration.d.ts +7 -5
  69. package/dist/{api → contract}/unit-declaration.js +19 -13
  70. package/dist/contract/unit.d.ts +57 -0
  71. package/dist/contract/unit.js +24 -0
  72. package/dist/contract/workbench-contract.d.ts +15 -0
  73. package/dist/contract/workbench-contract.js +1 -0
  74. package/dist/host/adapter-set.d.ts +26 -0
  75. package/dist/host/adapter-set.js +243 -0
  76. package/dist/host/adapter-types.d.ts +79 -0
  77. package/dist/host/adapter-types.js +23 -0
  78. package/dist/host/adapters.d.ts +22 -0
  79. package/dist/host/adapters.js +9 -0
  80. package/dist/host/browser.d.ts +3 -0
  81. package/dist/host/browser.js +3 -0
  82. package/dist/host/changelog.d.ts +21 -0
  83. package/dist/host/changelog.js +188 -0
  84. package/dist/host/channel-plugin.d.ts +15 -0
  85. package/dist/host/channel-plugin.js +42 -0
  86. package/dist/host/cli.d.ts +4 -0
  87. package/dist/host/cli.js +7 -0
  88. package/dist/host/command-name.d.ts +1 -0
  89. package/dist/host/command-name.js +14 -0
  90. package/dist/host/data-error.d.ts +13 -0
  91. package/dist/host/data-error.js +20 -0
  92. package/dist/host/data-root.js +3 -0
  93. package/dist/host/diy-debug.js +2 -1
  94. package/dist/host/diy-record.js +2 -1
  95. package/dist/host/facts.d.ts +1 -1
  96. package/dist/host/facts.js +3 -2
  97. package/dist/host/git.js +2 -2
  98. package/dist/host/http.js +1 -1
  99. package/dist/host/lib-capabilities.d.ts +22 -0
  100. package/dist/host/lib-capabilities.js +37 -0
  101. package/dist/host/lib-install.d.ts +9 -0
  102. package/dist/host/lib-install.js +10 -0
  103. package/dist/host/long-task.d.ts +1 -1
  104. package/dist/host/long-task.js +4 -3
  105. package/dist/host/market-index.d.ts +22 -0
  106. package/dist/host/market-index.js +420 -0
  107. package/dist/host/needs.d.ts +4 -0
  108. package/dist/host/needs.js +2 -0
  109. package/dist/host/patch.d.ts +9 -0
  110. package/dist/host/patch.js +78 -0
  111. package/dist/host/paths.d.ts +12 -0
  112. package/dist/host/paths.js +28 -0
  113. package/dist/host/platform.d.ts +14 -0
  114. package/dist/host/platform.js +40 -0
  115. package/dist/host/plugin-source.d.ts +8 -6
  116. package/dist/host/plugin-source.js +43 -33
  117. package/dist/host/plugin.d.ts +4 -0
  118. package/dist/host/plugin.js +39 -0
  119. package/dist/host/port-types.d.ts +191 -0
  120. package/dist/host/port-types.js +1 -0
  121. package/dist/host/preflight.d.ts +28 -0
  122. package/dist/host/preflight.js +1 -0
  123. package/dist/host/profile-port.d.ts +4 -0
  124. package/dist/host/profile-port.js +4 -0
  125. package/dist/host/provision.d.ts +2 -2
  126. package/dist/host/provision.js +5 -3
  127. package/dist/host/recipe-rules.d.ts +5 -0
  128. package/dist/host/recipe-rules.js +382 -0
  129. package/dist/host/recipe.d.ts +14 -0
  130. package/dist/host/recipe.js +283 -0
  131. package/dist/host/shell-text.d.ts +9 -2
  132. package/dist/host/shell-text.js +15 -3
  133. package/dist/host/shell.d.ts +2 -0
  134. package/dist/host/shell.js +7 -0
  135. package/dist/host/spec.d.ts +8 -0
  136. package/dist/host/spec.js +24 -0
  137. package/dist/host/supply-index.d.ts +34 -0
  138. package/dist/host/supply-index.js +202 -0
  139. package/dist/host/supply-port.d.ts +5 -0
  140. package/dist/host/supply-port.js +39 -0
  141. package/dist/host/time.d.ts +12 -0
  142. package/dist/host/time.js +19 -0
  143. package/dist/host/tokens.d.ts +26 -0
  144. package/dist/host/tokens.js +154 -0
  145. package/dist/host/tool-kit.js +1 -1
  146. package/dist/host/unit-face.d.ts +5 -4
  147. package/dist/host/version-range.d.ts +2 -0
  148. package/dist/host/version-range.js +73 -0
  149. package/dist/host/version.d.ts +3 -0
  150. package/dist/host/version.js +29 -0
  151. package/dist/host.d.ts +47 -16
  152. package/dist/host.js +47 -16
  153. package/dist/i18n/en.js +224 -71
  154. package/dist/i18n/index.d.ts +298 -73
  155. package/dist/i18n/merge.js +1 -1
  156. package/dist/i18n/need-text.d.ts +26 -0
  157. package/dist/i18n/need-text.js +26 -0
  158. package/dist/i18n/settings.d.ts +70 -0
  159. package/dist/i18n/settings.js +136 -0
  160. package/dist/i18n/zh.d.ts +297 -72
  161. package/dist/i18n/zh.js +226 -73
  162. package/dist/index.d.ts +23 -7
  163. package/dist/index.js +23 -7
  164. package/dist/{api → lib}/dsh-client.d.ts +11 -1
  165. package/dist/lib/dsh-client.js +1 -0
  166. package/dist/lib/market-index.d.ts +7 -0
  167. package/dist/lib/market-index.js +25 -0
  168. package/dist/lib/react.d.ts +0 -40
  169. package/dist/lib/react.js +0 -36
  170. package/dist/lib/ui.js +3 -9
  171. package/dist/testing/data.d.ts +13 -0
  172. package/dist/testing/data.js +46 -0
  173. package/dist/testing/declaration.d.ts +1 -1
  174. package/dist/testing/declaration.js +1 -1
  175. package/dist/testing/host-fakes.d.ts +0 -13
  176. package/dist/testing/host-fakes.js +0 -24
  177. package/dist/testing/needs.d.ts +16 -0
  178. package/dist/testing/needs.js +46 -0
  179. package/dist/testing.d.ts +2 -0
  180. package/dist/testing.js +2 -0
  181. package/package.json +18 -2
  182. package/src/api/__tests__/blocker-table.test.ts +135 -86
  183. package/src/api/blocker-table.ts +52 -26
  184. package/src/api/dsh.ts +1 -1
  185. package/src/api/host-write.ts +0 -1
  186. package/src/api/workbench-client.test.ts +2 -2
  187. package/src/api/workbench-client.ts +2 -1
  188. package/src/components/Activity.css +0 -1
  189. package/src/components/ApprovalDetail.css +1 -2
  190. package/src/components/ApprovalDetail.tsx +1 -1
  191. package/src/components/ApprovalPlan.css +0 -1
  192. package/src/components/Card.css +0 -1
  193. package/src/components/Card.tsx +1 -1
  194. package/src/components/CardAnchor.test.tsx +1 -1
  195. package/src/components/CardBoundary.tsx +1 -1
  196. package/src/components/CardHead.css +0 -1
  197. package/src/components/CardHead.tsx +1 -1
  198. package/src/components/ChoiceGroup.css +1 -2
  199. package/src/components/ConfirmBar.tsx +1 -1
  200. package/src/components/Form.css +1 -1
  201. package/src/components/Form.tsx +1 -1
  202. package/src/components/FormActions.tsx +1 -1
  203. package/src/components/LongTaskRow.css +1 -2
  204. package/src/components/LongTaskRow.tsx +1 -1
  205. package/src/components/Note.css +0 -1
  206. package/src/components/ResourceStates.css +0 -1
  207. package/src/components/SelectFieldNodes.tsx +0 -1
  208. package/src/components/SettingsSection.css +0 -1
  209. package/src/components/Spinner.css +0 -1
  210. package/src/components/Stack.css +0 -1
  211. package/src/components/StateBlock.css +0 -1
  212. package/src/components/__tests__/long-task-row.test.ts +1 -1
  213. package/src/components/board-module.ts +3 -3
  214. package/src/components/icons.tsx +16 -8
  215. package/src/config/constants.ts +2 -2
  216. package/src/{api → contract}/__tests__/facts.test.ts +73 -25
  217. package/src/{api → contract}/__tests__/long-task.test.ts +3 -3
  218. package/src/contract/__tests__/needs.test.ts +74 -0
  219. package/src/{host → contract}/__tests__/unit-declaration.test.ts +1 -1
  220. package/src/contract/__tests__/unit.test.ts +43 -0
  221. package/src/contract/adapters.ts +9 -0
  222. package/src/contract/cli.ts +3 -0
  223. package/src/contract/data.ts +145 -0
  224. package/src/{api → contract}/facts.ts +34 -4
  225. package/src/contract/needs.ts +331 -0
  226. package/src/contract/plugin-source.ts +1 -0
  227. package/src/contract/protocol/bundle-install.ts +198 -0
  228. package/src/contract/protocol/config-sync.ts +65 -0
  229. package/src/contract/protocol/diy.ts +4 -0
  230. package/src/contract/protocol/dsh-plugins.ts +13 -0
  231. package/src/contract/protocol/long-tasks.ts +16 -0
  232. package/src/contract/protocol/market-index.ts +246 -0
  233. package/src/contract/protocol/platform.ts +47 -0
  234. package/src/contract/protocol/preflight-wake.ts +17 -0
  235. package/src/contract/protocol/profile-create.ts +36 -0
  236. package/src/contract/protocol/sidebar-edition.ts +19 -0
  237. package/src/contract/protocol/unit-manifests.ts +8 -0
  238. package/src/{api → contract}/unit-board.ts +0 -1
  239. package/src/contract/unit-capability.ts +37 -0
  240. package/src/{host → contract}/unit-declaration.ts +22 -18
  241. package/src/contract/unit.ts +76 -0
  242. package/src/contract/workbench-contract.ts +30 -0
  243. package/src/host/__tests__/adapter-set.test.ts +228 -0
  244. package/src/host/__tests__/adapters.test.ts +27 -0
  245. package/src/host/__tests__/changelog.test.ts +102 -0
  246. package/src/host/__tests__/command-name.test.ts +16 -0
  247. package/src/host/__tests__/diy-record.test.ts +3 -3
  248. package/src/host/__tests__/facts.test.ts +5 -5
  249. package/src/host/__tests__/long-task.test.ts +1 -1
  250. package/src/host/__tests__/market-index.test.ts +179 -0
  251. package/src/host/__tests__/plugin-ledger.test.ts +10 -10
  252. package/src/host/__tests__/provision.test.ts +7 -6
  253. package/src/host/__tests__/shell-text.test.ts +16 -1
  254. package/src/host/__tests__/supply-index.test.ts +137 -0
  255. package/src/host/__tests__/tokens.test.ts +110 -0
  256. package/src/host/__tests__/version-range.test.ts +21 -0
  257. package/src/host/adapter-set.ts +298 -0
  258. package/src/host/adapter-types.ts +105 -0
  259. package/src/host/adapters.ts +44 -0
  260. package/src/host/browser.ts +3 -0
  261. package/src/host/changelog.ts +212 -0
  262. package/src/host/channel-plugin.ts +55 -0
  263. package/src/host/cli.ts +11 -0
  264. package/src/host/command-name.ts +15 -0
  265. package/src/host/data-error.ts +21 -0
  266. package/src/host/data-root.ts +2 -0
  267. package/src/host/diy-debug.ts +2 -1
  268. package/src/host/diy-record.ts +2 -1
  269. package/src/host/facts.ts +4 -3
  270. package/src/host/git.ts +2 -2
  271. package/src/host/http.ts +1 -1
  272. package/src/host/lib-capabilities.ts +52 -0
  273. package/src/host/lib-install.ts +18 -0
  274. package/src/host/long-task.ts +4 -3
  275. package/src/host/market-index.ts +413 -0
  276. package/src/host/needs.ts +6 -0
  277. package/src/host/patch.ts +93 -0
  278. package/src/host/paths.ts +37 -0
  279. package/src/host/platform.ts +48 -0
  280. package/src/host/plugin-source.ts +48 -56
  281. package/src/host/plugin.ts +39 -0
  282. package/src/host/port-types.ts +222 -0
  283. package/src/host/preflight.ts +31 -0
  284. package/src/host/profile-port.ts +9 -0
  285. package/src/host/provision.ts +7 -4
  286. package/src/host/recipe-rules.ts +330 -0
  287. package/src/host/recipe.test.ts +334 -0
  288. package/src/host/recipe.ts +323 -0
  289. package/src/host/shell-text.ts +15 -3
  290. package/src/host/shell.ts +9 -0
  291. package/src/host/spec.ts +32 -0
  292. package/src/host/supply-index.ts +256 -0
  293. package/src/host/supply-port.ts +45 -0
  294. package/src/host/time.ts +22 -0
  295. package/src/host/tokens.ts +186 -0
  296. package/src/host/tool-kit.ts +1 -1
  297. package/src/host/unit-face.ts +5 -4
  298. package/src/host/version-range.ts +71 -0
  299. package/src/host/version.ts +30 -0
  300. package/src/host.ts +47 -16
  301. package/src/i18n/en.ts +224 -71
  302. package/src/i18n/merge.test.ts +6 -6
  303. package/src/i18n/merge.ts +1 -1
  304. package/src/i18n/need-text.ts +27 -0
  305. package/src/i18n/settings.ts +141 -0
  306. package/src/i18n/zh.ts +227 -73
  307. package/src/index.ts +23 -7
  308. package/src/lib/blocker-action.ts +0 -1
  309. package/src/{api → lib}/dsh-client.ts +12 -1
  310. package/src/lib/market-index.ts +36 -0
  311. package/src/lib/react.ts +0 -40
  312. package/src/lib/text.test.ts +2 -2
  313. package/src/lib/ui.test.ts +6 -5
  314. package/src/lib/ui.ts +3 -9
  315. package/src/testing/__tests__/declaration.test.ts +1 -1
  316. package/src/testing/data.ts +66 -0
  317. package/src/testing/declaration.ts +2 -2
  318. package/src/testing/host-fakes.ts +0 -38
  319. package/src/testing/needs.ts +80 -0
  320. package/src/testing.ts +2 -0
  321. package/dist/api/unit-declaration.d.ts +0 -65
  322. package/dist/api/unit.d.ts +0 -85
  323. package/dist/api/unit.js +0 -8
  324. package/dist/api/workbench-contract.d.ts +0 -44
  325. package/dist/components/MockStrip.css +0 -39
  326. package/dist/components/MockStrip.d.ts +0 -15
  327. package/dist/components/MockStrip.js +0 -8
  328. package/dist/components/SaveBar.css +0 -7
  329. package/dist/host/browser-find.d.ts +0 -38
  330. package/dist/host/browser-find.js +0 -242
  331. package/dist/host/browser-read.d.ts +0 -28
  332. package/dist/host/browser-read.js +0 -243
  333. package/dist/host/opencli-runtime.d.ts +0 -25
  334. package/dist/host/opencli-runtime.js +0 -56
  335. package/dist/host/opencli-window.d.ts +0 -2
  336. package/dist/host/opencli-window.js +0 -8
  337. package/dist/host/opencli.d.ts +0 -37
  338. package/dist/host/opencli.js +0 -155
  339. package/dist/host/unit-declaration.js +0 -213
  340. package/dist/host/unit-libs.d.ts +0 -37
  341. package/dist/lib/diy-debug.d.ts +0 -80
  342. package/dist/lib/diy-debug.js +0 -88
  343. package/dist/lib/diy-record.d.ts +0 -135
  344. package/dist/lib/diy-record.js +0 -162
  345. package/dist/lib/lint-probe.d.ts +0 -1
  346. package/dist/lib/lint-probe.js +0 -6
  347. package/dist/lib/panel-state.d.ts +0 -120
  348. package/dist/lib/panel-state.js +0 -176
  349. package/src/api/__tests__/unit.test.ts +0 -38
  350. package/src/api/unit.ts +0 -93
  351. package/src/api/workbench-contract.ts +0 -59
  352. package/src/host/__tests__/browser-find.test.ts +0 -330
  353. package/src/host/__tests__/browser-read.test.ts +0 -228
  354. package/src/host/__tests__/opencli-runtime.test.ts +0 -46
  355. package/src/host/browser-find.ts +0 -311
  356. package/src/host/browser-read.ts +0 -311
  357. package/src/host/opencli-runtime.ts +0 -79
  358. package/src/host/opencli-window.ts +0 -11
  359. package/src/host/opencli.ts +0 -213
  360. package/src/host/unit-libs.ts +0 -41
  361. /package/dist/{api/blocker.js → contract/adapters.js} +0 -0
  362. /package/dist/{api → contract}/blocker.d.ts +0 -0
  363. /package/dist/{api/dsh-client.js → contract/blocker.js} +0 -0
  364. /package/dist/{api/unit-board.js → contract/cli.js} +0 -0
  365. /package/dist/{api/workbench-contract.js → contract/data.js} +0 -0
  366. /package/dist/{api → contract}/long-task.d.ts +0 -0
  367. /package/dist/{api → contract}/long-task.js +0 -0
  368. /package/dist/{host/unit-libs.js → contract/plugin-source.js} +0 -0
  369. /package/dist/{api → contract}/unit-board.d.ts +0 -0
  370. /package/src/{api → contract}/blocker.ts +0 -0
  371. /package/src/{api → contract}/long-task.ts +0 -0
@@ -1,7 +1,14 @@
1
1
  /**
2
- * 把一个值裹成 shell 里的单引号字面量(值里的单引号一并转义),保证元字符按字面量传递。
2
+ * 按目标平台把一个值裹成 shell 字面量:POSIX 用单引号,win32 用双引号(cmd 与 PowerShell 都认)。
3
3
  * @param value - 任意值;不是字符串的先 `String()`。
4
- * @returns 可安全拼进 `/bin/sh -c` 的一段文本 —— 含空格 / `$()` / `;` / 通配符的值都不会被当成语法。
4
+ * @param platform - 目标平台,默认当前 `process.platform`。
5
+ * @returns 可安全拼进该平台 shell 命令的一段文本;含空格 / 元字符的值不会被当成语法。
6
+ */
7
+ export declare function quoteShellArgFor(value: unknown, platform?: NodeJS.Platform): string;
8
+ /**
9
+ * 按当前平台把值裹成 shell 字面量;跨平台代码要固定平台时用 `quoteShellArgFor`。
10
+ * @param value - 任意值;不是字符串的先 `String()`。
11
+ * @returns 可安全拼进当前平台 shell 命令的一段文本。
5
12
  */
6
13
  export declare function quoteShellArg(value: unknown): string;
7
14
  /**
@@ -1,10 +1,22 @@
1
1
  /**
2
- * 把一个值裹成 shell 里的单引号字面量(值里的单引号一并转义),保证元字符按字面量传递。
2
+ * 按目标平台把一个值裹成 shell 字面量:POSIX 用单引号,win32 用双引号(cmd 与 PowerShell 都认)。
3
3
  * @param value - 任意值;不是字符串的先 `String()`。
4
- * @returns 可安全拼进 `/bin/sh -c` 的一段文本 —— 含空格 / `$()` / `;` / 通配符的值都不会被当成语法。
4
+ * @param platform - 目标平台,默认当前 `process.platform`。
5
+ * @returns 可安全拼进该平台 shell 命令的一段文本;含空格 / 元字符的值不会被当成语法。
6
+ */
7
+ export function quoteShellArgFor(value, platform = process.platform) {
8
+ const text = String(value);
9
+ if (platform === 'win32')
10
+ return `"${text.replace(/"/g, '\\"')}"`;
11
+ return `'${text.replace(/'/g, `'\\''`)}'`;
12
+ }
13
+ /**
14
+ * 按当前平台把值裹成 shell 字面量;跨平台代码要固定平台时用 `quoteShellArgFor`。
15
+ * @param value - 任意值;不是字符串的先 `String()`。
16
+ * @returns 可安全拼进当前平台 shell 命令的一段文本。
5
17
  */
6
18
  export function quoteShellArg(value) {
7
- return `'${String(value).replace(/'/g, `'\\''`)}'`;
19
+ return quoteShellArgFor(value, process.platform);
8
20
  }
9
21
  /**
10
22
  * 取一段文本的末尾若干行(如命令输出),顺带去掉首尾空白。
@@ -12,3 +12,5 @@ export declare function runShell(shell: DshShell, command: string, options?: {
12
12
  timeoutMs?: number;
13
13
  signal?: AbortSignal;
14
14
  }): Promise<ShellResult>;
15
+ export declare function backgroundPrefix(): readonly string[];
16
+ export declare function backgroundLine(command: string, argv: readonly string[]): string;
@@ -1,4 +1,5 @@
1
1
  import { GIT_TIMEOUT_MS } from '../config/constants.js';
2
+ import { quoteShellArg } from './shell-text.js';
2
3
  const DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
3
4
  export async function runShell(shell, command, options = {}) {
4
5
  const { workdir, timeoutMs = GIT_TIMEOUT_MS, signal } = options;
@@ -21,3 +22,9 @@ export async function runShell(shell, command, options = {}) {
21
22
  truncated: result.stdout.truncated || result.stderr.truncated,
22
23
  };
23
24
  }
25
+ export function backgroundPrefix() {
26
+ return [quoteShellArg('env'), quoteShellArg('OPENCLI_WINDOW=background')];
27
+ }
28
+ export function backgroundLine(command, argv) {
29
+ return [...backgroundPrefix(), quoteShellArg(command), ...argv.map(quoteShellArg)].join(' ');
30
+ }
@@ -0,0 +1,8 @@
1
+ export interface NpmRef {
2
+ readonly name: string;
3
+ readonly version?: string;
4
+ }
5
+ export declare function isPackageName(value: string): boolean;
6
+ export declare function splitNpmSpec(spec: string): NpmRef | undefined;
7
+ export declare function localDirOf(spec: string): string | undefined;
8
+ export declare function refusalReason(): string;
@@ -0,0 +1,24 @@
1
+ import path from 'node:path';
2
+ const PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
3
+ const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]*$/;
4
+ export function isPackageName(value) {
5
+ return value.length <= 214 && PACKAGE_NAME.test(value);
6
+ }
7
+ export function splitNpmSpec(spec) {
8
+ const value = spec.trim();
9
+ const at = value.lastIndexOf('@');
10
+ const name = at > 0 ? value.slice(0, at) : value;
11
+ const version = at > 0 ? value.slice(at + 1) : '';
12
+ if (!isPackageName(name))
13
+ return undefined;
14
+ if (version !== '' && !VERSION.test(version))
15
+ return undefined;
16
+ return { name, ...(version === '' ? {} : { version }) };
17
+ }
18
+ export function localDirOf(spec) {
19
+ const dir = spec.trim().replace(/^(?:file|link):/, '');
20
+ return path.isAbsolute(dir) ? dir : undefined;
21
+ }
22
+ export function refusalReason() {
23
+ return '这个包既不是工作台的模块,也不是 opencli 的插件,装了也用不上';
24
+ }
@@ -0,0 +1,34 @@
1
+ import type { Need, SupplySource } from '../contract/needs.js';
2
+ export interface SupplyDeclaration {
3
+ readonly id: string;
4
+ readonly needs?: readonly Need[];
5
+ }
6
+ export interface SupplyEntry {
7
+ readonly key: string;
8
+ readonly kind: 'extension' | 'lib';
9
+ readonly names: readonly string[];
10
+ readonly package: string;
11
+ readonly runtime?: string;
12
+ readonly sources: readonly SupplySource[];
13
+ readonly declarers: readonly string[];
14
+ readonly commands: readonly string[];
15
+ readonly conflicted: boolean;
16
+ }
17
+ export interface SupplyConflict {
18
+ readonly kind: 'source-mismatch' | 'name-mismatch';
19
+ readonly key: string;
20
+ readonly names: readonly string[];
21
+ readonly declarers: readonly string[];
22
+ readonly detail: string;
23
+ }
24
+ export interface SupplyIndex {
25
+ readonly entries: ReadonlyMap<string, SupplyEntry>;
26
+ readonly conflicts: readonly SupplyConflict[];
27
+ readonly problems: readonly string[];
28
+ readonly entryOf: (kind: 'extension' | 'lib', name: string) => SupplyEntry | undefined;
29
+ readonly sourcesOf: (kind: 'extension' | 'lib', name: string) => readonly SupplySource[];
30
+ }
31
+ export declare function npmSourceOf(sources: readonly SupplySource[] | undefined): Extract<SupplySource, {
32
+ kind: 'npm';
33
+ }> | undefined;
34
+ export declare function buildSupplyIndex(declarations: readonly SupplyDeclaration[]): SupplyIndex;
@@ -0,0 +1,202 @@
1
+ export function npmSourceOf(sources) {
2
+ return sources?.find((source) => source.kind === 'npm');
3
+ }
4
+ function text(value) {
5
+ return value === undefined ? '' : value.trim();
6
+ }
7
+ function conventionPackage(name) {
8
+ return `opencli-plugin-${name}`;
9
+ }
10
+ function nativeSourcePackage(source) {
11
+ if (source.kind === 'npm')
12
+ return text(source.package);
13
+ if (source.kind === 'git')
14
+ return `git:${text(source.url)}`;
15
+ return `local:${text(source.env) || text(source.path)}`;
16
+ }
17
+ function packageOf(need) {
18
+ if (need.kind === 'lib')
19
+ return text(need.name);
20
+ const first = need.sources?.[0];
21
+ if (first === undefined)
22
+ return conventionPackage(need.name);
23
+ if (first.kind === 'npm') {
24
+ const pkg = text(first.package);
25
+ return pkg === '' ? conventionPackage(need.name) : pkg;
26
+ }
27
+ return nativeSourcePackage(first);
28
+ }
29
+ function keyOf(kind, pkg) {
30
+ return `${kind}:${pkg}`;
31
+ }
32
+ function sourceCompatible(left, right) {
33
+ if (left.kind !== right.kind)
34
+ return false;
35
+ if (left.kind === 'npm' && right.kind === 'npm') {
36
+ if (text(left.package) !== '' && text(right.package) !== '' && text(left.package) !== text(right.package)) {
37
+ return false;
38
+ }
39
+ if (text(left.registryEnv) !== text(right.registryEnv))
40
+ return false;
41
+ const l = text(left.registryDefault);
42
+ const r = text(right.registryDefault);
43
+ return l === '' || r === '' || l === r;
44
+ }
45
+ if (left.kind === 'git' && right.kind === 'git')
46
+ return text(left.url) === text(right.url);
47
+ if (left.kind === 'local' && right.kind === 'local') {
48
+ return text(left.env) === text(right.env) && text(left.path) === text(right.path);
49
+ }
50
+ return false;
51
+ }
52
+ function sourcesCompatible(left, right) {
53
+ if (left.length !== right.length)
54
+ return false;
55
+ return left.every((source, index) => {
56
+ const other = right[index];
57
+ return other !== undefined && sourceCompatible(source, other);
58
+ });
59
+ }
60
+ function mergedSource(left, right) {
61
+ if (left.kind === 'npm' && right.kind === 'npm') {
62
+ const pkg = text(left.package) === '' ? right.package : left.package;
63
+ const registryDefault = text(left.registryDefault) === '' ? right.registryDefault : left.registryDefault;
64
+ return {
65
+ ...left,
66
+ ...(pkg === undefined ? {} : { package: pkg }),
67
+ ...(registryDefault === undefined ? {} : { registryDefault }),
68
+ };
69
+ }
70
+ return left;
71
+ }
72
+ function mergeSources(entry, sources) {
73
+ if (!entry.declared) {
74
+ entry.declared = true;
75
+ entry.sources = [...sources];
76
+ return true;
77
+ }
78
+ if (!sourcesCompatible(entry.sources, sources)) {
79
+ entry.conflicted = true;
80
+ return false;
81
+ }
82
+ entry.sources = entry.sources.map((source, index) => {
83
+ const other = sources[index];
84
+ return other === undefined ? source : mergedSource(source, other);
85
+ });
86
+ return true;
87
+ }
88
+ function sourceText(source) {
89
+ if (source.kind === 'npm') {
90
+ return `${source.package === undefined ? '按包名约定' : source.package}(${source.registryEnv ?? '默认源'})`;
91
+ }
92
+ if (source.kind === 'git')
93
+ return `git:${source.url}`;
94
+ return `local:${source.env ?? source.path ?? ''}`;
95
+ }
96
+ function addDeclarer(entry, unit, commands) {
97
+ if (!entry.declarers.includes(unit))
98
+ entry.declarers.push(unit);
99
+ for (const command of commands)
100
+ if (!entry.commands.includes(command))
101
+ entry.commands.push(command);
102
+ }
103
+ export function buildSupplyIndex(declarations) {
104
+ const entries = new Map();
105
+ const byName = new Map();
106
+ const conflicts = [];
107
+ const ensure = (kind, pkg) => {
108
+ const key = keyOf(kind, pkg);
109
+ const found = entries.get(key);
110
+ if (found !== undefined)
111
+ return found;
112
+ const created = {
113
+ key,
114
+ kind,
115
+ package: pkg,
116
+ declared: false,
117
+ names: [],
118
+ sources: [],
119
+ declarers: [],
120
+ commands: [],
121
+ conflicted: false,
122
+ };
123
+ entries.set(key, created);
124
+ return created;
125
+ };
126
+ for (const declaration of declarations) {
127
+ for (const need of declaration.needs ?? []) {
128
+ if (need.kind !== 'extension' && need.kind !== 'lib')
129
+ continue;
130
+ const pkg = packageOf(need);
131
+ const entry = ensure(need.kind, pkg);
132
+ if (!entry.names.includes(need.name))
133
+ entry.names.push(need.name);
134
+ if (need.kind === 'extension') {
135
+ entry.runtime = need.runtime;
136
+ addDeclarer(entry, declaration.id, need.commands ?? []);
137
+ }
138
+ else {
139
+ addDeclarer(entry, declaration.id, []);
140
+ }
141
+ const same = mergeSources(entry, need.sources ?? []);
142
+ if (!same) {
143
+ conflicts.push({
144
+ kind: 'source-mismatch',
145
+ key: entry.key,
146
+ names: [...entry.names],
147
+ declarers: [...entry.declarers],
148
+ detail: `${entry.kind === 'extension' ? '插件' : '共用库'} ${entry.names.join('、')} 被 ` +
149
+ `${entry.declarers.join('、')} 声明成了不同的来源(` +
150
+ `${entry.sources.map(sourceText).join(' / ') || '无来源'})`,
151
+ });
152
+ }
153
+ const nameKey = `${need.kind}:${need.name}`;
154
+ const seen = byName.get(nameKey);
155
+ if (seen !== undefined && seen.key !== entry.key) {
156
+ const detail = `${need.kind === 'extension' ? '插件' : '共用库'} ${need.name} 来自不同的包:` +
157
+ `${seen.package} / ${entry.package}`;
158
+ entry.conflicted = true;
159
+ seen.conflicted = true;
160
+ conflicts.push({
161
+ kind: 'name-mismatch',
162
+ key: entry.key,
163
+ names: [need.name],
164
+ declarers: [...new Set([...seen.declarers, ...entry.declarers])],
165
+ detail,
166
+ });
167
+ }
168
+ else if (seen === undefined) {
169
+ byName.set(nameKey, entry);
170
+ }
171
+ }
172
+ }
173
+ const deduped = new Map();
174
+ for (const conflict of conflicts) {
175
+ deduped.set(`${conflict.kind}:${conflict.key}`, conflict);
176
+ }
177
+ const frozenEntries = new Map();
178
+ for (const [key, entry] of entries) {
179
+ frozenEntries.set(key, {
180
+ key: entry.key,
181
+ kind: entry.kind,
182
+ names: [...entry.names],
183
+ package: entry.package,
184
+ ...(entry.runtime === undefined ? {} : { runtime: entry.runtime }),
185
+ sources: entry.sources.map((source) => ({ ...source })),
186
+ declarers: [...entry.declarers],
187
+ commands: [...entry.commands],
188
+ conflicted: entry.conflicted,
189
+ });
190
+ }
191
+ const entryOf = (kind, name) => byName.get(`${kind}:${name}`);
192
+ return {
193
+ entries: frozenEntries,
194
+ conflicts: [...deduped.values()],
195
+ problems: [...deduped.values()].map((conflict) => conflict.detail),
196
+ entryOf,
197
+ sourcesOf: (kind, name) => {
198
+ const entry = entryOf(kind, name);
199
+ return entry === undefined || entry.conflicted ? [] : entry.sources;
200
+ },
201
+ };
202
+ }
@@ -0,0 +1,5 @@
1
+ import type { DshHostContext } from '../api/dsh.js';
2
+ import type { SupplyPort } from './port-types.js';
3
+ export type { SupplyPort } from './port-types.js';
4
+ export declare function supplyPortOf(ctx: DshHostContext): SupplyPort;
5
+ export declare function requireSupply(): SupplyPort;
@@ -0,0 +1,39 @@
1
+ import { adaptersOf } from './adapters.js';
2
+ export function supplyPortOf(ctx) {
3
+ const set = adaptersOf(ctx);
4
+ const env = set.supply;
5
+ const modules = set.modules;
6
+ return {
7
+ env,
8
+ modules,
9
+ resolvePluginSource: (source, environment, options) => env.resolvePluginSource(source, environment, options),
10
+ libInstallCommand: (options) => env.libInstallCommand(options),
11
+ pluginInstallPlan: (options) => env.pluginInstallPlan(options),
12
+ latestVersion: (options) => env.latestVersion(options),
13
+ missingReleaseParts: (options) => env.missingReleaseParts(options),
14
+ probeRelease: (options) => env.probeRelease(options),
15
+ splitNpmSpec: (spec) => env.splitNpmSpec(spec),
16
+ isolatedHome: () => modules.isolatedHome(),
17
+ cliCatalogPath: () => modules.cliCatalogPath(),
18
+ vendorPluginsDir: () => modules.vendorPluginsDir(),
19
+ opencliInstallCommand: () => modules.opencliInstallCommand(),
20
+ profileDirOf: (context) => modules.profileDirOf(context),
21
+ profileModules: (dir) => modules.profileModules(dir),
22
+ readInstalledModule: (dir, pkg) => modules.readInstalledModule(dir, pkg),
23
+ readProfilePackage: (dir, pkg) => modules.readProfilePackage(dir, pkg),
24
+ readBundleManager: (context) => modules.readBundleManager(context),
25
+ createRegistryNotebook: (dir) => modules.createRegistryNotebook(dir),
26
+ declarationGaps: (dir) => modules.declarationGaps(dir),
27
+ moduleDeclarationOf: (dir, pkg) => modules.moduleDeclarationOf(dir, pkg),
28
+ registryDeclarationOf: (options) => modules.registryDeclarationOf(options),
29
+ pathDeclarationOf: (spec) => modules.pathDeclarationOf(spec),
30
+ declarationRefusalOf: (name, raw) => modules.declarationRefusalOf(name, raw),
31
+ refusalReason: () => modules.refusalReason(),
32
+ packageRouteOf: (options) => modules.packageRouteOf(options),
33
+ isNewerVersion: (left, right) => modules.isNewerVersion(left, right),
34
+ startSelfUpdate: (request, onError) => modules.startSelfUpdate(request, onError),
35
+ };
36
+ }
37
+ export function requireSupply() {
38
+ throw new Error('workbenchSupply 未提供');
39
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * UTC 时钟(`HH:mm:ss`):日志与状态行只给人看时分秒,不带日期。
3
+ * @param value ISO 字符串、时间戳或 Date。
4
+ * @returns `HH:mm:ss`;非法时间返回 `Invalid Date`。
5
+ */
6
+ export declare function clockOf(value: string | number | Date): string;
7
+ /**
8
+ * 把时间戳/ISO 字符串转成毫秒;非法输入给 `NaN`(调用方据此回退)。
9
+ * @param value ISO 字符串、时间戳或 Date。
10
+ * @returns 毫秒时间戳或 `NaN`。
11
+ */
12
+ export declare function epochOf(value: string | number | Date): number;
@@ -0,0 +1,19 @@
1
+ import dayjs from 'dayjs';
2
+ import utc from 'dayjs/plugin/utc.js';
3
+ dayjs.extend(utc);
4
+ /**
5
+ * UTC 时钟(`HH:mm:ss`):日志与状态行只给人看时分秒,不带日期。
6
+ * @param value ISO 字符串、时间戳或 Date。
7
+ * @returns `HH:mm:ss`;非法时间返回 `Invalid Date`。
8
+ */
9
+ export function clockOf(value) {
10
+ return dayjs(value).utc().format('HH:mm:ss');
11
+ }
12
+ /**
13
+ * 把时间戳/ISO 字符串转成毫秒;非法输入给 `NaN`(调用方据此回退)。
14
+ * @param value ISO 字符串、时间戳或 Date。
15
+ * @returns 毫秒时间戳或 `NaN`。
16
+ */
17
+ export function epochOf(value) {
18
+ return dayjs(value).valueOf();
19
+ }
@@ -0,0 +1,26 @@
1
+ export declare const DSH_THEME_PACKAGE = "@deepseek-ai/dsh-client-ui-theme";
2
+ export declare const SHELL_PACKAGE = "@dsh-workbench/core";
3
+ export declare const DSW_PREFIX = "--dsw-";
4
+ export declare const WB_PREFIX = "--wb-";
5
+ export interface TokenValues {
6
+ readonly light: string | null;
7
+ readonly dark: string | null;
8
+ }
9
+ export interface TokenEntry {
10
+ readonly name: string;
11
+ readonly values: TokenValues;
12
+ }
13
+ export interface TokenSource {
14
+ readonly package: string;
15
+ readonly version: string | null;
16
+ readonly file: string;
17
+ readonly entries: readonly TokenEntry[];
18
+ }
19
+ export interface TokenSet {
20
+ readonly dsw: TokenSource | null;
21
+ readonly wb: TokenSource | null;
22
+ }
23
+ export declare function tokenEntriesIn(text: string, prefix: string): readonly TokenEntry[];
24
+ export declare function readTokens(startDirs: readonly string[]): TokenSet;
25
+ export declare function nearestTokens(name: string, names: readonly string[], limit?: number): readonly string[];
26
+ export declare function tokenFamilyOf(name: string): string;
@@ -0,0 +1,154 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ export const DSH_THEME_PACKAGE = '@deepseek-ai/dsh-client-ui-theme';
4
+ export const SHELL_PACKAGE = '@dsh-workbench/core';
5
+ export const DSW_PREFIX = '--dsw-';
6
+ export const WB_PREFIX = '--wb-';
7
+ const BLOCK = /([^{}]*)\{([^{}]*)\}/g;
8
+ const DECLARATION = /(--[a-z0-9-]+)\s*:\s*([^;{}]+)/g;
9
+ const DARK_BLOCK = /data-ds-dark-theme/;
10
+ const VAR_USE = /var\(\s*(--[a-z0-9-]+)\s*(?:,[^()]*)?\)/g;
11
+ function rawDefinitionsIn(text, prefix) {
12
+ const defs = new Map();
13
+ for (const block of text.matchAll(BLOCK)) {
14
+ const selector = block[1] ?? '';
15
+ const dark = DARK_BLOCK.test(selector);
16
+ for (const declaration of (block[2] ?? '').matchAll(DECLARATION)) {
17
+ const name = declaration[1] ?? '';
18
+ const value = (declaration[2] ?? '').trim();
19
+ if (!name.startsWith(prefix) || value === '')
20
+ continue;
21
+ const found = defs.get(name) ?? {};
22
+ const key = dark ? 'dark' : 'light';
23
+ if (found[key] === undefined)
24
+ found[key] = value;
25
+ defs.set(name, found);
26
+ }
27
+ }
28
+ return defs;
29
+ }
30
+ function resolved(value, scheme, defs, depth = 0) {
31
+ if (depth >= 4 || !value.includes('var('))
32
+ return value;
33
+ return value.replace(VAR_USE, (whole, name) => {
34
+ const found = defs.get(name);
35
+ if (found === undefined)
36
+ return whole;
37
+ const next = scheme === 'dark' ? found.dark ?? found.light : found.light ?? found.dark;
38
+ return next === undefined ? whole : resolved(next, scheme, defs, depth + 1);
39
+ });
40
+ }
41
+ export function tokenEntriesIn(text, prefix) {
42
+ const defs = rawDefinitionsIn(text, prefix);
43
+ return [...defs.entries()]
44
+ .map(([name, found]) => ({
45
+ name,
46
+ values: {
47
+ light: found.light === undefined ? null : resolved(found.light, 'light', defs),
48
+ dark: found.dark === undefined ? null : resolved(found.dark, 'dark', defs),
49
+ },
50
+ }))
51
+ .sort((left, right) => left.name.localeCompare(right.name));
52
+ }
53
+ function manifestAt(root) {
54
+ try {
55
+ const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
56
+ if (typeof manifest !== 'object' || manifest === null)
57
+ return null;
58
+ const record = manifest;
59
+ return {
60
+ name: typeof record.name === 'string' ? record.name : null,
61
+ version: typeof record.version === 'string' ? record.version : null,
62
+ root,
63
+ };
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ function findPackage(startDirs, packageName) {
70
+ for (const start of startDirs) {
71
+ if (start.trim() === '')
72
+ continue;
73
+ const own = manifestAt(start);
74
+ if (own !== null && own.name === packageName)
75
+ return own;
76
+ let at = resolve(start);
77
+ for (;;) {
78
+ const candidate = join(at, 'node_modules', ...packageName.split('/'));
79
+ const manifest = manifestAt(candidate);
80
+ if (manifest !== null && (manifest.name === null || manifest.name === packageName))
81
+ return manifest;
82
+ const parent = dirname(at);
83
+ if (parent === at)
84
+ break;
85
+ at = parent;
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+ function sourceAt(startDirs, packageName, tail, prefix) {
91
+ const manifest = findPackage(startDirs, packageName);
92
+ if (manifest === null)
93
+ return null;
94
+ const file = join(manifest.root, tail);
95
+ if (!existsSync(file))
96
+ return null;
97
+ return {
98
+ package: packageName,
99
+ version: manifest.version,
100
+ file,
101
+ entries: tokenEntriesIn(readFileSync(file, 'utf8'), prefix),
102
+ };
103
+ }
104
+ export function readTokens(startDirs) {
105
+ const dsw = sourceAt(startDirs, DSH_THEME_PACKAGE, join('lib', 'client.js'), DSW_PREFIX);
106
+ const wb = sourceAt(startDirs, SHELL_PACKAGE, 'client.js', WB_PREFIX);
107
+ return { dsw, wb };
108
+ }
109
+ function distance(left, right) {
110
+ let previous = Array.from({ length: right.length + 1 }, (_unused, index) => index);
111
+ for (let row = 1; row <= left.length; row += 1) {
112
+ const current = [row];
113
+ for (let column = 1; column <= right.length; column += 1) {
114
+ const same = left[row - 1] === right[column - 1] ? 0 : 1;
115
+ current.push(Math.min((previous[column] ?? 0) + 1, (current[column - 1] ?? 0) + 1, (previous[column - 1] ?? 0) + same));
116
+ }
117
+ previous = current;
118
+ }
119
+ return previous[right.length] ?? 0;
120
+ }
121
+ function commonPrefixLength(left, right) {
122
+ const cap = Math.min(left.length, right.length);
123
+ let at = 0;
124
+ while (at < cap && left[at] === right[at])
125
+ at += 1;
126
+ return at;
127
+ }
128
+ export function nearestTokens(name, names, limit = 6) {
129
+ const wanted = name.trim().toLowerCase();
130
+ if (wanted === '')
131
+ return [];
132
+ const shared = wanted.slice(0, wanted.lastIndexOf('-') + 1);
133
+ return names
134
+ .flatMap((one) => {
135
+ const lower = one.toLowerCase();
136
+ const typos = lower.length < 3 ? Number.POSITIVE_INFINITY : distance(lower, wanted);
137
+ if (typos <= 2)
138
+ return [{ one, typos }];
139
+ const prefix = commonPrefixLength(lower, wanted);
140
+ if (prefix < 8)
141
+ return [];
142
+ const sameStem = shared.length >= 8 && lower.startsWith(shared);
143
+ const score = 10 + typos - prefix + (sameStem ? 0 : 20);
144
+ return score < 20 ? [{ one, typos: score }] : [];
145
+ })
146
+ .sort((left, right) => left.typos - right.typos || left.one.length - right.one.length || left.one.localeCompare(right.one))
147
+ .slice(0, limit)
148
+ .map((one) => one.one);
149
+ }
150
+ export function tokenFamilyOf(name) {
151
+ const rest = name.startsWith(DSW_PREFIX) ? name.slice(DSW_PREFIX.length) : name.startsWith(WB_PREFIX) ? name.slice(WB_PREFIX.length) : name;
152
+ const cut = rest.indexOf('-');
153
+ return cut === -1 ? rest : rest.slice(0, cut);
154
+ }
@@ -1,4 +1,4 @@
1
- import { WorkbenchDataError } from './opencli.js';
1
+ import { WorkbenchDataError } from './data-error.js';
2
2
  export function sessionWorkspace(exec) {
3
3
  const cwd = exec?.agent?.session?.header?.cwd;
4
4
  return typeof cwd === 'string' && cwd.trim() !== '' ? cwd.trim() : null;
@@ -1,12 +1,13 @@
1
1
  import type { DshHostContext } from '../api/dsh.js';
2
- import type { UnitManifest } from '../api/unit.js';
2
+ import type { UnitManifest } from '../contract/unit.js';
3
3
  import type { RouteTable } from '../host/http.js';
4
4
  import type { LongTaskBase, LongTaskHost, LongTaskRegistry } from '../host/long-task.js';
5
- import type { ProvisionHandler } from '../host/provision.js';
6
- import type { UnitCapability } from './unit-libs.js';
5
+ import type { ProvisionHandler } from './provision.js';
6
+ import type { UnitCapability } from '../contract/unit-capability.js';
7
7
  import type { ApprovalCall, ApprovalFacts, ApprovalPolicy } from '../host/tool-approval.js';
8
8
  import type { ValueHandoff } from '../host/value-handoff.js';
9
9
  import type { WorkspaceStore } from '../host/workspace-store.js';
10
+ import type { DataReader } from '../contract/data.js';
10
11
  export interface ToolScopeContext {
11
12
  readonly workspace: string | null;
12
13
  readonly preset: string | null;
@@ -21,7 +22,7 @@ export interface UnitMountDeps {
21
22
  readonly manifests: () => readonly UnitManifest[];
22
23
  readonly ownedUnits: () => readonly string[];
23
24
  readonly installable?: (() => readonly string[]) | undefined;
24
- readonly opencliCommand?: string;
25
+ readonly data: DataReader;
25
26
  readonly store: WorkspaceStore;
26
27
  readonly values?: ValueHandoff | undefined;
27
28
  readonly probe?: (unit: string, options?: {
@@ -0,0 +1,2 @@
1
+ export type VersionVerdict = 'satisfied' | 'unsatisfied' | 'malformed';
2
+ export declare function checkVersionRange(contract: string | undefined, version: string): VersionVerdict;