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,404 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import * as fs from 'fs';
3
- import * as os from 'os';
4
- import * as path from 'path';
5
- import { buildChildArgs, pollForSession, runAsDetachedParent, isInternalDetachedChild, looksLikeBunStandaloneArtifact, stripInternalChildFlag, INTERNAL_DETACHED_CHILD_FLAG, } from '../detach.js';
6
- import { buildSessionFile, getSessionPaths, writeSessionFile, } from '../session.js';
7
- function createTmpAppDir() {
8
- return fs.mkdtempSync(path.join(os.tmpdir(), 'runwork-detach-test-'));
9
- }
10
- function makeSessionFile(overrides = {}) {
11
- return buildSessionFile({
12
- pid: 11111,
13
- sessionId: 'sess_test',
14
- appId: 'test-app',
15
- previewUrl: 'https://x.example',
16
- cliVersion: '0.10.2',
17
- mode: 'detached',
18
- deps: { bootTime: () => 1_000_000_000_000 },
19
- ...overrides,
20
- });
21
- }
22
- describe('isInternalDetachedChild() / stripInternalChildFlag()', () => {
23
- it('detects the internal marker', () => {
24
- expect(isInternalDetachedChild(['runwork', 'dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG])).toBe(true);
25
- expect(isInternalDetachedChild(['runwork', 'dev', '--detach'])).toBe(false);
26
- expect(isInternalDetachedChild(['runwork'])).toBe(false);
27
- });
28
- it('strips the marker but leaves other args alone', () => {
29
- expect(stripInternalChildFlag([
30
- 'dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG, '--json',
31
- ])).toEqual(['dev', '--detach', '--json']);
32
- expect(stripInternalChildFlag(['dev', '--detach'])).toEqual(['dev', '--detach']);
33
- });
34
- });
35
- describe('looksLikeBunStandaloneArtifact()', () => {
36
- it('detects Bun-on-Windows virtual-FS paths (forward slashes)', () => {
37
- expect(looksLikeBunStandaloneArtifact('B:/~BUN/root/runwork-windows-x64.exe')).toBe(true);
38
- expect(looksLikeBunStandaloneArtifact('C:/~BUN/root/foo.exe')).toBe(true);
39
- });
40
- it('detects Bun-on-Windows virtual-FS paths (backslashes)', () => {
41
- expect(looksLikeBunStandaloneArtifact('B:\\~BUN\\root\\runwork.exe')).toBe(true);
42
- });
43
- it('detects bunfs prefix on POSIX (defensive)', () => {
44
- expect(looksLikeBunStandaloneArtifact('/$bunfs/root/runwork')).toBe(true);
45
- });
46
- it('does not flag normal paths or arguments', () => {
47
- expect(looksLikeBunStandaloneArtifact('dev')).toBe(false);
48
- expect(looksLikeBunStandaloneArtifact('--detach')).toBe(false);
49
- expect(looksLikeBunStandaloneArtifact('/usr/local/bin/runwork')).toBe(false);
50
- expect(looksLikeBunStandaloneArtifact('C:/Users/Oytun/.runwork/bin/runwork.exe')).toBe(false);
51
- expect(looksLikeBunStandaloneArtifact('node')).toBe(false);
52
- });
53
- });
54
- describe('buildChildArgs()', () => {
55
- it('Node script invocation: forwards script path + user args, appends marker', () => {
56
- // node /path/to/dist/index.js dev --detach
57
- const argv = ['node', '/path/to/dist/index.js', 'dev', '--detach'];
58
- expect(buildChildArgs(argv)).toEqual([
59
- '/path/to/dist/index.js', 'dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG,
60
- ]);
61
- });
62
- it('Bun standalone macOS/Linux: forwards user args directly', () => {
63
- // /usr/local/bin/runwork dev --detach
64
- const argv = ['/usr/local/bin/runwork', 'dev', '--detach'];
65
- expect(buildChildArgs(argv)).toEqual([
66
- 'dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG,
67
- ]);
68
- });
69
- it('Bun standalone Windows: drops the virtual-FS argv[1] before forwarding', () => {
70
- // The exact failure from the field. Bun-on-Windows injects argv[1]
71
- // = "B:/~BUN/root/runwork-windows-x64.exe". We must NOT forward it
72
- // -- the child Bun runtime will inject its own.
73
- const argv = [
74
- 'C:\\Users\\Oytun\\.runwork\\bin\\runwork.exe',
75
- 'B:/~BUN/root/runwork-windows-x64.exe',
76
- 'dev',
77
- '--detach',
78
- ];
79
- expect(buildChildArgs(argv)).toEqual([
80
- 'dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG,
81
- ]);
82
- });
83
- it('strips an existing internal-child flag and re-adds exactly one', () => {
84
- const argv = [
85
- '/usr/local/bin/runwork',
86
- 'dev',
87
- '--detach',
88
- INTERNAL_DETACHED_CHILD_FLAG,
89
- INTERNAL_DETACHED_CHILD_FLAG,
90
- ];
91
- const out = buildChildArgs(argv);
92
- expect(out.filter((a) => a === INTERNAL_DETACHED_CHILD_FLAG)).toHaveLength(1);
93
- });
94
- it('preserves the order of user args and only mutates argv[0..1]', () => {
95
- const argv = [
96
- 'C:\\bin\\runwork.exe',
97
- 'B:/~BUN/root/runwork-windows-x64.exe',
98
- 'dev',
99
- '--restart',
100
- '--detach',
101
- '--json',
102
- ];
103
- expect(buildChildArgs(argv)).toEqual([
104
- 'dev', '--restart', '--detach', '--json', INTERNAL_DETACHED_CHILD_FLAG,
105
- ]);
106
- });
107
- it('handles an empty argv tail (just the binary)', () => {
108
- expect(buildChildArgs(['runwork'])).toEqual([INTERNAL_DETACHED_CHILD_FLAG]);
109
- });
110
- });
111
- describe('pollForSession()', () => {
112
- let appDir;
113
- beforeEach(() => {
114
- appDir = createTmpAppDir();
115
- });
116
- afterEach(() => {
117
- if (fs.existsSync(appDir)) {
118
- fs.rmSync(appDir, { recursive: true, force: true });
119
- }
120
- });
121
- it('returns "ready" immediately when the file is already present and matches', async () => {
122
- const file = makeSessionFile({ pid: 12345 });
123
- writeSessionFile(appDir, file);
124
- const out = await pollForSession(appDir, 12345, 'test-app', {
125
- intervalMs: 10,
126
- timeoutMs: 1000,
127
- });
128
- expect(out.result).toBe('ready');
129
- if (out.result === 'ready') {
130
- expect(out.file).toEqual(file);
131
- }
132
- });
133
- it('returns "ready" once the file appears mid-poll', async () => {
134
- setTimeout(() => {
135
- writeSessionFile(appDir, makeSessionFile({ pid: 22222 }));
136
- }, 80);
137
- const out = await pollForSession(appDir, 22222, 'test-app', {
138
- intervalMs: 20,
139
- timeoutMs: 1000,
140
- });
141
- expect(out.result).toBe('ready');
142
- });
143
- it('keeps polling past an intermediate empty-previewUrl write and resolves on the URL update', async () => {
144
- // Simulate the child writing the file early without a URL -- the
145
- // poller must NOT accept that as ready, and must wait for the URL
146
- // update.
147
- writeSessionFile(appDir, makeSessionFile({ pid: 33333, previewUrl: '' }));
148
- setTimeout(() => {
149
- writeSessionFile(appDir, makeSessionFile({ pid: 33333, previewUrl: 'https://late.example' }));
150
- }, 100);
151
- const out = await pollForSession(appDir, 33333, 'test-app', {
152
- intervalMs: 20,
153
- timeoutMs: 1000,
154
- });
155
- expect(out.result).toBe('ready');
156
- if (out.result === 'ready') {
157
- expect(out.file.previewUrl).toBe('https://late.example');
158
- }
159
- });
160
- it('returns "wrong-pid" when a file appears with a different pid (race winner)', async () => {
161
- writeSessionFile(appDir, makeSessionFile({ pid: 99999 }));
162
- const out = await pollForSession(appDir, 12345, 'test-app', {
163
- intervalMs: 10,
164
- timeoutMs: 500,
165
- });
166
- expect(out.result).toBe('wrong-pid');
167
- if (out.result === 'wrong-pid') {
168
- expect(out.file.pid).toBe(99999);
169
- }
170
- });
171
- it('keeps polling past a different-app file (foreign session file in the same dir)', async () => {
172
- // Edge case: the file's appId doesn't match the one we expect. We
173
- // ignore it (rather than treat as wrong-pid) so this kind of stale
174
- // cross-app contamination doesn't accidentally short-circuit our
175
- // detach handshake.
176
- writeSessionFile(appDir, makeSessionFile({ pid: 99999, appId: 'other-app' }));
177
- setTimeout(() => {
178
- writeSessionFile(appDir, makeSessionFile({ pid: 12345, appId: 'test-app' }));
179
- }, 80);
180
- const out = await pollForSession(appDir, 12345, 'test-app', {
181
- intervalMs: 20,
182
- timeoutMs: 1000,
183
- });
184
- expect(out.result).toBe('ready');
185
- if (out.result === 'ready') {
186
- expect(out.file.pid).toBe(12345);
187
- }
188
- });
189
- it('returns "timeout" when the file never appears', async () => {
190
- const out = await pollForSession(appDir, 12345, 'test-app', {
191
- intervalMs: 20,
192
- timeoutMs: 100,
193
- });
194
- expect(out.result).toBe('timeout');
195
- });
196
- it('returns "child-exited" mid-poll when isChildAlive flips to false', async () => {
197
- let alive = true;
198
- setTimeout(() => { alive = false; }, 60);
199
- const out = await pollForSession(appDir, 12345, 'test-app', {
200
- intervalMs: 20,
201
- timeoutMs: 1000,
202
- isChildAlive: () => alive,
203
- });
204
- expect(out.result).toBe('child-exited');
205
- });
206
- it('catches a child that exited just at the deadline (final probe)', async () => {
207
- // The child stays "alive" through the loop (no probe ever sees
208
- // false), but exits in the gap between the last sleep and the
209
- // deadline check. The trailing isChildAlive probe surfaces this
210
- // as child-exited rather than a misleading timeout.
211
- let probeCount = 0;
212
- const out = await pollForSession(appDir, 12345, 'test-app', {
213
- intervalMs: 20,
214
- timeoutMs: 60,
215
- isChildAlive: () => {
216
- probeCount += 1;
217
- // Only fail on the very last (post-loop) probe.
218
- return probeCount < 100;
219
- },
220
- });
221
- // We can hit either branch depending on probe ordering -- but with
222
- // a finite timeout we should never see "ready" or "wrong-pid".
223
- expect(['child-exited', 'timeout']).toContain(out.result);
224
- });
225
- });
226
- describe('runAsDetachedParent()', () => {
227
- let appDir;
228
- beforeEach(() => {
229
- appDir = createTmpAppDir();
230
- });
231
- afterEach(() => {
232
- if (fs.existsSync(appDir)) {
233
- fs.rmSync(appDir, { recursive: true, force: true });
234
- }
235
- });
236
- it('orchestrates spawn -> poll -> ready when the mock child writes the file', async () => {
237
- const childPid = 54321;
238
- const spawn = vi.fn(() => {
239
- // Schedule the "child" to write the session file shortly after spawn.
240
- setTimeout(() => {
241
- writeSessionFile(appDir, makeSessionFile({ pid: childPid, previewUrl: 'https://detached.example' }));
242
- }, 50);
243
- return {
244
- pid: childPid,
245
- kill: vi.fn(() => true),
246
- isAlive: () => true,
247
- };
248
- });
249
- const out = await runAsDetachedParent({
250
- appDir,
251
- expectedAppId: 'test-app',
252
- childArgs: ['dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG],
253
- intervalMs: 20,
254
- timeoutMs: 1000,
255
- spawn,
256
- });
257
- expect(spawn).toHaveBeenCalledOnce();
258
- expect(out.result).toBe('started');
259
- if (out.result === 'started') {
260
- expect(out.file.pid).toBe(childPid);
261
- expect(out.file.previewUrl).toBe('https://detached.example');
262
- }
263
- });
264
- it('on timeout: kills the child, removes our partial file, returns childLogTail when stderr exists', async () => {
265
- const kill = vi.fn(() => true);
266
- const spawn = vi.fn(() => {
267
- // Pre-create a stderr log with a known tail so we can assert it's
268
- // surfaced. The fake child does not write a session file.
269
- const paths = getSessionPaths(appDir);
270
- fs.mkdirSync(paths.dir, { recursive: true });
271
- fs.writeFileSync(paths.stderrLog, 'fatal: sandbox failed to boot\n', 'utf-8');
272
- return { pid: 12345, kill, isAlive: () => true };
273
- });
274
- const out = await runAsDetachedParent({
275
- appDir,
276
- expectedAppId: 'test-app',
277
- childArgs: ['dev', '--detach', INTERNAL_DETACHED_CHILD_FLAG],
278
- intervalMs: 20,
279
- timeoutMs: 80,
280
- spawn,
281
- });
282
- expect(out.result).toBe('timeout');
283
- if (out.result === 'timeout') {
284
- expect(out.ourPid).toBe(12345);
285
- expect(out.childLogTail).toContain('fatal: sandbox failed to boot');
286
- }
287
- expect(kill).toHaveBeenCalledWith('SIGTERM');
288
- });
289
- it('on timeout: leaves another process\'s session file untouched (PID-aware cleanup)', async () => {
290
- // Race: our child timed out, but in the meantime another process
291
- // wrote its OWN session file with a different PID. We must NOT
292
- // remove that file -- it belongs to the winner.
293
- const winnerFile = makeSessionFile({ pid: 99999, previewUrl: 'https://winner.example' });
294
- writeSessionFile(appDir, winnerFile);
295
- const spawn = vi.fn(() => ({
296
- pid: 12345,
297
- kill: vi.fn(() => true),
298
- // Pretend our child is alive (so we don't take the child-exited
299
- // path) but write nothing -- triggering timeout. wrong-pid would
300
- // also fire here since the file's appId matches; we use a
301
- // different appId on the file to isolate the timeout path.
302
- isAlive: () => true,
303
- }));
304
- // Overwrite with a foreign-app file so wrong-pid doesn't fire and
305
- // we land in the timeout branch.
306
- writeSessionFile(appDir, makeSessionFile({ pid: 99999, appId: 'other-app', previewUrl: 'https://other.example' }));
307
- const out = await runAsDetachedParent({
308
- appDir,
309
- expectedAppId: 'test-app',
310
- childArgs: [],
311
- intervalMs: 10,
312
- timeoutMs: 80,
313
- spawn,
314
- });
315
- expect(out.result).toBe('timeout');
316
- // The foreign file is still there.
317
- const stillThere = fs.existsSync(getSessionPaths(appDir).file);
318
- expect(stillThere).toBe(true);
319
- });
320
- it('returns "spawn-failed" when the spawn override throws', async () => {
321
- const spawn = vi.fn(() => { throw new Error('execvp: ENOENT'); });
322
- const out = await runAsDetachedParent({
323
- appDir,
324
- expectedAppId: 'test-app',
325
- childArgs: [],
326
- intervalMs: 10,
327
- timeoutMs: 100,
328
- spawn,
329
- });
330
- expect(out.result).toBe('spawn-failed');
331
- });
332
- it('returns "spawn-failed" when the child has no pid', async () => {
333
- const spawn = vi.fn(() => ({ pid: 0, kill: vi.fn(() => true), isAlive: () => true }));
334
- const out = await runAsDetachedParent({
335
- appDir,
336
- expectedAppId: 'test-app',
337
- childArgs: [],
338
- intervalMs: 10,
339
- timeoutMs: 100,
340
- spawn,
341
- });
342
- expect(out.result).toBe('spawn-failed');
343
- });
344
- it('returns "wrong-pid" AND kills the child when another process wins the write race', async () => {
345
- // Codex review #2: leaving the loser child running would cause it
346
- // to overwrite the winner's session file moments later. Killing
347
- // the loser is the correct behavior.
348
- const kill = vi.fn(() => true);
349
- const spawn = vi.fn(() => {
350
- setTimeout(() => {
351
- writeSessionFile(appDir, makeSessionFile({ pid: 99999, previewUrl: 'https://winner.example' }));
352
- }, 30);
353
- return { pid: 12345, kill, isAlive: () => true };
354
- });
355
- const out = await runAsDetachedParent({
356
- appDir,
357
- expectedAppId: 'test-app',
358
- childArgs: [],
359
- intervalMs: 10,
360
- timeoutMs: 1000,
361
- spawn,
362
- });
363
- expect(out.result).toBe('wrong-pid');
364
- if (out.result === 'wrong-pid') {
365
- expect(out.ourPid).toBe(12345);
366
- expect(out.file.pid).toBe(99999);
367
- }
368
- expect(kill).toHaveBeenCalledWith('SIGTERM');
369
- });
370
- it('returns "child-exited" promptly when the spawned child dies before writing the session file', async () => {
371
- // Codex review #1: without an isAlive probe, a fast-failing child
372
- // (missing auth, sync conflict, etc.) leaves the parent hanging
373
- // for the full 90s timeout instead of surfacing the failure.
374
- const paths = getSessionPaths(appDir);
375
- fs.mkdirSync(paths.dir, { recursive: true });
376
- fs.writeFileSync(paths.stderrLog, 'fatal: not authenticated\n', 'utf-8');
377
- let alive = true;
378
- const kill = vi.fn(() => true);
379
- const spawn = vi.fn(() => {
380
- // Simulate the child dying ~50ms after spawn (well before the
381
- // 1000ms timeout), without ever writing a session file.
382
- setTimeout(() => { alive = false; }, 50);
383
- return { pid: 12345, kill, isAlive: () => alive };
384
- });
385
- const start = Date.now();
386
- const out = await runAsDetachedParent({
387
- appDir,
388
- expectedAppId: 'test-app',
389
- childArgs: [],
390
- intervalMs: 20,
391
- timeoutMs: 1000,
392
- spawn,
393
- });
394
- const elapsed = Date.now() - start;
395
- expect(out.result).toBe('child-exited');
396
- if (out.result === 'child-exited') {
397
- expect(out.ourPid).toBe(12345);
398
- expect(out.childLogTail).toContain('fatal: not authenticated');
399
- }
400
- // The whole point of this fix: we should resolve far below the
401
- // timeout, not at 1000ms. Allow a generous bound for CI noise.
402
- expect(elapsed).toBeLessThan(500);
403
- });
404
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,149 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { startPreviewUrlPoller } from '../preview-url-poller.js';
3
- function makeClient(getDevStatus) {
4
- return { getDevStatus };
5
- }
6
- describe('startPreviewUrlPoller', () => {
7
- beforeEach(() => {
8
- vi.useFakeTimers();
9
- });
10
- afterEach(() => {
11
- vi.useRealTimers();
12
- });
13
- it('does not fire onChange when the URL stays the same', async () => {
14
- const onChange = vi.fn();
15
- const getDevStatus = vi.fn().mockResolvedValue({
16
- previewUrl: 'https://stable.example',
17
- sessionId: 's',
18
- appId: 'a',
19
- });
20
- const poller = startPreviewUrlPoller({
21
- client: makeClient(getDevStatus),
22
- appId: 'a',
23
- initialUrl: 'https://stable.example',
24
- intervalMs: 1000,
25
- onChange,
26
- });
27
- await vi.advanceTimersByTimeAsync(2500);
28
- expect(getDevStatus).toHaveBeenCalled();
29
- expect(onChange).not.toHaveBeenCalled();
30
- expect(poller.getCurrent()).toBe('https://stable.example');
31
- poller.stop();
32
- });
33
- it('fires onChange with previous URL and updates getCurrent() when the URL rotates', async () => {
34
- const onChange = vi.fn();
35
- const getDevStatus = vi.fn()
36
- .mockResolvedValueOnce({ previewUrl: 'https://old.example', sessionId: 's', appId: 'a' })
37
- .mockResolvedValue({ previewUrl: 'https://new.example', sessionId: 's', appId: 'a' });
38
- const poller = startPreviewUrlPoller({
39
- client: makeClient(getDevStatus),
40
- appId: 'a',
41
- initialUrl: 'https://old.example',
42
- intervalMs: 1000,
43
- onChange,
44
- });
45
- // First tick at t=1000 returns the unchanged URL: no onChange.
46
- await vi.advanceTimersByTimeAsync(1500);
47
- expect(onChange).not.toHaveBeenCalled();
48
- expect(poller.getCurrent()).toBe('https://old.example');
49
- // Second tick at t=2000 returns a new URL: onChange fires.
50
- await vi.advanceTimersByTimeAsync(1000);
51
- expect(onChange).toHaveBeenCalledTimes(1);
52
- expect(onChange).toHaveBeenCalledWith('https://new.example', 'https://old.example');
53
- expect(poller.getCurrent()).toBe('https://new.example');
54
- poller.stop();
55
- });
56
- it('ignores transient empty URLs from the server (sandbox restart in flight)', async () => {
57
- const onChange = vi.fn();
58
- // Server briefly reports "" while replacing the sandbox; we should
59
- // hold the last known good URL rather than flicker the status line.
60
- const getDevStatus = vi.fn().mockResolvedValue({
61
- previewUrl: '',
62
- sessionId: 's',
63
- appId: 'a',
64
- });
65
- const poller = startPreviewUrlPoller({
66
- client: makeClient(getDevStatus),
67
- appId: 'a',
68
- initialUrl: 'https://stable.example',
69
- intervalMs: 1000,
70
- onChange,
71
- });
72
- await vi.advanceTimersByTimeAsync(3000);
73
- expect(onChange).not.toHaveBeenCalled();
74
- expect(poller.getCurrent()).toBe('https://stable.example');
75
- poller.stop();
76
- });
77
- it('keeps polling after a failed fetch and reports the error', async () => {
78
- const onChange = vi.fn();
79
- const onError = vi.fn();
80
- const getDevStatus = vi.fn()
81
- .mockRejectedValueOnce(new Error('network down'))
82
- .mockResolvedValue({ previewUrl: 'https://recovered.example', sessionId: 's', appId: 'a' });
83
- const poller = startPreviewUrlPoller({
84
- client: makeClient(getDevStatus),
85
- appId: 'a',
86
- initialUrl: 'https://old.example',
87
- intervalMs: 1000,
88
- onChange,
89
- onError,
90
- });
91
- // First tick rejects.
92
- await vi.advanceTimersByTimeAsync(1500);
93
- expect(onError).toHaveBeenCalledTimes(1);
94
- expect(onChange).not.toHaveBeenCalled();
95
- expect(poller.getCurrent()).toBe('https://old.example');
96
- // Second tick recovers.
97
- await vi.advanceTimersByTimeAsync(1000);
98
- expect(onChange).toHaveBeenCalledWith('https://recovered.example', 'https://old.example');
99
- expect(poller.getCurrent()).toBe('https://recovered.example');
100
- poller.stop();
101
- });
102
- it('stop() cancels future polls', async () => {
103
- const onChange = vi.fn();
104
- const getDevStatus = vi.fn().mockResolvedValue({
105
- previewUrl: 'https://new.example',
106
- sessionId: 's',
107
- appId: 'a',
108
- });
109
- const poller = startPreviewUrlPoller({
110
- client: makeClient(getDevStatus),
111
- appId: 'a',
112
- initialUrl: 'https://old.example',
113
- intervalMs: 1000,
114
- onChange,
115
- });
116
- poller.stop();
117
- await vi.advanceTimersByTimeAsync(5000);
118
- expect(getDevStatus).not.toHaveBeenCalled();
119
- expect(onChange).not.toHaveBeenCalled();
120
- });
121
- it('skips overlapping ticks while a previous fetch is still in flight', async () => {
122
- const onChange = vi.fn();
123
- let resolveFirst;
124
- const getDevStatus = vi.fn().mockImplementation(() => {
125
- // First call returns a promise that we control manually; subsequent
126
- // calls would resolve immediately, but the in-flight guard should
127
- // prevent them from firing at all.
128
- if (!resolveFirst) {
129
- return new Promise((r) => { resolveFirst = r; });
130
- }
131
- return Promise.resolve({ previewUrl: 'https://later.example', sessionId: 's', appId: 'a' });
132
- });
133
- const poller = startPreviewUrlPoller({
134
- client: makeClient(getDevStatus),
135
- appId: 'a',
136
- initialUrl: 'https://initial.example',
137
- intervalMs: 1000,
138
- onChange,
139
- });
140
- // Fire several intervals while the first fetch is still pending.
141
- await vi.advanceTimersByTimeAsync(4500);
142
- expect(getDevStatus).toHaveBeenCalledTimes(1);
143
- // Resolve it and advance one more interval -- now the next tick fires.
144
- resolveFirst({ previewUrl: 'https://initial.example', sessionId: 's', appId: 'a' });
145
- await vi.advanceTimersByTimeAsync(1000);
146
- expect(getDevStatus).toHaveBeenCalledTimes(2);
147
- poller.stop();
148
- });
149
- });
@@ -1 +0,0 @@
1
- export {};