runwork 0.15.1 → 0.16.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 (404) hide show
  1. package/bundled-types/task-delegation/task-delegation/types.d.ts +6 -0
  2. package/dist/index.js +20237 -116
  3. package/package.json +4 -4
  4. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  5. package/dist/__tests__/curl-parser.test.js +0 -250
  6. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  7. package/dist/__tests__/install-scripts.test.js +0 -280
  8. package/dist/__tests__/types-manager.test.d.ts +0 -1
  9. package/dist/__tests__/types-manager.test.js +0 -89
  10. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  11. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  12. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  13. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -105
  14. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  15. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  16. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  17. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  18. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  19. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  21. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  23. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  25. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  26. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  27. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  28. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  29. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  31. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  32. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  33. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  34. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  35. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  36. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  37. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  38. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  39. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  40. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  41. package/dist/agents/__tests__/detection.test.js +0 -89
  42. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  43. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  44. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  45. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  46. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  47. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  48. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  49. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  50. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  51. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  52. package/dist/agents/claude-code.d.ts +0 -59
  53. package/dist/agents/claude-code.js +0 -753
  54. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  55. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  56. package/dist/agents/claude-desktop.d.ts +0 -47
  57. package/dist/agents/claude-desktop.js +0 -684
  58. package/dist/agents/cline.d.ts +0 -15
  59. package/dist/agents/cline.js +0 -130
  60. package/dist/agents/codex.d.ts +0 -44
  61. package/dist/agents/codex.js +0 -453
  62. package/dist/agents/conversation-skills.d.ts +0 -18
  63. package/dist/agents/conversation-skills.js +0 -229
  64. package/dist/agents/cursor.d.ts +0 -35
  65. package/dist/agents/cursor.js +0 -294
  66. package/dist/agents/default-config.d.ts +0 -30
  67. package/dist/agents/default-config.js +0 -67
  68. package/dist/agents/defaults-merge.d.ts +0 -87
  69. package/dist/agents/defaults-merge.js +0 -150
  70. package/dist/agents/detect.d.ts +0 -4
  71. package/dist/agents/detect.js +0 -67
  72. package/dist/agents/detection.d.ts +0 -18
  73. package/dist/agents/detection.js +0 -94
  74. package/dist/agents/gemini.d.ts +0 -15
  75. package/dist/agents/gemini.js +0 -122
  76. package/dist/agents/generic-adapter.d.ts +0 -25
  77. package/dist/agents/generic-adapter.js +0 -151
  78. package/dist/agents/intro-skill.d.ts +0 -45
  79. package/dist/agents/intro-skill.js +0 -447
  80. package/dist/agents/registry-data.d.ts +0 -192
  81. package/dist/agents/registry-data.js +0 -669
  82. package/dist/agents/registry.d.ts +0 -13
  83. package/dist/agents/registry.js +0 -36
  84. package/dist/agents/runtime-detection.d.ts +0 -82
  85. package/dist/agents/runtime-detection.js +0 -271
  86. package/dist/agents/session-start-hook.d.ts +0 -37
  87. package/dist/agents/session-start-hook.js +0 -159
  88. package/dist/agents/types.d.ts +0 -171
  89. package/dist/agents/types.js +0 -75
  90. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  91. package/dist/agents/utils/instruction-hint.js +0 -108
  92. package/dist/agents/utils/json-config.d.ts +0 -19
  93. package/dist/agents/utils/json-config.js +0 -69
  94. package/dist/agents/utils/toml-config.d.ts +0 -8
  95. package/dist/agents/utils/toml-config.js +0 -27
  96. package/dist/agents/windsurf.d.ts +0 -14
  97. package/dist/agents/windsurf.js +0 -102
  98. package/dist/api/__tests__/client.test.d.ts +0 -1
  99. package/dist/api/__tests__/client.test.js +0 -272
  100. package/dist/api/client.d.ts +0 -326
  101. package/dist/api/client.js +0 -427
  102. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  103. package/dist/auth/__tests__/login-flow.test.js +0 -101
  104. package/dist/auth/__tests__/store.test.d.ts +0 -1
  105. package/dist/auth/__tests__/store.test.js +0 -132
  106. package/dist/auth/login-flow.d.ts +0 -26
  107. package/dist/auth/login-flow.js +0 -137
  108. package/dist/auth/store.d.ts +0 -5
  109. package/dist/auth/store.js +0 -62
  110. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  111. package/dist/commands/__tests__/clone-args.test.js +0 -51
  112. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  113. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  114. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  115. package/dist/commands/__tests__/info-merge.test.js +0 -55
  116. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  117. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  118. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  119. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  120. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  121. package/dist/commands/__tests__/setup.test.js +0 -81
  122. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  123. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  124. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  125. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  126. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  127. package/dist/commands/__tests__/upgrade.test.js +0 -157
  128. package/dist/commands/agents.d.ts +0 -2
  129. package/dist/commands/agents.js +0 -160
  130. package/dist/commands/api-keys.d.ts +0 -2
  131. package/dist/commands/api-keys.js +0 -95
  132. package/dist/commands/apps.d.ts +0 -2
  133. package/dist/commands/apps.js +0 -82
  134. package/dist/commands/build-plugin.d.ts +0 -2
  135. package/dist/commands/build-plugin.js +0 -135
  136. package/dist/commands/clone.d.ts +0 -60
  137. package/dist/commands/clone.js +0 -271
  138. package/dist/commands/components.d.ts +0 -2
  139. package/dist/commands/components.js +0 -43
  140. package/dist/commands/deploy.d.ts +0 -2
  141. package/dist/commands/deploy.js +0 -279
  142. package/dist/commands/dev.d.ts +0 -11
  143. package/dist/commands/dev.js +0 -1011
  144. package/dist/commands/doctor.d.ts +0 -2
  145. package/dist/commands/doctor.js +0 -230
  146. package/dist/commands/endpoints.d.ts +0 -2
  147. package/dist/commands/endpoints.js +0 -189
  148. package/dist/commands/entities.d.ts +0 -2
  149. package/dist/commands/entities.js +0 -198
  150. package/dist/commands/files.d.ts +0 -2
  151. package/dist/commands/files.js +0 -193
  152. package/dist/commands/inbox.d.ts +0 -11
  153. package/dist/commands/inbox.js +0 -60
  154. package/dist/commands/info.d.ts +0 -178
  155. package/dist/commands/info.js +0 -455
  156. package/dist/commands/init.d.ts +0 -21
  157. package/dist/commands/init.js +0 -185
  158. package/dist/commands/integrations.d.ts +0 -2
  159. package/dist/commands/integrations.js +0 -233
  160. package/dist/commands/login.d.ts +0 -2
  161. package/dist/commands/login.js +0 -44
  162. package/dist/commands/logout.d.ts +0 -2
  163. package/dist/commands/logout.js +0 -13
  164. package/dist/commands/logs.d.ts +0 -2
  165. package/dist/commands/logs.js +0 -232
  166. package/dist/commands/mcp-entries.d.ts +0 -13
  167. package/dist/commands/mcp-entries.js +0 -26
  168. package/dist/commands/mcp.d.ts +0 -2
  169. package/dist/commands/mcp.js +0 -245
  170. package/dist/commands/open.d.ts +0 -2
  171. package/dist/commands/open.js +0 -53
  172. package/dist/commands/resume.d.ts +0 -2
  173. package/dist/commands/resume.js +0 -289
  174. package/dist/commands/save-convo.d.ts +0 -8
  175. package/dist/commands/save-convo.js +0 -20
  176. package/dist/commands/schedules.d.ts +0 -2
  177. package/dist/commands/schedules.js +0 -221
  178. package/dist/commands/setup.d.ts +0 -27
  179. package/dist/commands/setup.js +0 -177
  180. package/dist/commands/share-convo.d.ts +0 -24
  181. package/dist/commands/share-convo.js +0 -167
  182. package/dist/commands/skills.d.ts +0 -2
  183. package/dist/commands/skills.js +0 -352
  184. package/dist/commands/sync-telemetry.d.ts +0 -33
  185. package/dist/commands/sync-telemetry.js +0 -186
  186. package/dist/commands/sync.d.ts +0 -37
  187. package/dist/commands/sync.js +0 -702
  188. package/dist/commands/uninstall.d.ts +0 -2
  189. package/dist/commands/uninstall.js +0 -145
  190. package/dist/commands/upgrade.d.ts +0 -14
  191. package/dist/commands/upgrade.js +0 -217
  192. package/dist/commands/validate.d.ts +0 -2
  193. package/dist/commands/validate.js +0 -89
  194. package/dist/commands/welcome.d.ts +0 -1
  195. package/dist/commands/welcome.js +0 -86
  196. package/dist/commands/workflows.d.ts +0 -2
  197. package/dist/commands/workflows.js +0 -187
  198. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  199. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  200. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  201. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  202. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  203. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  204. package/dist/deploy/deploy-state.d.ts +0 -36
  205. package/dist/deploy/deploy-state.js +0 -63
  206. package/dist/deploy/deploy-status.d.ts +0 -21
  207. package/dist/deploy/deploy-status.js +0 -36
  208. package/dist/deploy/detach.d.ts +0 -32
  209. package/dist/deploy/detach.js +0 -71
  210. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  211. package/dist/dev/__tests__/attach.test.js +0 -296
  212. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  213. package/dist/dev/__tests__/detach.test.js +0 -404
  214. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  215. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  216. package/dist/dev/__tests__/session.test.d.ts +0 -1
  217. package/dist/dev/__tests__/session.test.js +0 -446
  218. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  219. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  220. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  221. package/dist/dev/__tests__/stop.test.js +0 -172
  222. package/dist/dev/attach.d.ts +0 -120
  223. package/dist/dev/attach.js +0 -269
  224. package/dist/dev/detach.d.ts +0 -187
  225. package/dist/dev/detach.js +0 -292
  226. package/dist/dev/preview-url-poller.d.ts +0 -35
  227. package/dist/dev/preview-url-poller.js +0 -50
  228. package/dist/dev/session.d.ts +0 -175
  229. package/dist/dev/session.js +0 -258
  230. package/dist/dev/startup-sync.d.ts +0 -23
  231. package/dist/dev/startup-sync.js +0 -14
  232. package/dist/dev/stop.d.ts +0 -52
  233. package/dist/dev/stop.js +0 -101
  234. package/dist/devtools/registry-data.d.ts +0 -46
  235. package/dist/devtools/registry-data.js +0 -40
  236. package/dist/generated/bundled-types.d.ts +0 -1
  237. package/dist/generated/bundled-types.js +0 -46
  238. package/dist/generated/version.d.ts +0 -1
  239. package/dist/generated/version.js +0 -2
  240. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  241. package/dist/git/__tests__/auto-commit.test.js +0 -431
  242. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  243. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  244. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  245. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  246. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  247. package/dist/git/__tests__/credentials.test.js +0 -141
  248. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  249. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  251. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  252. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  253. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  254. package/dist/git/__tests__/identity.test.d.ts +0 -1
  255. package/dist/git/__tests__/identity.test.js +0 -146
  256. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  257. package/dist/git/__tests__/manifest.test.js +0 -446
  258. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  259. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  260. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  261. package/dist/git/__tests__/preflight.test.js +0 -36
  262. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  263. package/dist/git/__tests__/repo-config.test.js +0 -26
  264. package/dist/git/__tests__/sync.test.d.ts +0 -1
  265. package/dist/git/__tests__/sync.test.js +0 -405
  266. package/dist/git/auto-commit.d.ts +0 -35
  267. package/dist/git/auto-commit.js +0 -293
  268. package/dist/git/classify-sync-error.d.ts +0 -21
  269. package/dist/git/classify-sync-error.js +0 -111
  270. package/dist/git/credentials.d.ts +0 -75
  271. package/dist/git/credentials.js +0 -164
  272. package/dist/git/critical-files.d.ts +0 -20
  273. package/dist/git/critical-files.js +0 -68
  274. package/dist/git/deploy-guard.d.ts +0 -53
  275. package/dist/git/deploy-guard.js +0 -78
  276. package/dist/git/identity.d.ts +0 -44
  277. package/dist/git/identity.js +0 -133
  278. package/dist/git/preflight.d.ts +0 -57
  279. package/dist/git/preflight.js +0 -276
  280. package/dist/git/remote.d.ts +0 -37
  281. package/dist/git/remote.js +0 -75
  282. package/dist/git/repo-config.d.ts +0 -8
  283. package/dist/git/repo-config.js +0 -29
  284. package/dist/git/sync.d.ts +0 -15
  285. package/dist/git/sync.js +0 -159
  286. package/dist/health/__tests__/checks.test.d.ts +0 -1
  287. package/dist/health/__tests__/checks.test.js +0 -357
  288. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  289. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  290. package/dist/health/__tests__/fix.test.d.ts +0 -1
  291. package/dist/health/__tests__/fix.test.js +0 -72
  292. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  293. package/dist/health/__tests__/runner-filter.test.js +0 -61
  294. package/dist/health/checks.d.ts +0 -42
  295. package/dist/health/checks.js +0 -636
  296. package/dist/health/fix.d.ts +0 -22
  297. package/dist/health/fix.js +0 -62
  298. package/dist/health/runner.d.ts +0 -8
  299. package/dist/health/runner.js +0 -47
  300. package/dist/health/types.d.ts +0 -12
  301. package/dist/health/types.js +0 -1
  302. package/dist/index.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  304. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  305. package/dist/logs/tailer.d.ts +0 -17
  306. package/dist/logs/tailer.js +0 -217
  307. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  308. package/dist/sync/__tests__/change-detect.test.js +0 -123
  309. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  310. package/dist/sync/__tests__/hash.test.js +0 -18
  311. package/dist/sync/change-detect.d.ts +0 -19
  312. package/dist/sync/change-detect.js +0 -136
  313. package/dist/sync/conflict-ui.d.ts +0 -5
  314. package/dist/sync/conflict-ui.js +0 -78
  315. package/dist/sync/executor.d.ts +0 -23
  316. package/dist/sync/executor.js +0 -102
  317. package/dist/sync/hash.d.ts +0 -1
  318. package/dist/sync/hash.js +0 -4
  319. package/dist/sync/types.d.ts +0 -24
  320. package/dist/sync/types.js +0 -1
  321. package/dist/template/manifest.d.ts +0 -17
  322. package/dist/template/manifest.js +0 -145
  323. package/dist/tools/types.d.ts +0 -52
  324. package/dist/tools/types.js +0 -8
  325. package/dist/types-manager.d.ts +0 -1
  326. package/dist/types-manager.js +0 -35
  327. package/dist/types.d.ts +0 -349
  328. package/dist/types.js +0 -1
  329. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  330. package/dist/ui/__tests__/banner.test.js +0 -98
  331. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  332. package/dist/ui/__tests__/colors.test.js +0 -22
  333. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  334. package/dist/ui/__tests__/keyboard.test.js +0 -34
  335. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  336. package/dist/ui/__tests__/status-line.test.js +0 -54
  337. package/dist/ui/banner.d.ts +0 -29
  338. package/dist/ui/banner.js +0 -153
  339. package/dist/ui/colors.d.ts +0 -4
  340. package/dist/ui/colors.js +0 -7
  341. package/dist/ui/keyboard.d.ts +0 -12
  342. package/dist/ui/keyboard.js +0 -61
  343. package/dist/ui/status-line.d.ts +0 -6
  344. package/dist/ui/status-line.js +0 -53
  345. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  346. package/dist/utils/__tests__/format-error.test.js +0 -43
  347. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  348. package/dist/utils/__tests__/help-json.test.js +0 -39
  349. package/dist/utils/__tests__/http.test.d.ts +0 -1
  350. package/dist/utils/__tests__/http.test.js +0 -381
  351. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  352. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  353. package/dist/utils/__tests__/output.test.d.ts +0 -1
  354. package/dist/utils/__tests__/output.test.js +0 -38
  355. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  356. package/dist/utils/__tests__/prompt.test.js +0 -27
  357. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  358. package/dist/utils/__tests__/resolve.test.js +0 -95
  359. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  360. package/dist/utils/__tests__/sqlite.test.js +0 -89
  361. package/dist/utils/agent-guidance.d.ts +0 -47
  362. package/dist/utils/agent-guidance.js +0 -128
  363. package/dist/utils/app-info.d.ts +0 -70
  364. package/dist/utils/app-info.js +0 -167
  365. package/dist/utils/curl-parser.d.ts +0 -12
  366. package/dist/utils/curl-parser.js +0 -162
  367. package/dist/utils/data-input.d.ts +0 -1
  368. package/dist/utils/data-input.js +0 -38
  369. package/dist/utils/format-error.d.ts +0 -10
  370. package/dist/utils/format-error.js +0 -38
  371. package/dist/utils/fs.d.ts +0 -5
  372. package/dist/utils/fs.js +0 -23
  373. package/dist/utils/help-json.d.ts +0 -70
  374. package/dist/utils/help-json.js +0 -88
  375. package/dist/utils/http.d.ts +0 -46
  376. package/dist/utils/http.js +0 -421
  377. package/dist/utils/ignore-matcher.d.ts +0 -47
  378. package/dist/utils/ignore-matcher.js +0 -132
  379. package/dist/utils/output.d.ts +0 -17
  380. package/dist/utils/output.js +0 -27
  381. package/dist/utils/prompt.d.ts +0 -5
  382. package/dist/utils/prompt.js +0 -42
  383. package/dist/utils/resolve.d.ts +0 -12
  384. package/dist/utils/resolve.js +0 -52
  385. package/dist/utils/setup-state.d.ts +0 -3
  386. package/dist/utils/setup-state.js +0 -19
  387. package/dist/utils/sqlite-adapter.d.ts +0 -48
  388. package/dist/utils/sqlite-adapter.js +0 -147
  389. package/dist/utils/sqlite.d.ts +0 -14
  390. package/dist/utils/sqlite.js +0 -14
  391. package/dist/utils/subprocess.d.ts +0 -19
  392. package/dist/utils/subprocess.js +0 -27
  393. package/dist/utils/which.d.ts +0 -14
  394. package/dist/utils/which.js +0 -47
  395. package/dist/utils/zip.d.ts +0 -7
  396. package/dist/utils/zip.js +0 -42
  397. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  398. package/dist/validate/__tests__/validate.test.js +0 -42
  399. package/dist/validate/freshness.d.ts +0 -28
  400. package/dist/validate/freshness.js +0 -48
  401. package/dist/validate/preview.d.ts +0 -21
  402. package/dist/validate/preview.js +0 -39
  403. package/dist/workspace/resolve.d.ts +0 -19
  404. package/dist/workspace/resolve.js +0 -100
@@ -1,427 +0,0 @@
1
- import { httpFetch } from '../utils/http.js';
2
- const DEFAULT_BASE_URL = 'https://runwork.ai';
3
- export class ApiClient {
4
- baseUrl;
5
- apiKey;
6
- constructor(credentials) {
7
- this.baseUrl = credentials.baseUrl || DEFAULT_BASE_URL;
8
- this.apiKey = credentials.apiKey;
9
- }
10
- async request(path, options = {}) {
11
- const url = `${this.baseUrl}${path}`;
12
- const headers = {
13
- 'Content-Type': 'application/json',
14
- ...Object.fromEntries(Object.entries(options.headers || {}).filter(([, v]) => v !== undefined)),
15
- };
16
- if (this.apiKey) {
17
- headers['Authorization'] = `Bearer ${this.apiKey}`;
18
- }
19
- const response = await httpFetch(url, { ...options, headers });
20
- if (!response.ok) {
21
- const body = await response.text();
22
- throw new Error(`API error ${response.status}: ${body}`);
23
- }
24
- return response.json();
25
- }
26
- async listWorkspaces() {
27
- const res = await this.request('/api/dev/workspaces');
28
- return res.data;
29
- }
30
- async listApps(workspaceId) {
31
- const query = workspaceId ? `?workspaceId=${workspaceId}` : '';
32
- const res = await this.request(`/api/dev/apps${query}`);
33
- return res.data;
34
- }
35
- async getApp(appId) {
36
- const res = await this.request(`/api/dev/apps/${appId}`);
37
- return res.data;
38
- }
39
- async initApp(workspaceId, appName) {
40
- const res = await this.request('/api/dev/init', {
41
- method: 'POST',
42
- body: JSON.stringify({ workspaceId, appName }),
43
- });
44
- const app = res.data;
45
- // Server returns `appName` for init, normalize to `name`
46
- if (!app.name && app.appName) {
47
- app.name = app.appName;
48
- }
49
- return app;
50
- }
51
- async startDevSession(appId) {
52
- const res = await this.request('/api/dev/sessions', {
53
- method: 'POST',
54
- body: JSON.stringify({ appId }),
55
- });
56
- return res.data;
57
- }
58
- async getDevStatus(appId) {
59
- const res = await this.request(`/api/dev/status/${appId}`);
60
- return res.data;
61
- }
62
- async triggerDeploy(appId) {
63
- const res = await this.request(`/api/dev/deploy/${appId}`, {
64
- method: 'POST',
65
- });
66
- return res.data;
67
- }
68
- async initiateLogin() {
69
- const res = await this.request('/api/dev/auth/login', { method: 'POST' });
70
- return res.data;
71
- }
72
- async pollLogin(sessionId) {
73
- try {
74
- const res = await this.request(`/api/dev/auth/poll/${sessionId}`);
75
- return res.data;
76
- }
77
- catch {
78
- return null;
79
- }
80
- }
81
- async getAppSkill(appId) {
82
- const res = await this.request(`/api/dev/skill/${appId}`);
83
- return res.data;
84
- }
85
- async getPreviewLogs(appId) {
86
- const res = await this.request(`/api/dev/logs/${appId}/preview`);
87
- return res.data.logs;
88
- }
89
- async getProductionLogs(appId, options) {
90
- const params = new URLSearchParams();
91
- if (options?.limit !== undefined)
92
- params.set('limit', String(options.limit));
93
- if (options?.level)
94
- params.set('level', options.level);
95
- if (options?.search)
96
- params.set('search', options.search);
97
- if (options?.startTime)
98
- params.set('startTime', options.startTime);
99
- if (options?.endTime)
100
- params.set('endTime', options.endTime);
101
- const query = params.toString();
102
- const res = await this.request(`/api/dev/logs/${appId}/production${query ? `?${query}` : ''}`);
103
- return res.data;
104
- }
105
- async getAppEvents(appId, options) {
106
- const params = new URLSearchParams();
107
- if (options?.limit !== undefined)
108
- params.set('limit', String(options.limit));
109
- if (options?.type)
110
- params.set('type', options.type);
111
- if (options?.source)
112
- params.set('source', options.source);
113
- if (options?.before)
114
- params.set('before', options.before);
115
- const query = params.toString();
116
- const res = await this.request(`/api/dev/events/${appId}${query ? `?${query}` : ''}`);
117
- return res.data;
118
- }
119
- async downloadSkeleton() {
120
- const url = `${this.baseUrl}/api/dev/skeleton`;
121
- const headers = {};
122
- if (this.apiKey) {
123
- headers['Authorization'] = `Bearer ${this.apiKey}`;
124
- }
125
- const response = await httpFetch(url, { headers });
126
- if (!response.ok) {
127
- throw new Error(`Failed to download skeleton: ${response.status}`);
128
- }
129
- return response.arrayBuffer();
130
- }
131
- async syncFiles(appId, files, deletedFiles) {
132
- await this.request(`/api/dev/sync/${appId}`, {
133
- method: 'POST',
134
- body: JSON.stringify({ files, deletedFiles }),
135
- });
136
- }
137
- async searchIntegrations(query, limit = 20, workspaceId) {
138
- const params = new URLSearchParams({ q: query, limit: String(limit) });
139
- if (workspaceId)
140
- params.set('workspaceId', workspaceId);
141
- const res = await this.request(`/api/integrations/search?${params}`);
142
- return res.data;
143
- }
144
- async listConnectedIntegrations(workspaceId) {
145
- const res = await this.request(`/api/workspaces/${workspaceId}/integrations`);
146
- return res.data.integrations;
147
- }
148
- async getTeamIntegrationUsage(workspaceId) {
149
- const res = await this.request(`/api/workspaces/${workspaceId}/integrations/team-usage`);
150
- return res.data.usage;
151
- }
152
- /**
153
- * Get git remote URL for an app.
154
- * Both canonical ({baseUrl}/api/git/{workspaceId}/{appId}) and
155
- * subdomain ({slug}.runwork.ai/api/git/{appId}) formats are supported.
156
- */
157
- async getWorkspaceAll(workspaceId) {
158
- const res = await this.request(`/api/workspaces/${workspaceId}/all`);
159
- return res.data;
160
- }
161
- getGitRemoteUrl(workspaceId, appId) {
162
- return `${this.baseUrl}/api/git/${workspaceId}/${appId}`;
163
- }
164
- // --- Workspace Chat API (skills & MCP) ---
165
- async listWorkspaceSkills(workspaceId, includeContent = false) {
166
- const query = includeContent ? '?includeContent=true' : '';
167
- const res = await this.request(`/api/workspaces/${workspaceId}/skills${query}`);
168
- return res.data.skills;
169
- }
170
- async listExternalSkills(workspaceId) {
171
- const res = await this.request(`/api/workspaces/${workspaceId}/external-skills`);
172
- return res.data.skills;
173
- }
174
- async importExternalSkill(workspaceId, skill) {
175
- const res = await this.request(`/api/workspaces/${workspaceId}/external-skills`, { method: 'POST', body: JSON.stringify(skill) });
176
- return res.data.skill;
177
- }
178
- async updateExternalSkill(workspaceId, skillId, skill) {
179
- const res = await this.request(`/api/workspaces/${workspaceId}/external-skills/${skillId}`, { method: 'PUT', body: JSON.stringify(skill) });
180
- return res.data.skill;
181
- }
182
- async getAppSkillContent(workspaceId, appId) {
183
- const res = await this.request(`/api/workspaces/${workspaceId}/apps/${appId}/skill`);
184
- return res.data.skill;
185
- }
186
- async listMcpServers(workspaceId) {
187
- const res = await this.request(`/api/workspaces/${workspaceId}/mcp-servers`);
188
- return res.data.servers;
189
- }
190
- async addMcpServer(workspaceId, server) {
191
- const res = await this.request(`/api/workspaces/${workspaceId}/mcp-servers`, { method: 'POST', body: JSON.stringify(server) });
192
- return res.data.server;
193
- }
194
- async removeMcpServer(workspaceId, serverId) {
195
- await this.request(`/api/workspaces/${workspaceId}/mcp-servers/${serverId}`, { method: 'DELETE' });
196
- }
197
- /**
198
- * Resolve decrypted auth headers for header-auth MCP servers, scoped to the
199
- * authenticated user (their own + workspace-wide credentials). Keyed by server id.
200
- */
201
- async resolveMcpCredentials(workspaceId) {
202
- const res = await this.request(`/api/workspaces/${workspaceId}/mcp-credentials/resolved`);
203
- return res.data.servers;
204
- }
205
- // --- Community Marketplace ---
206
- async searchCommunitySkills(query, limit = 10, includeContent = false) {
207
- const res = await this.request(`/api/community/skills/search?q=${encodeURIComponent(query)}&limit=${limit}&include_content=${includeContent}`);
208
- return res.data;
209
- }
210
- async getCommunitySkillContent(source, skillId) {
211
- // source is "owner/repo", keep the slash as a path separator (route is /skills/:owner/:repo/:skillId)
212
- const encodedSource = source.split('/').map(encodeURIComponent).join('/');
213
- const res = await this.request(`/api/community/skills/${encodedSource}/${encodeURIComponent(skillId)}`);
214
- return res.data;
215
- }
216
- async searchCommunityMcpServers(query, limit = 20) {
217
- const res = await this.request(`/api/community/mcp-servers/search?q=${encodeURIComponent(query)}&limit=${limit}`);
218
- return res.data;
219
- }
220
- // --- Workspace Registry: Entities ---
221
- async listEntities(workspaceId) {
222
- const res = await this.request(`/api/workspaces/${workspaceId}/entities`);
223
- return res.data.entities;
224
- }
225
- async listEntityRecords(workspaceId, entityName, opts) {
226
- const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/list`, {
227
- method: 'POST',
228
- body: JSON.stringify({
229
- limit: opts?.limit,
230
- cursor: opts?.cursor,
231
- deploymentMode: opts?.deploymentMode,
232
- }),
233
- });
234
- return res.data;
235
- }
236
- async getEntityRecord(workspaceId, entityName, recordId) {
237
- const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`);
238
- return res.data;
239
- }
240
- async createEntityRecord(workspaceId, entityName, data) {
241
- const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}`, { method: 'POST', body: JSON.stringify({ data }) });
242
- return res.data;
243
- }
244
- async updateEntityRecord(workspaceId, entityName, recordId, data) {
245
- const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`, { method: 'PUT', body: JSON.stringify({ data }) });
246
- return res.data;
247
- }
248
- async deleteEntityRecord(workspaceId, entityName, recordId) {
249
- const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`, { method: 'DELETE' });
250
- return res.data;
251
- }
252
- // --- Workspace Registry: Workflows ---
253
- async listWorkflows(workspaceId) {
254
- const res = await this.request(`/api/workspaces/${workspaceId}/workflows?includeStatus=true`);
255
- return res.data.workflows;
256
- }
257
- async triggerWorkflow(workspaceId, opts) {
258
- const res = await this.request(`/api/workspaces/${workspaceId}/workflows/trigger`, { method: 'POST', body: JSON.stringify(opts) });
259
- return res.data;
260
- }
261
- async listWorkflowInstances(workspaceId, appId, opts) {
262
- const params = new URLSearchParams({ appId });
263
- if (opts?.workflowName)
264
- params.set('workflowName', opts.workflowName);
265
- if (opts?.status)
266
- params.set('status', opts.status);
267
- if (opts?.limit)
268
- params.set('limit', String(opts.limit));
269
- const res = await this.request(`/api/workspaces/${workspaceId}/workflows/instances?${params}`);
270
- return res.data;
271
- }
272
- async getWorkflowInstance(workspaceId, instanceId, appId) {
273
- const params = appId ? `?appId=${appId}` : '';
274
- const res = await this.request(`/api/workspaces/${workspaceId}/workflows/instances/${encodeURIComponent(instanceId)}${params}`);
275
- return res.data;
276
- }
277
- // --- Workspace Registry: Schedules ---
278
- async listSchedules(workspaceId) {
279
- const res = await this.request(`/api/workspaces/${workspaceId}/schedules?includeStatus=true`);
280
- return res.data.schedules;
281
- }
282
- async triggerSchedule(workspaceId, opts) {
283
- const res = await this.request(`/api/workspaces/${workspaceId}/schedules/trigger`, { method: 'POST', body: JSON.stringify(opts) });
284
- return res.data;
285
- }
286
- async getScheduleHistory(workspaceId, appId) {
287
- const res = await this.request(`/api/workspaces/${workspaceId}/schedules/history?appId=${appId}`);
288
- return res.data;
289
- }
290
- async getScheduleStatus(workspaceId, appId) {
291
- const res = await this.request(`/api/workspaces/${workspaceId}/schedules/status?appId=${appId}`);
292
- return res.data;
293
- }
294
- async pauseSchedule(workspaceId, scheduleName, appId) {
295
- await this.request(`/api/workspaces/${workspaceId}/schedules/${encodeURIComponent(scheduleName)}/pause?appId=${appId}`, { method: 'POST' });
296
- }
297
- async resumeSchedule(workspaceId, scheduleName, appId) {
298
- await this.request(`/api/workspaces/${workspaceId}/schedules/${encodeURIComponent(scheduleName)}/resume?appId=${appId}`, { method: 'POST' });
299
- }
300
- // --- Workspace Registry: Endpoints ---
301
- async listEndpoints(workspaceId) {
302
- const res = await this.request(`/api/workspaces/${workspaceId}/endpoints`);
303
- return res.data.endpoints;
304
- }
305
- // --- Workspace Registry: File Storage ---
306
- async listFileStorages(workspaceId) {
307
- const res = await this.request(`/api/workspaces/${workspaceId}/file-storages`);
308
- return res.data.fileStorages;
309
- }
310
- async listBucketFiles(workspaceId, bucketName, opts) {
311
- const params = new URLSearchParams();
312
- if (opts?.prefix)
313
- params.set('prefix', opts.prefix);
314
- if (opts?.delimiter)
315
- params.set('delimiter', opts.delimiter);
316
- const query = params.toString();
317
- const res = await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/files${query ? `?${query}` : ''}`);
318
- return res.data;
319
- }
320
- async getPresignedUrl(workspaceId, bucketName, opts) {
321
- const res = await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/presign`, { method: 'POST', body: JSON.stringify(opts) });
322
- return res.data;
323
- }
324
- async deleteBucketFile(workspaceId, bucketName, key) {
325
- await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/files?key=${encodeURIComponent(key)}`, { method: 'DELETE' });
326
- }
327
- // --- Workspace Registry: Components ---
328
- async listComponents(workspaceId) {
329
- const res = await this.request(`/api/workspaces/${workspaceId}/components`);
330
- return res.data.components;
331
- }
332
- // --- Workspace Registry: API Keys ---
333
- async listApiKeys(workspaceId) {
334
- const res = await this.request(`/api/workspaces/${workspaceId}/api-keys`);
335
- return res.data.apiKeys;
336
- }
337
- async createApiKey(workspaceId, opts) {
338
- const res = await this.request(`/api/workspaces/${workspaceId}/api-keys`, { method: 'POST', body: JSON.stringify(opts) });
339
- return res.data;
340
- }
341
- // --- Workspace Registry: Agents ---
342
- async listAgents(workspaceId) {
343
- const res = await this.request(`/api/workspaces/${workspaceId}/agents`);
344
- return res.data.agents;
345
- }
346
- async getAgentStatus(workspaceId, agentName, appId) {
347
- const res = await this.request(`/api/workspaces/${workspaceId}/agents/status`, { method: 'POST', body: JSON.stringify({ agentName, appId }) });
348
- return res.data;
349
- }
350
- async listAgentExecutions(workspaceId) {
351
- const res = await this.request(`/api/workspaces/${workspaceId}/agent-executions`);
352
- return res.data.executions;
353
- }
354
- async getAgentExecutionStream(workspaceId, sessionId) {
355
- const res = await this.request(`/api/workspaces/${workspaceId}/agent-executions/${encodeURIComponent(sessionId)}/stream`);
356
- return res.data.stream;
357
- }
358
- // --- Team Telemetry ---
359
- async getOnboardingConfig(workspaceId) {
360
- const res = await this.request(`/api/workspaces/${workspaceId}/onboarding-config`);
361
- return res.data;
362
- }
363
- async reportTelemetry(workspaceId, events) {
364
- await this.request(`/api/workspaces/${workspaceId}/team/telemetry`, { method: 'POST', body: JSON.stringify({ events }) });
365
- }
366
- // --- Shared Conversations ---
367
- async createSharedConversation(workspaceId, body) {
368
- const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations`, {
369
- method: 'POST',
370
- body: JSON.stringify(body),
371
- });
372
- return res.data;
373
- }
374
- async listSharedConversations(workspaceId, opts) {
375
- const search = new URLSearchParams();
376
- if (opts?.scope)
377
- search.set('scope', opts.scope);
378
- if (opts?.limit !== undefined)
379
- search.set('limit', String(opts.limit));
380
- if (opts?.offset !== undefined)
381
- search.set('offset', String(opts.offset));
382
- const query = search.toString() ? `?${search.toString()}` : '';
383
- const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations${query}`);
384
- return res.data;
385
- }
386
- async getSharedConversation(workspaceId, shareId) {
387
- const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}`);
388
- return res.data;
389
- }
390
- async downloadSharedConversationBundle(workspaceId, shareId, format) {
391
- const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}/bundle/${encodeURIComponent(format)}`);
392
- return res.data;
393
- }
394
- async markSharedConversationResumed(workspaceId, shareId) {
395
- const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}/resumed`, { method: 'POST' });
396
- return res.data;
397
- }
398
- // --- Integrations: Proxy Call ---
399
- async callIntegrationProxy(integrationDbId, method, path, opts) {
400
- const targetPath = opts?.query ? `${path}?${opts.query}` : path;
401
- const url = `${this.baseUrl}/api/proxy/integrations${targetPath}`;
402
- const headers = {
403
- 'X-Workspace-Integration-Id': integrationDbId,
404
- ...Object.fromEntries(Object.entries(opts?.headers || {})),
405
- };
406
- if (this.apiKey) {
407
- headers['Authorization'] = `Bearer ${this.apiKey}`;
408
- }
409
- if (opts?.body) {
410
- headers['Content-Type'] = 'application/json';
411
- }
412
- const response = await httpFetch(url, {
413
- method,
414
- headers,
415
- body: opts?.body ? JSON.stringify(opts.body) : undefined,
416
- });
417
- if (!response.ok) {
418
- const body = await response.text();
419
- throw new Error(`Integration proxy error ${response.status}: ${body}`);
420
- }
421
- const contentType = response.headers.get('content-type') || '';
422
- if (contentType.includes('application/json')) {
423
- return response.json();
424
- }
425
- return response.text();
426
- }
427
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,101 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- // Mock only the side-effect dependencies, not ApiClient
3
- vi.mock('../store.js', () => ({
4
- saveCredentials: vi.fn(),
5
- }));
6
- vi.mock('../../git/credentials.js', () => ({
7
- configureGitCredentials: vi.fn().mockResolvedValue(undefined),
8
- }));
9
- // HTTP goes through our `httpFetch` wrapper (single seam for diagnostics
10
- // and the optional `curl` transport). Tests mock that wrapper directly so
11
- // they exercise the same code path the production CLI uses.
12
- const mockFetch = vi.fn();
13
- vi.mock('../../utils/http.js', () => ({
14
- httpFetch: (...args) => mockFetch(...args),
15
- }));
16
- import { saveCredentials } from '../store.js';
17
- function jsonResponse(data, status = 200) {
18
- return {
19
- ok: status >= 200 && status < 300,
20
- status,
21
- statusText: '',
22
- url: '',
23
- headers: new Headers(),
24
- json: () => Promise.resolve(data),
25
- text: () => Promise.resolve(JSON.stringify(data)),
26
- arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
27
- };
28
- }
29
- beforeEach(() => {
30
- vi.clearAllMocks();
31
- vi.spyOn(console, 'log').mockImplementation(() => { });
32
- vi.spyOn(console, 'error').mockImplementation(() => { });
33
- });
34
- describe('performLoginNoOpen', () => {
35
- it('with printOnly prints URL and returns null without polling', async () => {
36
- mockFetch.mockResolvedValue(jsonResponse({
37
- data: { sessionId: 'sess-123', loginUrl: 'https://runwork.ai/cli-auth?session=sess-123' },
38
- }));
39
- const { performLoginNoOpen } = await import('../login-flow.js');
40
- const result = await performLoginNoOpen('https://runwork.ai', true);
41
- expect(console.log).toHaveBeenCalledWith('https://runwork.ai/cli-auth?session=sess-123');
42
- expect(result).toBeNull();
43
- expect(saveCredentials).not.toHaveBeenCalled();
44
- });
45
- });
46
- describe('performLoginWithApiKey', () => {
47
- it('validates key by listing workspaces and saves credentials', async () => {
48
- mockFetch.mockResolvedValue(jsonResponse({
49
- data: [{ id: 'ws-1', name: 'My Workspace' }],
50
- }));
51
- const { performLoginWithApiKey } = await import('../login-flow.js');
52
- const result = await performLoginWithApiKey('rw_test123');
53
- expect(saveCredentials).toHaveBeenCalledWith(expect.objectContaining({
54
- apiKey: 'rw_test123',
55
- defaultWorkspaceId: 'ws-1',
56
- defaultWorkspaceName: 'My Workspace',
57
- }));
58
- expect(result.apiKey).toBe('rw_test123');
59
- });
60
- it('saves credentials with custom base URL', async () => {
61
- mockFetch.mockResolvedValue(jsonResponse({ data: [{ id: 'ws-1', name: 'WS' }] }));
62
- const { performLoginWithApiKey } = await import('../login-flow.js');
63
- const result = await performLoginWithApiKey('rw_key', 'https://custom.runwork.dev');
64
- expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('https://custom.runwork.dev'), expect.anything());
65
- expect(result.baseUrl).toBe('https://custom.runwork.dev');
66
- });
67
- it('handles no workspaces (sets no default)', async () => {
68
- mockFetch.mockResolvedValue(jsonResponse({ data: [] }));
69
- const { performLoginWithApiKey } = await import('../login-flow.js');
70
- const result = await performLoginWithApiKey('rw_key');
71
- expect(saveCredentials).toHaveBeenCalledWith(expect.objectContaining({
72
- apiKey: 'rw_key',
73
- defaultWorkspaceId: undefined,
74
- defaultWorkspaceName: undefined,
75
- }));
76
- expect(result.apiKey).toBe('rw_key');
77
- });
78
- it('exits on invalid API key', async () => {
79
- mockFetch.mockResolvedValue({
80
- ok: false,
81
- status: 401,
82
- statusText: 'Unauthorized',
83
- url: '',
84
- headers: new Headers(),
85
- json: () => Promise.resolve({ error: 'Unauthorized' }),
86
- text: () => Promise.resolve('Unauthorized'),
87
- arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
88
- });
89
- const mockExit = vi.spyOn(process, 'exit').mockImplementation(((code) => {
90
- throw new Error(`process.exit(${code})`);
91
- }));
92
- try {
93
- const { performLoginWithApiKey } = await import('../login-flow.js');
94
- await expect(performLoginWithApiKey('bad-key')).rejects.toThrow('process.exit(1)');
95
- expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Invalid API key'));
96
- }
97
- finally {
98
- mockExit.mockRestore();
99
- }
100
- });
101
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,132 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('fs');
3
- vi.mock('os', () => ({
4
- homedir: () => '/tmp/test-runwork-home',
5
- }));
6
- const mockFs = await import('fs');
7
- const { getCredentials, saveCredentials, clearCredentials, requireAuth, } = await import('../store.js');
8
- const EXPECTED_DIR = '/tmp/test-runwork-home/.runwork';
9
- const EXPECTED_FILE = '/tmp/test-runwork-home/.runwork/.credentials';
10
- const validCredentials = {
11
- apiKey: 'test-api-key-123',
12
- email: 'test@example.com',
13
- baseUrl: 'https://runwork.ai',
14
- };
15
- describe('auth/store', () => {
16
- beforeEach(() => {
17
- vi.clearAllMocks();
18
- });
19
- describe('getCredentials()', () => {
20
- it('returns null when credentials file does not exist', () => {
21
- vi.mocked(mockFs.existsSync).mockReturnValue(false);
22
- const result = getCredentials();
23
- expect(result).toBeNull();
24
- expect(mockFs.existsSync).toHaveBeenCalledWith(EXPECTED_FILE);
25
- });
26
- it('returns parsed credentials when file exists with valid JSON', () => {
27
- vi.mocked(mockFs.existsSync).mockReturnValue(true);
28
- vi.mocked(mockFs.readFileSync).mockReturnValue(JSON.stringify(validCredentials));
29
- const result = getCredentials();
30
- expect(result).toEqual(validCredentials);
31
- expect(mockFs.readFileSync).toHaveBeenCalledWith(EXPECTED_FILE, 'utf-8');
32
- });
33
- it('returns null on malformed JSON', () => {
34
- vi.mocked(mockFs.existsSync).mockReturnValue(true);
35
- vi.mocked(mockFs.readFileSync).mockReturnValue('not valid json {{{');
36
- const result = getCredentials();
37
- expect(result).toBeNull();
38
- });
39
- it('returns null when readFileSync throws', () => {
40
- vi.mocked(mockFs.existsSync).mockReturnValue(true);
41
- vi.mocked(mockFs.readFileSync).mockImplementation(() => {
42
- throw new Error('EACCES: permission denied');
43
- });
44
- const result = getCredentials();
45
- expect(result).toBeNull();
46
- });
47
- });
48
- describe('saveCredentials()', () => {
49
- it('creates the .runwork directory recursively', () => {
50
- saveCredentials(validCredentials);
51
- expect(mockFs.mkdirSync).toHaveBeenCalledWith(EXPECTED_DIR, {
52
- recursive: true,
53
- });
54
- });
55
- it('writes JSON with 0o600 permissions', () => {
56
- saveCredentials(validCredentials);
57
- expect(mockFs.writeFileSync).toHaveBeenCalledWith(EXPECTED_FILE, JSON.stringify(validCredentials, null, 2), { mode: 0o600 });
58
- });
59
- it('stores the correct credential data', () => {
60
- const customCreds = {
61
- apiKey: 'custom-key',
62
- email: 'custom@test.com',
63
- baseUrl: 'https://custom.runwork.dev',
64
- };
65
- saveCredentials(customCreds);
66
- const writtenData = vi.mocked(mockFs.writeFileSync).mock.calls[0][1];
67
- const parsed = JSON.parse(writtenData);
68
- expect(parsed).toEqual(customCreds);
69
- });
70
- });
71
- describe('clearCredentials()', () => {
72
- it('deletes the credentials file when it exists', () => {
73
- vi.mocked(mockFs.existsSync).mockReturnValue(true);
74
- clearCredentials();
75
- expect(mockFs.unlinkSync).toHaveBeenCalledWith(EXPECTED_FILE);
76
- });
77
- it('does nothing when credentials file does not exist', () => {
78
- vi.mocked(mockFs.existsSync).mockReturnValue(false);
79
- clearCredentials();
80
- expect(mockFs.unlinkSync).not.toHaveBeenCalled();
81
- });
82
- });
83
- describe('requireAuth()', () => {
84
- it('returns credentials when logged in', () => {
85
- vi.mocked(mockFs.existsSync).mockReturnValue(true);
86
- vi.mocked(mockFs.readFileSync).mockReturnValue(JSON.stringify(validCredentials));
87
- const result = requireAuth();
88
- expect(result).toEqual(validCredentials);
89
- });
90
- it('exits process with code 1 with TTY guidance when invoked from a terminal', () => {
91
- vi.mocked(mockFs.existsSync).mockReturnValue(false);
92
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
93
- throw new Error('process.exit called');
94
- }));
95
- const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
96
- const previousTTY = process.stdin.isTTY;
97
- Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true });
98
- try {
99
- expect(() => requireAuth()).toThrow('process.exit called');
100
- expect(exitSpy).toHaveBeenCalledWith(1);
101
- expect(errorSpy).toHaveBeenCalledWith('Not logged in. Run `runwork login` first.');
102
- }
103
- finally {
104
- Object.defineProperty(process.stdin, 'isTTY', { value: previousTTY, configurable: true });
105
- exitSpy.mockRestore();
106
- errorSpy.mockRestore();
107
- }
108
- });
109
- it('exits process with code 1 with headless guidance when invoked without a TTY', () => {
110
- vi.mocked(mockFs.existsSync).mockReturnValue(false);
111
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
112
- throw new Error('process.exit called');
113
- }));
114
- const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
115
- const previousTTY = process.stdin.isTTY;
116
- Object.defineProperty(process.stdin, 'isTTY', { value: false, configurable: true });
117
- try {
118
- expect(() => requireAuth()).toThrow('process.exit called');
119
- expect(exitSpy).toHaveBeenCalledWith(1);
120
- const message = errorSpy.mock.calls[0]?.[0];
121
- expect(message).toContain('Not logged in.');
122
- expect(message).toContain('RUNWORK_API_KEY');
123
- expect(message).toContain('runwork login --api-key');
124
- }
125
- finally {
126
- Object.defineProperty(process.stdin, 'isTTY', { value: previousTTY, configurable: true });
127
- exitSpy.mockRestore();
128
- errorSpy.mockRestore();
129
- }
130
- });
131
- });
132
- });