@dsh-workbench/shared 1.1.8 → 1.1.10

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 (226) hide show
  1. package/dist/api/blocker-table.d.ts +1 -0
  2. package/dist/api/blocker-table.js +1 -1
  3. package/dist/components/SelectField.css +0 -6
  4. package/dist/components/SelectField.d.ts +2 -3
  5. package/dist/components/SelectField.js +9 -30
  6. package/dist/components/SelectFieldNodes.d.ts +3 -1
  7. package/dist/components/SelectFieldNodes.js +2 -1
  8. package/dist/components/SelectFieldWheel.d.ts +9 -0
  9. package/dist/components/SelectFieldWheel.js +35 -0
  10. package/dist/config/constants.d.ts +4 -4
  11. package/dist/config/constants.js +4 -4
  12. package/dist/contract/capabilities.d.ts +29 -0
  13. package/dist/contract/capabilities.js +1 -0
  14. package/dist/contract/needs.d.ts +3 -3
  15. package/dist/contract/needs.js +1 -1
  16. package/dist/contract/plugin-source.d.ts +19 -0
  17. package/dist/contract/protocol/bundle-install.d.ts +3 -1
  18. package/dist/contract/protocol/bundle-install.js +3 -0
  19. package/dist/contract/protocol/market-index.d.ts +1 -1
  20. package/dist/contract/protocol/platform.d.ts +1 -1
  21. package/dist/contract/runner.d.ts +6 -0
  22. package/dist/contract/runner.js +1 -0
  23. package/dist/contract/unit.d.ts +4 -4
  24. package/dist/host/adapter-contract.d.ts +3 -0
  25. package/dist/host/adapter-contract.js +93 -0
  26. package/dist/host/adapter-set.js +6 -4
  27. package/dist/host/adapter-types.d.ts +1 -1
  28. package/dist/host/bundle-manager.d.ts +3 -0
  29. package/dist/host/bundle-manager.js +181 -0
  30. package/dist/host/cli.js +3 -1
  31. package/dist/host/config-sync.d.ts +48 -0
  32. package/dist/host/config-sync.js +342 -0
  33. package/dist/host/dsh-plugins.d.ts +5 -0
  34. package/dist/host/dsh-plugins.js +51 -0
  35. package/dist/host/extension.js +1 -1
  36. package/dist/host/flow/check.d.ts +9 -0
  37. package/dist/host/flow/check.js +179 -0
  38. package/dist/host/flow/expr.d.ts +30 -0
  39. package/dist/host/flow/expr.js +99 -0
  40. package/dist/host/flow/kit.d.ts +14 -0
  41. package/dist/host/flow/kit.js +13 -0
  42. package/dist/host/flow/run.d.ts +13 -0
  43. package/dist/host/flow/run.js +287 -0
  44. package/dist/host/flow/types.d.ts +188 -0
  45. package/dist/host/flow/types.js +1 -0
  46. package/dist/host/host-actions.d.ts +2 -0
  47. package/dist/host/host-actions.js +5 -0
  48. package/dist/host/host-kit.d.ts +19 -0
  49. package/dist/host/host-kit.js +14 -0
  50. package/dist/host/http.d.ts +2 -6
  51. package/dist/host/http.js +2 -2
  52. package/dist/host/installed-module.d.ts +23 -0
  53. package/dist/host/installed-module.js +264 -0
  54. package/dist/host/lib-install.d.ts +7 -9
  55. package/dist/host/lib-install.js +9 -12
  56. package/dist/host/lib-runners.d.ts +3 -5
  57. package/dist/host/lib-runners.js +2 -2
  58. package/dist/host/local-declaration.d.ts +7 -0
  59. package/dist/host/local-declaration.js +33 -0
  60. package/dist/host/module-root.d.ts +1 -0
  61. package/dist/host/module-root.js +5 -0
  62. package/dist/host/npm-registry.d.ts +10 -0
  63. package/dist/host/npm-registry.js +16 -0
  64. package/dist/host/opencli-runner.d.ts +2 -1
  65. package/dist/host/package-content.d.ts +7 -0
  66. package/dist/host/package-content.js +69 -0
  67. package/dist/host/package-kind.d.ts +13 -0
  68. package/dist/host/package-kind.js +51 -0
  69. package/dist/host/package-route.d.ts +31 -0
  70. package/dist/host/package-route.js +57 -0
  71. package/dist/host/paths.d.ts +11 -19
  72. package/dist/host/paths.js +16 -43
  73. package/dist/host/platform.js +1 -1
  74. package/dist/host/plugin-ledger.d.ts +8 -8
  75. package/dist/host/plugin-ledger.js +23 -16
  76. package/dist/host/plugin.d.ts +1 -2
  77. package/dist/host/plugin.js +4 -5
  78. package/dist/host/port-types.d.ts +42 -9
  79. package/dist/host/preflight.d.ts +3 -2
  80. package/dist/host/profile-create.d.ts +18 -0
  81. package/dist/host/profile-create.js +118 -0
  82. package/dist/host/profile-registries.d.ts +10 -0
  83. package/dist/host/profile-registries.js +150 -0
  84. package/dist/host/registry-declaration.d.ts +21 -0
  85. package/dist/host/registry-declaration.js +33 -0
  86. package/dist/host/release-probe.d.ts +34 -0
  87. package/dist/host/release-probe.js +88 -0
  88. package/dist/host/runner.d.ts +26 -0
  89. package/dist/host/runner.js +50 -0
  90. package/dist/host/shell.d.ts +0 -2
  91. package/dist/host/shell.js +0 -7
  92. package/dist/host/spec.js +1 -1
  93. package/dist/host/supply-index.d.ts +1 -0
  94. package/dist/host/supply-index.js +8 -7
  95. package/dist/host/supply-port.js +13 -3
  96. package/dist/host/unit-face.d.ts +2 -1
  97. package/dist/host/version.js +11 -6
  98. package/dist/host.d.ts +24 -6
  99. package/dist/host.js +23 -6
  100. package/dist/i18n/en.js +23 -24
  101. package/dist/i18n/index.d.ts +23 -24
  102. package/dist/i18n/runtime-terms.d.ts +15 -0
  103. package/dist/i18n/runtime-terms.js +22 -0
  104. package/dist/i18n/zh.d.ts +22 -23
  105. package/dist/i18n/zh.js +22 -23
  106. package/dist/index.d.ts +4 -0
  107. package/dist/index.js +4 -0
  108. package/dist/testing/fake-adapter-set.d.ts +5 -0
  109. package/dist/testing/fake-adapter-set.js +150 -0
  110. package/dist/testing/needs.js +1 -1
  111. package/dist/testing.d.ts +1 -0
  112. package/dist/testing.js +1 -0
  113. package/package.json +1 -1
  114. package/src/api/__tests__/blocker-table.test.ts +25 -0
  115. package/src/api/{workbench-client.test.ts → __tests__/workbench-client.test.ts} +2 -2
  116. package/src/api/blocker-table.ts +6 -2
  117. package/src/components/SelectField.css +0 -6
  118. package/src/components/SelectField.tsx +7 -36
  119. package/src/components/SelectFieldNodes.tsx +4 -1
  120. package/src/components/{Card.test.tsx → __tests__/Card.test.tsx} +2 -2
  121. package/src/components/{CardAnchor.test.tsx → __tests__/CardAnchor.test.tsx} +3 -3
  122. package/src/components/{CardHead.test.tsx → __tests__/CardHead.test.tsx} +1 -1
  123. package/src/components/{ChoiceGroup.test.tsx → __tests__/ChoiceGroup.test.tsx} +2 -2
  124. package/src/components/{ConfirmBar.test.tsx → __tests__/ConfirmBar.test.tsx} +5 -5
  125. package/src/components/{Field.test.tsx → __tests__/Field.test.tsx} +1 -1
  126. package/src/components/{Form.test.tsx → __tests__/Form.test.tsx} +5 -5
  127. package/src/components/{FormActions.test.tsx → __tests__/FormActions.test.tsx} +3 -3
  128. package/src/components/{FormRows.test.tsx → __tests__/FormRows.test.tsx} +2 -2
  129. package/src/components/{FormTypes.test.ts → __tests__/FormTypes.test.ts} +1 -1
  130. package/src/components/{FormWiring.test.tsx → __tests__/FormWiring.test.tsx} +4 -4
  131. package/src/components/{Link.test.tsx → __tests__/Link.test.tsx} +1 -1
  132. package/src/components/{Rows.test.tsx → __tests__/Rows.test.tsx} +2 -2
  133. package/src/components/{SelectField.test.tsx → __tests__/SelectField.test.tsx} +7 -37
  134. package/src/components/{Spinner.test.tsx → __tests__/Spinner.test.tsx} +4 -4
  135. package/src/config/{constants.test.ts → __tests__/constants.test.ts} +1 -1
  136. package/src/config/{storage.test.ts → __tests__/storage.test.ts} +1 -1
  137. package/src/config/constants.ts +4 -4
  138. package/src/contract/capabilities.ts +30 -0
  139. package/src/contract/needs.ts +4 -4
  140. package/src/contract/plugin-source.ts +24 -0
  141. package/src/contract/protocol/bundle-install.ts +7 -1
  142. package/src/contract/protocol/market-index.ts +1 -0
  143. package/src/contract/protocol/platform.ts +1 -1
  144. package/src/contract/runner.ts +6 -0
  145. package/src/contract/unit.ts +4 -4
  146. package/src/host/{extension.test.ts → __tests__/extension.test.ts} +4 -4
  147. package/src/host/{install-failure.test.ts → __tests__/install-failure.test.ts} +1 -1
  148. package/src/host/{installed-sources.test.ts → __tests__/installed-sources.test.ts} +1 -1
  149. package/src/host/__tests__/lib-runners.test.ts +11 -2
  150. package/src/host/__tests__/plugin-ledger.test.ts +19 -6
  151. package/src/host/{recipe.test.ts → __tests__/recipe.test.ts} +3 -3
  152. package/src/host/__tests__/runtime-layout.test.ts +14 -0
  153. package/src/host/__tests__/supply-index.test.ts +2 -2
  154. package/src/host/__tests__/supply-port.test.ts +32 -0
  155. package/src/host/adapter-contract.ts +93 -0
  156. package/src/host/adapter-set.ts +6 -4
  157. package/src/host/adapter-types.ts +1 -1
  158. package/src/host/bundle-manager.ts +195 -0
  159. package/src/host/cli.ts +3 -1
  160. package/src/host/config-sync.ts +386 -0
  161. package/src/host/dsh-plugins.ts +60 -0
  162. package/src/host/extension.ts +1 -1
  163. package/src/host/flow/__tests__/advanced.test.ts +302 -0
  164. package/src/host/flow/__tests__/check.test.ts +169 -0
  165. package/src/host/flow/__tests__/run.test.ts +301 -0
  166. package/src/host/flow/check.ts +216 -0
  167. package/src/host/flow/expr.ts +94 -0
  168. package/src/host/flow/kit.ts +30 -0
  169. package/src/host/flow/run.ts +325 -0
  170. package/src/host/flow/types.ts +199 -0
  171. package/src/host/host-actions.ts +7 -0
  172. package/src/host/host-kit.ts +26 -0
  173. package/src/host/http.ts +6 -8
  174. package/src/host/installed-module.ts +272 -0
  175. package/src/host/lib-install.ts +14 -12
  176. package/src/host/lib-runners.ts +6 -8
  177. package/src/host/local-declaration.ts +37 -0
  178. package/src/host/module-root.ts +6 -0
  179. package/src/host/npm-registry.ts +21 -0
  180. package/src/host/package-content.ts +76 -0
  181. package/src/host/package-kind.ts +63 -0
  182. package/src/host/package-route.ts +93 -0
  183. package/src/host/paths.ts +27 -52
  184. package/src/host/platform.ts +1 -1
  185. package/src/host/plugin-ledger.ts +25 -18
  186. package/src/host/plugin.ts +4 -5
  187. package/src/host/port-types.ts +43 -9
  188. package/src/host/preflight.ts +3 -2
  189. package/src/host/profile-create.ts +133 -0
  190. package/src/host/profile-registries.ts +145 -0
  191. package/src/host/registry-declaration.ts +70 -0
  192. package/src/host/release-probe.ts +202 -0
  193. package/src/host/shell.ts +0 -9
  194. package/src/host/spec.ts +1 -1
  195. package/src/host/supply-index.ts +9 -7
  196. package/src/host/supply-port.ts +13 -3
  197. package/src/host/unit-face.ts +2 -1
  198. package/src/host/version.ts +12 -7
  199. package/src/host.ts +34 -6
  200. package/src/i18n/{index.test.ts → __tests__/index.test.ts} +3 -3
  201. package/src/i18n/{merge.test.ts → __tests__/merge.test.ts} +1 -1
  202. package/src/i18n/{zh.test.ts → __tests__/zh.test.ts} +2 -2
  203. package/src/i18n/en.ts +23 -25
  204. package/src/i18n/runtime-terms.ts +26 -0
  205. package/src/i18n/zh.ts +22 -24
  206. package/src/index.ts +4 -0
  207. package/src/lib/{board-fact.test.ts → __tests__/board-fact.test.ts} +1 -1
  208. package/src/lib/{busy.test.ts → __tests__/busy.test.ts} +1 -1
  209. package/src/lib/{form-problem.test.ts → __tests__/form-problem.test.ts} +1 -1
  210. package/src/lib/{git-address.test.ts → __tests__/git-address.test.ts} +1 -1
  211. package/src/lib/{react.test.ts → __tests__/react.test.ts} +1 -1
  212. package/src/lib/{text.test.ts → __tests__/text.test.ts} +1 -1
  213. package/src/lib/{ui.test.ts → __tests__/ui.test.ts} +1 -1
  214. package/src/testing/__tests__/fake-adapter-set.test.ts +28 -0
  215. package/src/testing/fake-adapter-set.ts +173 -0
  216. package/src/testing/needs.ts +1 -1
  217. package/src/testing.ts +1 -0
  218. package/src/host/__tests__/command-name.test.ts +0 -16
  219. package/src/host/__tests__/opencli-runner.test.ts +0 -120
  220. package/src/host/channel-plugin.ts +0 -55
  221. package/src/host/command-name.ts +0 -15
  222. package/src/host/opencli-runner.ts +0 -76
  223. package/src/host/paths.test.ts +0 -26
  224. package/src/host/plugin-source.ts +0 -137
  225. package/src/host/runtime-links.test.ts +0 -31
  226. package/src/host/runtime-links.ts +0 -23
package/src/i18n/en.ts CHANGED
@@ -79,7 +79,11 @@ export const en: Record<keyof WorkbenchMessages, string> = {
79
79
 
80
80
  'panels.title': 'Panel modules',
81
81
  'panels.groupBoardless': 'No-board modules',
82
- 'panels.groupPlugins': 'opencli plugins',
82
+ 'panels.groupPlugins': 'Plugins',
83
+ 'runtime.plugin': 'plugin',
84
+ 'runtime.pluginOf': 'a plugin the runtime provides',
85
+ 'runtime.pluginThing': 'a plugin',
86
+ 'runtime.pluginArea': 'the plugin area',
83
87
  'panels.market.defaultHint': 'When on, it is on by default in every workspace; you can also turn it off for a single workspace in Panel setup.',
84
88
  'panels.market.defaultLabel': 'On by default everywhere',
85
89
  'panels.market.defaultLocked': 'Unusable right now — update or uninstall it first',
@@ -159,10 +163,6 @@ export const en: Record<keyof WorkbenchMessages, string> = {
159
163
  'panels.market.confirmNo': 'Cancel',
160
164
  'panels.market.noMarketSource': 'The index has no newer version of this module (refresh the index and retry)',
161
165
  'panels.market.failed': 'Failed: {reason}',
162
- 'panels.market.askAgent': 'Ask the agent',
163
- 'panels.market.askAgentCopied': 'Copied',
164
- 'panels.market.askAgentText':
165
- 'This workbench module cannot be used: "{name}" (unit {unit}) — {reason}. Work out what is missing and how to add it, then confirm it works.',
166
166
  'panels.market.failure.permission': "Didn't install: no write access",
167
167
  'panels.market.failure.diskFull': "Didn't install: the disk is full",
168
168
  'panels.market.failure.sandbox': "Didn't install: the system blocked it",
@@ -202,7 +202,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
202
202
  'panels.market.noSource': 'This module declares no install method — install it yourself',
203
203
  'panels.market.badSource': 'The install method is incomplete — install it yourself',
204
204
  'panels.market.empty': 'No modules available',
205
- 'panels.market.sectionPlugins': 'Installed opencli plugins',
205
+ 'panels.market.sectionPlugins': 'Installed plugins',
206
206
  'panels.market.moduleOutdated': 'update available',
207
207
  'panels.market.updateNeedsWorkbench': 'this version needs a newer workbench first',
208
208
  'panels.market.updateIncompatible': 'the new version does not match this workbench, so it cannot be installed now',
@@ -240,7 +240,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
240
240
  'panels.market.justNow': 'just now',
241
241
  'panels.market.minutesAgo': '{n} min ago',
242
242
  'panels.market.hoursAgo': '{n} h ago',
243
- "panels.market.add.description": "Enter a module or opencli plugin package name, Git repository URL, or local directory path.",
243
+ "panels.market.add.description": "Enter a module or {plugin} package name, Git repository URL, or local directory path.",
244
244
  'panels.market.add.specPlaceholder': 'e.g. @dsh-workbench/module-hello',
245
245
  'panels.market.add.guideToggle': 'Install guide and examples',
246
246
  'panels.market.add.guideHide': 'Hide guide',
@@ -280,13 +280,13 @@ export const en: Record<keyof WorkbenchMessages, string> = {
280
280
  'panels.market.add.problemNotFound': 'No such module found',
281
281
  'panels.market.add.problemNotPackage': 'That path does not exist or is not a valid module package',
282
282
  'panels.market.add.problemNotBundle':
283
- 'This package cannot be installed here: {reason}. This entry recognises workbench modules and opencli plugins by package name, and installs either; but a git URL or a tarball does not reveal what it is — if it is really one of those two, use its package name or a local folder instead.',
283
+ 'This package cannot be installed here: {reason}. This entry recognises workbench modules and {plugin}s by package name, and installs either; but a git URL or a tarball does not reveal what it is — if it is really one of those two, use its package name or a local folder instead.',
284
284
  'panels.market.add.problemNotWorkbenchModule': 'This package does not match the workbench you are running, so installing it would not work. Pick another version, or ask the module author.',
285
- 'panels.market.add.problemNotModuleOrPlugin': 'This package is neither a workbench module nor an opencli plugin, so installing it would do nothing. Pick another version, or ask the package author.',
286
- 'panels.market.add.failureNotModuleOrPlugin': 'This package is neither a workbench module nor an opencli plugin, so installing it would do nothing',
287
- 'panels.market.add.installedPlugin': 'Installed: the opencli plugin {name}',
285
+ 'panels.market.add.problemNotModuleOrPlugin': 'This package is neither a workbench module nor {pluginOf}, so installing it would do nothing. Pick another version, or ask the package author.',
286
+ 'panels.market.add.failureNotModuleOrPlugin': 'This package is neither a workbench module nor {pluginOf}, so installing it would do nothing',
287
+ 'panels.market.add.installedPlugin': 'Installed: {plugin} {name}',
288
288
  'panels.market.add.pluginPreview':
289
- 'This is an opencli plugin: it goes into the opencli plugin area and works as soon as it is installed — no restart.',
289
+ 'This is {pluginThing}: it goes into {pluginArea} and works as soon as it is installed — no restart.',
290
290
  'panels.market.add.pluginAlias': 'Plugin name: {name}',
291
291
  'panels.market.add.problemNetwork': 'Cannot reach the module source; check the network and retry',
292
292
  'panels.market.add.problemUnknown': 'Cannot fetch module information: {reason}',
@@ -377,6 +377,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
377
377
  'panels.discover.noSourceHint': 'Add a module market index (http address or git repository) to browse and install its modules here',
378
378
  'panels.discover.sourcesFailed': 'Could not read the index sources.',
379
379
  'panels.discover.unreadable': 'Could not read this index.',
380
+ 'panels.discover.sandbox': 'Blocked by the system: this profile does not allow the workbench to write its own cache directory.',
380
381
  'panels.discover.sourceAuth': 'This index source could not be read: this machine has no git credentials for it. Set up credentials (or switch the source to its SSH address), then refresh.',
381
382
  'panels.discover.invalid': 'This index is not in a valid format.',
382
383
  'panels.discover.emptyRepo': 'This repository has no commits yet.',
@@ -564,7 +565,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
564
565
  'blocker.forbidden.hint': 'You are signed in, but this project/repo is not permitted for your account.',
565
566
  'blocker.forbidden.open': 'Open permissions page',
566
567
  'blocker.timeout.hint': 'The background browser may not have started; retrying usually helps.',
567
- 'blocker.exec.hint': 'Make sure opencli is installed and runs from your terminal (which opencli).',
568
+ 'blocker.exec.hint': 'Make sure the runtime is installed and runs from your terminal.',
568
569
  'blocker.unknown.title': 'Something went wrong',
569
570
  'panels.reading': 'Reading the panel setup…',
570
571
  'panels.cardBroken': 'This module will not render: {unit} ({reason})',
@@ -574,6 +575,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
574
575
  'env.title': 'Preparing the workbench',
575
576
  'env.checking': 'Getting the runtime ready…',
576
577
  'env.installing': 'Installing background tools — the first run takes a moment…',
578
+ 'env.installingToolchain': 'Installing the workbench’s own npm / pnpm — the first run downloads them, so it can take a while.',
577
579
  'env.failed': 'One step away',
578
580
  'env.elapsed': 'Waiting {seconds}s',
579
581
  'env.stepFailed.install': 'install failed',
@@ -581,16 +583,11 @@ export const en: Record<keyof WorkbenchMessages, string> = {
581
583
  'env.stepFailed.shell': 'cannot reach the command line',
582
584
  'env.toolchain.ok': 'Looks good',
583
585
  'env.toolchain.warn': 'Almost ready',
584
- 'env.opencli.ok': 'Ready',
586
+ 'env.runtime.ok': 'Ready',
585
587
  'env.bridge.ok': 'Connected',
586
588
  'env.bridge.short': 'Not connected yet',
587
589
  'env.bridge.why': 'Panel data uses the login state in your browser. Without this connection, modules cannot fetch data. It does not block startup: fix it, or enter the workbench first.',
588
590
  'env.bridge.hold': 'The browser is not connected yet \u2014 fix it below and hit Retry, or enter the workbench first.',
589
- 'env.bridge.daemon': 'The background service is not running. It usually starts by itself \u2014 run the command below in your terminal first.',
590
- 'env.bridge.extension': 'The browser extension is not connected. Make sure the browser is running and the extension is enabled; install it once from the store if needed (then hit Retry here).',
591
- 'env.bridge.extensionLink': 'Get the extension in the Chrome Web Store',
592
- 'env.bridge.profile': 'Several browser accounts are connected but none is the default: list them (command below), then pick one.',
593
- 'env.bridge.stale': 'The default browser account is stale (it names an extension instance that no longer exists): pick one again.',
594
591
  'env.bridge.unknown': 'Could not tell what went wrong. Expand the raw output and follow the steps in it.',
595
592
  'env.fix.title': 'How to fix it',
596
593
  'env.fix.why': 'The workbench uses its own background tool (installed separately from the one in your terminal), and it is not set up on this machine yet.',
@@ -619,13 +616,14 @@ export const en: Record<keyof WorkbenchMessages, string> = {
619
616
  'env.diy.continue': 'Enter the workbench anyway',
620
617
  'env.copyCommand': 'Copy command',
621
618
  'env.copied': 'Copied',
622
- 'env.step.toolchain': 'Runtime',
623
- 'env.step.opencli': 'Background tools',
624
- 'env.step.bridge': 'Browser connection',
625
- 'env.step.diy': 'DIY mode',
626
- 'env.step.warm': 'Site sign-in',
619
+ 'env.step.toolchain': 'Check the environment',
620
+ 'env.step.adapter': 'Check the runtime',
621
+ 'env.step.runtime': 'Install background tools',
622
+ 'env.step.bridge': 'Connect your browser',
623
+ 'env.step.diy': 'Check DIY mode',
624
+ 'env.step.warm': 'Reach your sites',
627
625
  'env.warm.done': 'Ready ({n} sites)',
628
- 'env.warm.short': 'Could not sign in early this time \u2014 nothing breaks; the first read fills it in',
626
+ 'env.warm.short': 'Could not reach your sites early this time \u2014 nothing breaks; the first read fills it in',
629
627
  'env.unit.failed': 'This module cannot start',
630
628
  'env.unit.failedHint': 'It failed while starting up; other modules are unaffected.',
631
629
  'env.unit.unchecked': 'Cannot check: no command line',
@@ -0,0 +1,26 @@
1
+ import type { Translate } from '../lib/dsh-client.js';
2
+ import type { RuntimeText } from '../contract/capabilities.js';
3
+
4
+ /**
5
+ * 把适配器给的 zh / en 两份文案落到当前语言。
6
+ * @param text 适配器档案里的那段话。
7
+ * @param resolve dsh 的语言解析器;没有就取中文那份。
8
+ * @returns 当前语言的那一段。
9
+ */
10
+ export function resolveRuntimeText(text: RuntimeText, resolve?: (text: RuntimeText) => string): string {
11
+ return resolve === undefined ? text.zh : resolve(text);
12
+ }
13
+
14
+ /**
15
+ * 取当前语言的运行时术语(没给档案时的兜底)。
16
+ * @param t 文案函数。
17
+ * @returns `plugin` / `pluginOf` / `pluginThing` / `pluginArea` 四个名词短语。
18
+ */
19
+ export function runtimeTermsOf(t: Translate): Readonly<Record<string, string>> {
20
+ return {
21
+ plugin: t('runtime.plugin'),
22
+ pluginOf: t('runtime.pluginOf'),
23
+ pluginThing: t('runtime.pluginThing'),
24
+ pluginArea: t('runtime.pluginArea'),
25
+ };
26
+ }
package/src/i18n/zh.ts CHANGED
@@ -78,7 +78,11 @@ export const zh = {
78
78
 
79
79
  'panels.title': '面板模块',
80
80
  'panels.groupBoardless': '无看板模块',
81
- 'panels.groupPlugins': 'opencli 插件',
81
+ 'panels.groupPlugins': '插件',
82
+ 'runtime.plugin': '插件',
83
+ 'runtime.pluginOf': '运行时提供的插件',
84
+ 'runtime.pluginThing': '插件',
85
+ 'runtime.pluginArea': '插件区',
82
86
  'panels.market.defaultHint': '打开后所有工作区默认开启,也可在工作区面板配置中单独关闭',
83
87
  'panels.market.defaultLabel': '全局默认开启',
84
88
  'panels.market.defaultLocked': '这份现在用不了,先更新或卸载',
@@ -156,10 +160,6 @@ export const zh = {
156
160
  'panels.market.confirmNo': '取消',
157
161
  'panels.market.noMarketSource': '索引里没有这个模块的新版本(刷新一次索引再试)',
158
162
  'panels.market.failed': '没成功:{reason}',
159
- 'panels.market.askAgent': '问 agent',
160
- 'panels.market.askAgentCopied': '已复制',
161
- 'panels.market.askAgentText':
162
- '工作台里「{name}」(单元 {unit})用不了:{reason}。帮我查清缺什么、怎么补,补完确认真能用。',
163
163
  'panels.market.failure.permission': '没装上:没有写入权限',
164
164
  'panels.market.failure.diskFull': '没装上:磁盘满了',
165
165
  'panels.market.failure.sandbox': '没装上:被系统拦住了',
@@ -199,7 +199,7 @@ export const zh = {
199
199
  'panels.market.noSource': '这个模块没声明怎么装,只能自己动手',
200
200
  'panels.market.badSource': '安装方式没写全,只能自己动手',
201
201
  'panels.market.empty': '暂无可用模块',
202
- 'panels.market.sectionPlugins': '已安装 opencli 插件',
202
+ 'panels.market.sectionPlugins': '已安装的插件',
203
203
  'panels.market.moduleOutdated': '有新版',
204
204
  'panels.market.updateNeedsWorkbench': '新版本要先把工作台升级才能用',
205
205
  'panels.market.updateIncompatible': '新版本和当前的工作台不匹配,暂时不能更新',
@@ -237,7 +237,7 @@ export const zh = {
237
237
  'panels.market.justNow': '刚刚',
238
238
  'panels.market.minutesAgo': '{n} 分钟前',
239
239
  'panels.market.hoursAgo': '{n} 小时前',
240
- 'panels.market.add.description': '输入模块或 opencli 插件的包名、Git 仓库地址或本地目录路径。',
240
+ 'panels.market.add.description': '输入模块或 {plugin}的包名、Git 仓库地址或本地目录路径。',
241
241
  'panels.market.add.specPlaceholder': '例如 @dsh-workbench/module-hello',
242
242
  'panels.market.add.guideToggle': '模块安装引导和示例',
243
243
  'panels.market.add.guideHide': '收起引导',
@@ -277,13 +277,13 @@ export const zh = {
277
277
  'panels.market.add.problemNotFound': '未找到相关模块',
278
278
  'panels.market.add.problemNotPackage': '该路径不存在或不是有效的模块包',
279
279
  'panels.market.add.problemNotBundle':
280
- '这个包装不进这里:{reason}。这个入口按包名认工作台模块和 opencli 插件,两种都能装;但 git 地址和 tarball 判断不出它是什么 —— 要是它其实是这两样之一,请改填包名或本地目录。',
280
+ '这个包装不进这里:{reason}。这个入口按包名认工作台模块和 {plugin},两种都能装;但 git 地址和 tarball 判断不出它是什么 —— 要是它其实是这两样之一,请改填包名或本地目录。',
281
281
  'panels.market.add.problemNotWorkbenchModule': '这个包跟现在的工作台对不上,装上也用不了。换一个版本,或者找这个模块的作者。',
282
- 'panels.market.add.problemNotModuleOrPlugin': '这个包既不是工作台的模块,也不是 opencli 的插件,装了也用不上。换一个版本,或者找这个包的作者。',
283
- 'panels.market.add.failureNotModuleOrPlugin': '这个包既不是工作台的模块,也不是 opencli 的插件,装了也用不上',
284
- 'panels.market.add.installedPlugin': '装上了:opencli 插件 {name}',
282
+ 'panels.market.add.problemNotModuleOrPlugin': '这个包既不是工作台的模块,也不是 {pluginOf},装了也用不上。换一个版本,或者找这个包的作者。',
283
+ 'panels.market.add.failureNotModuleOrPlugin': '这个包既不是工作台的模块,也不是 {pluginOf},装了也用不上',
284
+ 'panels.market.add.installedPlugin': '装上了:{plugin} {name}',
285
285
  'panels.market.add.pluginPreview':
286
- '这是一份 opencli 插件:装进 opencli 的插件区,装完就能用,不用重启。',
286
+ '这是一份 {pluginThing}:装进 {pluginArea},装完就能用,不用重启。',
287
287
  'panels.market.add.pluginAlias': '插件名:{name}',
288
288
  'panels.market.add.problemNetwork': '无法连接模块源,请检查网络后重试',
289
289
  'panels.market.add.problemUnknown': '无法获取模块信息:{reason}',
@@ -374,6 +374,7 @@ export const zh = {
374
374
  'panels.discover.noSourceHint': '添加一个模块市场索引(http 地址或 git 仓库),即可在这里浏览和安装其中的模块',
375
375
  'panels.discover.sourcesFailed': '无法读取索引源',
376
376
  'panels.discover.unreadable': '无法读取此索引',
377
+ 'panels.discover.sandbox': '被系统拦住了:这个 profile 的可写根盖不住工作台的缓存目录',
377
378
  'panels.discover.sourceAuth': '这个索引源读不了:本机没有它的 git 凭据。配好凭据(或在源里改用 SSH 地址),再点右上角的刷新。',
378
379
  'panels.discover.invalid': '此索引的格式无效',
379
380
  'panels.discover.emptyRepo': '这个仓库还没有任何提交',
@@ -560,7 +561,7 @@ export const zh = {
560
561
  'blocker.forbidden.hint': '账号已登录,但没有这个项目/仓库的权限;申请之后再试。',
561
562
  'blocker.forbidden.open': '打开权限页',
562
563
  'blocker.timeout.hint': '后台浏览器没起来,重试一次通常就好。',
563
- 'blocker.exec.hint': '确认 opencli 已经装好、在终端里能直接运行(which opencli)。',
564
+ 'blocker.exec.hint': '确认运行时已经装好、在终端里能直接跑起来。',
564
565
  'blocker.unknown.title': '出了点问题',
565
566
  'panels.reading': '正在读取面板配置…',
566
567
  'panels.cardBroken': '这个模块起不来:{unit}({reason})',
@@ -570,6 +571,7 @@ export const zh = {
570
571
  'env.title': '准备工作台',
571
572
  'env.checking': '正在准备运行环境…',
572
573
  'env.installing': '正在安装后台工具,第一次会慢一点…',
574
+ 'env.installingToolchain': '正在装工作台自己那份 npm / pnpm —— 第一次要下载,慢一点正常。',
573
575
  'env.failed': '还差一步就能用了',
574
576
  'env.elapsed': '已等待 {seconds} 秒',
575
577
  'env.stepFailed.install': '装不上',
@@ -577,16 +579,11 @@ export const zh = {
577
579
  'env.stepFailed.shell': '连不上命令行',
578
580
  'env.toolchain.ok': '正常',
579
581
  'env.toolchain.warn': '还没完全准备好',
580
- 'env.opencli.ok': '已就绪',
582
+ 'env.runtime.ok': '已就绪',
581
583
  'env.bridge.ok': '已连接',
582
584
  'env.bridge.short': '还没连上',
583
585
  'env.bridge.why': '面板的数据要用你浏览器里的登录状态。这个连接没通,模块就取不到数据;不拦路:修好它,或者先进入工作台。',
584
586
  'env.bridge.hold': '浏览器还没连上 —— 按下面修好后点「重试」,也可以先进工作台。',
585
- 'env.bridge.daemon': '后台服务没起来:正常它会自己起,先在终端跑下面这条命令。',
586
- 'env.bridge.extension': '浏览器扩展没连上:确认浏览器开着、扩展已启用;没装就从商店装一次(装完回来点「重试」)。',
587
- 'env.bridge.extensionLink': '去 Chrome 应用商店装扩展',
588
- 'env.bridge.profile': '连上了多个浏览器账号,但没选默认的那个:先看有哪些(下面这条命令),再选一个。',
589
- 'env.bridge.stale': '默认的浏览器账号已经失效(它记的是上一次的扩展实例):重新选一个。',
590
587
  'env.bridge.unknown': '没认出是哪种问题:展开原文,按里面的步骤处理。',
591
588
  'env.fix.title': '怎么解决',
592
589
  'env.fix.why': '工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。',
@@ -615,11 +612,12 @@ export const zh = {
615
612
  'env.diy.continue': '先进入工作台',
616
613
  'env.copyCommand': '复制命令',
617
614
  'env.copied': '已复制',
618
- 'env.step.toolchain': '运行环境',
619
- 'env.step.opencli': '后台工具',
620
- 'env.step.bridge': '浏览器连接',
621
- 'env.step.diy': 'DIY 模式',
622
- 'env.step.warm': '站点登录状态',
615
+ 'env.step.toolchain': '检查运行环境',
616
+ 'env.step.adapter': '检查运行时',
617
+ 'env.step.runtime': '安装后台工具',
618
+ 'env.step.bridge': '连接浏览器',
619
+ 'env.step.diy': '检查 DIY 模式',
620
+ 'env.step.warm': '连上站点',
623
621
  'env.warm.done': '已就绪({n} 个站点)',
624
622
  'env.warm.short': '这次没提前连上 —— 不影响用,第一次取数会自己补',
625
623
  'env.unit.failed': '这个模块起不来',
package/src/index.ts CHANGED
@@ -42,6 +42,8 @@ export * from './contract/extension.js';
42
42
  export * from './contract/lib.js';
43
43
  export * from './contract/git.js';
44
44
  export * from './contract/command.js';
45
+ export * from './contract/runner.js';
46
+ export * from './contract/plugin-source.js';
45
47
  export * from './contract/facts.js';
46
48
  export * from './contract/long-task.js';
47
49
  export * from './contract/protocol/bundle-install.js';
@@ -57,12 +59,14 @@ export * from './contract/protocol/unit-manifests.js';
57
59
  export * from './contract/unit-board.js';
58
60
  export * from './contract/unit-declaration.js';
59
61
  export * from './contract/unit.js';
62
+ export * from './contract/capabilities.js';
60
63
  export * from './contract/needs.js';
61
64
  export * from './contract/unit-capability.js';
62
65
  export * from './contract/workbench-contract.js';
63
66
  export * from './i18n/en.js';
64
67
  export * from './i18n/index.js';
65
68
  export * from './i18n/merge.js';
69
+ export * from './i18n/runtime-terms.js';
66
70
  export * from './i18n/settings.js';
67
71
  export * from './i18n/zh.js';
68
72
  export * from './lib/blocker-action.js';
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { boardSituation, insideWorkshop, type BoardProbe } from './board-fact.js';
2
+ import { boardSituation, insideWorkshop, type BoardProbe } from '../board-fact.js';
3
3
 
4
4
  const WORKSHOP = '/w/workbench/diy';
5
5
  const FL0XIN = '/w/floxin-app';
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { holdBusy } from './busy.js';
2
+ import { holdBusy } from '../busy.js';
3
3
 
4
4
  describe('holdBusy', () => {
5
5
  it('这一轮忙刚开了头:还要按住,剩下的时长报出来(计时器按它收尾)', () => {
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { firstProblemOf, revealFirstProblem } from './form-problem.js';
2
+ import { firstProblemOf, revealFirstProblem } from '../form-problem.js';
3
3
 
4
4
  function rootWith(problem: unknown): { readonly root: ParentNode; readonly queries: string[] } {
5
5
  const queries: string[] = [];
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { gitAddressOf, gitAddressText, gitTransportCandidates } from './git-address.js';
2
+ import { gitAddressOf, gitAddressText, gitTransportCandidates } from '../git-address.js';
3
3
 
4
4
  describe('git 地址的两种读法', () => {
5
5
  it('https 原样留着,另一条推成 ssh://', () => {
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { describe, expect, it } from 'vitest';
3
- import { Fragment, h, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from './react.js';
3
+ import { Fragment, h, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from '../react.js';
4
4
 
5
5
  describe('react 入口', () => {
6
6
  it('h 就是 React.createElement(同一个引用,不是包装)', () => {
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { excerpt, parseJsonLoose } from './text.js';
2
+ import { excerpt, parseJsonLoose } from '../text.js';
3
3
 
4
4
  describe('parseJsonLoose', () => {
5
5
  it('干净 JSON 直接解析', () => {
@@ -9,7 +9,7 @@ import {
9
9
  relativeTimeCompact,
10
10
  shortenPath,
11
11
  type TimeTranslate,
12
- } from './ui.js';
12
+ } from '../ui.js';
13
13
 
14
14
  const t: TimeTranslate = (key, params) => {
15
15
  if (params === undefined) return key;
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { adapterContractGaps } from '../../host/adapter-contract.js';
3
+ import { fakeAdapterSet } from '../fake-adapter-set.js';
4
+
5
+ const ctx = { get: () => undefined } as never;
6
+
7
+ describe('假集合:证明协议是闭合的', () => {
8
+ it('一个最小的外来实现(不含任何具体运行时)也能过整份契约', () => {
9
+ expect(adapterContractGaps(fakeAdapterSet(), ctx)).toEqual([]);
10
+ });
11
+
12
+ it('它声明的能力全是 false —— 外壳不该能从它身上猜到任何具体运行时', () => {
13
+ expect(fakeAdapterSet().runtime.capabilities(ctx)).toEqual({
14
+ console: false,
15
+ pluginMarket: false,
16
+ browserBridge: false,
17
+ });
18
+ });
19
+
20
+ it('覆盖项能替换任意成员(测试就地造场景)', () => {
21
+ const set = fakeAdapterSet({ runtime: { ...fakeAdapterSet().runtime, capabilities: () => ({
22
+ console: true,
23
+ pluginMarket: false,
24
+ browserBridge: false,
25
+ }) } });
26
+ expect(set.runtime.capabilities(ctx).console).toBe(true);
27
+ });
28
+ });
@@ -0,0 +1,173 @@
1
+ import type { DataReader, DataRequest, DataResult, RecipeCalls, RecipeResults, RequestRecipe } from '../contract/data.js';
2
+ import type { AdapterSet } from '../host/adapters.js';
3
+ import type { EnvSupplyPort, ModulePort, ProbePort, ProfilePort, RuntimePort, SupplyPort } from '../host/port-types.js';
4
+ import type { HostActions } from '../host/port-types.js';
5
+ import type { PluginSurface } from '../host/port-types.js';
6
+ import { ADAPTER_SET_API_VERSION } from '../host/adapters.js';
7
+ import { readBundleManager } from '../host/bundle-manager.js';
8
+ import {
9
+ declarationGaps,
10
+ moduleDeclarationOf,
11
+ profileDirOf,
12
+ profileModules,
13
+ readInstalledModule,
14
+ readProfilePackage,
15
+ } from '../host/installed-module.js';
16
+ import { isNewerVersion } from '../host/version.js';
17
+ import { refusalReason } from '../host/spec.js';
18
+ import { declarationRefusalOf, pathDeclarationOf } from '../host/local-declaration.js';
19
+ import { createRegistryLookup } from '../host/registry-declaration.js';
20
+ import { createPackageRouter } from '../host/package-route.js';
21
+ import { createReleaseProbe } from '../host/release-probe.js';
22
+
23
+ export const FAKE_ADAPTER_MARKER = { adapterSet: 'fake' } as const;
24
+
25
+ function result<T>(): DataResult<T> {
26
+ return { ok: true, data: FAKE_ADAPTER_MARKER as unknown as T };
27
+ }
28
+
29
+ const data: DataReader = {
30
+ async read<T = unknown>(_request: DataRequest): Promise<DataResult<T>> {
31
+ return result<T>();
32
+ },
33
+ async request<T = unknown>(_recipe: RequestRecipe): Promise<DataResult<T>> {
34
+ return result<T>();
35
+ },
36
+ async requestMany<T = unknown>(_recipe: RequestRecipe, _calls: RecipeCalls): Promise<RecipeResults<T>> {
37
+ return {};
38
+ },
39
+ async submit<T = unknown>(_recipe: RequestRecipe): Promise<DataResult<T>> {
40
+ return result<T>();
41
+ },
42
+ };
43
+
44
+ const supply: EnvSupplyPort = {
45
+ resolvePluginSource: () => ({ ok: false, problem: 'not-declared' }),
46
+ libInstallCommand: () => '',
47
+ libUninstallCommand: () => '',
48
+ pluginInstallPlan: () => ({ ok: false, problem: 'not-declared' }),
49
+ latestVersion: async () => undefined,
50
+ missingReleaseParts: async () => [],
51
+ probeRelease: async () => undefined,
52
+ splitNpmSpec: () => undefined,
53
+ };
54
+
55
+ const modules: ModulePort = {
56
+ isolatedRoot: () => '/tmp/dsh-workbench-fake',
57
+ isolatedHome: () => '/tmp/dsh-workbench-fake/home',
58
+ pluginPackagePrefix: () => 'fake-plugin-',
59
+ pluginManifestFile: () => 'fake-plugin.json',
60
+ cliCatalogPath: () => '/tmp/dsh-workbench-fake/catalog.json',
61
+ vendorPluginsDir: () => '/tmp/dsh-workbench-fake/plugins',
62
+ runtimeInstallCommand: () => 'npm i -g fake-runtime',
63
+ afterLibInstall: () => undefined,
64
+ profileDirOf: (ctx) => profileDirOf(ctx),
65
+ profileModules,
66
+ readInstalledModule,
67
+ readProfilePackage,
68
+ readBundleManager,
69
+ createRegistryNotebook: () => ({}) as never,
70
+ declarationGaps,
71
+ moduleDeclarationOf,
72
+ registryDeclarationOf: async () => undefined,
73
+ pathDeclarationOf,
74
+ declarationRefusalOf,
75
+ refusalReason,
76
+ packageRouteOf: async () => undefined,
77
+ isNewerVersion,
78
+ startSelfUpdate: () => ({}) as never,
79
+ };
80
+
81
+ const profile: ProfilePort = {
82
+ dirOf: () => null,
83
+ dshPlugins: () => () => ({ ok: true, plugins: [] }),
84
+ selfUpdateView: () => undefined,
85
+ };
86
+
87
+ const probe: ProbePort = {
88
+ probeUnits: async () => [],
89
+ registerPreflight: () => undefined,
90
+ declaredPluginCommands: () => new Map(),
91
+ };
92
+
93
+ const runtimePreset = (capabilities: RuntimePort['capabilities'] extends never ? never : ReturnType<RuntimePort['capabilities']>): RuntimePort => ({
94
+ packageRoot: () => '/tmp/dsh-workbench-fake',
95
+ capabilities: () => capabilities,
96
+ profile: () => ({
97
+ label: 'fake',
98
+ terms: {
99
+ plugin: { zh: '插件', en: 'plugin' },
100
+ pluginOf: { zh: '的插件', en: 'a plugin of' },
101
+ pluginThing: { zh: '插件', en: 'a plugin' },
102
+ pluginArea: { zh: '插件区', en: 'the plugin area' },
103
+ },
104
+ installHint: { zh: '无', en: 'nothing to install' },
105
+ diagnose: {},
106
+ }),
107
+ commandSurface: () => ({
108
+ name: 'fake',
109
+ pluginPrefix: 'fake-plugin-',
110
+ invoke: (site: string, command?: string) => (command === undefined ? `fake ${site}` : `fake ${site} ${command}`),
111
+ help: (site: string) => `fake ${site} --help`,
112
+ browser: (verb: readonly string[]) => `fake browser ${verb.join(' ')}`,
113
+ }),
114
+ commands: () => ({}),
115
+ runners: () => ({}),
116
+ health: () => ({}),
117
+ seed: () => undefined,
118
+ warnUnwritableRoot: () => undefined,
119
+ });
120
+
121
+ const plugins: PluginSurface = {
122
+ declarationLookup: () => () => undefined,
123
+ createUnits: () => ({
124
+ refresh: async () => ({ units: [] }),
125
+ touch: () => undefined,
126
+ report: () => ({ units: [] }),
127
+ dispose: () => undefined,
128
+ }),
129
+ };
130
+
131
+ const actions: HostActions = {
132
+ configSyncHandler: () => (async () => ({ ok: true })) as never,
133
+ profileCreateHandler: () => (async () => ({ ok: true })) as never,
134
+ configSyncAction: () => ({}) as never,
135
+ profileCreateAction: () => ({}) as never,
136
+ };
137
+
138
+ export function fakeAdapterSet(overrides: Partial<AdapterSet> = {}): AdapterSet {
139
+ const release = createReleaseProbe();
140
+ const registry = createRegistryLookup();
141
+ const router = createPackageRouter({ manifestFile: 'fake-plugin.json', dshLookup: registry.registryDshOf });
142
+ const withRelease: EnvSupplyPort = {
143
+ ...supply,
144
+ latestVersion: release.latestVersion,
145
+ missingReleaseParts: release.missingReleaseParts,
146
+ probeRelease: release.probeRelease,
147
+ };
148
+ return {
149
+ apiVersion: ADAPTER_SET_API_VERSION,
150
+ id: 'fake-adapter-set',
151
+ version: '0.0.0',
152
+ data,
153
+ supply: {
154
+ ...withRelease,
155
+ ...modules,
156
+ env: withRelease,
157
+ modules,
158
+ registryDeclarationOf: registry.registryDeclarationOf,
159
+ packageRouteOf: router.packageRouteOf,
160
+ } as SupplyPort,
161
+ modules,
162
+ profile,
163
+ probe,
164
+ runtime: runtimePreset({
165
+ console: false,
166
+ pluginMarket: false,
167
+ browserBridge: false,
168
+ }),
169
+ plugins,
170
+ actions,
171
+ ...overrides,
172
+ };
173
+ }
@@ -21,7 +21,7 @@ export const fakeNpmSource: SupplySource = {
21
21
  export function extensionNeedOf(name: string, extra: Partial<ExtensionNeed> = {}): ExtensionNeed {
22
22
  return {
23
23
  kind: 'extension',
24
- runtime: 'opencli',
24
+ runtime: 'fake-runtime',
25
25
  name,
26
26
  commands: [`${name}-read`],
27
27
  purpose: '测试',
package/src/testing.ts CHANGED
@@ -2,3 +2,4 @@ export * from './testing/host-fakes.js';
2
2
  export * from './testing/declaration.js';
3
3
  export * from './testing/needs.js';
4
4
  export * from './testing/data.js';
5
+ export * from './testing/fake-adapter-set.js';
@@ -1,16 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { commandNamesMatch } from '../command-name.js';
3
-
4
- describe('commandNamesMatch:声明的命令名与解析出来的命令路径', () => {
5
- it('缺省 opencli 不管写成名字还是绝对路径都算同一个', () => {
6
- expect(commandNamesMatch('opencli', '/Users/me/.dsh/workbench/opencli/bin/opencli')).toBe(true);
7
- expect(commandNamesMatch('opencli.cmd', 'C:\\dsh\\opencli.cmd')).toBe(true);
8
- expect(commandNamesMatch('opencli.exe', 'C:\\dsh\\opencli.exe')).toBe(true);
9
- expect(commandNamesMatch('gitops', '/usr/local/bin/gitops')).toBe(true);
10
- });
11
-
12
- it('不同的命令不算同一个', () => {
13
- expect(commandNamesMatch('gitops', '/usr/local/bin/opencli')).toBe(false);
14
- expect(commandNamesMatch('', 'opencli')).toBe(false);
15
- });
16
- });