runwork 0.15.0 → 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/dist/index.js +19272 -116
  2. package/package.json +4 -4
  3. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  4. package/dist/__tests__/curl-parser.test.js +0 -250
  5. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  6. package/dist/__tests__/install-scripts.test.js +0 -280
  7. package/dist/__tests__/types-manager.test.d.ts +0 -1
  8. package/dist/__tests__/types-manager.test.js +0 -89
  9. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  10. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  11. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  12. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -97
  13. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  14. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  15. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  16. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  17. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  18. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  19. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  21. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  23. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  25. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  26. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  27. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  28. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  29. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  31. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  32. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  33. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  34. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  35. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  36. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  37. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  38. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  39. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  40. package/dist/agents/__tests__/detection.test.js +0 -89
  41. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  42. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  43. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  44. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  45. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  46. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  47. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  48. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  49. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  50. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  51. package/dist/agents/claude-code.d.ts +0 -53
  52. package/dist/agents/claude-code.js +0 -754
  53. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  54. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  55. package/dist/agents/claude-desktop.d.ts +0 -47
  56. package/dist/agents/claude-desktop.js +0 -684
  57. package/dist/agents/cline.d.ts +0 -15
  58. package/dist/agents/cline.js +0 -130
  59. package/dist/agents/codex.d.ts +0 -44
  60. package/dist/agents/codex.js +0 -453
  61. package/dist/agents/conversation-skills.d.ts +0 -18
  62. package/dist/agents/conversation-skills.js +0 -229
  63. package/dist/agents/cursor.d.ts +0 -48
  64. package/dist/agents/cursor.js +0 -324
  65. package/dist/agents/default-config.d.ts +0 -30
  66. package/dist/agents/default-config.js +0 -67
  67. package/dist/agents/defaults-merge.d.ts +0 -72
  68. package/dist/agents/defaults-merge.js +0 -131
  69. package/dist/agents/detect.d.ts +0 -4
  70. package/dist/agents/detect.js +0 -67
  71. package/dist/agents/detection.d.ts +0 -18
  72. package/dist/agents/detection.js +0 -94
  73. package/dist/agents/gemini.d.ts +0 -15
  74. package/dist/agents/gemini.js +0 -122
  75. package/dist/agents/generic-adapter.d.ts +0 -25
  76. package/dist/agents/generic-adapter.js +0 -151
  77. package/dist/agents/intro-skill.d.ts +0 -45
  78. package/dist/agents/intro-skill.js +0 -447
  79. package/dist/agents/registry-data.d.ts +0 -192
  80. package/dist/agents/registry-data.js +0 -669
  81. package/dist/agents/registry.d.ts +0 -13
  82. package/dist/agents/registry.js +0 -36
  83. package/dist/agents/runtime-detection.d.ts +0 -82
  84. package/dist/agents/runtime-detection.js +0 -271
  85. package/dist/agents/session-start-hook.d.ts +0 -37
  86. package/dist/agents/session-start-hook.js +0 -159
  87. package/dist/agents/types.d.ts +0 -171
  88. package/dist/agents/types.js +0 -75
  89. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  90. package/dist/agents/utils/instruction-hint.js +0 -108
  91. package/dist/agents/utils/json-config.d.ts +0 -19
  92. package/dist/agents/utils/json-config.js +0 -69
  93. package/dist/agents/utils/toml-config.d.ts +0 -8
  94. package/dist/agents/utils/toml-config.js +0 -27
  95. package/dist/agents/windsurf.d.ts +0 -14
  96. package/dist/agents/windsurf.js +0 -102
  97. package/dist/api/__tests__/client.test.d.ts +0 -1
  98. package/dist/api/__tests__/client.test.js +0 -272
  99. package/dist/api/client.d.ts +0 -326
  100. package/dist/api/client.js +0 -427
  101. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  102. package/dist/auth/__tests__/login-flow.test.js +0 -101
  103. package/dist/auth/__tests__/store.test.d.ts +0 -1
  104. package/dist/auth/__tests__/store.test.js +0 -132
  105. package/dist/auth/login-flow.d.ts +0 -26
  106. package/dist/auth/login-flow.js +0 -137
  107. package/dist/auth/store.d.ts +0 -5
  108. package/dist/auth/store.js +0 -62
  109. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  110. package/dist/commands/__tests__/clone-args.test.js +0 -51
  111. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  112. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  113. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  114. package/dist/commands/__tests__/info-merge.test.js +0 -55
  115. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  116. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  117. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  118. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  119. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  120. package/dist/commands/__tests__/setup.test.js +0 -81
  121. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  122. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  123. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  124. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  125. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  126. package/dist/commands/__tests__/upgrade.test.js +0 -157
  127. package/dist/commands/agents.d.ts +0 -2
  128. package/dist/commands/agents.js +0 -160
  129. package/dist/commands/api-keys.d.ts +0 -2
  130. package/dist/commands/api-keys.js +0 -95
  131. package/dist/commands/apps.d.ts +0 -2
  132. package/dist/commands/apps.js +0 -82
  133. package/dist/commands/build-plugin.d.ts +0 -2
  134. package/dist/commands/build-plugin.js +0 -135
  135. package/dist/commands/clone.d.ts +0 -60
  136. package/dist/commands/clone.js +0 -271
  137. package/dist/commands/components.d.ts +0 -2
  138. package/dist/commands/components.js +0 -43
  139. package/dist/commands/deploy.d.ts +0 -2
  140. package/dist/commands/deploy.js +0 -279
  141. package/dist/commands/dev.d.ts +0 -11
  142. package/dist/commands/dev.js +0 -1011
  143. package/dist/commands/doctor.d.ts +0 -2
  144. package/dist/commands/doctor.js +0 -230
  145. package/dist/commands/endpoints.d.ts +0 -2
  146. package/dist/commands/endpoints.js +0 -189
  147. package/dist/commands/entities.d.ts +0 -2
  148. package/dist/commands/entities.js +0 -198
  149. package/dist/commands/files.d.ts +0 -2
  150. package/dist/commands/files.js +0 -193
  151. package/dist/commands/inbox.d.ts +0 -11
  152. package/dist/commands/inbox.js +0 -60
  153. package/dist/commands/info.d.ts +0 -178
  154. package/dist/commands/info.js +0 -455
  155. package/dist/commands/init.d.ts +0 -21
  156. package/dist/commands/init.js +0 -185
  157. package/dist/commands/integrations.d.ts +0 -2
  158. package/dist/commands/integrations.js +0 -233
  159. package/dist/commands/login.d.ts +0 -2
  160. package/dist/commands/login.js +0 -44
  161. package/dist/commands/logout.d.ts +0 -2
  162. package/dist/commands/logout.js +0 -13
  163. package/dist/commands/logs.d.ts +0 -2
  164. package/dist/commands/logs.js +0 -232
  165. package/dist/commands/mcp-entries.d.ts +0 -13
  166. package/dist/commands/mcp-entries.js +0 -26
  167. package/dist/commands/mcp.d.ts +0 -2
  168. package/dist/commands/mcp.js +0 -245
  169. package/dist/commands/open.d.ts +0 -2
  170. package/dist/commands/open.js +0 -53
  171. package/dist/commands/resume.d.ts +0 -2
  172. package/dist/commands/resume.js +0 -289
  173. package/dist/commands/save-convo.d.ts +0 -8
  174. package/dist/commands/save-convo.js +0 -20
  175. package/dist/commands/schedules.d.ts +0 -2
  176. package/dist/commands/schedules.js +0 -221
  177. package/dist/commands/setup.d.ts +0 -27
  178. package/dist/commands/setup.js +0 -177
  179. package/dist/commands/share-convo.d.ts +0 -24
  180. package/dist/commands/share-convo.js +0 -167
  181. package/dist/commands/skills.d.ts +0 -2
  182. package/dist/commands/skills.js +0 -352
  183. package/dist/commands/sync-telemetry.d.ts +0 -33
  184. package/dist/commands/sync-telemetry.js +0 -186
  185. package/dist/commands/sync.d.ts +0 -37
  186. package/dist/commands/sync.js +0 -702
  187. package/dist/commands/uninstall.d.ts +0 -2
  188. package/dist/commands/uninstall.js +0 -145
  189. package/dist/commands/upgrade.d.ts +0 -14
  190. package/dist/commands/upgrade.js +0 -217
  191. package/dist/commands/validate.d.ts +0 -2
  192. package/dist/commands/validate.js +0 -89
  193. package/dist/commands/welcome.d.ts +0 -1
  194. package/dist/commands/welcome.js +0 -86
  195. package/dist/commands/workflows.d.ts +0 -2
  196. package/dist/commands/workflows.js +0 -187
  197. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  198. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  199. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  200. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  201. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  202. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  203. package/dist/deploy/deploy-state.d.ts +0 -36
  204. package/dist/deploy/deploy-state.js +0 -63
  205. package/dist/deploy/deploy-status.d.ts +0 -21
  206. package/dist/deploy/deploy-status.js +0 -36
  207. package/dist/deploy/detach.d.ts +0 -32
  208. package/dist/deploy/detach.js +0 -71
  209. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  210. package/dist/dev/__tests__/attach.test.js +0 -296
  211. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  212. package/dist/dev/__tests__/detach.test.js +0 -404
  213. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  214. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  215. package/dist/dev/__tests__/session.test.d.ts +0 -1
  216. package/dist/dev/__tests__/session.test.js +0 -446
  217. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  218. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  219. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  220. package/dist/dev/__tests__/stop.test.js +0 -172
  221. package/dist/dev/attach.d.ts +0 -120
  222. package/dist/dev/attach.js +0 -269
  223. package/dist/dev/detach.d.ts +0 -187
  224. package/dist/dev/detach.js +0 -292
  225. package/dist/dev/preview-url-poller.d.ts +0 -35
  226. package/dist/dev/preview-url-poller.js +0 -50
  227. package/dist/dev/session.d.ts +0 -175
  228. package/dist/dev/session.js +0 -258
  229. package/dist/dev/startup-sync.d.ts +0 -23
  230. package/dist/dev/startup-sync.js +0 -14
  231. package/dist/dev/stop.d.ts +0 -52
  232. package/dist/dev/stop.js +0 -101
  233. package/dist/devtools/registry-data.d.ts +0 -46
  234. package/dist/devtools/registry-data.js +0 -40
  235. package/dist/generated/bundled-types.d.ts +0 -1
  236. package/dist/generated/bundled-types.js +0 -46
  237. package/dist/generated/version.d.ts +0 -1
  238. package/dist/generated/version.js +0 -2
  239. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  240. package/dist/git/__tests__/auto-commit.test.js +0 -431
  241. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  242. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  243. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  244. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  245. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  246. package/dist/git/__tests__/credentials.test.js +0 -141
  247. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  248. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  249. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  251. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  252. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  253. package/dist/git/__tests__/identity.test.d.ts +0 -1
  254. package/dist/git/__tests__/identity.test.js +0 -146
  255. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  256. package/dist/git/__tests__/manifest.test.js +0 -446
  257. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  258. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  259. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  260. package/dist/git/__tests__/preflight.test.js +0 -36
  261. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  262. package/dist/git/__tests__/repo-config.test.js +0 -26
  263. package/dist/git/__tests__/sync.test.d.ts +0 -1
  264. package/dist/git/__tests__/sync.test.js +0 -405
  265. package/dist/git/auto-commit.d.ts +0 -35
  266. package/dist/git/auto-commit.js +0 -293
  267. package/dist/git/classify-sync-error.d.ts +0 -21
  268. package/dist/git/classify-sync-error.js +0 -111
  269. package/dist/git/credentials.d.ts +0 -75
  270. package/dist/git/credentials.js +0 -164
  271. package/dist/git/critical-files.d.ts +0 -20
  272. package/dist/git/critical-files.js +0 -68
  273. package/dist/git/deploy-guard.d.ts +0 -53
  274. package/dist/git/deploy-guard.js +0 -78
  275. package/dist/git/identity.d.ts +0 -44
  276. package/dist/git/identity.js +0 -133
  277. package/dist/git/preflight.d.ts +0 -57
  278. package/dist/git/preflight.js +0 -276
  279. package/dist/git/remote.d.ts +0 -37
  280. package/dist/git/remote.js +0 -75
  281. package/dist/git/repo-config.d.ts +0 -8
  282. package/dist/git/repo-config.js +0 -29
  283. package/dist/git/sync.d.ts +0 -15
  284. package/dist/git/sync.js +0 -159
  285. package/dist/health/__tests__/checks.test.d.ts +0 -1
  286. package/dist/health/__tests__/checks.test.js +0 -357
  287. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  288. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  289. package/dist/health/__tests__/fix.test.d.ts +0 -1
  290. package/dist/health/__tests__/fix.test.js +0 -72
  291. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  292. package/dist/health/__tests__/runner-filter.test.js +0 -61
  293. package/dist/health/checks.d.ts +0 -42
  294. package/dist/health/checks.js +0 -636
  295. package/dist/health/fix.d.ts +0 -22
  296. package/dist/health/fix.js +0 -62
  297. package/dist/health/runner.d.ts +0 -8
  298. package/dist/health/runner.js +0 -47
  299. package/dist/health/types.d.ts +0 -12
  300. package/dist/health/types.js +0 -1
  301. package/dist/index.d.ts +0 -1
  302. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  304. package/dist/logs/tailer.d.ts +0 -17
  305. package/dist/logs/tailer.js +0 -217
  306. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  307. package/dist/sync/__tests__/change-detect.test.js +0 -123
  308. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  309. package/dist/sync/__tests__/hash.test.js +0 -18
  310. package/dist/sync/change-detect.d.ts +0 -19
  311. package/dist/sync/change-detect.js +0 -136
  312. package/dist/sync/conflict-ui.d.ts +0 -5
  313. package/dist/sync/conflict-ui.js +0 -78
  314. package/dist/sync/executor.d.ts +0 -23
  315. package/dist/sync/executor.js +0 -102
  316. package/dist/sync/hash.d.ts +0 -1
  317. package/dist/sync/hash.js +0 -4
  318. package/dist/sync/types.d.ts +0 -24
  319. package/dist/sync/types.js +0 -1
  320. package/dist/template/manifest.d.ts +0 -17
  321. package/dist/template/manifest.js +0 -145
  322. package/dist/tools/types.d.ts +0 -52
  323. package/dist/tools/types.js +0 -8
  324. package/dist/types-manager.d.ts +0 -1
  325. package/dist/types-manager.js +0 -35
  326. package/dist/types.d.ts +0 -349
  327. package/dist/types.js +0 -1
  328. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  329. package/dist/ui/__tests__/banner.test.js +0 -98
  330. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  331. package/dist/ui/__tests__/colors.test.js +0 -22
  332. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  333. package/dist/ui/__tests__/keyboard.test.js +0 -34
  334. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  335. package/dist/ui/__tests__/status-line.test.js +0 -54
  336. package/dist/ui/banner.d.ts +0 -29
  337. package/dist/ui/banner.js +0 -153
  338. package/dist/ui/colors.d.ts +0 -4
  339. package/dist/ui/colors.js +0 -7
  340. package/dist/ui/keyboard.d.ts +0 -12
  341. package/dist/ui/keyboard.js +0 -61
  342. package/dist/ui/status-line.d.ts +0 -6
  343. package/dist/ui/status-line.js +0 -53
  344. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  345. package/dist/utils/__tests__/format-error.test.js +0 -43
  346. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  347. package/dist/utils/__tests__/help-json.test.js +0 -39
  348. package/dist/utils/__tests__/http.test.d.ts +0 -1
  349. package/dist/utils/__tests__/http.test.js +0 -381
  350. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  351. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  352. package/dist/utils/__tests__/output.test.d.ts +0 -1
  353. package/dist/utils/__tests__/output.test.js +0 -38
  354. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  355. package/dist/utils/__tests__/prompt.test.js +0 -27
  356. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  357. package/dist/utils/__tests__/resolve.test.js +0 -95
  358. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  359. package/dist/utils/__tests__/sqlite.test.js +0 -89
  360. package/dist/utils/agent-guidance.d.ts +0 -47
  361. package/dist/utils/agent-guidance.js +0 -128
  362. package/dist/utils/app-info.d.ts +0 -70
  363. package/dist/utils/app-info.js +0 -167
  364. package/dist/utils/curl-parser.d.ts +0 -12
  365. package/dist/utils/curl-parser.js +0 -162
  366. package/dist/utils/data-input.d.ts +0 -1
  367. package/dist/utils/data-input.js +0 -38
  368. package/dist/utils/format-error.d.ts +0 -10
  369. package/dist/utils/format-error.js +0 -38
  370. package/dist/utils/fs.d.ts +0 -5
  371. package/dist/utils/fs.js +0 -23
  372. package/dist/utils/help-json.d.ts +0 -70
  373. package/dist/utils/help-json.js +0 -88
  374. package/dist/utils/http.d.ts +0 -46
  375. package/dist/utils/http.js +0 -421
  376. package/dist/utils/ignore-matcher.d.ts +0 -47
  377. package/dist/utils/ignore-matcher.js +0 -132
  378. package/dist/utils/output.d.ts +0 -17
  379. package/dist/utils/output.js +0 -27
  380. package/dist/utils/prompt.d.ts +0 -5
  381. package/dist/utils/prompt.js +0 -42
  382. package/dist/utils/resolve.d.ts +0 -12
  383. package/dist/utils/resolve.js +0 -52
  384. package/dist/utils/setup-state.d.ts +0 -3
  385. package/dist/utils/setup-state.js +0 -19
  386. package/dist/utils/sqlite-adapter.d.ts +0 -48
  387. package/dist/utils/sqlite-adapter.js +0 -147
  388. package/dist/utils/sqlite.d.ts +0 -14
  389. package/dist/utils/sqlite.js +0 -14
  390. package/dist/utils/subprocess.d.ts +0 -19
  391. package/dist/utils/subprocess.js +0 -27
  392. package/dist/utils/which.d.ts +0 -14
  393. package/dist/utils/which.js +0 -47
  394. package/dist/utils/zip.d.ts +0 -7
  395. package/dist/utils/zip.js +0 -42
  396. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  397. package/dist/validate/__tests__/validate.test.js +0 -42
  398. package/dist/validate/freshness.d.ts +0 -28
  399. package/dist/validate/freshness.js +0 -48
  400. package/dist/validate/preview.d.ts +0 -21
  401. package/dist/validate/preview.js +0 -39
  402. package/dist/workspace/resolve.d.ts +0 -19
  403. package/dist/workspace/resolve.js +0 -100
@@ -1,357 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- vi.mock('fs', async (importOriginal) => {
3
- const actual = await importOriginal();
4
- return { ...actual, existsSync: vi.fn(() => true) };
5
- });
6
- vi.mock('child_process', async (importOriginal) => {
7
- const actual = await importOriginal();
8
- return { ...actual, execFileSync: vi.fn() };
9
- });
10
- import { existsSync } from 'fs';
11
- import { execFileSync } from 'child_process';
12
- import { resetGitProbeCache } from '../../git/preflight.js';
13
- const mockedExistsSync = vi.mocked(existsSync);
14
- const mockedExecFileSync = vi.mocked(execFileSync);
15
- beforeEach(() => {
16
- vi.clearAllMocks();
17
- vi.restoreAllMocks();
18
- vi.spyOn(console, 'log').mockImplementation(() => { });
19
- vi.spyOn(console, 'error').mockImplementation(() => { });
20
- mockedExistsSync.mockReturnValue(true);
21
- // checkSystemDeps now goes through probeGit() which caches the resolved
22
- // git binary for the lifetime of the process. Reset between tests so each
23
- // mock setup actually drives a fresh probe.
24
- resetGitProbeCache();
25
- });
26
- afterEach(() => {
27
- vi.restoreAllMocks();
28
- });
29
- // ── Helpers ──────────────────────────────────────────────────────────
30
- function makeCtx(overrides = {}) {
31
- return {
32
- credentials: { apiKey: 'key', email: 'user@test.com', baseUrl: 'https://runwork.ai' },
33
- client: null,
34
- config: null,
35
- cwd: '/test/dir',
36
- ...overrides,
37
- };
38
- }
39
- function makeConfig(overrides = {}) {
40
- return {
41
- workspaceId: 'ws-1',
42
- workspaceName: 'Test WS',
43
- appId: 'app-1',
44
- appName: 'Test App',
45
- ...overrides,
46
- };
47
- }
48
- // ── 1. System Dependencies ───────────────────────────────────────────
49
- describe('checkSystemDeps', () => {
50
- it('passes with modern git', async () => {
51
- mockedExecFileSync.mockReturnValue(Buffer.from('git version 2.43.0'));
52
- const { checkSystemDeps } = await import('../checks.js');
53
- const result = await checkSystemDeps();
54
- expect(result.status).toBe('pass');
55
- expect(result.message).toContain('2.43.0');
56
- });
57
- it('warns with old git', async () => {
58
- mockedExecFileSync.mockReturnValue(Buffer.from('git version 2.15.0'));
59
- const { checkSystemDeps } = await import('../checks.js');
60
- const result = await checkSystemDeps();
61
- expect(result.status).toBe('warn');
62
- expect(result.message).toContain('old');
63
- });
64
- it('fails when git not found', async () => {
65
- mockedExecFileSync.mockImplementation(() => { throw new Error('not found'); });
66
- const { checkSystemDeps } = await import('../checks.js');
67
- const result = await checkSystemDeps();
68
- expect(result.status).toBe('fail');
69
- expect(result.fix).toBeDefined();
70
- });
71
- });
72
- // ── 4a. Git credential helper ────────────────────────────────────────
73
- describe('checkGitCredentialHelper', () => {
74
- function gitConfigOutput(line) {
75
- return Buffer.from(`${line}\n`);
76
- }
77
- function gitConfigEmpty() {
78
- // git config --get-regexp returns 1 with no output when nothing matches
79
- const err = new Error('git config exited with code 1');
80
- err.status = 1;
81
- throw err;
82
- }
83
- it('skips when not logged in', async () => {
84
- const { checkGitCredentialHelper } = await import('../checks.js');
85
- const ctx = makeCtx({ credentials: null });
86
- const result = await checkGitCredentialHelper(ctx);
87
- expect(result.status).toBe('skip');
88
- expect(result.message).toContain('not logged in');
89
- });
90
- it('skips when git is not installed', async () => {
91
- const { checkGitCredentialHelper } = await import('../checks.js');
92
- // First call (probeGit -> git --version) throws ENOENT-shaped error.
93
- mockedExecFileSync.mockImplementation((file) => {
94
- if (file === 'git') {
95
- const err = new Error('spawn git ENOENT');
96
- err.code = 'ENOENT';
97
- throw err;
98
- }
99
- throw new Error('unreachable');
100
- });
101
- const ctx = makeCtx();
102
- const result = await checkGitCredentialHelper(ctx);
103
- expect(result.status).toBe('skip');
104
- expect(result.message).toContain('git not installed');
105
- });
106
- it('passes when helper is registered for the credentials origin', async () => {
107
- const { checkGitCredentialHelper } = await import('../checks.js');
108
- mockedExecFileSync.mockImplementation(((file, args) => {
109
- if (file === 'git' && args?.[0] === '--version')
110
- return Buffer.from('git version 2.43.0');
111
- if (file === 'git' && args?.includes('--get-regexp')) {
112
- return gitConfigOutput('credential.https://runwork.ai.helper !runwork git-credential-helper');
113
- }
114
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
115
- }));
116
- const ctx = makeCtx();
117
- const result = await checkGitCredentialHelper(ctx);
118
- expect(result.status).toBe('pass');
119
- expect(result.message).toContain('https://runwork.ai');
120
- });
121
- it('fails when no entry exists in git config', async () => {
122
- const { checkGitCredentialHelper } = await import('../checks.js');
123
- mockedExecFileSync.mockImplementation(((file, args) => {
124
- if (file === 'git' && args?.[0] === '--version')
125
- return Buffer.from('git version 2.43.0');
126
- if (file === 'git' && args?.includes('--get-regexp'))
127
- gitConfigEmpty();
128
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
129
- }));
130
- const ctx = makeCtx();
131
- const result = await checkGitCredentialHelper(ctx);
132
- expect(result.status).toBe('fail');
133
- expect(result.fix).toBe('runwork doctor --fix');
134
- });
135
- it('fails when entries exist but none match the credentials origin', async () => {
136
- const { checkGitCredentialHelper } = await import('../checks.js');
137
- mockedExecFileSync.mockImplementation(((file, args) => {
138
- if (file === 'git' && args?.[0] === '--version')
139
- return Buffer.from('git version 2.43.0');
140
- if (file === 'git' && args?.includes('--get-regexp')) {
141
- // Stale entry from a previous staging URL.
142
- return gitConfigOutput('credential.https://runwork-staging.example.com.helper !runwork git-credential-helper');
143
- }
144
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
145
- }));
146
- const ctx = makeCtx({
147
- credentials: { apiKey: 'k', email: 'u@e.com', baseUrl: 'https://runwork.ai' },
148
- });
149
- const result = await checkGitCredentialHelper(ctx);
150
- expect(result.status).toBe('fail');
151
- expect(result.message).toContain('1 other runwork helper');
152
- });
153
- it('fails when the registered absolute path no longer exists', async () => {
154
- const { checkGitCredentialHelper } = await import('../checks.js');
155
- mockedExecFileSync.mockImplementation(((file, args) => {
156
- if (file === 'git' && args?.[0] === '--version')
157
- return Buffer.from('git version 2.43.0');
158
- if (file === 'git' && args?.includes('--get-regexp')) {
159
- return gitConfigOutput('credential.https://runwork.ai.helper !"/old/path/runwork" git-credential-helper');
160
- }
161
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
162
- }));
163
- mockedExistsSync.mockImplementation((p) => p !== '/old/path/runwork');
164
- const ctx = makeCtx();
165
- const result = await checkGitCredentialHelper(ctx);
166
- expect(result.status).toBe('fail');
167
- expect(result.message).toContain('binary not found');
168
- expect(result.fix).toContain('runwork doctor --fix');
169
- });
170
- it('passes when the registered absolute path still exists', async () => {
171
- const { checkGitCredentialHelper } = await import('../checks.js');
172
- mockedExecFileSync.mockImplementation(((file, args) => {
173
- if (file === 'git' && args?.[0] === '--version')
174
- return Buffer.from('git version 2.43.0');
175
- if (file === 'git' && args?.includes('--get-regexp')) {
176
- return gitConfigOutput('credential.https://runwork.ai.helper !"/usr/local/bin/runwork" git-credential-helper');
177
- }
178
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
179
- }));
180
- mockedExistsSync.mockReturnValue(true);
181
- const ctx = makeCtx();
182
- const result = await checkGitCredentialHelper(ctx);
183
- expect(result.status).toBe('pass');
184
- });
185
- it('passes a Windows-style absolute path that exists', async () => {
186
- const { checkGitCredentialHelper } = await import('../checks.js');
187
- mockedExecFileSync.mockImplementation(((file, args) => {
188
- if (file === 'git' && args?.[0] === '--version')
189
- return Buffer.from('git version 2.43.0');
190
- if (file === 'git' && args?.includes('--get-regexp')) {
191
- return gitConfigOutput('credential.https://runwork.ai.helper !"C:/Users/test/.runwork/bin/runwork.exe" git-credential-helper');
192
- }
193
- throw new Error(`unexpected call: ${file} ${args?.join(' ')}`);
194
- }));
195
- mockedExistsSync.mockReturnValue(true);
196
- const ctx = makeCtx();
197
- const result = await checkGitCredentialHelper(ctx);
198
- expect(result.status).toBe('pass');
199
- });
200
- });
201
- // ── 3 & 4. Auth + Network ───────────────────────────────────────────
202
- describe('checkAuthAndNetwork', () => {
203
- it('fails auth when no credentials', async () => {
204
- const { checkAuthAndNetwork } = await import('../checks.js');
205
- const ctx = makeCtx({ credentials: null, client: null });
206
- const { auth, network } = await checkAuthAndNetwork(ctx);
207
- expect(auth.status).toBe('fail');
208
- expect(auth.fix).toContain('login');
209
- expect(network.status).toBe('skip');
210
- });
211
- it('passes when API responds', async () => {
212
- const { checkAuthAndNetwork } = await import('../checks.js');
213
- const mockClient = {
214
- listWorkspaces: vi.fn().mockResolvedValue([{ id: 'ws-1', name: 'WS' }]),
215
- };
216
- const ctx = makeCtx({ client: mockClient });
217
- const { auth, network } = await checkAuthAndNetwork(ctx);
218
- expect(auth.status).toBe('pass');
219
- expect(auth.message).toContain('user@test.com');
220
- expect(network.status).toBe('pass');
221
- });
222
- it('distinguishes auth error from network error', async () => {
223
- const { checkAuthAndNetwork } = await import('../checks.js');
224
- const mockClient = {
225
- listWorkspaces: vi.fn().mockRejectedValue(new Error('API error 401: Unauthorized')),
226
- };
227
- const ctx = makeCtx({ client: mockClient });
228
- const { auth, network } = await checkAuthAndNetwork(ctx);
229
- expect(auth.status).toBe('fail');
230
- expect(network.status).toBe('pass');
231
- });
232
- it('fails network on connection error', async () => {
233
- const { checkAuthAndNetwork } = await import('../checks.js');
234
- const mockClient = {
235
- listWorkspaces: vi.fn().mockRejectedValue(new Error('fetch failed')),
236
- };
237
- const ctx = makeCtx({ client: mockClient });
238
- const { auth, network } = await checkAuthAndNetwork(ctx);
239
- expect(auth.status).toBe('skip');
240
- expect(network.status).toBe('fail');
241
- });
242
- });
243
- // ── 5. Project Config ────────────────────────────────────────────────
244
- describe('checkProjectConfig', () => {
245
- it('passes with valid config', async () => {
246
- const { checkProjectConfig } = await import('../checks.js');
247
- mockedExistsSync.mockReturnValue(true);
248
- const ctx = makeCtx({ config: makeConfig() });
249
- const result = await checkProjectConfig(ctx);
250
- expect(result.status).toBe('pass');
251
- expect(result.message).toContain('Test App');
252
- expect(result.message).toContain('Test WS');
253
- });
254
- it('fails with malformed config (null)', async () => {
255
- const { checkProjectConfig } = await import('../checks.js');
256
- mockedExistsSync.mockReturnValue(true);
257
- const ctx = makeCtx({ config: null });
258
- const result = await checkProjectConfig(ctx);
259
- expect(result.status).toBe('fail');
260
- expect(result.message).toContain('malformed');
261
- });
262
- it('passes outside project when default workspace set', async () => {
263
- const { checkProjectConfig } = await import('../checks.js');
264
- mockedExistsSync.mockReturnValue(false);
265
- const creds = {
266
- apiKey: 'key',
267
- email: 'user@test.com',
268
- baseUrl: 'https://runwork.ai',
269
- defaultWorkspaceId: 'ws-1',
270
- defaultWorkspaceName: 'My WS',
271
- };
272
- const ctx = makeCtx({ credentials: creds, config: null });
273
- const result = await checkProjectConfig(ctx);
274
- expect(result.status).toBe('pass');
275
- expect(result.message).toContain('My WS');
276
- });
277
- it('warns outside project when no default workspace', async () => {
278
- const { checkProjectConfig } = await import('../checks.js');
279
- mockedExistsSync.mockReturnValue(false);
280
- const ctx = makeCtx({ config: null });
281
- const result = await checkProjectConfig(ctx);
282
- expect(result.status).toBe('warn');
283
- expect(result.fix).toBeDefined();
284
- });
285
- });
286
- // ── 6. App Exists ────────────────────────────────────────────────────
287
- describe('checkAppExists', () => {
288
- it('skips when no config or client', async () => {
289
- const { checkAppExists } = await import('../checks.js');
290
- const ctx = makeCtx({ config: null });
291
- const result = await checkAppExists(ctx);
292
- expect(result.status).toBe('skip');
293
- });
294
- it('passes when app found on server', async () => {
295
- const { checkAppExists } = await import('../checks.js');
296
- const mockClient = {
297
- getApp: vi.fn().mockResolvedValue({ id: 'app-1', name: 'Test' }),
298
- };
299
- const ctx = makeCtx({ config: makeConfig(), client: mockClient });
300
- const result = await checkAppExists(ctx);
301
- expect(result.status).toBe('pass');
302
- });
303
- it('fails when app not found', async () => {
304
- const { checkAppExists } = await import('../checks.js');
305
- const mockClient = {
306
- getApp: vi.fn().mockRejectedValue(new Error('404')),
307
- };
308
- const ctx = makeCtx({ config: makeConfig(), client: mockClient });
309
- const result = await checkAppExists(ctx);
310
- expect(result.status).toBe('fail');
311
- expect(result.message).toContain('not found');
312
- });
313
- });
314
- // ── 7. Git Remote ────────────────────────────────────────────────────
315
- describe('checkGitRemote', () => {
316
- it('skips when no project config', async () => {
317
- const { checkGitRemote } = await import('../checks.js');
318
- const ctx = makeCtx({ config: null });
319
- const result = await checkGitRemote(ctx);
320
- expect(result.status).toBe('skip');
321
- });
322
- it('fails when not a git repo', async () => {
323
- const { checkGitRemote } = await import('../checks.js');
324
- mockedExistsSync.mockReturnValue(false);
325
- const ctx = makeCtx({ config: makeConfig() });
326
- const result = await checkGitRemote(ctx);
327
- expect(result.status).toBe('fail');
328
- expect(result.message).toContain('not a git repository');
329
- });
330
- it('passes when remote configured correctly', async () => {
331
- const { checkGitRemote } = await import('../checks.js');
332
- mockedExistsSync.mockReturnValue(true);
333
- mockedExecFileSync.mockReturnValue(Buffer.from('https://runwork.ai/git/ws-1/app-1'));
334
- const ctx = makeCtx({ config: makeConfig() });
335
- const result = await checkGitRemote(ctx);
336
- expect(result.status).toBe('pass');
337
- });
338
- it('fails when remote not configured', async () => {
339
- const { checkGitRemote } = await import('../checks.js');
340
- mockedExistsSync.mockReturnValue(true);
341
- mockedExecFileSync.mockImplementation(() => { throw new Error('No such remote'); });
342
- const ctx = makeCtx({ config: makeConfig() });
343
- const result = await checkGitRemote(ctx);
344
- expect(result.status).toBe('fail');
345
- expect(result.fix).toContain('git remote add');
346
- });
347
- });
348
- // ── 8. Agent Setup ───────────────────────────────────────────────────
349
- describe('checkAgentSetup', () => {
350
- it('fails when setup never run', async () => {
351
- const { checkAgentSetup } = await import('../checks.js');
352
- mockedExistsSync.mockReturnValue(false);
353
- const result = await checkAgentSetup();
354
- expect(result.status).toBe('fail');
355
- expect(result.fix).toContain('runwork setup');
356
- });
357
- });
@@ -1,196 +0,0 @@
1
- /**
2
- * Tests for the first-party distribution checks added to runwork doctor.
3
- *
4
- * These checks rely on `httpFetch` (our node:https-backed fetch wrapper) to
5
- * hit https://runwork.ai/cli/latest.json. We mock the wrapper to redirect
6
- * those calls to a local HTTP server so the suite has no outbound network
7
- * dependency. We still exercise the real wrapper end to end -- only the
8
- * URL is rewritten -- so this remains an integration test of the network
9
- * code path.
10
- */
11
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
12
- import { createServer } from 'node:http';
13
- let currentRedirectBase = null;
14
- vi.mock('../../utils/http.js', async () => {
15
- const actual = await vi.importActual('../../utils/http.js');
16
- return {
17
- ...actual,
18
- httpFetch: (url, init) => {
19
- if (currentRedirectBase && url.startsWith('https://runwork.ai')) {
20
- const redirected = url.replace('https://runwork.ai', currentRedirectBase);
21
- return actual.httpFetch(redirected, init);
22
- }
23
- return actual.httpFetch(url, init);
24
- },
25
- };
26
- });
27
- import { checkCliVersion, checkCliArtifactReachable, checkCliInstallLocation, } from '../checks.js';
28
- function startServer() {
29
- return new Promise((resolvePromise) => {
30
- let currentManifest = null;
31
- let manifestStatus = 200;
32
- const artifactStatuses = new Map();
33
- const server = createServer((req, res) => {
34
- const url = req.url ?? '/';
35
- if (url === '/cli/latest.json') {
36
- if (currentManifest === null) {
37
- res.writeHead(manifestStatus, { 'Content-Type': 'application/json' });
38
- res.end('{"error": "not available"}');
39
- return;
40
- }
41
- res.writeHead(manifestStatus, { 'Content-Type': 'application/json; charset=utf-8' });
42
- res.end(JSON.stringify(currentManifest));
43
- return;
44
- }
45
- // Artifact route: /cli/releases/<version>/<artifact>
46
- const releaseMatch = url.match(/^\/cli\/releases\/[^/]+\/runwork-([^/]+)\.(tar\.gz|zip)$/);
47
- if (releaseMatch) {
48
- const key = releaseMatch[1];
49
- const status = artifactStatuses.get(key) ?? 200;
50
- res.writeHead(status, { 'Content-Type': 'application/octet-stream' });
51
- res.end('');
52
- return;
53
- }
54
- res.writeHead(404);
55
- res.end('not found');
56
- });
57
- server.listen(0, '127.0.0.1', () => {
58
- const addr = server.address();
59
- if (addr && typeof addr === 'object') {
60
- const port = addr.port;
61
- resolvePromise({
62
- url: `http://127.0.0.1:${port}`,
63
- stop: () => new Promise((stop) => server.close(() => stop())),
64
- setManifest(m, s = 200) {
65
- currentManifest = m;
66
- manifestStatus = s;
67
- },
68
- setArtifactStatus(key, s) {
69
- artifactStatuses.set(key, s);
70
- },
71
- });
72
- }
73
- });
74
- });
75
- }
76
- describe('checkCliVersion (runwork.ai backed)', () => {
77
- let server;
78
- beforeEach(async () => {
79
- server = await startServer();
80
- currentRedirectBase = server.url;
81
- });
82
- afterEach(async () => {
83
- currentRedirectBase = null;
84
- await server.stop();
85
- });
86
- it('skips with an explicit unreachable message when the manifest 404s', async () => {
87
- server.setManifest(null, 404);
88
- const result = await checkCliVersion();
89
- expect(result.status).toBe('skip');
90
- expect(result.message).toContain('unreachable');
91
- });
92
- it('passes when manifest version matches current VERSION', async () => {
93
- // We cannot read VERSION here without depending on the generated file
94
- // at test time; instead, serve "0.0.0" and expect the test to compare.
95
- // To make this deterministic, we fetch the current VERSION from the
96
- // module under test via a side channel. See the runner for the value.
97
- const { VERSION } = await import('../../generated/version.js');
98
- server.setManifest({ version: VERSION });
99
- const result = await checkCliVersion();
100
- expect(result.status).toBe('pass');
101
- expect(result.message).toContain(VERSION);
102
- });
103
- it('warns when the manifest has a newer version', async () => {
104
- server.setManifest({ version: '99.99.99' });
105
- const result = await checkCliVersion();
106
- expect(result.status).toBe('warn');
107
- expect(result.message).toContain('99.99.99');
108
- expect(result.fix).toBe('runwork upgrade');
109
- });
110
- it('skips when the manifest has no version field', async () => {
111
- server.setManifest({ name: 'runwork' });
112
- const result = await checkCliVersion();
113
- expect(result.status).toBe('skip');
114
- });
115
- });
116
- describe('checkCliArtifactReachable', () => {
117
- let server;
118
- beforeEach(async () => {
119
- server = await startServer();
120
- currentRedirectBase = server.url;
121
- });
122
- afterEach(async () => {
123
- currentRedirectBase = null;
124
- await server.stop();
125
- });
126
- function platformKey() {
127
- const os = process.platform === 'darwin' ? 'darwin' : process.platform === 'linux' ? 'linux' : 'windows';
128
- const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
129
- return `${os}-${arch}`;
130
- }
131
- it('fails when the manifest is unreachable', async () => {
132
- server.setManifest(null, 500);
133
- const result = await checkCliArtifactReachable();
134
- expect(result.status).toBe('fail');
135
- expect(result.message).toContain('unreachable');
136
- });
137
- it('fails when the manifest has no artifact for the host platform', async () => {
138
- server.setManifest({
139
- version: '99.99.99',
140
- artifacts: {
141
- 'unknown-unknown': { path: '/cli/releases/99.99.99/runwork-unknown-unknown.tar.gz', sha256: 'deadbeef' },
142
- },
143
- });
144
- const result = await checkCliArtifactReachable();
145
- expect(result.status).toBe('fail');
146
- expect(result.message).toMatch(/no artifact for/);
147
- });
148
- it('passes when the artifact HEAD returns 200', async () => {
149
- const key = platformKey();
150
- const ext = key === 'windows-x64' ? 'zip' : 'tar.gz';
151
- server.setManifest({
152
- version: '99.99.99',
153
- artifacts: {
154
- [key]: {
155
- path: `/cli/releases/99.99.99/runwork-${key}.${ext}`,
156
- sha256: 'deadbeef',
157
- },
158
- },
159
- });
160
- server.setArtifactStatus(key, 200);
161
- const result = await checkCliArtifactReachable();
162
- expect(result.status).toBe('pass');
163
- expect(result.message).toContain(key);
164
- });
165
- it('fails when the artifact HEAD returns a non-2xx status', async () => {
166
- const key = platformKey();
167
- const ext = key === 'windows-x64' ? 'zip' : 'tar.gz';
168
- server.setManifest({
169
- version: '99.99.99',
170
- artifacts: {
171
- [key]: {
172
- path: `/cli/releases/99.99.99/runwork-${key}.${ext}`,
173
- sha256: 'deadbeef',
174
- },
175
- },
176
- });
177
- server.setArtifactStatus(key, 404);
178
- const result = await checkCliArtifactReachable();
179
- expect(result.status).toBe('fail');
180
- expect(result.message).toContain('404');
181
- });
182
- });
183
- describe('checkCliInstallLocation', () => {
184
- const originalExecPath = process.execPath;
185
- const originalArgv1 = process.argv[1];
186
- afterEach(() => {
187
- Object.defineProperty(process, 'execPath', { value: originalExecPath, writable: true });
188
- process.argv[1] = originalArgv1;
189
- });
190
- it('warns when process does not run from the canonical ~/.runwork/bin/runwork', async () => {
191
- Object.defineProperty(process, 'execPath', { value: '/usr/local/bin/node', writable: true });
192
- process.argv[1] = '/opt/homebrew/bin/runwork';
193
- const result = await checkCliInstallLocation();
194
- expect(result.status).toBe('warn');
195
- });
196
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,72 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('fs', () => ({ existsSync: vi.fn() }));
3
- vi.mock('../../git/credentials.js', () => ({ ensureGitCredentialHelper: vi.fn(async () => { }) }));
4
- vi.mock('../../git/remote.js', () => ({ ensureRunworkRemote: vi.fn(() => ({ action: 'added' })) }));
5
- const { existsSync: mockExistsSync } = await import('fs');
6
- const { ensureGitCredentialHelper } = await import('../../git/credentials.js');
7
- const { ensureRunworkRemote } = await import('../../git/remote.js');
8
- const { applyDoctorFixes, FIXABLE_CHECKS } = await import('../fix.js');
9
- const creds = { apiKey: 'k', email: 'u@e.com', baseUrl: 'https://runwork.ai' };
10
- const config = { workspaceId: 'ws', appId: 'app', workspaceName: 'WS', appName: 'App' };
11
- function makeCtx(overrides = {}) {
12
- return {
13
- credentials: creds,
14
- client: { getGitRemoteUrl: (ws, app) => `https://runwork.ai/api/git/${ws}/${app}` },
15
- config,
16
- cwd: '/repo',
17
- ...overrides,
18
- };
19
- }
20
- describe('health/fix applyDoctorFixes', () => {
21
- beforeEach(() => {
22
- vi.clearAllMocks();
23
- vi.mocked(mockExistsSync).mockReturnValue(true); // .git present by default
24
- });
25
- it('only advertises the two fixable checks', () => {
26
- expect(FIXABLE_CHECKS).toEqual(['git-credential-helper', 'git-remote']);
27
- });
28
- it('registers the git credential helper when that check is failing', async () => {
29
- const outcomes = await applyDoctorFixes(makeCtx(), ['git-credential-helper']);
30
- expect(ensureGitCredentialHelper).toHaveBeenCalledWith('https://runwork.ai');
31
- expect(outcomes).toEqual([
32
- { name: 'git-credential-helper', applied: true, message: expect.stringContaining('registered') },
33
- ]);
34
- });
35
- it('cannot fix the credential helper when not logged in', async () => {
36
- const outcomes = await applyDoctorFixes(makeCtx({ credentials: null }), ['git-credential-helper']);
37
- expect(ensureGitCredentialHelper).not.toHaveBeenCalled();
38
- expect(outcomes[0]).toMatchObject({ name: 'git-credential-helper', applied: false });
39
- expect(outcomes[0].message).toContain('runwork login');
40
- });
41
- it('configures the runwork remote with the canonical /api/git URL', async () => {
42
- const outcomes = await applyDoctorFixes(makeCtx(), ['git-remote']);
43
- expect(ensureRunworkRemote).toHaveBeenCalledWith('/repo', 'https://runwork.ai/api/git/ws/app');
44
- expect(outcomes[0]).toMatchObject({ name: 'git-remote', applied: true });
45
- });
46
- it('cannot fix the remote outside a project (no config)', async () => {
47
- const outcomes = await applyDoctorFixes(makeCtx({ config: null }), ['git-remote']);
48
- expect(ensureRunworkRemote).not.toHaveBeenCalled();
49
- expect(outcomes[0]).toMatchObject({ name: 'git-remote', applied: false });
50
- expect(outcomes[0].message).toContain('project');
51
- });
52
- it('cannot fix the remote when the directory is not a git repo', async () => {
53
- vi.mocked(mockExistsSync).mockReturnValue(false);
54
- const outcomes = await applyDoctorFixes(makeCtx(), ['git-remote']);
55
- expect(ensureRunworkRemote).not.toHaveBeenCalled();
56
- expect(outcomes[0]).toMatchObject({ name: 'git-remote', applied: false });
57
- expect(outcomes[0].message).toContain('git init');
58
- });
59
- it('ignores failing checks it cannot remediate', async () => {
60
- const outcomes = await applyDoctorFixes(makeCtx(), ['auth', 'network', 'cli-version']);
61
- expect(ensureGitCredentialHelper).not.toHaveBeenCalled();
62
- expect(ensureRunworkRemote).not.toHaveBeenCalled();
63
- expect(outcomes).toEqual([]);
64
- });
65
- it('applies both fixes when both checks fail', async () => {
66
- const outcomes = await applyDoctorFixes(makeCtx(), ['git-credential-helper', 'git-remote']);
67
- expect(ensureGitCredentialHelper).toHaveBeenCalledOnce();
68
- expect(ensureRunworkRemote).toHaveBeenCalledOnce();
69
- expect(outcomes.map(o => o.name)).toEqual(['git-credential-helper', 'git-remote']);
70
- expect(outcomes.every(o => o.applied)).toBe(true);
71
- });
72
- });
@@ -1 +0,0 @@
1
- export {};