@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
@@ -0,0 +1,420 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { MARKET_INDEX_FORMAT } from '../contract/protocol/market-index.js';
3
+ import { marketText } from '../lib/market-index.js';
4
+ export { marketBranchOk, marketInstallTarget, marketText } from '../lib/market-index.js';
5
+ export const MARKET_INDEX_SEED = '{\n "format": 1,\n "plugins": []\n}\n';
6
+ export const MARKET_INDEX_README_LINES = [
7
+ '# 模块市场索引',
8
+ '',
9
+ '这个仓库给 DeepSeek Harness 工作台当模块市场索引:`market.json`(format 1)列出可安装的模块与版本。',
10
+ '',
11
+ '## 发布模块',
12
+ '',
13
+ '在模块包里运行:',
14
+ '',
15
+ '```bash',
16
+ 'dsh-wb-module release --index <本仓库地址> --index-policy artifacts-in-repo',
17
+ '```',
18
+ '',
19
+ '产物会提交到 `packages/<unit>/`,并更新 `market.json`。',
20
+ '',
21
+ '## 使用这个索引',
22
+ '',
23
+ '在工作台的「模块市场 → 发现」里添加本仓库地址,即可浏览与安装。',
24
+ '',
25
+ ];
26
+ const SEMVER = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/;
27
+ const NPM_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
28
+ const GIT_COMMIT = /^[0-9a-f]{40}$/;
29
+ const MAX_ICON_CHARS = 32 * 1024;
30
+ function asRecord(value) {
31
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
32
+ ? value
33
+ : undefined;
34
+ }
35
+ function asText(value) {
36
+ return typeof value === 'string' ? value.trim() : '';
37
+ }
38
+ function asTextArray(value) {
39
+ return Array.isArray(value)
40
+ ? value.flatMap((item) => (typeof item === 'string' && item.trim() !== '' ? [item.trim()] : []))
41
+ : [];
42
+ }
43
+ function asLocalized(value) {
44
+ const record = asRecord(value);
45
+ if (record === undefined)
46
+ return undefined;
47
+ const zh = asText(record['zh']);
48
+ const en = asText(record['en']);
49
+ return zh === '' && en === '' ? undefined : { ...(zh === '' ? {} : { zh }), ...(en === '' ? {} : { en }) };
50
+ }
51
+ function problem(kind, detail, at) {
52
+ return { kind, detail, ...(at === undefined ? {} : { at }) };
53
+ }
54
+ export function compareSemver(left, right) {
55
+ const a = SEMVER.exec(left);
56
+ const b = SEMVER.exec(right);
57
+ if (a === null || b === null)
58
+ return undefined;
59
+ for (let index = 1; index <= 3; index += 1) {
60
+ const diff = Number(a[index]) - Number(b[index]);
61
+ if (diff !== 0)
62
+ return diff > 0 ? 1 : -1;
63
+ }
64
+ const preA = a[4];
65
+ const preB = b[4];
66
+ if (preA === undefined && preB === undefined)
67
+ return 0;
68
+ if (preA === undefined)
69
+ return 1;
70
+ if (preB === undefined)
71
+ return -1;
72
+ const leftParts = preA.split('.');
73
+ const rightParts = preB.split('.');
74
+ for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {
75
+ const one = leftParts[index];
76
+ const other = rightParts[index];
77
+ if (one === undefined)
78
+ return -1;
79
+ if (other === undefined)
80
+ return 1;
81
+ const oneNumber = /^\d+$/.test(one);
82
+ const otherNumber = /^\d+$/.test(other);
83
+ if (oneNumber && otherNumber) {
84
+ const diff = Number(one) - Number(other);
85
+ if (diff !== 0)
86
+ return diff > 0 ? 1 : -1;
87
+ continue;
88
+ }
89
+ if (oneNumber)
90
+ return -1;
91
+ if (otherNumber)
92
+ return 1;
93
+ if (one !== other)
94
+ return one > other ? 1 : -1;
95
+ }
96
+ return 0;
97
+ }
98
+ function sourceOf(raw, at) {
99
+ const record = asRecord(raw);
100
+ if (record === undefined)
101
+ return problem('source', 'source 必须是一个对象', at);
102
+ if (record['type'] === 'npm') {
103
+ const registry = record['registry'];
104
+ if (registry !== undefined && asText(registry) === '') {
105
+ return problem('source', 'npm source 的 registry 必须是非空字符串', at);
106
+ }
107
+ return { type: 'npm', ...(registry === undefined ? {} : { registry: asText(registry) }) };
108
+ }
109
+ if (record['type'] === 'git') {
110
+ const url = asText(record['url']);
111
+ const commit = asText(record['commit']);
112
+ if (url === '')
113
+ return problem('source', 'git source 缺 url', at);
114
+ if (!GIT_COMMIT.test(commit)) {
115
+ return problem('git-commit', `git source 的 commit 必须是 40 位小写 SHA(现在是 ${JSON.stringify(commit)})`, at);
116
+ }
117
+ const path = record['path'];
118
+ return {
119
+ type: 'git',
120
+ url,
121
+ commit,
122
+ ...(path === undefined || asText(path) === '' ? {} : { path: asText(path) }),
123
+ };
124
+ }
125
+ return problem('source', 'source.type 只能是 npm 或 git', at);
126
+ }
127
+ function versionOf(raw, at) {
128
+ const record = asRecord(raw);
129
+ if (record === undefined)
130
+ return problem('version', '版本必须是一个对象', at);
131
+ const version = asText(record['version']);
132
+ if (!SEMVER.test(version))
133
+ return problem('version', `版本号不是合法 SemVer:${JSON.stringify(version)}`, at);
134
+ const source = sourceOf(record['source'], `${at}.source`);
135
+ if ('kind' in source)
136
+ return source;
137
+ const timestamp = record['publishTimestamp'];
138
+ if (timestamp !== undefined && (!Number.isInteger(timestamp) || timestamp < 0)) {
139
+ return problem('timestamp', 'publishTimestamp 必须是 Unix 秒整数', at);
140
+ }
141
+ const engines = asRecord(record['engines']);
142
+ const dsh = engines === undefined ? '' : asText(engines['dsh']);
143
+ return {
144
+ version,
145
+ source,
146
+ ...(timestamp === undefined ? {} : { publishTimestamp: timestamp }),
147
+ ...(dsh === '' ? {} : { engines: { dsh } }),
148
+ };
149
+ }
150
+ function versionsOf(raw, at) {
151
+ if (!Array.isArray(raw) || raw.length === 0)
152
+ return problem('versions', 'versions 必须是非空数组', at);
153
+ const versions = [];
154
+ const seen = new Set();
155
+ for (const [index, item] of raw.entries()) {
156
+ const parsed = versionOf(item, `${at}[${String(index)}]`);
157
+ if ('kind' in parsed)
158
+ return parsed;
159
+ if (seen.has(parsed.version))
160
+ return problem('versions', `版本重复:${parsed.version}`, at);
161
+ seen.add(parsed.version);
162
+ versions.push(parsed);
163
+ }
164
+ for (let index = 1; index < versions.length; index += 1) {
165
+ const order = compareSemver(versions[index - 1]?.version ?? '', versions[index]?.version ?? '');
166
+ if (order === undefined || order < 0) {
167
+ return problem('version-order', 'versions 必须按 SemVer 降序', at);
168
+ }
169
+ }
170
+ return versions;
171
+ }
172
+ function iconProblem(icon) {
173
+ if (icon.length > MAX_ICON_CHARS)
174
+ return problem('icon', 'icon 超过 32 KiB');
175
+ if (icon.startsWith('data:image/'))
176
+ return icon.includes(';base64,') ? undefined : problem('icon', 'data URL 必须是 base64');
177
+ if (/^https?:\/\//i.test(icon))
178
+ return undefined;
179
+ return problem('icon', 'icon 只能是 base64 data URL 或 http(s) URL');
180
+ }
181
+ function metadataOf(raw) {
182
+ const record = asRecord(raw);
183
+ if (record === undefined)
184
+ return undefined;
185
+ const category = asText(record['category']);
186
+ const labels = asTextArray(record['labels']);
187
+ const keywords = asTextArray(record['keywords']);
188
+ const sortKeysRecord = asRecord(record['sortKeys']);
189
+ const sortKeys = sortKeysRecord === undefined
190
+ ? undefined
191
+ : Object.fromEntries(Object.entries(sortKeysRecord).flatMap(([key, value]) => typeof value === 'string' || typeof value === 'number' ? [[key, value]] : []));
192
+ return {
193
+ ...(category === '' ? {} : { category }),
194
+ ...(labels.length === 0 ? {} : { labels }),
195
+ ...(keywords.length === 0 ? {} : { keywords }),
196
+ ...(sortKeys === undefined || Object.keys(sortKeys).length === 0 ? {} : { sortKeys }),
197
+ };
198
+ }
199
+ function entryOf(raw, at) {
200
+ const record = asRecord(raw);
201
+ if (record === undefined)
202
+ return problem('plugin', '插件条目必须是对象', at);
203
+ const name = asText(record['name']);
204
+ if (name === '' || name.length > 214 || !NPM_NAME.test(name)) {
205
+ return problem('name', `不是合法 npm 包名:${JSON.stringify(name)}`, at);
206
+ }
207
+ const versions = versionsOf(record['versions'], `${at}.versions`);
208
+ if ('kind' in versions)
209
+ return versions;
210
+ const icon = asText(record['icon']);
211
+ if (icon !== '') {
212
+ const badIcon = iconProblem(icon);
213
+ if (badIcon !== undefined)
214
+ return badIcon;
215
+ }
216
+ const title = asLocalized(record['title']);
217
+ const description = asLocalized(record['description']);
218
+ const author = asText(record['author']);
219
+ const homepage = asText(record['homepage']);
220
+ const metadata = metadataOf(record['metadata']);
221
+ return {
222
+ name,
223
+ versions,
224
+ ...(title === undefined ? {} : { title }),
225
+ ...(description === undefined ? {} : { description }),
226
+ ...(author === '' ? {} : { author }),
227
+ ...(homepage === '' ? {} : { homepage }),
228
+ ...(icon === '' ? {} : { icon }),
229
+ ...(metadata === undefined ? {} : { metadata }),
230
+ };
231
+ }
232
+ export function parseMarketIndex(raw) {
233
+ const record = asRecord(raw);
234
+ if (record === undefined)
235
+ return { ok: false, problems: [problem('not-object', '索引必须是一个 JSON 对象')] };
236
+ if (record['format'] !== MARKET_INDEX_FORMAT) {
237
+ return {
238
+ ok: false,
239
+ problems: [problem('format', `format 必须是 ${String(MARKET_INDEX_FORMAT)}(现在是 ${JSON.stringify(record['format'])})`)],
240
+ };
241
+ }
242
+ const plugins = record['plugins'];
243
+ if (!Array.isArray(plugins))
244
+ return { ok: false, problems: [problem('plugins', 'plugins 必须是数组')] };
245
+ const entries = [];
246
+ const problems = [];
247
+ const seen = new Set();
248
+ for (const [index, item] of plugins.entries()) {
249
+ const parsed = entryOf(item, `plugins[${String(index)}]`);
250
+ if ('kind' in parsed) {
251
+ problems.push(parsed);
252
+ continue;
253
+ }
254
+ if (seen.has(parsed.name)) {
255
+ problems.push(problem('duplicate-name', `插件名重复:${parsed.name}`, `plugins[${String(index)}]`));
256
+ continue;
257
+ }
258
+ seen.add(parsed.name);
259
+ entries.push(parsed);
260
+ }
261
+ if (problems.length > 0)
262
+ return { ok: false, problems };
263
+ const title = asLocalized(record['title']);
264
+ const description = asLocalized(record['description']);
265
+ const metadata = asRecord(record['metadata']);
266
+ return {
267
+ ok: true,
268
+ index: {
269
+ format: MARKET_INDEX_FORMAT,
270
+ plugins: entries,
271
+ ...(title === undefined ? {} : { title }),
272
+ ...(description === undefined ? {} : { description }),
273
+ ...(metadata === undefined ? {} : { metadata: metadata }),
274
+ },
275
+ };
276
+ }
277
+ export function parseMarketIndexJson(text) {
278
+ try {
279
+ return parseMarketIndex(JSON.parse(text));
280
+ }
281
+ catch (error) {
282
+ return {
283
+ ok: false,
284
+ problems: [problem('not-json', `JSON 解析失败:${error instanceof Error ? error.message : String(error)}`)],
285
+ };
286
+ }
287
+ }
288
+ export function sortMarketVersions(versions) {
289
+ return [...versions].sort((left, right) => (compareSemver(right.version, left.version) ?? 0));
290
+ }
291
+ export function upsertMarketEntry(index, entry) {
292
+ const found = index.plugins.findIndex((item) => item.name === entry.name);
293
+ if (found === -1)
294
+ return { ...index, plugins: [...index.plugins, entry] };
295
+ const current = index.plugins[found];
296
+ if (current === undefined)
297
+ return { ...index, plugins: [...index.plugins, entry] };
298
+ const merged = new Map();
299
+ for (const one of current.versions)
300
+ merged.set(one.version, one);
301
+ for (const one of entry.versions)
302
+ merged.set(one.version, one);
303
+ const plugins = [...index.plugins];
304
+ plugins[found] = { ...current, ...entry, versions: sortMarketVersions([...merged.values()]) };
305
+ return { ...index, plugins };
306
+ }
307
+ export function marketEntryLabels(entry) {
308
+ return entry.metadata?.labels ?? [];
309
+ }
310
+ export function filterMarketIndex(index, filter) {
311
+ const query = (filter.query ?? '').trim().toLowerCase();
312
+ const category = (filter.category ?? '').trim();
313
+ const label = (filter.label ?? '').trim();
314
+ return index.plugins.filter((entry) => {
315
+ if (category !== '' && entry.metadata?.category !== category)
316
+ return false;
317
+ if (label !== '' && !marketEntryLabels(entry).includes(label))
318
+ return false;
319
+ if (query === '')
320
+ return true;
321
+ const haystack = [
322
+ entry.name,
323
+ marketText(entry.title, 'zh'),
324
+ marketText(entry.title, 'en'),
325
+ marketText(entry.description, 'zh'),
326
+ marketText(entry.description, 'en'),
327
+ entry.author ?? '',
328
+ ...(entry.metadata?.keywords ?? []),
329
+ ]
330
+ .join(' ')
331
+ .toLowerCase();
332
+ return haystack.includes(query);
333
+ });
334
+ }
335
+ export function marketSourceKey(source) {
336
+ const canonical = JSON.stringify([source.kind, source.url.trim(), source.ref ?? '', source.path ?? '']);
337
+ return createHash('sha256').update(canonical).digest('hex').slice(0, 16);
338
+ }
339
+ export function parseSourceConfig(raw) {
340
+ const record = asRecord(raw);
341
+ if (record === undefined)
342
+ return { ok: false, problem: problem('source', '索引源必须是对象') };
343
+ const id = asText(record['id']);
344
+ const label = asText(record['label']);
345
+ const kind = record['kind'];
346
+ const url = asText(record['url']);
347
+ if (id === '')
348
+ return { ok: false, problem: problem('source', '索引源缺 id') };
349
+ if (label === '')
350
+ return { ok: false, problem: problem('source', '索引源缺 label') };
351
+ if (kind !== 'http' && kind !== 'git')
352
+ return { ok: false, problem: problem('source', 'kind 只能是 http 或 git') };
353
+ if (kind === 'http') {
354
+ const bad = httpUrlProblem(url);
355
+ if (bad !== undefined)
356
+ return { ok: false, problem: problem('source', bad) };
357
+ return { ok: true, source: { id, label, kind, url } };
358
+ }
359
+ if (!gitUrlOk(url)) {
360
+ return { ok: false, problem: problem('source', 'git 地址不合格(只收 https / ssh / scp 形式,且不能带凭据)') };
361
+ }
362
+ const ref = asText(record['ref']);
363
+ const path = asText(record['path']);
364
+ const localPath = asText(record['localPath']);
365
+ const policy = record['policy'];
366
+ if (policy !== undefined && policy !== 'artifacts-in-repo' && policy !== 'catalog-only') {
367
+ return { ok: false, problem: problem('source', 'policy 只能是 artifacts-in-repo 或 catalog-only') };
368
+ }
369
+ return {
370
+ ok: true,
371
+ source: {
372
+ id,
373
+ label,
374
+ kind,
375
+ url,
376
+ ...(ref === '' ? {} : { ref }),
377
+ ...(path === '' ? {} : { path }),
378
+ ...(localPath === '' ? {} : { localPath }),
379
+ ...(policy === undefined ? {} : { policy: policy }),
380
+ },
381
+ };
382
+ }
383
+ export function httpUrlProblem(url) {
384
+ let parsed;
385
+ try {
386
+ parsed = new URL(url);
387
+ }
388
+ catch {
389
+ return '不是合法 URL';
390
+ }
391
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
392
+ return '只收 http / https';
393
+ if (parsed.username !== '' || parsed.password !== '')
394
+ return 'URL 不能带凭据';
395
+ if (parsed.search !== '' || parsed.hash !== '')
396
+ return 'URL 不能带 query / fragment';
397
+ return undefined;
398
+ }
399
+ export function gitUrlOk(url) {
400
+ if (url === '')
401
+ return false;
402
+ if (/^[^@\s]+@[^@\s:]+:[^@\s]+$/.test(url))
403
+ return true;
404
+ let parsed;
405
+ try {
406
+ parsed = new URL(url);
407
+ }
408
+ catch {
409
+ return false;
410
+ }
411
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'ssh:' && parsed.protocol !== 'http:')
412
+ return false;
413
+ if (parsed.password !== '')
414
+ return false;
415
+ if (parsed.username !== '' && parsed.protocol !== 'ssh:')
416
+ return false;
417
+ if (parsed.search !== '' || parsed.hash !== '')
418
+ return false;
419
+ return true;
420
+ }
@@ -0,0 +1,4 @@
1
+ export type { NeedKindSpec as NeedKindSpecOf } from '../contract/needs.js';
2
+ export type NeedProbe = 'bin' | 'extension' | 'package' | 'env';
3
+ export { NEED_KIND_SPECS } from '../contract/needs.js';
4
+ export declare const NEED_PROBES: readonly NeedProbe[];
@@ -0,0 +1,2 @@
1
+ export { NEED_KIND_SPECS } from '../contract/needs.js';
2
+ export const NEED_PROBES = ['bin', 'extension', 'package', 'env'];
@@ -0,0 +1,9 @@
1
+ export interface PatchBlock {
2
+ readonly key: string;
3
+ readonly id: string;
4
+ readonly insert: boolean;
5
+ readonly body: string;
6
+ readonly names: readonly string[];
7
+ }
8
+ export declare function patchBlocks(text: string): PatchBlock[];
9
+ export declare function writePatchFile(path: string, text: string): void;
@@ -0,0 +1,78 @@
1
+ import { renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ const ID_LINE = /^- id:[ \t]*"?([^"\s#]+)/;
3
+ const INSERT_LINE = /^- insert:[ \t]*$/;
4
+ const NESTED_ID = /^[ \t]+-[ \t]*id:[ \t]*"?([^"\s#]+)/;
5
+ const NAME_LINE = /^[ \t]*-?[ \t]*name:[ \t]*['"]?([^'"\s#]+)/;
6
+ function trimmedTail(lines) {
7
+ let end = lines.length;
8
+ while (end > 0 && (lines[end - 1] ?? '').trim() === '')
9
+ end -= 1;
10
+ return lines.slice(0, end);
11
+ }
12
+ function matched(text, pattern) {
13
+ const found = pattern.exec(text);
14
+ return found === null ? undefined : found[1];
15
+ }
16
+ function blockOf(body, index) {
17
+ const lines = body.split('\n');
18
+ const first = lines[0] ?? '';
19
+ const id = matched(first, ID_LINE);
20
+ const nested = lines.flatMap((line) => {
21
+ const one = matched(line, NESTED_ID);
22
+ return one === undefined ? [] : [one];
23
+ });
24
+ const insert = id === undefined && INSERT_LINE.test(first);
25
+ const label = id ?? nested.join(', ');
26
+ const key = id !== undefined ? `id:${id}` : insert ? `insert:${nested.join(', ')}` : `block:${String(index)}`;
27
+ const names = lines.flatMap((line) => {
28
+ const one = matched(line, NAME_LINE);
29
+ return one === undefined ? [] : [one];
30
+ });
31
+ return { key, id: label === '' ? key : label, insert, body, names };
32
+ }
33
+ function spannedBlocks(text) {
34
+ const lines = text.split('\n');
35
+ const starts = [];
36
+ lines.forEach((line, index) => {
37
+ if (/^- /.test(line) || line === '-')
38
+ starts.push(index);
39
+ });
40
+ const blocks = [];
41
+ for (let i = 0; i < starts.length; i += 1) {
42
+ const from = starts[i] ?? 0;
43
+ const to = i + 1 < starts.length ? (starts[i + 1] ?? lines.length) : lines.length;
44
+ const body = trimmedTail(lines.slice(from, to)).join('\n');
45
+ if (body.trim() === '')
46
+ continue;
47
+ blocks.push({ ...blockOf(body, blocks.length), from, to });
48
+ }
49
+ return blocks;
50
+ }
51
+ export function patchBlocks(text) {
52
+ return spannedBlocks(text).map(({ from: _from, to: _to, ...block }) => block);
53
+ }
54
+ function patchMode(path) {
55
+ try {
56
+ return statSync(path).mode & 0o777;
57
+ }
58
+ catch {
59
+ return 0o644;
60
+ }
61
+ }
62
+ export function writePatchFile(path, text) {
63
+ const mode = patchMode(path);
64
+ const tmp = `${path}.wb-sync-${String(process.pid)}`;
65
+ writeFileSync(tmp, text, { mode });
66
+ try {
67
+ renameSync(tmp, path);
68
+ }
69
+ catch (error) {
70
+ try {
71
+ unlinkSync(tmp);
72
+ }
73
+ catch {
74
+ throw error;
75
+ }
76
+ throw error;
77
+ }
78
+ }
@@ -0,0 +1,12 @@
1
+ export declare function isolatedRoot(): string;
2
+ export declare function isolatedHome(): string;
3
+ export declare function vendorPrefix(): string;
4
+ export declare function vendorPluginsDir(): string;
5
+ export declare function libsPrefix(): string;
6
+ export declare const OPENCLI_NPM_PACKAGE = "@jackwener/opencli";
7
+ export declare function toolchainOpencliDir(): string;
8
+ export declare function vendorPeerLink(): {
9
+ readonly dir: string;
10
+ readonly parent: string;
11
+ };
12
+ export declare function npmCacheDir(): string;
@@ -0,0 +1,28 @@
1
+ import { workbenchRoot } from './data-root.js';
2
+ export function isolatedRoot() {
3
+ return `${workbenchRoot()}/opencli`;
4
+ }
5
+ export function isolatedHome() {
6
+ return `${isolatedRoot()}/home`;
7
+ }
8
+ export function vendorPrefix() {
9
+ return `${isolatedRoot()}/plugins-npm`;
10
+ }
11
+ export function vendorPluginsDir() {
12
+ return `${vendorPrefix()}/node_modules`;
13
+ }
14
+ export function libsPrefix() {
15
+ return `${isolatedRoot()}/libs`;
16
+ }
17
+ export const OPENCLI_NPM_PACKAGE = '@jackwener/opencli';
18
+ export function toolchainOpencliDir() {
19
+ return `${isolatedRoot()}/toolchain/node_modules/${OPENCLI_NPM_PACKAGE}`;
20
+ }
21
+ export function vendorPeerLink() {
22
+ const base = `${vendorPrefix()}/node_modules`;
23
+ const [scope] = OPENCLI_NPM_PACKAGE.split('/');
24
+ return { dir: `${base}/${OPENCLI_NPM_PACKAGE}`, parent: `${base}/${scope}` };
25
+ }
26
+ export function npmCacheDir() {
27
+ return `${isolatedRoot()}/npm-cache`;
28
+ }
@@ -0,0 +1,14 @@
1
+ import type { HostOs, HostSurface, ProfileName } from '../contract/protocol/platform.js';
2
+ export interface HostSurfaceInput {
3
+ readonly proc?: {
4
+ readonly versions: {
5
+ readonly electron?: string | undefined;
6
+ readonly node?: string | undefined;
7
+ };
8
+ };
9
+ readonly profile?: string | undefined;
10
+ readonly platform?: NodeJS.Platform | undefined;
11
+ }
12
+ export declare function profileNameOf(raw: string | undefined): ProfileName;
13
+ export declare function hostOsOf(platform: NodeJS.Platform): HostOs;
14
+ export declare function hostSurface(input?: HostSurfaceInput): HostSurface;
@@ -0,0 +1,40 @@
1
+ export function profileNameOf(raw) {
2
+ const name = (raw ?? '').split(/[\\/]/).pop()?.toLowerCase() ?? '';
3
+ if (name === 'desktop' || name === 'web' || name === 'workbench' || name === 'headless')
4
+ return name;
5
+ return 'other';
6
+ }
7
+ export function hostOsOf(platform) {
8
+ if (platform === 'darwin' || platform === 'win32' || platform === 'linux')
9
+ return platform;
10
+ return 'other';
11
+ }
12
+ export function hostSurface(input = {}) {
13
+ const proc = input.proc ?? process;
14
+ const runtime = proc.versions.electron === undefined ? 'node' : 'electron';
15
+ const deployment = runtime === 'electron' ? 'desktop' : 'web';
16
+ const profile = profileNameOf(input.profile);
17
+ const hostOs = hostOsOf(input.platform ?? process.platform);
18
+ const pageDebug = deployment !== 'desktop';
19
+ const selfUpdateCli = profile === 'desktop' ? 'desktop-cli' : 'path-dsh';
20
+ return {
21
+ deployment,
22
+ hostOs,
23
+ runtime,
24
+ profile,
25
+ capabilities: {
26
+ pageDebug,
27
+ siteExplore: true,
28
+ recording: true,
29
+ browserWake: deployment === 'desktop',
30
+ selfUpdateCli,
31
+ safeMode: deployment === 'desktop',
32
+ },
33
+ restartHint: deployment === 'desktop' ? '退出并重开 Desktop' : '重启一次 dsh',
34
+ toolchain: {
35
+ node: { source: deployment === 'desktop' ? 'desktop-shim' : 'path' },
36
+ npm: { neededFor: 'opencli-install' },
37
+ pnpm: { neededFor: 'workshop', expectedMajor: 10 },
38
+ },
39
+ };
40
+ }
@@ -1,5 +1,6 @@
1
- import type { PluginSource } from '../api/unit.js';
2
- export type PluginSourceProblem = "not-declared" | "env-missing" | "malformed";
1
+ import type { SupplySource } from '../contract/needs.js';
2
+ import type { ProvisionProblem } from '../contract/plugin-source.js';
3
+ export type { ProvisionProblem } from '../contract/plugin-source.js';
3
4
  export interface PluginSourceCommand {
4
5
  readonly line: string;
5
6
  readonly optional?: true;
@@ -10,22 +11,23 @@ export type ResolvedPluginSource = {
10
11
  readonly line: string;
11
12
  } | {
12
13
  readonly ok: false;
13
- readonly problem: PluginSourceProblem;
14
+ readonly problem: ProvisionProblem;
14
15
  readonly env?: string;
15
16
  };
16
17
  export interface PluginSourceOptions {
17
18
  readonly command?: string;
18
19
  readonly plugin?: string;
19
20
  readonly version?: string;
20
- readonly mode?: "install" | "update";
21
+ readonly mode?: 'install' | 'update';
21
22
  }
22
23
  export declare function npmRegistryOf(source: {
23
- readonly registryEnv: string;
24
+ readonly registryEnv?: string;
24
25
  readonly registryDefault?: string;
25
26
  }, env: Readonly<Record<string, string | undefined>>): {
26
27
  readonly ok: true;
27
28
  readonly value: string;
28
29
  } | {
29
30
  readonly ok: false;
31
+ readonly env: string;
30
32
  };
31
- export declare function resolvePluginSource(source: PluginSource | undefined, env: Readonly<Record<string, string | undefined>>, options?: PluginSourceOptions): ResolvedPluginSource;
33
+ export declare function resolvePluginSource(source: SupplySource | undefined, env: Readonly<Record<string, string | undefined>>, options?: PluginSourceOptions): ResolvedPluginSource;