charness 3.7.0 → 3.8.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 (359) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/DEVELOPMENT.md +6 -2
  3. package/README.md +5 -5
  4. package/SETUP.md +16 -5
  5. package/agent-plugin/skills/charness-manager/SKILL.md +3 -3
  6. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  7. package/dist/adapters/openCodeAdapter.js +2 -1
  8. package/dist/adapters/openCodeAdapter.js.map +1 -1
  9. package/dist/bot.d.ts.map +1 -1
  10. package/dist/bot.js +50 -9
  11. package/dist/bot.js.map +1 -1
  12. package/dist/cli.js +44 -1
  13. package/dist/cli.js.map +1 -1
  14. package/dist/configDirFile.d.ts +7 -3
  15. package/dist/configDirFile.d.ts.map +1 -1
  16. package/dist/configDirFile.js +12 -5
  17. package/dist/configDirFile.js.map +1 -1
  18. package/dist/connectors/telegram/commands/botCore.d.ts +5 -1
  19. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  20. package/dist/connectors/telegram/commands/runners.d.ts +52 -0
  21. package/dist/connectors/telegram/commands/runners.d.ts.map +1 -0
  22. package/dist/connectors/telegram/commands/runners.js +486 -0
  23. package/dist/connectors/telegram/commands/runners.js.map +1 -0
  24. package/dist/connectors/telegram/runnerPairingMessages.d.ts +27 -0
  25. package/dist/connectors/telegram/runnerPairingMessages.d.ts.map +1 -0
  26. package/dist/connectors/telegram/runnerPairingMessages.js +105 -0
  27. package/dist/connectors/telegram/runnerPairingMessages.js.map +1 -0
  28. package/dist/i18n/de.d.ts.map +1 -1
  29. package/dist/i18n/de.js +58 -0
  30. package/dist/i18n/de.js.map +1 -1
  31. package/dist/i18n/en.d.ts.map +1 -1
  32. package/dist/i18n/en.js +58 -0
  33. package/dist/i18n/en.js.map +1 -1
  34. package/dist/i18n/es.d.ts.map +1 -1
  35. package/dist/i18n/es.js +58 -0
  36. package/dist/i18n/es.js.map +1 -1
  37. package/dist/i18n/fr.d.ts.map +1 -1
  38. package/dist/i18n/fr.js +58 -0
  39. package/dist/i18n/fr.js.map +1 -1
  40. package/dist/i18n/hi.d.ts.map +1 -1
  41. package/dist/i18n/hi.js +58 -0
  42. package/dist/i18n/hi.js.map +1 -1
  43. package/dist/i18n/ja.d.ts.map +1 -1
  44. package/dist/i18n/ja.js +58 -0
  45. package/dist/i18n/ja.js.map +1 -1
  46. package/dist/i18n/ka.d.ts.map +1 -1
  47. package/dist/i18n/ka.js +58 -0
  48. package/dist/i18n/ka.js.map +1 -1
  49. package/dist/i18n/pt.d.ts.map +1 -1
  50. package/dist/i18n/pt.js +58 -0
  51. package/dist/i18n/pt.js.map +1 -1
  52. package/dist/i18n/ru.d.ts.map +1 -1
  53. package/dist/i18n/ru.js +58 -0
  54. package/dist/i18n/ru.js.map +1 -1
  55. package/dist/i18n/uk.d.ts.map +1 -1
  56. package/dist/i18n/uk.js +58 -0
  57. package/dist/i18n/uk.js.map +1 -1
  58. package/dist/i18n/uz.d.ts.map +1 -1
  59. package/dist/i18n/uz.js +58 -0
  60. package/dist/i18n/uz.js.map +1 -1
  61. package/dist/i18n/zh.d.ts.map +1 -1
  62. package/dist/i18n/zh.js +58 -0
  63. package/dist/i18n/zh.js.map +1 -1
  64. package/dist/installManager.d.ts +57 -1
  65. package/dist/installManager.d.ts.map +1 -1
  66. package/dist/installManager.js +88 -10
  67. package/dist/installManager.js.map +1 -1
  68. package/dist/instanceSettings.d.ts +12 -2
  69. package/dist/instanceSettings.d.ts.map +1 -1
  70. package/dist/instanceSettings.js +17 -3
  71. package/dist/instanceSettings.js.map +1 -1
  72. package/dist/outputTrace.d.ts +6 -0
  73. package/dist/outputTrace.d.ts.map +1 -1
  74. package/dist/outputTrace.js +24 -1
  75. package/dist/outputTrace.js.map +1 -1
  76. package/dist/remoteRun/cliArgs.d.ts +2 -0
  77. package/dist/remoteRun/cliArgs.d.ts.map +1 -1
  78. package/dist/remoteRun/cliArgs.js +11 -2
  79. package/dist/remoteRun/cliArgs.js.map +1 -1
  80. package/dist/remoteRun/commands.d.ts +21 -0
  81. package/dist/remoteRun/commands.d.ts.map +1 -1
  82. package/dist/remoteRun/commands.js +38 -17
  83. package/dist/remoteRun/commands.js.map +1 -1
  84. package/dist/remoteRun/interrupts.d.ts +10 -0
  85. package/dist/remoteRun/interrupts.d.ts.map +1 -1
  86. package/dist/remoteRun/interrupts.js +43 -6
  87. package/dist/remoteRun/interrupts.js.map +1 -1
  88. package/dist/remoteRun/output.d.ts +2 -0
  89. package/dist/remoteRun/output.d.ts.map +1 -1
  90. package/dist/remoteRun/output.js +45 -0
  91. package/dist/remoteRun/output.js.map +1 -1
  92. package/dist/remoteRun/pairedRunners.d.ts +51 -0
  93. package/dist/remoteRun/pairedRunners.d.ts.map +1 -0
  94. package/dist/remoteRun/pairedRunners.js +165 -0
  95. package/dist/remoteRun/pairedRunners.js.map +1 -0
  96. package/dist/remoteRun/probe.d.ts +23 -1
  97. package/dist/remoteRun/probe.d.ts.map +1 -1
  98. package/dist/remoteRun/probe.js +45 -11
  99. package/dist/remoteRun/probe.js.map +1 -1
  100. package/dist/remoteRun/remoteRunCli.d.ts +13 -6
  101. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -1
  102. package/dist/remoteRun/remoteRunCli.js +34 -59
  103. package/dist/remoteRun/remoteRunCli.js.map +1 -1
  104. package/dist/remoteRun/runnerClient.d.ts +2 -0
  105. package/dist/remoteRun/runnerClient.d.ts.map +1 -1
  106. package/dist/remoteRun/runnerClient.js +5 -1
  107. package/dist/remoteRun/runnerClient.js.map +1 -1
  108. package/dist/remoteRun/runnerSummary.d.ts +24 -0
  109. package/dist/remoteRun/runnerSummary.d.ts.map +1 -0
  110. package/dist/remoteRun/runnerSummary.js +86 -0
  111. package/dist/remoteRun/runnerSummary.js.map +1 -0
  112. package/dist/remoteRun/runnerWait.d.ts +68 -0
  113. package/dist/remoteRun/runnerWait.d.ts.map +1 -0
  114. package/dist/remoteRun/runnerWait.js +137 -0
  115. package/dist/remoteRun/runnerWait.js.map +1 -0
  116. package/dist/remoteRun/runnerWaitTiming.d.ts +16 -0
  117. package/dist/remoteRun/runnerWaitTiming.d.ts.map +1 -0
  118. package/dist/remoteRun/runnerWaitTiming.js +37 -0
  119. package/dist/remoteRun/runnerWaitTiming.js.map +1 -0
  120. package/dist/remoteRun/runners.d.ts +7 -7
  121. package/dist/remoteRun/runners.d.ts.map +1 -1
  122. package/dist/remoteRun/runners.js +45 -17
  123. package/dist/remoteRun/runners.js.map +1 -1
  124. package/dist/remoteRun/runnersCatalog.d.ts +14 -0
  125. package/dist/remoteRun/runnersCatalog.d.ts.map +1 -0
  126. package/dist/remoteRun/runnersCatalog.js +68 -0
  127. package/dist/remoteRun/runnersCatalog.js.map +1 -0
  128. package/dist/remoteRun/runnersConfig.d.ts +29 -20
  129. package/dist/remoteRun/runnersConfig.d.ts.map +1 -1
  130. package/dist/remoteRun/runnersConfig.js +14 -12
  131. package/dist/remoteRun/runnersConfig.js.map +1 -1
  132. package/dist/remoteRun/ssh.d.ts +22 -2
  133. package/dist/remoteRun/ssh.d.ts.map +1 -1
  134. package/dist/remoteRun/ssh.js +41 -7
  135. package/dist/remoteRun/ssh.js.map +1 -1
  136. package/dist/runnerUtility/adminCheck.d.ts +11 -0
  137. package/dist/runnerUtility/adminCheck.d.ts.map +1 -0
  138. package/dist/runnerUtility/adminCheck.js +68 -0
  139. package/dist/runnerUtility/adminCheck.js.map +1 -0
  140. package/dist/runnerUtility/appInstall.d.ts +25 -0
  141. package/dist/runnerUtility/appInstall.d.ts.map +1 -0
  142. package/dist/runnerUtility/appInstall.js +147 -0
  143. package/dist/runnerUtility/appInstall.js.map +1 -0
  144. package/dist/runnerUtility/appUpdate.d.ts +39 -0
  145. package/dist/runnerUtility/appUpdate.d.ts.map +1 -0
  146. package/dist/runnerUtility/appUpdate.js +90 -0
  147. package/dist/runnerUtility/appUpdate.js.map +1 -0
  148. package/dist/runnerUtility/execEnv.d.ts +21 -0
  149. package/dist/runnerUtility/execEnv.d.ts.map +1 -0
  150. package/dist/runnerUtility/execEnv.js +109 -0
  151. package/dist/runnerUtility/execEnv.js.map +1 -0
  152. package/dist/runnerUtility/execSession.d.ts +13 -0
  153. package/dist/runnerUtility/execSession.d.ts.map +1 -0
  154. package/dist/runnerUtility/execSession.js +58 -0
  155. package/dist/runnerUtility/execSession.js.map +1 -0
  156. package/dist/runnerUtility/hubClient.d.ts +30 -0
  157. package/dist/runnerUtility/hubClient.d.ts.map +1 -0
  158. package/dist/runnerUtility/hubClient.js +127 -0
  159. package/dist/runnerUtility/hubClient.js.map +1 -0
  160. package/dist/runnerUtility/injectStream.d.ts +9 -0
  161. package/dist/runnerUtility/injectStream.d.ts.map +1 -0
  162. package/dist/runnerUtility/injectStream.js +12 -0
  163. package/dist/runnerUtility/injectStream.js.map +1 -0
  164. package/dist/runnerUtility/iosCheck.d.ts +62 -0
  165. package/dist/runnerUtility/iosCheck.d.ts.map +1 -0
  166. package/dist/runnerUtility/iosCheck.js +200 -0
  167. package/dist/runnerUtility/iosCheck.js.map +1 -0
  168. package/dist/runnerUtility/launcher.d.ts +5 -0
  169. package/dist/runnerUtility/launcher.d.ts.map +1 -0
  170. package/dist/runnerUtility/launcher.js +85 -0
  171. package/dist/runnerUtility/launcher.js.map +1 -0
  172. package/dist/runnerUtility/linkLoop.d.ts +47 -0
  173. package/dist/runnerUtility/linkLoop.d.ts.map +1 -0
  174. package/dist/runnerUtility/linkLoop.js +281 -0
  175. package/dist/runnerUtility/linkLoop.js.map +1 -0
  176. package/dist/runnerUtility/localLinkStop.d.ts +23 -0
  177. package/dist/runnerUtility/localLinkStop.d.ts.map +1 -0
  178. package/dist/runnerUtility/localLinkStop.js +79 -0
  179. package/dist/runnerUtility/localLinkStop.js.map +1 -0
  180. package/dist/runnerUtility/machineReport.d.ts +39 -0
  181. package/dist/runnerUtility/machineReport.d.ts.map +1 -0
  182. package/dist/runnerUtility/machineReport.js +161 -0
  183. package/dist/runnerUtility/machineReport.js.map +1 -0
  184. package/dist/runnerUtility/packageId.d.ts +5 -0
  185. package/dist/runnerUtility/packageId.d.ts.map +1 -0
  186. package/dist/runnerUtility/packageId.js +64 -0
  187. package/dist/runnerUtility/packageId.js.map +1 -0
  188. package/dist/runnerUtility/pairingRecovery.d.ts +31 -0
  189. package/dist/runnerUtility/pairingRecovery.d.ts.map +1 -0
  190. package/dist/runnerUtility/pairingRecovery.js +24 -0
  191. package/dist/runnerUtility/pairingRecovery.js.map +1 -0
  192. package/dist/runnerUtility/pueueDaemon.d.ts +36 -0
  193. package/dist/runnerUtility/pueueDaemon.d.ts.map +1 -0
  194. package/dist/runnerUtility/pueueDaemon.js +165 -0
  195. package/dist/runnerUtility/pueueDaemon.js.map +1 -0
  196. package/dist/runnerUtility/runnerCli.d.ts +18 -0
  197. package/dist/runnerUtility/runnerCli.d.ts.map +1 -0
  198. package/dist/runnerUtility/runnerCli.js +184 -0
  199. package/dist/runnerUtility/runnerCli.js.map +1 -0
  200. package/dist/runnerUtility/runnerCommands.d.ts +67 -0
  201. package/dist/runnerUtility/runnerCommands.d.ts.map +1 -0
  202. package/dist/runnerUtility/runnerCommands.js +418 -0
  203. package/dist/runnerUtility/runnerCommands.js.map +1 -0
  204. package/dist/runnerUtility/runnerConfig.d.ts +63 -0
  205. package/dist/runnerUtility/runnerConfig.d.ts.map +1 -0
  206. package/dist/runnerUtility/runnerConfig.js +153 -0
  207. package/dist/runnerUtility/runnerConfig.js.map +1 -0
  208. package/dist/runnerUtility/runnerFlags.d.ts +9 -0
  209. package/dist/runnerUtility/runnerFlags.d.ts.map +1 -0
  210. package/dist/runnerUtility/runnerFlags.js +53 -0
  211. package/dist/runnerUtility/runnerFlags.js.map +1 -0
  212. package/dist/runnerUtility/runnerHome.d.ts +30 -0
  213. package/dist/runnerUtility/runnerHome.d.ts.map +1 -0
  214. package/dist/runnerUtility/runnerHome.js +82 -0
  215. package/dist/runnerUtility/runnerHome.js.map +1 -0
  216. package/dist/runnerUtility/runnerKeys.d.ts +11 -0
  217. package/dist/runnerUtility/runnerKeys.d.ts.map +1 -0
  218. package/dist/runnerUtility/runnerKeys.js +80 -0
  219. package/dist/runnerUtility/runnerKeys.js.map +1 -0
  220. package/dist/runnerUtility/runnerServers.d.ts +40 -0
  221. package/dist/runnerUtility/runnerServers.d.ts.map +1 -0
  222. package/dist/runnerUtility/runnerServers.js +79 -0
  223. package/dist/runnerUtility/runnerServers.js.map +1 -0
  224. package/dist/runnerUtility/serviceManager.d.ts +54 -0
  225. package/dist/runnerUtility/serviceManager.d.ts.map +1 -0
  226. package/dist/runnerUtility/serviceManager.js +413 -0
  227. package/dist/runnerUtility/serviceManager.js.map +1 -0
  228. package/dist/runnerUtility/serviceUnits.d.ts +36 -0
  229. package/dist/runnerUtility/serviceUnits.d.ts.map +1 -0
  230. package/dist/runnerUtility/serviceUnits.js +169 -0
  231. package/dist/runnerUtility/serviceUnits.js.map +1 -0
  232. package/dist/runnerUtility/toolInstall.d.ts +95 -0
  233. package/dist/runnerUtility/toolInstall.d.ts.map +1 -0
  234. package/dist/runnerUtility/toolInstall.js +232 -0
  235. package/dist/runnerUtility/toolInstall.js.map +1 -0
  236. package/dist/runnerUtility/versionPollTiming.d.ts +16 -0
  237. package/dist/runnerUtility/versionPollTiming.d.ts.map +1 -0
  238. package/dist/runnerUtility/versionPollTiming.js +36 -0
  239. package/dist/runnerUtility/versionPollTiming.js.map +1 -0
  240. package/dist/runners/authorizedKeys.d.ts +52 -0
  241. package/dist/runners/authorizedKeys.d.ts.map +1 -0
  242. package/dist/runners/authorizedKeys.js +153 -0
  243. package/dist/runners/authorizedKeys.js.map +1 -0
  244. package/dist/runners/bootstrapLine.d.ts +4 -0
  245. package/dist/runners/bootstrapLine.d.ts.map +1 -0
  246. package/dist/runners/bootstrapLine.js +69 -0
  247. package/dist/runners/bootstrapLine.js.map +1 -0
  248. package/dist/runners/gate.d.ts +41 -0
  249. package/dist/runners/gate.d.ts.map +1 -0
  250. package/dist/runners/gate.js +216 -0
  251. package/dist/runners/gate.js.map +1 -0
  252. package/dist/runners/gateLink.d.ts +26 -0
  253. package/dist/runners/gateLink.d.ts.map +1 -0
  254. package/dist/runners/gateLink.js +240 -0
  255. package/dist/runners/gateLink.js.map +1 -0
  256. package/dist/runners/gateProtocol.d.ts +98 -0
  257. package/dist/runners/gateProtocol.d.ts.map +1 -0
  258. package/dist/runners/gateProtocol.js +149 -0
  259. package/dist/runners/gateProtocol.js.map +1 -0
  260. package/dist/runners/gateWrapper.d.ts +6 -0
  261. package/dist/runners/gateWrapper.d.ts.map +1 -0
  262. package/dist/runners/gateWrapper.js +70 -0
  263. package/dist/runners/gateWrapper.js.map +1 -0
  264. package/dist/runners/hubAddress.d.ts +33 -0
  265. package/dist/runners/hubAddress.d.ts.map +1 -0
  266. package/dist/runners/hubAddress.js +88 -0
  267. package/dist/runners/hubAddress.js.map +1 -0
  268. package/dist/runners/hubAddressCandidates.d.ts +16 -0
  269. package/dist/runners/hubAddressCandidates.d.ts.map +1 -0
  270. package/dist/runners/hubAddressCandidates.js +96 -0
  271. package/dist/runners/hubAddressCandidates.js.map +1 -0
  272. package/dist/runners/hubIds.d.ts +16 -0
  273. package/dist/runners/hubIds.d.ts.map +1 -0
  274. package/dist/runners/hubIds.js +25 -0
  275. package/dist/runners/hubIds.js.map +1 -0
  276. package/dist/runners/hubKey.d.ts +6 -0
  277. package/dist/runners/hubKey.d.ts.map +1 -0
  278. package/dist/runners/hubKey.js +78 -0
  279. package/dist/runners/hubKey.js.map +1 -0
  280. package/dist/runners/hubLock.d.ts +7 -0
  281. package/dist/runners/hubLock.d.ts.map +1 -0
  282. package/dist/runners/hubLock.js +230 -0
  283. package/dist/runners/hubLock.js.map +1 -0
  284. package/dist/runners/hubPackage.d.ts +23 -0
  285. package/dist/runners/hubPackage.d.ts.map +1 -0
  286. package/dist/runners/hubPackage.js +184 -0
  287. package/dist/runners/hubPackage.js.map +1 -0
  288. package/dist/runners/hubPairing.d.ts +63 -0
  289. package/dist/runners/hubPairing.d.ts.map +1 -0
  290. package/dist/runners/hubPairing.js +261 -0
  291. package/dist/runners/hubPairing.js.map +1 -0
  292. package/dist/runners/hubPaths.d.ts +38 -0
  293. package/dist/runners/hubPaths.d.ts.map +1 -0
  294. package/dist/runners/hubPaths.js +94 -0
  295. package/dist/runners/hubPaths.js.map +1 -0
  296. package/dist/runners/hubRegistry.d.ts +112 -0
  297. package/dist/runners/hubRegistry.d.ts.map +1 -0
  298. package/dist/runners/hubRegistry.js +210 -0
  299. package/dist/runners/hubRegistry.js.map +1 -0
  300. package/dist/runners/linkControl.d.ts +27 -0
  301. package/dist/runners/linkControl.d.ts.map +1 -0
  302. package/dist/runners/linkControl.js +124 -0
  303. package/dist/runners/linkControl.js.map +1 -0
  304. package/dist/runners/pairCode.d.ts +30 -0
  305. package/dist/runners/pairCode.d.ts.map +1 -0
  306. package/dist/runners/pairCode.js +46 -0
  307. package/dist/runners/pairCode.js.map +1 -0
  308. package/dist/runners/pairingTiming.d.ts +18 -0
  309. package/dist/runners/pairingTiming.d.ts.map +1 -0
  310. package/dist/runners/pairingTiming.js +42 -0
  311. package/dist/runners/pairingTiming.js.map +1 -0
  312. package/dist/runners/runnerProxy.d.ts +9 -0
  313. package/dist/runners/runnerProxy.d.ts.map +1 -0
  314. package/dist/runners/runnerProxy.js +67 -0
  315. package/dist/runners/runnerProxy.js.map +1 -0
  316. package/dist/runners/runnerRemoval.d.ts +21 -0
  317. package/dist/runners/runnerRemoval.d.ts.map +1 -0
  318. package/dist/runners/runnerRemoval.js +82 -0
  319. package/dist/runners/runnerRemoval.js.map +1 -0
  320. package/dist/runners/runnersCli.d.ts +16 -0
  321. package/dist/runners/runnersCli.d.ts.map +1 -0
  322. package/dist/runners/runnersCli.js +214 -0
  323. package/dist/runners/runnersCli.js.map +1 -0
  324. package/dist/runners/runnersList.d.ts +17 -0
  325. package/dist/runners/runnersList.d.ts.map +1 -0
  326. package/dist/runners/runnersList.js +49 -0
  327. package/dist/runners/runnersList.js.map +1 -0
  328. package/dist/runners/runnersOverview.d.ts +20 -0
  329. package/dist/runners/runnersOverview.d.ts.map +1 -0
  330. package/dist/runners/runnersOverview.js +55 -0
  331. package/dist/runners/runnersOverview.js.map +1 -0
  332. package/dist/runners/sshKeys.d.ts +26 -0
  333. package/dist/runners/sshKeys.d.ts.map +1 -0
  334. package/dist/runners/sshKeys.js +60 -0
  335. package/dist/runners/sshKeys.js.map +1 -0
  336. package/dist/runners/tarArchive.d.ts +20 -0
  337. package/dist/runners/tarArchive.d.ts.map +1 -0
  338. package/dist/runners/tarArchive.js +70 -0
  339. package/dist/runners/tarArchive.js.map +1 -0
  340. package/dist/scheduler/mcpSurface.d.ts +11 -5
  341. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  342. package/dist/scheduler/mcpSurface.js +59 -26
  343. package/dist/scheduler/mcpSurface.js.map +1 -1
  344. package/dist/selfUpdate/selfCheck.js +2 -2
  345. package/dist/selfUpdate/selfCheck.js.map +1 -1
  346. package/dist/testTimings.d.ts +5 -2
  347. package/dist/testTimings.d.ts.map +1 -1
  348. package/dist/testTimings.js +10 -1
  349. package/dist/testTimings.js.map +1 -1
  350. package/dist/utils/agentEnvironment.d.ts +6 -2
  351. package/dist/utils/agentEnvironment.d.ts.map +1 -1
  352. package/dist/utils/agentEnvironment.js +13 -2
  353. package/dist/utils/agentEnvironment.js.map +1 -1
  354. package/dist/utils/runnersScreenPlan.d.ts +130 -0
  355. package/dist/utils/runnersScreenPlan.d.ts.map +1 -0
  356. package/dist/utils/runnersScreenPlan.js +257 -0
  357. package/dist/utils/runnersScreenPlan.js.map +1 -0
  358. package/package.json +5 -2
  359. package/remoteRun/runner.sh +81 -6
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pairCodePrefix = void 0;
4
+ exports.encodePairCode = encodePairCode;
5
+ exports.decodePairCode = decodePairCode;
6
+ const zod_1 = require("zod");
7
+ const hubIds_1 = require("./hubIds");
8
+ /**
9
+ * @description The pairing code: everything a runner needs to reach the hub ONCE — the address, the hub's ssh host key to pin, the
10
+ * account to log in as, a private key that is good for one `redeem` (and the package download), and the pairing's id. Text
11
+ * `cr1.<base64url of a JSON object>`; the `1` is the format version. It is a secret until it is used or has expired: it is never
12
+ * logged, and a decode error names a field, never a value.
13
+ */
14
+ exports.pairCodePrefix = 'cr1.';
15
+ const maxCodeLength = 4096;
16
+ const privateKeyPattern = /^-----BEGIN OPENSSH PRIVATE KEY-----\n[A-Za-z0-9+/=\n]+\n-----END OPENSSH PRIVATE KEY-----\n?$/;
17
+ const pairCodePayloadSchema = zod_1.z.strictObject({
18
+ host: hubIds_1.hubHostSchema,
19
+ port: hubIds_1.hubPortSchema,
20
+ user: hubIds_1.hubSshUserSchema,
21
+ hostKey: hubIds_1.hubHostKeySchema,
22
+ privateKey: zod_1.z.string().max(2048).regex(privateKeyPattern, 'must be an OpenSSH private key'),
23
+ pairId: hubIds_1.hubIdSchema,
24
+ });
25
+ function encodePairCode(payload) {
26
+ return `${exports.pairCodePrefix}${Buffer.from(JSON.stringify(pairCodePayloadSchema.parse(payload)), 'utf8').toString('base64url')}`;
27
+ }
28
+ /** @description The payload of `code`, or why it is not one (the reason never quotes the code). */
29
+ function decodePairCode(code) {
30
+ if (!code.startsWith(exports.pairCodePrefix))
31
+ return { ok: false, error: `a pairing code starts with ${exports.pairCodePrefix}` };
32
+ if (code.length > maxCodeLength)
33
+ return { ok: false, error: 'the pairing code is too long' };
34
+ let parsedJson;
35
+ try {
36
+ parsedJson = JSON.parse(Buffer.from(code.slice(exports.pairCodePrefix.length), 'base64url').toString('utf8'));
37
+ }
38
+ catch {
39
+ return { ok: false, error: 'the pairing code is damaged (not a copy of the whole line?)' };
40
+ }
41
+ const parsed = pairCodePayloadSchema.safeParse(parsedJson);
42
+ if (parsed.success)
43
+ return { ok: true, payload: parsed.data };
44
+ return { ok: false, error: `the pairing code is damaged: ${parsed.error.issues.map((issue) => `${issue.path.join('.') || '(root)'} ${issue.message}`).join('; ')}` };
45
+ }
46
+ //# sourceMappingURL=pairCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairCode.js","sourceRoot":"","sources":["../../src/runners/pairCode.ts"],"names":[],"mappings":";;;AA4BA,wCAEC;AAGD,wCAYC;AA7CD,6BAAwB;AACxB,qCAAyG;AAEzG;;;;;GAKG;AAEU,QAAA,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,iBAAiB,GAAG,gGAAgG,CAAC;AAE3H,MAAM,qBAAqB,GAAG,OAAC,CAAC,YAAY,CAAC;IAC3C,IAAI,EAAE,sBAAa;IACnB,IAAI,EAAE,sBAAa;IACnB,IAAI,EAAE,yBAAgB;IACtB,OAAO,EAAE,yBAAgB;IACzB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;IAC3F,MAAM,EAAE,oBAAW;CACpB,CAAC,CAAC;AAOH,SAAgB,cAAc,CAAC,OAAwB;IACrD,OAAO,GAAG,sBAAc,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;AAC/H,CAAC;AAED,mGAAmG;AACnG,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,sBAAc,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,sBAAc,EAAE,EAAE,CAAC;IAClH,IAAI,IAAI,CAAC,MAAM,GAAG,aAAa;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;IAC7F,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAc,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC;IAC7F,CAAC;IACD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gCAAgC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;AACvK,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @description How long a pairing code works. In a module of its own so the headless CLI reads it without loading the bot.
3
+ *
4
+ * The test seam `CHARNESS_TEST_TIMINGS` (`testTimings.ts`) may only SHORTEN it (key `pairingLifetimeMs`, at least
5
+ * {@link pairingLifetimeMinMs}: sshd's `expiry-time` has a granularity of a second). Like the remote-run lease it is read tolerantly here,
6
+ * because this module cannot import `testTimings.ts` (its graph reaches the bot); the boot of an instance that carries a bad value is what
7
+ * refuses it by name.
8
+ */
9
+ export declare const pairingLifetimeMinutes = 10;
10
+ /** Production: a code works for ten minutes, once. */
11
+ export declare const pairingLifetimeMs: number;
12
+ /** sshd compares `expiry-time` in whole seconds: a shorter window would be rounding. */
13
+ export declare const pairingLifetimeMinMs = 5000;
14
+ /** @description The lifetime in force: the production one, or the seam's shorter `pairingLifetimeMs` when it is a whole number of ms within [min, production]. */
15
+ export declare function readPairingLifetimeMs(env: NodeJS.ProcessEnv): number;
16
+ /** @description «10 minutes», or «5 seconds» for a window shorter than a minute (only a test's). */
17
+ export declare function formatLifetime(lifetimeMs: number): string;
18
+ //# sourceMappingURL=pairingTiming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairingTiming.d.ts","sourceRoot":"","sources":["../../src/runners/pairingTiming.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,sDAAsD;AACtD,eAAO,MAAM,iBAAiB,QAAuC,CAAC;AACtE,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAIzC,kKAAkK;AAClK,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAYpE;AAED,oGAAoG;AACpG,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * @description How long a pairing code works. In a module of its own so the headless CLI reads it without loading the bot.
4
+ *
5
+ * The test seam `CHARNESS_TEST_TIMINGS` (`testTimings.ts`) may only SHORTEN it (key `pairingLifetimeMs`, at least
6
+ * {@link pairingLifetimeMinMs}: sshd's `expiry-time` has a granularity of a second). Like the remote-run lease it is read tolerantly here,
7
+ * because this module cannot import `testTimings.ts` (its graph reaches the bot); the boot of an instance that carries a bad value is what
8
+ * refuses it by name.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.pairingLifetimeMinMs = exports.pairingLifetimeMs = exports.pairingLifetimeMinutes = void 0;
12
+ exports.readPairingLifetimeMs = readPairingLifetimeMs;
13
+ exports.formatLifetime = formatLifetime;
14
+ const msPerMinute = 60 * 1000;
15
+ exports.pairingLifetimeMinutes = 10;
16
+ /** Production: a code works for ten minutes, once. */
17
+ exports.pairingLifetimeMs = exports.pairingLifetimeMinutes * msPerMinute;
18
+ /** sshd compares `expiry-time` in whole seconds: a shorter window would be rounding. */
19
+ exports.pairingLifetimeMinMs = 5000;
20
+ const testTimingsVariableName = 'CHARNESS_TEST_TIMINGS';
21
+ /** @description The lifetime in force: the production one, or the seam's shorter `pairingLifetimeMs` when it is a whole number of ms within [min, production]. */
22
+ function readPairingLifetimeMs(env) {
23
+ const rawTestTimings = env[testTimingsVariableName];
24
+ if (rawTestTimings === undefined || rawTestTimings.trim() === '')
25
+ return exports.pairingLifetimeMs;
26
+ let overrides;
27
+ try {
28
+ overrides = JSON.parse(rawTestTimings);
29
+ }
30
+ catch {
31
+ return exports.pairingLifetimeMs;
32
+ }
33
+ const overrideMs = overrides?.pairingLifetimeMs;
34
+ if (overrideMs === undefined || !Number.isInteger(overrideMs))
35
+ return exports.pairingLifetimeMs;
36
+ return overrideMs >= exports.pairingLifetimeMinMs && overrideMs <= exports.pairingLifetimeMs ? overrideMs : exports.pairingLifetimeMs;
37
+ }
38
+ /** @description «10 minutes», or «5 seconds» for a window shorter than a minute (only a test's). */
39
+ function formatLifetime(lifetimeMs) {
40
+ return lifetimeMs >= msPerMinute ? `${Math.round(lifetimeMs / msPerMinute)} minutes` : `${Math.round(lifetimeMs / 1000)} seconds`;
41
+ }
42
+ //# sourceMappingURL=pairingTiming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairingTiming.js","sourceRoot":"","sources":["../../src/runners/pairingTiming.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAYH,sDAYC;AAGD,wCAEC;AA3BD,MAAM,WAAW,GAAG,EAAE,GAAG,IAAI,CAAC;AACjB,QAAA,sBAAsB,GAAG,EAAE,CAAC;AACzC,sDAAsD;AACzC,QAAA,iBAAiB,GAAG,8BAAsB,GAAG,WAAW,CAAC;AACtE,wFAAwF;AAC3E,QAAA,oBAAoB,GAAG,IAAI,CAAC;AAEzC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAExD,kKAAkK;AAClK,SAAgB,qBAAqB,CAAC,GAAsB;IAC1D,MAAM,cAAc,GAAG,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACpD,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,yBAAiB,CAAC;IAC3F,IAAI,SAAgD,CAAC;IACrD,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,yBAAiB,CAAC;IAC3B,CAAC;IACD,MAAM,UAAU,GAAG,SAAS,EAAE,iBAAiB,CAAC;IAChD,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAAE,OAAO,yBAAiB,CAAC;IACxF,OAAO,UAAU,IAAI,4BAAoB,IAAI,UAAU,IAAI,yBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,yBAAiB,CAAC;AAChH,CAAC;AAED,oGAAoG;AACpG,SAAgB,cAAc,CAAC,UAAkB;IAC/C,OAAO,UAAU,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;AACpI,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Readable, Writable } from 'stream';
2
+ export interface RunnerProxyIo {
3
+ stdin: Readable;
4
+ stdout: Writable;
5
+ stderr: Writable;
6
+ }
7
+ /** @description Join `io` to the socket; resolves with the exit code when either side ends. */
8
+ export declare function runRunnerProxy(socketPath: string, io: RunnerProxyIo): Promise<number>;
9
+ //# sourceMappingURL=runnerProxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnerProxy.d.ts","sourceRoot":"","sources":["../../src/runners/runnerProxy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAWjD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBrF"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runRunnerProxy = runRunnerProxy;
37
+ const net = __importStar(require("net"));
38
+ /**
39
+ * @description `charness runner-proxy <socket>` — the `ProxyCommand` of the ssh calls to a paired runner: it joins ssh's stdin and
40
+ * stdout to the unix socket that the runner's gate listens on (`gateLink.ts`). When nothing listens, the runner is offline: the
41
+ * proxy says so on stderr, which ssh shows as the reason, and exits 255 — the status ssh itself uses for a failed connection, which
42
+ * remote-run already treats as «the connection was lost».
43
+ */
44
+ const connectionFailedExitCode = 255;
45
+ /** @description Join `io` to the socket; resolves with the exit code when either side ends. */
46
+ function runRunnerProxy(socketPath, io) {
47
+ return new Promise((resolve) => {
48
+ const socket = net.connect(socketPath);
49
+ let isConnected = false;
50
+ socket.once('connect', () => {
51
+ isConnected = true;
52
+ io.stdin.pipe(socket);
53
+ socket.pipe(io.stdout, { end: false });
54
+ });
55
+ socket.once('error', () => {
56
+ if (!isConnected)
57
+ io.stderr.write('charness runner-proxy: the runner is not connected\n');
58
+ socket.destroy();
59
+ });
60
+ socket.once('close', () => {
61
+ io.stdin.unpipe(socket);
62
+ resolve(isConnected ? 0 : connectionFailedExitCode);
63
+ });
64
+ io.stdin.once('end', () => socket.end());
65
+ });
66
+ }
67
+ //# sourceMappingURL=runnerProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnerProxy.js","sourceRoot":"","sources":["../../src/runners/runnerProxy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,wCAmBC;AAtCD,yCAA2B;AAG3B;;;;;GAKG;AAEH,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAQrC,+FAA+F;AAC/F,SAAgB,cAAc,CAAC,UAAkB,EAAE,EAAiB;IAClE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,WAAW,GAAG,IAAI,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,WAAW;gBAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1F,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { runSshCommand } from '../remoteRun/ssh';
2
+ import type { HubContext } from './hubPaths';
3
+ import { type PairedRunner } from './hubRegistry';
4
+ /** What became of the jobs on the removed runner: ended through the link; could not be ended from here; or the runner was offline. */
5
+ export type RunnerJobsStop = 'stopped' | 'failed' | 'offline';
6
+ export interface RunnerRemovalDeps {
7
+ isLinkOnline: (ctx: HubContext, runnerId: string) => Promise<boolean>;
8
+ runSsh: typeof runSshCommand;
9
+ cacheDir: string;
10
+ log: (line: string) => void;
11
+ }
12
+ /**
13
+ * @description Remove `nameOrId`: while it is still paired, pause it and stop its jobs through the link (when it is online); then drop it
14
+ * from the registry (its key line goes with it) and cut the link. `null` when no such runner is paired. A registry that cannot be
15
+ * written stops the call before the link is touched.
16
+ */
17
+ export declare function removeRunnerAndEndItsWork(ctx: HubContext, nameOrId: string, nowMs: number, deps?: RunnerRemovalDeps): Promise<{
18
+ runner: PairedRunner;
19
+ jobs: RunnerJobsStop;
20
+ } | null>;
21
+ //# sourceMappingURL=runnerRemoval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnerRemoval.d.ts","sourceRoot":"","sources":["../../src/runners/runnerRemoval.ts"],"names":[],"mappings":"AACA,OAAO,EAAiE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAiBlE,sIAAsI;AACtI,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AA0CD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAAC,CAc1L"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeRunnerAndEndItsWork = removeRunnerAndEndItsWork;
4
+ const pairedRunners_1 = require("../remoteRun/pairedRunners");
5
+ const ssh_1 = require("../remoteRun/ssh");
6
+ const hubPairing_1 = require("./hubPairing");
7
+ const hubRegistry_1 = require("./hubRegistry");
8
+ const linkControl_1 = require("./linkControl");
9
+ /**
10
+ * @description Removing a runner from the hub, and ending the work the hub's agents left on it. Pueue outlives any link by design, so
11
+ * cutting the link leaves their background jobs running on a machine that is no longer theirs. When the runner is ONLINE the hub says so
12
+ * itself, over the link that is still open: it runs `pueue reset --force` there (the queue's private Pueue, found from the work dir the
13
+ * runner reported). That is certain — unlike the runner's own inference from a refused key, which a hub with a locked home folder or a
14
+ * wrong file mode produces too (see `runnerUtility/linkLoop.ts`) — and it works whatever the runner's version.
15
+ *
16
+ * The ORDER matters: the gate ends a link as soon as its runner has left `paired.json`, which would cut the reset off half-way, so the
17
+ * runner is paused (no new job is sent to it meanwhile) and its jobs are stopped while it is still paired; only then it is removed and
18
+ * its link cut.
19
+ */
20
+ const stopJobsTimeoutMs = 20 * 1000;
21
+ function createRemovalDeps() {
22
+ return {
23
+ isLinkOnline: async (ctx, runnerId) => (await (0, linkControl_1.getRunnerLinkStatus)(ctx.dir, runnerId)).isOnline,
24
+ runSsh: ssh_1.runSshCommand,
25
+ cacheDir: (0, ssh_1.getRemoteRunCacheDir)(),
26
+ log: (line) => { console.error(line); },
27
+ };
28
+ }
29
+ /** Is the runner's link up? `null` when that could not be read (logged): a runner nobody can tell about is not «offline». */
30
+ async function checkIsLinkOnline(ctx, runner, deps) {
31
+ try {
32
+ return await deps.isLinkOnline(ctx, runner.id);
33
+ }
34
+ catch (error) {
35
+ deps.log(`runners: could not tell whether "${runner.name}" is online (${error instanceof Error ? error.message : 'unknown error'}); its jobs are not stopped from here`);
36
+ return null;
37
+ }
38
+ }
39
+ /** Reset the queue of a runner whose link is up. Never throws: a failure is logged and told as `failed`. */
40
+ async function resetQueueOverLink(ctx, runner, deps) {
41
+ try {
42
+ const config = (0, pairedRunners_1.buildPairedRunnerConfig)(runner, { hubDir: ctx.dir, nodePath: ctx.nodePath, cliPath: ctx.cliPath });
43
+ if (config.pueue?.bin === undefined || config.pueue.config === undefined) {
44
+ deps.log(`runners: cannot stop the jobs of "${runner.name}" from here: its work folder does not follow the runner utility's layout`);
45
+ return 'failed';
46
+ }
47
+ (0, ssh_1.ensureRemoteRunCacheDir)(deps.cacheDir);
48
+ // No shared connection: this one call must not leave a master behind for the link that is about to be cut.
49
+ const noMaster = { ...config, sshOptions: ['-o', 'ControlMaster=no', ...(config.sshOptions ?? [])] };
50
+ const result = await deps.runSsh({ runner: noMaster, cacheDir: deps.cacheDir, remoteCommand: (0, ssh_1.joinShellWords)([config.pueue.bin, '--config', config.pueue.config, 'reset', '--force']), timeoutMs: stopJobsTimeoutMs });
51
+ if (result.exitCode === 0)
52
+ return 'stopped';
53
+ deps.log(`runners: the jobs of "${runner.name}" were not stopped (${result.isTimedOut ? 'no answer in time' : `exit ${result.exitCode ?? 'none'}`})`);
54
+ return 'failed';
55
+ }
56
+ catch (error) {
57
+ deps.log(`runners: could not stop the jobs of "${runner.name}" (${error instanceof Error ? error.message : 'unknown error'})`);
58
+ return 'failed';
59
+ }
60
+ }
61
+ /**
62
+ * @description Remove `nameOrId`: while it is still paired, pause it and stop its jobs through the link (when it is online); then drop it
63
+ * from the registry (its key line goes with it) and cut the link. `null` when no such runner is paired. A registry that cannot be
64
+ * written stops the call before the link is touched.
65
+ */
66
+ async function removeRunnerAndEndItsWork(ctx, nameOrId, nowMs, deps) {
67
+ const resolvedDeps = deps ?? createRemovalDeps();
68
+ const found = (0, hubPairing_1.findPairedRunner)((0, hubRegistry_1.readPairedFile)(ctx.dir).runners, nameOrId);
69
+ if (found === undefined)
70
+ return null;
71
+ const isOnline = await checkIsLinkOnline(ctx, found, resolvedDeps);
72
+ let jobs = isOnline === null ? 'failed' : 'offline';
73
+ if (isOnline === true) {
74
+ // No agent is sent to it from now on; the reset below takes seconds.
75
+ await (0, hubPairing_1.setPairedRunnerPaused)(ctx, found.id, true).catch((error) => { resolvedDeps.log(`runners: could not pause "${found.name}" before stopping its jobs (${error instanceof Error ? error.message : 'unknown error'})`); });
76
+ jobs = await resetQueueOverLink(ctx, found, resolvedDeps);
77
+ }
78
+ const removed = await (0, hubPairing_1.removePairedRunner)(ctx, found.id, nowMs);
79
+ (0, linkControl_1.cutRunnerLink)(ctx.dir, found.id);
80
+ return removed === null ? null : { runner: removed, jobs };
81
+ }
82
+ //# sourceMappingURL=runnerRemoval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnerRemoval.js","sourceRoot":"","sources":["../../src/runners/runnerRemoval.ts"],"names":[],"mappings":";;AA4EA,8DAcC;AA1FD,8DAAqE;AACrE,0CAAgH;AAChH,6CAA2F;AAE3F,+CAAkE;AAClE,+CAAmE;AAEnE;;;;;;;;;;GAUG;AAEH,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,CAAC;AAYpC,SAAS,iBAAiB;IACxB,OAAO;QACL,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,IAAA,iCAAmB,EAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ;QAC9F,MAAM,EAAE,mBAAa;QACrB,QAAQ,EAAE,IAAA,0BAAoB,GAAE;QAChC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,6HAA6H;AAC7H,KAAK,UAAU,iBAAiB,CAAC,GAAe,EAAE,MAAoB,EAAE,IAAuB;IAC7F,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,IAAI,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,uCAAuC,CAAC,CAAC;QACzK,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,4GAA4G;AAC5G,KAAK,UAAU,kBAAkB,CAAC,GAAe,EAAE,MAAoB,EAAE,IAAuB;IAC9F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,uCAAuB,EAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAClH,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACzE,IAAI,CAAC,GAAG,CAAC,qCAAqC,MAAM,CAAC,IAAI,0EAA0E,CAAC,CAAC;YACrI,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAA,6BAAuB,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,2GAA2G;QAC3G,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACrG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAA,oBAAc,EAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACtN,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,yBAAyB,MAAM,CAAC,IAAI,uBAAuB,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE,GAAG,CAAC,CAAC;QACtJ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,wCAAwC,MAAM,CAAC,IAAI,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC;QAC/H,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,yBAAyB,CAAC,GAAe,EAAE,QAAgB,EAAE,KAAa,EAAE,IAAwB;IACxH,MAAM,YAAY,GAAG,IAAI,IAAI,iBAAiB,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,IAAA,6BAAgB,EAAC,IAAA,4BAAc,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACnE,IAAI,IAAI,GAAmB,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,qEAAqE;QACrE,MAAM,IAAA,kCAAqB,EAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,IAAI,+BAA+B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5N,IAAI,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,IAAA,+BAAkB,EAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC/D,IAAA,2BAAa,EAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IACjC,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { CliIo } from '../remoteRun/output';
2
+ import { type HostKeyScanner } from './hubAddress';
3
+ import { type HubContext } from './hubPaths';
4
+ export declare const runnersUsage = "Usage:\n charness runners [ls] the machines paired as runners: online or not, OS, how they are kept running\n charness runners pair --host <host[:port]> [--label <text>] [--wait]\n make a pairing line (valid 10 minutes, single use) to run on the runner machine;\n <host[:port]> is the address the runner dials to reach this machine's sshd;\n --wait blocks until the line is used or expires\n charness runners remove <name> detach a runner: its key is deleted and its link cut\n charness runners pause <name> keep a runner attached but send it no jobs\n charness runners resume <name>\n";
5
+ /** @description What the CLI needs from outside; tests replace the scanner, the clock and the wait. */
6
+ export interface RunnersCliDeps {
7
+ ctx: HubContext;
8
+ scanHostKey: HostKeyScanner;
9
+ now: () => number;
10
+ sleep: (ms: number) => Promise<void>;
11
+ sshUser?: string;
12
+ }
13
+ export declare function createRunnersCliDeps(io: Pick<CliIo, 'homeDir'>): RunnersCliDeps;
14
+ /** @description Run the command line (the words after `runners`); resolves with the exit code. */
15
+ export declare function runRunnersCli(argv: readonly string[], io: CliIo, deps?: RunnersCliDeps): Promise<number>;
16
+ //# sourceMappingURL=runnersCli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnersCli.d.ts","sourceRoot":"","sources":["../../src/runners/runnersCli.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,OAAO,EAAiD,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAkB/D,eAAO,MAAM,YAAY,2wBASxB,CAAC;AAEF,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,UAAU,CAAC;IAChB,WAAW,EAAE,cAAc,CAAC;IAC5B,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,cAAc,CAO/E;AAmHD,kGAAkG;AAClG,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,GAAE,cAAyC,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BxI"}
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runnersUsage = void 0;
37
+ exports.createRunnersCliDeps = createRunnersCliDeps;
38
+ exports.runRunnersCli = runRunnersCli;
39
+ const os = __importStar(require("os"));
40
+ const bootstrapLine_1 = require("./bootstrapLine");
41
+ const gateWrapper_1 = require("./gateWrapper");
42
+ const hubAddress_1 = require("./hubAddress");
43
+ const hubPaths_1 = require("./hubPaths");
44
+ const hubPairing_1 = require("./hubPairing");
45
+ const pairingTiming_1 = require("./pairingTiming");
46
+ const hubRegistry_1 = require("./hubRegistry");
47
+ const linkControl_1 = require("./linkControl");
48
+ const runnerRemoval_1 = require("./runnerRemoval");
49
+ const runnersList_1 = require("./runnersList");
50
+ /**
51
+ * @description `charness runners [ls | pair | remove <name> | pause <name> | resume <name>]` — the headless twin of `/runners`, for an
52
+ * instance without Telegram (a Jira-only one) and for the flow tests. It works on the registry of the OS user
53
+ * (`~/.config/charness/runners/`), loads no env file and never touches `DATA_DIR`.
54
+ */
55
+ const usageExitCode = 2;
56
+ const failedExitCode = 1;
57
+ const waitPollMs = 1000;
58
+ exports.runnersUsage = `Usage:
59
+ charness runners [ls] the machines paired as runners: online or not, OS, how they are kept running
60
+ charness runners pair --host <host[:port]> [--label <text>] [--wait]
61
+ make a pairing line (valid 10 minutes, single use) to run on the runner machine;
62
+ <host[:port]> is the address the runner dials to reach this machine's sshd;
63
+ --wait blocks until the line is used or expires
64
+ charness runners remove <name> detach a runner: its key is deleted and its link cut
65
+ charness runners pause <name> keep a runner attached but send it no jobs
66
+ charness runners resume <name>
67
+ `;
68
+ function createRunnersCliDeps(io) {
69
+ return {
70
+ ctx: (0, hubPaths_1.createHubContext)({ homeDir: io.homeDir }),
71
+ scanHostKey: hubAddress_1.scanHostKey,
72
+ now: Date.now,
73
+ sleep: (ms) => new Promise((resolve) => { setTimeout(resolve, ms); }),
74
+ };
75
+ }
76
+ function parsePairOptions(args) {
77
+ const options = { host: null, label: null, isWaiting: false };
78
+ for (let index = 0; index < args.length; index += 1) {
79
+ const argument = args[index];
80
+ if (argument === '--wait') {
81
+ options.isWaiting = true;
82
+ }
83
+ else if (argument === '--host' || argument === '--label') {
84
+ const value = args[index + 1];
85
+ if (value === undefined)
86
+ return `${argument} needs a value`;
87
+ if (argument === '--host')
88
+ options.host = value;
89
+ else
90
+ options.label = value;
91
+ index += 1;
92
+ }
93
+ else {
94
+ return `unknown argument: ${argument}`;
95
+ }
96
+ }
97
+ return options;
98
+ }
99
+ async function runPairCommand(args, io, deps) {
100
+ const options = parsePairOptions(args);
101
+ if (typeof options === 'string' || options.host === null) {
102
+ io.stderr(`runners: ${typeof options === 'string' ? options : '--host <host[:port]> is required (the address runners dial to reach this machine over ssh)'}\n\n${exports.runnersUsage}`);
103
+ return usageExitCode;
104
+ }
105
+ const parsedAddress = (0, hubAddress_1.parseHubAddress)(options.host);
106
+ if (!parsedAddress.ok) {
107
+ io.stderr(`runners: ${parsedAddress.error}\n`);
108
+ return usageExitCode;
109
+ }
110
+ const check = await (0, hubAddress_1.checkHubAddress)(parsedAddress.address, deps.scanHostKey);
111
+ if (!check.ok) {
112
+ io.stderr(`runners: ${check.error}\n`);
113
+ return failedExitCode;
114
+ }
115
+ if (check.note !== null)
116
+ io.stderr(`runners: ${check.note}\n`);
117
+ (0, gateWrapper_1.ensureGateWrapper)(deps.ctx);
118
+ const pairing = await (0, hubPairing_1.createPairing)(deps.ctx, {
119
+ host: parsedAddress.address.host,
120
+ port: parsedAddress.address.port,
121
+ hostKey: check.hostKey,
122
+ label: options.label ?? os.hostname(),
123
+ nowMs: deps.now(),
124
+ lifetimeMs: (0, pairingTiming_1.readPairingLifetimeMs)(io.env),
125
+ sshUser: deps.sshUser,
126
+ });
127
+ io.stdout(`Pair a runner — valid ${(0, pairingTiming_1.formatLifetime)((0, pairingTiming_1.readPairingLifetimeMs)(io.env))}, single use.\n\n` +
128
+ `Run this on the runner machine, as the account that will run jobs\n` +
129
+ `(not your main account — it runs the agents' code):\n\n` +
130
+ `${(0, bootstrapLine_1.buildBootstrapLine)(pairing.payload)}\n\n` +
131
+ `Anyone with this line can attach a machine to this charness until it is used or expires.\n`);
132
+ return options.isWaiting ? waitForPairing(pairing.pairId, io, deps) : 0;
133
+ }
134
+ async function waitForPairing(pairId, io, deps) {
135
+ for (;;) {
136
+ const runner = (0, hubRegistry_1.readPairedFile)(deps.ctx.dir).runners.find((candidate) => candidate.pairId === pairId);
137
+ if (runner !== undefined) {
138
+ io.stdout(`Runner "${runner.name}" paired ${(0, runnersList_1.formatListTimestamp)(runner.pairedAtMs)}.\n`);
139
+ return 0;
140
+ }
141
+ const pairing = (0, hubRegistry_1.readPendingFile)(deps.ctx.dir).pending.find((candidate) => candidate.pairId === pairId);
142
+ if (pairing === undefined || pairing.expiresAtMs <= deps.now()) {
143
+ await (0, hubPairing_1.sweepExpiredPairings)(deps.ctx, deps.now());
144
+ io.stderr('runners: the pairing code expired unused.\n');
145
+ return failedExitCode;
146
+ }
147
+ await deps.sleep(waitPollMs);
148
+ }
149
+ }
150
+ async function runListCommand(io, deps) {
151
+ await (0, hubPairing_1.sweepExpiredPairings)(deps.ctx, deps.now());
152
+ const paired = (0, hubRegistry_1.readPairedFile)(deps.ctx.dir);
153
+ const entries = await Promise.all(paired.runners.map(async (runner) => ({ runner, status: await (0, linkControl_1.getRunnerLinkStatus)(deps.ctx.dir, runner.id) })));
154
+ io.stdout((0, runnersList_1.formatRunnerList)(entries, (0, hubRegistry_1.readPendingFile)(deps.ctx.dir).pending, deps.now()));
155
+ return 0;
156
+ }
157
+ async function runRemoveCommand(name, io, deps) {
158
+ const removal = await (0, runnerRemoval_1.removeRunnerAndEndItsWork)(deps.ctx, name, deps.now());
159
+ if (removal === null) {
160
+ io.stderr(`runners: no runner named "${name}"\n`);
161
+ return failedExitCode;
162
+ }
163
+ const jobsNote = {
164
+ stopped: 'the jobs it had running are stopped',
165
+ failed: 'the jobs it had running could not be stopped from here (it stops them itself once it finds out it was removed)',
166
+ offline: 'it is offline: it stops the jobs it had running itself once it finds out it was removed',
167
+ }[removal.jobs];
168
+ io.stdout(`Runner "${removal.runner.name}" removed: its key is deleted and its link cut; ${jobsNote}.\n`);
169
+ return 0;
170
+ }
171
+ async function runPauseCommand(name, isPaused, io, deps) {
172
+ const runner = (0, hubPairing_1.findPairedRunner)((0, hubRegistry_1.readPairedFile)(deps.ctx.dir).runners, name);
173
+ const updated = runner === undefined ? null : await (0, hubPairing_1.setPairedRunnerPaused)(deps.ctx, runner.id, isPaused);
174
+ if (updated === null) {
175
+ io.stderr(`runners: no runner named "${name}"\n`);
176
+ return failedExitCode;
177
+ }
178
+ io.stdout(`Runner "${updated.name}" ${isPaused ? 'paused: it gets no jobs until resumed' : 'resumed'}.\n`);
179
+ return 0;
180
+ }
181
+ /** @description Run the command line (the words after `runners`); resolves with the exit code. */
182
+ async function runRunnersCli(argv, io, deps = createRunnersCliDeps(io)) {
183
+ const [command = 'ls', ...args] = argv;
184
+ try {
185
+ switch (command) {
186
+ case 'ls':
187
+ return await runListCommand(io, deps);
188
+ case 'pair':
189
+ return await runPairCommand(args, io, deps);
190
+ case 'remove':
191
+ case 'pause':
192
+ case 'resume': {
193
+ if (args.length !== 1) {
194
+ io.stderr(`runners: ${command} needs exactly one runner name\n\n${exports.runnersUsage}`);
195
+ return usageExitCode;
196
+ }
197
+ return command === 'remove' ? await runRemoveCommand(args[0], io, deps) : await runPauseCommand(args[0], command === 'pause', io, deps);
198
+ }
199
+ case '--help':
200
+ case '-h':
201
+ case 'help':
202
+ io.stdout(exports.runnersUsage);
203
+ return 0;
204
+ default:
205
+ io.stderr(`runners: unknown command: ${command}\n\n${exports.runnersUsage}`);
206
+ return usageExitCode;
207
+ }
208
+ }
209
+ catch (error) {
210
+ io.stderr(`runners: ${error instanceof hubRegistry_1.HubRegistryError ? error.message : `failed (${error instanceof Error ? error.name : 'unknown error'}: ${error instanceof Error ? error.message : ''})`}\n`);
211
+ return failedExitCode;
212
+ }
213
+ }
214
+ //# sourceMappingURL=runnersCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnersCli.js","sourceRoot":"","sources":["../../src/runners/runnersCli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { RunnerLinkStatus } from './linkControl';
2
+ import type { PairedRunner, PendingPairing, RunnerServiceKind } from './hubRegistry';
3
+ /**
4
+ * @description The text of `charness runners ls`: one line per paired runner (name, online or offline since when, paused, OS, how it
5
+ * is kept running, version) and a line for each pairing code still open. Pure: the status is read by the caller.
6
+ */
7
+ export declare const serviceKindLabels: Record<RunnerServiceKind, string>;
8
+ export interface RunnerListEntry {
9
+ runner: PairedRunner;
10
+ status: RunnerLinkStatus;
11
+ }
12
+ /** @description `2026-11-01 14:05` in the zone of this process. */
13
+ export declare function formatListTimestamp(epochMs: number): string;
14
+ export declare function formatRunnerListLine(entry: RunnerListEntry): string;
15
+ /** @description The whole `ls` output. */
16
+ export declare function formatRunnerList(entries: readonly RunnerListEntry[], pending: readonly PendingPairing[], nowMs: number): string;
17
+ //# sourceMappingURL=runnersList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnersList.d.ts","sourceRoot":"","sources":["../../src/runners/runnersList.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAErF;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAK/D,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI3D;AAOD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAWnE;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAO/H"}