@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,135 +0,0 @@
1
- /**
2
- * 录制交接的三个相位:`armed` 等用户在外站页面上动手,`recording` 正在录,`finished` 录完待取。
3
- */
4
- export type RecordPhase = 'armed' | 'recording' | 'finished';
5
- /**
6
- * 录制约定的有效期(15 分钟,毫秒):超过它没动静的约定算过期、当场让人。
7
- */
8
- export declare const RECORD_STALE_MS: number;
9
- /**
10
- * 这次录制要找的那一次写:HTTP 方法 + URL 里必须含的一段(不填就是只认方法)。
11
- */
12
- export interface RecordExpect {
13
- readonly method: string;
14
- readonly urlContains: string;
15
- }
16
- /**
17
- * 一次「截图」在宿主台账里的那一行:页面上的计数、落图那一刻、落盘路径;没落下来时带 `error` 原文(落成的那条没有它)。
18
- */
19
- export interface RecordShot {
20
- readonly n: number;
21
- readonly at: number;
22
- readonly path: string;
23
- readonly error?: string;
24
- }
25
- /**
26
- * 某个页面计数已经试过几次:初拍算一次,失败再试一次;计数一换就从头数。
27
- */
28
- export interface RecordShotTries {
29
- readonly n: number;
30
- readonly tries: number;
31
- }
32
- /**
33
- * 一张图最多试几次(初拍 + 一次重试):失败如实报过就停,不每拍重试到底。
34
- */
35
- export declare const RECORD_SHOT_TRIES = 2;
36
- /**
37
- * 一份活着的录制约定:相位 + 谁的会话 + 哪个工作区 / 单元 + 页面 URL 与标题 + 要找的那一次写 +
38
- * 落盘文件 + 三个时间戳,以及两份台账:按计数落图的 `shots`(`shotsSeen` 只记落成的那个计数)
39
- * 与门铃的 `beats` / `beatMs`(命中几次、最近一次等了多久)。
40
- */
41
- export interface RecordState {
42
- readonly phase: RecordPhase;
43
- readonly sessionId: string;
44
- readonly workspace: string;
45
- readonly unit: string;
46
- readonly name: string;
47
- readonly url: string;
48
- readonly title: string;
49
- readonly action: string;
50
- readonly expect: RecordExpect | null;
51
- readonly captureFile: string;
52
- readonly startedAt: number;
53
- readonly t0: number | null;
54
- readonly t1: number | null;
55
- readonly shots: readonly RecordShot[];
56
- readonly shotsSeen: number;
57
- readonly shotTries: RecordShotTries | null;
58
- readonly beats: number;
59
- readonly beatMs: number;
60
- readonly at: number;
61
- }
62
- /**
63
- * 开一次录制要交的那几件:会话、工作区、单元、名字、页面 URL 与标题、动作名、期望、落盘文件,以及此刻时间。
64
- */
65
- export interface RecordPact {
66
- readonly sessionId: string;
67
- readonly workspace: string;
68
- readonly unit: string;
69
- readonly name: string;
70
- readonly url: string;
71
- readonly title: string;
72
- readonly action: string;
73
- readonly expect: RecordExpect | null;
74
- readonly captureFile: string;
75
- readonly now: number;
76
- }
77
- /**
78
- * 录制被拒的原因码:自己已持有 / 别人持着 / 不是持有者 / 没有约定 / 已在录 / 还没 arm / 不在录 / 还没录完。
79
- */
80
- export type RecordRefusal = 'already-held' | 'held-by-other' | 'not-owner' | 'none' | 'already-recording' | 'not-armed' | 'not-recording' | 'not-finished';
81
- /**
82
- * 一次录制动作的结果:成功带新状态,失败带拒绝码。
83
- */
84
- export type RecordMove = {
85
- readonly ok: true;
86
- readonly state: RecordState;
87
- } | {
88
- readonly ok: false;
89
- readonly code: RecordRefusal;
90
- };
91
- /**
92
- * 录制约定收得下的三个人话动作:看看进度 / 停手 / 结束并取回。
93
- */
94
- export type RecordIntent = 'peek' | 'halt' | 'stop';
95
- /**
96
- * 把工具入参收成人话动作。
97
- * @param raw - 任意入参值。
98
- * @returns `'peek'` / `'halt'` / `'stop'` 原样;别的值(含 `undefined`、多余空白)给 `null`,由调用方拒。
99
- */
100
- export declare function parseRecordIntent(raw: unknown): RecordIntent | null;
101
- /**
102
- * 录制约定的存取口(外壳持有一份):相位随 `begin → started → finished` 推进,`release` 是收尾时放掉浏览器那一跳。
103
- */
104
- export interface RecordStore {
105
- readonly release?: ((state: RecordState) => Promise<{
106
- readonly tab: boolean;
107
- readonly capture: boolean;
108
- }>) | undefined;
109
- live(now: number): RecordState | null;
110
- begin(pact: RecordPact): RecordMove;
111
- started(sessionId: string, at: number, now: number): RecordMove;
112
- finished(sessionId: string, at: number, now: number): RecordMove;
113
- shotTaken(sessionId: string, shot: RecordShot, now: number): RecordMove;
114
- shotFailed(sessionId: string, shot: RecordShot, now: number): RecordMove;
115
- beat(sessionId: string, ms: number, now: number): RecordMove;
116
- stop(sessionId: string, now: number): RecordMove;
117
- }
118
- /**
119
- * 这一拍该不该落图:页面计数涨过 `shotsSeen` 才算;同一个计数已经试满就先放下,等他自己再按。
120
- * @param state - 当前有效的那份约定。
121
- * @param pageShots - 页面浮条上那个「已拍」计数。
122
- * @returns 该落的那个计数;不该落给 `null`(没涨 / 试满了 / 不是个正经数)。
123
- */
124
- export declare function shotDueOf(state: RecordState, pageShots: number): number | null;
125
- /**
126
- * 造一份新的录制约定存储(进程内存,同一时刻只可能有一份有效约定)。
127
- * @returns 存取口;动作成不成都在返回的 `RecordMove` 里,不抛异常。
128
- */
129
- export declare function createRecordStore(): RecordStore;
130
- /**
131
- * 「谁还占着、在录哪个动作」的一句话,用于别人来抢时说清现况。
132
- * @param state - 当前有效的那份约定。
133
- * @returns 形如「会话 x(自 HH:mm:ssZ 起在录 y 的「动作」)」的中文串。
134
- */
135
- export declare function recordOwnerText(state: RecordState): string;
@@ -1,162 +0,0 @@
1
- /**
2
- * 录制约定的有效期(15 分钟,毫秒):超过它没动静的约定算过期、当场让人。
3
- */
4
- export const RECORD_STALE_MS = 15 * 60 * 1000;
5
- /**
6
- * 一张图最多试几次(初拍 + 一次重试):失败如实报过就停,不每拍重试到底。
7
- */
8
- export const RECORD_SHOT_TRIES = 2;
9
- /**
10
- * 把工具入参收成人话动作。
11
- * @param raw - 任意入参值。
12
- * @returns `'peek'` / `'halt'` / `'stop'` 原样;别的值(含 `undefined`、多余空白)给 `null`,由调用方拒。
13
- */
14
- export function parseRecordIntent(raw) {
15
- return raw === 'peek' || raw === 'halt' || raw === 'stop' ? raw : null;
16
- }
17
- /**
18
- * 这一拍该不该落图:页面计数涨过 `shotsSeen` 才算;同一个计数已经试满就先放下,等他自己再按。
19
- * @param state - 当前有效的那份约定。
20
- * @param pageShots - 页面浮条上那个「已拍」计数。
21
- * @returns 该落的那个计数;不该落给 `null`(没涨 / 试满了 / 不是个正经数)。
22
- */
23
- export function shotDueOf(state, pageShots) {
24
- if (!Number.isFinite(pageShots))
25
- return null;
26
- const n = Math.floor(pageShots);
27
- if (n <= state.shotsSeen)
28
- return null;
29
- if (state.shotTries !== null && state.shotTries.n === n && state.shotTries.tries >= RECORD_SHOT_TRIES)
30
- return null;
31
- return n;
32
- }
33
- function alive(state, now) {
34
- if (state === null)
35
- return null;
36
- return now - state.at <= RECORD_STALE_MS ? state : null;
37
- }
38
- function ownerOf(state, sessionId, now) {
39
- const held = alive(state, now);
40
- if (held === null)
41
- return 'none';
42
- return held.sessionId === sessionId ? held : 'not-owner';
43
- }
44
- /**
45
- * 造一份新的录制约定存储(进程内存,同一时刻只可能有一份有效约定)。
46
- * @returns 存取口;动作成不成都在返回的 `RecordMove` 里,不抛异常。
47
- */
48
- export function createRecordStore() {
49
- let held = null;
50
- const live = (now) => alive(held, now);
51
- const withShot = (found, shot, now, error) => {
52
- const row = error === undefined ? shot : { n: shot.n, at: shot.at, path: shot.path, error };
53
- const kept = found.shots.filter((one) => one.n !== shot.n);
54
- const tries = found.shotTries !== null && found.shotTries.n === shot.n ? found.shotTries.tries : 0;
55
- return {
56
- ...found,
57
- shots: [...kept, row].sort((one, two) => one.n - two.n),
58
- shotsSeen: error === undefined ? Math.max(found.shotsSeen, shot.n) : found.shotsSeen,
59
- shotTries: error === undefined ? null : { n: shot.n, tries: tries + 1 },
60
- at: now,
61
- };
62
- };
63
- return {
64
- live,
65
- begin(pact) {
66
- const current = alive(held, pact.now);
67
- if (current !== null) {
68
- return { ok: false, code: current.sessionId === pact.sessionId ? 'already-held' : 'held-by-other' };
69
- }
70
- const state = {
71
- phase: 'armed',
72
- sessionId: pact.sessionId,
73
- workspace: pact.workspace,
74
- unit: pact.unit,
75
- name: pact.name,
76
- url: pact.url,
77
- title: pact.title,
78
- action: pact.action,
79
- expect: pact.expect,
80
- captureFile: pact.captureFile,
81
- startedAt: pact.now,
82
- t0: null,
83
- t1: null,
84
- shots: [],
85
- shotsSeen: 0,
86
- shotTries: null,
87
- beats: 0,
88
- beatMs: 0,
89
- at: pact.now,
90
- };
91
- held = state;
92
- return { ok: true, state };
93
- },
94
- started(sessionId, at, now) {
95
- const found = ownerOf(held, sessionId, now);
96
- if (typeof found === 'string')
97
- return { ok: false, code: found };
98
- if (found.phase === 'recording')
99
- return { ok: false, code: 'already-recording' };
100
- if (found.phase !== 'armed')
101
- return { ok: false, code: 'not-armed' };
102
- const state = { ...found, phase: 'recording', t0: at, at: now };
103
- held = state;
104
- return { ok: true, state };
105
- },
106
- finished(sessionId, at, now) {
107
- const found = ownerOf(held, sessionId, now);
108
- if (typeof found === 'string')
109
- return { ok: false, code: found };
110
- if (found.phase !== 'recording')
111
- return { ok: false, code: 'not-recording' };
112
- const state = { ...found, phase: 'finished', t1: at, at: now };
113
- held = state;
114
- return { ok: true, state };
115
- },
116
- shotTaken(sessionId, shot, now) {
117
- const found = ownerOf(held, sessionId, now);
118
- if (typeof found === 'string')
119
- return { ok: false, code: found };
120
- const state = withShot(found, shot, now, undefined);
121
- held = state;
122
- return { ok: true, state };
123
- },
124
- shotFailed(sessionId, shot, now) {
125
- const found = ownerOf(held, sessionId, now);
126
- if (typeof found === 'string')
127
- return { ok: false, code: found };
128
- const state = withShot(found, shot, now, shot.error === undefined ? '落图失败' : shot.error);
129
- held = state;
130
- return { ok: true, state };
131
- },
132
- beat(sessionId, ms, now) {
133
- const found = ownerOf(held, sessionId, now);
134
- if (typeof found === 'string')
135
- return { ok: false, code: found };
136
- const state = {
137
- ...found,
138
- beats: found.beats + 1,
139
- beatMs: Math.max(0, Math.floor(ms)),
140
- at: now,
141
- };
142
- held = state;
143
- return { ok: true, state };
144
- },
145
- stop(sessionId, now) {
146
- const found = ownerOf(held, sessionId, now);
147
- if (typeof found === 'string')
148
- return { ok: false, code: found };
149
- held = null;
150
- return { ok: true, state: found };
151
- },
152
- };
153
- }
154
- /**
155
- * 「谁还占着、在录哪个动作」的一句话,用于别人来抢时说清现况。
156
- * @param state - 当前有效的那份约定。
157
- * @returns 形如「会话 x(自 HH:mm:ssZ 起在录 y 的「动作」)」的中文串。
158
- */
159
- export function recordOwnerText(state) {
160
- const at = new Date(state.startedAt).toISOString().slice(11, 19);
161
- return `会话 ${state.sessionId}(自 ${at}Z 起在录 ${state.unit} 的「${state.action}」)`;
162
- }
@@ -1 +0,0 @@
1
- export declare function useLintProbe(): number;
@@ -1,6 +0,0 @@
1
- import { useRef } from './react';
2
- export function useLintProbe() {
3
- const probeRef = useRef(0);
4
- probeRef.current = 1;
5
- return probeRef.current;
6
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * 一张面板卡片取数走到哪一步:`idle` 还没取、`loading` 取着、`ready` 拿到了、`error` 失败了。
3
- */
4
- export type PanelCardPhase = 'idle' | 'loading' | 'ready' | 'error';
5
- /**
6
- * 一次取数失败:机器码 + 给人看的一句话。
7
- */
8
- export interface PanelCardError {
9
- readonly code: string;
10
- readonly message: string;
11
- }
12
- /**
13
- * 一张卡片最近一次取数的读数:哪个单元、哪条路由、什么相位、什么时候、失败原因。
14
- */
15
- export interface PanelCardRead {
16
- readonly unit: string;
17
- readonly route: string;
18
- readonly phase: PanelCardPhase;
19
- readonly at: number;
20
- readonly error?: PanelCardError;
21
- }
22
- /**
23
- * 一张卡片崩了的读数:单元、原因、时间,以及同一原因连着崩了几次(窗口见 `PANEL_STATE_CRASH_WINDOW_MS`)。
24
- */
25
- export interface PanelCardCrash {
26
- readonly unit: string;
27
- readonly reason: string;
28
- readonly at: number;
29
- readonly count: number;
30
- }
31
- /**
32
- * 一个单元此刻的读数:它的卡片、最近一次读成的时间(`okAt`,没成过给 `null`),以及崩了的那一条。
33
- */
34
- export interface PanelUnitReport {
35
- readonly unit: string;
36
- readonly at: number;
37
- readonly okAt: number | null;
38
- readonly cards: readonly PanelCardRead[];
39
- readonly crash?: PanelCardCrash;
40
- }
41
- /**
42
- * 一个工作区此刻的全量读数(面板按工作区存):所有单元的读数 + 整块最近动过的时间。
43
- */
44
- export interface PanelWorkspaceReport {
45
- readonly workspace: string | null;
46
- readonly at: number;
47
- readonly units: readonly PanelUnitReport[];
48
- }
49
- /**
50
- * 客户端往上报的一批卡片读数(`POST` 请求体的形状)。
51
- */
52
- export interface PanelCardsReport {
53
- readonly workspace: string;
54
- readonly cards: readonly PanelCardRead[];
55
- }
56
- /**
57
- * 客户端往上报的一次卡片崩溃(`POST` 请求体的形状)。
58
- */
59
- export interface PanelCrashReport {
60
- readonly workspace: string;
61
- readonly unit: string;
62
- readonly reason: string;
63
- readonly at: number;
64
- }
65
- /**
66
- * 面板运行态的留存口(宿主持有一份):收卡片读数与崩溃,按工作区取快照。
67
- */
68
- export interface PanelStateStore {
69
- cards(report: PanelCardsReport): void;
70
- crash(report: PanelCrashReport): void;
71
- snapshot(workspace: string | null): PanelWorkspaceReport;
72
- }
73
- /**
74
- * 留存的工作区上限(LRU,满 64 个丢最旧的)。
75
- */
76
- export declare const PANEL_STATE_MAX_UNITS = 64;
77
- /**
78
- * 每个单元留存的卡片上限(按路由 LRU,满 12 张丢最旧的)。
79
- */
80
- export declare const PANEL_STATE_MAX_CARDS = 12;
81
- /**
82
- * 一次上报最多读入的卡片条数(32 条之后的丢掉)。
83
- */
84
- export declare const PANEL_STATE_MAX_REPORTS = 32;
85
- /**
86
- * 同一原因的连续崩溃算进同一次计数的窗口(10 分钟,毫秒)。
87
- */
88
- export declare const PANEL_STATE_CRASH_WINDOW_MS = 600000;
89
- /**
90
- * 上报文本字段的截断长度(2000 字符;workspace / reason / message 共用)。
91
- */
92
- export declare const PANEL_STATE_MAX_TEXT = 2000;
93
- /**
94
- * 上报解析的结果:`ok: true` 带收好的值,`ok: false` 带一句中文原因(直接回给上报方)。
95
- */
96
- export type PanelParse<T> = {
97
- readonly ok: true;
98
- readonly value: T;
99
- } | {
100
- readonly ok: false;
101
- readonly message: string;
102
- };
103
- /**
104
- * 收一批卡片读数上报。
105
- * @param payload - `POST` 的请求体。
106
- * @returns 至少收到一条能认的卡片才 `ok: true`;请求体不是对象、`workspace` 为空、`cards` 不是数组,
107
- * 或一条都认不出(`unit` / `route` / `phase` / `at` 缺一)时 `ok: false` + 中文原因;认不出的单条静默跳过。
108
- */
109
- export declare function parseCardsReport(payload: unknown): PanelParse<PanelCardsReport>;
110
- /**
111
- * 收一次卡片崩溃上报。
112
- * @param payload - `POST` 的请求体。
113
- * @returns `workspace` / `unit` / `reason` 都不能空,缺一给 `ok: false` + 中文原因;`at` 缺省或不合法时取当前时间。
114
- */
115
- export declare function parseCrashReport(payload: unknown): PanelParse<PanelCrashReport>;
116
- /**
117
- * 造一份面板运行态的留存(进程内存、按工作区分桶,带上面那几条上限的 LRU)。
118
- * @returns 留存口:`cards` / `crash` 收上报,`snapshot(workspace)` 取全量;没存过的工作区(含 `null`)给一份空的。
119
- */
120
- export declare function createPanelStateStore(): PanelStateStore;
@@ -1,176 +0,0 @@
1
- /**
2
- * 留存的工作区上限(LRU,满 64 个丢最旧的)。
3
- */
4
- export const PANEL_STATE_MAX_UNITS = 64;
5
- /**
6
- * 每个单元留存的卡片上限(按路由 LRU,满 12 张丢最旧的)。
7
- */
8
- export const PANEL_STATE_MAX_CARDS = 12;
9
- /**
10
- * 一次上报最多读入的卡片条数(32 条之后的丢掉)。
11
- */
12
- export const PANEL_STATE_MAX_REPORTS = 32;
13
- /**
14
- * 同一原因的连续崩溃算进同一次计数的窗口(10 分钟,毫秒)。
15
- */
16
- export const PANEL_STATE_CRASH_WINDOW_MS = 600000;
17
- /**
18
- * 上报文本字段的截断长度(2000 字符;workspace / reason / message 共用)。
19
- */
20
- export const PANEL_STATE_MAX_TEXT = 2000;
21
- const PHASES = ['idle', 'loading', 'ready', 'error'];
22
- function asRecord(value) {
23
- return typeof value === 'object' && value !== null ? value : undefined;
24
- }
25
- function textOf(value, max) {
26
- if (typeof value !== 'string')
27
- return '';
28
- const trimmed = value.trim();
29
- return trimmed.length > max ? trimmed.slice(0, max) : trimmed;
30
- }
31
- function atOf(value) {
32
- if (typeof value !== 'number' || !Number.isFinite(value))
33
- return null;
34
- if (value < 0)
35
- return null;
36
- return Math.trunc(value);
37
- }
38
- function errorOf(raw) {
39
- const record = asRecord(raw);
40
- if (record === undefined)
41
- return undefined;
42
- const code = textOf(record['code'], 120);
43
- const message = textOf(record['message'], PANEL_STATE_MAX_TEXT);
44
- if (code === '' && message === '')
45
- return undefined;
46
- return { code: code === '' ? 'unknown' : code, message };
47
- }
48
- /**
49
- * 收一批卡片读数上报。
50
- * @param payload - `POST` 的请求体。
51
- * @returns 至少收到一条能认的卡片才 `ok: true`;请求体不是对象、`workspace` 为空、`cards` 不是数组,
52
- * 或一条都认不出(`unit` / `route` / `phase` / `at` 缺一)时 `ok: false` + 中文原因;认不出的单条静默跳过。
53
- */
54
- export function parseCardsReport(payload) {
55
- const record = asRecord(payload);
56
- if (record === undefined)
57
- return { ok: false, message: '请求体要是一个对象' };
58
- const workspace = textOf(record['workspace'], PANEL_STATE_MAX_TEXT);
59
- if (workspace === '')
60
- return { ok: false, message: 'workspace 不能是空的 —— 面板按工作区存' };
61
- const raw = record['cards'];
62
- if (!Array.isArray(raw))
63
- return { ok: false, message: 'cards 要是一个数组' };
64
- const cards = [];
65
- for (const item of raw.slice(0, PANEL_STATE_MAX_REPORTS)) {
66
- const card = asRecord(item);
67
- if (card === undefined)
68
- continue;
69
- const unit = textOf(card['unit'], 200);
70
- const route = textOf(card['route'], 400);
71
- const phase = textOf(card['phase'], 20);
72
- const at = atOf(card['at']);
73
- if (unit === '' || route === '' || at === null || !PHASES.includes(phase))
74
- continue;
75
- const error = errorOf(card['error']);
76
- cards.push({ unit, route, phase, at, ...(error === undefined ? {} : { error }) });
77
- }
78
- if (cards.length === 0)
79
- return { ok: false, message: 'cards 里没有一条能认的(unit / route / phase / at 都要有)' };
80
- return { ok: true, value: { workspace, cards } };
81
- }
82
- /**
83
- * 收一次卡片崩溃上报。
84
- * @param payload - `POST` 的请求体。
85
- * @returns `workspace` / `unit` / `reason` 都不能空,缺一给 `ok: false` + 中文原因;`at` 缺省或不合法时取当前时间。
86
- */
87
- export function parseCrashReport(payload) {
88
- const record = asRecord(payload);
89
- if (record === undefined)
90
- return { ok: false, message: '请求体要是一个对象' };
91
- const workspace = textOf(record['workspace'], PANEL_STATE_MAX_TEXT);
92
- const unit = textOf(record['unit'], 200);
93
- const reason = textOf(record['reason'], PANEL_STATE_MAX_TEXT);
94
- if (workspace === '')
95
- return { ok: false, message: 'workspace 不能是空的' };
96
- if (unit === '')
97
- return { ok: false, message: 'unit 不能是空的' };
98
- if (reason === '')
99
- return { ok: false, message: 'reason 不能是空的(没有原因的崩溃没法查)' };
100
- return { ok: true, value: { workspace, unit, reason, at: atOf(record['at']) ?? Date.now() } };
101
- }
102
- /**
103
- * 造一份面板运行态的留存(进程内存、按工作区分桶,带上面那几条上限的 LRU)。
104
- * @returns 留存口:`cards` / `crash` 收上报,`snapshot(workspace)` 取全量;没存过的工作区(含 `null`)给一份空的。
105
- */
106
- export function createPanelStateStore() {
107
- const workspaces = new Map();
108
- function trim(entry, max) {
109
- while (entry.size > max) {
110
- const oldest = entry.keys().next();
111
- if (oldest.done === true)
112
- return;
113
- entry.delete(oldest.value);
114
- }
115
- }
116
- function workspaceEntryOf(workspace) {
117
- const existing = workspaces.get(workspace);
118
- if (existing !== undefined)
119
- return existing;
120
- const created = { at: 0, units: new Map() };
121
- workspaces.set(workspace, created);
122
- trim(workspaces, PANEL_STATE_MAX_UNITS);
123
- return created;
124
- }
125
- function unitEntryOf(entry, unit) {
126
- const existing = entry.units.get(unit);
127
- if (existing !== undefined)
128
- return existing;
129
- const created = { at: 0, cards: new Map() };
130
- entry.units.set(unit, created);
131
- return created;
132
- }
133
- return {
134
- cards(report) {
135
- const entry = workspaceEntryOf(report.workspace);
136
- for (const card of report.cards) {
137
- const unit = unitEntryOf(entry, card.unit);
138
- unit.cards.delete(card.route);
139
- unit.cards.set(card.route, card);
140
- trim(unit.cards, PANEL_STATE_MAX_CARDS);
141
- if (card.at > unit.at)
142
- unit.at = card.at;
143
- if (card.at > entry.at)
144
- entry.at = card.at;
145
- }
146
- },
147
- crash(report) {
148
- const entry = workspaceEntryOf(report.workspace);
149
- const unit = unitEntryOf(entry, report.unit);
150
- const previous = unit.crash;
151
- const counted = previous !== undefined &&
152
- previous.reason === report.reason &&
153
- report.at >= previous.at &&
154
- report.at - previous.at <= PANEL_STATE_CRASH_WINDOW_MS;
155
- unit.crash = { unit: report.unit, reason: report.reason, at: report.at, count: counted ? previous.count + 1 : 1 };
156
- if (report.at > unit.at)
157
- unit.at = report.at;
158
- if (report.at > entry.at)
159
- entry.at = report.at;
160
- },
161
- snapshot(workspace) {
162
- if (workspace === null)
163
- return { workspace: null, at: 0, units: [] };
164
- const entry = workspaces.get(workspace);
165
- if (entry === undefined)
166
- return { workspace, at: 0, units: [] };
167
- const units = [...entry.units.entries()].map(([unit, one]) => {
168
- const cards = [...one.cards.values()].sort((a, b) => a.route.localeCompare(b.route));
169
- const okAt = cards.reduce((best, card) => (card.phase === 'ready' && (best === null || card.at > best) ? card.at : best), null);
170
- return { unit, at: one.at, okAt, cards, ...(one.crash === undefined ? {} : { crash: one.crash }) };
171
- });
172
- units.sort((a, b) => b.at - a.at || a.unit.localeCompare(b.unit));
173
- return { workspace, at: entry.at, units };
174
- },
175
- };
176
- }
@@ -1,38 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { hasEnvSupply, type UnitManifest } from '../unit.js';
3
-
4
- function manifest(env?: UnitManifest['env']): UnitManifest {
5
- return {
6
- id: 'issues',
7
- card: { titleKey: 'issues.mine', order: 10 },
8
- tools: [],
9
- host: { inject: [] },
10
- ...(env === undefined ? {} : { env }),
11
- };
12
- }
13
-
14
- describe('hasEnvSupply(缺来源时那条回退口径,宿主与浏览器共用一份)', () => {
15
- it('声明了插件或库 → 有供给', () => {
16
- expect(hasEnvSupply(manifest({ plugins: [{ name: 'coding', commands: ['x'] }] }))).toBe(true);
17
- expect(
18
- hasEnvSupply(
19
- manifest({
20
- libs: [
21
- {
22
- name: 'opencli-workflow',
23
- registryEnv: 'WB_NPM',
24
- registryDefault: 'https://registry.example/',
25
- purpose: '夹具',
26
- },
27
- ],
28
- }),
29
- ),
30
- ).toBe(true);
31
- });
32
-
33
- it('★ 只有基座命令(无卡片模块那种)不算供给 —— 它不是市场门槛,只是缺来源时的回退', () => {
34
- expect(hasEnvSupply(manifest({ command: 'gitops' }))).toBe(false);
35
- expect(hasEnvSupply(manifest({ plugins: [], libs: [] }))).toBe(false);
36
- expect(hasEnvSupply(manifest())).toBe(false);
37
- });
38
- });