charness 3.7.0 → 3.9.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 (393) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DEVELOPMENT.md +8 -2
  3. package/README.md +5 -5
  4. package/SETUP.md +17 -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.d.ts +2 -0
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +56 -6
  15. package/dist/cli.js.map +1 -1
  16. package/dist/configDirFile.d.ts +7 -3
  17. package/dist/configDirFile.d.ts.map +1 -1
  18. package/dist/configDirFile.js +12 -5
  19. package/dist/configDirFile.js.map +1 -1
  20. package/dist/connectors/telegram/commands/botCore.d.ts +5 -1
  21. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  22. package/dist/connectors/telegram/commands/runners.d.ts +52 -0
  23. package/dist/connectors/telegram/commands/runners.d.ts.map +1 -0
  24. package/dist/connectors/telegram/commands/runners.js +524 -0
  25. package/dist/connectors/telegram/commands/runners.js.map +1 -0
  26. package/dist/connectors/telegram/runnerPairingMessages.d.ts +29 -0
  27. package/dist/connectors/telegram/runnerPairingMessages.d.ts.map +1 -0
  28. package/dist/connectors/telegram/runnerPairingMessages.js +112 -0
  29. package/dist/connectors/telegram/runnerPairingMessages.js.map +1 -0
  30. package/dist/i18n/de.d.ts.map +1 -1
  31. package/dist/i18n/de.js +60 -0
  32. package/dist/i18n/de.js.map +1 -1
  33. package/dist/i18n/en.d.ts.map +1 -1
  34. package/dist/i18n/en.js +60 -0
  35. package/dist/i18n/en.js.map +1 -1
  36. package/dist/i18n/es.d.ts.map +1 -1
  37. package/dist/i18n/es.js +60 -0
  38. package/dist/i18n/es.js.map +1 -1
  39. package/dist/i18n/fr.d.ts.map +1 -1
  40. package/dist/i18n/fr.js +60 -0
  41. package/dist/i18n/fr.js.map +1 -1
  42. package/dist/i18n/hi.d.ts.map +1 -1
  43. package/dist/i18n/hi.js +60 -0
  44. package/dist/i18n/hi.js.map +1 -1
  45. package/dist/i18n/ja.d.ts.map +1 -1
  46. package/dist/i18n/ja.js +60 -0
  47. package/dist/i18n/ja.js.map +1 -1
  48. package/dist/i18n/ka.d.ts.map +1 -1
  49. package/dist/i18n/ka.js +60 -0
  50. package/dist/i18n/ka.js.map +1 -1
  51. package/dist/i18n/pt.d.ts.map +1 -1
  52. package/dist/i18n/pt.js +60 -0
  53. package/dist/i18n/pt.js.map +1 -1
  54. package/dist/i18n/ru.d.ts.map +1 -1
  55. package/dist/i18n/ru.js +60 -0
  56. package/dist/i18n/ru.js.map +1 -1
  57. package/dist/i18n/uk.d.ts.map +1 -1
  58. package/dist/i18n/uk.js +60 -0
  59. package/dist/i18n/uk.js.map +1 -1
  60. package/dist/i18n/uz.d.ts.map +1 -1
  61. package/dist/i18n/uz.js +60 -0
  62. package/dist/i18n/uz.js.map +1 -1
  63. package/dist/i18n/zh.d.ts.map +1 -1
  64. package/dist/i18n/zh.js +60 -0
  65. package/dist/i18n/zh.js.map +1 -1
  66. package/dist/index.d.ts +1 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +3 -1
  69. package/dist/index.js.map +1 -1
  70. package/dist/installManager.d.ts +57 -1
  71. package/dist/installManager.d.ts.map +1 -1
  72. package/dist/installManager.js +88 -10
  73. package/dist/installManager.js.map +1 -1
  74. package/dist/instanceSettings.d.ts +12 -2
  75. package/dist/instanceSettings.d.ts.map +1 -1
  76. package/dist/instanceSettings.js +17 -3
  77. package/dist/instanceSettings.js.map +1 -1
  78. package/dist/outputTrace.d.ts +6 -0
  79. package/dist/outputTrace.d.ts.map +1 -1
  80. package/dist/outputTrace.js +24 -1
  81. package/dist/outputTrace.js.map +1 -1
  82. package/dist/remoteRun/cliArgs.d.ts +2 -0
  83. package/dist/remoteRun/cliArgs.d.ts.map +1 -1
  84. package/dist/remoteRun/cliArgs.js +11 -2
  85. package/dist/remoteRun/cliArgs.js.map +1 -1
  86. package/dist/remoteRun/commands.d.ts +21 -0
  87. package/dist/remoteRun/commands.d.ts.map +1 -1
  88. package/dist/remoteRun/commands.js +38 -17
  89. package/dist/remoteRun/commands.js.map +1 -1
  90. package/dist/remoteRun/interrupts.d.ts +10 -0
  91. package/dist/remoteRun/interrupts.d.ts.map +1 -1
  92. package/dist/remoteRun/interrupts.js +43 -6
  93. package/dist/remoteRun/interrupts.js.map +1 -1
  94. package/dist/remoteRun/output.d.ts +2 -0
  95. package/dist/remoteRun/output.d.ts.map +1 -1
  96. package/dist/remoteRun/output.js +45 -0
  97. package/dist/remoteRun/output.js.map +1 -1
  98. package/dist/remoteRun/pairedRunners.d.ts +51 -0
  99. package/dist/remoteRun/pairedRunners.d.ts.map +1 -0
  100. package/dist/remoteRun/pairedRunners.js +165 -0
  101. package/dist/remoteRun/pairedRunners.js.map +1 -0
  102. package/dist/remoteRun/probe.d.ts +23 -1
  103. package/dist/remoteRun/probe.d.ts.map +1 -1
  104. package/dist/remoteRun/probe.js +45 -11
  105. package/dist/remoteRun/probe.js.map +1 -1
  106. package/dist/remoteRun/remoteRunCli.d.ts +13 -6
  107. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -1
  108. package/dist/remoteRun/remoteRunCli.js +34 -59
  109. package/dist/remoteRun/remoteRunCli.js.map +1 -1
  110. package/dist/remoteRun/runnerClient.d.ts +2 -0
  111. package/dist/remoteRun/runnerClient.d.ts.map +1 -1
  112. package/dist/remoteRun/runnerClient.js +5 -1
  113. package/dist/remoteRun/runnerClient.js.map +1 -1
  114. package/dist/remoteRun/runnerSummary.d.ts +24 -0
  115. package/dist/remoteRun/runnerSummary.d.ts.map +1 -0
  116. package/dist/remoteRun/runnerSummary.js +86 -0
  117. package/dist/remoteRun/runnerSummary.js.map +1 -0
  118. package/dist/remoteRun/runnerWait.d.ts +68 -0
  119. package/dist/remoteRun/runnerWait.d.ts.map +1 -0
  120. package/dist/remoteRun/runnerWait.js +137 -0
  121. package/dist/remoteRun/runnerWait.js.map +1 -0
  122. package/dist/remoteRun/runnerWaitTiming.d.ts +16 -0
  123. package/dist/remoteRun/runnerWaitTiming.d.ts.map +1 -0
  124. package/dist/remoteRun/runnerWaitTiming.js +37 -0
  125. package/dist/remoteRun/runnerWaitTiming.js.map +1 -0
  126. package/dist/remoteRun/runners.d.ts +15 -8
  127. package/dist/remoteRun/runners.d.ts.map +1 -1
  128. package/dist/remoteRun/runners.js +59 -19
  129. package/dist/remoteRun/runners.js.map +1 -1
  130. package/dist/remoteRun/runnersCatalog.d.ts +14 -0
  131. package/dist/remoteRun/runnersCatalog.d.ts.map +1 -0
  132. package/dist/remoteRun/runnersCatalog.js +68 -0
  133. package/dist/remoteRun/runnersCatalog.js.map +1 -0
  134. package/dist/remoteRun/runnersConfig.d.ts +31 -20
  135. package/dist/remoteRun/runnersConfig.d.ts.map +1 -1
  136. package/dist/remoteRun/runnersConfig.js +14 -12
  137. package/dist/remoteRun/runnersConfig.js.map +1 -1
  138. package/dist/remoteRun/ssh.d.ts +22 -2
  139. package/dist/remoteRun/ssh.d.ts.map +1 -1
  140. package/dist/remoteRun/ssh.js +41 -7
  141. package/dist/remoteRun/ssh.js.map +1 -1
  142. package/dist/runnerUtility/adminCheck.d.ts +18 -0
  143. package/dist/runnerUtility/adminCheck.d.ts.map +1 -0
  144. package/dist/runnerUtility/adminCheck.js +69 -0
  145. package/dist/runnerUtility/adminCheck.js.map +1 -0
  146. package/dist/runnerUtility/adminService.d.ts +22 -0
  147. package/dist/runnerUtility/adminService.d.ts.map +1 -0
  148. package/dist/runnerUtility/adminService.js +145 -0
  149. package/dist/runnerUtility/adminService.js.map +1 -0
  150. package/dist/runnerUtility/appInstall.d.ts +25 -0
  151. package/dist/runnerUtility/appInstall.d.ts.map +1 -0
  152. package/dist/runnerUtility/appInstall.js +147 -0
  153. package/dist/runnerUtility/appInstall.js.map +1 -0
  154. package/dist/runnerUtility/appUpdate.d.ts +39 -0
  155. package/dist/runnerUtility/appUpdate.d.ts.map +1 -0
  156. package/dist/runnerUtility/appUpdate.js +90 -0
  157. package/dist/runnerUtility/appUpdate.js.map +1 -0
  158. package/dist/runnerUtility/execEnv.d.ts +21 -0
  159. package/dist/runnerUtility/execEnv.d.ts.map +1 -0
  160. package/dist/runnerUtility/execEnv.js +109 -0
  161. package/dist/runnerUtility/execEnv.js.map +1 -0
  162. package/dist/runnerUtility/execSession.d.ts +13 -0
  163. package/dist/runnerUtility/execSession.d.ts.map +1 -0
  164. package/dist/runnerUtility/execSession.js +58 -0
  165. package/dist/runnerUtility/execSession.js.map +1 -0
  166. package/dist/runnerUtility/hubClient.d.ts +30 -0
  167. package/dist/runnerUtility/hubClient.d.ts.map +1 -0
  168. package/dist/runnerUtility/hubClient.js +127 -0
  169. package/dist/runnerUtility/hubClient.js.map +1 -0
  170. package/dist/runnerUtility/injectStream.d.ts +9 -0
  171. package/dist/runnerUtility/injectStream.d.ts.map +1 -0
  172. package/dist/runnerUtility/injectStream.js +12 -0
  173. package/dist/runnerUtility/injectStream.js.map +1 -0
  174. package/dist/runnerUtility/iosCheck.d.ts +62 -0
  175. package/dist/runnerUtility/iosCheck.d.ts.map +1 -0
  176. package/dist/runnerUtility/iosCheck.js +200 -0
  177. package/dist/runnerUtility/iosCheck.js.map +1 -0
  178. package/dist/runnerUtility/launcher.d.ts +5 -0
  179. package/dist/runnerUtility/launcher.d.ts.map +1 -0
  180. package/dist/runnerUtility/launcher.js +85 -0
  181. package/dist/runnerUtility/launcher.js.map +1 -0
  182. package/dist/runnerUtility/linkLoop.d.ts +39 -0
  183. package/dist/runnerUtility/linkLoop.d.ts.map +1 -0
  184. package/dist/runnerUtility/linkLoop.js +274 -0
  185. package/dist/runnerUtility/linkLoop.js.map +1 -0
  186. package/dist/runnerUtility/localLinkStop.d.ts +23 -0
  187. package/dist/runnerUtility/localLinkStop.d.ts.map +1 -0
  188. package/dist/runnerUtility/localLinkStop.js +79 -0
  189. package/dist/runnerUtility/localLinkStop.js.map +1 -0
  190. package/dist/runnerUtility/machineReport.d.ts +39 -0
  191. package/dist/runnerUtility/machineReport.d.ts.map +1 -0
  192. package/dist/runnerUtility/machineReport.js +161 -0
  193. package/dist/runnerUtility/machineReport.js.map +1 -0
  194. package/dist/runnerUtility/packageId.d.ts +5 -0
  195. package/dist/runnerUtility/packageId.d.ts.map +1 -0
  196. package/dist/runnerUtility/packageId.js +64 -0
  197. package/dist/runnerUtility/packageId.js.map +1 -0
  198. package/dist/runnerUtility/pairArgs.d.ts +16 -0
  199. package/dist/runnerUtility/pairArgs.d.ts.map +1 -0
  200. package/dist/runnerUtility/pairArgs.js +17 -0
  201. package/dist/runnerUtility/pairArgs.js.map +1 -0
  202. package/dist/runnerUtility/pairingRecovery.d.ts +31 -0
  203. package/dist/runnerUtility/pairingRecovery.d.ts.map +1 -0
  204. package/dist/runnerUtility/pairingRecovery.js +24 -0
  205. package/dist/runnerUtility/pairingRecovery.js.map +1 -0
  206. package/dist/runnerUtility/pueueDaemon.d.ts +36 -0
  207. package/dist/runnerUtility/pueueDaemon.d.ts.map +1 -0
  208. package/dist/runnerUtility/pueueDaemon.js +165 -0
  209. package/dist/runnerUtility/pueueDaemon.js.map +1 -0
  210. package/dist/runnerUtility/rootServiceCli.d.ts +8 -0
  211. package/dist/runnerUtility/rootServiceCli.d.ts.map +1 -0
  212. package/dist/runnerUtility/rootServiceCli.js +31 -0
  213. package/dist/runnerUtility/rootServiceCli.js.map +1 -0
  214. package/dist/runnerUtility/runnerCli.d.ts +18 -0
  215. package/dist/runnerUtility/runnerCli.d.ts.map +1 -0
  216. package/dist/runnerUtility/runnerCli.js +190 -0
  217. package/dist/runnerUtility/runnerCli.js.map +1 -0
  218. package/dist/runnerUtility/runnerCommands.d.ts +76 -0
  219. package/dist/runnerUtility/runnerCommands.d.ts.map +1 -0
  220. package/dist/runnerUtility/runnerCommands.js +464 -0
  221. package/dist/runnerUtility/runnerCommands.js.map +1 -0
  222. package/dist/runnerUtility/runnerConfig.d.ts +63 -0
  223. package/dist/runnerUtility/runnerConfig.d.ts.map +1 -0
  224. package/dist/runnerUtility/runnerConfig.js +153 -0
  225. package/dist/runnerUtility/runnerConfig.js.map +1 -0
  226. package/dist/runnerUtility/runnerFlags.d.ts +9 -0
  227. package/dist/runnerUtility/runnerFlags.d.ts.map +1 -0
  228. package/dist/runnerUtility/runnerFlags.js +53 -0
  229. package/dist/runnerUtility/runnerFlags.js.map +1 -0
  230. package/dist/runnerUtility/runnerHome.d.ts +30 -0
  231. package/dist/runnerUtility/runnerHome.d.ts.map +1 -0
  232. package/dist/runnerUtility/runnerHome.js +82 -0
  233. package/dist/runnerUtility/runnerHome.js.map +1 -0
  234. package/dist/runnerUtility/runnerKeys.d.ts +11 -0
  235. package/dist/runnerUtility/runnerKeys.d.ts.map +1 -0
  236. package/dist/runnerUtility/runnerKeys.js +80 -0
  237. package/dist/runnerUtility/runnerKeys.js.map +1 -0
  238. package/dist/runnerUtility/runnerServers.d.ts +40 -0
  239. package/dist/runnerUtility/runnerServers.d.ts.map +1 -0
  240. package/dist/runnerUtility/runnerServers.js +79 -0
  241. package/dist/runnerUtility/runnerServers.js.map +1 -0
  242. package/dist/runnerUtility/serviceCommon.d.ts +97 -0
  243. package/dist/runnerUtility/serviceCommon.d.ts.map +1 -0
  244. package/dist/runnerUtility/serviceCommon.js +209 -0
  245. package/dist/runnerUtility/serviceCommon.js.map +1 -0
  246. package/dist/runnerUtility/serviceManager.d.ts +51 -0
  247. package/dist/runnerUtility/serviceManager.d.ts.map +1 -0
  248. package/dist/runnerUtility/serviceManager.js +344 -0
  249. package/dist/runnerUtility/serviceManager.js.map +1 -0
  250. package/dist/runnerUtility/serviceUnits.d.ts +38 -0
  251. package/dist/runnerUtility/serviceUnits.d.ts.map +1 -0
  252. package/dist/runnerUtility/serviceUnits.js +189 -0
  253. package/dist/runnerUtility/serviceUnits.js.map +1 -0
  254. package/dist/runnerUtility/toolInstall.d.ts +95 -0
  255. package/dist/runnerUtility/toolInstall.d.ts.map +1 -0
  256. package/dist/runnerUtility/toolInstall.js +232 -0
  257. package/dist/runnerUtility/toolInstall.js.map +1 -0
  258. package/dist/runnerUtility/versionPollTiming.d.ts +16 -0
  259. package/dist/runnerUtility/versionPollTiming.d.ts.map +1 -0
  260. package/dist/runnerUtility/versionPollTiming.js +36 -0
  261. package/dist/runnerUtility/versionPollTiming.js.map +1 -0
  262. package/dist/runners/authorizedKeys.d.ts +52 -0
  263. package/dist/runners/authorizedKeys.d.ts.map +1 -0
  264. package/dist/runners/authorizedKeys.js +153 -0
  265. package/dist/runners/authorizedKeys.js.map +1 -0
  266. package/dist/runners/bootstrapLine.d.ts +13 -0
  267. package/dist/runners/bootstrapLine.d.ts.map +1 -0
  268. package/dist/runners/bootstrapLine.js +154 -0
  269. package/dist/runners/bootstrapLine.js.map +1 -0
  270. package/dist/runners/gate.d.ts +41 -0
  271. package/dist/runners/gate.d.ts.map +1 -0
  272. package/dist/runners/gate.js +225 -0
  273. package/dist/runners/gate.js.map +1 -0
  274. package/dist/runners/gateLink.d.ts +26 -0
  275. package/dist/runners/gateLink.d.ts.map +1 -0
  276. package/dist/runners/gateLink.js +240 -0
  277. package/dist/runners/gateLink.js.map +1 -0
  278. package/dist/runners/gateProtocol.d.ts +104 -0
  279. package/dist/runners/gateProtocol.d.ts.map +1 -0
  280. package/dist/runners/gateProtocol.js +151 -0
  281. package/dist/runners/gateProtocol.js.map +1 -0
  282. package/dist/runners/gateWrapper.d.ts +6 -0
  283. package/dist/runners/gateWrapper.d.ts.map +1 -0
  284. package/dist/runners/gateWrapper.js +70 -0
  285. package/dist/runners/gateWrapper.js.map +1 -0
  286. package/dist/runners/hubAddress.d.ts +33 -0
  287. package/dist/runners/hubAddress.d.ts.map +1 -0
  288. package/dist/runners/hubAddress.js +88 -0
  289. package/dist/runners/hubAddress.js.map +1 -0
  290. package/dist/runners/hubAddressCandidates.d.ts +16 -0
  291. package/dist/runners/hubAddressCandidates.d.ts.map +1 -0
  292. package/dist/runners/hubAddressCandidates.js +96 -0
  293. package/dist/runners/hubAddressCandidates.js.map +1 -0
  294. package/dist/runners/hubIds.d.ts +16 -0
  295. package/dist/runners/hubIds.d.ts.map +1 -0
  296. package/dist/runners/hubIds.js +25 -0
  297. package/dist/runners/hubIds.js.map +1 -0
  298. package/dist/runners/hubKey.d.ts +6 -0
  299. package/dist/runners/hubKey.d.ts.map +1 -0
  300. package/dist/runners/hubKey.js +78 -0
  301. package/dist/runners/hubKey.js.map +1 -0
  302. package/dist/runners/hubLock.d.ts +7 -0
  303. package/dist/runners/hubLock.d.ts.map +1 -0
  304. package/dist/runners/hubLock.js +230 -0
  305. package/dist/runners/hubLock.js.map +1 -0
  306. package/dist/runners/hubPackage.d.ts +23 -0
  307. package/dist/runners/hubPackage.d.ts.map +1 -0
  308. package/dist/runners/hubPackage.js +184 -0
  309. package/dist/runners/hubPackage.js.map +1 -0
  310. package/dist/runners/hubPairing.d.ts +70 -0
  311. package/dist/runners/hubPairing.d.ts.map +1 -0
  312. package/dist/runners/hubPairing.js +277 -0
  313. package/dist/runners/hubPairing.js.map +1 -0
  314. package/dist/runners/hubPaths.d.ts +42 -0
  315. package/dist/runners/hubPaths.d.ts.map +1 -0
  316. package/dist/runners/hubPaths.js +96 -0
  317. package/dist/runners/hubPaths.js.map +1 -0
  318. package/dist/runners/hubRegistry.d.ts +134 -0
  319. package/dist/runners/hubRegistry.d.ts.map +1 -0
  320. package/dist/runners/hubRegistry.js +256 -0
  321. package/dist/runners/hubRegistry.js.map +1 -0
  322. package/dist/runners/linkControl.d.ts +38 -0
  323. package/dist/runners/linkControl.d.ts.map +1 -0
  324. package/dist/runners/linkControl.js +171 -0
  325. package/dist/runners/linkControl.js.map +1 -0
  326. package/dist/runners/pairCode.d.ts +30 -0
  327. package/dist/runners/pairCode.d.ts.map +1 -0
  328. package/dist/runners/pairCode.js +46 -0
  329. package/dist/runners/pairCode.js.map +1 -0
  330. package/dist/runners/pairingTiming.d.ts +18 -0
  331. package/dist/runners/pairingTiming.d.ts.map +1 -0
  332. package/dist/runners/pairingTiming.js +42 -0
  333. package/dist/runners/pairingTiming.js.map +1 -0
  334. package/dist/runners/removalTiming.d.ts +13 -0
  335. package/dist/runners/removalTiming.d.ts.map +1 -0
  336. package/dist/runners/removalTiming.js +17 -0
  337. package/dist/runners/removalTiming.js.map +1 -0
  338. package/dist/runners/runnerProxy.d.ts +9 -0
  339. package/dist/runners/runnerProxy.d.ts.map +1 -0
  340. package/dist/runners/runnerProxy.js +67 -0
  341. package/dist/runners/runnerProxy.js.map +1 -0
  342. package/dist/runners/runnerRemoval.d.ts +21 -0
  343. package/dist/runners/runnerRemoval.d.ts.map +1 -0
  344. package/dist/runners/runnerRemoval.js +94 -0
  345. package/dist/runners/runnerRemoval.js.map +1 -0
  346. package/dist/runners/runnerServiceKind.d.ts +10 -0
  347. package/dist/runners/runnerServiceKind.d.ts.map +1 -0
  348. package/dist/runners/runnerServiceKind.js +13 -0
  349. package/dist/runners/runnerServiceKind.js.map +1 -0
  350. package/dist/runners/runnersCli.d.ts +25 -0
  351. package/dist/runners/runnersCli.d.ts.map +1 -0
  352. package/dist/runners/runnersCli.js +239 -0
  353. package/dist/runners/runnersCli.js.map +1 -0
  354. package/dist/runners/runnersList.d.ts +14 -0
  355. package/dist/runners/runnersList.d.ts.map +1 -0
  356. package/dist/runners/runnersList.js +51 -0
  357. package/dist/runners/runnersList.js.map +1 -0
  358. package/dist/runners/runnersOverview.d.ts +20 -0
  359. package/dist/runners/runnersOverview.d.ts.map +1 -0
  360. package/dist/runners/runnersOverview.js +56 -0
  361. package/dist/runners/runnersOverview.js.map +1 -0
  362. package/dist/runners/sshKeys.d.ts +26 -0
  363. package/dist/runners/sshKeys.d.ts.map +1 -0
  364. package/dist/runners/sshKeys.js +60 -0
  365. package/dist/runners/sshKeys.js.map +1 -0
  366. package/dist/runners/tarArchive.d.ts +20 -0
  367. package/dist/runners/tarArchive.d.ts.map +1 -0
  368. package/dist/runners/tarArchive.js +70 -0
  369. package/dist/runners/tarArchive.js.map +1 -0
  370. package/dist/scheduler/mcpSurface.d.ts +11 -5
  371. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  372. package/dist/scheduler/mcpSurface.js +59 -26
  373. package/dist/scheduler/mcpSurface.js.map +1 -1
  374. package/dist/selfUpdate/selfCheck.d.ts +13 -0
  375. package/dist/selfUpdate/selfCheck.d.ts.map +1 -1
  376. package/dist/selfUpdate/selfCheck.js +9 -3
  377. package/dist/selfUpdate/selfCheck.js.map +1 -1
  378. package/dist/stt/sttInstallEntry.js +7 -4
  379. package/dist/stt/sttInstallEntry.js.map +1 -1
  380. package/dist/testTimings.d.ts +5 -2
  381. package/dist/testTimings.d.ts.map +1 -1
  382. package/dist/testTimings.js +10 -1
  383. package/dist/testTimings.js.map +1 -1
  384. package/dist/utils/agentEnvironment.d.ts +6 -2
  385. package/dist/utils/agentEnvironment.d.ts.map +1 -1
  386. package/dist/utils/agentEnvironment.js +13 -2
  387. package/dist/utils/agentEnvironment.js.map +1 -1
  388. package/dist/utils/runnersScreenPlan.d.ts +141 -0
  389. package/dist/utils/runnersScreenPlan.d.ts.map +1 -0
  390. package/dist/utils/runnersScreenPlan.js +272 -0
  391. package/dist/utils/runnersScreenPlan.js.map +1 -0
  392. package/package.json +5 -2
  393. package/remoteRun/runner.sh +81 -6
@@ -0,0 +1,95 @@
1
+ import { type CommandRunner } from '../selfUpdate/commandRunner';
2
+ import type { RunnerHomePaths } from './runnerHome';
3
+ /**
4
+ * @description The two tools phase 1 needs on a runner besides Node, `ssh` and `tar`.
5
+ *
6
+ * PUEUE is installed by the utility from the pinned release binaries of Nukesor/pueue, each checked against a sha256 written here
7
+ * (a download that does not match is thrown away — nothing is ever executed unchecked). The hashes were taken from the release assets
8
+ * of v4.0.4 on 2026-11-01. They go into `~/.charness-runner/bin/`, no admin needed.
9
+ *
10
+ * RSYNC ≥ 3.1 is FOUND (PATH, Homebrew, /usr/local, /usr/bin). macOS 15.4 and later ship `openrsync`, which lacks the options phase 1
11
+ * uses (`--copy-dest`, `--modify-window=-1`), so it does not count. Without a usable one, rsync 3.4.1 is BUILT from its pinned source
12
+ * with the machine's C compiler (Xcode's command line tools on a Mac); without a compiler the check names the one command to run.
13
+ */
14
+ export declare const pueueVersion = "4.0.4";
15
+ export declare const rsyncVersion = "3.4.1";
16
+ export interface PueueAsset {
17
+ pueueUrl: string;
18
+ pueueSha256: string;
19
+ pueuedUrl: string;
20
+ pueuedSha256: string;
21
+ }
22
+ /** The pinned binaries by `${process.platform}-${process.arch}`. */
23
+ export declare const pueueAssets: Readonly<Record<string, PueueAsset>>;
24
+ export declare function getPueueAsset(platform: NodeJS.Platform, arch: string, table?: Readonly<Record<string, PueueAsset>>): PueueAsset | undefined;
25
+ export type FetchFunction = (url: string, init: {
26
+ signal: AbortSignal;
27
+ redirect: 'follow';
28
+ }) => Promise<{
29
+ ok: boolean;
30
+ status: number;
31
+ arrayBuffer: () => Promise<ArrayBuffer>;
32
+ }>;
33
+ /**
34
+ * @description Download `url` to `destinationPath` (mode 755) only if its sha256 is `expectedSha256`: the bytes are checked in memory
35
+ * first, so a wrong file never exists on disk under the final name.
36
+ */
37
+ export declare function downloadVerified(url: string, expectedSha256: string, destinationPath: string, fetchImpl?: FetchFunction): Promise<void>;
38
+ /** @description The first `x.y.z` in a tool's `--version` output, or `null`. */
39
+ export declare function parseToolVersion(output: string): string | null;
40
+ export interface RsyncInfo {
41
+ /** `openrsync` is Apple's reimplementation; it lacks what phase 1 needs. */
42
+ flavor: 'rsync' | 'openrsync';
43
+ version: string | null;
44
+ }
45
+ export declare function parseRsyncVersion(output: string): RsyncInfo | null;
46
+ export declare function checkIsRsyncUsable(info: RsyncInfo): boolean;
47
+ export interface ToolFound {
48
+ path: string;
49
+ version: string;
50
+ }
51
+ export interface ToolDeps {
52
+ runner: CommandRunner;
53
+ platform: NodeJS.Platform;
54
+ arch: string;
55
+ environment: NodeJS.ProcessEnv;
56
+ fetchImpl: FetchFunction;
57
+ /** The pinned binaries to choose from; a test supplies its own. */
58
+ pueueAssetTable: Readonly<Record<string, PueueAsset>>;
59
+ checkExists: (candidate: string) => boolean;
60
+ cpuCount: number;
61
+ }
62
+ export declare function createToolDeps(): ToolDeps;
63
+ /** @description A usable rsync from PATH, Homebrew or the system folders, with the one `<root>/bin/rsync` (built earlier) first. */
64
+ export declare function findRsync(paths: RunnerHomePaths, deps: ToolDeps): Promise<ToolFound | null>;
65
+ /** @description Our pueue in `<root>/bin`, when it is there and runs. */
66
+ export declare function findPueue(paths: RunnerHomePaths, deps: ToolDeps): Promise<ToolFound | null>;
67
+ export type ToolInstallOutcome = {
68
+ ok: true;
69
+ tool: ToolFound;
70
+ wasInstalled: boolean;
71
+ } | {
72
+ ok: false;
73
+ reason: string;
74
+ };
75
+ /** @description Make sure `<root>/bin/pueue` and `pueued` are there (downloaded and verified when not). */
76
+ export declare function ensurePueue(paths: RunnerHomePaths, deps: ToolDeps): Promise<ToolInstallOutcome>;
77
+ /** @description The one thing to tell the operator when rsync cannot be built here. */
78
+ export declare function describeRsyncRemedy(platform: NodeJS.Platform): string;
79
+ /** @description The build steps of rsync, in order (pure, so a test can read them). */
80
+ export declare function planRsyncBuild(paths: RunnerHomePaths, cpuCount: number): Array<{
81
+ file: string;
82
+ args: string[];
83
+ cwd: string;
84
+ }>;
85
+ /** @description Build rsync from the pinned source and link it as `<root>/bin/rsync`. */
86
+ export declare function buildRsync(paths: RunnerHomePaths, deps: ToolDeps): Promise<ToolInstallOutcome>;
87
+ /**
88
+ * @description Make `<root>/bin/<name>` the tool at `targetPath`. Jobs get `~/.charness-runner/bin` FIRST on their PATH, so what is linked
89
+ * there is what every job (and phase 1's runner script) runs — discovery that only looked at the caller's PATH would report a tool that
90
+ * the jobs never see.
91
+ */
92
+ export declare function linkToolIntoBin(paths: RunnerHomePaths, name: string, targetPath: string): void;
93
+ /** @description rsync: the usable one that is there — linked into the runner's bin folder so jobs run exactly that one — else a built one. */
94
+ export declare function ensureRsync(paths: RunnerHomePaths, deps: ToolDeps): Promise<ToolInstallOutcome>;
95
+ //# sourceMappingURL=toolInstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolInstall.d.ts","sourceRoot":"","sources":["../../src/runnerUtility/toolInstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
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.pueueAssets = exports.rsyncVersion = exports.pueueVersion = void 0;
37
+ exports.getPueueAsset = getPueueAsset;
38
+ exports.downloadVerified = downloadVerified;
39
+ exports.parseToolVersion = parseToolVersion;
40
+ exports.parseRsyncVersion = parseRsyncVersion;
41
+ exports.checkIsRsyncUsable = checkIsRsyncUsable;
42
+ exports.createToolDeps = createToolDeps;
43
+ exports.findRsync = findRsync;
44
+ exports.findPueue = findPueue;
45
+ exports.ensurePueue = ensurePueue;
46
+ exports.describeRsyncRemedy = describeRsyncRemedy;
47
+ exports.planRsyncBuild = planRsyncBuild;
48
+ exports.buildRsync = buildRsync;
49
+ exports.linkToolIntoBin = linkToolIntoBin;
50
+ exports.ensureRsync = ensureRsync;
51
+ const crypto_1 = require("crypto");
52
+ const fs = __importStar(require("fs"));
53
+ const os = __importStar(require("os"));
54
+ const path = __importStar(require("path"));
55
+ const commandRunner_1 = require("../selfUpdate/commandRunner");
56
+ /**
57
+ * @description The two tools phase 1 needs on a runner besides Node, `ssh` and `tar`.
58
+ *
59
+ * PUEUE is installed by the utility from the pinned release binaries of Nukesor/pueue, each checked against a sha256 written here
60
+ * (a download that does not match is thrown away — nothing is ever executed unchecked). The hashes were taken from the release assets
61
+ * of v4.0.4 on 2026-11-01. They go into `~/.charness-runner/bin/`, no admin needed.
62
+ *
63
+ * RSYNC ≥ 3.1 is FOUND (PATH, Homebrew, /usr/local, /usr/bin). macOS 15.4 and later ship `openrsync`, which lacks the options phase 1
64
+ * uses (`--copy-dest`, `--modify-window=-1`), so it does not count. Without a usable one, rsync 3.4.1 is BUILT from its pinned source
65
+ * with the machine's C compiler (Xcode's command line tools on a Mac); without a compiler the check names the one command to run.
66
+ */
67
+ exports.pueueVersion = '4.0.4';
68
+ exports.rsyncVersion = '3.4.1';
69
+ const pueueBaseUrl = `https://github.com/Nukesor/pueue/releases/download/v${exports.pueueVersion}`;
70
+ const rsyncSourceUrl = `https://download.samba.org/pub/rsync/src/rsync-${exports.rsyncVersion}.tar.gz`;
71
+ const rsyncSourceSha256 = '2924bcb3a1ed8b551fc101f740b9f0fe0a202b115027647cf69850d65fd88c52';
72
+ const downloadTimeoutMs = 3 * 60 * 1000;
73
+ const maxDownloadBytes = 64 * 1024 * 1024;
74
+ const versionProbeTimeoutMs = 4000;
75
+ const buildStepTimeoutMs = 15 * 60 * 1000;
76
+ const executableMode = 0o755;
77
+ const minRsync = { major: 3, minor: 1 };
78
+ const extraRsyncDirs = ['/opt/homebrew/bin', '/usr/local/bin', '/usr/bin'];
79
+ function createPueueAsset(target, pueueSha256, pueuedSha256) {
80
+ return { pueueUrl: `${pueueBaseUrl}/pueue-${target}`, pueueSha256, pueuedUrl: `${pueueBaseUrl}/pueued-${target}`, pueuedSha256 };
81
+ }
82
+ /** The pinned binaries by `${process.platform}-${process.arch}`. */
83
+ exports.pueueAssets = {
84
+ 'linux-x64': createPueueAsset('x86_64-unknown-linux-musl', 'c1b10d7e4e62211075ddd0e1dc3e8cbfc5a43d662cb3be7402a28504e23fcb51', '5afeff6adbafb909e8d54e2caff158e6966c2adffa2c09e60fd631cc51b60390'),
85
+ 'linux-arm64': createPueueAsset('aarch64-unknown-linux-musl', '759bf5100a51024997111c6913aaf3330a0cdfd893ff552dcf429ae9b5e01e09', '332c5ef74270b64aeaf04894c8c04826f3422eb7d50dbd1a8e0706d74a42f653'),
86
+ 'darwin-x64': createPueueAsset('x86_64-apple-darwin', 'c5b89a2f9f9d355b33880735a1f12a8b8d09002f95cc7d2e5f3294e313fb8540', '4de7c4790989198007c6c0789c56606237d0456a2ce3666b5a0b198478c06263'),
87
+ 'darwin-arm64': createPueueAsset('aarch64-apple-darwin', '7780dbd21e3a4106e88a57396d6dc2dbcbbae253c7e00d92d994902896b8cb82', 'bf5a1151d70c328dd036fb6d786fba53a68d8574c12391d04db3d08b04079205'),
88
+ };
89
+ function getPueueAsset(platform, arch, table = exports.pueueAssets) {
90
+ return table[`${platform}-${arch}`];
91
+ }
92
+ /**
93
+ * @description Download `url` to `destinationPath` (mode 755) only if its sha256 is `expectedSha256`: the bytes are checked in memory
94
+ * first, so a wrong file never exists on disk under the final name.
95
+ */
96
+ async function downloadVerified(url, expectedSha256, destinationPath, fetchImpl = fetch) {
97
+ const response = await fetchImpl(url, { signal: AbortSignal.timeout(downloadTimeoutMs), redirect: 'follow' });
98
+ if (!response.ok)
99
+ throw new Error(`download failed (HTTP ${response.status}): ${url}`);
100
+ const bytes = Buffer.from(await response.arrayBuffer());
101
+ if (bytes.length > maxDownloadBytes)
102
+ throw new Error(`download is larger than expected: ${url}`);
103
+ const actualSha256 = (0, crypto_1.createHash)('sha256').update(bytes).digest('hex');
104
+ if (actualSha256 !== expectedSha256)
105
+ throw new Error(`checksum mismatch for ${url}: expected ${expectedSha256.slice(0, 12)}…, got ${actualSha256.slice(0, 12)}…`);
106
+ fs.mkdirSync(path.dirname(destinationPath), { recursive: true, mode: 0o700 });
107
+ const temporaryPath = `${destinationPath}.${process.pid}.tmp`;
108
+ fs.writeFileSync(temporaryPath, bytes, { mode: executableMode });
109
+ fs.renameSync(temporaryPath, destinationPath);
110
+ }
111
+ /** @description The first `x.y.z` in a tool's `--version` output, or `null`. */
112
+ function parseToolVersion(output) {
113
+ return /(\d+\.\d+(?:\.\d+)?)/.exec(output)?.[1] ?? null;
114
+ }
115
+ function parseRsyncVersion(output) {
116
+ if (/openrsync/i.test(output))
117
+ return { flavor: 'openrsync', version: null };
118
+ const match = /rsync\s+version\s+v?(\d+\.\d+(?:\.\d+)?)/i.exec(output);
119
+ return match === null ? null : { flavor: 'rsync', version: match[1] };
120
+ }
121
+ function checkIsRsyncUsable(info) {
122
+ if (info.flavor !== 'rsync' || info.version === null)
123
+ return false;
124
+ const [major, minor] = info.version.split('.').map(Number);
125
+ return major > minRsync.major || (major === minRsync.major && minor >= minRsync.minor);
126
+ }
127
+ function createToolDeps() {
128
+ return { runner: commandRunner_1.runCommand, platform: process.platform, arch: process.arch, environment: process.env, fetchImpl: fetch, pueueAssetTable: exports.pueueAssets, checkExists: fs.existsSync, cpuCount: os.cpus().length };
129
+ }
130
+ /** @description A usable rsync from PATH, Homebrew or the system folders, with the one `<root>/bin/rsync` (built earlier) first. */
131
+ async function findRsync(paths, deps) {
132
+ const pathDirs = (deps.environment.PATH ?? '').split(path.delimiter).filter((dir) => dir !== '');
133
+ const candidates = [...new Set([paths.binDir, ...pathDirs, ...extraRsyncDirs])].map((dir) => path.join(dir, 'rsync')).filter(deps.checkExists);
134
+ for (const candidate of candidates) {
135
+ const result = await deps.runner(candidate, ['--version'], { timeoutMs: versionProbeTimeoutMs });
136
+ const info = result.ok ? parseRsyncVersion(result.stdout) : null;
137
+ if (info !== null && checkIsRsyncUsable(info) && info.version !== null)
138
+ return { path: candidate, version: info.version };
139
+ }
140
+ return null;
141
+ }
142
+ /** @description Our pueue in `<root>/bin`, when it is there and runs. */
143
+ async function findPueue(paths, deps) {
144
+ const candidate = path.join(paths.binDir, 'pueue');
145
+ if (!deps.checkExists(candidate))
146
+ return null;
147
+ const result = await deps.runner(candidate, ['--version'], { timeoutMs: versionProbeTimeoutMs });
148
+ const version = result.ok ? parseToolVersion(result.stdout) : null;
149
+ return version === null ? null : { path: candidate, version };
150
+ }
151
+ /** @description Make sure `<root>/bin/pueue` and `pueued` are there (downloaded and verified when not). */
152
+ async function ensurePueue(paths, deps) {
153
+ const existing = await findPueue(paths, deps);
154
+ if (existing !== null && deps.checkExists(path.join(paths.binDir, 'pueued')))
155
+ return { ok: true, tool: existing, wasInstalled: false };
156
+ const asset = getPueueAsset(deps.platform, deps.arch, deps.pueueAssetTable);
157
+ if (asset === undefined)
158
+ return { ok: false, reason: `no pinned Pueue binary for ${deps.platform}/${deps.arch}; install Pueue ${exports.pueueVersion} by hand into ${paths.binDir}` };
159
+ try {
160
+ await downloadVerified(asset.pueueUrl, asset.pueueSha256, path.join(paths.binDir, 'pueue'), deps.fetchImpl);
161
+ await downloadVerified(asset.pueuedUrl, asset.pueuedSha256, path.join(paths.binDir, 'pueued'), deps.fetchImpl);
162
+ }
163
+ catch (error) {
164
+ return { ok: false, reason: error instanceof Error ? error.message : 'the Pueue download failed' };
165
+ }
166
+ const installed = await findPueue(paths, deps);
167
+ return installed === null ? { ok: false, reason: 'the downloaded pueue does not run on this machine' } : { ok: true, tool: installed, wasInstalled: true };
168
+ }
169
+ /** @description The one thing to tell the operator when rsync cannot be built here. */
170
+ function describeRsyncRemedy(platform) {
171
+ return platform === 'darwin'
172
+ ? 'rsync 3.1 or newer is missing (macOS\'s own is openrsync). Install the compiler tools with `xcode-select --install` and run `charness-runner check` again, or `brew install rsync`.'
173
+ : 'rsync 3.1 or newer is missing. Install it with your package manager (for example `sudo apt install rsync`) and run `charness-runner check` again.';
174
+ }
175
+ /** @description The build steps of rsync, in order (pure, so a test can read them). */
176
+ function planRsyncBuild(paths, cpuCount) {
177
+ const sourceDir = path.join(paths.buildDir, `rsync-${exports.rsyncVersion}`);
178
+ const prefix = path.join(paths.root, 'rsync');
179
+ return [
180
+ { file: 'tar', args: ['-xzf', path.join(paths.buildDir, `rsync-${exports.rsyncVersion}.tar.gz`), '-C', paths.buildDir], cwd: paths.buildDir },
181
+ { file: './configure', args: [`--prefix=${prefix}`, '--disable-md2man', '--disable-xxhash', '--disable-zstd', '--disable-lz4', '--disable-openssl', '--with-included-popt', '--with-included-zlib'], cwd: sourceDir },
182
+ { file: 'make', args: [`-j${Math.max(1, cpuCount)}`], cwd: sourceDir },
183
+ { file: 'make', args: ['install'], cwd: sourceDir },
184
+ ];
185
+ }
186
+ /** @description Build rsync from the pinned source and link it as `<root>/bin/rsync`. */
187
+ async function buildRsync(paths, deps) {
188
+ const compiler = await deps.runner('cc', ['--version'], { timeoutMs: versionProbeTimeoutMs });
189
+ const make = await deps.runner('make', ['--version'], { timeoutMs: versionProbeTimeoutMs });
190
+ if (!compiler.ok || !make.ok)
191
+ return { ok: false, reason: describeRsyncRemedy(deps.platform) };
192
+ fs.mkdirSync(paths.buildDir, { recursive: true, mode: 0o700 });
193
+ try {
194
+ await downloadVerified(rsyncSourceUrl, rsyncSourceSha256, path.join(paths.buildDir, `rsync-${exports.rsyncVersion}.tar.gz`), deps.fetchImpl);
195
+ }
196
+ catch (error) {
197
+ return { ok: false, reason: error instanceof Error ? error.message : 'the rsync download failed' };
198
+ }
199
+ for (const step of planRsyncBuild(paths, deps.cpuCount)) {
200
+ const result = await deps.runner(step.file, step.args, { cwd: step.cwd, timeoutMs: buildStepTimeoutMs });
201
+ if (!result.ok)
202
+ return { ok: false, reason: `building rsync failed at «${step.file} ${step.args[0] ?? ''}»: ${result.stderr.trim().split('\n').slice(-2).join(' | ')}` };
203
+ }
204
+ const built = path.join(paths.root, 'rsync', 'bin', 'rsync');
205
+ fs.mkdirSync(paths.binDir, { recursive: true, mode: 0o700 });
206
+ fs.rmSync(path.join(paths.binDir, 'rsync'), { force: true });
207
+ fs.symlinkSync(built, path.join(paths.binDir, 'rsync'));
208
+ const found = await findRsync(paths, deps);
209
+ return found === null ? { ok: false, reason: 'the rsync that was built does not run' } : { ok: true, tool: found, wasInstalled: true };
210
+ }
211
+ /**
212
+ * @description Make `<root>/bin/<name>` the tool at `targetPath`. Jobs get `~/.charness-runner/bin` FIRST on their PATH, so what is linked
213
+ * there is what every job (and phase 1's runner script) runs — discovery that only looked at the caller's PATH would report a tool that
214
+ * the jobs never see.
215
+ */
216
+ function linkToolIntoBin(paths, name, targetPath) {
217
+ const linkPath = path.join(paths.binDir, name);
218
+ if (linkPath === targetPath)
219
+ return;
220
+ fs.mkdirSync(paths.binDir, { recursive: true, mode: 0o700 });
221
+ fs.rmSync(linkPath, { force: true });
222
+ fs.symlinkSync(targetPath, linkPath);
223
+ }
224
+ /** @description rsync: the usable one that is there — linked into the runner's bin folder so jobs run exactly that one — else a built one. */
225
+ async function ensureRsync(paths, deps) {
226
+ const found = await findRsync(paths, deps);
227
+ if (found === null)
228
+ return buildRsync(paths, deps);
229
+ linkToolIntoBin(paths, 'rsync', found.path);
230
+ return { ok: true, tool: found, wasInstalled: false };
231
+ }
232
+ //# sourceMappingURL=toolInstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolInstall.js","sourceRoot":"","sources":["../../src/runnerUtility/toolInstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @description How often a LINKED runner asks the hub which package it has now (the `version` request, over the connection it already
3
+ * holds). A link that stays healthy for days would otherwise never learn of a hub update: the `link` answer names the package once, when
4
+ * the link starts. In a module of its own so the runner utility reads it without loading the bot.
5
+ *
6
+ * The test seam `CHARNESS_TEST_TIMINGS` (`testTimings.ts`) may only SHORTEN it (key `runnerVersionPollMs`); like the remote-run lease it
7
+ * is read tolerantly here, because this module cannot import `testTimings.ts` (its graph reaches the bot) — the boot of an instance that
8
+ * carries a bad value is what refuses it by name.
9
+ */
10
+ /** Production: ask every five minutes. */
11
+ export declare const runnerVersionPollMs: number;
12
+ /** A shorter poll than this is a request loop, not a check. */
13
+ export declare const runnerVersionPollMinMs = 1000;
14
+ /** @description The poll interval in force: the production one, or the seam's shorter `runnerVersionPollMs` when it is a whole number of ms within [min, production]. */
15
+ export declare function readRunnerVersionPollMs(env: NodeJS.ProcessEnv): number;
16
+ //# sourceMappingURL=versionPollTiming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionPollTiming.d.ts","sourceRoot":"","sources":["../../src/runnerUtility/versionPollTiming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AACjD,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAI3C,yKAAyK;AACzK,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAYtE"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * @description How often a LINKED runner asks the hub which package it has now (the `version` request, over the connection it already
4
+ * holds). A link that stays healthy for days would otherwise never learn of a hub update: the `link` answer names the package once, when
5
+ * the link starts. In a module of its own so the runner utility reads it without loading the bot.
6
+ *
7
+ * The test seam `CHARNESS_TEST_TIMINGS` (`testTimings.ts`) may only SHORTEN it (key `runnerVersionPollMs`); like the remote-run lease it
8
+ * is read tolerantly here, because this module cannot import `testTimings.ts` (its graph reaches the bot) — the boot of an instance that
9
+ * carries a bad value is what refuses it by name.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.runnerVersionPollMinMs = exports.runnerVersionPollMs = void 0;
13
+ exports.readRunnerVersionPollMs = readRunnerVersionPollMs;
14
+ /** Production: ask every five minutes. */
15
+ exports.runnerVersionPollMs = 5 * 60 * 1000;
16
+ /** A shorter poll than this is a request loop, not a check. */
17
+ exports.runnerVersionPollMinMs = 1000;
18
+ const testTimingsVariableName = 'CHARNESS_TEST_TIMINGS';
19
+ /** @description The poll interval in force: the production one, or the seam's shorter `runnerVersionPollMs` when it is a whole number of ms within [min, production]. */
20
+ function readRunnerVersionPollMs(env) {
21
+ const rawTestTimings = env[testTimingsVariableName];
22
+ if (rawTestTimings === undefined || rawTestTimings.trim() === '')
23
+ return exports.runnerVersionPollMs;
24
+ let overrides;
25
+ try {
26
+ overrides = JSON.parse(rawTestTimings);
27
+ }
28
+ catch {
29
+ return exports.runnerVersionPollMs;
30
+ }
31
+ const overrideMs = overrides?.runnerVersionPollMs;
32
+ if (overrideMs === undefined || !Number.isInteger(overrideMs))
33
+ return exports.runnerVersionPollMs;
34
+ return overrideMs >= exports.runnerVersionPollMinMs && overrideMs <= exports.runnerVersionPollMs ? overrideMs : exports.runnerVersionPollMs;
35
+ }
36
+ //# sourceMappingURL=versionPollTiming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionPollTiming.js","sourceRoot":"","sources":["../../src/runnerUtility/versionPollTiming.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAUH,0DAYC;AApBD,0CAA0C;AAC7B,QAAA,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACjD,+DAA+D;AAClD,QAAA,sBAAsB,GAAG,IAAI,CAAC;AAE3C,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAExD,yKAAyK;AACzK,SAAgB,uBAAuB,CAAC,GAAsB;IAC5D,MAAM,cAAc,GAAG,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACpD,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,2BAAmB,CAAC;IAC7F,IAAI,SAAkD,CAAC;IACvD,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,2BAAmB,CAAC;IAC7B,CAAC;IACD,MAAM,UAAU,GAAG,SAAS,EAAE,mBAAmB,CAAC;IAClD,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAAE,OAAO,2BAAmB,CAAC;IAC1F,OAAO,UAAU,IAAI,8BAAsB,IAAI,UAAU,IAAI,2BAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,2BAAmB,CAAC;AACtH,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @description The part of the account's `authorized_keys` that charness owns: ONE marked block, replaced as a whole and derived from
3
+ * the registry (`hubRegistry.ts` renders it), so the file and the registry never drift apart. Every line outside the markers is the
4
+ * operator's and is kept byte for byte. A file with a damaged block (a marker without its twin, two blocks) is NOT edited — guessing
5
+ * which lines are ours could delete a key of the operator.
6
+ *
7
+ * A runner's key is a forced-command key with NO forwarding of any kind: `restrict` turns off port, unix-socket, agent and X11
8
+ * forwarding, ptys and `~/.ssh/rc`; OpenSSH cannot limit forwarding of unix sockets in any finer way, and a key that could forward
9
+ * one could open the bot's tmux sockets.
10
+ */
11
+ export declare const authorizedKeysBlockStart = "# charness runners: managed block, do not edit between the markers";
12
+ export declare const authorizedKeysBlockEnd = "# charness runners: end of the managed block";
13
+ export declare class AuthorizedKeysBlockError extends Error {
14
+ constructor(message: string);
15
+ }
16
+ /** @description The lines between the markers (none when there is no block). */
17
+ export declare function extractManagedBlock(text: string): string[];
18
+ /**
19
+ * @description `text` with the managed block holding exactly `blockLines`: an existing block is replaced in place, a new one is
20
+ * appended, and no lines remove the block (the file is returned as it was when there is none). Nothing outside the block changes.
21
+ */
22
+ export declare function replaceManagedBlock(text: string, blockLines: readonly string[]): string;
23
+ /** @description `YYYYMMDDHHMMSSZ` (UTC), the form of sshd's `expiry-time` option. */
24
+ export declare function formatExpiryTime(epochMs: number): string;
25
+ export interface TempKeyLineParams {
26
+ publicKey: string;
27
+ expiresAtMs: number;
28
+ gatePath: string;
29
+ keysPath: string;
30
+ dir: string;
31
+ pairId: string;
32
+ }
33
+ /** @description The line of a pairing's temporary key: it may log in until `expiresAtMs` and only to be handed to the gate's `redeem` mode. */
34
+ export declare function buildTempKeyLine(params: TempKeyLineParams): string;
35
+ export interface RunnerKeyLineParams {
36
+ publicKey: string;
37
+ gatePath: string;
38
+ keysPath: string;
39
+ dir: string;
40
+ runnerId: string;
41
+ }
42
+ /** @description The line of a paired runner's key: no expiry, the gate's `runner` mode. */
43
+ export declare function buildRunnerKeyLine(params: RunnerKeyLineParams): string;
44
+ /** @description Throws {@link AuthorizedKeysBlockError} when the file holds a damaged block — asked BEFORE a change is committed, so a block that cannot be edited never leaves a half-done change behind. */
45
+ export declare function assertManagedBlockIntact(authorizedKeysPath: string): void;
46
+ /**
47
+ * @description Make the managed block of `authorizedKeysPath` hold exactly `blockLines`. The folder is created 0700 when missing
48
+ * (sshd's StrictModes refuses a writable one), the file is written 0600 through a temp file and a rename — into the file a symlink
49
+ * points to, never over the link (a dotfile manager keeps the real file elsewhere). Nothing is written when nothing changes.
50
+ */
51
+ export declare function writeManagedBlock(authorizedKeysPath: string, blockLines: readonly string[]): void;
52
+ //# sourceMappingURL=authorizedKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorizedKeys.d.ts","sourceRoot":"","sources":["../../src/runners/authorizedKeys.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AAEH,eAAO,MAAM,wBAAwB,uEAAuE,CAAC;AAC7G,eAAO,MAAM,sBAAsB,iDAAiD,CAAC;AAOrF,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAiBD,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAI1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAUvF;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGxD;AAUD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+IAA+I;AAC/I,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAElE;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAWD,8MAA8M;AAC9M,wBAAgB,wBAAwB,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAOjG"}
@@ -0,0 +1,153 @@
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.AuthorizedKeysBlockError = exports.authorizedKeysBlockEnd = exports.authorizedKeysBlockStart = void 0;
37
+ exports.extractManagedBlock = extractManagedBlock;
38
+ exports.replaceManagedBlock = replaceManagedBlock;
39
+ exports.formatExpiryTime = formatExpiryTime;
40
+ exports.buildTempKeyLine = buildTempKeyLine;
41
+ exports.buildRunnerKeyLine = buildRunnerKeyLine;
42
+ exports.assertManagedBlockIntact = assertManagedBlockIntact;
43
+ exports.writeManagedBlock = writeManagedBlock;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const configDirFile_1 = require("../configDirFile");
47
+ const ssh_1 = require("../remoteRun/ssh");
48
+ /**
49
+ * @description The part of the account's `authorized_keys` that charness owns: ONE marked block, replaced as a whole and derived from
50
+ * the registry (`hubRegistry.ts` renders it), so the file and the registry never drift apart. Every line outside the markers is the
51
+ * operator's and is kept byte for byte. A file with a damaged block (a marker without its twin, two blocks) is NOT edited — guessing
52
+ * which lines are ours could delete a key of the operator.
53
+ *
54
+ * A runner's key is a forced-command key with NO forwarding of any kind: `restrict` turns off port, unix-socket, agent and X11
55
+ * forwarding, ptys and `~/.ssh/rc`; OpenSSH cannot limit forwarding of unix sockets in any finer way, and a key that could forward
56
+ * one could open the bot's tmux sockets.
57
+ */
58
+ exports.authorizedKeysBlockStart = '# charness runners: managed block, do not edit between the markers';
59
+ exports.authorizedKeysBlockEnd = '# charness runners: end of the managed block';
60
+ const sshDirectoryMode = 0o700;
61
+ const authorizedKeysMode = 0o600;
62
+ /** What may not appear in the folder path inside `command="…"`: sshd cannot escape a backslash, and a quote ends the option. */
63
+ const unsafeCommandCharacters = /["'\\\n\r]/;
64
+ const msPerSecond = 1000;
65
+ class AuthorizedKeysBlockError extends Error {
66
+ constructor(message) {
67
+ super(message);
68
+ this.name = 'AuthorizedKeysBlockError';
69
+ }
70
+ }
71
+ exports.AuthorizedKeysBlockError = AuthorizedKeysBlockError;
72
+ function findBlock(lines) {
73
+ const starts = lines.flatMap((line, index) => (line.trimEnd() === exports.authorizedKeysBlockStart ? [index] : []));
74
+ const ends = lines.flatMap((line, index) => (line.trimEnd() === exports.authorizedKeysBlockEnd ? [index] : []));
75
+ if (starts.length === 0 && ends.length === 0)
76
+ return null;
77
+ if (starts.length !== 1 || ends.length !== 1 || ends[0] < starts[0]) {
78
+ throw new AuthorizedKeysBlockError('authorized_keys holds a damaged charness block (the two marker lines do not pair up); fix it by hand — nothing was changed');
79
+ }
80
+ return { startIndex: starts[0], endIndex: ends[0] };
81
+ }
82
+ /** @description The lines between the markers (none when there is no block). */
83
+ function extractManagedBlock(text) {
84
+ const lines = text.split('\n');
85
+ const block = findBlock(lines);
86
+ return block === null ? [] : lines.slice(block.startIndex + 1, block.endIndex);
87
+ }
88
+ /**
89
+ * @description `text` with the managed block holding exactly `blockLines`: an existing block is replaced in place, a new one is
90
+ * appended, and no lines remove the block (the file is returned as it was when there is none). Nothing outside the block changes.
91
+ */
92
+ function replaceManagedBlock(text, blockLines) {
93
+ const lines = text.split('\n');
94
+ const block = findBlock(lines);
95
+ if (block === null) {
96
+ if (blockLines.length === 0)
97
+ return text;
98
+ const prefix = text === '' || text.endsWith('\n') ? text : `${text}\n`;
99
+ return `${prefix}${[exports.authorizedKeysBlockStart, ...blockLines, exports.authorizedKeysBlockEnd].join('\n')}\n`;
100
+ }
101
+ const replacement = blockLines.length === 0 ? [] : [exports.authorizedKeysBlockStart, ...blockLines, exports.authorizedKeysBlockEnd];
102
+ return [...lines.slice(0, block.startIndex), ...replacement, ...lines.slice(block.endIndex + 1)].join('\n');
103
+ }
104
+ /** @description `YYYYMMDDHHMMSSZ` (UTC), the form of sshd's `expiry-time` option. */
105
+ function formatExpiryTime(epochMs) {
106
+ const iso = new Date(Math.floor(epochMs / msPerSecond) * msPerSecond).toISOString();
107
+ return `${iso.slice(0, 4)}${iso.slice(5, 7)}${iso.slice(8, 10)}${iso.slice(11, 13)}${iso.slice(14, 16)}${iso.slice(17, 19)}Z`;
108
+ }
109
+ function buildGateCommand(gatePath, keysPath, dir, kind, id) {
110
+ for (const value of [gatePath, keysPath, dir]) {
111
+ if (unsafeCommandCharacters.test(value))
112
+ throw new AuthorizedKeysBlockError('the charness folder path holds a quote, a backslash or a line break, which an authorized_keys command cannot carry');
113
+ }
114
+ const command = [(0, ssh_1.quoteShellWord)(gatePath), '--dir', (0, ssh_1.quoteShellWord)(dir), '--keys', (0, ssh_1.quoteShellWord)(keysPath), kind, id].join(' ');
115
+ return `command="${command}"`;
116
+ }
117
+ /** @description The line of a pairing's temporary key: it may log in until `expiresAtMs` and only to be handed to the gate's `redeem` mode. */
118
+ function buildTempKeyLine(params) {
119
+ return `restrict,expiry-time="${formatExpiryTime(params.expiresAtMs)}",${buildGateCommand(params.gatePath, params.keysPath, params.dir, 'redeem', params.pairId)} ${params.publicKey} charness-pairing:${params.pairId}`;
120
+ }
121
+ /** @description The line of a paired runner's key: no expiry, the gate's `runner` mode. */
122
+ function buildRunnerKeyLine(params) {
123
+ return `restrict,${buildGateCommand(params.gatePath, params.keysPath, params.dir, 'runner', params.runnerId)} ${params.publicKey} charness-runner:${params.runnerId}`;
124
+ }
125
+ function readTextIfPresent(filePath) {
126
+ try {
127
+ return fs.readFileSync(filePath, 'utf8');
128
+ }
129
+ catch (error) {
130
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
131
+ return '';
132
+ throw error;
133
+ }
134
+ }
135
+ /** @description Throws {@link AuthorizedKeysBlockError} when the file holds a damaged block — asked BEFORE a change is committed, so a block that cannot be edited never leaves a half-done change behind. */
136
+ function assertManagedBlockIntact(authorizedKeysPath) {
137
+ extractManagedBlock(readTextIfPresent(authorizedKeysPath));
138
+ }
139
+ /**
140
+ * @description Make the managed block of `authorizedKeysPath` hold exactly `blockLines`. The folder is created 0700 when missing
141
+ * (sshd's StrictModes refuses a writable one), the file is written 0600 through a temp file and a rename — into the file a symlink
142
+ * points to, never over the link (a dotfile manager keeps the real file elsewhere). Nothing is written when nothing changes.
143
+ */
144
+ function writeManagedBlock(authorizedKeysPath, blockLines) {
145
+ fs.mkdirSync(path.dirname(authorizedKeysPath), { recursive: true, mode: sshDirectoryMode });
146
+ const targetPath = fs.existsSync(authorizedKeysPath) ? fs.realpathSync(authorizedKeysPath) : authorizedKeysPath;
147
+ const current = readTextIfPresent(targetPath);
148
+ const next = replaceManagedBlock(current, blockLines);
149
+ if (next === current)
150
+ return;
151
+ (0, configDirFile_1.writeTextFileAtomically)(targetPath, next, authorizedKeysMode);
152
+ }
153
+ //# sourceMappingURL=authorizedKeys.js.map