@fastagent-sh/fastagent 0.24.3 → 0.25.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 (480) hide show
  1. package/README.md +53 -82
  2. package/dist/agent-api.d.ts +452 -0
  3. package/dist/agent-api.js +201 -0
  4. package/dist/answer-text.d.ts +8 -0
  5. package/dist/answer-text.js +18 -0
  6. package/dist/atomic-write.d.ts +2 -2
  7. package/dist/atomic-write.js +2 -2
  8. package/dist/authoring.d.ts +77 -0
  9. package/dist/authoring.js +238 -0
  10. package/dist/channel.d.ts +29 -15
  11. package/dist/channel.js +4 -1
  12. package/dist/channels/agentcore-protocol.d.ts +36 -50
  13. package/dist/channels/agentcore-protocol.js +3 -3
  14. package/dist/channels/agentcore-service.d.ts +8 -18
  15. package/dist/channels/agentcore-service.js +108 -127
  16. package/dist/channels/agentcore.d.ts +8 -24
  17. package/dist/channels/agentcore.js +32 -65
  18. package/dist/channels/body.d.ts +0 -16
  19. package/dist/channels/body.js +0 -25
  20. package/dist/channels/busy.js +6 -1
  21. package/dist/channels/context.d.ts +4 -0
  22. package/dist/channels/context.js +35 -0
  23. package/dist/channels/discover.d.ts +18 -20
  24. package/dist/channels/discover.js +41 -99
  25. package/dist/channels/feishu/feishu-api.d.ts +54 -4
  26. package/dist/channels/feishu/feishu-api.js +192 -149
  27. package/dist/channels/feishu/feishu.d.ts +3 -0
  28. package/dist/channels/feishu/feishu.js +117 -106
  29. package/dist/channels/feishu/history.d.ts +55 -0
  30. package/dist/channels/feishu/history.js +199 -0
  31. package/dist/channels/feishu/invoke-turn.d.ts +13 -11
  32. package/dist/channels/feishu/invoke-turn.js +9 -10
  33. package/dist/channels/feishu/model.d.ts +2 -1
  34. package/dist/channels/feishu/normalize.js +100 -0
  35. package/dist/channels/feishu/preview.d.ts +2 -2
  36. package/dist/channels/feishu/register-webhook.d.ts +1 -0
  37. package/dist/channels/feishu/register-webhook.js +3 -2
  38. package/dist/channels/feishu/scaffold/channel.ts +65 -46
  39. package/dist/channels/feishu/scaffold/feishu-send.ts +38 -33
  40. package/dist/channels/feishu/scaffold/feishu-threads.ts +25 -0
  41. package/dist/channels/feishu/setup-mode.d.ts +45 -25
  42. package/dist/channels/feishu/setup-mode.js +74 -23
  43. package/dist/channels/feishu/shared-api.d.ts +24 -6
  44. package/dist/channels/feishu/shared-api.js +30 -24
  45. package/dist/channels/kit/context-buffer.d.ts +11 -2
  46. package/dist/channels/kit/context-buffer.js +7 -4
  47. package/dist/channels/kit/delivery.d.ts +19 -3
  48. package/dist/channels/kit/delivery.js +74 -15
  49. package/dist/channels/kit/event-stream.js +2 -1
  50. package/dist/channels/kit/invoke-turn-kit.d.ts +41 -41
  51. package/dist/channels/kit/invoke-turn-kit.js +62 -71
  52. package/dist/channels/kit/place-history.d.ts +107 -0
  53. package/dist/channels/kit/place-history.js +182 -0
  54. package/dist/channels/kit/preview-kit.d.ts +9 -5
  55. package/dist/channels/kit/preview-kit.js +36 -15
  56. package/dist/channels/kit/room-threads.d.ts +46 -0
  57. package/dist/channels/kit/room-threads.js +81 -0
  58. package/dist/channels/kit/seen.js +1 -1
  59. package/dist/channels/kit/stop-command.d.ts +6 -3
  60. package/dist/channels/kit/stop-command.js +20 -18
  61. package/dist/channels/kit/thread-fork.d.ts +17 -0
  62. package/dist/channels/kit/thread-fork.js +43 -0
  63. package/dist/channels/kit/thread-participants.js +1 -1
  64. package/dist/channels/kit/transport.d.ts +5 -0
  65. package/dist/channels/kit/transport.js +5 -0
  66. package/dist/channels/kit/turn-runner.d.ts +10 -9
  67. package/dist/channels/kit/turn-runner.js +17 -19
  68. package/dist/channels/kit/turn-store.d.ts +5 -4
  69. package/dist/channels/kit/turn-store.js +5 -5
  70. package/dist/channels/lark/lark.d.ts +3 -0
  71. package/dist/channels/lark/lark.js +5 -0
  72. package/dist/channels/lark/onboard.d.ts +5 -3
  73. package/dist/channels/lark/onboard.js +14 -14
  74. package/dist/channels/lark/scaffold/channel.ts +67 -44
  75. package/dist/channels/lark/scaffold/lark-send.ts +38 -33
  76. package/dist/channels/lark/scaffold/lark-threads.ts +25 -0
  77. package/dist/channels/respond.d.ts +0 -4
  78. package/dist/channels/respond.js +1 -1
  79. package/dist/channels/router.d.ts +18 -0
  80. package/dist/channels/router.js +68 -0
  81. package/dist/channels/serve.d.ts +5 -70
  82. package/dist/channels/serve.js +105 -287
  83. package/dist/channels/slack/history.d.ts +42 -0
  84. package/dist/channels/slack/history.js +282 -0
  85. package/dist/channels/slack/invoke-turn.d.ts +12 -5
  86. package/dist/channels/slack/invoke-turn.js +7 -5
  87. package/dist/channels/slack/manifest.d.ts +1 -4
  88. package/dist/channels/slack/manifest.js +22 -10
  89. package/dist/channels/slack/model.d.ts +2 -1
  90. package/dist/channels/slack/onboard.d.ts +0 -2
  91. package/dist/channels/slack/onboard.js +2 -4
  92. package/dist/channels/slack/onboarding-state.d.ts +0 -2
  93. package/dist/channels/slack/onboarding-state.js +0 -1
  94. package/dist/channels/slack/parse.d.ts +0 -5
  95. package/dist/channels/slack/parse.js +1 -16
  96. package/dist/channels/slack/preview.d.ts +2 -3
  97. package/dist/channels/slack/preview.js +78 -52
  98. package/dist/channels/slack/register-webhook.d.ts +1 -0
  99. package/dist/channels/slack/register-webhook.js +6 -5
  100. package/dist/channels/slack/scaffold/channel.ts +23 -24
  101. package/dist/channels/slack/scaffold/slack-send.ts +50 -43
  102. package/dist/channels/slack/scaffold/slack-threads.ts +29 -0
  103. package/dist/channels/slack/setup-server.d.ts +19 -0
  104. package/dist/channels/slack/setup-server.js +113 -11
  105. package/dist/channels/slack/shared-api.d.ts +15 -4
  106. package/dist/channels/slack/shared-api.js +19 -14
  107. package/dist/channels/slack/slack-api.d.ts +61 -2
  108. package/dist/channels/slack/slack-api.js +28 -5
  109. package/dist/channels/slack/slack.js +97 -52
  110. package/dist/channels/slack/welcomed.js +1 -1
  111. package/dist/channels/telegram/context-buffer.d.ts +6 -1
  112. package/dist/channels/telegram/context-buffer.js +19 -0
  113. package/dist/channels/telegram/invoke-turn.d.ts +8 -4
  114. package/dist/channels/telegram/invoke-turn.js +7 -7
  115. package/dist/channels/telegram/parse.d.ts +7 -2
  116. package/dist/channels/telegram/parse.js +7 -0
  117. package/dist/channels/telegram/preview.d.ts +2 -2
  118. package/dist/channels/telegram/register-webhook.d.ts +1 -0
  119. package/dist/channels/telegram/register-webhook.js +3 -2
  120. package/dist/channels/telegram/scaffold/channel.ts +27 -28
  121. package/dist/channels/telegram/scaffold/telegram-send.ts +61 -108
  122. package/dist/channels/telegram/shared-api.d.ts +34 -0
  123. package/dist/channels/telegram/shared-api.js +79 -0
  124. package/dist/channels/telegram/telegram-api.d.ts +15 -5
  125. package/dist/channels/telegram/telegram-api.js +10 -6
  126. package/dist/channels/telegram/telegram.js +27 -21
  127. package/dist/channels/telegram/turn-store.js +1 -1
  128. package/dist/channels/{kit/turn-queue.d.ts → turn-queue.d.ts} +2 -2
  129. package/dist/channels/{kit/turn-queue.js → turn-queue.js} +10 -10
  130. package/dist/cli/add-feishu.d.ts +42 -12
  131. package/dist/cli/add-feishu.js +177 -124
  132. package/dist/cli/add-slack.d.ts +8 -3
  133. package/dist/cli/add-slack.js +115 -63
  134. package/dist/cli/auth-view.d.ts +10 -3
  135. package/dist/cli/auth-view.js +8 -6
  136. package/dist/cli/box-login.d.ts +17 -7
  137. package/dist/cli/box-login.js +46 -12
  138. package/dist/cli/commands/add.d.ts +15 -4
  139. package/dist/cli/commands/add.js +252 -143
  140. package/dist/cli/commands/auth.d.ts +6 -0
  141. package/dist/cli/commands/auth.js +50 -0
  142. package/dist/cli/commands/content.d.ts +6 -0
  143. package/dist/cli/commands/content.js +45 -0
  144. package/dist/cli/commands/deploy/agentcore.js +50 -77
  145. package/dist/cli/commands/deploy/docker.js +38 -39
  146. package/dist/cli/commands/deploy/fly.js +21 -18
  147. package/dist/cli/commands/deploy/host-login.d.ts +26 -0
  148. package/dist/cli/commands/deploy/host-login.js +90 -0
  149. package/dist/cli/commands/deploy/railway.js +21 -26
  150. package/dist/cli/commands/deploy/shared.d.ts +45 -17
  151. package/dist/cli/commands/deploy/shared.js +34 -15
  152. package/dist/cli/commands/deploy.d.ts +0 -4
  153. package/dist/cli/commands/deploy.js +237 -50
  154. package/dist/cli/commands/destroy.js +8 -6
  155. package/dist/cli/commands/dev.d.ts +0 -2
  156. package/dist/cli/commands/dev.js +20 -19
  157. package/dist/cli/commands/env.d.ts +12 -0
  158. package/dist/cli/commands/env.js +190 -0
  159. package/dist/cli/commands/info.js +95 -156
  160. package/dist/cli/commands/init.d.ts +2 -2
  161. package/dist/cli/commands/init.js +35 -33
  162. package/dist/cli/commands/invoke.d.ts +6 -0
  163. package/dist/cli/commands/invoke.js +131 -16
  164. package/dist/cli/commands/login.d.ts +31 -2
  165. package/dist/cli/commands/login.js +413 -64
  166. package/dist/cli/commands/logout.d.ts +4 -0
  167. package/dist/cli/commands/logout.js +53 -0
  168. package/dist/cli/commands/logs.js +8 -6
  169. package/dist/cli/commands/models.d.ts +2 -1
  170. package/dist/cli/commands/models.js +39 -37
  171. package/dist/cli/commands/schedules.d.ts +21 -0
  172. package/dist/cli/commands/schedules.js +143 -0
  173. package/dist/cli/commands/start.d.ts +11 -10
  174. package/dist/cli/commands/start.js +35 -62
  175. package/dist/cli/content-view.d.ts +9 -0
  176. package/dist/cli/content-view.js +26 -0
  177. package/dist/cli/fail.d.ts +9 -12
  178. package/dist/cli/fail.js +17 -14
  179. package/dist/cli/invoke-stream.d.ts +12 -3
  180. package/dist/cli/invoke-stream.js +85 -23
  181. package/dist/cli/kernel.d.ts +9 -2
  182. package/dist/cli/kernel.js +15 -6
  183. package/dist/cli/login-relay.d.ts +3 -2
  184. package/dist/cli/login-relay.js +18 -6
  185. package/dist/cli/models-view.d.ts +5 -1
  186. package/dist/cli/models-view.js +1 -1
  187. package/dist/cli/person.d.ts +10 -0
  188. package/dist/cli/person.js +23 -0
  189. package/dist/cli/program.js +421 -203
  190. package/dist/cli/serve.d.ts +13 -63
  191. package/dist/cli/serve.js +31 -121
  192. package/dist/cli/shared.d.ts +21 -48
  193. package/dist/cli/shared.js +68 -89
  194. package/dist/cli/ticket.d.ts +136 -0
  195. package/dist/cli/ticket.js +476 -0
  196. package/dist/client.d.ts +7 -0
  197. package/dist/client.js +2 -0
  198. package/dist/content/declare.d.ts +70 -0
  199. package/dist/content/declare.js +163 -0
  200. package/dist/content/file.d.ts +32 -0
  201. package/dist/content/file.js +119 -0
  202. package/dist/content/git.d.ts +41 -0
  203. package/dist/content/git.js +217 -0
  204. package/dist/content/mount.d.ts +2 -0
  205. package/dist/content/mount.js +15 -0
  206. package/dist/content/resolve.d.ts +52 -0
  207. package/dist/content/resolve.js +151 -0
  208. package/dist/content/source.d.ts +27 -0
  209. package/dist/content/source.js +53 -0
  210. package/dist/conversation-sessions.d.ts +26 -0
  211. package/dist/conversation-sessions.js +99 -0
  212. package/dist/declared-secrets.d.ts +19 -37
  213. package/dist/declared-secrets.js +16 -58
  214. package/dist/deploy/agentcore/destroy.d.ts +3 -3
  215. package/dist/deploy/agentcore/destroy.js +46 -28
  216. package/dist/deploy/agentcore/forwarder.js +105 -22
  217. package/dist/deploy/agentcore/logs.js +1 -1
  218. package/dist/deploy/agentcore/plan.d.ts +10 -24
  219. package/dist/deploy/agentcore/plan.js +31 -135
  220. package/dist/deploy/agentcore/run.d.ts +1 -1
  221. package/dist/deploy/agentcore/run.js +8 -5
  222. package/dist/deploy/agentcore/shell.d.ts +1 -1
  223. package/dist/deploy/agentcore/shell.js +5 -5
  224. package/dist/deploy/api.d.ts +34 -0
  225. package/dist/deploy/api.js +50 -0
  226. package/dist/deploy/box-shell.d.ts +6 -0
  227. package/dist/deploy/box-shell.js +7 -0
  228. package/dist/deploy/build-context.d.ts +7 -5
  229. package/dist/deploy/build-context.js +41 -35
  230. package/dist/deploy/channel-ingress.d.ts +6 -1
  231. package/dist/deploy/channel-ingress.js +18 -5
  232. package/dist/deploy/container.d.ts +22 -9
  233. package/dist/deploy/container.js +96 -55
  234. package/dist/deploy/docker/plan.d.ts +3 -2
  235. package/dist/deploy/docker/plan.js +13 -14
  236. package/dist/deploy/docker/run.d.ts +2 -2
  237. package/dist/deploy/docker/run.js +8 -4
  238. package/dist/deploy/fly/plan.d.ts +1 -1
  239. package/dist/deploy/fly/plan.js +12 -21
  240. package/dist/deploy/fly/run.d.ts +10 -6
  241. package/dist/deploy/fly/run.js +11 -6
  242. package/dist/deploy/hosts.d.ts +2 -1
  243. package/dist/deploy/hosts.js +2 -1
  244. package/dist/deploy/preflight.d.ts +21 -23
  245. package/dist/deploy/preflight.js +222 -201
  246. package/dist/deploy/railway/plan.d.ts +8 -6
  247. package/dist/deploy/railway/plan.js +15 -58
  248. package/dist/deploy/railway/run.d.ts +8 -3
  249. package/dist/deploy/railway/run.js +12 -8
  250. package/dist/deploy/residency.d.ts +5 -11
  251. package/dist/deploy/residency.js +0 -6
  252. package/dist/deploy/runner.d.ts +1 -1
  253. package/dist/deploy/runner.js +1 -1
  254. package/dist/deploy/secrets.d.ts +16 -2
  255. package/dist/deploy/secrets.js +33 -6
  256. package/dist/deploy/workspace.d.ts +11 -6
  257. package/dist/deploy/workspace.js +55 -38
  258. package/dist/dev-supervisor.d.ts +11 -2
  259. package/dist/dev-supervisor.js +51 -26
  260. package/dist/effect-port.d.ts +4 -4
  261. package/dist/effect-port.js +4 -4
  262. package/dist/environment/apt.d.ts +4 -0
  263. package/dist/environment/apt.js +32 -0
  264. package/dist/environment/declare.d.ts +59 -0
  265. package/dist/environment/declare.js +210 -0
  266. package/dist/environment/mise.d.ts +50 -0
  267. package/dist/environment/mise.js +268 -0
  268. package/dist/feishu.d.ts +2 -2
  269. package/dist/feishu.js +2 -2
  270. package/dist/git.d.ts +13 -0
  271. package/dist/git.js +55 -0
  272. package/dist/harnesses/models/catalog.d.ts +20 -0
  273. package/dist/harnesses/models/catalog.js +254 -0
  274. package/dist/{engines/pi/auth.d.ts → harnesses/models/credentials.d.ts} +3 -3
  275. package/dist/{engines/pi/auth.js → harnesses/models/credentials.js} +3 -3
  276. package/dist/harnesses/models/environment.d.ts +43 -0
  277. package/dist/harnesses/models/environment.js +82 -0
  278. package/dist/{engines/pi → harnesses/models}/login.d.ts +57 -26
  279. package/dist/{engines/pi → harnesses/models}/login.js +187 -79
  280. package/dist/harnesses/models/models.d.ts +83 -0
  281. package/dist/harnesses/models/models.js +158 -0
  282. package/dist/harnesses/pi-durable/agent.d.ts +42 -0
  283. package/dist/harnesses/pi-durable/agent.js +579 -0
  284. package/dist/harnesses/pi-durable/defaults.d.ts +28 -0
  285. package/dist/harnesses/pi-durable/defaults.js +26 -0
  286. package/dist/harnesses/pi-durable/define.d.ts +77 -0
  287. package/dist/harnesses/pi-durable/define.js +28 -0
  288. package/dist/harnesses/pi-durable/entries.d.ts +32 -0
  289. package/dist/harnesses/pi-durable/entries.js +126 -0
  290. package/dist/harnesses/pi-durable/events.d.ts +25 -0
  291. package/dist/harnesses/pi-durable/events.js +238 -0
  292. package/dist/harnesses/pi-durable/ids.d.ts +16 -0
  293. package/dist/harnesses/pi-durable/ids.js +55 -0
  294. package/dist/harnesses/pi-durable/messages.d.ts +41 -0
  295. package/dist/harnesses/pi-durable/messages.js +116 -0
  296. package/dist/harnesses/pi-durable/open.d.ts +88 -0
  297. package/dist/harnesses/pi-durable/open.js +329 -0
  298. package/dist/harnesses/pi-durable/reads.d.ts +30 -0
  299. package/dist/harnesses/pi-durable/reads.js +94 -0
  300. package/dist/harnesses/pi-durable/registry.d.ts +18 -0
  301. package/dist/harnesses/pi-durable/registry.js +56 -0
  302. package/dist/harnesses/pi-durable/release.d.ts +13 -0
  303. package/dist/harnesses/pi-durable/release.js +40 -0
  304. package/dist/harnesses/pi-durable/serve.d.ts +80 -0
  305. package/dist/harnesses/pi-durable/serve.js +156 -0
  306. package/dist/harnesses/pi-durable/sessions.d.ts +27 -0
  307. package/dist/harnesses/pi-durable/sessions.js +47 -0
  308. package/dist/harnesses/pi-durable/storage.d.ts +4 -0
  309. package/dist/harnesses/pi-durable/storage.js +49 -0
  310. package/dist/harnesses/pi-durable/stream.d.ts +20 -0
  311. package/dist/harnesses/pi-durable/stream.js +221 -0
  312. package/dist/harnesses/pi-durable/text.d.ts +30 -0
  313. package/dist/harnesses/pi-durable/text.js +292 -0
  314. package/dist/harnesses/pi-durable/wake.d.ts +4 -0
  315. package/dist/harnesses/pi-durable/wake.js +81 -0
  316. package/dist/http/client.d.ts +6 -0
  317. package/dist/http/client.js +256 -0
  318. package/dist/http/contract.d.ts +541 -0
  319. package/dist/http/contract.js +179 -0
  320. package/dist/http/server.d.ts +34 -0
  321. package/dist/http/server.js +194 -0
  322. package/dist/index.d.ts +17 -4
  323. package/dist/index.js +10 -5
  324. package/dist/lark.d.ts +2 -2
  325. package/dist/lark.js +2 -2
  326. package/dist/locked-file.d.ts +17 -0
  327. package/dist/{engines/pi/locked-file.js → locked-file.js} +16 -10
  328. package/dist/once.d.ts +6 -0
  329. package/dist/once.js +23 -0
  330. package/dist/paths.d.ts +36 -52
  331. package/dist/paths.js +66 -182
  332. package/dist/runtime.d.ts +25 -2
  333. package/dist/runtime.js +27 -0
  334. package/dist/scaffold/add-channel.d.ts +14 -27
  335. package/dist/scaffold/add-channel.js +82 -180
  336. package/dist/scaffold/init.d.ts +17 -18
  337. package/dist/scaffold/init.js +87 -99
  338. package/dist/scaffold/templates/SYSTEM.md +12 -0
  339. package/dist/scaffold/templates/env.example +4 -10
  340. package/dist/scaffold/templates/fastagent.config.ts +21 -33
  341. package/dist/scaffold/templates/gitignore +8 -1
  342. package/dist/scaffold/templates/skills/writing-great-skills/SKILL.md +1 -2
  343. package/dist/scaffold/templates.d.ts +9 -4
  344. package/dist/scaffold/templates.js +7 -5
  345. package/dist/scaffold/vendor-skill.d.ts +1 -4
  346. package/dist/scaffold/vendor-skill.js +5 -6
  347. package/dist/schedule/cron.d.ts +13 -0
  348. package/dist/schedule/cron.js +52 -0
  349. package/dist/schedule/eventbridge-cron.d.ts +17 -0
  350. package/dist/schedule/eventbridge-cron.js +88 -0
  351. package/dist/schedule/schedule.d.ts +23 -0
  352. package/dist/schedule/schedule.js +34 -0
  353. package/dist/schedule/scheduler.d.ts +34 -33
  354. package/dist/schedule/scheduler.js +251 -137
  355. package/dist/schedule/state.d.ts +4 -14
  356. package/dist/schedule/state.js +7 -7
  357. package/dist/schedule/wake-alarm.d.ts +22 -2
  358. package/dist/schedule/wake-alarm.js +66 -20
  359. package/dist/schedule/wakeups.d.ts +16 -15
  360. package/dist/schedule/wakeups.js +47 -45
  361. package/dist/service.d.ts +56 -169
  362. package/dist/service.js +91 -187
  363. package/dist/serving-command.d.ts +10 -0
  364. package/dist/serving-command.js +16 -0
  365. package/dist/slack.d.ts +1 -1
  366. package/dist/slack.js +1 -1
  367. package/dist/{channels/kit/state.js → state-file.js} +6 -6
  368. package/dist/telegram.d.ts +1 -0
  369. package/dist/telegram.js +1 -0
  370. package/dist/tunnel.d.ts +3 -0
  371. package/dist/tunnel.js +12 -4
  372. package/dist/value-file.d.ts +21 -0
  373. package/dist/value-file.js +108 -0
  374. package/dist/version.d.ts +5 -0
  375. package/dist/version.js +14 -1
  376. package/package.json +18 -28
  377. package/dist/agent.d.ts +0 -106
  378. package/dist/agent.js +0 -21
  379. package/dist/channels/control.d.ts +0 -31
  380. package/dist/channels/control.js +0 -329
  381. package/dist/channels/define-channel.d.ts +0 -39
  382. package/dist/channels/define-channel.js +0 -9
  383. package/dist/channels/feishu/context-buffer.d.ts +0 -35
  384. package/dist/channels/feishu/context-buffer.js +0 -65
  385. package/dist/channels/feishu/scaffold/channel.websocket.ts +0 -31
  386. package/dist/channels/http.d.ts +0 -23
  387. package/dist/channels/http.js +0 -57
  388. package/dist/channels/lark/scaffold/channel.websocket.ts +0 -31
  389. package/dist/channels/slack/context-buffer.d.ts +0 -23
  390. package/dist/channels/slack/context-buffer.js +0 -37
  391. package/dist/channels/sse.d.ts +0 -4
  392. package/dist/channels/sse.js +0 -66
  393. package/dist/cli/commands/chat.d.ts +0 -3
  394. package/dist/cli/commands/chat.js +0 -14
  395. package/dist/cli/commands/routine-run.d.ts +0 -6
  396. package/dist/cli/commands/routine-run.js +0 -46
  397. package/dist/cli/commands/routine.d.ts +0 -25
  398. package/dist/cli/commands/routine.js +0 -122
  399. package/dist/cli/commands/tool.d.ts +0 -1
  400. package/dist/cli/commands/tool.js +0 -57
  401. package/dist/collect.d.ts +0 -63
  402. package/dist/collect.js +0 -90
  403. package/dist/core.d.ts +0 -13
  404. package/dist/core.js +0 -15
  405. package/dist/engines/pi/agent-models.d.ts +0 -83
  406. package/dist/engines/pi/agent-models.js +0 -120
  407. package/dist/engines/pi/agent-session-factory.d.ts +0 -121
  408. package/dist/engines/pi/agent-session-factory.js +0 -517
  409. package/dist/engines/pi/chat.d.ts +0 -3
  410. package/dist/engines/pi/chat.js +0 -8
  411. package/dist/engines/pi/config.d.ts +0 -71
  412. package/dist/engines/pi/config.js +0 -199
  413. package/dist/engines/pi/create.d.ts +0 -170
  414. package/dist/engines/pi/create.js +0 -343
  415. package/dist/engines/pi/definition.d.ts +0 -74
  416. package/dist/engines/pi/definition.js +0 -236
  417. package/dist/engines/pi/entry-images.d.ts +0 -14
  418. package/dist/engines/pi/entry-images.js +0 -23
  419. package/dist/engines/pi/invoke-session.d.ts +0 -18
  420. package/dist/engines/pi/invoke-session.js +0 -403
  421. package/dist/engines/pi/locked-file.d.ts +0 -9
  422. package/dist/engines/pi/machine.d.ts +0 -53
  423. package/dist/engines/pi/machine.js +0 -137
  424. package/dist/engines/pi/models.d.ts +0 -200
  425. package/dist/engines/pi/models.js +0 -533
  426. package/dist/engines/pi/open.d.ts +0 -180
  427. package/dist/engines/pi/open.js +0 -270
  428. package/dist/engines/pi/openai-account-models.d.ts +0 -35
  429. package/dist/engines/pi/openai-account-models.js +0 -116
  430. package/dist/engines/pi/report.d.ts +0 -18
  431. package/dist/engines/pi/report.js +0 -59
  432. package/dist/engines/pi/retry-event.d.ts +0 -6
  433. package/dist/engines/pi/retry-event.js +0 -15
  434. package/dist/engines/pi/service.d.ts +0 -9
  435. package/dist/engines/pi/service.js +0 -14
  436. package/dist/engines/pi/session-builder.d.ts +0 -13
  437. package/dist/engines/pi/session-builder.js +0 -117
  438. package/dist/engines/pi/session-control.d.ts +0 -77
  439. package/dist/engines/pi/session-control.js +0 -908
  440. package/dist/engines/pi/session-effects.d.ts +0 -14
  441. package/dist/engines/pi/session-effects.js +0 -30
  442. package/dist/engines/pi/session-inheritance.d.ts +0 -21
  443. package/dist/engines/pi/session-inheritance.js +0 -204
  444. package/dist/engines/pi/session-markers.d.ts +0 -49
  445. package/dist/engines/pi/session-markers.js +0 -60
  446. package/dist/engines/pi/session-settings.d.ts +0 -67
  447. package/dist/engines/pi/session-settings.js +0 -119
  448. package/dist/engines/pi/session-store.d.ts +0 -69
  449. package/dist/engines/pi/session-store.js +0 -430
  450. package/dist/engines/pi/tool-context.d.ts +0 -45
  451. package/dist/engines/pi/tool-context.js +0 -31
  452. package/dist/engines/pi/tool.d.ts +0 -99
  453. package/dist/engines/pi/tool.js +0 -118
  454. package/dist/engines/pi/turn-kit.d.ts +0 -83
  455. package/dist/engines/pi/turn-kit.js +0 -275
  456. package/dist/engines/pi/wake-tool.d.ts +0 -9
  457. package/dist/engines/pi/wake-tool.js +0 -92
  458. package/dist/loader.d.ts +0 -41
  459. package/dist/loader.js +0 -116
  460. package/dist/node.d.ts +0 -3
  461. package/dist/node.js +0 -4
  462. package/dist/observe.d.ts +0 -6
  463. package/dist/observe.js +0 -47
  464. package/dist/pi.d.ts +0 -25
  465. package/dist/pi.js +0 -15
  466. package/dist/scaffold/templates/APPEND_SYSTEM.md +0 -12
  467. package/dist/scaffold/templates/tools/fetch-url.ts +0 -25
  468. package/dist/schedule/discover.d.ts +0 -17
  469. package/dist/schedule/discover.js +0 -61
  470. package/dist/schedule/routine.d.ts +0 -43
  471. package/dist/schedule/routine.js +0 -32
  472. package/dist/schedule/run.d.ts +0 -55
  473. package/dist/schedule/run.js +0 -146
  474. package/dist/secrets-gate.d.ts +0 -32
  475. package/dist/secrets-gate.js +0 -33
  476. package/dist/session-remote.d.ts +0 -47
  477. package/dist/session-remote.js +0 -460
  478. package/dist/session.d.ts +0 -466
  479. package/dist/session.js +0 -57
  480. /package/dist/{channels/kit/state.d.ts → state-file.d.ts} +0 -0
@@ -1,24 +1,24 @@
1
1
  /**
2
- * `deploy railway`: a thin config file, scale-to-zero is a manual dashboard step, the URL is minted (see
2
+ * `deploy railway`: no config file of its own, scale-to-zero is a manual dashboard step, the URL is minted (see
3
3
  * planRailwayDeploy).
4
4
  */
5
5
  import { basename } from "node:path";
6
- import { dockerfilePathVar, isGeneratedRailwayJson, planRailwayDeploy, toRailwayName, } from "../../../deploy/railway/plan.js";
6
+ import { planRailwayDeploy, toRailwayName } from "../../../deploy/railway/plan.js";
7
7
  import { deployRailwayRun } from "../../../deploy/railway/run.js";
8
8
  import { spawnRunner } from "../../../deploy/runner.js";
9
9
  import { assembleSecrets } from "../../../deploy/secrets.js";
10
10
  import { processShell } from "../../../deploy/box-shell.js";
11
11
  import { failStartup } from "../../fail.js";
12
- import { isInteractive } from "../../shared.js";
12
+ import { RAILWAY_LOGIN, hostLogin } from "./host-login.js";
13
13
  import { boxLoginStep, registrarsFor } from "./shared.js";
14
14
  export const railwayHost = {
15
- isOurs: (path, content) => path.endsWith("railway.json") && isGeneratedRailwayJson(content),
16
- artifact: "railway.json",
17
- shell: async ({ workspace }) => railwayShell(toRailwayName(basename(workspace)), workspace),
15
+ // Railway's only artifacts are the container's, which planArtifacts owns for every host.
16
+ isOurs: () => false,
17
+ shell: async (agentDir) => railwayShell(toRailwayName(basename(agentDir)), agentDir),
18
18
  async deploy(ctx) {
19
- const { opts, agentDir, workspace, pre, channels, write } = ctx;
19
+ const { opts, agentDir, pre, channels, write } = ctx;
20
20
  const { hasCron, modelAuth, boxLogin, container, declaredSecrets, values, valueFile } = pre;
21
- const serviceName = toRailwayName(basename(workspace));
21
+ const serviceName = toRailwayName(basename(agentDir));
22
22
  const plan = planRailwayDeploy({
23
23
  serviceName,
24
24
  boxLogin,
@@ -29,36 +29,29 @@ export const railwayHost = {
29
29
  });
30
30
  await write(plan.artifacts, { force: !!opts.force });
31
31
  if (opts.run) {
32
- // The BUILD entry is guaranteed by the RAILWAY_DOCKERFILE_PATH service variable the runner sets (Railway's
33
- // documented non-root-Dockerfile route), and Railway's default restart policy already equals the file's
34
- // ON_FAILURE — the dashboard-only Config-as-code pointer only adds the /health deploy gate (boot-crash
35
- // visibility), so it is an OPTIONAL note, not a gate.
36
- console.error(`[fastagent] note: optional — point the service at fastagent/railway.json (Service → Settings → ` +
37
- `Config-as-code, dashboard-only) so the /health healthcheck marks a boot-crashing deploy as FAILED; ` +
38
- `the build already uses fastagent/Dockerfile via the RAILWAY_DOCKERFILE_PATH variable`);
39
32
  return runDeployRailway({
40
33
  agentDir,
41
- workspace,
42
34
  name: serviceName,
43
35
  modelAuth,
44
36
  boxLogin,
45
- input: opts.input !== false && isInteractive(),
37
+ answerer: ctx.answerer,
38
+ rerun: ctx.rerun,
46
39
  channels,
47
40
  declaredSecrets,
48
41
  values,
49
42
  valueFile,
50
43
  intoLinked: !!opts.intoLinked,
51
- dockerfilePath: dockerfilePathVar(pre.container.agentPrefix),
52
44
  });
53
45
  }
54
46
  console.log(plan.runbook.join("\n"));
55
- return;
47
+ // Railway mints the domain when the runbook's step generates it.
48
+ return undefined;
56
49
  },
57
50
  };
58
51
  /** `deploy railway --run`: drive the railway CLI to completion. */
59
52
  async function runDeployRailway(params) {
60
- const { agentDir, workspace, name, channels, intoLinked, dockerfilePath } = params;
61
- const railway = spawnRunner("railway", workspace);
53
+ const { agentDir, name, channels, intoLinked } = params;
54
+ const railway = spawnRunner("railway", agentDir);
62
55
  // Fail fast if the railway CLI is absent (spawn ENOENT → 127), with the install link.
63
56
  if ((await railway(["--version"], { capture: true })).code === 127) {
64
57
  failStartup(new Error(`railway CLI not found — install it: https://docs.railway.com/guides/cli, then re-run`));
@@ -76,15 +69,17 @@ async function runDeployRailway(params) {
76
69
  valueFile: params.valueFile,
77
70
  channels,
78
71
  intoLinked,
79
- dockerfilePath,
80
- ...boxLoginStep("railway", params, () => railwayShell(name, workspace)),
81
- }, railway, (m) => console.error(`[fastagent] ${m}`), registrarsFor(agentDir));
72
+ ...boxLoginStep("railway", params, () => railwayShell(name, agentDir)),
73
+ ...hostLogin(RAILWAY_LOGIN, params.answerer, agentDir),
74
+ forAgent: `${params.rerun} --json`,
75
+ }, railway, (m) => console.error(`[fastagent] ${m}`), registrarsFor(agentDir, params.values, params.answerer));
82
76
  if (!outcome.ok)
83
77
  failStartup(new Error(`deploy stopped: ${outcome.gate}`));
84
78
  console.error(`[fastagent] deployed → ${outcome.url}`);
79
+ return outcome.url;
85
80
  }
86
81
  /** `railway ssh` into the service, in the project and environment this directory is linked to. */
87
- function railwayShell(service, workspace) {
82
+ function railwayShell(service, agentDir) {
88
83
  // One quoted word: the command reaches the box as ONE line its shell parses, the way OpenSSH hands it over.
89
- return processShell("railway", (command) => ["ssh", "--service", service, "--", `sh -c '${command}'`], workspace);
84
+ return processShell("railway", (command) => ["ssh", "--service", service, "--", `sh -c '${command}'`], agentDir);
90
85
  }
@@ -1,9 +1,9 @@
1
1
  import type { DeclaredChannel } from "../../../channels/discover.ts";
2
2
  import type { Registrars } from "../../../deploy/channel-ingress.ts";
3
3
  import type { DeployPreflight } from "../../../deploy/preflight.ts";
4
- import type { FastagentConfig } from "../../../engines/pi/config.ts";
5
- import { type ResolvedPlacement } from "../../../paths.ts";
4
+ import type { AgentConfig } from "../../../harnesses/pi-durable/define.ts";
6
5
  import { type BoxLoginStep, type BoxShell } from "../../../deploy/box-shell.ts";
6
+ import type { TicketStep } from "../../ticket.ts";
7
7
  import type { DeployHost } from "../../../deploy/hosts.ts";
8
8
  export interface DeployOptions {
9
9
  run?: boolean;
@@ -12,23 +12,49 @@ export interface DeployOptions {
12
12
  intoLinked?: boolean;
13
13
  /** false ⇔ `--no-input`. */
14
14
  input?: boolean;
15
+ /** `--json`: a coding agent's `--run`, run in a ticket that hands each step only a person can take to its user. */
16
+ json?: boolean;
17
+ /** `--check <ticket>`: where such a deploy stands. */
18
+ check?: string;
19
+ /** `--code <code>` (with `--check`): the code a host's approval page showed, when it could not reach this machine. */
20
+ code?: string;
21
+ /** `--stop` (with `--check`): stop that deploy where it is. */
22
+ stop?: boolean;
23
+ /** `--timeout <seconds>`: how long it stays open. */
24
+ timeout?: string;
25
+ /** `--ticket <id>`: the process that runs it. */
26
+ ticket?: string;
15
27
  }
16
28
  /**
17
- * What the dispatcher resolved before handing off: the placement, the flags, the config and the host-neutral
29
+ * Who takes a deploy's steps only a person can (a host account's sign-in, a production app's confirmation, the box's
30
+ * model login): the person at this terminal, a coding agent's person through the deploy's ticket, or nobody (CI, or a
31
+ * script), for whom such a step stops the deploy naming how to give it.
32
+ */
33
+ export type Answerer = {
34
+ kind: "terminal";
35
+ } | {
36
+ kind: "ticket";
37
+ step: TicketStep;
38
+ } | {
39
+ kind: "nobody";
40
+ };
41
+ /**
42
+ * What the dispatcher resolved before handing off: the agent directory, the flags, the config and the host-neutral
18
43
  * pre-flight, plus the channel lists every host asks about.
19
44
  */
20
45
  interface DeployContext {
21
46
  opts: DeployOptions;
47
+ answerer: Answerer;
48
+ /** The command that runs this deploy again, from where it ran: its agent directory and flags. */
49
+ rerun: string;
22
50
  agentDir: string;
23
- workspace: string;
24
- config: FastagentConfig;
51
+ config: AgentConfig;
25
52
  pre: Extract<DeployPreflight, {
26
53
  ok: true;
27
54
  }>;
28
55
  channels: readonly DeclaredChannel[];
29
56
  webhookChannels: readonly DeclaredChannel[];
30
- longConnectionChannels: readonly DeclaredChannel[];
31
- /** Write this host's planned artifacts into the workspace under the ownership rule. */
57
+ /** Write this host's planned artifacts into the agent directory under the ownership rule. */
32
58
  write(artifacts: {
33
59
  path: string;
34
60
  content: string;
@@ -41,26 +67,28 @@ interface DeployContext {
41
67
  export interface HostDeploy {
42
68
  /** Did this host generate the file at `path`? */
43
69
  isOurs(path: string, content: string): boolean;
44
- /** The file in the agent dir whose presence says this workspace deploys to the host. */
45
- artifact: string;
46
- /** The shell into this workspace's running box (`fastagent login --deployment`). */
47
- shell(placement: ResolvedPlacement): Promise<BoxShell>;
70
+ /** The shell into this agent's running box (`fastagent login --deployment`). */
71
+ shell(agentDir: string): Promise<BoxShell>;
72
+ validate?(ctx: Pick<DeployContext, "opts" | "agentDir" | "pre">): void;
48
73
  /**
49
74
  * Plan the artifacts from the pre-flight facts and what is on disk, write them, then either drive the host CLI
50
- * (`--run`) or print the runbook.
75
+ * (`--run`) or print the runbook. Answers the URL the deployment is reached at, when this host knows it.
51
76
  */
52
- deploy(ctx: DeployContext): Promise<void>;
77
+ deploy(ctx: DeployContext): Promise<string | undefined>;
53
78
  }
54
- /** The registrars every host driver gets. */
55
- export declare function registrarsFor(agentDir: string): Registrars;
79
+ /** Where a step left to the person goes for `answerer`: a ticket's `afterwards`; nowhere else but the log. */
80
+ export declare function leftToPerson(answerer: Answerer): ((step: string) => void) | undefined;
81
+ /** The registrars every host driver gets; a channel's manual step also goes to `answerer`'s person. */
82
+ export declare function registrarsFor(agentDir: string, values: ReadonlyMap<string, string>, answerer: Answerer): Registrars;
56
83
  /**
57
84
  * The login `--run` starts on the box it just deployed, before any webhook is pointed at it (a host driver's `boxLogin`): for
58
85
  * the model's provider, keeping a credential the box already holds (a redeploy), and asking only when a person can
59
86
  * answer. None when the model's credential travels as a variable.
60
87
  */
61
- export declare function boxLoginStep<Args extends unknown[]>(host: DeployHost, params: ResolvedPlacement & {
88
+ export declare function boxLoginStep<Args extends unknown[]>(host: DeployHost, params: {
89
+ agentDir: string;
62
90
  boxLogin: string | undefined;
63
- input: boolean;
91
+ answerer: Answerer;
64
92
  },
65
93
  /** The shell, from whatever the driver learns only after deploying (AgentCore's runtime ARN). */
66
94
  shell: (...args: Args) => BoxShell): {
@@ -3,23 +3,29 @@
3
3
  * ownership rule.
4
4
  */
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
6
- import { dirname, join } from "node:path";
6
+ import { basename, dirname, join } from "node:path";
7
7
  import { registerFeishuWebhook } from "../../../channels/feishu/register-webhook.js";
8
8
  import { DEPLOY_REGISTRATION_ATTEMPTS } from "../../../channels/registration.js";
9
9
  import { registerSlackWebhook } from "../../../channels/slack/register-webhook.js";
10
10
  import { registerTelegramWebhook } from "../../../channels/telegram/register-webhook.js";
11
- import { isGeneratedDockerfile, isGeneratedDockerignore } from "../../../deploy/container.js";
12
- import { RELEASE_FILE } from "../../../deploy/workspace.js";
11
+ import { BUILD_OUTPUTS, IMAGE_DEFINITION_DIR, isGeneratedDockerfile, isGeneratedDockerignore, } from "../../../deploy/container.js";
13
12
  import { exists, resolveStateRoot } from "../../../paths.js";
14
13
  import { deploymentLoginCommand } from "../../../deploy/box-shell.js";
15
- import { loginOnBox } from "../../box-login.js";
16
- /** The registrars every host driver gets. */
17
- export function registrarsFor(agentDir) {
14
+ import { loginOnBox, ticketLoginIO } from "../../box-login.js";
15
+ /** Where a step left to the person goes for `answerer`: a ticket's `afterwards`; nowhere else but the log. */
16
+ export function leftToPerson(answerer) {
17
+ return answerer.kind === "ticket" ? (step) => answerer.step.person.afterwards(step) : undefined;
18
+ }
19
+ /** The registrars every host driver gets; a channel's manual step also goes to `answerer`'s person. */
20
+ export function registrarsFor(agentDir, values, answerer) {
18
21
  const attempts = DEPLOY_REGISTRATION_ATTEMPTS;
22
+ const env = Object.fromEntries(values);
23
+ const leave = leftToPerson(answerer);
19
24
  return {
20
- telegram: (baseUrl) => registerTelegramWebhook(baseUrl, { attempts }),
21
- slack: (baseUrl) => registerSlackWebhook(baseUrl, { stateRoot: resolveStateRoot(agentDir), attempts }),
22
- feishu: (baseUrl, kind) => registerFeishuWebhook(baseUrl, kind, { attempts }),
25
+ ...(leave === undefined ? {} : { leave }),
26
+ telegram: (baseUrl) => registerTelegramWebhook(baseUrl, { attempts, env }),
27
+ slack: (baseUrl) => registerSlackWebhook(baseUrl, { stateRoot: resolveStateRoot(agentDir), environment: "production", attempts }),
28
+ feishu: (baseUrl, kind) => registerFeishuWebhook(baseUrl, kind, { attempts, env }),
23
29
  };
24
30
  }
25
31
  /**
@@ -33,11 +39,24 @@ shell) {
33
39
  const provider = params.boxLogin;
34
40
  if (provider === undefined)
35
41
  return {};
36
- const placement = { agentDir: params.agentDir, workspace: params.workspace };
42
+ const command = deploymentLoginCommand(host, provider);
43
+ const { answerer } = params;
37
44
  return {
38
45
  boxLogin: {
39
- command: deploymentLoginCommand(host, provider),
40
- run: (...args) => loginOnBox({ host, shell: shell(...args), placement, provider, ifMissing: true, input: params.input }),
46
+ command,
47
+ run: async (...args) => {
48
+ const request = { host, shell: shell(...args), provider, ifMissing: true };
49
+ if (answerer.kind !== "ticket")
50
+ return loginOnBox({ ...request, input: answerer.kind === "terminal" });
51
+ // An account sign-in: a key cannot be typed into a ticket.
52
+ const io = ticketLoginIO(answerer.step, command);
53
+ const failed = await loginOnBox({ ...request, method: "oauth", input: true, io });
54
+ if (failed !== undefined)
55
+ return io.refusal() ?? failed;
56
+ // Logged in: what follows (the webhooks) is the deploy finishing, never cut by the person's deadline.
57
+ answerer.step.person.carriesOn();
58
+ return undefined;
59
+ },
41
60
  },
42
61
  };
43
62
  }
@@ -54,7 +73,7 @@ export async function planArtifacts(target, artifacts, options) {
54
73
  for (const a of artifacts) {
55
74
  const abs = join(target, a.path);
56
75
  // Pure build output, not operator-owned configuration. It must track the generated template/runbook.
57
- if (a.path.endsWith(`/${RELEASE_FILE}`) || options.alwaysWrite?.includes(a.path)) {
76
+ if (BUILD_OUTPUTS.includes(basename(a.path)) || options.alwaysWrite?.includes(a.path)) {
58
77
  write(a.path, abs, a.content);
59
78
  continue;
60
79
  }
@@ -67,7 +86,7 @@ export async function planArtifacts(target, artifacts, options) {
67
86
  (a.path.endsWith(".dockerignore")
68
87
  ? `; see the preflight warnings for what it must exclude`
69
88
  : a.path.endsWith("Dockerfile")
70
- ? `; deploy still assumes it listens on $PORT and runs \`fastagent start /app\``
89
+ ? `; deploy still assumes it listens on $PORT and runs \`fastagent start ${IMAGE_DEFINITION_DIR}\``
71
90
  : ``));
72
91
  continue;
73
92
  }
@@ -88,7 +107,7 @@ export async function planArtifacts(target, artifacts, options) {
88
107
  export async function applyArtifactPlan(plan) {
89
108
  for (const step of plan.steps) {
90
109
  if (step.content !== undefined) {
91
- await mkdir(dirname(step.abs), { recursive: true }); // artifacts live under fastagent/
110
+ await mkdir(dirname(step.abs), { recursive: true });
92
111
  await writeFile(step.abs, step.content);
93
112
  }
94
113
  console.error(step.message);
@@ -1,7 +1,3 @@
1
- /**
2
- * `fastagent deploy <host> [dir]`: generate host artifacts from the resolved definition and print an ordered deploy
3
- * runbook.
4
- */
5
1
  import type { DeployHost } from "../../deploy/hosts.ts";
6
2
  import { type DeployOptions, type HostDeploy, applyArtifactPlan, planArtifacts } from "./deploy/shared.ts";
7
3
  export { applyArtifactPlan, planArtifacts };
@@ -1,12 +1,28 @@
1
+ /**
2
+ * `fastagent deploy <host> [agent]`: generate host artifacts from the resolved definition and print an ordered deploy
3
+ * runbook.
4
+ */
5
+ import { relative } from "node:path";
6
+ import { cloudFor } from "../../channels/feishu/cloud.js";
7
+ import { FEISHU_INGRESS_SETTINGS } from "../../channels/feishu/setup-mode.js";
8
+ import { assembleSecrets, divergentSettingsGate, missingValuesGate } from "../../deploy/secrets.js";
9
+ import { dotEnvPath, loadEnvValues } from "../../env.js";
10
+ import { unmarkDevServe } from "../../serving-command.js";
11
+ import { assertIndependentFeishuApps, feishuAppSecretNames, larkCredentialsNeeded, prepareFeishuApps, unpreparedFeishuApps, } from "../add-feishu.js";
12
+ import { displayPath, selectAgentEnvironment } from "../../paths.js";
1
13
  import { preflightDeploy } from "../../deploy/preflight.js";
2
- import { loadConfig } from "../../engines/pi/config.js";
14
+ import { apiReport, deploymentApi, writeApiKey } from "../../deploy/api.js";
15
+ import { unprotectedSecretsNote } from "../../value-file.js";
16
+ import { loadConfig } from "../../harnesses/pi-durable/open.js";
3
17
  import { failStartup, failUsage } from "../fail.js";
4
- import { enterAgentDirectory } from "../shared.js";
18
+ import { enterAgentDirectory, isInteractive, shellArg } from "../shared.js";
19
+ import { terminalPerson } from "../person.js";
20
+ import { checkTicket, printReport, refusedCheck, runTicket, startTicket, stopTicket, ticketExitCode, ticketReport, } from "../ticket.js";
5
21
  import { agentcoreHost } from "./deploy/agentcore.js";
6
22
  import { dockerHost } from "./deploy/docker.js";
7
23
  import { flyHost } from "./deploy/fly.js";
8
24
  import { railwayHost } from "./deploy/railway.js";
9
- import { applyArtifactPlan, planArtifacts } from "./deploy/shared.js";
25
+ import { applyArtifactPlan, planArtifacts, } from "./deploy/shared.js";
10
26
  export { applyArtifactPlan, planArtifacts };
11
27
  /** Every host, by the name the CLI takes. */
12
28
  export const HOSTS = {
@@ -50,59 +66,230 @@ export function warnHostOnlyFlags(host, opts) {
50
66
  console.error(`[fastagent] warn: ${rule.flag}: ${rule.owner}-only — ${instead}`);
51
67
  }
52
68
  }
69
+ /** The command that reads a deploy's ticket, as every such ticket records it. */
70
+ const deployCheck = (host) => `fastagent deploy ${host} --check`;
71
+ /** How long a coding agent's deploy stays open: a build, and the person's steps between. */
72
+ const TICKET_TIMEOUT_SECONDS = 3600;
53
73
  export async function runDeploy(host, dirArg, opts) {
74
+ if (opts.check !== undefined)
75
+ return checkDeploy(host, opts.check, opts);
76
+ if (opts.stop)
77
+ failUsage("--stop stops a deploy started with --json: pass --check <ticket> too");
78
+ if (opts.ticket !== undefined) {
79
+ // The process `startTicket` started: it takes the ticket before the pre-flight (seconds of building the
80
+ // definition), then does the whole deploy, its person the ticket's.
81
+ await runTicket(opts.ticket, (step) => deploy(host, dirArg, opts, step));
82
+ process.exit(0);
83
+ }
84
+ await deploy(host, dirArg, opts);
85
+ }
86
+ /** The deploy itself: through a ticket's `step` when one runs it, else at this terminal or with nobody to ask. */
87
+ async function deploy(host, dirArg, opts, step) {
88
+ if (opts.code !== undefined)
89
+ failUsage("--code hands a code to a deploy's ticket: pass --check <ticket> too");
54
90
  if (opts.tunnel && host !== "docker") {
55
91
  // A flag/host combination the parser cannot see (host is an argument) — usage class, exit 2.
56
92
  failUsage(`deploy stopped: --tunnel is supported only by the local Docker target`);
57
93
  }
58
- // The picker's write-back lands the model in fastagent.config.ts.
59
- const placement = await enterAgentDirectory(dirArg, opts);
60
- // ONE deploy semantic: bake the WORKSPACE (WYSIWYG).
61
- const { agentDir, workspace } = placement;
62
- const { config } = await loadConfig(agentDir).catch(failStartup);
63
- // The host-neutral pre-flight (the model and its source, channel discovery, model-auth probe, container facts +
64
- // their warnings) lives in deploy/preflight.ts.
65
- const pre = await preflightDeploy({
66
- placement,
94
+ if (opts.json && !opts.run)
95
+ failUsage("--json reports a deploy --run drives: pass --run too");
96
+ selectAgentEnvironment("production");
97
+ const { agentDir } = await enterAgentDirectory(dirArg, opts);
98
+ const config = await loadConfig(agentDir).catch(failStartup);
99
+ // Never `dev`, whatever spawned this; and what decides a channel's shape is read here as the box will read it.
100
+ unmarkDevServe();
101
+ const shaped = divergentSettingsGate(FEISHU_INGRESS_SETTINGS, process.env, loadEnvValues(dotEnvPath(agentDir)), relative(agentDir, dotEnvPath(agentDir)));
102
+ if (shaped)
103
+ failStartup(new Error(`deploy stopped: ${shaped}`));
104
+ const independentApps = (values) => {
105
+ try {
106
+ assertIndependentFeishuApps(agentDir, ["feishu", "lark"], values);
107
+ }
108
+ catch (error) {
109
+ failStartup(error);
110
+ }
111
+ };
112
+ independentApps(loadEnvValues(dotEnvPath(agentDir)));
113
+ const api = deploymentApi({
67
114
  config,
68
- run: !!opts.run,
69
- force: !!opts.force,
70
- externalClock: host === "agentcore", // cron rides EventBridge there — the resident-host notes don't apply
71
- // AgentCore DOES get a public URL (the forwarder's, AuthType NONE) — but nothing of ours answers behind it:
72
- // that relay reaches the channels' routes only, each verifying its platform's signature (agentcore-service.ts).
73
- publicUrl: host !== "agentcore",
74
- }).catch(failStartup);
75
- if (!pre.ok)
76
- failStartup(new Error(`deploy stopped: ${pre.gate}`));
77
- for (const m of pre.messages)
78
- console.error(`[fastagent] ${m.level}: ${m.text}`);
79
- const { channels } = pre;
80
- warnHostOnlyFlags(host, opts);
115
+ hostServes: host !== "agentcore",
116
+ values: loadEnvValues(dotEnvPath(agentDir)),
117
+ });
81
118
  const target = HOSTS[host];
82
- await target.deploy({
83
- opts,
84
- agentDir,
85
- workspace,
86
- config,
87
- pre,
88
- channels,
89
- webhookChannels: channels.filter((channel) => channel.ingress === "webhook"),
90
- longConnectionChannels: channels.filter((channel) => channel.ingress === "long-connection"),
91
- // The ownership predicate is bound HERE, from the same lookup that chose the host, so no host module can pass
92
- // one.
93
- // Reporting a stale artifact is enough when only generating them — the operator reads the line and decides. But
94
- // `--run` would then deploy FROM it: a determinate mismatch between what ships and what the definition says,
95
- // the same class as a Dockerfile that cannot read the manifest, and gated the
96
- // same way. `--force` regenerates ours; a file we did not generate is never touched by either, and the marker
97
- // line is how an operator takes a path back on purpose.
98
- write: async (artifacts, options) => {
99
- const plan = await planArtifacts(workspace, artifacts, { ...options, isOurs: target.isOurs });
100
- if (opts.run && plan.stale.length > 0) {
101
- failStartup(new Error(`deploy stopped: ${plan.stale.join(", ")} no longer match what this definition generates, and --run ` +
102
- `would deploy from them. Re-run with --force to regenerate, or remove each file's generated-by ` +
103
- `marker to own it yourself.`));
119
+ const preflight = async () => {
120
+ const facts = await preflightDeploy({
121
+ agentDir,
122
+ config,
123
+ run: !!opts.run,
124
+ force: !!opts.force,
125
+ noResidentProcess: host === "agentcore", // alarms and webhooks wake the container there — no machine to keep up
126
+ // Every AgentCore deployment starts the storage over (core.md §9).
127
+ storageResets: host === "agentcore",
128
+ servesApi: api.served,
129
+ }).catch(failStartup);
130
+ if (!facts.ok)
131
+ failStartup(new Error(`deploy stopped: ${facts.gate}`));
132
+ target.validate?.({ opts, agentDir, pre: facts });
133
+ return facts;
134
+ };
135
+ let pre = await preflight();
136
+ const agentArg = displayPath(process.cwd(), agentDir);
137
+ const rerun = `fastagent deploy ${host}${agentArg === undefined ? "" : ` ${shellArg(agentArg)}`}` +
138
+ `${opts.tunnel ? " --tunnel" : ""}${opts.intoLinked ? " --into-linked" : ""} --run`;
139
+ const unprepared = opts.run ? unpreparedFeishuApps(pre.channels, pre.values) : [];
140
+ if (opts.json && step === undefined) {
141
+ // A coding agent's deploy: what this machine can refuse is refused above, at once; the rest runs in a ticket.
142
+ if (unprepared.some(({ kind }) => kind === "lark")) {
143
+ const needed = await larkCredentialsNeeded(agentDir, rerun).catch(failStartup);
144
+ if (needed !== undefined) {
145
+ printReport(true, needed.json, needed.text);
146
+ process.exit(0);
104
147
  }
105
- await applyArtifactPlan(plan);
106
- },
107
- });
148
+ }
149
+ const timeout = opts.timeout === undefined ? TICKET_TIMEOUT_SECONDS : Number(opts.timeout);
150
+ if (!Number.isInteger(timeout) || timeout <= 0)
151
+ failUsage("--timeout must be a whole number of seconds");
152
+ const ticket = await startTicket({
153
+ subject: `deploy:${host}:${agentDir}`,
154
+ fields: { deployment: host },
155
+ action: `deploy the agent to ${host}`,
156
+ check: deployCheck(host),
157
+ restart: rerun,
158
+ timeoutSeconds: timeout,
159
+ waitsFirst: false,
160
+ // A deploy stopped halfway leaves the host half-changed: one already running is the answer.
161
+ whenRunning: "join",
162
+ command: {
163
+ file: process.execPath,
164
+ args: [
165
+ ...process.execArgv,
166
+ process.argv[1],
167
+ "deploy",
168
+ host,
169
+ agentDir,
170
+ ...(opts.tunnel ? ["--tunnel"] : []),
171
+ ...(opts.force ? ["--force"] : []),
172
+ ...(opts.intoLinked ? ["--into-linked"] : []),
173
+ "--run",
174
+ "--json",
175
+ ],
176
+ cwd: process.cwd(),
177
+ },
178
+ });
179
+ reportDeploy(ticket, "started");
180
+ process.exit(ticketExitCode(ticket));
181
+ }
182
+ /** Everything past the pre-flight, its person's steps taken by `answerer`; the URL and what the API report says. */
183
+ const deployWith = async (answerer) => {
184
+ if (unprepared.length > 0) {
185
+ const supplied = unprepared.flatMap(({ kind, ingress }) => feishuAppSecretNames(kind, ingress));
186
+ const kinds = unprepared.map(({ kind }) => kind);
187
+ const { values } = pre;
188
+ const absent = supplied.filter((name) => !values.get(name)?.trim());
189
+ const { missingSecrets } = assembleSecrets({
190
+ modelAuth: pre.modelAuth,
191
+ declared: pre.declaredSecrets,
192
+ values: pre.values,
193
+ });
194
+ const missing = missingValuesGate(missingSecrets.filter((name) => !supplied.includes(name)), pre.valueFile);
195
+ if (missing)
196
+ failStartup(new Error(`deploy stopped: ${missing}`));
197
+ if (host === "docker" && !opts.tunnel && unprepared.some(({ ingress }) => ingress === "webhook")) {
198
+ failStartup(new Error(`deploy stopped: ${kinds.join(", ")} receive by webhook here, and this Docker deployment has no ` +
199
+ `public URL to point the app at — re-run with --tunnel (the app is prepared then), or set up your own ` +
200
+ `ingress and supply ${absent.join(", ")} from a separate production app in ${pre.valueFile}, or ` +
201
+ `set ${kinds.map((kind) => `${cloudFor(kind).envPrefix}_INGRESS=websocket`).join(", ")} there`));
202
+ }
203
+ if (answerer.kind === "nobody") {
204
+ failUsage(`deploy stopped: ${pre.valueFile} has no ${absent.join(", ")}: setting up the separate production app ` +
205
+ `needs a person — run this deploy in a terminal; from a coding agent, run \`${rerun} --json\`, which ` +
206
+ `hands their part to its user`);
207
+ }
208
+ const person = answerer.kind === "ticket" ? answerer.step.person : terminalPerson;
209
+ const again = answerer.kind === "ticket" ? `${rerun} --json` : rerun;
210
+ await prepareFeishuApps(agentDir, unprepared, again, person).catch(failStartup);
211
+ pre = await preflight();
212
+ }
213
+ independentApps(pre.values);
214
+ if (api.served && api.generatesKey) {
215
+ // Past every refusal the pre-flight makes, and read again, so this deploy carries it.
216
+ const unprotected = await writeApiKey(agentDir).catch(failStartup);
217
+ if (unprotected !== undefined)
218
+ console.error(`[fastagent] note: ${unprotectedSecretsNote(unprotected)}`);
219
+ pre = await preflight();
220
+ }
221
+ for (const m of pre.messages)
222
+ console.error(`[fastagent] ${m.level}: ${m.text}`);
223
+ const { channels } = pre;
224
+ warnHostOnlyFlags(host, opts);
225
+ // What follows is the host's work: a deadline meant for the person must never cut it halfway. Its own steps for
226
+ // the person (a host sign-in, the box's login) wait again, and are bounded again.
227
+ if (answerer.kind === "ticket")
228
+ answerer.step.person.carriesOn();
229
+ const reachedAt = await target.deploy({
230
+ opts,
231
+ answerer,
232
+ rerun,
233
+ agentDir,
234
+ config,
235
+ pre,
236
+ channels,
237
+ webhookChannels: channels.filter((channel) => channel.ingress === "webhook"),
238
+ // The ownership predicate is bound HERE, from the same lookup that chose the host, so no host module can pass
239
+ // one.
240
+ // Reporting a stale artifact is enough when only generating them — the operator reads the line and decides. But
241
+ // `--run` would then deploy FROM it: a determinate mismatch between what ships and what the definition says,
242
+ // the same class as a Dockerfile that cannot read the manifest, and gated the
243
+ // same way. `--force` regenerates ours; a file we did not generate is never touched by either, and the marker
244
+ // line is how an operator takes a path back on purpose.
245
+ write: async (artifacts, options) => {
246
+ const plan = await planArtifacts(agentDir, artifacts, { ...options, isOurs: target.isOurs });
247
+ if (opts.run && plan.stale.length > 0) {
248
+ failStartup(new Error(`deploy stopped: ${plan.stale.join(", ")} no longer match what this definition generates, and --run ` +
249
+ `would deploy from them. Re-run with --force to regenerate, or remove each file's generated-by ` +
250
+ `marker to own it yourself.`));
251
+ }
252
+ await applyArtifactPlan(plan);
253
+ },
254
+ });
255
+ const notes = apiReport(api, { valueFile: pre.valueFile, agentArg }, reachedAt);
256
+ for (const line of notes)
257
+ console.error(`[fastagent] ${line}`);
258
+ return { ...(reachedAt === undefined ? {} : { url: reachedAt }), notes };
259
+ };
260
+ if (step !== undefined)
261
+ return deployWith({ kind: "ticket", step });
262
+ return deployWith(opts.input === false || !isInteractive() ? { kind: "nobody" } : { kind: "terminal" });
263
+ }
264
+ /** `deploy <host> --check <ticket> [--code <code>]`. */
265
+ async function checkDeploy(host, id, opts) {
266
+ const refused = refusedCheck(id, deployCheck(host));
267
+ if (refused !== undefined)
268
+ failUsage(refused);
269
+ // There: refusedCheck read it, and a ticket is pruned only a day after it ends.
270
+ const ticket = opts.stop ? await stopTicket(id) : (await checkTicket(id, opts.code));
271
+ reportDeploy(ticket, "checked");
272
+ process.exit(ticketExitCode(ticket));
273
+ }
274
+ /** A deploy's ticket for the agent that started or checked it, always as JSON: `--json` is how one started. */
275
+ function reportDeploy(ticket, when) {
276
+ const report = ticketReport(ticket, when, (result) => ({
277
+ fields: result,
278
+ text: [],
279
+ next: result.url === undefined
280
+ ? "Deployed. Tell the user what the notes say."
281
+ : `Deployed to ${String(result.url)}. Tell the user what the notes say.`,
282
+ }));
283
+ const running = ticket.status === "starting" || ticket.status === "working" || ticket.status === "need_user_action";
284
+ if (!running) {
285
+ printReport(true, report.json, []);
286
+ return;
287
+ }
288
+ // A deploy finishing is never cut by its deadline, so one that hangs there ends only on someone's say.
289
+ const stop = `${ticket.check} ${ticket.ticket} --stop --json`;
290
+ const hung = ticket.status === "need_user_action"
291
+ ? ""
292
+ : " If its log has shown no progress for a long while, stop_command stops it where it is, which can leave the " +
293
+ "host half-changed: ask the user first.";
294
+ printReport(true, { ...report.json, stop_command: stop, agent_next_steps: `${String(report.json.agent_next_steps)}${hung}` }, []);
108
295
  }