@fastagent-sh/fastagent 0.21.1 → 0.22.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 (388) hide show
  1. package/README.md +9 -12
  2. package/dist/agent.d.ts +24 -37
  3. package/dist/agent.js +7 -15
  4. package/dist/atomic-write.d.ts +13 -17
  5. package/dist/atomic-write.js +18 -29
  6. package/dist/bind.d.ts +12 -22
  7. package/dist/bind.js +18 -27
  8. package/dist/channel.d.ts +11 -33
  9. package/dist/channels/agentcore-limits.d.ts +2 -13
  10. package/dist/channels/agentcore-limits.js +2 -13
  11. package/dist/channels/agentcore-protocol.d.ts +67 -58
  12. package/dist/channels/agentcore-protocol.js +23 -15
  13. package/dist/channels/agentcore-service.d.ts +19 -33
  14. package/dist/channels/agentcore-service.js +176 -59
  15. package/dist/channels/agentcore.d.ts +39 -33
  16. package/dist/channels/agentcore.js +90 -224
  17. package/dist/channels/body.d.ts +15 -2
  18. package/dist/channels/body.js +24 -2
  19. package/dist/channels/busy.d.ts +1 -21
  20. package/dist/channels/busy.js +2 -39
  21. package/dist/channels/control.d.ts +17 -62
  22. package/dist/channels/control.js +74 -182
  23. package/dist/channels/define-channel.d.ts +39 -0
  24. package/dist/channels/define-channel.js +9 -0
  25. package/dist/channels/discover.d.ts +10 -31
  26. package/dist/channels/discover.js +37 -31
  27. package/dist/channels/feishu/bootstrap-token.d.ts +1 -8
  28. package/dist/channels/feishu/bootstrap-token.js +7 -23
  29. package/dist/channels/feishu/card.d.ts +14 -28
  30. package/dist/channels/feishu/card.js +16 -30
  31. package/dist/channels/feishu/cloud.d.ts +1 -5
  32. package/dist/channels/feishu/context-buffer.d.ts +4 -23
  33. package/dist/channels/feishu/context-buffer.js +8 -31
  34. package/dist/channels/feishu/crypto.d.ts +10 -5
  35. package/dist/channels/feishu/crypto.js +12 -19
  36. package/dist/channels/feishu/feishu-api.d.ts +2 -1
  37. package/dist/channels/feishu/feishu-api.js +5 -4
  38. package/dist/channels/feishu/feishu.d.ts +4 -10
  39. package/dist/channels/feishu/feishu.js +113 -227
  40. package/dist/channels/feishu/invoke-turn.d.ts +5 -4
  41. package/dist/channels/feishu/invoke-turn.js +36 -54
  42. package/dist/channels/feishu/model.d.ts +4 -21
  43. package/dist/channels/feishu/model.js +1 -8
  44. package/dist/channels/feishu/normalize.d.ts +2 -10
  45. package/dist/channels/feishu/normalize.js +7 -42
  46. package/dist/channels/feishu/parse.d.ts +9 -29
  47. package/dist/channels/feishu/parse.js +8 -26
  48. package/dist/channels/feishu/preview.d.ts +12 -14
  49. package/dist/channels/feishu/preview.js +108 -207
  50. package/dist/channels/feishu/register-app.d.ts +8 -23
  51. package/dist/channels/feishu/register-app.js +7 -20
  52. package/dist/channels/feishu/register-webhook.d.ts +2 -9
  53. package/dist/channels/feishu/register-webhook.js +9 -33
  54. package/dist/channels/feishu/scaffold/channel.ts +27 -19
  55. package/dist/channels/feishu/scaffold/channel.websocket.ts +31 -0
  56. package/dist/channels/feishu/setup-mode.d.ts +11 -36
  57. package/dist/channels/feishu/setup-mode.js +7 -26
  58. package/dist/channels/feishu/ws-ingress.d.ts +1 -2
  59. package/dist/channels/feishu/ws-ingress.js +6 -8
  60. package/dist/channels/http.d.ts +15 -15
  61. package/dist/channels/http.js +19 -9
  62. package/dist/channels/kit/attachment-path.d.ts +4 -5
  63. package/dist/channels/kit/attachment-path.js +10 -34
  64. package/dist/channels/kit/context-buffer.d.ts +14 -21
  65. package/dist/channels/kit/context-buffer.js +25 -38
  66. package/dist/channels/kit/delivery.d.ts +35 -0
  67. package/dist/channels/kit/delivery.js +129 -0
  68. package/dist/channels/kit/event-stream.d.ts +5 -0
  69. package/dist/channels/kit/event-stream.js +29 -0
  70. package/dist/channels/kit/invoke-turn-kit.d.ts +53 -26
  71. package/dist/channels/kit/invoke-turn-kit.js +89 -32
  72. package/dist/channels/kit/preview-kit.d.ts +18 -72
  73. package/dist/channels/kit/preview-kit.js +22 -88
  74. package/dist/channels/kit/signature.d.ts +3 -9
  75. package/dist/channels/kit/signature.js +3 -9
  76. package/dist/channels/kit/state.d.ts +1 -2
  77. package/dist/channels/kit/state.js +5 -14
  78. package/dist/channels/kit/stop-command.d.ts +1 -2
  79. package/dist/channels/kit/stop-command.js +6 -9
  80. package/dist/channels/kit/tasks.d.ts +1 -1
  81. package/dist/channels/kit/tasks.js +8 -21
  82. package/dist/channels/kit/text.d.ts +2 -16
  83. package/dist/channels/kit/text.js +23 -31
  84. package/dist/channels/kit/thread-participants.d.ts +4 -17
  85. package/dist/channels/kit/thread-participants.js +8 -55
  86. package/dist/channels/kit/transport.d.ts +26 -0
  87. package/dist/channels/kit/transport.js +20 -0
  88. package/dist/channels/kit/turn-queue.d.ts +7 -11
  89. package/dist/channels/kit/turn-queue.js +21 -39
  90. package/dist/channels/kit/turn-runner.d.ts +32 -18
  91. package/dist/channels/kit/turn-runner.js +98 -53
  92. package/dist/channels/kit/turn-store.d.ts +32 -32
  93. package/dist/channels/kit/turn-store.js +45 -88
  94. package/dist/channels/lark/lark.d.ts +1 -5
  95. package/dist/channels/lark/onboard.d.ts +3 -12
  96. package/dist/channels/lark/onboard.js +3 -13
  97. package/dist/channels/lark/scaffold/channel.ts +27 -19
  98. package/dist/channels/lark/scaffold/channel.websocket.ts +31 -0
  99. package/dist/channels/registration.d.ts +9 -35
  100. package/dist/channels/registration.js +6 -37
  101. package/dist/channels/secret.js +2 -5
  102. package/dist/channels/serve.d.ts +47 -44
  103. package/dist/channels/serve.js +165 -101
  104. package/dist/channels/slack/config-api.d.ts +4 -27
  105. package/dist/channels/slack/config-api.js +5 -34
  106. package/dist/channels/slack/context-buffer.d.ts +2 -3
  107. package/dist/channels/slack/context-buffer.js +5 -5
  108. package/dist/channels/slack/invoke-turn.d.ts +3 -1
  109. package/dist/channels/slack/invoke-turn.js +25 -34
  110. package/dist/channels/slack/manifest.js +1 -3
  111. package/dist/channels/slack/model.d.ts +1 -2
  112. package/dist/channels/slack/model.js +1 -1
  113. package/dist/channels/slack/onboard.d.ts +4 -3
  114. package/dist/channels/slack/onboard.js +8 -11
  115. package/dist/channels/slack/onboarding-state.d.ts +3 -5
  116. package/dist/channels/slack/onboarding-state.js +9 -6
  117. package/dist/channels/slack/parse.d.ts +4 -13
  118. package/dist/channels/slack/parse.js +7 -28
  119. package/dist/channels/slack/preview.d.ts +12 -2
  120. package/dist/channels/slack/preview.js +292 -269
  121. package/dist/channels/slack/reaction.d.ts +11 -3
  122. package/dist/channels/slack/reaction.js +19 -8
  123. package/dist/channels/slack/register-webhook.js +4 -7
  124. package/dist/channels/slack/scaffold/channel.ts +20 -13
  125. package/dist/channels/slack/scaffold/slack-send.ts +2 -2
  126. package/dist/channels/slack/setup-server.d.ts +1 -5
  127. package/dist/channels/slack/setup-server.js +1 -5
  128. package/dist/channels/slack/shared-api.d.ts +1 -4
  129. package/dist/channels/slack/shared-api.js +2 -13
  130. package/dist/channels/slack/slack-api.d.ts +2 -1
  131. package/dist/channels/slack/slack-api.js +6 -4
  132. package/dist/channels/slack/slack.d.ts +11 -14
  133. package/dist/channels/slack/slack.js +121 -122
  134. package/dist/channels/sse.d.ts +1 -1
  135. package/dist/channels/sse.js +1 -1
  136. package/dist/channels/telegram/context-buffer.d.ts +7 -22
  137. package/dist/channels/telegram/context-buffer.js +6 -23
  138. package/dist/channels/telegram/invoke-turn.d.ts +7 -7
  139. package/dist/channels/telegram/invoke-turn.js +24 -43
  140. package/dist/channels/telegram/parse.d.ts +24 -51
  141. package/dist/channels/telegram/parse.js +32 -84
  142. package/dist/channels/telegram/preview.d.ts +10 -1
  143. package/dist/channels/telegram/preview.js +79 -100
  144. package/dist/channels/telegram/register-webhook.js +5 -23
  145. package/dist/channels/telegram/scaffold/channel.ts +25 -18
  146. package/dist/channels/telegram/scaffold/telegram-send.ts +6 -4
  147. package/dist/channels/telegram/telegram-api.d.ts +4 -3
  148. package/dist/channels/telegram/telegram-api.js +9 -7
  149. package/dist/channels/telegram/telegram.d.ts +4 -18
  150. package/dist/channels/telegram/telegram.js +38 -94
  151. package/dist/channels/telegram/turn-store.d.ts +11 -14
  152. package/dist/channels/telegram/turn-store.js +8 -6
  153. package/dist/channels/wait-health.d.ts +4 -6
  154. package/dist/channels/wait-health.js +10 -14
  155. package/dist/cli/add-feishu.d.ts +2 -12
  156. package/dist/cli/add-feishu.js +24 -71
  157. package/dist/cli/add-slack.d.ts +5 -3
  158. package/dist/cli/add-slack.js +53 -76
  159. package/dist/cli/auth-view.d.ts +2 -16
  160. package/dist/cli/auth-view.js +2 -16
  161. package/dist/cli/commands/add.js +25 -40
  162. package/dist/cli/commands/chat.d.ts +0 -1
  163. package/dist/cli/commands/chat.js +5 -6
  164. package/dist/cli/commands/deploy/agentcore.js +60 -65
  165. package/dist/cli/commands/deploy/docker.js +50 -23
  166. package/dist/cli/commands/deploy/fly.js +23 -61
  167. package/dist/cli/commands/deploy/railway.js +23 -18
  168. package/dist/cli/commands/deploy/shared.d.ts +38 -57
  169. package/dist/cli/commands/deploy/shared.js +40 -59
  170. package/dist/cli/commands/deploy.d.ts +10 -27
  171. package/dist/cli/commands/deploy.js +38 -60
  172. package/dist/cli/commands/destroy.d.ts +4 -0
  173. package/dist/cli/commands/destroy.js +56 -0
  174. package/dist/cli/commands/dev.d.ts +2 -1
  175. package/dist/cli/commands/dev.js +20 -23
  176. package/dist/cli/commands/info.d.ts +0 -2
  177. package/dist/cli/commands/info.js +83 -49
  178. package/dist/cli/commands/init.d.ts +1 -2
  179. package/dist/cli/commands/init.js +16 -55
  180. package/dist/cli/commands/invoke.d.ts +0 -1
  181. package/dist/cli/commands/invoke.js +5 -7
  182. package/dist/cli/commands/login.d.ts +2 -1
  183. package/dist/cli/commands/login.js +33 -38
  184. package/dist/cli/commands/logs.js +3 -4
  185. package/dist/cli/commands/models.js +1 -5
  186. package/dist/cli/commands/routine-run.d.ts +6 -0
  187. package/dist/cli/commands/routine-run.js +47 -0
  188. package/dist/cli/commands/routine.d.ts +25 -0
  189. package/dist/cli/commands/routine.js +122 -0
  190. package/dist/cli/commands/start.d.ts +31 -3
  191. package/dist/cli/commands/start.js +131 -81
  192. package/dist/cli/commands/tool.js +26 -12
  193. package/dist/cli/fail.d.ts +13 -23
  194. package/dist/cli/fail.js +20 -23
  195. package/dist/cli/invoke-stream.d.ts +1 -8
  196. package/dist/cli/kernel.d.ts +6 -38
  197. package/dist/cli/kernel.js +14 -77
  198. package/dist/cli/models-view.d.ts +1 -9
  199. package/dist/cli/models-view.js +11 -22
  200. package/dist/cli/program.d.ts +5 -6
  201. package/dist/cli/program.js +120 -157
  202. package/dist/cli/serve.d.ts +57 -41
  203. package/dist/cli/serve.js +94 -121
  204. package/dist/cli/shared.d.ts +15 -61
  205. package/dist/cli/shared.js +55 -181
  206. package/dist/cli.js +1 -8
  207. package/dist/collect.d.ts +6 -0
  208. package/dist/collect.js +6 -0
  209. package/dist/core.d.ts +4 -1
  210. package/dist/core.js +9 -7
  211. package/dist/declared-secrets.d.ts +55 -0
  212. package/dist/declared-secrets.js +88 -0
  213. package/dist/deploy/agentcore/aws-cli.d.ts +91 -0
  214. package/dist/deploy/agentcore/aws-cli.js +64 -0
  215. package/dist/deploy/agentcore/destroy.d.ts +51 -0
  216. package/dist/deploy/agentcore/destroy.js +273 -0
  217. package/dist/deploy/agentcore/forwarder.js +28 -79
  218. package/dist/deploy/agentcore/logs.d.ts +2 -18
  219. package/dist/deploy/agentcore/logs.js +27 -51
  220. package/dist/deploy/agentcore/plan.d.ts +85 -105
  221. package/dist/deploy/agentcore/plan.js +152 -314
  222. package/dist/deploy/agentcore/run.d.ts +28 -28
  223. package/dist/deploy/agentcore/run.js +227 -306
  224. package/dist/deploy/agentcore/zip.d.ts +2 -15
  225. package/dist/deploy/agentcore/zip.js +3 -17
  226. package/dist/deploy/build-context.d.ts +21 -0
  227. package/dist/deploy/build-context.js +137 -0
  228. package/dist/deploy/channel-ingress.d.ts +26 -39
  229. package/dist/deploy/channel-ingress.js +57 -28
  230. package/dist/deploy/container.d.ts +20 -34
  231. package/dist/deploy/container.js +49 -100
  232. package/dist/deploy/docker/plan.d.ts +12 -11
  233. package/dist/deploy/docker/plan.js +43 -24
  234. package/dist/deploy/docker/run.d.ts +22 -25
  235. package/dist/deploy/docker/run.js +39 -37
  236. package/dist/deploy/fly/plan.d.ts +15 -44
  237. package/dist/deploy/fly/plan.js +41 -73
  238. package/dist/deploy/fly/run.d.ts +16 -51
  239. package/dist/deploy/fly/run.js +42 -95
  240. package/dist/deploy/hosts.d.ts +24 -3
  241. package/dist/deploy/hosts.js +24 -3
  242. package/dist/deploy/preflight.d.ts +47 -41
  243. package/dist/deploy/preflight.js +282 -383
  244. package/dist/deploy/railway/plan.d.ts +16 -42
  245. package/dist/deploy/railway/plan.js +42 -60
  246. package/dist/deploy/railway/run.d.ts +30 -68
  247. package/dist/deploy/railway/run.js +86 -100
  248. package/dist/deploy/registration-gate.d.ts +6 -13
  249. package/dist/deploy/residency.d.ts +37 -0
  250. package/dist/deploy/residency.js +24 -0
  251. package/dist/deploy/runner.d.ts +10 -9
  252. package/dist/deploy/runner.js +7 -18
  253. package/dist/deploy/secrets.d.ts +40 -41
  254. package/dist/deploy/secrets.js +117 -103
  255. package/dist/deploy/workspace.d.ts +50 -0
  256. package/dist/deploy/workspace.js +197 -0
  257. package/dist/dev-supervisor.d.ts +1 -9
  258. package/dist/dev-supervisor.js +21 -64
  259. package/dist/effect-port.d.ts +50 -0
  260. package/dist/effect-port.js +77 -0
  261. package/dist/engines/pi/agent-session-factory.d.ts +50 -69
  262. package/dist/engines/pi/agent-session-factory.js +249 -146
  263. package/dist/engines/pi/auth.d.ts +15 -11
  264. package/dist/engines/pi/auth.js +96 -99
  265. package/dist/engines/pi/chat.d.ts +1 -5
  266. package/dist/engines/pi/chat.js +2 -14
  267. package/dist/engines/pi/config.d.ts +53 -51
  268. package/dist/engines/pi/config.js +83 -92
  269. package/dist/engines/pi/create.d.ts +60 -75
  270. package/dist/engines/pi/create.js +108 -141
  271. package/dist/engines/pi/definition.d.ts +14 -58
  272. package/dist/engines/pi/definition.js +21 -85
  273. package/dist/engines/pi/invoke-session.d.ts +5 -25
  274. package/dist/engines/pi/invoke-session.js +209 -244
  275. package/dist/engines/pi/login.d.ts +95 -35
  276. package/dist/engines/pi/login.js +259 -107
  277. package/dist/engines/pi/machine.d.ts +31 -0
  278. package/dist/engines/pi/machine.js +106 -0
  279. package/dist/engines/pi/models.d.ts +70 -89
  280. package/dist/engines/pi/models.js +188 -81
  281. package/dist/engines/pi/open.d.ts +65 -53
  282. package/dist/engines/pi/open.js +129 -69
  283. package/dist/engines/pi/report.d.ts +3 -12
  284. package/dist/engines/pi/report.js +2 -16
  285. package/dist/engines/pi/search-tools.d.ts +1 -9
  286. package/dist/engines/pi/search-tools.js +26 -57
  287. package/dist/engines/pi/service.d.ts +2 -16
  288. package/dist/engines/pi/service.js +2 -16
  289. package/dist/engines/pi/session-builder.d.ts +5 -9
  290. package/dist/engines/pi/session-builder.js +44 -82
  291. package/dist/engines/pi/session-control.js +286 -269
  292. package/dist/engines/pi/session-effects.d.ts +14 -0
  293. package/dist/engines/pi/session-effects.js +30 -0
  294. package/dist/engines/pi/session-inheritance.d.ts +9 -18
  295. package/dist/engines/pi/session-inheritance.js +103 -160
  296. package/dist/engines/pi/session-markers.d.ts +31 -30
  297. package/dist/engines/pi/session-markers.js +26 -25
  298. package/dist/engines/pi/session-settings.d.ts +6 -22
  299. package/dist/engines/pi/session-settings.js +10 -21
  300. package/dist/engines/pi/session-store.d.ts +26 -92
  301. package/dist/engines/pi/session-store.js +96 -310
  302. package/dist/engines/pi/tool-context.d.ts +17 -45
  303. package/dist/engines/pi/tool-context.js +7 -26
  304. package/dist/engines/pi/tool.d.ts +45 -36
  305. package/dist/engines/pi/tool.js +43 -57
  306. package/dist/engines/pi/turn-kit.d.ts +14 -52
  307. package/dist/engines/pi/turn-kit.js +18 -67
  308. package/dist/engines/pi/wake-tool.d.ts +2 -10
  309. package/dist/engines/pi/wake-tool.js +7 -27
  310. package/dist/env.d.ts +27 -28
  311. package/dist/env.js +45 -50
  312. package/dist/index.js +0 -2
  313. package/dist/lark.d.ts +1 -2
  314. package/dist/lark.js +1 -2
  315. package/dist/loader.d.ts +14 -55
  316. package/dist/loader.js +24 -43
  317. package/dist/log.d.ts +2 -12
  318. package/dist/log.js +3 -24
  319. package/dist/node.d.ts +2 -15
  320. package/dist/node.js +2 -18
  321. package/dist/observe.d.ts +2 -8
  322. package/dist/open-url.d.ts +1 -1
  323. package/dist/open-url.js +1 -1
  324. package/dist/paths.d.ts +70 -134
  325. package/dist/paths.js +165 -232
  326. package/dist/pi.d.ts +4 -6
  327. package/dist/pi.js +3 -3
  328. package/dist/proxy.d.ts +16 -6
  329. package/dist/proxy.js +52 -16
  330. package/dist/runtime.d.ts +18 -12
  331. package/dist/runtime.js +18 -11
  332. package/dist/scaffold/add-channel.d.ts +14 -31
  333. package/dist/scaffold/add-channel.js +48 -112
  334. package/dist/scaffold/init.d.ts +9 -31
  335. package/dist/scaffold/init.js +45 -138
  336. package/dist/scaffold/templates/env.example +6 -4
  337. package/dist/scaffold/templates/fastagent.config.ts +36 -0
  338. package/dist/scaffold/templates.d.ts +3 -3
  339. package/dist/scaffold/templates.js +5 -8
  340. package/dist/scaffold/vendor-skill.d.ts +2 -5
  341. package/dist/scaffold/vendor-skill.js +19 -29
  342. package/dist/schedule/cron.d.ts +9 -5
  343. package/dist/schedule/cron.js +9 -11
  344. package/dist/schedule/discover.d.ts +12 -12
  345. package/dist/schedule/discover.js +43 -34
  346. package/dist/schedule/routine.d.ts +43 -0
  347. package/dist/schedule/routine.js +32 -0
  348. package/dist/schedule/run.d.ts +55 -0
  349. package/dist/schedule/run.js +146 -0
  350. package/dist/schedule/scheduler.d.ts +44 -55
  351. package/dist/schedule/scheduler.js +291 -265
  352. package/dist/schedule/state.d.ts +105 -10
  353. package/dist/schedule/state.js +293 -19
  354. package/dist/schedule/wake-alarm.d.ts +10 -23
  355. package/dist/schedule/wake-alarm.js +91 -121
  356. package/dist/schedule/wakeups.d.ts +23 -39
  357. package/dist/schedule/wakeups.js +33 -75
  358. package/dist/secrets-gate.d.ts +32 -0
  359. package/dist/secrets-gate.js +33 -0
  360. package/dist/service.d.ts +137 -98
  361. package/dist/service.js +250 -252
  362. package/dist/session-remote.d.ts +33 -44
  363. package/dist/session-remote.js +203 -192
  364. package/dist/session.d.ts +153 -228
  365. package/dist/session.js +33 -55
  366. package/dist/tunnel.d.ts +8 -36
  367. package/dist/tunnel.js +24 -65
  368. package/dist/version.d.ts +2 -2
  369. package/dist/version.js +2 -2
  370. package/package.json +10 -16
  371. package/dist/channels/agentcore-state.d.ts +0 -77
  372. package/dist/channels/agentcore-state.js +0 -276
  373. package/dist/channels/github/github.d.ts +0 -31
  374. package/dist/channels/github/github.js +0 -89
  375. package/dist/channels/github/scaffold/channel.ts +0 -25
  376. package/dist/cli/commands/attach.d.ts +0 -108
  377. package/dist/cli/commands/attach.js +0 -637
  378. package/dist/cli/commands/fire.d.ts +0 -7
  379. package/dist/cli/commands/fire.js +0 -38
  380. package/dist/cli/commands/schedule.d.ts +0 -12
  381. package/dist/cli/commands/schedule.js +0 -87
  382. package/dist/github.d.ts +0 -3
  383. package/dist/github.js +0 -2
  384. package/dist/scaffold/templates/fastagent.config.mjs +0 -23
  385. package/dist/schedule/audit.d.ts +0 -18
  386. package/dist/schedule/audit.js +0 -57
  387. package/dist/schedule/schedule.d.ts +0 -35
  388. package/dist/schedule/schedule.js +0 -23
@@ -1,43 +1,24 @@
1
- /**
2
- * `fastagent deploy railway` — the Railway deploy PLAN, computed from the resolved definition. Pure:
3
- * facts in, artifact contents + an ordered runbook out; the CLI writes the files and prints the runbook.
4
- *
5
- * Railway is the second target, and it is NOT a copy of Fly — three asymmetries drive this module:
6
- *
7
- * 1. The config file is thin. `railway.json` (config-as-code) holds ONLY build/deploy settings; the
8
- * volume, the variables (state root + secrets), and App Sleeping are Railway service settings applied
9
- * by CLI/dashboard, not the file. So Fly's "one committed file is the single source" does not carry:
10
- * Railway's source of truth is the linked project's platform state, not a file we generate.
11
- *
12
- * 2. Scale-to-zero is not scriptable. Railway's App Sleeping is a dashboard-only toggle (no CLI/API),
13
- * so unlike Fly's `auto_stop_machines`, we cannot generate it — the runbook states the manual step.
14
- * This is a real capability downgrade vs Fly, named rather than hidden.
15
- *
16
- * 3. The public URL is minted, not deterministic. Fly gives `<app>.fly.dev` up front; Railway mints a
17
- * `*.up.railway.app` domain that must be read back (`railway domain`), so the webhook step points at
18
- * "the domain from `railway domain`" rather than a precomputed URL.
19
- *
20
- * What IS shared with Fly comes from the neutral modules: the container (Dockerfile + .dockerignore) and
21
- * the required-secret list. `railway.json`'s `healthcheckPath=/health` also fixes the "routed before the
22
- * server is listening" boot race Fly's deploy hit — Railway only routes once /health passes.
23
- */
1
+ /** `fastagent deploy railway` — the Railway deploy PLAN, computed from the resolved definition. */
24
2
  import type { DeclaredChannel } from "../../channels/discover.ts";
25
3
  import { type Artifact, type ContainerInput } from "../container.ts";
4
+ import { type DeploymentSecret } from "../secrets.ts";
26
5
  export interface RailwayPlanInput extends ContainerInput {
27
- /** The service name to create (`railway add --service`). Railway service names are project-scoped, not
28
- * globally unique (unlike a Fly app), so the CLI derives it from the dir basename — any value works. */
6
+ /** The service name to create (`railway add --service`). */
29
7
  serviceName: string;
30
8
  /** What satisfies model auth locally: an env-var name, an OAuth/stored label, or undefined. */
31
9
  modelAuth: string | undefined;
32
- /** Every declared channel and its ingress — the source of the secret list, the webhook steps, and
33
- * whether App Sleeping must stay off for an outbound connection. */
10
+ /**
11
+ * Every declared channel and its ingress — the source of the secret list, the webhook steps, and whether App
12
+ * Sleeping must stay off for an outbound connection.
13
+ */
34
14
  channels: readonly DeclaredChannel[];
35
- /** Extra secret env-var names (fastagent.config deploy.secrets) — added to the runbook's secret list. */
36
- extraSecrets?: string[];
37
- /** Time triggers present (schedules/ or selfSchedule) — the runbook forbids App Sleeping: cron/wake has
38
- * no external wake-up, so a sleeping service sleeps through them. Required (like FlyPlanInput's) so a
39
- * caller can't silently omit it and degrade the sleeping guidance to "optional". */
40
- hasTimeTriggers: boolean;
15
+ /**
16
+ * The runbook's variable list (`deploymentSecrets`): what must have a value, then everything else the value file
17
+ * carries.
18
+ */
19
+ secrets?: readonly DeploymentSecret[];
20
+ /** `routines/` declares a cron — one of the things that forbids App Sleeping (deploy/residency.ts). */
21
+ hasCron: boolean;
41
22
  }
42
23
  export interface RailwayPlan {
43
24
  /** railway.json / Dockerfile / .dockerignore — written by the CLI (skipped if present unless --force). */
@@ -45,17 +26,10 @@ export interface RailwayPlan {
45
26
  /** The ordered, values-resolved deploy runbook — printed to stdout for the coding agent to execute. */
46
27
  runbook: string[];
47
28
  }
48
- /** The `RAILWAY_DOCKERFILE_PATH` value for an agent under `prefix` — repo-root-anchored with a leading
49
- * slash, the form Railway's builds/dockerfiles docs use for a Dockerfile in another directory. The
50
- * config file's `dockerfilePath` spells it WITHOUT the slash (the config-as-code schema's own
51
- * convention); two mechanisms, two documented spellings, one fact each. */
29
+ /** The `RAILWAY_DOCKERFILE_PATH` value for an agent under `prefix`. */
52
30
  export declare const dockerfilePathVar: (prefix: string) => string;
53
- /** The name this tool gives BOTH the project and the service, derived from the workspace directory.
54
- * Railway names are project-scoped (not globally unique like a Fly app), so this only has to survive
55
- * the command — slug anything that would break `railway add --service <name>`, and name the fallback
56
- * rather than emitting an empty argument. Shared so the live probe tears down what the CLI creates. */
31
+ /** The name this tool gives BOTH the project and the service, derived from the workspace directory. */
57
32
  export declare function toRailwayName(basename: string): string;
58
- /** Did fastagent generate this `railway.json`? Unparseable or unmarked reads as the author's. */
59
33
  export declare function isGeneratedRailwayJson(content: string): boolean;
60
34
  /** Compute the Railway deploy plan from the resolved definition. */
61
35
  export declare function planRailwayDeploy(input: RailwayPlanInput): RailwayPlan;
@@ -1,25 +1,18 @@
1
1
  import { webhookRunbook } from "../channel-ingress.js";
2
2
  import { containerArtifacts } from "../container.js";
3
- import { deploymentSecrets, isEnvKey } from "../secrets.js";
4
- /** State root = the volume mount path, kept in lockstep. `/data` matches the Fly recipe. */
3
+ import { CRON_CAN_BE_EXTERNAL, WAKEUPS_WHEN_ASLEEP, residencyFor } from "../residency.js";
4
+ import { isEnvKey } from "../secrets.js";
5
+ /** State root = the volume mount path, kept in lockstep. */
5
6
  const MOUNT = "/data";
6
- /** The `RAILWAY_DOCKERFILE_PATH` value for an agent under `prefix` — repo-root-anchored with a leading
7
- * slash, the form Railway's builds/dockerfiles docs use for a Dockerfile in another directory. The
8
- * config file's `dockerfilePath` spells it WITHOUT the slash (the config-as-code schema's own
9
- * convention); two mechanisms, two documented spellings, one fact each. */
7
+ /** The `RAILWAY_DOCKERFILE_PATH` value for an agent under `prefix`. */
10
8
  export const dockerfilePathVar = (prefix) => `/${prefix}Dockerfile`;
11
- /** The name this tool gives BOTH the project and the service, derived from the workspace directory.
12
- * Railway names are project-scoped (not globally unique like a Fly app), so this only has to survive
13
- * the command — slug anything that would break `railway add --service <name>`, and name the fallback
14
- * rather than emitting an empty argument. Shared so the live probe tears down what the CLI creates. */
9
+ /** The name this tool gives BOTH the project and the service, derived from the workspace directory. */
15
10
  export function toRailwayName(basename) {
16
11
  return basename.replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
17
12
  }
18
- /** railway.json is JSON, so its ownership marker is a KEY rather than a comment line. Railway ignores
19
- * unknown keys; the predicate below is what lets `--force` reset OUR file and keep a hand-written one. */
13
+ /** railway.json is JSON, so its ownership marker is a KEY rather than a comment line. */
20
14
  const GENERATED_RAILWAY_KEY = "x-generated-by";
21
15
  const GENERATED_RAILWAY_VALUE = "fastagent deploy railway";
22
- /** Did fastagent generate this `railway.json`? Unparseable or unmarked reads as the author's. */
23
16
  export function isGeneratedRailwayJson(content) {
24
17
  try {
25
18
  return JSON.parse(content)[GENERATED_RAILWAY_KEY] === GENERATED_RAILWAY_VALUE;
@@ -28,8 +21,7 @@ export function isGeneratedRailwayJson(content) {
28
21
  return false;
29
22
  }
30
23
  }
31
- /** railway.json — build/deploy only (Railway's config-as-code scope). No env/volume/sleeping here: those
32
- * are service settings the runbook applies via CLI. healthcheckPath gates routing on a live server. */
24
+ /** railway.json — build/deploy only (Railway's config-as-code scope). */
33
25
  function railwayJson(prefix) {
34
26
  return `${JSON.stringify({
35
27
  $schema: "https://railway.com/railway.schema.json",
@@ -42,31 +34,22 @@ function railwayJson(prefix) {
42
34
  /** Compute the Railway deploy plan from the resolved definition. */
43
35
  export function planRailwayDeploy(input) {
44
36
  const { serviceName, modelAuth, channels } = input;
45
- // railway.json is namespaced under the agent dir too (the workspace may carry its own
46
- // railway.toml/json for the product). Railway reads config-as-code from the repo root by default and
47
- // pointing it at a custom path is DASHBOARD-ONLY — so the BUILD entry travels as the scriptable
48
- // RAILWAY_DOCKERFILE_PATH service variable instead (Railway's documented non-root-Dockerfile route),
49
- // and the config-as-code pointer degrades to an OPTIONAL enhancement: the /health gate (Railway's
50
- // default restart policy already matches the file's ON_FAILURE).
37
+ // railway.json is namespaced under the agent dir too (the workspace may carry its own railway.toml/json for the
38
+ // product).
51
39
  const configPath = `${input.agentPrefix}railway.json`;
52
40
  const artifacts = [
53
41
  { path: configPath, content: railwayJson(input.agentPrefix) },
54
42
  ...containerArtifacts(input),
55
43
  ];
56
- const secrets = deploymentSecrets(modelAuth, channels, input.extraSecrets);
57
- const requiredSecrets = secrets.filter((secret) => secret.required);
58
- const optionalSecrets = secrets.filter((secret) => !secret.required);
59
- // Order matters, not cosmetics: `railway init` creates a PROJECT with no service, but the volume and
60
- // variables are service-scoped and `railway up` deploys THE service — so the service must exist first
61
- // (`railway add --service`), and variables must be set BEFORE the first `up` or the box boots without a
62
- // model key / FASTAGENT_STATE_DIR and crash-loops against restartPolicy ON_FAILURE + the healthcheck.
44
+ const secrets = input.secrets ?? [];
45
+ // Order matters, not cosmetics: `railway init` creates a PROJECT with no service, but the volume and variables are
46
+ // service-scoped and `railway up` deploys THE service.
63
47
  const runbook = [
64
48
  `# Deploy to Railway. ${configPath} / Dockerfile(.dockerignore) are generated above.`,
65
49
  `# Prereqs: the Railway CLI (https://docs.railway.com/guides/cli) and \`railway login\`.`,
66
50
  ``,
67
- `# One-time setup (init → service → volume → variables). SKIP all of it on a redeploy — a redeploy is`,
68
- `# just \`railway up\` (below). Re-running these makes a second project, a DUPLICATE service (Railway`,
69
- `# service names are project-scoped, NOT unique — no error), and another volume, splitting state.`,
51
+ `# One-time setup (init → service → volume → variables). Skip it on redeploy: repeating it creates`,
52
+ `# another project/service/volume, splitting the persistent workspace.`,
70
53
  ``,
71
54
  `# Create + link a project (writes .railway link state in this dir; the project — not a committed`,
72
55
  `# file — is Railway's source of truth for identity, variables, and the volume).`,
@@ -85,44 +68,43 @@ export function planRailwayDeploy(input) {
85
68
  `# Railway's documented route to a non-root Dockerfile (no dashboard step needed for the build).`,
86
69
  `railway variables set FASTAGENT_STATE_DIR=${MOUNT}/.state FASTAGENT_SECRETS_DIR=${MOUNT}/.secrets RAILWAY_DOCKERFILE_PATH=${dockerfilePathVar(input.agentPrefix)}`,
87
70
  ];
88
- if (requiredSecrets.length > 0) {
89
- runbook.push(`# Required secrets:`, `# ${requiredSecrets.map((s) => `${s.name}: ${s.hint}`).join("\n# ")}`, `railway variables set ${requiredSecrets.map((s) => `${s.name}=<value>`).join(" ")}`);
71
+ if (secrets.length > 0) {
72
+ runbook.push(`# Secrets:`, `# ${secrets.map((s) => `${s.name}: ${s.hint}`).join("\n# ")}`, `railway variables set ${secrets.map((s) => `${s.name}=<value>`).join(" ")}`);
90
73
  }
91
- if (optionalSecrets.length > 0) {
92
- runbook.push(`# Optional secrets — set only when the matching feature is configured:`, `# ${optionalSecrets.map((s) => `${s.name}: ${s.hint}`).join("\n# ")}`, `# railway variables set ${optionalSecrets.map((s) => `${s.name}=<value>`).join(" ")}`);
93
- }
94
- // Model-auth guidance: an env key becomes a variable above. Otherwise the plan can't read the local
95
- // credential's value (OAuth or a stored key) to set it — same wording discipline as the Fly plan.
74
+ // Model-auth guidance: an env key becomes a variable above.
96
75
  if (!isEnvKey(modelAuth)) {
97
76
  runbook.push(modelAuth === undefined
98
- ? `# Model auth: none found at the local auth path — a global \`fastagent login\` isn't read here; pass --auth-path <file> (e.g. ~/.fastagent/.secrets/auth.json), or \`--run\` carries it automatically.`
77
+ ? `# Model auth: none found at the local auth path — a global \`fastagent login\` isn't read here; set FASTAGENT_AUTH_PATH (e.g. ~/.fastagent/.secrets/auth.json), or \`--run\` carries it automatically.`
99
78
  : `# Model auth: your local auth is "${modelAuth}" — the plan can't read its value to set as a variable.`, `# Set your provider API key as a variable (railway variables set KEY=...), OR place auth.json on the ${MOUNT} volume.`);
100
79
  }
101
80
  runbook.push(``, `# OPTIONAL — the build already uses the agent's Dockerfile via RAILWAY_DOCKERFILE_PATH (set above),`, `# and Railway's default restart policy equals what ${configPath} declares (ON_FAILURE).`, `# Pointing the service at ${configPath} (Service → Settings → Config-as-code — dashboard-only) adds`, `# the /health healthcheck gate: a boot-crashing deploy is marked FAILED instead of going live dead.`, `# (Zero-downtime switching doesn't apply either way — the ${MOUNT} volume allows one active deployment.)`);
102
- runbook.push(``, `# Deploy — uploads this dir and builds the Dockerfile on Railway (no local Docker needed). This is`, `# also the ENTIRE redeploy: re-run \`railway up\` alone (the one-time setup above is not repeated).`, `railway up`);
103
- if (input.shipsGit) {
104
- runbook.push(``, `# The image is a WYSIWYG snapshot of this directory. Freshness/durability run through git, driven`, `# by the agent itself (pull to freshen, commit/push to write back; creds ride config.deploy.secrets;`, `# git is baked into the image). CAVEAT — \`railway up\` is known to strip .git from its upload:`, `# expect NO baked history on the box; the agent should \`git clone\` its repo in the workspace`, `# (same token) before making changes.`, `# Un-pushed changes on the box never survive a redeploy; durability lives in git.`);
105
- }
106
- else {
107
- runbook.push(``, `# The image is a WYSIWYG snapshot of this directory. No .git here, so no history ships and the`, `# generated image does not install git — changes on the box are ephemeral and never survive a`, `# redeploy. If the agent should clone/push repos as part of its work, add deploy: { apt: ["git"] }.`);
108
- }
109
- // The public URL is minted, not deterministic (unlike Fly's <app>.fly.dev) — ONE mint step, then each
110
- // channel's webhook uses that domain (mint once even when both channels are present).
111
- // Mint only when something below needs it: with nothing to point at the domain (no channels, or only
112
- // long-connection ones), "use it in the step(s) below" would refer to steps that do not follow.
81
+ runbook.push(``, `# Before a new definition release, run \`fastagent deploy railway\` to refresh the release manifest.`, `# Upload this workspace and build on Railway (no local Docker needed):`, `railway up`);
82
+ runbook.push(``, `# The volume keeps /data/base (including uncommitted work), .state and .secrets across restarts and deploys.`, `# Each generated release replaces only /data/base/${input.agentPrefix}; other workspace files are initialized once.`, input.shipsGit
83
+ ? `# Railway uploads may strip .git. Clone inside the persistent workspace when collaboration needs history.`
84
+ : `# To use Git for collaboration, add deploy: { apt: ["git"] }. Storage durability does not require Git.`);
85
+ // The public URL is minted, not deterministic (unlike Fly's <app>.fly.dev).
113
86
  const steps = webhookRunbook(`https://<your-domain>`, channels);
114
87
  if (steps.length > 0) {
115
88
  runbook.push(``, `# Public URL — Railway mints a *.up.railway.app domain (NOT deterministic). Generate it, then read`, `# the printed https URL and use it as <your-domain> in the webhook step(s) below:`, `railway domain`, ...steps);
116
89
  }
117
- // Scale-to-zero: App Sleeping is dashboard-only (no CLI/API) — a manual step, not a generated setting.
118
- // A github channel should NOT enable it: fire-and-forget reviews have no replay (unlike Telegram's L1
119
- // turn store), so a sleep mid-review would drop it — the same floor the Fly plan enforces via config.
120
- runbook.push(``, channels.some((channel) => channel.name === "github")
121
- ? `# Scale-to-zero: do NOT enable App Sleeping — github turns have no replay, a sleep mid-review is lost.`
122
- : input.hasTimeTriggers
123
- ? `# Scale-to-zero: do NOT enable App Sleeping — schedules/wake-ups have no external wake-up; a sleeping service sleeps through them.`
124
- : channels.some((channel) => channel.ingress === "long-connection")
125
- ? `# Scale-to-zero: do NOT enable App Sleeping — a long-connection channel must remain connected.`
126
- : `# Scale-to-zero (optional, dashboard-only — no CLI/API): Settings → Deploy → Serverless → App Sleeping.`, `# Keep this a SINGLE service: the ${MOUNT} volume is tied to one service; extra replicas split state.`);
90
+ // Scale-to-zero: App Sleeping is dashboard-only (no CLI/API) — a manual step, not a generated setting. WHY it is
91
+ // forbidden is residency.ts's to decide; the SETTING and the path through the dashboard are Railway's.
92
+ const residency = residencyFor({ channels, hasCron: input.hasCron });
93
+ runbook.push(``, residency
94
+ ? `# Scale-to-zero: do NOT enable App Sleeping — ${residency.why}.`
95
+ : `# Scale-to-zero (optional, dashboard-only — no CLI/API): Settings → Deploy → Serverless → App Sleeping —\n# ${WAKEUPS_WHEN_ASLEEP}.`, ...(residency?.reason === CRON_CAN_BE_EXTERNAL
96
+ ? [
97
+ `# To sleep anyway: keep the time in a Railway CRON SERVICE (Settings -> Cron Schedule, >= 5 min) that`,
98
+ `# calls this service's \`POST /run\` over the private network — traffic from another service in the`,
99
+ `# project wakes a slept one. A cron service must EXIT, so it cannot be this service.`,
100
+ `# set a variable on the cron service and curl it (Railway resolves the reference at deploy):`,
101
+ `# AGENT_RUN=http://${serviceName}.railway.internal:\${{${serviceName}.PORT}}/run`,
102
+ `# curl --retry 3 -fsS -X POST "$AGENT_RUN" -H 'content-type: application/json' -d '{"name":"<routine>"}'`,
103
+ `# --retry because the FIRST request to a slept service may answer 502 (Railway documents it). The`,
104
+ `# route has no dedup, so decide for yourself whether a retry that may duplicate work is what you want.`,
105
+ `# \`POST /run\` is an API, not a clock: read its contract — docs/api-reference.md#post-run.`,
106
+ `# Asleep, ${WAKEUPS_WHEN_ASLEEP}.`,
107
+ ]
108
+ : []), `# Keep this a SINGLE service: the ${MOUNT} volume is tied to one service; extra replicas split state.`);
127
109
  return { artifacts, runbook };
128
110
  }
@@ -1,59 +1,34 @@
1
- /**
2
- * `fastagent deploy railway --run` — drive the Railway CLI to completion. The middle of the deploy the
3
- * plain runbook hands to the operator; `--run` executes it so a coding agent runs ONE command.
4
- *
5
- * Railway's model forces differences from the Fly runner (fly/run.ts), all validated against CLI 5.15.0:
6
- *
7
- * - **`--run` PROVISIONS a project and only runs on an UNLINKED directory** — so it can never deploy
8
- * into a project it didn't create. `railway init` isn't check-then-act (it ALWAYS makes a new project)
9
- * and `railway status` exits 0 even when unlinked (linkedness is read from stdout: JSON when linked,
10
- * empty when not). We do NOT track ownership: a pre-existing link is refused (Railway has no globally
11
- * unique name to give free identity like Fly's app name, and synthesizing one — a machine-local marker
12
- * — was a large, bug-prone premature optimization). The only "yes, this project" signal is the operator's
13
- * explicit `--into-linked`, which provisions INTO the linked project; a routine redeploy is just
14
- * `railway up`. The volume is check-then-act, so `--into-linked` (or a create that failed at volume-add) still gets it.
15
- * - **Every command needs `--service` explicitly** to stay non-interactive (a bare command prompts to
16
- * pick a service). `railway volume add` is the exception — it has NO `--service` flag and rides the
17
- * linked service, so the service must be created (and thus linked) first.
18
- * - **The public URL is minted, not deterministic** — bare `railway domain --json` returns the service
19
- * domain (minting one if absent), read for the webhook. We avoid the newer `domain list` subcommand:
20
- * on a CLI without it, `railway domain list` registers a bogus custom domain named "list" (destructive).
21
- *
22
- * Secrets go in one-per-`variable set --stdin` (value on stdin, never argv/process listing — Railway has
23
- * no bulk stdin import like Fly's `secrets import`). Auth needs an ACCOUNT credential (login or
24
- * `RAILWAY_API_TOKEN`), not the project-scoped `RAILWAY_TOKEN`: `init` creates a project that a project
25
- * token can't predate.
26
- */
27
- import { type Registrars } from "../channel-ingress.ts";
1
+ /** `fastagent deploy railway --run` — drive the Railway CLI to completion. */
2
+ import { type PublicHealthProbe, type Registrars } from "../channel-ingress.ts";
28
3
  import type { DeclaredChannel } from "../../channels/discover.ts";
29
4
  import type { CliRunner } from "../runner.ts";
30
5
  export interface RailwayRunPlan {
31
- /** Names both the project (`railway init --name`) and the service (`railway add --service`). Railway
32
- * names are project-scoped, not globally unique — the CLI derives it from the dir basename. */
6
+ /** Names both the project (`railway init --name`) and the service (`railway add --service`). */
33
7
  name: string;
34
- /** The volume mount path; `FASTAGENT_STATE_DIR`/`FASTAGENT_SECRETS_DIR` are set to `.state`/`.secrets`
35
- * under it (kept in lockstep). `/data`, matching the Fly recipe. */
8
+ /**
9
+ * The volume mount path; `FASTAGENT_STATE_DIR`/`FASTAGENT_SECRETS_DIR` are set to `.state`/`.secrets` under it (kept
10
+ * in lockstep).
11
+ */
36
12
  mountPath: string;
37
- /** `KEY=value` secrets set one-per-`variable set --stdin`: model key (env auth) or `FASTAGENT_AUTH_SEED`
38
- * (file auth) + channel secrets. Never on argv. */
13
+ /**
14
+ * `KEY=value` secrets set one-per-`variable set --stdin`: the value file's variables + `FASTAGENT_AUTH_SEED` for a
15
+ * file credential.
16
+ */
39
17
  secrets: Record<string, string>;
40
- /** Required secret names with NO local value — the run gates on these before any side effect. */
18
+ /** Declared names the value file supplies no value for — the run gates on these before any side effect. */
41
19
  missingSecrets: string[];
20
+ /** That value file, workspace-relative, so the gate names the file this deploy actually read. */
21
+ valueFile: string;
42
22
  /** Every declared channel and its ingress — the driver asks which of them have a webhook. */
43
23
  channels: readonly DeclaredChannel[];
44
- /** Opt-in (CLI `--into-linked`) to provision INTO the project this directory is already linked to. Off
45
- * by default so `--run` only creates on an unlinked dir and never deploys into a pre-existing (possibly
46
- * unrelated/production) project; the flag is the operator's explicit "yes, this project". */
24
+ /** Opt-in (CLI `--into-linked`) to provision INTO the project this directory is already linked to. */
47
25
  intoLinked: boolean;
48
- /** `RAILWAY_DOCKERFILE_PATH` value (`/fastagent/Dockerfile`) — Railway's service-variable route to a
49
- * non-root Dockerfile (builds/dockerfiles docs), set with the machinery variables BEFORE the first
50
- * `up` so the build never falls back to auto-detecting the workspace root. The config-as-code file
51
- * also carries the path, but pointing Railway at `fastagent/railway.json` is dashboard-only — the
52
- * variable is the scriptable way. */
26
+ /** `RAILWAY_DOCKERFILE_PATH` value (`/fastagent/Dockerfile`). */
53
27
  dockerfilePath: string;
54
28
  }
55
- /** Done (with the live URL), or a gate the operator must clear before re-running (printed + non-zero
56
- * exit by the CLI). */
29
+ /**
30
+ * Done (with the live URL), or a gate the operator must clear before re-running (printed + non-zero exit by the CLI).
31
+ */
57
32
  export type RailwayRunOutcome = {
58
33
  ok: true;
59
34
  url: string;
@@ -61,33 +36,20 @@ export type RailwayRunOutcome = {
61
36
  ok: false;
62
37
  gate: string;
63
38
  };
64
- /**
65
- * Whether `railway status --json` shows a linked project: non-empty stdout. Unlinked prints its message
66
- * to stderr and leaves stdout EMPTY (the exit code is 0 either way, so it can't be the signal). ANY
67
- * non-empty output — parseable or not — counts as linked, so an unreadable shape is refused, never
68
- * mistaken for unlinked (which would `init` a duplicate). Verified against CLI 5.15.0.
69
- */
39
+ /** Whether `railway status --json` shows a linked project: non-empty stdout. */
70
40
  export declare function isLinked(stdout: string): boolean;
71
- /** The linked project's name for the gate message, or undefined if it can't be read (still linked —
72
- * `railway status --json` puts `name` at the top level on 5.15.0). */
73
- export declare function linkedName(stdout: string): string | undefined;
74
41
  /**
75
- * The first Railway-provided domain as an https URL, or undefined if none is present — reads `railway
76
- * domain --json` without assuming exact field names: any string value carrying a `*.railway.app` host
77
- * wins (unanchored, so a scheme/port/path around it still yields the bare host). Undefined → the CLI
78
- * gates (register manually).
42
+ * The linked project's name for the gate message, or undefined if it can't be read (still linked — `railway status
43
+ * --json` puts `name` at the top level on 5.15.0).
79
44
  */
45
+ export declare function linkedName(stdout: string): string | undefined;
46
+ /** The first Railway-provided domain as an https URL, or undefined if none is present. */
80
47
  export declare function parseDomainUrl(stdout: string): string | undefined;
81
48
  /**
82
- * Whether `railway volume list --json` shows a volume at `mountPath` — shape-agnostic, like
83
- * {@link parseDomainUrl}. Drives check-then-act so a half-provisioned project (service created, volume
84
- * add failed) self-heals on re-run instead of silently deploying with no volume.
85
- */
86
- export declare function parseHasVolume(stdout: string, mountPath: string): boolean;
87
- /**
88
- * Run the deploy through `railway`. `log` reports progress; the injected {@link Registrars} perform
89
- * the post-deploy webhook steps from the builder machine (Slack's control credential never travels to
90
- * the host). A registrar the caller did not wire becomes the printed manual step. Every gate is
91
- * fail-visible.
49
+ * The status of the volume `railway volume list --json` shows mounted at `mountPath` ON `service`, or undefined when
50
+ * that service has none there. The list is the whole PROJECT's: another service's volume, or one a deleted service
51
+ * left behind (`serviceName: null` — deleting a service keeps its volume), sits at the same path and is not this
52
+ * one. Read from any object carrying `mountPath` and `serviceName`, so a wrapper key moving does not matter.
92
53
  */
93
- export declare function deployRailwayRun(plan: RailwayRunPlan, railway: CliRunner, log: (msg: string) => void, registrars: Registrars): Promise<RailwayRunOutcome>;
54
+ export declare function volumeOn(stdout: string, service: string, mountPath: string): string | undefined;
55
+ export declare function deployRailwayRun(plan: RailwayRunPlan, railway: CliRunner, log: (msg: string) => void, registrars: Registrars, healthProbe?: PublicHealthProbe, sleep?: (ms: number) => Promise<void>): Promise<RailwayRunOutcome>;